NeoMutt  2022-04-29-215-gc12b98
Teaching an old dog new tricks
DOXYGEN
enriched.c File Reference

Rich text handler. More...

#include "config.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include <wchar.h>
#include <wctype.h>
#include "mutt/lib.h"
#include "email/lib.h"
#include "enriched.h"
+ Include dependency graph for enriched.c:

Go to the source code of this file.

Data Structures

struct  Etags
 Enriched text tags. More...
 
struct  EnrichedState
 State of enriched-text parser. More...
 

Macros

#define INDENT_SIZE   4
 A (not so) minimal implementation of RFC1563. More...
 

Enumerations

enum  RichAttribs {
  RICH_PARAM = 0 , RICH_BOLD , RICH_UNDERLINE , RICH_ITALIC ,
  RICH_NOFILL , RICH_INDENT , RICH_INDENT_RIGHT , RICH_EXCERPT ,
  RICH_CENTER , RICH_FLUSHLEFT , RICH_FLUSHRIGHT , RICH_COLOR ,
  RICH_MAX
}
 Rich text attributes. More...
 

Functions

static void enriched_wrap (struct EnrichedState *stte)
 Wrap enriched text. More...
 
static void enriched_flush (struct EnrichedState *stte, bool wrap)
 Write enriched text to the State. More...
 
static void enriched_putwc (wchar_t c, struct EnrichedState *stte)
 Write one wide character to the state. More...
 
static void enriched_puts (const char *s, struct EnrichedState *stte)
 Write an enriched text string to the State. More...
 
static void enriched_set_flags (const wchar_t *tag, struct EnrichedState *stte)
 Set flags on the enriched text state. More...
 
int text_enriched_handler (struct Body *a, struct State *s)
 Handler for enriched text - Implements handler_t -. More...
 

Variables

static const struct Etags EnrichedTags []
 

Detailed Description

Rich text handler.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file enriched.c.

Macro Definition Documentation

◆ INDENT_SIZE

#define INDENT_SIZE   4

A (not so) minimal implementation of RFC1563.

Definition at line 43 of file enriched.c.

Enumeration Type Documentation

◆ RichAttribs

Rich text attributes.

Enumerator
RICH_PARAM 

Parameter label.

RICH_BOLD 

Bold text.

RICH_UNDERLINE 

Underlined text.

RICH_ITALIC 

Italic text.

RICH_NOFILL 

Text will not be reformatted.

RICH_INDENT 

Indented text.

RICH_INDENT_RIGHT 

Right-indented text.

RICH_EXCERPT 

Excerpt text.

RICH_CENTER 

Centred text.

RICH_FLUSHLEFT 

Left-justified text.

RICH_FLUSHRIGHT 

Right-justified text.

RICH_COLOR 

Coloured text.

RICH_MAX 

Definition at line 48 of file enriched.c.

49{
50 RICH_PARAM = 0,
51 RICH_BOLD,
63};
@ RICH_FLUSHRIGHT
Right-justified text.
Definition: enriched.c:60
@ RICH_NOFILL
Text will not be reformatted.
Definition: enriched.c:54
@ RICH_COLOR
Coloured text.
Definition: enriched.c:61
@ RICH_PARAM
Parameter label.
Definition: enriched.c:50
@ RICH_INDENT
Indented text.
Definition: enriched.c:55
@ RICH_BOLD
Bold text.
Definition: enriched.c:51
@ RICH_CENTER
Centred text.
Definition: enriched.c:58
@ RICH_ITALIC
Italic text.
Definition: enriched.c:53
@ RICH_UNDERLINE
Underlined text.
Definition: enriched.c:52
@ RICH_EXCERPT
Excerpt text.
Definition: enriched.c:57
@ RICH_INDENT_RIGHT
Right-indented text.
Definition: enriched.c:56
@ RICH_MAX
Definition: enriched.c:62
@ RICH_FLUSHLEFT
Left-justified text.
Definition: enriched.c:59

Function Documentation

◆ enriched_wrap()

static void enriched_wrap ( struct EnrichedState stte)
static

Wrap enriched text.

Parameters
stteState of enriched text

Definition at line 120 of file enriched.c.

