NeoMutt  2022-04-29-81-g9c5a59
Teaching an old dog new tricks
DOXYGEN
quoted.h File Reference

Quoted-Email colours. More...

#include "config.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "core/lib.h"
#include "attr.h"
#include "color.h"
+ Include dependency graph for quoted.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  QuoteStyle
 Style of quoted text. More...
 

Macros

#define COLOR_QUOTES_MAX   10
 Ten colours, quoted0..quoted9 (quoted and quoted0 are equivalent) More...
 

Functions

void quoted_colors_clear (void)
 Reset the quoted-email colours. More...
 
struct AttrColorquoted_colors_get (int q)
 Return the color of a quote, cycling through the used quotes. More...
 
int quoted_colors_num_used (void)
 Return the number of used quotes. More...
 
bool quoted_colors_parse_color (enum ColorId cid, uint32_t fg, uint32_t bg, int attrs, int q_level, int *rc, struct Buffer *err)
 Parse the 'color quoted' command. More...
 
enum CommandResult quoted_colors_parse_uncolor (enum ColorId cid, int q_level, struct Buffer *err)
 Parse the 'uncolor quoted' command. More...
 
struct QuoteStyleqstyle_classify (struct QuoteStyle **quote_list, const char *qptr, size_t length, bool *force_redraw, int *q_level)
 Find a style for a string. More...
 
void qstyle_free_tree (struct QuoteStyle **quote_list)
 Free an entire tree of QuoteStyle. More...
 
void qstyle_recolour (struct QuoteStyle *quote_list)
 Recolour quotes after colour changes. More...
 

Variables

struct AttrColor QuotedColors []
 Array of colours for quoted email text. More...
 
int NumQuotedColors
 Number of colours for quoted email text. More...
 

Detailed Description

Quoted-Email colours.

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 quoted.h.

Macro Definition Documentation

◆ COLOR_QUOTES_MAX

#define COLOR_QUOTES_MAX   10

Ten colours, quoted0..quoted9 (quoted and quoted0 are equivalent)

Definition at line 37 of file quoted.h.

Function Documentation

◆ quoted_colors_clear()

void quoted_colors_clear ( void  )

Reset the quoted-email colours.

Definition at line 57 of file quoted.c.

58 {
59  color_debug(LL_DEBUG5, "QuotedColors: clean up\n");
60  for (size_t i = 0; i < COLOR_QUOTES_MAX; i++)
61  {
63  }
64  NumQuotedColors = 0;
65 }
void attr_color_clear(struct AttrColor *ac)
Free the contents of an AttrColor.
Definition: attr.c:44
int color_debug(enum LogLevel level, const char *format,...)
Write to the log file.
Definition: debug.c:44
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
int NumQuotedColors
Number of colours for quoted email text.
Definition: quoted.c:38
struct AttrColor QuotedColors[COLOR_QUOTES_MAX]
Array of colours for quoted email text.
Definition: quoted.c:37
#define COLOR_QUOTES_MAX
Ten colours, quoted0..quoted9 (quoted and quoted0 are equivalent)
Definition: quoted.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ quoted_colors_get()

struct AttrColor* quoted_colors_get ( int  q)

Return the color of a quote, cycling through the used quotes.

Parameters
qQuote level
Return values
numColor ID, e.g. MT_COLOR_QUOTED

Definition at line 72 of file quoted.c.

73 {
74  if (NumQuotedColors == 0)
75  return NULL;
76  return &QuotedColors[q % NumQuotedColors];
77 }
+ Here is the caller graph for this function:

◆ quoted_colors_num_used()

int quoted_colors_num_used ( void  )

Return the number of used quotes.

Return values
numNumber of used quotes

Definition at line 83 of file quoted.c.

84 {
85  return NumQuotedColors;
86 }
+ Here is the caller graph for this function:

◆ quoted_colors_parse_color()

bool quoted_colors_parse_color ( enum ColorId  cid,
uint32_t  fg,
uint32_t  bg,
int  attrs,
int  q_level,
int *  rc,
struct Buffer err 
)

Parse the 'color quoted' command.

