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 static struct mapping_t Colors[] = {
29 {"black", COLOR_BLACK},
32 {"green", COLOR_GREEN},
33 {"magenta", COLOR_MAGENTA},
35 {"white", COLOR_WHITE},
36 {"yellow", COLOR_YELLOW},
37 {"default", COLOR_DEFAULT},
41 static struct mapping_t Fields[] = {
42 {"hdrdefault", MT_COLOR_HDEFAULT},
43 {"quoted", MT_COLOR_QUOTED},
44 {"signature", MT_COLOR_SIGNATURE},
45 {"indicator", MT_COLOR_INDICATOR},
46 {"status", MT_COLOR_STATUS},
47 {"tree", MT_COLOR_TREE},
48 {"error", MT_COLOR_ERROR},
49 {"normal", MT_COLOR_NORMAL},
50 {"tilde", MT_COLOR_TILDE},
51 {"markers", MT_COLOR_MARKERS},
52 {"header", MT_COLOR_HEADER},
53 {"body", MT_COLOR_BODY},
54 {"message", MT_COLOR_MESSAGE},
55 {"attachment", MT_COLOR_ATTACHMENT},
56 {"search", MT_COLOR_SEARCH},
57 {"bold", MT_COLOR_BOLD},
58 {"underline", MT_COLOR_UNDERLINE},
59 {"index", MT_COLOR_INDEX},
60 {"sidebar_new", MT_COLOR_NEW},
61 {"sidebar", MT_COLOR_SIDEBAR},
62 {"sidebar_flagged", MT_COLOR_FLAGGED},
66 #define COLOR_QUOTE_INIT 8
68 static COLOR_LINE *mutt_new_color_line (void)
70 COLOR_LINE *p = p_new(COLOR_LINE, 1);
77 static void mutt_free_color_line(COLOR_LINE ** l)
85 /* we should really use the container type for regular expressions. */
87 pattern_list_wipe(&tmp->color_pattern);
88 p_delete(&tmp->pattern);
92 void ci_start_color (void)
94 memset(ColorDefs, A_NORMAL, sizeof(int) * MT_COLOR_MAX);
95 ColorQuote = p_new(int, COLOR_QUOTE_INIT);
96 memset(ColorQuote, A_NORMAL, sizeof(int) * COLOR_QUOTE_INIT);
97 ColorQuoteSize = COLOR_QUOTE_INIT;
100 /* set some defaults */
101 ColorDefs[MT_COLOR_STATUS] = A_REVERSE;
102 ColorDefs[MT_COLOR_INDICATOR] = A_REVERSE;
103 ColorDefs[MT_COLOR_SEARCH] = A_REVERSE;
104 ColorDefs[MT_COLOR_MARKERS] = A_REVERSE;
105 /* special meaning: toggle the relevant attribute */
106 ColorDefs[MT_COLOR_BOLD] = 0;
107 ColorDefs[MT_COLOR_UNDERLINE] = 0;
111 parse_color_name (const char *s, int *col, int *attr, int brite, BUFFER * err)
113 if (m_strncasecmp(s, "bright", 6) == 0) {
118 if ((*col = mutt_getvaluebyname (s, Colors)) == -1) {
119 snprintf (err->data, err->dsize, _("%s: no such color"), s);
126 /* usage: uncolor index pattern [pattern...] */
127 int mutt_parse_uncolor(BUFFER *buf, BUFFER *s, unsigned long data, BUFFER
130 int object = 0, do_cache = 0;
131 COLOR_LINE *tmp, *last = NULL;
133 mutt_extract_token (buf, s, 0);
135 if ((object = mutt_getvaluebyname (buf->data, Fields)) == -1) {
136 snprintf (err->data, err->dsize, _("%s: no such object"), buf->data);
140 if (m_strncmp(buf->data, "index", 5) != 0) {
141 snprintf (err->data, err->dsize,
142 _("%s: command valid only for index object"), "uncolor");
147 snprintf (err->data, err->dsize, _("%s: too few arguments"), "uncolor");
151 if (option(OPTNOCURSES)) {
152 /* just eat the command, but don't do anything real about it */
154 mutt_extract_token (buf, s, 0);
155 } while (MoreArgs(s));
160 mutt_extract_token (buf, s, 0);
161 if (!m_strcmp("*", buf->data)) {
162 for (tmp = ColorIndexList; tmp;) {
167 mutt_free_color_line(&last);
169 ColorIndexList = NULL;
172 for (last = NULL, tmp = ColorIndexList; tmp;
173 last = tmp, tmp = tmp->next) {
174 if (!m_strcmp(buf->data, tmp->pattern)) {
178 last->next = tmp->next;
180 ColorIndexList = tmp->next;
181 mutt_free_color_line(&tmp);
187 while (MoreArgs (s));
190 if (do_cache && !option (OPTNOCURSES)) {
193 set_option (OPTFORCEREDRAWINDEX);
194 /* force re-caching of index colors */
195 for (i = 0; Context && i < Context->msgcount; i++)
196 Context->hdrs[i]->pair = 0;
203 add_pattern (COLOR_LINE ** top, const char *s, int sensitive,
204 int fg, int bg, int attr, BUFFER * err, int is_index)
207 /* is_index used to store compiled pattern
208 * only for `index' color object
209 * when called from mutt_parse_color() */
211 COLOR_LINE *tmp = *top;
215 if (m_strcmp(s, tmp->pattern) == 0)
219 if (m_strcasecmp(s, tmp->pattern) == 0)
226 if (fg != -1 && bg != -1) {
227 if (tmp->fg != fg || tmp->bg != bg) {
230 attr |= madtty_color_pair(fg, bg);
232 attr |= (tmp->pair & ~A_BOLD);
240 tmp = mutt_new_color_line ();
244 m_strcpy(buf, sizeof(buf), NONULL(s));
245 mutt_check_simple (buf, sizeof (buf), NONULL (SimpleSearch));
246 if ((tmp->color_pattern =
247 mutt_pattern_comp (buf, M_FULL_MSG, err)) == NULL) {
248 mutt_free_color_line(&tmp);
251 /* force re-caching of index colors */
252 for (i = 0; Context && i < Context->msgcount; i++)
253 Context->hdrs[i]->pair = 0;
257 REGCOMP (&tmp->rx, s,
258 (sensitive ? mutt_which_case (s) : REG_ICASE))) != 0) {
259 regerror (r, &tmp->rx, err->data, err->dsize);
260 mutt_free_color_line(&tmp);
264 tmp->pattern = m_strdup(s);
265 if (fg != -1 && bg != -1) {
268 attr |= madtty_color_pair(fg, bg);
278 parse_object (BUFFER * buf, BUFFER * s, int *o, int *ql, BUFFER * err)
284 m_strcpy(err->data, err->dsize, _("Missing arguments."));
288 mutt_extract_token (buf, s, 0);
289 if (!m_strncmp(buf->data, "quoted", 6)) {
291 *ql = strtol (buf->data + 6, &eptr, 10);
292 if (*eptr || q_level < 0) {
293 snprintf (err->data, err->dsize, _("%s: no such object"), buf->data);
300 *o = MT_COLOR_QUOTED;
302 else if ((*o = mutt_getvaluebyname (buf->data, Fields)) == -1) {
303 snprintf (err->data, err->dsize, _("%s: no such object"), buf->data);
311 parse_color_pair (BUFFER * buf, BUFFER * s, int *fg, int *bg, int *attr,
315 m_strcpy(err->data, err->dsize, _("color: too few arguments"));
319 mutt_extract_token (buf, s, 0);
321 if (parse_color_name (buf->data, fg, attr, A_BOLD, err) != 0)
325 m_strcpy(err->data, err->dsize, _("color: too few arguments"));
329 mutt_extract_token (buf, s, 0);
331 if (parse_color_name (buf->data, bg, attr, A_BLINK, err) != 0)
339 parse_attr_spec (BUFFER * buf, BUFFER * s, int *fg, int *bg, int *attr,
349 m_strcpy(err->data, err->dsize, _("mono: too few arguments"));
353 mutt_extract_token (buf, s, 0);
355 if (ascii_strcasecmp ("bold", buf->data) == 0)
357 else if (ascii_strcasecmp ("underline", buf->data) == 0)
358 *attr |= A_UNDERLINE;
359 else if (ascii_strcasecmp ("none", buf->data) == 0)
361 else if (ascii_strcasecmp ("reverse", buf->data) == 0)
363 else if (ascii_strcasecmp ("standout", buf->data) == 0)
365 else if (ascii_strcasecmp ("normal", buf->data) == 0)
366 *attr = A_NORMAL; /* needs use = instead of |= to clear other bits */
368 snprintf (err->data, err->dsize, _("%s: no such attribute"), buf->data);
376 static int fgbgattr_to_color (int fg, int bg, int attr)
378 if (fg != -1 && bg != -1)
379 return attr | madtty_color_pair(fg, bg);
384 /* usage: color <object> <fg> <bg> [ <regexp> ] */
385 int mutt_parse_color(BUFFER *buf, BUFFER *s, unsigned long i, BUFFER *err)
387 int object = 0, attr = 0, fg = 0, bg = 0, q_level = 0;
390 if (parse_object (buf, s, &object, &q_level, err) == -1)
393 if (parse_color_pair(buf, s, &fg, &bg, &attr, err) == -1)
396 /* extract a regular expression if needed */
398 if (object == MT_COLOR_HEADER || object == MT_COLOR_BODY
399 || object == MT_COLOR_INDEX) {
401 m_strcpy(err->data, err->dsize, _("too few arguments"));
405 mutt_extract_token (buf, s, 0);
409 m_strcpy(err->data, err->dsize, _("too many arguments"));
413 if (option(OPTNOCURSES))
416 /* delay use_default_colors() until needed, since it initializes things */
417 if (has_colors () && (fg == COLOR_DEFAULT || bg == COLOR_DEFAULT)
418 && use_default_colors () != OK)
420 m_strcpy(err->data, err->dsize, _("default colors not supported"));
424 if (object == MT_COLOR_HEADER)
425 r = add_pattern (&ColorHdrList, buf->data, 0, fg, bg, attr, err, 0);
426 else if (object == MT_COLOR_BODY)
427 r = add_pattern (&ColorBodyList, buf->data, 1, fg, bg, attr, err, 0);
428 else if (object == MT_COLOR_INDEX) {
429 r = add_pattern (&ColorIndexList, buf->data, 1, fg, bg, attr, err, 1);
430 set_option (OPTFORCEREDRAWINDEX);
432 else if (object == MT_COLOR_QUOTED) {
433 if (q_level >= ColorQuoteSize) {
434 p_realloc(&ColorQuote, ColorQuoteSize += 2);
435 ColorQuote[ColorQuoteSize - 2] = ColorDefs[MT_COLOR_QUOTED];
436 ColorQuote[ColorQuoteSize - 1] = ColorDefs[MT_COLOR_QUOTED];
438 if (q_level >= ColorQuoteUsed)
439 ColorQuoteUsed = q_level + 1;
441 ColorDefs[MT_COLOR_QUOTED] = fgbgattr_to_color (fg, bg, attr);
443 ColorQuote[0] = ColorDefs[MT_COLOR_QUOTED];
444 for (q_level = 1; q_level < ColorQuoteUsed; q_level++) {
445 if (ColorQuote[q_level] == A_NORMAL)
446 ColorQuote[q_level] = ColorDefs[MT_COLOR_QUOTED];
449 ColorQuote[q_level] = fgbgattr_to_color (fg, bg, attr);
452 ColorDefs[object] = fgbgattr_to_color (fg, bg, attr);
455 if (object == MT_COLOR_NORMAL)
456 BKGDSET(main_w, MT_COLOR_NORMAL);