121{
122 if (!stte)
123 return;
124
125 int x;
126
127 if (stte->line_len)
128 {
129 if (stte->tag_level[RICH_CENTER] || stte->tag_level[RICH_FLUSHRIGHT])
130 {
131 /* Strip trailing white space */
132 size_t y = stte->line_used - 1;
133
134 while (y && iswspace(stte->line[y]))
135 {
136 stte->line[y] = (wchar_t) '\0';
137 y--;
138 stte->line_used--;
139 stte->line_len--;
140 }
141 if (stte->tag_level[RICH_CENTER])
142 {
143 /* Strip leading whitespace */
144 y = 0;
145
146 while (stte->line[y] && iswspace(stte->line[y]))
147 y++;
148 if (y)
149 {
150 for (size_t z = y; z <= stte->line_used; z++)
151 {
152 stte->line[z - y] = stte->line[z];
153 }
154
155 stte->line_len -= y;
156 stte->line_used -= y;
157 }
158 }
159 }
160
161 const int extra = stte->wrap_margin - stte->line_len - stte->indent_len -
163 if (extra > 0)
164 {
165 if (stte->tag_level[RICH_CENTER])
166 {
167 x = extra / 2;
168 while (x)
169 {
170 state_putc(stte->s, ' ');
171 x--;
172 }
173 }
174 else if (stte->tag_level[RICH_FLUSHRIGHT])
175 {
176 x = extra - 1;
177 while (x)
178 {
179 state_putc(stte->s, ' ');
180 x--;
181 }
182 }
183 }
184 state_putws(stte->s, (const wchar_t *) stte->line);
185 }
186
187 state_putc(stte->s, '\n');
188 stte->line[0] = (wchar_t) '\0';
189 stte->line_len = 0;
190 stte->line_used = 0;
191 stte->indent_len = 0;
192 if (stte->s->prefix)
193 {
194 state_puts(stte->s, stte->s->prefix);
195 stte->indent_len += mutt_str_len(stte->s->prefix);
196 }
197
198 if (stte->tag_level[RICH_EXCERPT])
199 {
200 x = stte->tag_level[RICH_EXCERPT];
201 while (x)
202 {
203 if (stte->s->prefix)
204 {
205 state_puts(stte->s, stte->s->prefix);
206 stte->indent_len += mutt_str_len(stte->s->prefix);
207 }
208 else
209 {
210 state_puts(stte->s, "> ");
211 stte->indent_len += mutt_str_len("> ");
212 }
213 x--;
214 }
215 }
216 else
217 stte->indent_len = 0;
218 if (stte->tag_level[RICH_INDENT])
219 {
220 x = stte->tag_level[RICH_INDENT] * INDENT_SIZE;
221 stte->indent_len += x;
222 while (x)
223 {
224 state_putc(stte->s, ' ');
225 x--;
226 }
227 }
228}
#define INDENT_SIZE
A (not so) minimal implementation of RFC1563.
Definition: enriched.c:43
int state_putws(struct State *s, const wchar_t *ws)
Write a wide string to the state.
Definition: state.c:143
#define state_puts(STATE, STR)
Definition: state.h:56
#define state_putc(STATE, STR)
Definition: state.h:57
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
wchar_t * line
Definition: enriched.c:100
int tag_level[RICH_MAX]
Definition: enriched.c:111
struct State * s
Definition: enriched.c:113
size_t line_used
Definition: enriched.c:104
size_t line_len
Definition: enriched.c:103
int wrap_margin
Definition: enriched.c:112
size_t indent_len
Definition: enriched.c:106
char * prefix
String to add to the beginning of each output line.
Definition: state.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ enriched_flush()

static void enriched_flush ( struct EnrichedState stte,
bool  wrap 
)
static

Write enriched text to the State.

Parameters
stteState of Enriched text
wraptrue if the text should be wrapped

Definition at line 235 of file enriched.c.

236{
237 if (!stte || !stte->buffer)
238 return;
239
240 if (!stte->tag_level[RICH_NOFILL] &&
241 ((stte->line_len + stte->word_len) >
242 (stte->wrap_margin - (stte->tag_level[RICH_INDENT_RIGHT] * INDENT_SIZE) - stte->indent_len)))
243 {
244 enriched_wrap(stte);
245 }
246
247 if (stte->buf_used)
248 {
249 stte->buffer[stte->buf_used] = (wchar_t) '\0';
250 stte->line_used += stte->buf_used;
251 if (stte->line_used > stte->line_max)
252 {
253 stte->line_max = stte->line_used;
254 mutt_mem_realloc(&stte->line, (stte->line_max + 1) * sizeof(wchar_t));
255 }
256 wcscat(stte->line, stte->buffer);
257 stte->line_len += stte->word_len;
258 stte->word_len = 0;
259 stte->buf_used = 0;
260 }
261 if (wrap)
262 enriched_wrap(stte);
263 fflush(stte->s->fp_out);
264}
static void enriched_wrap(struct EnrichedState *stte)
Wrap enriched text.
Definition: enriched.c:120
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
wchar_t * buffer
Definition: enriched.c:99
size_t buf_used
Definition: enriched.c:108
size_t word_len
Definition: enriched.c:107
size_t line_max
Definition: enriched.c:105
FILE * fp_out
File to write to.
Definition: state.h:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ enriched_putwc()

