NeoMutt  2024-12-12-19-ge4b57e
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
enriched.c File Reference

Rich text handler. More...

#include "config.h"
#include <stdbool.h>
#include <stddef.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.
 

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 *enriched)
 Wrap enriched text.
 
static void enriched_flush (struct EnrichedState *enriched, bool wrap)
 Write enriched text to the State.
 
static void enriched_putwc (wchar_t c, struct EnrichedState *enriched)
 Write one wide character to the state.
 
static void enriched_puts (const char *s, struct EnrichedState *enriched)
 Write an enriched text string to the State.
 
static void enriched_set_flags (const wchar_t *tag, struct EnrichedState *enriched)
 Set flags on the enriched text state.
 
int text_enriched_handler (struct Body *b_email, struct State *state)
 Handler for enriched text - Implements handler_t -.
 

Variables

static const struct Etags EnrichedTags []
 EnrichedTags - Lookup table of tags allowed in enriched text.
 

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 enriched)
static

Wrap enriched text.

Parameters
enrichedState of enriched text

Definition at line 121 of file enriched.c.

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

◆ enriched_flush()

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

Write enriched text to the State.

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

Definition at line 238 of file enriched.c.

239{
240 if (!enriched || !enriched->buffer)
241 return;
242
243 if (!enriched->tag_level[RICH_NOFILL] &&
244 ((enriched->line_len + enriched->word_len) >
245 (enriched->wrap_margin - (enriched->tag_level[RICH_INDENT_RIGHT] * INDENT_SIZE) -
246 enriched->indent_len)))
247 {
248 enriched_wrap(enriched);
249 }
250
251 if (enriched->buf_used)
252 {
253 enriched->buffer[enriched->buf_used] = (wchar_t) '\0';
254 enriched->line_used += enriched->buf_used;
255 if (enriched->line_used > enriched->line_max)
256 {
257 enriched->line_max = enriched->line_used;
258 MUTT_MEM_REALLOC(&enriched->line, enriched->line_max + 1, wchar_t);
259 }
260 wcscat(enriched->line, enriched->buffer);
261 enriched->line_len += enriched->word_len;
262 enriched->word_len = 0;
263 enriched->buf_used = 0;
264 }
265 if (wrap)
266 enriched_wrap(enriched);
267 fflush(enriched->state->fp_out);
268}
static void enriched_wrap(struct EnrichedState *enriched)
Wrap enriched text.
Definition: enriched.c:121
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition: memory.h:43
wchar_t * buffer
Definition: enriched.c:100
size_t buf_used
Definition: enriched.c:109
size_t word_len
Definition: enriched.c:108
size_t line_max
Definition: enriched.c:106
FILE * fp_out
File to write to.
Definition: state.h:50
+ 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 enriched 
)
static

Write one wide character to the state.

Parameters
cCharacter to write
enrichedState of Enriched text

Definition at line 275 of file enriched.c.

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

Write an enriched text string to the State.

Parameters
sString to write
enrichedState of Enriched text

Definition at line 352 of file enriched.c.

353{
354 if (!enriched)
355 return;
356
357 const char *c = NULL;
358
359 if ((enriched->buf_len < (enriched->buf_used + mutt_str_len(s))) || !enriched->buffer)
360 {
361 enriched->buf_len += 1024;
362 MUTT_MEM_REALLOC(&enriched->buffer, enriched->buf_len + 1, wchar_t);
363 }
364 c = s;
365 while (*c)
366 {
367 enriched->buffer[enriched->buf_used++] = (wchar_t) *c;
368 c++;
369 }
370}
+ 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 enriched 
)
static

Set flags on the enriched text state.

Parameters
tagTag to set
enrichedState of Enriched text

Definition at line 377 of file enriched.c.

378{
379 if (!enriched)
380 return;
381
382 const wchar_t *tagptr = tag;
383 int i, j;
384
385 if (*tagptr == (wchar_t) '/')
386 tagptr++;
387
388 for (i = 0, j = -1; EnrichedTags[i].tag_name; i++)
389 {
390 if (wcscasecmp(EnrichedTags[i].tag_name, tagptr) == 0)
391 {
392 j = EnrichedTags[i].index;
393 break;
394 }
395 }
396
397 if (j != -1)
398 {
399 if ((j == RICH_CENTER) || (j == RICH_FLUSHLEFT) || (j == RICH_FLUSHRIGHT))
400 enriched_flush(enriched, true);
401
402 if (*tag == (wchar_t) '/')
403 {
404 if (enriched->tag_level[j]) /* make sure not to go negative */
405 enriched->tag_level[j]--;
406 if ((enriched->state->flags & STATE_DISPLAY) && (j == RICH_PARAM) &&
407 enriched->tag_level[RICH_COLOR])
408 {
409 enriched->param[enriched->param_used] = (wchar_t) '\0';
410 if (wcscasecmp(L"black", enriched->param) == 0)
411 {
412 enriched_puts("\033[30m", enriched); // Escape
413 }
414 else if (wcscasecmp(L"red", enriched->param) == 0)
415 {
416 enriched_puts("\033[31m", enriched); // Escape
417 }
418 else if (wcscasecmp(L"green", enriched->param) == 0)
419 {
420 enriched_puts("\033[32m", enriched); // Escape
421 }
422 else if (wcscasecmp(L"yellow", enriched->param) == 0)
423 {
424 enriched_puts("\033[33m", enriched); // Escape
425 }
426 else if (wcscasecmp(L"blue", enriched->param) == 0)
427 {
428 enriched_puts("\033[34m", enriched); // Escape
429 }
430 else if (wcscasecmp(L"magenta", enriched->param) == 0)
431 {
432 enriched_puts("\033[35m", enriched); // Escape
433 }
434 else if (wcscasecmp(L"cyan", enriched->param) == 0)
435 {
436 enriched_puts("\033[36m", enriched); // Escape
437 }
438 else if (wcscasecmp(L"white", enriched->param) == 0)
439 {
440 enriched_puts("\033[37m", enriched); // Escape
441 }
442 }
443 if ((enriched->state->flags & STATE_DISPLAY) && (j == RICH_COLOR))
444 {
445 enriched_puts("\033[0m", enriched); // Escape
446 }
447
448 /* flush parameter buffer when closing the tag */
449 if (j == RICH_PARAM)
450 {
451 enriched->param_used = 0;
452 enriched->param[0] = (wchar_t) '\0';
453 }
454 }
455 else
456 {
457 enriched->tag_level[j]++;
458 }
459
460 if (j == RICH_EXCERPT)
461 enriched_flush(enriched, true);
462 }
463}
static const struct Etags EnrichedTags[]
EnrichedTags - Lookup table of tags allowed in enriched text.
Definition: enriched.c:75
static void enriched_puts(const char *s, struct EnrichedState *enriched)
Write an enriched text string to the State.
Definition: enriched.c:352
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 },
}

EnrichedTags - Lookup table of tags allowed in enriched text.

Definition at line 75 of file enriched.c.