Parameters
cidColour Id, should be MT_COLOR_QUOTED
fgForeground colour
bgBackground colour
attrsAttributes, e.g. A_UNDERLINE
q_levelQuoting depth level
rcReturn code, e.g. MUTT_CMD_SUCCESS
errBuffer for error messages
Return values
trueColour was parsed

Definition at line 99 of file quoted.c.

101 {
102  if (cid != MT_COLOR_QUOTED)
103  return false;
104 
105  color_debug(LL_DEBUG5, "quoted %d\n", q_level);
106  if (q_level >= COLOR_QUOTES_MAX)
107  {
108  mutt_buffer_printf(err, _("Maximum quoting level is %d"), COLOR_QUOTES_MAX - 1);
109  return MUTT_CMD_WARNING;
110  }
111 
112  if (q_level >= NumQuotedColors)
113  NumQuotedColors = q_level + 1;
114 
115  struct AttrColor *ac = &QuotedColors[q_level];
116  const bool was_set = ((ac->attrs != 0) || ac->curses_color);
117  ac->attrs = attrs;
118 
119  struct CursesColor *cc = curses_color_new(fg, bg);
121  ac->curses_color = cc;
122 
123  if (!cc)
125 
126  if (was_set)
127  quoted_color_dump(ac, q_level, "QuotedColors changed: ");
128  else
129  quoted_color_dump(ac, q_level, "QuotedColors new: ");
130 
131  struct Buffer *buf = mutt_buffer_pool_get();
132  get_colorid_name(cid, buf);
133  color_debug(LL_DEBUG5, "NT_COLOR_SET: %s\n", buf->data);
135 
136  if (q_level == 0)
137  {
138  // Copy the colour into the SimpleColors
139  struct AttrColor *ac_quoted = simple_color_get(MT_COLOR_QUOTED);
140  *ac_quoted = *ac;
141  ac_quoted->ref_count = 1;
142  if (ac_quoted->curses_color)
143  ac_quoted->curses_color->ref_count++;
144  }
145 
146  struct EventColor ev_c = { cid, ac };
148 
151 
152  *rc = MUTT_CMD_SUCCESS;
153  return true;
154 }
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void get_colorid_name(unsigned int cid, struct Buffer *buf)
Get the name of a color id.
Definition: command.c:321
struct Notify * ColorsNotify
Notifications: ColorId, EventColor.
Definition: notify.c:34
struct AttrColor * simple_color_get(enum ColorId cid)
Get the colour of an object by its ID.
Definition: simple.c:74
@ MT_COLOR_QUOTED
Pager: quoted text.
Definition: color.h:57
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:37
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:36
void curses_color_free(struct CursesColor **ptr)
Free a CursesColor.
Definition: curses.c:116
struct CursesColor * curses_color_new(int fg, int bg)
Create a new CursesColor.
Definition: curses.c:148
void quoted_color_list_dump(void)
Log all the Quoted colours.
Definition: debug.c:310
void quoted_color_dump(struct AttrColor *ac, int q_level, const char *prefix)
Log a Quoted colour.
Definition: debug.c:286
void curses_colors_dump(void)
Log all the Curses colours.
Definition: debug.c:265
#define _(a)
Definition: message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
@ NT_COLOR_SET
Color has been set.
Definition: notify2.h:41
@ NT_COLOR
Colour has changed, NotifyColor, EventColor.
Definition: notify_type.h:41
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
int find_highest_used(void)
Find the highest-numbered quotedN in use.
Definition: quoted.c:44
A curses colour and its attributes.
Definition: attr.h:35
short ref_count
Number of users.
Definition: attr.h:38
int attrs
Text attributes, e.g. A_BOLD.
Definition: attr.h:37
struct CursesColor * curses_color
Underlying Curses colour.
Definition: attr.h:36
String manipulation buffer.
Definition: buffer.h:34
char * data
Pointer to data.
Definition: buffer.h:35
Colour in the ncurses palette.
Definition: curses2.h:38
uint32_t fg
Foreground colour.
Definition: curses2.h:41
uint32_t bg
Background colour.
Definition: curses2.h:42
short ref_count
Number of users.
Definition: curses2.h:44
An Event that happened to a Colour.
Definition: notify2.h:53
enum ColorId cid
Colour ID that has changed.
Definition: notify2.h:54
+ Here is the call graph for this function:

