2 * Copyright notice from original mutt:
3 * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
5 * This file is part of mutt-ng, see http://www.muttng.org/.
6 * It's licensed under the GNU General Public License,
7 * please see the file GPL in the top level source directory.
10 #include <lib-ui/lib-ui.h>
18 int ColorDefs[MT_COLOR_MAX];
19 COLOR_LINE *ColorHdrList = NULL;
20 COLOR_LINE *ColorBodyList = NULL;
21 COLOR_LINE *ColorIndexList = NULL;
23 /* local to this file */
24 static int ColorQuoteSize;
26 #define COLOR_DEFAULT (-2)
28 typedef struct color_list {
33 struct color_list *next;
36 static struct mapping_t Colors[] = {
37 {"black", COLOR_BLACK},
40 {"green", COLOR_GREEN},
41 {"magenta", COLOR_MAGENTA},
43 {"white", COLOR_WHITE},
44 {"yellow", COLOR_YELLOW},
45 {"default", COLOR_DEFAULT},
49 static struct mapping_t Fields[] = {
50 {"hdrdefault", MT_COLOR_HDEFAULT},
51 {"quoted", MT_COLOR_QUOTED},
52 {"signature", MT_COLOR_SIGNATURE},
53 {"indicator", MT_COLOR_INDICATOR},
54 {"status", MT_COLOR_STATUS},
55 {"tree", MT_COLOR_TREE},
56 {"error", MT_COLOR_ERROR},
57 {"normal", MT_COLOR_NORMAL},
58 {"tilde", MT_COLOR_TILDE},
59 {"markers", MT_COLOR_MARKERS},
60 {"header", MT_COLOR_HEADER},
61 {"body", MT_COLOR_BODY},
62 {"message", MT_COLOR_MESSAGE},
63 {"attachment", MT_COLOR_ATTACHMENT},
64 {"search", MT_COLOR_SEARCH},
65 {"bold", MT_COLOR_BOLD},
66 {"underline", MT_COLOR_UNDERLINE},
67 {"index", MT_COLOR_INDEX},
68 {"sidebar_new", MT_COLOR_NEW},
69 {"sidebar", MT_COLOR_SIDEBAR},
70 {"sidebar_flagged", MT_COLOR_FLAGGED},
74 #define COLOR_QUOTE_INIT 8
76 static COLOR_LINE *mutt_new_color_line (void)
78 COLOR_LINE *p = p_new(COLOR_LINE, 1);
85 static void mutt_free_color_line(COLOR_LINE ** l)
93 /* we should really use the container type for regular expressions. */
95 pattern_list_wipe(&tmp->color_pattern);
96 p_delete(&tmp->pattern);
100 void ci_start_color (void)
102 memset(ColorDefs, A_NORMAL, sizeof(int) * MT_COLOR_MAX);
103 ColorQuote = p_new(int, COLOR_QUOTE_INIT);
104 memset(ColorQuote, A_NORMAL, sizeof(int) * COLOR_QUOTE_INIT);
105 ColorQuoteSize = COLOR_QUOTE_INIT;
108 /* set some defaults */
109 ColorDefs[MT_COLOR_STATUS] = A_REVERSE;
110 ColorDefs[MT_COLOR_INDICATOR] = A_REVERSE;
111 ColorDefs[MT_COLOR_SEARCH] = A_REVERSE;
112 ColorDefs[MT_COLOR_MARKERS] = A_REVERSE;
113 /* special meaning: toggle the relevant attribute */
114 ColorDefs[MT_COLOR_BOLD] = 0;
115 ColorDefs[MT_COLOR_UNDERLINE] = 0;
119 parse_color_name (const char *s, int *col, int *attr, int brite, BUFFER * err)
121 if (m_strncasecmp(s, "bright", 6) == 0) {
126 if ((*col = mutt_getvaluebyname (s, Colors)) == -1) {
127 snprintf (err->data, err->dsize, _("%s: no such color"), s);
134 /* usage: uncolor index pattern [pattern...] */
135 int mutt_parse_uncolor(BUFFER *buf, BUFFER *s, unsigned long data, BUFFER
138 int object = 0, do_cache = 0;
139 COLOR_LINE *tmp, *last = NULL;
141 mutt_extract_token (buf, s, 0);
143 if ((object = mutt_getvaluebyname (buf->data, Fields)) == -1) {
144 snprintf (err->data, err->dsize, _("%s: no such object"), buf->data);
148 if (m_strncmp(buf->data, "index", 5) != 0) {
149 snprintf (err->data, err->dsize,
150 _("%s: command valid only for index object"), "uncolor");
155 snprintf (err->data, err->dsize, _("%s: too few arguments"), "uncolor");
159 if (option(OPTNOCURSES)) {
160 /* just eat the command, but don't do anything real about it */
162 mutt_extract_token (buf, s, 0);
163 } while (MoreArgs(s));
168 mutt_extract_token (buf, s, 0);
169 if (!m_strcmp("*", buf->data)) {
170 for (tmp = ColorIndexList; tmp;) {
175 mutt_free_color_line(&last);
177 ColorIndexList = NULL;
180 for (last = NULL, tmp = ColorIndexList; tmp;
181 last = tmp, tmp = tmp->next) {
182 if (!m_strcmp(buf->data, tmp->pattern)) {
186 last->next = tmp->next;
188 ColorIndexList = tmp->next;
189 mutt_free_color_line(&tmp);
195 while (MoreArgs (s));
198 if (do_cache && !option (OPTNOCURSES)) {
201 set_option (OPTFORCEREDRAWINDEX);
202 /* force re-caching of index colors */
203 for (i = 0; Context && i < Context->msgcount; i++)
204 Context->hdrs[i]->pair = 0;
211 add_pattern (COLOR_LINE ** top, const char *s, int sensitive,
212 int fg, int bg, int attr, BUFFER * err, int is_index)
215 /* is_index used to store compiled pattern
216 * only for `index' color object
217 * when called from mutt_parse_color() */
219 COLOR_LINE *tmp = *top;
223 if (m_strcmp(s, tmp->pattern) == 0)
227 if (m_strcasecmp(s, tmp->pattern) == 0)
234 if (fg != -1 && bg != -1) {
235 if (tmp->fg != fg || tmp->bg != bg) {
238 attr |= madtty_color_pair(fg, bg);
240 attr |= (tmp->pair & ~A_BOLD);
248 tmp = mutt_new_color_line ();
252 m_strcpy(buf, sizeof(buf), NONULL(s));
253 mutt_check_simple (buf, sizeof (buf), NONULL (SimpleSearch));
254 if ((tmp->color_pattern =
255 mutt_pattern_comp (buf, M_FULL_MSG, err)) == NULL) {
256 mutt_free_color_line(&tmp);
259 /* force re-caching of index colors */
260 for (i = 0; Context && i < Context->msgcount; i++)
261 Context->hdrs[i]->pair = 0;
265 REGCOMP (&tmp->rx, s,
266 (sensitive ? mutt_which_case (s) : REG_ICASE))) != 0) {
267 regerror (r, &tmp->rx, err->data, err->dsize);
268 mutt_free_color_line(&tmp);
272 tmp->pattern = m_strdup(s);
273 if (fg != -1 && bg != -1) {
276 attr |= madtty_color_pair(fg, bg);
286 parse_object (BUFFER * buf, BUFFER * s, int *o, int *ql, BUFFER * err)
292 m_strcpy(err->data, err->dsize, _("Missing arguments."));
296 mutt_extract_token (buf, s, 0);
297 if (!m_strncmp(buf->data, "quoted", 6)) {
299 *ql = strtol (buf->data + 6, &eptr, 10);
300 if (*eptr || q_level < 0) {
301 snprintf (err->data, err->dsize, _("%s: no such object"), buf->data);
308 *o = MT_COLOR_QUOTED;
310 else if ((*o = mutt_getvaluebyname (buf->data, Fields)) == -1) {
311 snprintf (err->data, err->dsize, _("%s: no such object"), buf->data);
319 parse_color_pair (BUFFER * buf, BUFFER * s, int *fg, int *bg, int *attr,
323 m_strcpy(err->data, err->dsize, _("color: too few arguments"));
327 mutt_extract_token (buf, s, 0);
329 if (parse_color_name (buf->data, fg, attr, A_BOLD, err) != 0)
333 m_strcpy(err->data, err->dsize, _("color: too few arguments"));
337 mutt_extract_token (buf, s, 0);
339 if (parse_color_name (buf->data, bg, attr, A_BLINK, err) != 0)
347 parse_attr_spec (BUFFER * buf, BUFFER * s, int *fg, int *bg, int *attr,
357 m_strcpy(err->data, err->dsize, _("mono: too few arguments"));
361 mutt_extract_token (buf, s, 0);
363 if (ascii_strcasecmp ("bold", buf->data) == 0)
365 else if (ascii_strcasecmp ("underline", buf->data) == 0)
366 *attr |= A_UNDERLINE;
367 else if (ascii_strcasecmp ("none", buf->data) == 0)
369 else if (ascii_strcasecmp ("reverse", buf->data) == 0)
371 else if (ascii_strcasecmp ("standout", buf->data) == 0)
373 else if (ascii_strcasecmp ("normal", buf->data) == 0)
374 *attr = A_NORMAL; /* needs use = instead of |= to clear other bits */
376 snprintf (err->data, err->dsize, _("%s: no such attribute"), buf->data);
384 static int fgbgattr_to_color (int fg, int bg, int attr)
386 if (fg != -1 && bg != -1)
387 return attr | madtty_color_pair(fg, bg);
392 /* usage: color <object> <fg> <bg> [ <regexp> ] */
393 int mutt_parse_color(BUFFER *buf, BUFFER *s, unsigned long i, BUFFER *err)
395 int object = 0, attr = 0, fg = 0, bg = 0, q_level = 0;
398 if (parse_object (buf, s, &object, &q_level, err) == -1)
401 if (parse_color_pair(buf, s, &fg, &bg, &attr, err) == -1)
404 /* extract a regular expression if needed */
406 if (object == MT_COLOR_HEADER || object == MT_COLOR_BODY
407 || object == MT_COLOR_INDEX) {
409 m_strcpy(err->data, err->dsize, _("too few arguments"));
413 mutt_extract_token (buf, s, 0);
417 m_strcpy(err->data, err->dsize, _("too many arguments"));
421 if (option(OPTNOCURSES))
424 /* delay use_default_colors() until needed, since it initializes things */
425 if (has_colors () && (fg == COLOR_DEFAULT || bg == COLOR_DEFAULT)
426 && use_default_colors () != OK)
428 m_strcpy(err->data, err->dsize, _("default colors not supported"));
432 if (object == MT_COLOR_HEADER)
433 r = add_pattern (&ColorHdrList, buf->data, 0, fg, bg, attr, err, 0);
434 else if (object == MT_COLOR_BODY)
435 r = add_pattern (&ColorBodyList, buf->data, 1, fg, bg, attr, err, 0);
436 else if (object == MT_COLOR_INDEX) {
437 r = add_pattern (&ColorIndexList, buf->data, 1, fg, bg, attr, err, 1);
438 set_option (OPTFORCEREDRAWINDEX);
440 else if (object == MT_COLOR_QUOTED) {
441 if (q_level >= ColorQuoteSize) {
442 p_realloc(&ColorQuote, ColorQuoteSize += 2);
443 ColorQuote[ColorQuoteSize - 2] = ColorDefs[MT_COLOR_QUOTED];
444 ColorQuote[ColorQuoteSize - 1] = ColorDefs[MT_COLOR_QUOTED];
446 if (q_level >= ColorQuoteUsed)
447 ColorQuoteUsed = q_level + 1;
449 ColorDefs[MT_COLOR_QUOTED] = fgbgattr_to_color (fg, bg, attr);
451 ColorQuote[0] = ColorDefs[MT_COLOR_QUOTED];
452 for (q_level = 1; q_level < ColorQuoteUsed; q_level++) {
453 if (ColorQuote[q_level] == A_NORMAL)
454 ColorQuote[q_level] = ColorDefs[MT_COLOR_QUOTED];
457 ColorQuote[q_level] = fgbgattr_to_color (fg, bg, attr);
460 ColorDefs[object] = fgbgattr_to_color (fg, bg, attr);
463 if (object == MT_COLOR_NORMAL)
464 BKGDSET(main_w, MT_COLOR_NORMAL);