NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
color.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <stdbool.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include "mutt/lib.h"
36 #include "email/lib.h"
37 #include "core/lib.h"
38 #include "mutt.h"
39 #include "color.h"
40 #include "pattern/lib.h"
41 #include "context.h"
42 #include "init.h"
43 #include "mutt_commands.h"
44 #include "mutt_curses.h"
45 #include "mutt_globals.h"
46 #include "options.h"
47 #ifdef USE_SLANG_CURSES
48 #include <assert.h>
49 #endif
50 
62 typedef int (*parser_callback_t)(struct Buffer *buf, struct Buffer *s, uint32_t *fg,
63  uint32_t *bg, int *attr, struct Buffer *err);
64 
65 #define COLOR_UNSET UINT32_MAX
66 #define COLOR_QUOTES_MAX \
67  10
68 
69 #ifdef HAVE_COLOR
70 
71 #define COLOR_DEFAULT (-2)
72 
73 /*
74  * Flags for the high 8bits of the color value.
75  *
76  * Note that no flag means it's a palette color.
77  */
78 #define RGB24 (1U << 24)
79 
80 // clang-format off
81 static const struct Mapping ColorNames[] = {
82  { "black", COLOR_BLACK },
83  { "blue", COLOR_BLUE },
84  { "cyan", COLOR_CYAN },
85  { "green", COLOR_GREEN },
86  { "magenta", COLOR_MAGENTA },
87  { "red", COLOR_RED },
88  { "white", COLOR_WHITE },
89  { "yellow", COLOR_YELLOW },
90 #if defined(USE_SLANG_CURSES) || defined(HAVE_USE_DEFAULT_COLORS)
91  { "default", COLOR_DEFAULT },
92 #endif
93  { 0, 0 },
94 };
95 // clang-format on
96 #endif /* HAVE_COLOR */
97 
98 // clang-format off
99 const struct Mapping Fields[] = {
100  { "attachment", MT_COLOR_ATTACHMENT },
101  { "attach_headers", MT_COLOR_ATTACH_HEADERS },
102  { "body", MT_COLOR_BODY },
103  { "bold", MT_COLOR_BOLD },
104  { "error", MT_COLOR_ERROR },
105  { "hdrdefault", MT_COLOR_HDRDEFAULT },
106  { "header", MT_COLOR_HEADER },
107  { "index", MT_COLOR_INDEX },
108  { "index_author", MT_COLOR_INDEX_AUTHOR },
109  { "index_collapsed", MT_COLOR_INDEX_COLLAPSED },
110  { "index_date", MT_COLOR_INDEX_DATE },
111  { "index_flags", MT_COLOR_INDEX_FLAGS },
112  { "index_label", MT_COLOR_INDEX_LABEL },
113  { "index_number", MT_COLOR_INDEX_NUMBER },
114  { "index_size", MT_COLOR_INDEX_SIZE },
115  { "index_subject", MT_COLOR_INDEX_SUBJECT },
116  { "index_tag", MT_COLOR_INDEX_TAG },
117  { "index_tags", MT_COLOR_INDEX_TAGS },
118  { "indicator", MT_COLOR_INDICATOR },
119  { "markers", MT_COLOR_MARKERS },
120  { "message", MT_COLOR_MESSAGE },
121  { "normal", MT_COLOR_NORMAL },
122  { "options", MT_COLOR_OPTIONS },
123  { "progress", MT_COLOR_PROGRESS },
124  { "prompt", MT_COLOR_PROMPT },
125  { "quoted", MT_COLOR_QUOTED },
126  { "search", MT_COLOR_SEARCH },
127 #ifdef USE_SIDEBAR
128  { "sidebar_divider", MT_COLOR_SIDEBAR_DIVIDER },
129  { "sidebar_flagged", MT_COLOR_SIDEBAR_FLAGGED },
130  { "sidebar_highlight", MT_COLOR_SIDEBAR_HIGHLIGHT },
131  { "sidebar_indicator", MT_COLOR_SIDEBAR_INDICATOR },
132  { "sidebar_new", MT_COLOR_SIDEBAR_NEW },
133  { "sidebar_ordinary", MT_COLOR_SIDEBAR_ORDINARY },
134  { "sidebar_spool_file", MT_COLOR_SIDEBAR_SPOOLFILE },
135  { "sidebar_unread", MT_COLOR_SIDEBAR_UNREAD },
136 #endif
137  { "signature", MT_COLOR_SIGNATURE },
138  { "status", MT_COLOR_STATUS },
139  { "tilde", MT_COLOR_TILDE },
140  { "tree", MT_COLOR_TREE },
141  { "underline", MT_COLOR_UNDERLINE },
142  { "warning", MT_COLOR_WARNING },
143  { NULL, 0 },
144 };
145 
146 const struct Mapping ComposeFields[] = {
147  { "header", MT_COLOR_COMPOSE_HEADER },
148  { "security_encrypt", MT_COLOR_COMPOSE_SECURITY_ENCRYPT },
149  { "security_sign", MT_COLOR_COMPOSE_SECURITY_SIGN },
150  { "security_both", MT_COLOR_COMPOSE_SECURITY_BOTH },
151  { "security_none", MT_COLOR_COMPOSE_SECURITY_NONE },
152  { NULL, 0 }
153 };
154 // clang-format off
155 
160 static void defs_free(struct Colors *c)
161 {
162  FREE(&c->defs);
163 }
164 
169 static void defs_init(struct Colors *c)
170 {
171  c->defs = mutt_mem_malloc(MT_COLOR_MAX * sizeof(int));
172  memset(c->defs, A_NORMAL, MT_COLOR_MAX * sizeof(int));
173 
174  // Set some defaults
175  c->defs[MT_COLOR_INDICATOR] = A_REVERSE;
176  c->defs[MT_COLOR_MARKERS] = A_REVERSE;
177  c->defs[MT_COLOR_SEARCH] = A_REVERSE;
178 #ifdef USE_SIDEBAR
179  c->defs[MT_COLOR_SIDEBAR_HIGHLIGHT] = A_UNDERLINE;
180 #endif
181  c->defs[MT_COLOR_STATUS] = A_REVERSE;
182 }
183 
188 static void defs_clear(struct Colors *c)
189 {
190  memset(c->defs, A_NORMAL, MT_COLOR_MAX * sizeof(int));
191 }
192 
197 static void quotes_free(struct Colors *c)
198 {
199  FREE(&c->quotes);
200 }
201 
206 static void quotes_init(struct Colors *c)
207 {
208  c->quotes = mutt_mem_malloc(COLOR_QUOTES_MAX * sizeof(int));
209  memset(c->quotes, A_NORMAL, COLOR_QUOTES_MAX * sizeof(int));
210  c->quotes_used = 0;
211 }
212 
217 static void quotes_clear(struct Colors *c)
218 {
219  memset(c->quotes, A_NORMAL, COLOR_QUOTES_MAX * sizeof(int));
220  c->quotes_used = 0;
221 }
222 
227 static void color_list_free(struct ColorList **ptr)
228 {
229  if (!ptr || !*ptr)
230  return;
231 
232  struct ColorList *cl = *ptr;
233  struct ColorList *next = NULL;
234 
235  while (cl)
236  {
237  next = cl->next;
238  FREE(&cl);
239  cl = next;
240  }
241  *ptr = NULL;
242 }
243 
252 void mutt_color_free(struct Colors *c, uint32_t fg, uint32_t bg)
253 {
254  struct ColorList *q = NULL;
255 
256  struct ColorList *p = c->user_colors;
257  while (p)
258  {
259  if ((p->fg == fg) && (p->bg == bg))
260  {
261  (p->count)--;
262  if (p->count > 0)
263  return;
264 
265  c->num_user_colors--;
266  mutt_debug(LL_DEBUG1, "Color pairs used so far: %d\n", c->num_user_colors);
267 
268  if (p == c->user_colors)
269  {
270  c->user_colors = c->user_colors->next;
271  FREE(&p);
272  return;
273  }
274  q = c->user_colors;
275  while (q)
276  {
277  if (q->next == p)
278  {
279  q->next = p->next;
280  FREE(&p);
281  return;
282  }
283  q = q->next;
284  }
285  /* can't get here */
286  }
287  p = p->next;
288  }
289 }
290 
297 static void color_line_free(struct Colors *c, struct ColorLine **ptr, bool free_colors)
298 {
299  if (!ptr || !*ptr)
300  return;
301 
302  struct ColorLine *cl = *ptr;
303 
304 #ifdef HAVE_COLOR
305  if (free_colors && (cl->fg != COLOR_UNSET) && (cl->bg != COLOR_UNSET))
306  mutt_color_free(c, cl->fg, cl->bg);
307 #endif
308 
309  regfree(&cl->regex);
311  FREE(&cl->pattern);
312  FREE(ptr);
313 }
314 
320 static void color_line_list_clear(struct Colors *c, struct ColorLineList *list)
321 {
322  struct ColorLine *np = NULL, *tmp = NULL;
323  STAILQ_FOREACH_SAFE(np, list, entries, tmp)
324  {
325  STAILQ_REMOVE(list, np, ColorLine, entries);
326  color_line_free(c, &np, true);
327  }
328 }
329 
334 static void colors_clear(struct Colors *c)
335 {
345 
346  defs_clear(c);
347  quotes_clear(c);
348 
350 }
351 
356 void mutt_colors_free(struct Colors **ptr)
357 {
358  if (!ptr || !*ptr)
359  return;
360 
361  struct Colors *c = *ptr;
362 
363  colors_clear(c);
364  defs_free(c);
365  quotes_free(c);
366  notify_free(&c->notify);
367  FREE(ptr);
368 }
369 
374 struct Colors *mutt_colors_new(void)
375 {
376  struct Colors *c = mutt_mem_calloc(1, sizeof(*c));
377  c->notify = notify_new();
378 
379  quotes_init(c);
380  defs_init(c);
381 
383  STAILQ_INIT(&c->body_list);
384  STAILQ_INIT(&c->hdr_list);
387  STAILQ_INIT(&c->index_list);
391 
392 #ifdef HAVE_COLOR
393  start_color();
394 #endif
395 
397  return c;
398 }
399 
404 static struct ColorLine *color_line_new(void)
405 {
406  struct ColorLine *cl = mutt_mem_calloc(1, sizeof(struct ColorLine));
407 
408  cl->fg = COLOR_UNSET;
409  cl->bg = COLOR_UNSET;
410 
411  return cl;
412 }
413 
414 #ifdef HAVE_COLOR
415 #ifdef USE_SLANG_CURSES
416 
423 static char *get_color_name(char *dest, size_t destlen, uint32_t val)
424 {
425  static const char *const missing[3] = { "brown", "lightgray", "default" };
426 
427  if (val & RGB24)
428  {
429  assert(snprintf(dest, destlen, "#%06X", val & 0xffffff) == 7);
430  return dest;
431  }
432 
433  switch (val)
434  {
435  case COLOR_YELLOW:
436  mutt_str_copy(dest, missing[0], destlen);
437  return dest;
438 
439  case COLOR_WHITE:
440  mutt_str_copy(dest, missing[1], destlen);
441  return dest;
442 
443  case COLOR_DEFAULT:
444  mutt_str_copy(dest, missing[2], destlen);
445  return dest;
446  }
447 
448  for (int i = 0; ColorNames[i].name; i++)
449  {
450  if (ColorNames[i].value == val)
451  {
452  mutt_str_copy(dest, ColorNames[i].name, destlen);
453  return dest;
454  }
455  }
456 
457  /* Sigh. If we got this far, the color is of the form 'colorN'
458  * Slang can handle this itself, so just return 'colorN' */
459  snprintf(dest, destlen, "color%d", val);
460 
461  return dest;
462 }
463 #endif
464 
472 int mutt_color_alloc(struct Colors *c, uint32_t fg, uint32_t bg)
473 {
474 #ifdef USE_SLANG_CURSES
475  char fgc[128], bgc[128];
476 #endif
477  struct ColorList *p = c->user_colors;
478 
479  /* check to see if this color is already allocated to save space */
480  while (p)
481  {
482  if ((p->fg == fg) && (p->bg == bg))
483  {
484  (p->count)++;
485  return COLOR_PAIR(p->index);
486  }
487  p = p->next;
488  }
489 
490  /* check to see if there are colors left */
491  if (++c->num_user_colors > COLOR_PAIRS)
492  return A_NORMAL;
493 
494  /* find the smallest available index (object) */
495  int i = 1;
496  while (true)
497  {
498  p = c->user_colors;
499  while (p)
500  {
501  if (p->index == i)
502  break;
503  p = p->next;
504  }
505  if (!p)
506  break;
507  i++;
508  }
509 
510  p = mutt_mem_malloc(sizeof(struct ColorList));
511  p->next = c->user_colors;
512  c->user_colors = p;
513 
514  p->index = i;
515  p->count = 1;
516  p->bg = bg;
517  p->fg = fg;
518 
519 #ifdef USE_SLANG_CURSES
520  /*
521  * If using s-lang always use SLtt_set_color which allows using truecolor
522  * values. Note that I couldn't figure out if s-lang somehow reports
523  * truecolor support.
524  */
525  SLtt_set_color(i, NULL, get_color_name(fgc, sizeof(fgc), fg),
526  get_color_name(bgc, sizeof(bgc), bg));
527 #else
528 #ifdef HAVE_USE_DEFAULT_COLORS
529  if (fg == COLOR_DEFAULT)
530  fg = COLOR_UNSET;
531  if (bg == COLOR_DEFAULT)
532  bg = COLOR_UNSET;
533 #endif
534  init_pair(i, fg, bg);
535 #endif
536 
537  mutt_debug(LL_DEBUG3, "Color pairs used so far: %d\n", c->num_user_colors);
538 
539  return COLOR_PAIR(p->index);
540 }
541 
551 static int mutt_lookup_color(struct Colors *c, short pair, uint32_t *fg, uint32_t *bg)
552 {
553  struct ColorList *p = c->user_colors;
554 
555  while (p)
556  {
557  if (COLOR_PAIR(p->index) == pair)
558  {
559  if (fg)
560  *fg = p->fg;
561  if (bg)
562  *bg = p->bg;
563  return 0;
564  }
565  p = p->next;
566  }
567  return -1;
568 }
569 
577 int mutt_color_combine(struct Colors *c, uint32_t fg_attr, uint32_t bg_attr)
578 {
579  uint32_t fg = COLOR_DEFAULT;
580  uint32_t bg = COLOR_DEFAULT;
581 
582  mutt_lookup_color(c, fg_attr, &fg, NULL);
583  mutt_lookup_color(c, bg_attr, NULL, &bg);
584 
585  if ((fg == COLOR_DEFAULT) && (bg == COLOR_DEFAULT))
586  return A_NORMAL;
587  return mutt_color_alloc(c, fg, bg);
588 }
589 #endif /* HAVE_COLOR */
590 
591 #ifdef HAVE_COLOR
592 
603 static enum CommandResult parse_color_name(const char *s, uint32_t *col, int *attr,
604  bool is_fg, struct Buffer *err)
605 {
606  char *eptr = NULL;
607  bool is_alert = false, is_bright = false, is_light = false;
608  int clen;
609 
610  if ((clen = mutt_istr_startswith(s, "bright")))
611  {
612  is_bright = true;
613  s += clen;
614  }
615  else if ((clen = mutt_istr_startswith(s, "alert")))
616  {
617  is_alert = true;
618  is_bright = true;
619  s += clen;
620  }
621  else if ((clen = mutt_istr_startswith(s, "light")))
622  {
623  is_light = true;
624  s += clen;
625  }
626 
627  /* allow aliases for xterm color resources */
628  if ((clen = mutt_istr_startswith(s, "color")))
629  {
630  s += clen;
631  *col = strtoul(s, &eptr, 10);
632  if ((*s == '\0') || (*eptr != '\0') || ((*col >= COLORS) && !OptNoCurses && has_colors()))
633  {
634  mutt_buffer_printf(err, _("%s: color not supported by term"), s);
635  return MUTT_CMD_ERROR;
636  }
637  }
638 #ifdef HAVE_DIRECTCOLOR
639  else if (*s == '#')
640  {
641  s += 1;
642  *col = strtoul(s, &eptr, 16);
643  if ((*s == '\0') || (*eptr != '\0') || ((*col == COLOR_UNSET) && !OptNoCurses && has_colors()))
644  {
645  snprintf(err->data, err->dsize, _("%s: color not supported by term"), s);
646  return MUTT_CMD_ERROR;
647  }
648  *col |= RGB24;
649  }
650 #endif
651  else if ((*col = mutt_map_get_value(s, ColorNames)) == -1)
652  {
653  mutt_buffer_printf(err, _("%s: no such color"), s);
654  return MUTT_CMD_WARNING;
655  }
656 
657  if (is_bright || is_light)
658  {
659  if (is_alert)
660  {
661  *attr |= A_BOLD;
662  *attr |= A_BLINK;
663  }
664  else if (is_fg)
665  {
666  if ((COLORS >= 16) && is_light)
667  {
668  if (*col <= 7)
669  {
670  /* Advance the color 0-7 by 8 to get the light version */
671  *col += 8;
672  }
673  }
674  else
675  {
676  *attr |= A_BOLD;
677  }
678  }
679  else if (!(*col & RGB24))
680  {
681  if (COLORS >= 16)
682  {
683  if (*col <= 7)
684  {
685  /* Advance the color 0-7 by 8 to get the light version */
686  *col += 8;
687  }
688  }
689  }
690  }
691 
692  return MUTT_CMD_SUCCESS;
693 }
694 #endif
695 
705 static enum CommandResult parse_object(struct Buffer *buf, struct Buffer *s,
706  enum ColorId *obj, int *ql, struct Buffer *err)
707 {
708  int rc;
709 
710  if (mutt_str_startswith(buf->data, "quoted") != 0)
711  {
712  int val = 0;
713  if (buf->data[6] != '\0')
714  {
715  rc = mutt_str_atoi(buf->data + 6, &val);
716  if ((rc != 0) || (val > COLOR_QUOTES_MAX))
717  {
718  mutt_buffer_printf(err, _("%s: no such object"), buf->data);
719  return MUTT_CMD_WARNING;
720  }
721  }
722 
723  *ql = val;
724  *obj = MT_COLOR_QUOTED;
725  return MUTT_CMD_SUCCESS;
726  }
727 
728  if (mutt_istr_equal(buf->data, "compose"))
729  {
730  if (!MoreArgs(s))
731  {
732  mutt_buffer_printf(err, _("%s: too few arguments"), "color");
733  return MUTT_CMD_WARNING;
734  }
735 
737 
739  if (rc == -1)
740  {
741  mutt_buffer_printf(err, _("%s: no such object"), buf->data);
742  return MUTT_CMD_WARNING;
743  }
744 
745  *obj = rc;
746  return MUTT_CMD_SUCCESS;
747  }
748 
749  rc = mutt_map_get_value(buf->data, Fields);
750  if (rc == -1)
751  {
752  mutt_buffer_printf(err, _("%s: no such object"), buf->data);
753  return MUTT_CMD_WARNING;
754  }
755 
756  *obj = rc;
757  return MUTT_CMD_SUCCESS;
758 }
759 
769 static bool do_uncolor(struct Colors *c, struct Buffer *buf, struct Buffer *s,
770  struct ColorLineList *cl, bool uncolor)
771 {
772  struct ColorLine *np = NULL, *prev = NULL;
773  bool rc = false;
774 
775  do
776  {
778  if (mutt_str_equal("*", buf->data))
779  {
780  rc = STAILQ_FIRST(cl);
781  color_line_list_clear(c, cl);
782  return rc;
783  }
784 
785  prev = NULL;
786  STAILQ_FOREACH(np, cl, entries)
787  {
788  if (mutt_str_equal(buf->data, np->pattern))
789  {
790  rc = true;
791 
792  mutt_debug(LL_DEBUG1, "Freeing pattern \"%s\" from user_colors\n", buf->data);
793  if (prev)
794  STAILQ_REMOVE_AFTER(cl, prev, entries);
795  else
796  STAILQ_REMOVE_HEAD(cl, entries);
797  color_line_free(c, &np, uncolor);
798  break;
799  }
800  prev = np;
801  }
802  } while (MoreArgs(s));
803 
804  return rc;
805 }
806 
820 static enum CommandResult parse_uncolor(struct Buffer *buf, struct Buffer *s,
821  struct Colors *c, struct Buffer *err, bool uncolor)
822 {
824 
825  if (mutt_str_equal(buf->data, "*"))
826  {
827  colors_clear(c);
828  struct EventColor ec = { MT_COLOR_MAX };
830  return MUTT_CMD_SUCCESS;
831  }
832 
833  unsigned int object = MT_COLOR_NONE;
834  int ql = 0;
835  enum CommandResult rc = parse_object(buf, s, &object, &ql, err);
836  if (rc != MUTT_CMD_SUCCESS)
837  return rc;
838 
839  if (object == -1)
840  {
841  mutt_buffer_printf(err, _("%s: no such object"), buf->data);
842  return MUTT_CMD_ERROR;
843  }
844 
845  if (object == MT_COLOR_QUOTED)
846  {
847  c->quotes[ql] = A_NORMAL;
848  /* fallthrough to simple case */
849  }
850 
851  if ((object != MT_COLOR_ATTACH_HEADERS) && (object != MT_COLOR_BODY) &&
852  (object != MT_COLOR_HEADER) && (object != MT_COLOR_INDEX) &&
853  (object != MT_COLOR_INDEX_AUTHOR) && (object != MT_COLOR_INDEX_FLAGS) &&
854  (object != MT_COLOR_INDEX_SUBJECT) && (object != MT_COLOR_INDEX_TAG) &&
855  (object != MT_COLOR_STATUS))
856  {
857  // Simple colours
858  c->defs[object] = A_NORMAL;
859 
860  struct EventColor ec = { object };
862  return MUTT_CMD_SUCCESS;
863  }
864 
865  if (!MoreArgs(s))
866  {
867  mutt_buffer_printf(err, _("%s: too few arguments"), uncolor ? "uncolor" : "unmono");
868  return MUTT_CMD_WARNING;
869  }
870 
871 #ifdef HAVE_COLOR
872  if (OptNoCurses || // running without curses
873  (uncolor && !has_colors()) || // parsing an uncolor command, and have no colors
874  (!uncolor && has_colors())) // parsing an unmono command, and have colors
875 #else
876  if (uncolor) // We don't even have colors compiled in
877 #endif
878  {
879  do
880  {
881  /* just eat the command, but don't do anything real about it */
883  } while (MoreArgs(s));
884 
885  return MUTT_CMD_SUCCESS;
886  }
887 
888  bool changed = false;
889  if (object == MT_COLOR_ATTACH_HEADERS)
890  changed |= do_uncolor(c, buf, s, &c->attach_list, uncolor);
891  else if (object == MT_COLOR_BODY)
892  changed |= do_uncolor(c, buf, s, &c->body_list, uncolor);
893  else if (object == MT_COLOR_HEADER)
894  changed |= do_uncolor(c, buf, s, &c->hdr_list, uncolor);
895  else if (object == MT_COLOR_INDEX)
896  changed |= do_uncolor(c, buf, s, &c->index_list, uncolor);
897  else if (object == MT_COLOR_INDEX_AUTHOR)
898  changed |= do_uncolor(c, buf, s, &c->index_author_list, uncolor);
899  else if (object == MT_COLOR_INDEX_FLAGS)
900  changed |= do_uncolor(c, buf, s, &c->index_flags_list, uncolor);
901  else if (object == MT_COLOR_INDEX_SUBJECT)
902  changed |= do_uncolor(c, buf, s, &c->index_subject_list, uncolor);
903  else if (object == MT_COLOR_INDEX_TAG)
904  changed |= do_uncolor(c, buf, s, &c->index_tag_list, uncolor);
905  else if (object == MT_COLOR_STATUS)
906  changed |= do_uncolor(c, buf, s, &c->status_list, uncolor);
907 
908  if (changed)
909  {
910  struct EventColor ec = { object };
912  }
913 
914  return MUTT_CMD_SUCCESS;
915 }
916 
917 #ifdef HAVE_COLOR
918 
921 enum CommandResult mutt_parse_uncolor(struct Buffer *buf, struct Buffer *s,
922  intptr_t data, struct Buffer *err)
923 {
924  return parse_uncolor(buf, s, Colors, err, true);
925 }
926 #endif
927 
931 enum CommandResult mutt_parse_unmono(struct Buffer *buf, struct Buffer *s,
932  intptr_t data, struct Buffer *err)
933 {
934  return parse_uncolor(buf, s, Colors, err, false);
935 }
936 
954 static enum CommandResult add_pattern(struct Colors *c, struct ColorLineList *top, const char *s,
955  bool sensitive, uint32_t fg, uint32_t bg, int attr,
956  struct Buffer *err, bool is_index, int match)
957 {
958  struct ColorLine *tmp = NULL;
959 
960  STAILQ_FOREACH(tmp, top, entries)
961  {
962  if ((sensitive && mutt_str_equal(s, tmp->pattern)) ||
963  (!sensitive && mutt_istr_equal(s, tmp->pattern)))
964  {
965  break;
966  }
967  }
968 
969  if (tmp)
970  {
971 #ifdef HAVE_COLOR
972  if ((fg != COLOR_UNSET) && (bg != COLOR_UNSET))
973  {
974  if ((tmp->fg != fg) || (tmp->bg != bg))
975  {
976  mutt_color_free(c, tmp->fg, tmp->bg);
977  tmp->fg = fg;
978  tmp->bg = bg;
979  attr |= mutt_color_alloc(c, fg, bg);
980  }
981  else
982  attr |= (tmp->pair & ~A_BOLD);
983  }
984 #endif /* HAVE_COLOR */
985  tmp->pair = attr;
986  }
987  else
988  {
989  tmp = color_line_new();
990  if (is_index)
991  {
992  struct Buffer *buf = mutt_buffer_pool_get();
993  mutt_buffer_strcpy(buf, s);
997  if (!tmp->color_pattern)
998  {
999  color_line_free(c, &tmp, true);
1000  return MUTT_CMD_ERROR;
1001  }
1002  }
1003  else
1004  {
1005  uint16_t flags = 0;
1006  if (sensitive)
1007  flags = mutt_mb_is_lower(s) ? REG_ICASE : 0;
1008  else
1009  flags = REG_ICASE;
1010 
1011  const int r = REG_COMP(&tmp->regex, s, flags);
1012  if (r != 0)
1013  {
1014  regerror(r, &tmp->regex, err->data, err->dsize);
1015  color_line_free(c, &tmp, true);
1016  return MUTT_CMD_ERROR;
1017  }
1018  }
1019  tmp->pattern = mutt_str_dup(s);
1020  tmp->match = match;
1021 #ifdef HAVE_COLOR
1022  if ((fg != COLOR_UNSET) && (bg != COLOR_UNSET))
1023  {
1024  tmp->fg = fg;
1025  tmp->bg = bg;
1026  attr |= mutt_color_alloc(c, fg, bg);
1027  }
1028 #endif
1029  tmp->pair = attr;
1030  STAILQ_INSERT_HEAD(top, tmp, entries);
1031  }
1032 
1033  /* force re-caching of index colors */
1034  const struct Mailbox *m = ctx_mailbox(Context);
1035  if (is_index && m)
1036  {
1037  for (int i = 0; i < m->msg_count; i++)
1038  {
1039  struct Email *e = m->emails[i];
1040  if (!e)
1041  break;
1042  e->pair = 0;
1043  }
1044  }
1045 
1046  return MUTT_CMD_SUCCESS;
1047 }
1048 
1049 #ifdef HAVE_COLOR
1050 
1053 static enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s,
1054  uint32_t *fg, uint32_t *bg,
1055  int *attr, struct Buffer *err)
1056 {
1057  while (true)
1058  {
1059  if (!MoreArgs(s))
1060  {
1061  mutt_buffer_printf(err, _("%s: too few arguments"), "color");
1062  return MUTT_CMD_WARNING;
1063  }
1064 
1066 
1067  if (mutt_istr_equal("bold", buf->data))
1068  *attr |= A_BOLD;
1069  else if (mutt_istr_equal("none", buf->data))
1070  *attr = A_NORMAL; // Use '=' to clear other bits
1071  else if (mutt_istr_equal("normal", buf->data))
1072  *attr = A_NORMAL; // Use '=' to clear other bits
1073  else if (mutt_istr_equal("reverse", buf->data))
1074  *attr |= A_REVERSE;
1075  else if (mutt_istr_equal("standout", buf->data))
1076  *attr |= A_STANDOUT;
1077  else if (mutt_istr_equal("underline", buf->data))
1078  *attr |= A_UNDERLINE;
1079  else
1080  {
1081  enum CommandResult rc = parse_color_name(buf->data, fg, attr, true, err);
1082  if (rc != MUTT_CMD_SUCCESS)
1083  return rc;
1084  break;
1085  }
1086  }
1087 
1088  if (!MoreArgs(s))
1089  {
1090  mutt_buffer_printf(err, _("%s: too few arguments"), "color");
1091  return MUTT_CMD_WARNING;
1092  }
1093 
1095 
1096  return parse_color_name(buf->data, bg, attr, false, err);
1097 }
1098 #endif
1099 
1103 static enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s,
1104  uint32_t *fg, uint32_t *bg, int *attr,
1105  struct Buffer *err)
1106 {
1107  if (fg)
1108  *fg = COLOR_UNSET;
1109  if (bg)
1110  *bg = COLOR_UNSET;
1111 
1112  if (!MoreArgs(s))
1113  {
1114  mutt_buffer_printf(err, _("%s: too few arguments"), "mono");
1115  return MUTT_CMD_WARNING;
1116  }
1117 
1119 
1120  if (mutt_istr_equal("bold", buf->data))
1121  *attr |= A_BOLD;
1122  else if (mutt_istr_equal("none", buf->data))
1123  *attr = A_NORMAL; // Use '=' to clear other bits
1124  else if (mutt_istr_equal("normal", buf->data))
1125  *attr = A_NORMAL; // Use '=' to clear other bits
1126  else if (mutt_istr_equal("reverse", buf->data))
1127  *attr |= A_REVERSE;
1128  else if (mutt_istr_equal("standout", buf->data))
1129  *attr |= A_STANDOUT;
1130  else if (mutt_istr_equal("underline", buf->data))
1131  *attr |= A_UNDERLINE;
1132  else
1133  {
1134  mutt_buffer_printf(err, _("%s: no such attribute"), buf->data);
1135  return MUTT_CMD_WARNING;
1136  }
1137 
1138  return MUTT_CMD_SUCCESS;
1139 }
1140 
1149 static int fgbgattr_to_color(struct Colors *c, int fg, int bg, int attr)
1150 {
1151 #ifdef HAVE_COLOR
1152  if ((fg != COLOR_UNSET) && (bg != COLOR_UNSET))
1153  return attr | mutt_color_alloc(c, fg, bg);
1154 #endif
1155  return attr;
1156 }
1157 
1172 static enum CommandResult parse_color(struct Colors *c, struct Buffer *buf, struct Buffer *s,
1173  struct Buffer *err, parser_callback_t callback,
1174  bool dry_run, bool color)
1175 {
1176  int attr = 0, q_level = 0;
1177  uint32_t fg = 0, bg = 0, match = 0;
1178  enum ColorId object = MT_COLOR_NONE;
1179  enum CommandResult rc;
1180 
1181  if (!MoreArgs(s))
1182  {
1183  mutt_buffer_printf(err, _("%s: too few arguments"), "color");
1184  return MUTT_CMD_WARNING;
1185  }
1186 
1188 
1189  rc = parse_object(buf, s, &object, &q_level, err);
1190  if (rc != MUTT_CMD_SUCCESS)
1191  return rc;
1192 
1193  rc = callback(buf, s, &fg, &bg, &attr, err);
1194  if (rc != MUTT_CMD_SUCCESS)
1195  return rc;
1196 
1197  /* extract a regular expression if needed */
1198 
1199  if ((object == MT_COLOR_ATTACH_HEADERS) || (object == MT_COLOR_BODY) ||
1200  (object == MT_COLOR_HEADER) || (object == MT_COLOR_INDEX) ||
1201  (object == MT_COLOR_INDEX_AUTHOR) || (object == MT_COLOR_INDEX_FLAGS) ||
1202  (object == MT_COLOR_INDEX_SUBJECT) || (object == MT_COLOR_INDEX_TAG))
1203  {
1204  if (!MoreArgs(s))
1205  {
1206  mutt_buffer_printf(err, _("%s: too few arguments"), color ? "color" : "mono");
1207  return MUTT_CMD_WARNING;
1208  }
1209 
1211  }
1212 
1213  if (MoreArgs(s) && (object != MT_COLOR_STATUS))
1214  {
1215  mutt_buffer_printf(err, _("%s: too many arguments"), color ? "color" : "mono");
1216  return MUTT_CMD_WARNING;
1217  }
1218 
1219  if (dry_run)
1220  {
1221  *s->dptr = '\0'; /* fake that we're done parsing */
1222  return MUTT_CMD_SUCCESS;
1223  }
1224 
1225 #ifdef HAVE_COLOR
1226 #ifdef HAVE_USE_DEFAULT_COLORS
1227  if (!OptNoCurses &&
1228  has_colors()
1229  /* delay use_default_colors() until needed, since it initializes things */
1230  && ((fg == COLOR_DEFAULT) || (bg == COLOR_DEFAULT) || (object == MT_COLOR_TREE)) &&
1231  (use_default_colors() != OK))
1232  /* the case of the tree object is special, because a non-default fg color of
1233  * the tree element may be combined dynamically with the default bg color of
1234  * an index line, not necessarily defined in a rc file. */
1235  {
1236  mutt_buffer_strcpy(err, _("default colors not supported"));
1237  return MUTT_CMD_ERROR;
1238  }
1239 #endif /* HAVE_USE_DEFAULT_COLORS */
1240 #endif
1241 
1242  if (object == MT_COLOR_ATTACH_HEADERS)
1243  rc = add_pattern(c, &c->attach_list, buf->data, true, fg, bg, attr, err, false, match);
1244  else if (object == MT_COLOR_BODY)
1245  rc = add_pattern(c, &c->body_list, buf->data, true, fg, bg, attr, err, false, match);
1246  else if (object == MT_COLOR_HEADER)
1247  rc = add_pattern(c, &c->hdr_list, buf->data, false, fg, bg, attr, err, false, match);
1248  else if (object == MT_COLOR_INDEX)
1249  {
1250  rc = add_pattern(c, &c->index_list, buf->data, true, fg, bg, attr, err, true, match);
1251  }
1252  else if (object == MT_COLOR_INDEX_AUTHOR)
1253  {
1254  rc = add_pattern(c, &c->index_author_list, buf->data, true, fg, bg, attr,
1255  err, true, match);
1256  }
1257  else if (object == MT_COLOR_INDEX_FLAGS)
1258  {
1259  rc = add_pattern(c, &c->index_flags_list, buf->data, true, fg, bg, attr, err, true, match);
1260  }
1261  else if (object == MT_COLOR_INDEX_SUBJECT)
1262  {
1263  rc = add_pattern(c, &c->index_subject_list, buf->data, true, fg, bg, attr,
1264  err, true, match);
1265  }
1266  else if (object == MT_COLOR_INDEX_TAG)
1267  {
1268  rc = add_pattern(c, &c->index_tag_list, buf->data, true, fg, bg, attr, err, true, match);
1269  }
1270  else if (object == MT_COLOR_QUOTED)
1271  {
1272  if (q_level >= COLOR_QUOTES_MAX)
1273  {
1274  mutt_buffer_printf(err, _("Maximum quoting level is %d"), COLOR_QUOTES_MAX - 1);
1275  return MUTT_CMD_WARNING;
1276  }
1277 
1278  if (q_level >= c->quotes_used)
1279  c->quotes_used = q_level + 1;
1280  if (q_level == 0)
1281  {
1282  c->defs[MT_COLOR_QUOTED] = fgbgattr_to_color(c, fg, bg, attr);
1283 
1284  c->quotes[0] = c->defs[MT_COLOR_QUOTED];
1285  for (q_level = 1; q_level < c->quotes_used; q_level++)
1286  {
1287  if (c->quotes[q_level] == A_NORMAL)
1288  c->quotes[q_level] = c->defs[MT_COLOR_QUOTED];
1289  }
1290  }
1291  else
1292  {
1293  c->quotes[q_level] = fgbgattr_to_color(c, fg, bg, attr);
1294  }
1295  rc = MUTT_CMD_SUCCESS;
1296  }
1297  else if ((object == MT_COLOR_STATUS) && MoreArgs(s))
1298  {
1299  /* 'color status fg bg' can have up to 2 arguments:
1300  * 0 arguments: sets the default status color (handled below by else part)
1301  * 1 argument : colorize pattern on match
1302  * 2 arguments: colorize nth submatch of pattern */
1304 
1305  if (MoreArgs(s))
1306  {
1307  struct Buffer tmp = mutt_buffer_make(0);
1309  if (mutt_str_atoui(tmp.data, &match) < 0)
1310  {
1311  mutt_buffer_printf(err, _("%s: invalid number: %s"),
1312  color ? "color" : "mono", tmp.data);
1313  mutt_buffer_dealloc(&tmp);
1314  return MUTT_CMD_WARNING;
1315  }
1316  mutt_buffer_dealloc(&tmp);
1317  }
1318 
1319  if (MoreArgs(s))
1320  {
1321  mutt_buffer_printf(err, _("%s: too many arguments"), color ? "color" : "mono");
1322  return MUTT_CMD_WARNING;
1323  }
1324 
1325  rc = add_pattern(c, &c->status_list, buf->data, true, fg, bg, attr, err, false, match);
1326  }
1327  else // Remaining simple colours
1328  {
1329  c->defs[object] = fgbgattr_to_color(c, fg, bg, attr);
1330  rc = MUTT_CMD_SUCCESS;
1331  }
1332 
1333  if (rc == MUTT_CMD_SUCCESS)
1334  {
1335  struct EventColor ec = { object };
1337  }
1338 
1339  return rc;
1340 }
1341 
1342 #ifdef HAVE_COLOR
1343 
1346 enum CommandResult mutt_parse_color(struct Buffer *buf, struct Buffer *s,
1347  intptr_t data, struct Buffer *err)
1348 {
1349  bool dry_run = false;
1350 
1351  if (OptNoCurses || !has_colors())
1352  dry_run = true;
1353 
1354  return parse_color(Colors, buf, s, err, parse_color_pair, dry_run, true);
1355 }
1356 #endif
1357 
1361 enum CommandResult mutt_parse_mono(struct Buffer *buf, struct Buffer *s,
1362  intptr_t data, struct Buffer *err)
1363 {
1364  bool dry_run = false;
1365 
1366 #ifdef HAVE_COLOR
1367  if (OptNoCurses || has_colors())
1368  dry_run = true;
1369 #else
1370  if (OptNoCurses)
1371  dry_run = true;
1372 #endif
1373 
1374  return parse_color(Colors, buf, s, err, parse_attr_spec, dry_run, false);
1375 }
MT_COLOR_UNDERLINE
@ MT_COLOR_UNDERLINE
Underlined text.
Definition: color.h:97
fgbgattr_to_color
static int fgbgattr_to_color(struct Colors *c, int fg, int bg, int attr)
Convert a foreground, background, attribute triplet into a colour.
Definition: color.c:1149
mutt_color_free
void mutt_color_free(struct Colors *c, uint32_t fg, uint32_t bg)
Free a colour.
Definition: color.c:252
MT_COLOR_COMPOSE_HEADER
@ MT_COLOR_COMPOSE_HEADER
Header labels, e.g. From:
Definition: color.h:65
STAILQ_INIT
#define STAILQ_INIT(head)
Definition: queue.h:369
mutt_pattern_comp
struct PatternList * mutt_pattern_comp(struct Context *ctx, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:1082
MT_COLOR_SIDEBAR_HIGHLIGHT
@ MT_COLOR_SIDEBAR_HIGHLIGHT
Select cursor.
Definition: color.h:86
parse_attr_spec
static enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s, uint32_t *fg, uint32_t *bg, int *attr, struct Buffer *err)
Parse an attribute description - Implements parser_callback_t.
Definition: color.c:1103
Colors::index_author_list
struct ColorLineList index_author_list
List of colours applied to the author in the index.
Definition: color.h:136
MT_COLOR_INDEX_DATE
@ MT_COLOR_INDEX_DATE
Index: date field.
Definition: color.h:107
ColorLine::regex
regex_t regex
Compiled regex.
Definition: color.h:37
mutt_mem_calloc
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
NT_COLOR_RESET
@ NT_COLOR_RESET
Color has been reset/removed.
Definition: color.h:172
ColorLine::bg
uint32_t bg
Background colour.
Definition: color.h:42
_
#define _(a)
Definition: message.h:28
NONULL
#define NONULL(x)
Definition: string2.h:37
Mailbox
A mailbox.
Definition: mailbox.h:81
Mailbox::emails
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
MT_COLOR_INDEX_LABEL
@ MT_COLOR_INDEX_LABEL
Index: label field.
Definition: color.h:108
mutt_pattern_free
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1029
MT_COLOR_ERROR
@ MT_COLOR_ERROR
Error message.
Definition: color.h:70
MoreArgs
#define MoreArgs(buf)
Definition: buffer.h:40
color_line_new
static struct ColorLine * color_line_new(void)
Create a new ColorLine.
Definition: color.c:404
MT_COLOR_STATUS
@ MT_COLOR_STATUS
Status bar (takes a pattern)
Definition: color.h:94
Buffer
String manipulation buffer.
Definition: buffer.h:33
LL_DEBUG3
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
STAILQ_REMOVE
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:399
ctx_mailbox
struct Mailbox * ctx_mailbox(struct Context *ctx)
wrapper to get the mailbox in a Context, or NULL
Definition: context.c:429
MT_COLOR_INDEX_AUTHOR
@ MT_COLOR_INDEX_AUTHOR
Index: author field (takes a pattern)
Definition: color.h:101
ColorList::fg
uint32_t fg
Definition: color.h:122
do_uncolor
static bool do_uncolor(struct Colors *c, struct Buffer *buf, struct Buffer *s, struct ColorLineList *cl, bool uncolor)
Parse the 'uncolor' or 'unmono' command.
Definition: color.c:769
mutt_buffer_dealloc
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
mutt_lookup_color
static int mutt_lookup_color(struct Colors *c, short pair, uint32_t *fg, uint32_t *bg)
Get the colours from a colour pair.
Definition: color.c:551
mutt_color_combine
int mutt_color_combine(struct Colors *c, uint32_t fg_attr, uint32_t bg_attr)
Combine two colours.
Definition: color.c:577
MT_COLOR_HDRDEFAULT
@ MT_COLOR_HDRDEFAULT
Header default colour.
Definition: color.h:71
MT_COLOR_WARNING
@ MT_COLOR_WARNING
Warning messages.
Definition: color.h:98
mutt_parse_unmono
enum CommandResult mutt_parse_unmono(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unmono' command - Implements Command::parse()
Definition: color.c:931
defs_free
static void defs_free(struct Colors *c)
Free the simple colour definitions.
Definition: color.c:160
Colors::num_user_colors
int num_user_colors
Definition: color.h:147
NeoMutt::notify
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
Colors::body_list
struct ColorLineList body_list
List of colours applied to the email body.
Definition: color.h:134
RGB24
#define RGB24
Definition: color.c:78
color_line_free
static void color_line_free(struct Colors *c, struct ColorLine **ptr, bool free_colors)
Free a ColorLine.
Definition: color.c:297
MT_COLOR_QUOTED
@ MT_COLOR_QUOTED
Pager: quoted text.
Definition: color.h:81
defs_clear
static void defs_clear(struct Colors *c)
Reset the simple colour definitions.
Definition: color.c:188
Context
The "current" mailbox.
Definition: context.h:38
mutt_str_dup
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
MT_COLOR_BOLD
@ MT_COLOR_BOLD
Bold text.
Definition: color.h:64
mutt_globals.h
LL_DEBUG1
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
MT_COLOR_INDICATOR
@ MT_COLOR_INDICATOR
Selected item in list.
Definition: color.h:73
COLOR_QUOTES_MAX
#define COLOR_QUOTES_MAX
Ten colours, quoted0..quoted9 (quoted and quoted0 are equivalent)
Definition: color.c:66
FREE
#define FREE(x)
Definition: memory.h:40
options.h
STAILQ_FIRST
#define STAILQ_FIRST(head)
Definition: queue.h:347
MUTT_TOKEN_NO_FLAGS
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:70
parse_uncolor
static enum CommandResult parse_uncolor(struct Buffer *buf, struct Buffer *s, struct Colors *c, struct Buffer *err, bool uncolor)
Parse an 'uncolor' command.
Definition: color.c:820
mutt_parse_mono
enum CommandResult mutt_parse_mono(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'mono' command - Implements Command::parse()
Definition: color.c:1361
Buffer::dptr
char * dptr
Current read/write position.
Definition: buffer.h:36
Buffer::dsize
size_t dsize
Length of data.
Definition: buffer.h:37
Colors::user_colors
struct ColorList * user_colors
Definition: color.h:146
OptNoCurses
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:48
MT_COLOR_INDEX_NUMBER
@ MT_COLOR_INDEX_NUMBER
Index: index number.
Definition: color.h:109
mutt_buffer_pool_release
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
mutt_parse_uncolor
enum CommandResult mutt_parse_uncolor(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'uncolor' command - Implements Command::parse()
Definition: color.c:921
ColorId
ColorId
List of all colored objects.
Definition: color.h:58
colors_clear
static void colors_clear(struct Colors *c)
Reset all the colours.
Definition: color.c:334
NT_COLOR_SET
@ NT_COLOR_SET
A new Color has been set.
Definition: color.h:171
ColorList::count
short count
Definition: color.h:125
mutt_str_atoi
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:252
STAILQ_FOREACH
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
MT_COLOR_BODY
@ MT_COLOR_BODY
Pager: highlight body of message (takes a pattern)
Definition: color.h:63
defs_init
static void defs_init(struct Colors *c)
Initialise the simple colour definitions.
Definition: color.c:169
MT_COLOR_NORMAL
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:77
add_pattern
static enum CommandResult add_pattern(struct Colors *c, struct ColorLineList *top, const char *s, bool sensitive, uint32_t fg, uint32_t bg, int attr, struct Buffer *err, bool is_index, int match)
Associate a colour to a pattern.
Definition: color.c:954
notify_send
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:152
MT_COLOR_INDEX_TAGS
@ MT_COLOR_INDEX_TAGS
Index: tags field (g, J)
Definition: color.h:111
Colors::hdr_list
struct ColorLineList hdr_list
List of colours applied to the email headers.
Definition: color.h:135
quotes_clear
static void quotes_clear(struct Colors *c)
Reset the quoted-email colours.
Definition: color.c:217
MT_COLOR_NONE
@ MT_COLOR_NONE
Definition: color.h:60
mutt_istr_equal
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
mutt_str_equal
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
MT_COLOR_SEARCH
@ MT_COLOR_SEARCH
Pager: search matches.
Definition: color.h:82
Mapping
Mapping between user-readable string and a constant.
Definition: mapping.h:31
notify_new
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:49
mutt_extract_token
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:393
MT_COLOR_SIGNATURE
@ MT_COLOR_SIGNATURE
Pager: signature lines.
Definition: color.h:93
Colors::quotes_used
int quotes_used
Number of colours for quoted email text.
Definition: color.h:144
MT_COLOR_MESSAGE
@ MT_COLOR_MESSAGE
Informational message.
Definition: color.h:75
parser_callback_t
int(* parser_callback_t)(struct Buffer *buf, struct Buffer *s, uint32_t *fg, uint32_t *bg, int *attr, struct Buffer *err)
Prototype for a function to parse color config.
Definition: color.c:62
mutt_buffer_pool_get
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
MT_COLOR_COMPOSE_SECURITY_NONE
@ MT_COLOR_COMPOSE_SECURITY_NONE
Mail will not be encrypted or signed.
Definition: color.h:68
MT_COLOR_ATTACH_HEADERS
@ MT_COLOR_ATTACH_HEADERS
MIME attachment test (takes a pattern)
Definition: color.h:62
MT_COLOR_COMPOSE_SECURITY_SIGN
@ MT_COLOR_COMPOSE_SECURITY_SIGN
Mail will be signed.
Definition: color.h:69
init.h
lib.h
MT_COLOR_ATTACHMENT
@ MT_COLOR_ATTACHMENT
MIME attachments text (entire line)
Definition: color.h:61
MT_COLOR_SIDEBAR_ORDINARY
@ MT_COLOR_SIDEBAR_ORDINARY
Mailbox with no new or flagged messages.
Definition: color.h:89
NT_COLOR
@ NT_COLOR
Colour has changed, ColorId, EventColor.
Definition: notify_type.h:35
color_line_list_clear
static void color_line_list_clear(struct Colors *c, struct ColorLineList *list)
Clear a list of colours.
Definition: color.c:320
Colors::index_flags_list
struct ColorLineList index_flags_list
List of colours applied to the flags in the index.
Definition: color.h:137
lib.h
ComposeFields
const struct Mapping ComposeFields[]
Definition: color.c:146
Mailbox::msg_count
int msg_count
Total number of messages.
Definition: mailbox.h:91
parse_color_pair
static enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s, uint32_t *fg, uint32_t *bg, int *attr, struct Buffer *err)
Parse a pair of colours - Implements parser_callback_t.
Definition: color.c:1053
MT_COLOR_OPTIONS
@ MT_COLOR_OPTIONS
Options in prompt.
Definition: color.h:78
MUTT_PC_FULL_MSG
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: lib.h:65
STAILQ_INSERT_HEAD
#define STAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:380
MT_COLOR_MAX
@ MT_COLOR_MAX
Definition: color.h:112
Colors::attach_list
struct ColorLineList attach_list
List of colours applied to the attachment headers.
Definition: color.h:133
Colors
Definition: color.h:129
ColorLine::pair
int pair
Colour pair index.
Definition: color.h:43
MT_COLOR_INDEX_COLLAPSED
@ MT_COLOR_INDEX_COLLAPSED
Index: number of messages in collapsed thread.
Definition: color.h:106
mutt_debug
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Fields
const struct Mapping Fields[]
Definition: color.c:99
MT_COLOR_PROMPT
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:80
EventColor
An Event that happened to a Colour.
Definition: color.h:159
MUTT_CMD_SUCCESS
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: mutt_commands.h:38
mutt_colors_free
void mutt_colors_free(struct Colors **ptr)
Free all the colours.
Definition: color.c:356
REG_COMP
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:54
Colors::notify
struct Notify * notify
Notifications system.
Definition: color.h:149
MT_COLOR_TILDE
@ MT_COLOR_TILDE
Pager: empty lines after message.
Definition: color.h:95
STAILQ_REMOVE_HEAD
#define STAILQ_REMOVE_HEAD(head, field)
Definition: queue.h:419
parse_object
static enum CommandResult parse_object(struct Buffer *buf, struct Buffer *s, enum ColorId *obj, int *ql, struct Buffer *err)
Identify a colour object.
Definition: color.c:705
MT_COLOR_INDEX_SIZE
@ MT_COLOR_INDEX_SIZE
Index: size field.
Definition: color.h:110
STAILQ_FOREACH_SAFE
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:359
Mapping::name
const char * name
Definition: mapping.h:33
MUTT_CMD_ERROR
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: mutt_commands.h:36
MT_COLOR_TREE
@ MT_COLOR_TREE
Index: tree-drawing characters.
Definition: color.h:96
MT_COLOR_INDEX_TAG
@ MT_COLOR_INDEX_TAG
Index: tag field (g, takes a pattern)
Definition: color.h:104
C_SimpleSearch
WHERE char * C_SimpleSearch
Config: Pattern to search for when search doesn't contain ~'s.
Definition: mutt_globals.h:107
MT_COLOR_PROGRESS
@ MT_COLOR_PROGRESS
Progress bar.
Definition: color.h:79
mutt_check_simple
void mutt_check_simple(struct Buffer *s, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:111
lib.h
CommandResult
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
STAILQ_REMOVE_AFTER
#define STAILQ_REMOVE_AFTER(head, elm, field)
Definition: queue.h:413
lib.h
Colors::quotes
int * quotes
Array of colours for quoted email text.
Definition: color.h:143
MUTT_CMD_WARNING
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: mutt_commands.h:37
MT_COLOR_SIDEBAR_FLAGGED
@ MT_COLOR_SIDEBAR_FLAGGED
Mailbox with flagged messages.
Definition: color.h:85
MT_COLOR_COMPOSE_SECURITY_ENCRYPT
@ MT_COLOR_COMPOSE_SECURITY_ENCRYPT
Mail will be encrypted.
Definition: color.h:67
Colors::index_list
struct ColorLineList index_list
List of default colours applied to the index.
Definition: color.h:138
ColorList::bg
uint32_t bg
Definition: color.h:123
mutt_colors_new
struct Colors * mutt_colors_new(void)
Create new colours.
Definition: color.c:374
MT_COLOR_MARKERS
@ MT_COLOR_MARKERS
Pager: markers, line continuation.
Definition: color.h:74
MT_COLOR_INDEX
@ MT_COLOR_INDEX
Index: default colour (takes a pattern)
Definition: color.h:100
ColorNames
static const struct Mapping ColorNames[]
Definition: color.c:81
Colors::index_tag_list
struct ColorLineList index_tag_list
List of colours applied to tags in the index.
Definition: color.h:140
mutt_color_alloc
int mutt_color_alloc(struct Colors *c, uint32_t fg, uint32_t bg)
Allocate a colour pair.
Definition: color.c:472
mutt_mem_malloc
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
MT_COLOR_HEADER
@ MT_COLOR_HEADER
Message headers (takes a pattern)
Definition: color.h:72
MT_COLOR_SIDEBAR_NEW
@ MT_COLOR_SIDEBAR_NEW
Mailbox with new mail.
Definition: color.h:88
ColorList::next
struct ColorList * next
Definition: color.h:126
ColorList
A set of colors.
Definition: color.h:118
MT_COLOR_INDEX_FLAGS
@ MT_COLOR_INDEX_FLAGS
Index: flags field (takes a pattern)
Definition: color.h:102
mutt_mb_is_lower
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:358
NeoMutt
Container for Accounts, Notifications.
Definition: neomutt.h:36
mutt.h
mutt_istr_startswith
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:172
COLOR_DEFAULT
#define COLOR_DEFAULT
Definition: color.c:71
notify_free
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:62
mutt_map_get_value
int mutt_map_get_value(const char *name, const struct Mapping *map)
Lookup the constant for a string.
Definition: mapping.c:85
parse_color_name
static enum CommandResult parse_color_name(const char *s, uint32_t *col, int *attr, bool is_fg, struct Buffer *err)
Parse a colour name.
Definition: color.c:603
context.h
mutt_parse_color
enum CommandResult mutt_parse_color(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'color' command - Implements Command::parse()
Definition: color.c:1346
ColorLine::match
int match
Substring to match, 0 for old behaviour.
Definition: color.h:38
ColorLine
A regular expression and a color to highlight a line.
Definition: color.h:35
MT_COLOR_INDEX_SUBJECT
@ MT_COLOR_INDEX_SUBJECT
Index: subject field (takes a pattern)
Definition: color.h:103
ColorLine::color_pattern
struct PatternList * color_pattern
Compiled pattern to speed up index color calculation.
Definition: color.h:40
notify_set_parent
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:82
color.h
ColorLine::pattern
char * pattern
Pattern to match.
Definition: color.h:39
MT_COLOR_SIDEBAR_DIVIDER
@ MT_COLOR_SIDEBAR_DIVIDER
Line dividing sidebar from the index/pager.
Definition: color.h:84
MT_COLOR_SIDEBAR_SPOOLFILE
@ MT_COLOR_SIDEBAR_SPOOLFILE
$spool_file (Spool mailbox)
Definition: color.h:90
mutt_commands.h
Colors::defs
int * defs
Array of all fixed colours, see enum ColorId.
Definition: color.h:131
ColorLine::fg
uint32_t fg
Foreground colour.
Definition: color.h:41
mutt_curses.h
mutt_str_atoui
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:282
Buffer::data
char * data
Pointer to data.
Definition: buffer.h:35
Email
The envelope/body of an email.
Definition: email.h:37
Colors::index_subject_list
struct ColorLineList index_subject_list
List of colours applied to the subject in the index.
Definition: color.h:139
MT_COLOR_COMPOSE_SECURITY_BOTH
@ MT_COLOR_COMPOSE_SECURITY_BOTH
Mail will be encrypted and signed.
Definition: color.h:66
Colors::status_list
struct ColorLineList status_list
List of colours applied to the status bar.
Definition: color.h:141
mutt_str_startswith
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
ColorList::index
short index
Definition: color.h:124
mutt_buffer_printf
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
COLOR_UNSET
#define COLOR_UNSET
Definition: color.c:65
mutt_buffer_make
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
parse_color
static enum CommandResult parse_color(struct Colors *c, struct Buffer *buf, struct Buffer *s, struct Buffer *err, parser_callback_t callback, bool dry_run, bool color)
Parse a 'color' command.
Definition: color.c:1172
mutt_buffer_strcpy
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
MT_COLOR_SIDEBAR_INDICATOR
@ MT_COLOR_SIDEBAR_INDICATOR
Current open mailbox.
Definition: color.h:87
MT_COLOR_SIDEBAR_UNREAD
@ MT_COLOR_SIDEBAR_UNREAD
Mailbox with unread mail.
Definition: color.h:91
color_list_free
static void color_list_free(struct ColorList **ptr)
Free the list of curses colours.
Definition: color.c:227
quotes_free
static void quotes_free(struct Colors *c)
Free the quoted-email colours.
Definition: color.c:197
quotes_init
static void quotes_init(struct Colors *c)
Initialise the quoted-email colours.
Definition: color.c:206
Email::pair
int pair
Color-pair to use when displaying in the index.
Definition: email.h:80
mutt_str_copy
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716