◆ quoted_colors_parse_uncolor()

enum CommandResult quoted_colors_parse_uncolor ( enum ColorId  cid,
int  q_level,
struct Buffer err 
)

Parse the 'uncolor quoted' command.

Parameters
cidColour Id, should be MT_COLOR_QUOTED
q_levelQuoting depth level
errBuffer for error messages
Return values
numResult, e.g. MUTT_CMD_SUCCESS

Definition at line 99 of file quoted.c.

165 {
166  color_debug(LL_DEBUG5, "unquoted %d\n", q_level);
167 
168  struct AttrColor *ac = &QuotedColors[q_level];
169  attr_color_clear(ac);
170  quoted_color_dump(ac, q_level, "QuotedColors clear: ");
171 
174 
176 
177  struct EventColor ev_c = { cid, ac };
179 
180  return MUTT_CMD_SUCCESS;
181 }
@ NT_COLOR_RESET
Color has been reset/removed.
Definition: notify2.h:42

◆ qstyle_classify()

struct QuoteStyle* qstyle_classify ( struct QuoteStyle **  quote_list,
const char *  qptr,
size_t  length,
bool *  force_redraw,
int *  q_level 
)

Find a style for a string.

Parameters
[out]quote_listList of quote colours
[in]qptrString to classify
[in]lengthLength of string
[out]force_redrawSet to true if a screen redraw is needed
[out]q_levelQuoting level
Return values
ptrQuoting style

Definition at line 280 of file quoted.c.