static void enriched_putwc ( wchar_t  c,
struct EnrichedState stte 
)
static

Write one wide character to the state.

Parameters
cCharacter to write
stteState of Enriched text

Definition at line 271 of file enriched.c.

272{
273 if (!stte)
274 return;
275
276 if (stte->tag_level[RICH_PARAM])
277 {
278 if (stte->tag_level[RICH_COLOR])
279 {
280 if (stte->param_used + 1 >= stte->param_len)
281 mutt_mem_realloc(&stte->param, (stte->param_len += 256) * sizeof(wchar_t));
282
283 stte->param[stte->param_used++] = c;
284 }
285 return; /* nothing to do */
286 }
287
288 /* see if more space is needed (plus extra for possible rich characters) */
289 if ((stte->buf_len < (stte->buf_used + 3)) || !stte->buffer)
290 {
291 stte->buf_len += 1024;
292 mutt_mem_realloc(&stte->buffer, (stte->buf_len + 1) * sizeof(wchar_t));
293 }
294
295 if ((!stte->tag_level[RICH_NOFILL] && iswspace(c)) || (c == (wchar_t) '\0'))
296 {
297 if (c == (wchar_t) '\t')
298 stte->word_len += 8 - (stte->line_len + stte->word_len) % 8;
299 else
300 stte->word_len++;
301
302 stte->buffer[stte->buf_used++] = c;
303 enriched_flush(stte, false);
304 }
305 else
306 {
307 if (stte->s->flags & MUTT_DISPLAY)
308 {
309 if (stte->tag_level[RICH_BOLD])
310 {
311 stte->buffer[stte->buf_used++] = c;
312 stte->buffer[stte->buf_used++] = (wchar_t) '\010'; // Ctrl-H (backspace)
313 stte->buffer[stte->buf_used++] = c;
314 }
315 else if (stte->tag_level[RICH_UNDERLINE])
316 {
317 stte->buffer[stte->buf_used++] = '_';
318 stte->buffer[stte->buf_used++] = (wchar_t) '\010'; // Ctrl-H (backspace)
319 stte->buffer[stte->buf_used++] = c;
320 }
321 else if (stte->tag_level[RICH_ITALIC])
322 {
323 stte->buffer[stte->buf_used++] = c;
324 stte->buffer[stte->buf_used++] = (wchar_t) '\010'; // Ctrl-H (backspace)
325 stte->buffer[stte->buf_used++] = '_';
326 }
327 else
328 {
329 stte->buffer[stte->buf_used++] = c;
330 }
331 }
332 else
333 {
334 stte->buffer[stte->buf_used++] = c;
335 }
336 stte->word_len++;
337 }
338}
static void enriched_flush(struct EnrichedState *stte, bool wrap)
Write enriched text to the State.
Definition: enriched.c:235
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
size_t buf_len
Definition: enriched.c:102
size_t param_used
Definition: enriched.c:109
wchar_t * param
Definition: enriched.c:101
size_t param_len
Definition: enriched.c:110
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ enriched_puts()

static void enriched_puts ( const char *  s,
struct EnrichedState stte 
)
static

Write an enriched text string to the State.

Parameters
sString to write
stteState of Enriched text

Definition at line 345 of file enriched.c.

346{
347 if (!stte)
348 return;
349
350 const char *c = NULL;
351
352 if ((stte->buf_len < (stte->buf_used + mutt_str_len(s))) || !stte->buffer)
353 {
354 stte->buf_len += 1024;
355 mutt_mem_realloc(&stte->buffer, (stte->buf_len + 1) * sizeof(wchar_t));
356 }
357 c = s;
358 while (*c)
359 {
360 stte->buffer[stte->buf_used++] = (wchar_t) *c;
361 c++;
362 }
363}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ enriched_set_flags()

