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