282 {
283  struct QuoteStyle *q_list = *quote_list;
284  struct QuoteStyle *qc = NULL, *tmp = NULL, *ptr = NULL, *save = NULL;
285  const char *tail_qptr = NULL;
286  size_t offset, tail_lng;
287  int index = -1;
288 
289  /* classify quoting prefix */
290  while (q_list)
291  {
292  if (length <= q_list->prefix_len)
293  {
294  /* case 1: check the top level nodes */
295 
296  if (mutt_strn_equal(qptr, q_list->prefix, length))
297  {
298  if (length == q_list->prefix_len)
299  return q_list; /* same prefix: return the current class */
300 
301  /* found shorter prefix */
302  if (!tmp)
303  {
304  /* add a node above q_list */
305  tmp = qstyle_new();
306  tmp->prefix = mutt_strn_dup(qptr, length);
307  tmp->prefix_len = length;
308 
309  /* replace q_list by tmp in the top level list */
310  if (q_list->next)
311  {
312  tmp->next = q_list->next;
313  q_list->next->prev = tmp;
314  }
315  if (q_list->prev)
316  {
317  tmp->prev = q_list->prev;
318  q_list->prev->next = tmp;
319  }
320 
321  /* make q_list a child of tmp */
322  tmp->down = q_list;
323  q_list->up = tmp;
324 
325  /* q_list has no siblings for now */
326  q_list->next = NULL;
327  q_list->prev = NULL;
328 
329  /* update the root if necessary */
330  if (q_list == *quote_list)
331  *quote_list = tmp;
332 
333  index = q_list->quote_n;
334 
335  /* tmp should be the return class too */
336  qc = tmp;
337 
338  /* next class to test; if tmp is a shorter prefix for another
339  * node, that node can only be in the top level list, so don't
340  * go down after this point */
341  q_list = tmp->next;
342  }
343  else
344  {
345  /* found another branch for which tmp is a shorter prefix */
346 
347  /* save the next sibling for later */
348  save = q_list->next;
349 
350  /* unlink q_list from the top level list */
351  if (q_list->next)
352  q_list->next->prev = q_list->prev;
353  if (q_list->prev)
354  q_list->prev->next = q_list->next;
355 
356  /* at this point, we have a tmp->down; link q_list to it */
357  ptr = tmp->down;
358  /* sibling order is important here, q_list should be linked last */
359  while (ptr->next)
360  ptr = ptr->next;
361  ptr->next = q_list;
362  q_list->next = NULL;
363  q_list->prev = ptr;
364  q_list->up = tmp;
365 
366  index = q_list->quote_n;
367 
368  /* next class to test; as above, we shouldn't go down */
369  q_list = save;
370  }
371 
372  /* we found a shorter prefix, so certain quotes have changed classes */
373  *force_redraw = true;
374  continue;
375  }
376  else
377  {
378  /* shorter, but not a substring of the current class: try next */
379  q_list = q_list->next;
380  continue;
381  }
382  }
383  else
384  {
385  /* case 2: try subclassing the current top level node */
386 
387  /* tmp != NULL means we already found a shorter prefix at case 1 */
388  if (!tmp && mutt_strn_equal(qptr, q_list->prefix, q_list->prefix_len))
389  {
390  /* ok, it's a subclass somewhere on this branch */
391 
392  ptr = q_list;
393  offset = q_list->prefix_len;
394 
395  q_list = q_list->down;
396  tail_lng = length - offset;
397  tail_qptr = qptr + offset;
398 
399  while (q_list)
400  {
401  if (length <= q_list->prefix_len)
402  {
403  if (mutt_strn_equal(tail_qptr, (q_list->prefix) + offset, tail_lng))
404  {
405  /* same prefix: return the current class */
406  if (length == q_list->prefix_len)
407  return q_list;
408 
409  /* found shorter common prefix */
410  if (!tmp)
411  {
412  /* add a node above q_list */
413  tmp = qstyle_new();
414  tmp->prefix = mutt_strn_dup(qptr, length);
415  tmp->prefix_len = length;
416 
417  /* replace q_list by tmp */
418  if (q_list->next)
419  {
420  tmp->next = q_list->next;
421  q_list->next->prev = tmp;
422  }
423  if (q_list->prev)
424  {
425  tmp->prev = q_list->prev;
426  q_list->prev->next = tmp;
427  }
428 
429  /* make q_list a child of tmp */
430  tmp->down = q_list;
431  tmp->up = q_list->up;
432  q_list->up = tmp;
433  if (tmp->up->down == q_list)
434  tmp->up->down = tmp;
435 
436  /* q_list has no siblings */
437  q_list->next = NULL;
438  q_list->prev = NULL;
439 
440  index = q_list->quote_n;
441 
442  /* tmp should be the return class too */
443  qc = tmp;
444 
445  /* next class to test */
446  q_list = tmp->next;
447  }
448  else
449  {
450  /* found another branch for which tmp is a shorter prefix */
451 
452  /* save the next sibling for later */
453  save = q_list->next;
454 
455  /* unlink q_list from the top level list */
456  if (q_list->next)
457  q_list->next->prev = q_list->prev;
458  if (q_list->prev)
459  q_list->prev->next = q_list->next;
460 
461  /* at this point, we have a tmp->down; link q_list to it */
462  ptr = tmp->down;
463  while (ptr->next)
464  ptr = ptr->next;
465  ptr->next = q_list;
466  q_list->next = NULL;
467  q_list->prev = ptr;
468  q_list->up = tmp;
469 
470  index = q_list->quote_n;
471 
472  /* next class to test */
473  q_list = save;
474  }
475 
476  /* we found a shorter prefix, so we need a redraw */
477  *force_redraw = true;
478  continue;
479  }
480  else
481  {
482  q_list = q_list->next;
483  continue;
484  }
485  }
486  else
487  {
488  /* longer than the current prefix: try subclassing it */
489  if (!tmp && mutt_strn_equal(tail_qptr, (q_list->prefix) + offset,
490  q_list->prefix_len - offset))
491  {
492  /* still a subclass: go down one level */
493  ptr = q_list;
494  offset = q_list->prefix_len;
495 
496  q_list = q_list->down;
497  tail_lng = length - offset;
498  tail_qptr = qptr + offset;
499 
500  continue;
501  }
502  else
503  {
504  /* nope, try the next prefix */
505  q_list = q_list->next;
506  continue;
507  }
508  }
509  }
510 
511  /* still not found so far: add it as a sibling to the current node */
512  if (!qc)
513  {
514  tmp = qstyle_new();
515  tmp->prefix = mutt_strn_dup(qptr, length);
516  tmp->prefix_len = length;
517 
518  if (ptr->down)
519  {
520  tmp->next = ptr->down;
521  ptr->down->prev = tmp;
522  }
523  ptr->down = tmp;
524  tmp->up = ptr;
525 
526  tmp->quote_n = (*q_level)++;
527  tmp->attr_color = quoted_colors_get(tmp->quote_n);
528 
529  return tmp;
530  }
531  else
532  {
533  if (index != -1)
534  qstyle_insert(*quote_list, tmp, index, q_level);
535 
536  return qc;
537  }
538  }
539  else
540  {
541  /* nope, try the next prefix */
542  q_list = q_list->next;
543  continue;
544  }
545  }
546  }
547 
548  if (!qc)
549  {
550  /* not found so far: add it as a top level class */
551  qc = qstyle_new();
552  qc->prefix = mutt_strn_dup(qptr, length);
553  qc->prefix_len = length;
554  qc->quote_n = (*q_level)++;
556 
557  if (*quote_list)
558  {
559  if ((*quote_list)->next)
560  {
561  qc->next = (*quote_list)->next;
562  qc->next->prev = qc;
563  }
564  (*quote_list)->next = qc;
565  qc->prev = *quote_list;
566  }
567  else
568  {
569  *quote_list = qc;
570  }
571  }
572 
573  if (index != -1)
574  qstyle_insert(*quote_list, tmp, index, q_level);
575 
576  return qc;
577 }
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:428
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:473
struct AttrColor * quoted_colors_get(int q)
Return the color of a quote, cycling through the used quotes.
Definition: quoted.c:72
static void qstyle_insert(struct QuoteStyle *quote_list, struct QuoteStyle *new_class, int index, int *q_level)
Insert a new quote colour class into a list.
Definition: quoted.c:236
static struct QuoteStyle * qstyle_new(void)
Create a new QuoteStyle.
Definition: quoted.c:224
Style of quoted text.
Definition: quoted.h:68
struct AttrColor * attr_color
Colour and attribute of the text.
Definition: quoted.h:70
struct QuoteStyle * next
Different quoting styles at the same level.
Definition: quoted.h:73
struct QuoteStyle * up
Definition: quoted.h:74
size_t prefix_len
Length of the prefix string.
Definition: quoted.h:72
struct QuoteStyle * prev
Definition: quoted.h:73
char * prefix
Prefix string, e.g. "> ".
Definition: quoted.h:71
struct QuoteStyle * down
Parent (less quoted) and child (more quoted) levels.
Definition: quoted.h:74
int quote_n
The quoteN colour index for this level.
Definition: quoted.h:69
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ qstyle_free_tree()

