NeoMutt  2021-02-05-666-ge300cd
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 "config/lib.h"
37 #include "email/lib.h"
38 #include "core/lib.h"
39 #include "mutt.h"
40 #include "color.h"
41 #include "pattern/lib.h"
42 #include "context.h"
43 #include "init.h"
44 #include "mutt_commands.h"
45 #include "mutt_curses.h"
46 #include "mutt_globals.h"
47 #include "options.h"
48 #ifdef USE_SLANG_CURSES
49 #include <assert.h>
50 #endif
51 
52 #define COLOR_UNSET UINT32_MAX
53 #define COLOR_QUOTES_MAX \
54  10
55 
56 
59 struct ColorList
60 {
61  /* TrueColor uses 24bit. Use fixed-width integer type to make sure it fits.
62  * Use the upper 8 bits to store flags. */
63  uint32_t fg;
64  uint32_t bg;
65  short index;
66  short count;
67  struct ColorList *next;
68 };
69 
73 static struct
74 {
76 
77  /* These are lazily initialized, so make sure to always refer to them using
78  * the mutt_color_<object>() wrappers. */
79  struct ColorLineList attach_list;
80  struct ColorLineList body_list;
81  struct ColorLineList hdr_list;
82  struct ColorLineList index_author_list;
83  struct ColorLineList index_flags_list;
84  struct ColorLineList index_list;
85  struct ColorLineList index_subject_list;
86  struct ColorLineList index_tag_list;
87  struct ColorLineList status_list;
88 
91 
94 
95  struct Notify *notify;
96 } Colors;
97 
103 static struct ColorLineList *get_color_line_list(struct ColorLineList *cll)
104 {
105  if (cll->stqh_last == NULL)
106  {
107  STAILQ_INIT(cll);
108  }
109  return cll;
110 }
111 
123 typedef int (*parser_callback_t)(struct Buffer *buf, struct Buffer *s, uint32_t *fg,
124  uint32_t *bg, int *attr, struct Buffer *err);
125 
126 #ifdef HAVE_COLOR
127 
128 #define COLOR_DEFAULT (-2)
129 
130 /*
131  * Flags for the high 8bits of the color value.
132  *
133  * Note that no flag means it's a palette color.
134  */
135 #define RGB24 (1U << 24)
136 
137 // clang-format off
138 static const struct Mapping ColorNames[] = {
139  { "black", COLOR_BLACK },
140  { "blue", COLOR_BLUE },
141  { "cyan", COLOR_CYAN },
142  { "green", COLOR_GREEN },
143  { "magenta", COLOR_MAGENTA },
144  { "red", COLOR_RED },
145  { "white", COLOR_WHITE },
146  { "yellow", COLOR_YELLOW },
147 #if defined(USE_SLANG_CURSES) || defined(HAVE_USE_DEFAULT_COLORS)
148  { "default", COLOR_DEFAULT },
149 #endif
150  { 0, 0 },
151 };
152 // clang-format on
153 #endif /* HAVE_COLOR */
154 
155 // clang-format off
156 const struct Mapping ColorFields[] = {
157  { "attachment", MT_COLOR_ATTACHMENT },
158  { "attach_headers", MT_COLOR_ATTACH_HEADERS },
159  { "body", MT_COLOR_BODY },
160  { "bold", MT_COLOR_BOLD },
161  { "error", MT_COLOR_ERROR },
162  { "hdrdefault", MT_COLOR_HDRDEFAULT },
163  { "header", MT_COLOR_HEADER },
164  { "index", MT_COLOR_INDEX },
165  { "index_author", MT_COLOR_INDEX_AUTHOR },
166  { "index_collapsed", MT_COLOR_INDEX_COLLAPSED },
167  { "index_date", MT_COLOR_INDEX_DATE },
168  { "index_flags", MT_COLOR_INDEX_FLAGS },
169  { "index_label", MT_COLOR_INDEX_LABEL },
170  { "index_number", MT_COLOR_INDEX_NUMBER },
171  { "index_size", MT_COLOR_INDEX_SIZE },
172  { "index_subject", MT_COLOR_INDEX_SUBJECT },
173  { "index_tag", MT_COLOR_INDEX_TAG },
174  { "index_tags", MT_COLOR_INDEX_TAGS },
175  { "indicator", MT_COLOR_INDICATOR },
176  { "markers", MT_COLOR_MARKERS },
177  { "message", MT_COLOR_MESSAGE },
178  { "normal", MT_COLOR_NORMAL },
179  { "options", MT_COLOR_OPTIONS },
180  { "progress", MT_COLOR_PROGRESS },
181  { "prompt", MT_COLOR_PROMPT },
182  { "quoted", MT_COLOR_QUOTED },
183  { "search", MT_COLOR_SEARCH },
184 #ifdef USE_SIDEBAR
185  { "sidebar_divider", MT_COLOR_SIDEBAR_DIVIDER },
186  { "sidebar_flagged", MT_COLOR_SIDEBAR_FLAGGED },
187  { "sidebar_highlight", MT_COLOR_SIDEBAR_HIGHLIGHT },
188  { "sidebar_indicator", MT_COLOR_SIDEBAR_INDICATOR },
189  { "sidebar_new", MT_COLOR_SIDEBAR_NEW },
190  { "sidebar_ordinary", MT_COLOR_SIDEBAR_ORDINARY },
191  { "sidebar_spool_file", MT_COLOR_SIDEBAR_SPOOLFILE },
192  { "sidebar_unread", MT_COLOR_SIDEBAR_UNREAD },
193 #endif
194  { "signature", MT_COLOR_SIGNATURE },
195  { "status", MT_COLOR_STATUS },
196  { "tilde", MT_COLOR_TILDE },
197  { "tree", MT_COLOR_TREE },
198  { "underline", MT_COLOR_UNDERLINE },
199  { "warning", MT_COLOR_WARNING },
200  { NULL, 0 },
201 };
202 
203 const struct Mapping ComposeColorFields[] = {
204  { "header", MT_COLOR_COMPOSE_HEADER },
205  { "security_encrypt", MT_COLOR_COMPOSE_SECURITY_ENCRYPT },
206  { "security_sign", MT_COLOR_COMPOSE_SECURITY_SIGN },
207  { "security_both", MT_COLOR_COMPOSE_SECURITY_BOTH },
208  { "security_none", MT_COLOR_COMPOSE_SECURITY_NONE },
209  { NULL, 0 }
210 };
211 // clang-format off
212 
216 static void defs_init(void)
217 {
218  memset(Colors.defs, A_NORMAL, MT_COLOR_MAX * sizeof(int));
219 
220  // Set some defaults
221  Colors.defs[MT_COLOR_INDICATOR] = A_REVERSE;
222  Colors.defs[MT_COLOR_MARKERS] = A_REVERSE;
223  Colors.defs[MT_COLOR_SEARCH] = A_REVERSE;
224 #ifdef USE_SIDEBAR
225  Colors.defs[MT_COLOR_SIDEBAR_HIGHLIGHT] = A_UNDERLINE;
226 #endif
227  Colors.defs[MT_COLOR_STATUS] = A_REVERSE;
228 }
229 
233 static void defs_clear(void)
234 {
235  memset(Colors.defs, A_NORMAL, MT_COLOR_MAX * sizeof(int));
236 }
237 
241 static void quotes_init(void)
242 {
243  memset(Colors.quotes, A_NORMAL, COLOR_QUOTES_MAX * sizeof(int));
244  Colors.quotes_used = 0;
245 }
246 
250 static void quotes_clear(void)
251 {
252  memset(Colors.quotes, A_NORMAL, COLOR_QUOTES_MAX * sizeof(int));
253  Colors.quotes_used = 0;
254 }
255 
260 static void color_list_free(struct ColorList **ptr)
261 {
262  if (!ptr || !*ptr)
263  return;
264 
265  struct ColorList *cl = *ptr;
266  struct ColorList *next = NULL;
267 
268  while (cl)
269  {
270  next = cl->next;
271  FREE(&cl);
272  cl = next;
273  }
274  *ptr = NULL;
275 }
276 
284 void mutt_color_free(uint32_t fg, uint32_t bg)
285 {
286  struct ColorList *q = NULL;
287 
288  struct ColorList *p = Colors.user_colors;
289  while (p)
290  {
291  if ((p->fg == fg) && (p->bg == bg))
292  {
293  (p->count)--;
294  if (p->count > 0)
295  return;
296 
297  Colors.num_user_colors--;
298  mutt_debug(LL_DEBUG1, "Color pairs used so far: %d\n", Colors.num_user_colors);
299 
300  if (p == Colors.user_colors)
301  {
302  Colors.user_colors = Colors.user_colors->next;
303  FREE(&p);
304  return;
305  }
306  q = Colors.user_colors;
307  while (q)
308  {
309  if (q->next == p)
310  {
311  q->next = p->next;
312  FREE(&p);
313  return;
314  }
315  q = q->next;
316  }
317  /* can't get here */
318  }
319  p = p->next;
320  }
321 }
322 
328 static void color_line_free(struct ColorLine **ptr, bool free_colors)
329 {
330  if (!ptr || !*ptr)
331  return;
332 
333  struct ColorLine *cl = *ptr;
334 
335 #ifdef HAVE_COLOR
336  if (free_colors && (cl->fg != COLOR_UNSET) && (cl->bg != COLOR_UNSET))
337  mutt_color_free(cl->fg, cl->bg);
338 #endif
339 
340  regfree(&cl->regex);
342  FREE(&cl->pattern);
343  FREE(ptr);
344 }
345 
350 static void color_line_list_clear(struct ColorLineList *list)
351 {
352  struct ColorLine *np = NULL, *tmp = NULL;
353  STAILQ_FOREACH_SAFE(np, list, entries, tmp)
354  {
355  STAILQ_REMOVE(list, np, ColorLine, entries);
356  color_line_free(&np, true);
357  }
358 }
359 
363 static void colors_clear(void)
364 {
374 
375  defs_clear();
376  quotes_clear();
377 
378  color_list_free(&Colors.user_colors);
379 }
380 
385 {
386  colors_clear();
387  notify_free(&Colors.notify);
388 }
389 
394 {
395  Colors.notify = notify_new();
396 
397  quotes_init();
398  defs_init();
399 
400 #ifdef HAVE_COLOR
401  start_color();
402 #endif
403 
405 }
406 
411 static struct ColorLine *color_line_new(void)
412 {
413  struct ColorLine *cl = mutt_mem_calloc(1, sizeof(struct ColorLine));
414 
415  cl->fg = COLOR_UNSET;
416  cl->bg = COLOR_UNSET;
417 
418  return cl;
419 }
420 
421 #ifdef HAVE_COLOR
422 #ifdef USE_SLANG_CURSES
423 
430 static char *get_color_name(char *dest, size_t destlen, uint32_t val)
431 {
432  static const char *const missing[3] = { "brown", "lightgray", "default" };
433 
434  if (val & RGB24)
435  {
436  assert(snprintf(dest, destlen, "#%06X", val & 0xffffff) == 7);
437  return dest;
438  }
439 
440  switch (val)
441  {
442  case COLOR_YELLOW:
443  mutt_str_copy(dest, missing[0], destlen);
444  return dest;
445 
446  case COLOR_WHITE:
447  mutt_str_copy(dest, missing[1], destlen);
448  return dest;
449 
450  case COLOR_DEFAULT:
451  mutt_str_copy(dest, missing[2], destlen);
452  return dest;
453  }
454 
455  for (int i = 0; ColorNames[i].name; i++)
456  {
457  if (ColorNames[i].value == val)
458  {
459  mutt_str_copy(dest, ColorNames[i].name, destlen);
460  return dest;
461  }
462  }
463 
464  /* Sigh. If we got this far, the color is of the form 'colorN'
465  * Slang can handle this itself, so just return 'colorN' */
466  snprintf(dest, destlen, "color%d", val);
467 
468  return dest;
469 }
470 #endif
471 
478 int mutt_color_alloc(uint32_t fg, uint32_t bg)
479 {
480 #ifdef USE_SLANG_CURSES
481  char fgc[128], bgc[128];
482 #endif
483  struct ColorList *p = Colors.user_colors;
484 
485  /* check to see if this color is already allocated to save space */
486  while (p)
487  {
488  if ((p->fg == fg) && (p->bg == bg))
489  {
490  (p->count)++;
491  return COLOR_PAIR(p->index);
492  }
493  p = p->next;
494  }
495 
496  /* check to see if there are colors left */
497  if (++Colors.num_user_colors > COLOR_PAIRS)
498  return A_NORMAL;
499 
500  /* find the smallest available index (object) */
501  int i = 1;
502  while (true)
503  {
504  p = Colors.user_colors;
505  while (p)
506  {
507  if (p->index == i)
508  break;
509  p = p->next;
510  }
511  if (!p)
512  break;
513  i++;
514  }
515 
516  p = mutt_mem_malloc(sizeof(struct ColorList));
517  p->next = Colors.user_colors;
518  Colors.user_colors = p;
519 
520  p->index = i;
521  p->count = 1;
522  p->bg = bg;
523  p->fg = fg;
524 
525 #ifdef USE_SLANG_CURSES
526  /*
527  * If using s-lang always use SLtt_set_color which allows using truecolor
528  * values. Note that I couldn't figure out if s-lang somehow reports
529  * truecolor support.
530  */
531  SLtt_set_color(i, NULL, get_color_name(fgc, sizeof(fgc), fg),
532  get_color_name(bgc, sizeof(bgc), bg));
533 #else
534 #ifdef HAVE_USE_DEFAULT_COLORS
535  if (fg == COLOR_DEFAULT)
536  fg = COLOR_UNSET;
537  if (bg == COLOR_DEFAULT)
538  bg = COLOR_UNSET;
539 #endif
540  init_pair(i, fg, bg);
541 #endif
542 
543  mutt_debug(LL_DEBUG3, "Color pairs used so far: %d\n", Colors.num_user_colors);
544 
545  return COLOR_PAIR(p->index);
546 }
547 
556 static int mutt_lookup_color(short pair, uint32_t *fg, uint32_t *bg)
557 {
558  struct ColorList *p = Colors.user_colors;
559 
560  while (p)
561  {
562  if (COLOR_PAIR(p->index) == pair)
563  {
564  if (fg)
565  *fg = p->fg;
566  if (bg)
567  *bg = p->bg;
568  return 0;
569  }
570  p = p->next;
571  }
572  return -1;
573 }
574 
581 int mutt_color_combine(uint32_t fg_attr, uint32_t bg_attr)
582 {
583  uint32_t fg = COLOR_DEFAULT;
584  uint32_t bg = COLOR_DEFAULT;
585 
586  mutt_lookup_color(fg_attr, &fg, NULL);
587  mutt_lookup_color(bg_attr, NULL, &bg);
588 
589  if ((fg == COLOR_DEFAULT) && (bg == COLOR_DEFAULT))
590  return A_NORMAL;
591  return mutt_color_alloc(fg, bg);
592 }
593 #endif /* HAVE_COLOR */
594 
595 #ifdef HAVE_COLOR
596 
607 static enum CommandResult parse_color_name(const char *s, uint32_t *col, int *attr,
608  bool is_fg, struct Buffer *err)
609 {
610  char *eptr = NULL;
611  bool is_alert = false, is_bright = false, is_light = false;
612  int clen;
613 
614  if ((clen = mutt_istr_startswith(s, "bright")))
615  {
616  is_bright = true;
617  s += clen;
618  }
619  else if ((clen = mutt_istr_startswith(s, "alert")))
620  {
621  is_alert = true;
622  is_bright = true;
623  s += clen;
624  }
625  else if ((clen = mutt_istr_startswith(s, "light")))
626  {
627  is_light = true;
628  s += clen;
629  }
630 
631  /* allow aliases for xterm color resources */
632  if ((clen = mutt_istr_startswith(s, "color")))
633  {
634  s += clen;
635  *col = strtoul(s, &eptr, 10);
636  if ((*s == '\0') || (*eptr != '\0') || ((*col >= COLORS) && !OptNoCurses && has_colors()))
637  {
638  mutt_buffer_printf(err, _("%s: color not supported by term"), s);
639  return MUTT_CMD_ERROR;
640  }
641  }
642 #ifdef HAVE_DIRECTCOLOR
643  else if (*s == '#')
644  {
645  s += 1;
646  *col = strtoul(s, &eptr, 16);
647  if ((*s == '\0') || (*eptr != '\0') || ((*col == COLOR_UNSET) && !OptNoCurses && has_colors()))
648  {
649  snprintf(err->data, err->dsize, _("%s: color not supported by term"), s);
650  return MUTT_CMD_ERROR;
651  }
652  *col |= RGB24;
653  }
654 #endif
655  else if ((*col = mutt_map_get_value(s, ColorNames)) == -1)
656  {
657  mutt_buffer_printf(err, _("%s: no such color"), s);
658  return MUTT_CMD_WARNING;
659  }
660 
661  if (is_bright || is_light)
662  {
663  if (is_alert)
664  {
665  *attr |= A_BOLD;
666  *attr |= A_BLINK;
667  }
668  else if (is_fg)
669  {
670  if ((COLORS >= 16) && is_light)
671  {
672  if (*col <= 7)
673  {
674  /* Advance the color 0-7 by 8 to get the light version */
675  *col += 8;
676  }
677  }
678  else
679  {
680  *attr |= A_BOLD;
681  }
682  }
683  else if (!(*col & RGB24))
684  {
685  if (COLORS >= 16)
686  {
687  if (*col <= 7)
688  {
689  /* Advance the color 0-7 by 8 to get the light version */
690  *col += 8;
691  }
692  }
693  }
694  }
695 
696  return MUTT_CMD_SUCCESS;
697 }
698 #endif
699 
709 static enum CommandResult parse_object(struct Buffer *buf, struct Buffer *s,
710  enum ColorId *obj, int *ql, struct Buffer *err)
711 {
712  int rc;
713 
714  if (mutt_str_startswith(buf->data, "quoted") != 0)
715  {
716  int val = 0;
717  if (buf->data[6] != '\0')
718  {
719  rc = mutt_str_atoi(buf->data + 6, &val);
720  if ((rc != 0) || (val > COLOR_QUOTES_MAX))
721  {
722  mutt_buffer_printf(err, _("%s: no such object"), buf->data);
723  return MUTT_CMD_WARNING;
724  }
725  }
726 
727  *ql = val;
728  *obj = MT_COLOR_QUOTED;
729  return MUTT_CMD_SUCCESS;
730  }
731 
732  if (mutt_istr_equal(buf->data, "compose"))
733  {
734  if (!MoreArgs(s))
735  {
736  mutt_buffer_printf(err, _("%s: too few arguments"), "color");
737  return MUTT_CMD_WARNING;
738  }
739 
741 
742  rc = mutt_map_get_value(buf->data, ComposeColorFields);
743  if (rc == -1)
744  {
745  mutt_buffer_printf(err, _("%s: no such object"), buf->data);
746  return MUTT_CMD_WARNING;
747  }
748 
749  *obj = rc;
750  return MUTT_CMD_SUCCESS;
751  }
752 
753  rc = mutt_map_get_value(buf->data, ColorFields);
754  if (rc == -1)
755  {
756  mutt_buffer_printf(err, _("%s: no such object"), buf->data);
757  return MUTT_CMD_WARNING;
758  }
759 
760  *obj = rc;
761  return MUTT_CMD_SUCCESS;
762 }
763 
772 static bool do_uncolor(struct Buffer *buf, struct Buffer *s,
773  struct ColorLineList *cl, bool uncolor)
774 {
775  struct ColorLine *np = NULL, *prev = NULL;
776  bool rc = false;
777 
778  do
779  {
781  if (mutt_str_equal("*", buf->data))
782  {
783  rc = STAILQ_FIRST(cl);
785  return rc;
786  }
787 
788  prev = NULL;
789  STAILQ_FOREACH(np, cl, entries)
790  {
791  if (mutt_str_equal(buf->data, np->pattern))
792  {
793  rc = true;
794 
795  mutt_debug(LL_DEBUG1, "Freeing pattern \"%s\" from user_colors\n", buf->data);
796  if (prev)
797  STAILQ_REMOVE_AFTER(cl, prev, entries);
798  else
799  STAILQ_REMOVE_HEAD(cl, entries);
800  color_line_free(&np, uncolor);
801  break;
802  }
803  prev = np;
804  }
805  } while (MoreArgs(s));
806 
807  return rc;
808 }
809 
810 
816 void get_colorid_name(unsigned int color_id, struct Buffer *buf)
817 {
818  const char *name = NULL;
819 
820  if ((color_id >= MT_COLOR_COMPOSE_HEADER) && (color_id <= MT_COLOR_COMPOSE_SECURITY_SIGN))
821  {
822  name = mutt_map_get_name(color_id, ComposeColorFields);
823  if (name)
824  {
825  mutt_buffer_printf(buf, "compose %s", name);
826  return;
827  }
828  }
829 
830  name = mutt_map_get_name(color_id, ColorFields);
831  if (name)
832  mutt_buffer_printf(buf, "%s", name);
833  else
834  mutt_buffer_printf(buf, "UNKNOWN %d", color_id);
835 }
836 
849 static enum CommandResult parse_uncolor(struct Buffer *buf, struct Buffer *s,
850  struct Buffer *err, bool uncolor)
851 {
853 
854  if (mutt_str_equal(buf->data, "*"))
855  {
856  mutt_debug(LL_NOTIFY, "NT_COLOR_RESET: [ALL]\n");
857  colors_clear();
858  struct EventColor ev_c = { MT_COLOR_MAX };
859  notify_send(Colors.notify, NT_COLOR, NT_COLOR_RESET, &ev_c);
860  return MUTT_CMD_SUCCESS;
861  }
862 
863  unsigned int object = MT_COLOR_NONE;
864  int ql = 0;
865  enum CommandResult rc = parse_object(buf, s, &object, &ql, err);
866  if (rc != MUTT_CMD_SUCCESS)
867  return rc;
868 
869  if (object == -1)
870  {
871  mutt_buffer_printf(err, _("%s: no such object"), buf->data);
872  return MUTT_CMD_ERROR;
873  }
874 
875  if (object == MT_COLOR_QUOTED)
876  {
877  Colors.quotes[ql] = A_NORMAL;
878  /* fallthrough to simple case */
879  }
880 
881  if ((object != MT_COLOR_ATTACH_HEADERS) && (object != MT_COLOR_BODY) &&
882  (object != MT_COLOR_HEADER) && (object != MT_COLOR_INDEX) &&
883  (object != MT_COLOR_INDEX_AUTHOR) && (object != MT_COLOR_INDEX_FLAGS) &&
884  (object != MT_COLOR_INDEX_SUBJECT) && (object != MT_COLOR_INDEX_TAG) &&
885  (object != MT_COLOR_STATUS))
886  {
887  // Simple colours
888  Colors.defs[object] = A_NORMAL;
889 
890  get_colorid_name(object, buf);
891  mutt_debug(LL_NOTIFY, "NT_COLOR_RESET: %s\n", buf->data);
892  struct EventColor ev_c = { object };
893  notify_send(Colors.notify, NT_COLOR, NT_COLOR_RESET, &ev_c);
894  return MUTT_CMD_SUCCESS;
895  }
896 
897  if (!MoreArgs(s))
898  {
899  mutt_buffer_printf(err, _("%s: too few arguments"), uncolor ? "uncolor" : "unmono");
900  return MUTT_CMD_WARNING;
901  }
902 
903 #ifdef HAVE_COLOR
904  if (OptNoCurses || // running without curses
905  (uncolor && !has_colors()) || // parsing an uncolor command, and have no colors
906  (!uncolor && has_colors())) // parsing an unmono command, and have colors
907 #else
908  if (uncolor) // We don't even have colors compiled in
909 #endif
910  {
911  do
912  {
913  /* just eat the command, but don't do anything real about it */
915  } while (MoreArgs(s));
916 
917  return MUTT_CMD_SUCCESS;
918  }
919 
920  bool changed = false;
921  if (object == MT_COLOR_ATTACH_HEADERS)
922  changed |= do_uncolor(buf, s, mutt_color_attachments(), uncolor);
923  else if (object == MT_COLOR_BODY)
924  changed |= do_uncolor(buf, s, mutt_color_body(), uncolor);
925  else if (object == MT_COLOR_HEADER)
926  changed |= do_uncolor(buf, s, mutt_color_headers(), uncolor);
927  else if (object == MT_COLOR_INDEX)
928  changed |= do_uncolor(buf, s, mutt_color_index(), uncolor);
929  else if (object == MT_COLOR_INDEX_AUTHOR)
930  changed |= do_uncolor(buf, s, mutt_color_index_author(), uncolor);
931  else if (object == MT_COLOR_INDEX_FLAGS)
932  changed |= do_uncolor(buf, s, mutt_color_index_flags(), uncolor);
933  else if (object == MT_COLOR_INDEX_SUBJECT)
934  changed |= do_uncolor(buf, s, mutt_color_index_subject(), uncolor);
935  else if (object == MT_COLOR_INDEX_TAG)
936  changed |= do_uncolor(buf, s, mutt_color_index_tags(), uncolor);
937  else if (object == MT_COLOR_STATUS)
938  changed |= do_uncolor(buf, s, mutt_color_status_line(), uncolor);
939 
940  if (changed)
941  {
942  get_colorid_name(object, buf);
943  mutt_debug(LL_NOTIFY, "NT_COLOR_RESET: %s\n", buf->data);
944  struct EventColor ev_c = { object };
945  notify_send(Colors.notify, NT_COLOR, NT_COLOR_RESET, &ev_c);
946  }
947 
948  return MUTT_CMD_SUCCESS;
949 }
950 
951 #ifdef HAVE_COLOR
952 
955 enum CommandResult mutt_parse_uncolor(struct Buffer *buf, struct Buffer *s,
956  intptr_t data, struct Buffer *err)
957 {
958  if (OptNoCurses || !has_colors())
959  {
960  *s->dptr = '\0'; /* fake that we're done parsing */
961  return MUTT_CMD_SUCCESS;
962  }
963  return parse_uncolor(buf, s, err, true);
964 }
965 #endif
966 
970 enum CommandResult mutt_parse_unmono(struct Buffer *buf, struct Buffer *s,
971  intptr_t data, struct Buffer *err)
972 {
973  if (OptNoCurses || !has_colors())
974  {
975  *s->dptr = '\0'; /* fake that we're done parsing */
976  return MUTT_CMD_SUCCESS;
977  }
978  return parse_uncolor(buf, s, err, false);
979 }
980 
997 static enum CommandResult add_pattern(struct ColorLineList *top, const char *s,
998  bool sensitive, uint32_t fg, uint32_t bg, int attr,
999  struct Buffer *err, bool is_index, int match)
1000 {
1001  struct ColorLine *tmp = NULL;
1002 
1003  STAILQ_FOREACH(tmp, top, entries)
1004  {
1005  if ((sensitive && mutt_str_equal(s, tmp->pattern)) ||
1006  (!sensitive && mutt_istr_equal(s, tmp->pattern)))
1007  {
1008  break;
1009  }
1010  }
1011 
1012  if (tmp)
1013  {
1014 #ifdef HAVE_COLOR
1015  if ((fg != COLOR_UNSET) && (bg != COLOR_UNSET))
1016  {
1017  if ((tmp->fg != fg) || (tmp->bg != bg))
1018  {
1019  mutt_color_free(tmp->fg, tmp->bg);
1020  tmp->fg = fg;
1021  tmp->bg = bg;
1022  attr |= mutt_color_alloc(fg, bg);
1023  }
1024  else
1025  attr |= (tmp->pair & ~A_BOLD);
1026  }
1027 #endif /* HAVE_COLOR */
1028  tmp->pair = attr;
1029  }
1030  else
1031  {
1032  tmp = color_line_new();
1033  if (is_index)
1034  {
1035  struct Buffer *buf = mutt_buffer_pool_get();
1036  mutt_buffer_strcpy(buf, s);
1037  const char *const c_simple_search =
1038  cs_subset_string(NeoMutt->sub, "simple_search");
1039  mutt_check_simple(buf, NONULL(c_simple_search));
1042  if (!tmp->color_pattern)
1043  {
1044  color_line_free(&tmp, true);
1045  return MUTT_CMD_ERROR;
1046  }
1047  }
1048  else
1049  {
1050  uint16_t flags = 0;
1051  if (sensitive)
1052  flags = mutt_mb_is_lower(s) ? REG_ICASE : 0;
1053  else
1054  flags = REG_ICASE;
1055 
1056  const int r = REG_COMP(&tmp->regex, s, flags);
1057  if (r != 0)
1058  {
1059  regerror(r, &tmp->regex, err->data, err->dsize);
1060  color_line_free(&tmp, true);
1061  return MUTT_CMD_ERROR;
1062  }
1063  }
1064  tmp->pattern = mutt_str_dup(s);
1065  tmp->match = match;
1066 #ifdef HAVE_COLOR
1067  if ((fg != COLOR_UNSET) && (bg != COLOR_UNSET))
1068  {
1069  tmp->fg = fg;
1070  tmp->bg = bg;
1071  attr |= mutt_color_alloc(fg, bg);
1072  }
1073 #endif
1074  tmp->pair = attr;
1075  STAILQ_INSERT_HEAD(top, tmp, entries);
1076  }
1077 
1078  /* force re-caching of index colors */
1079  const struct Mailbox *m = ctx_mailbox(Context);
1080  if (is_index && m)
1081  {
1082  for (int i = 0; i < m->msg_count; i++)
1083  {
1084  struct Email *e = m->emails[i];
1085  if (!e)
1086  break;
1087  e->pair = 0;
1088  }
1089  }
1090 
1091  return MUTT_CMD_SUCCESS;
1092 }
1093 
1094 #ifdef HAVE_COLOR
1095 
1098 static enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s,
1099  uint32_t *fg, uint32_t *bg,
1100  int *attr, struct Buffer *err)
1101 {
1102  while (true)
1103  {
1104  if (!MoreArgs(s))
1105  {
1106  mutt_buffer_printf(err, _("%s: too few arguments"), "color");
1107  return MUTT_CMD_WARNING;
1108  }
1109 
1111 
1112  if (mutt_istr_equal("bold", buf->data))
1113  *attr |= A_BOLD;
1114  else if (mutt_istr_equal("none", buf->data))
1115  *attr = A_NORMAL; // Use '=' to clear other bits
1116  else if (mutt_istr_equal("normal", buf->data))
1117  *attr = A_NORMAL; // Use '=' to clear other bits
1118  else if (mutt_istr_equal("reverse", buf->data))
1119  *attr |= A_REVERSE;
1120  else if (mutt_istr_equal("standout", buf->data))
1121  *attr |= A_STANDOUT;
1122  else if (mutt_istr_equal("underline", buf->data))
1123  *attr |= A_UNDERLINE;
1124  else
1125  {
1126  enum CommandResult rc = parse_color_name(buf->data, fg, attr, true, err);
1127  if (rc != MUTT_CMD_SUCCESS)
1128  return rc;
1129  break;
1130  }
1131  }
1132 
1133  if (!MoreArgs(s))
1134  {
1135  mutt_buffer_printf(err, _("%s: too few arguments"), "color");
1136  return MUTT_CMD_WARNING;
1137  }
1138 
1140 
1141  return parse_color_name(buf->data, bg, attr, false, err);
1142 }
1143 #endif
1144 
1148 static enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s,
1149  uint32_t *fg, uint32_t *bg, int *attr,
1150  struct Buffer *err)
1151 {
1152  if (fg)
1153  *fg = COLOR_UNSET;
1154  if (bg)
1155  *bg = COLOR_UNSET;
1156 
1157  if (!MoreArgs(s))
1158  {
1159  mutt_buffer_printf(err, _("%s: too few arguments"), "mono");
1160  return MUTT_CMD_WARNING;
1161  }
1162 
1164 
1165  if (mutt_istr_equal("bold", buf->data))
1166  *attr |= A_BOLD;
1167  else if (mutt_istr_equal("none", buf->data))
1168  *attr = A_NORMAL; // Use '=' to clear other bits
1169  else if (mutt_istr_equal("normal", buf->data))
1170  *attr = A_NORMAL; // Use '=' to clear other bits
1171  else if (mutt_istr_equal("reverse", buf->data))
1172  *attr |= A_REVERSE;
1173  else if (mutt_istr_equal("standout", buf->data))
1174  *attr |= A_STANDOUT;
1175  else if (mutt_istr_equal("underline", buf->data))
1176  *attr |= A_UNDERLINE;
1177  else
1178  {
1179  mutt_buffer_printf(err, _("%s: no such attribute"), buf->data);
1180  return MUTT_CMD_WARNING;
1181  }
1182 
1183  return MUTT_CMD_SUCCESS;
1184 }
1185 
1193 static int fgbgattr_to_color(int fg, int bg, int attr)
1194 {
1195 #ifdef HAVE_COLOR
1196  if ((fg != COLOR_UNSET) && (bg != COLOR_UNSET))
1197  return attr | mutt_color_alloc(fg, bg);
1198 #endif
1199  return attr;
1200 }
1201 
1215 static enum CommandResult parse_color(struct Buffer *buf, struct Buffer *s,
1216  struct Buffer *err, parser_callback_t callback,
1217  bool dry_run, bool color)
1218 {
1219  int attr = 0, q_level = 0;
1220  uint32_t fg = 0, bg = 0, match = 0;
1221  enum ColorId object = MT_COLOR_NONE;
1222  enum CommandResult rc;
1223 
1224  if (!MoreArgs(s))
1225  {
1226  mutt_buffer_printf(err, _("%s: too few arguments"), "color");
1227  return MUTT_CMD_WARNING;
1228  }
1229 
1231 
1232  rc = parse_object(buf, s, &object, &q_level, err);
1233  if (rc != MUTT_CMD_SUCCESS)
1234  return rc;
1235 
1236  rc = callback(buf, s, &fg, &bg, &attr, err);
1237  if (rc != MUTT_CMD_SUCCESS)
1238  return rc;
1239 
1240  /* extract a regular expression if needed */
1241 
1242  if ((object == MT_COLOR_ATTACH_HEADERS) || (object == MT_COLOR_BODY) ||
1243  (object == MT_COLOR_HEADER) || (object == MT_COLOR_INDEX) ||
1244  (object == MT_COLOR_INDEX_AUTHOR) || (object == MT_COLOR_INDEX_FLAGS) ||
1245  (object == MT_COLOR_INDEX_SUBJECT) || (object == MT_COLOR_INDEX_TAG))
1246  {
1247  if (!MoreArgs(s))
1248  {
1249  mutt_buffer_printf(err, _("%s: too few arguments"), color ? "color" : "mono");
1250  return MUTT_CMD_WARNING;
1251  }
1252 
1254  }
1255 
1256  if (MoreArgs(s) && (object != MT_COLOR_STATUS))
1257  {
1258  mutt_buffer_printf(err, _("%s: too many arguments"), color ? "color" : "mono");
1259  return MUTT_CMD_WARNING;
1260  }
1261 
1262  if (dry_run)
1263  {
1264  *s->dptr = '\0'; /* fake that we're done parsing */
1265  return MUTT_CMD_SUCCESS;
1266  }
1267 
1268 #ifdef HAVE_COLOR
1269 #ifdef HAVE_USE_DEFAULT_COLORS
1270  if (!OptNoCurses &&
1271  has_colors()
1272  /* delay use_default_colors() until needed, since it initializes things */
1273  && ((fg == COLOR_DEFAULT) || (bg == COLOR_DEFAULT) || (object == MT_COLOR_TREE)) &&
1274  (use_default_colors() != OK))
1275  /* the case of the tree object is special, because a non-default fg color of
1276  * the tree element may be combined dynamically with the default bg color of
1277  * an index line, not necessarily defined in a rc file. */
1278  {
1279  mutt_buffer_strcpy(err, _("default colors not supported"));
1280  return MUTT_CMD_ERROR;
1281  }
1282 #endif /* HAVE_USE_DEFAULT_COLORS */
1283 #endif
1284 
1285  if (object == MT_COLOR_ATTACH_HEADERS)
1286  rc = add_pattern(mutt_color_attachments(), buf->data, true, fg, bg, attr, err, false, match);
1287  else if (object == MT_COLOR_BODY)
1288  rc = add_pattern(mutt_color_body(), buf->data, true, fg, bg, attr, err, false, match);
1289  else if (object == MT_COLOR_HEADER)
1290  rc = add_pattern(mutt_color_headers(), buf->data, false, fg, bg, attr, err, false, match);
1291  else if (object == MT_COLOR_INDEX)
1292  {
1293  rc = add_pattern(mutt_color_index(), buf->data, true, fg, bg, attr, err, true, match);
1294  }
1295  else if (object == MT_COLOR_INDEX_AUTHOR)
1296  {
1297  rc = add_pattern(mutt_color_index_author(), buf->data, true, fg, bg, attr,
1298  err, true, match);
1299  }
1300  else if (object == MT_COLOR_INDEX_FLAGS)
1301  {
1302  rc = add_pattern(mutt_color_index_flags(), buf->data, true, fg, bg, attr, err, true, match);
1303  }
1304  else if (object == MT_COLOR_INDEX_SUBJECT)
1305  {
1306  rc = add_pattern(mutt_color_index_subject(), buf->data, true, fg, bg, attr,
1307  err, true, match);
1308  }
1309  else if (object == MT_COLOR_INDEX_TAG)
1310  {
1311  rc = add_pattern(mutt_color_index_tags(), buf->data, true, fg, bg, attr, err, true, match);
1312  }
1313  else if (object == MT_COLOR_QUOTED)
1314  {
1315  if (q_level >= COLOR_QUOTES_MAX)
1316  {
1317  mutt_buffer_printf(err, _("Maximum quoting level is %d"), COLOR_QUOTES_MAX - 1);
1318  return MUTT_CMD_WARNING;
1319  }
1320 
1321  if (q_level >= Colors.quotes_used)
1322  Colors.quotes_used = q_level + 1;
1323  if (q_level == 0)
1324  {
1325  Colors.defs[MT_COLOR_QUOTED] = fgbgattr_to_color(fg, bg, attr);
1326 
1327  Colors.quotes[0] = Colors.defs[MT_COLOR_QUOTED];
1328  for (q_level = 1; q_level < Colors.quotes_used; q_level++)
1329  {
1330  if (Colors.quotes[q_level] == A_NORMAL)
1331  Colors.quotes[q_level] = Colors.defs[MT_COLOR_QUOTED];
1332  }
1333  }
1334  else
1335  {
1336  Colors.quotes[q_level] = fgbgattr_to_color(fg, bg, attr);
1337  }
1338  rc = MUTT_CMD_SUCCESS;
1339  }
1340  else if ((object == MT_COLOR_STATUS) && MoreArgs(s))
1341  {
1342  /* 'color status fg bg' can have up to 2 arguments:
1343  * 0 arguments: sets the default status color (handled below by else part)
1344  * 1 argument : colorize pattern on match
1345  * 2 arguments: colorize nth submatch of pattern */
1347 
1348  if (MoreArgs(s))
1349  {
1350  struct Buffer tmp = mutt_buffer_make(0);
1352  if (mutt_str_atoui(tmp.data, &match) < 0)
1353  {
1354  mutt_buffer_printf(err, _("%s: invalid number: %s"),
1355  color ? "color" : "mono", tmp.data);
1356  mutt_buffer_dealloc(&tmp);
1357  return MUTT_CMD_WARNING;
1358  }
1359  mutt_buffer_dealloc(&tmp);
1360  }
1361 
1362  if (MoreArgs(s))
1363  {
1364  mutt_buffer_printf(err, _("%s: too many arguments"), color ? "color" : "mono");
1365  return MUTT_CMD_WARNING;
1366  }
1367 
1368  rc = add_pattern(mutt_color_status_line(), buf->data, true, fg, bg, attr, err, false, match);
1369  }
1370  else // Remaining simple colours
1371  {
1372  Colors.defs[object] = fgbgattr_to_color(fg, bg, attr);
1373  rc = MUTT_CMD_SUCCESS;
1374  }
1375 
1376  if (rc == MUTT_CMD_SUCCESS)
1377  {
1378  get_colorid_name(object, buf);
1379  mutt_debug(LL_NOTIFY, "NT_COLOR_SET: %s\n", buf->data);
1380  struct EventColor ev_c = { object };
1381  notify_send(Colors.notify, NT_COLOR, NT_COLOR_SET, &ev_c);
1382  }
1383 
1384  return rc;
1385 }
1386 
1387 #ifdef HAVE_COLOR
1388 
1391 enum CommandResult mutt_parse_color(struct Buffer *buf, struct Buffer *s,
1392  intptr_t data, struct Buffer *err)
1393 {
1394  bool dry_run = false;
1395 
1396  if (OptNoCurses || !has_colors())
1397  dry_run = true;
1398 
1399  return parse_color(buf, s, err, parse_color_pair, dry_run, true);
1400 }
1401 #endif
1402 
1406 enum CommandResult mutt_parse_mono(struct Buffer *buf, struct Buffer *s,
1407  intptr_t data, struct Buffer *err)
1408 {
1409  bool dry_run = false;
1410 
1411 #ifdef HAVE_COLOR
1412  if (OptNoCurses || has_colors())
1413  dry_run = true;
1414 #else
1415  if (OptNoCurses)
1416  dry_run = true;
1417 #endif
1418 
1419  return parse_color(buf, s, err, parse_attr_spec, dry_run, false);
1420 }
1421 
1427 int mutt_color(enum ColorId id)
1428 {
1429  return Colors.defs[id];
1430 }
1431 
1436 struct ColorLineList *mutt_color_status_line(void)
1437 {
1438  return get_color_line_list(&Colors.status_list);
1439 }
1440 
1445 struct ColorLineList *mutt_color_index(void)
1446 {
1447  return get_color_line_list(&Colors.index_list);
1448 }
1449 
1454 struct ColorLineList *mutt_color_headers(void)
1455 {
1456  return get_color_line_list(&Colors.hdr_list);
1457 }
1458 
1463 struct ColorLineList *mutt_color_body(void)
1464 {
1465  return get_color_line_list(&Colors.body_list);
1466 }
1467 
1472 struct ColorLineList *mutt_color_attachments(void)
1473 {
1474  return get_color_line_list(&Colors.attach_list);
1475 }
1476 
1481 struct ColorLineList *mutt_color_index_author(void)
1482 {
1483  return get_color_line_list(&Colors.index_author_list);
1484 }
1485 
1490 struct ColorLineList *mutt_color_index_flags(void)
1491 {
1492  return get_color_line_list(&Colors.index_flags_list);
1493 }
1494 
1499 struct ColorLineList *mutt_color_index_subject(void)
1500 {
1501  return get_color_line_list(&Colors.index_subject_list);
1502 }
1503 
1508 struct ColorLineList *mutt_color_index_tags(void)
1509 {
1510  return get_color_line_list(&Colors.index_tag_list);
1511 }
1512 
1519 {
1520  const int used = Colors.quotes_used;
1521  if (used == 0)
1522  return 0;
1523  return Colors.quotes[q % used];
1524 }
1525 
1531 {
1532  return Colors.quotes_used;
1533 }
1534 
1541 {
1542  notify_observer_add(Colors.notify, NT_COLOR, callback, global_data);
1543 }
1544 
1551 {
1552  notify_observer_remove(Colors.notify, callback, global_data);
1553 }
1554 
1560 bool mutt_color_is_header(enum ColorId color_id)
1561 {
1562  return (color_id == MT_COLOR_HEADER) || (color_id == MT_COLOR_HDRDEFAULT);
1563 }
Mail will be encrypted.
Definition: color.h:48
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
int defs[MT_COLOR_MAX]
Array of all fixed colours, see enum ColorId.
Definition: color.c:75
MIME attachment test (takes a pattern)
Definition: color.h:43
The "current" mailbox.
Definition: context.h:37
#define COLOR_UNSET
Definition: color.c:52
Bold text.
Definition: color.h:45
void mutt_colors_init(void)
Initialize colours.
Definition: color.c:393
Index: index number.
Definition: color.h:90
Header default colour.
Definition: color.h:52
Underlined text.
Definition: color.h:78
Progress bar.
Definition: color.h:60
#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:402
Define wrapper functions around Curses/Slang.
int msg_count
Total number of messages.
Definition: mailbox.h:91
static enum CommandResult parse_uncolor(struct Buffer *buf, struct Buffer *s, struct Buffer *err, bool uncolor)
Parse an &#39;uncolor&#39; command.
Definition: color.c:849
#define COLOR_DEFAULT
Definition: color.c:128
int mutt_color_alloc(uint32_t fg, uint32_t bg)
Allocate a colour pair.
Definition: color.c:478
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:252
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:92
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
Config/command parsing.
struct Mailbox * ctx_mailbox(struct Context *ctx)
wrapper to get the mailbox in a Context, or NULL
Definition: context.c:444
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
Log of notifications.
Definition: logging.h:45
Informational message.
Definition: color.h:56
Structs that make up an email.
An Event that happened to a Colour.
Definition: color.h:122
int quotes[COLOR_QUOTES_MAX]
Array of colours for quoted email text.
Definition: color.c:89
The "currently-open" mailbox.
struct ColorLineList index_subject_list
List of colours applied to the subject in the index.
Definition: color.c:85
bool mutt_color_is_header(enum ColorId color_id)
Colour is for an Email header.
Definition: color.c:1560
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:955
Pager: highlight body of message (takes a pattern)
Definition: color.h:44
struct ColorLineList * mutt_color_index_subject(void)
Return the ColorLineList for subject in the index.
Definition: color.c:1499
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:73
Mailbox with no new or flagged messages.
Definition: color.h:70
static void defs_init(void)
Initialise the simple colour definitions.
Definition: color.c:216
struct ColorLineList * mutt_color_index_flags(void)
Return the ColorLineList for flags in the index.
Definition: color.c:1490
struct Notify * notify
Notifications: ColorId, EventColor.
Definition: color.c:95
struct PatternList * color_pattern
Compiled pattern to speed up index color calculation.
Definition: color.h:104
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
struct ColorLineList * mutt_color_index(void)
Return the ColorLineList for the index.
Definition: color.c:1445
char * pattern
Pattern to match.
Definition: color.h:103
int pair
Colour pair index.
Definition: color.h:107
String manipulation buffer.
Definition: buffer.h:33
struct ColorLineList * mutt_color_index_tags(void)
Return the ColorLineList for tags in the index.
Definition: color.c:1508
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:65
#define _(a)
Definition: message.h:28
static struct ColorLine * color_line_new(void)
Create a new ColorLine.
Definition: color.c:411
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:54
Pager: signature lines.
Definition: color.h:74
#define COLOR_QUOTES_MAX
Ten colours, quoted0..quoted9 (quoted and quoted0 are equivalent)
Definition: color.c:53
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:47
Select cursor.
Definition: color.h:67
#define STAILQ_REMOVE_HEAD(head, field)
Definition: queue.h:422
void mutt_check_simple(struct Buffer *s, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:113
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:135
Pager: quoted text.
Definition: color.h:62
static void quotes_clear(void)
Reset the quoted-email colours.
Definition: color.c:250
Index: number of messages in collapsed thread.
Definition: color.h:87
short count
Definition: color.c:66
int num_user_colors
Definition: color.c:93
Container for Accounts, Notifications.
Definition: neomutt.h:36
Mailbox with new mail.
Definition: color.h:69
Current open mailbox.
Definition: color.h:68
Convenience wrapper for the config headers.
void mutt_color_observer_remove(observer_t callback, void *global_data)
Remove an observer.
Definition: color.c:1550
int match
Substring to match, 0 for old behaviour.
Definition: color.h:102
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:123
struct ColorLineList status_list
List of colours applied to the status bar.
Definition: color.c:87
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
size_t dsize
Length of data.
Definition: buffer.h:37
Index: author field (takes a pattern)
Definition: color.h:82
#define MoreArgs(buf)
Definition: buffer.h:40
short index
Definition: color.c:65
static int mutt_lookup_color(short pair, uint32_t *fg, uint32_t *bg)
Get the colours from a colour pair.
Definition: color.c:556
Pager: empty lines after message.
Definition: color.h:76
int(* observer_t)(struct NotifyCallback *nc)
Prototype for a notification callback function.
Definition: observer.h:58
Many unsorted constants and some structs.
struct ColorLineList index_tag_list
List of colours applied to tags in the index.
Definition: color.c:86
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:709
Message headers (takes a pattern)
Definition: color.h:53
#define STAILQ_INIT(head)
Definition: queue.h:372
Index: tag field (g, takes a pattern)
Definition: color.h:85
Convenience wrapper for the core headers.
ColorId
List of all colored objects.
Definition: color.h:39
uint32_t bg
Definition: color.c:64
struct ColorLineList index_list
List of default colours applied to the index.
Definition: color.c:84
static enum CommandResult add_pattern(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:997
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:77
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:1148
static void color_line_free(struct ColorLine **ptr, bool free_colors)
Free a ColorLine.
Definition: color.c:328
Pager: markers, line continuation.
Definition: color.h:55
struct Menu * menu
Needed for pattern compilation.
Definition: context.h:45
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:189
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
struct ColorList * user_colors
Definition: color.c:92
int mutt_color_quote(int q)
Return the color of a quote, cycling through the used quotes.
Definition: color.c:1518
Plain text.
Definition: color.h:58
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
struct ColorLineList * mutt_color_attachments(void)
Return the ColorLineList for the attachments.
Definition: color.c:1472
struct PatternList * mutt_pattern_comp(struct Mailbox *m, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:1092
Color has been set.
Definition: color.h:136
uint32_t fg
Foreground colour.
Definition: color.h:105
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:60
Index: date field.
Definition: color.h:88
Colour has changed, NotifyColor, EventColor.
Definition: notify_type.h:39
struct ColorLineList * mutt_color_index_author(void)
Return the ColorLineList for author in the index.
Definition: color.c:1481
struct ColorList * next
Definition: color.c:67
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
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:1391
Index: size field.
Definition: color.h:91
Status bar (takes a pattern)
Definition: color.h:75
A mailbox.
Definition: mailbox.h:81
uint32_t bg
Background colour.
Definition: color.h:106
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:395
Header labels, e.g. From:
Definition: color.h:46
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 attach_list
List of colours applied to the attachment headers.
Definition: color.c:79
struct ColorLineList index_author_list
List of colours applied to the author in the index.
Definition: color.c:82
Match patterns to emails.
char * data
Pointer to data.
Definition: buffer.h:35
Color has been reset/removed.
Definition: color.h:137
uint32_t fg
Definition: color.c:63
Selected item in list.
Definition: color.h:54
Definitions of NeoMutt commands.
struct ColorLineList hdr_list
List of colours applied to the email headers.
Definition: color.c:81
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Mail will be signed.
Definition: color.h:50
static void colors_clear(void)
Reset all the colours.
Definition: color.c:363
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:383
static int fgbgattr_to_color(int fg, int bg, int attr)
Convert a foreground, background, attribute triplet into a colour.
Definition: color.c:1193
Notification API.
Definition: notify.c:50
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
struct ColorLineList body_list
List of colours applied to the email body.
Definition: color.c:80
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
struct ColorLineList * mutt_color_body(void)
Return the ColorLineList for the body.
Definition: color.c:1463
static void * global_data
Original opaque data in fallback implementation.
Definition: qsort_r.c:41
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
int mutt_color(enum ColorId id)
Return the color of an object.
Definition: color.c:1427
Color and attribute parsing.
void mutt_colors_cleanup(void)
Cleanup all the colours.
Definition: color.c:384
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
regex_t regex
Compiled regex.
Definition: color.h:101
Mail will be encrypted and signed.
Definition: color.h:47
Index: label field.
Definition: color.h:89
static enum CommandResult parse_color(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:1215
Success: Command worked.
Definition: mutt_commands.h:38
Index: subject field (takes a pattern)
Definition: color.h:84
Error message.
Definition: color.h:51
Log at debug level 1.
Definition: logging.h:40
Warning: Help given to the user.
Definition: mutt_commands.h:37
int mutt_color_quotes_used(void)
Return the number of used quotes.
Definition: color.c:1530
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:749
static void defs_clear(void)
Reset the simple colour definitions.
Definition: color.c:233
struct ColorLineList * mutt_color_status_line(void)
Return the ColorLineList for the status_line.
Definition: color.c:1436
MIME attachments text (entire line)
Definition: color.h:42
struct ColorLineList index_flags_list
List of colours applied to the flags in the index.
Definition: color.c:83
static bool do_uncolor(struct Buffer *buf, struct Buffer *s, struct ColorLineList *cl, bool uncolor)
Parse the &#39;uncolor&#39; or &#39;unmono&#39; command.
Definition: color.c:772
A set of colors.
Definition: color.c:59
#define FREE(x)
Definition: memory.h:40
Mailbox with unread mail.
Definition: color.h:72
Mapping between user-readable string and a constant.
Definition: mapping.h:31
Pager: search matches.
Definition: color.h:63
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:228
static void quotes_init(void)
Initialise the quoted-email colours.
Definition: color.c:241
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:93
Mail will not be encrypted or signed.
Definition: color.h:49
Options in prompt.
Definition: color.h:59
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
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:607
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:1098
const char * name
Definition: mapping.h:33
Index: default colour (takes a pattern)
Definition: color.h:81
void mutt_color_free(uint32_t fg, uint32_t bg)
Free a colour.
Definition: color.c:284
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1038
int mutt_color_combine(uint32_t fg_attr, uint32_t bg_attr)
Combine two colours.
Definition: color.c:581
static struct ColorLineList * get_color_line_list(struct ColorLineList *cll)
Sanitize and return a ColorLineList.
Definition: color.c:103
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: lib.h:61
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:970
Convenience wrapper for the library headers.
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:1406
void get_colorid_name(unsigned int color_id, struct Buffer *buf)
Get the name of a color id.
Definition: color.c:816
struct ColorLineList * mutt_color_headers(void)
Return the ColorLineList for headers.
Definition: color.c:1454
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:357
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_REMOVE_AFTER(head, elm, field)
Definition: queue.h:416
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:61
Mailbox with flagged messages.
Definition: color.h:66
void mutt_color_observer_add(observer_t callback, void *global_data)
Add an observer.
Definition: color.c:1540
Warning messages.
Definition: color.h:79
Index: flags field (takes a pattern)
Definition: color.h:83
A regular expression and a color to highlight a line.
Definition: color.h:99
$spool_file (Spool mailbox)
Definition: color.h:71
static void color_line_list_clear(struct ColorLineList *list)
Clear a list of colours.
Definition: color.c:350
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:66
static struct @2 Colors
Wrapper for all the colours.
int quotes_used
Number of colours for quoted email text.
Definition: color.c:90
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:260
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171