static void enriched_set_flags ( const wchar_t *  tag,
struct EnrichedState stte 
)
static

Set flags on the enriched text state.

Parameters
tagTag to set
stteState of Enriched text

Definition at line 370 of file enriched.c.

371{
372 if (!stte)
373 return;
374
375 const wchar_t *tagptr = tag;
376 int i, j;
377
378 if (*tagptr == (wchar_t) '/')
379 tagptr++;
380
381 for (i = 0, j = -1; EnrichedTags[i].tag_name; i++)
382 {
383 if (wcscasecmp(EnrichedTags[i].tag_name, tagptr) == 0)
384 {
385 j = EnrichedTags[i].index;
386 break;
387 }
388 }
389
390 if (j != -1)
391 {
392 if ((j == RICH_CENTER) || (j == RICH_FLUSHLEFT) || (j == RICH_FLUSHRIGHT))
393 enriched_flush(stte, true);
394
395 if (*tag == (wchar_t) '/')
396 {
397 if (stte->tag_level[j]) /* make sure not to go negative */
398 stte->tag_level[j]--;
399 if ((stte->s->flags & MUTT_DISPLAY) && (j == RICH_PARAM) && stte->tag_level[RICH_COLOR])
400 {
401 stte->param[stte->param_used] = (wchar_t) '\0';
402 if (wcscasecmp(L"black", stte->param) == 0)
403 {
404 enriched_puts("\033[30m", stte); // Escape
405 }
406 else if (wcscasecmp(L"red", stte->param) == 0)
407 {
408 enriched_puts("\033[31m", stte); // Escape
409 }
410 else if (wcscasecmp(L"green", stte->param) == 0)
411 {
412 enriched_puts("\033[32m", stte); // Escape
413 }
414 else if (wcscasecmp(L"yellow", stte->param) == 0)
415 {
416 enriched_puts("\033[33m", stte); // Escape
417 }
418 else if (wcscasecmp(L"blue", stte->param) == 0)
419 {
420 enriched_puts("\033[34m", stte); // Escape
421 }
422 else if (wcscasecmp(L"magenta", stte->param) == 0)
423 {
424 enriched_puts("\033[35m", stte); // Escape
425 }
426 else if (wcscasecmp(L"cyan", stte->param) == 0)
427 {
428 enriched_puts("\033[36m", stte); // Escape
429 }
430 else if (wcscasecmp(L"white", stte->param) == 0)
431 {
432 enriched_puts("\033[37m", stte); // Escape
433 }
434 }
435 if ((stte->s->flags & MUTT_DISPLAY) && (j == RICH_COLOR))
436 {
437 enriched_puts("\033[0m", stte); // Escape
438 }
439
440 /* flush parameter buffer when closing the tag */
441 if (j == RICH_PARAM)
442 {
443 stte->param_used = 0;
444 stte->param[0] = (wchar_t) '\0';
445 }
446 }
447 else
448 stte->tag_level[j]++;
449
450 if (j == RICH_EXCERPT)
451 enriched_flush(stte, true);
452 }
453}
static const struct Etags EnrichedTags[]
Definition: enriched.c:74
static void enriched_puts(const char *s, struct EnrichedState *stte)
Write an enriched text string to the State.
Definition: enriched.c:345
int wcscasecmp(const wchar_t *a, const wchar_t *b)
Compare two wide-character strings, ignoring case.
Definition: wcscasecmp.c:41
int index
Index number.
Definition: enriched.c:71
const wchar_t * tag_name
Tag name.
Definition: enriched.c:70
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ EnrichedTags

const struct Etags EnrichedTags[]
static
Initial value:
= {
{ L"param", RICH_PARAM },
{ L"bold", RICH_BOLD },
{ L"italic", RICH_ITALIC },
{ L"underline", RICH_UNDERLINE },
{ L"nofill", RICH_NOFILL },
{ L"excerpt", RICH_EXCERPT },
{ L"indent", RICH_INDENT },
{ L"indentright", RICH_INDENT_RIGHT },
{ L"center", RICH_CENTER },
{ L"flushleft", RICH_FLUSHLEFT },
{ L"flushright", RICH_FLUSHRIGHT },
{ L"flushboth", RICH_FLUSHLEFT },
{ L"color", RICH_COLOR },
{ L"x-color", RICH_COLOR },
{ NULL, -1 },
}

Definition at line 74 of file enriched.c.