void qstyle_free_tree ( struct QuoteStyle **  quote_list)

Free an entire tree of QuoteStyle.

Parameters
[out]quote_listQuote list to free
Note
Use qstyle_free() to free a single object

Definition at line 206 of file quoted.c.

207 {
208  struct QuoteStyle *next = NULL;
209 
210  while (*quote_list)
211  {
212  if ((*quote_list)->down)
213  qstyle_free_tree(&((*quote_list)->down));
214  next = (*quote_list)->next;
215  qstyle_free(quote_list);
216  *quote_list = next;
217  }
218 }
void qstyle_free_tree(struct QuoteStyle **quote_list)
Free an entire tree of QuoteStyle.
Definition: quoted.c:206
static void qstyle_free(struct QuoteStyle **ptr)
Free a single QuoteStyle object.
Definition: quoted.c:189
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ qstyle_recolour()

void qstyle_recolour ( struct QuoteStyle quote_list)

Recolour quotes after colour changes.

Parameters
quote_listList of quote colours

Definition at line 608 of file quoted.c.

609 {
610  if (!quote_list)
611  return;
612 
613  int num = quoted_colors_num_used();
614  int cur = 0;
615 
617  qstyle_recurse(quote_list, num, &cur);
619 }
int quoted_colors_num_used(void)
Return the number of used quotes.
Definition: quoted.c:83
static void qstyle_recurse(struct QuoteStyle *quote_list, int num_qlevel, int *cur_qlevel)
Update the quoting styles after colour changes.
Definition: quoted.c:585
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ QuotedColors

struct AttrColor QuotedColors[]
extern

Array of colours for quoted email text.

Definition at line 1 of file quoted.c.

◆ NumQuotedColors

int NumQuotedColors
extern

Number of colours for quoted email text.

Definition at line 38 of file quoted.c.