📄 color.c
字号:
/* * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mutt_curses.h"#include "mapping.h"#include <string.h>#include <stdlib.h>#include <ctype.h>/* globals */int *ColorQuote;int ColorQuoteUsed;int ColorDefs[MT_COLOR_MAX];COLOR_LINE *ColorHdrList = NULL;COLOR_LINE *ColorBodyList = NULL;COLOR_LINE *ColorIndexList = NULL;/* local to this file */static int ColorQuoteSize;#ifdef HAVE_COLOR#define COLOR_DEFAULT (-2)typedef struct color_list{ short fg; short bg; short index; short count; struct color_list *next;} COLOR_LIST;static COLOR_LIST *ColorList = NULL;static int UserColors = 0;static struct mapping_t Colors[] ={ { "black", COLOR_BLACK }, { "blue", COLOR_BLUE }, { "cyan", COLOR_CYAN }, { "green", COLOR_GREEN }, { "magenta", COLOR_MAGENTA }, { "red", COLOR_RED }, { "white", COLOR_WHITE }, { "yellow", COLOR_YELLOW },#if defined (USE_SLANG_CURSES) || defined (HAVE_USE_DEFAULT_COLORS) { "default", COLOR_DEFAULT },#endif { 0, 0 }};#endif /* HAVE_COLOR */static struct mapping_t Fields[] ={ { "hdrdefault", MT_COLOR_HDEFAULT }, { "quoted", MT_COLOR_QUOTED }, { "signature", MT_COLOR_SIGNATURE }, { "indicator", MT_COLOR_INDICATOR }, { "status", MT_COLOR_STATUS }, { "tree", MT_COLOR_TREE }, { "error", MT_COLOR_ERROR }, { "normal", MT_COLOR_NORMAL }, { "tilde", MT_COLOR_TILDE }, { "markers", MT_COLOR_MARKERS }, { "header", MT_COLOR_HEADER }, { "body", MT_COLOR_BODY }, { "message", MT_COLOR_MESSAGE }, { "attachment", MT_COLOR_ATTACHMENT }, { "search", MT_COLOR_SEARCH }, { "bold", MT_COLOR_BOLD }, { "underline", MT_COLOR_UNDERLINE }, { "index", MT_COLOR_INDEX }, { NULL, 0 }};#define COLOR_QUOTE_INIT 8static COLOR_LINE *mutt_new_color_line (void){ COLOR_LINE *p = safe_calloc (1, sizeof (COLOR_LINE)); p->fg = p->bg = -1; return (p);}static void mutt_free_color_line(COLOR_LINE **l, int free_colors){ COLOR_LINE *tmp; if(!l || !*l) return; tmp = *l;#ifdef HAVE_COLOR if(free_colors && tmp->fg != -1 && tmp->bg != -1) mutt_free_color(tmp->fg, tmp->bg);#endif /* we should really introduce a container * type for regular expressions. */ regfree(&tmp->rx); mutt_pattern_free(&tmp->color_pattern); FREE (&tmp->pattern); FREE (l); /* __FREE_CHECKED__ */}void ci_start_color (void){ memset (ColorDefs, A_NORMAL, sizeof (int) * MT_COLOR_MAX); ColorQuote = (int *) safe_malloc (COLOR_QUOTE_INIT * sizeof (int)); memset (ColorQuote, A_NORMAL, sizeof (int) * COLOR_QUOTE_INIT); ColorQuoteSize = COLOR_QUOTE_INIT; ColorQuoteUsed = 0; /* set some defaults */ ColorDefs[MT_COLOR_STATUS] = A_REVERSE; ColorDefs[MT_COLOR_INDICATOR] = A_REVERSE; ColorDefs[MT_COLOR_SEARCH] = A_REVERSE; ColorDefs[MT_COLOR_MARKERS] = A_REVERSE; /* special meaning: toggle the relevant attribute */ ColorDefs[MT_COLOR_BOLD] = 0; ColorDefs[MT_COLOR_UNDERLINE] = 0;#ifdef HAVE_COLOR start_color ();#endif}#ifdef HAVE_COLOR#ifdef USE_SLANG_CURSESstatic char *get_color_name (char *dest, size_t destlen, int val){ static char * missing[3] = {"brown", "lightgray", "default"}; int i; switch (val) { case COLOR_YELLOW: strfcpy (dest, missing[0], destlen); return dest; case COLOR_WHITE: strfcpy (dest, missing[1], destlen); return dest; case COLOR_DEFAULT: strfcpy (dest, missing[2], destlen); return dest; } for (i = 0; Colors[i].name; i++) { if (Colors[i].value == val) { strfcpy (dest, Colors[i].name, destlen); return dest; } } /* Sigh. If we got this far, the color is of the form 'colorN' * Slang can handle this itself, so just return 'colorN' */ snprintf (dest, destlen, "color%d", val); return dest;}#endifint mutt_alloc_color (int fg, int bg){ COLOR_LIST *p = ColorList; int i; #if defined (USE_SLANG_CURSES) char fgc[SHORT_STRING], bgc[SHORT_STRING];#endif /* check to see if this color is already allocated to save space */ while (p) { if (p->fg == fg && p->bg == bg) { (p->count)++; return (COLOR_PAIR (p->index)); } p = p->next; } /* check to see if there are colors left */ if (++UserColors > COLOR_PAIRS) return (A_NORMAL); /* find the smallest available index (object) */ i = 1; FOREVER { p = ColorList; while (p) { if (p->index == i) break; p = p->next; } if (p == NULL) break; i++; } p = (COLOR_LIST *) safe_malloc (sizeof (COLOR_LIST)); p->next = ColorList; ColorList = p; p->index = i; p->count = 1; p->bg = bg; p->fg = fg;#if defined (USE_SLANG_CURSES) if (fg == COLOR_DEFAULT || bg == COLOR_DEFAULT) SLtt_set_color (i, NULL, get_color_name (fgc, sizeof (fgc), fg), get_color_name (bgc, sizeof (bgc), bg)); else#elif defined (HAVE_USE_DEFAULT_COLORS) if (fg == COLOR_DEFAULT) fg = -1; if (bg == COLOR_DEFAULT) bg = -1;#endif init_pair(i, fg, bg); dprint(1,(debugfile,"mutt_alloc_color(): Color pairs used so far: %d\n", UserColors)); return (COLOR_PAIR (p->index));}void mutt_free_color (int fg, int bg){ COLOR_LIST *p, *q; p = ColorList; while (p) { if (p->fg == fg && p->bg == bg) { (p->count)--; if (p->count > 0) return; UserColors--; dprint(1,(debugfile,"mutt_free_color(): Color pairs used so far: %d\n", UserColors)); if (p == ColorList) { ColorList = ColorList->next; FREE (&p); return; } q = ColorList; while (q) { if (q->next == p) { q->next = p->next; FREE (&p); return; } q = q->next; } /* can't get here */ } p = p->next; }}#endif /* HAVE_COLOR */#ifdef HAVE_COLORstatic intparse_color_name (const char *s, int *col, int *attr, int brite, BUFFER *err){ char *eptr; if (ascii_strncasecmp (s, "bright", 6) == 0) { *attr |= brite; s += 6; } /* allow aliases for xterm color resources */ if (ascii_strncasecmp (s, "color", 5) == 0) { s += 5; *col = strtol (s, &eptr, 10); if (!*s || *eptr || *col < 0 || (*col >= COLORS && !option(OPTNOCURSES) && has_colors())) { snprintf (err->data, err->dsize, _("%s: color not supported by term"), s); return (-1); } } else if ((*col = mutt_getvaluebyname (s, Colors)) == -1) { snprintf (err->data, err->dsize, _("%s: no such color"), s); return (-1); } return 0;}#endif/* usage: uncolor index pattern [pattern...] * unmono index pattern [pattern...] */static int _mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err, short parse_uncolor);#ifdef HAVE_COLORint mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err){ return _mutt_parse_uncolor(buf, s, data, err, 1);}#endifint mutt_parse_unmono (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err){ return _mutt_parse_uncolor(buf, s, data, err, 0);}static int _mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err, short parse_uncolor){ int object = 0, do_cache = 0; COLOR_LINE *tmp, *last = NULL; mutt_extract_token (buf, s, 0); if ((object = mutt_getvaluebyname (buf->data, Fields)) == -1) { snprintf (err->data, err->dsize, _("%s: no such object"), buf->data); return (-1); } if (mutt_strncmp (buf->data, "index", 5) != 0) { snprintf (err->data, err->dsize, _("%s: command valid only for index object"), parse_uncolor ? "uncolor" : "unmono"); return (-1); } if (!MoreArgs (s)) { snprintf (err->data, err->dsize, _("%s: too few arguments"), parse_uncolor ? "uncolor" : "unmono"); return (-1); } if(#ifdef HAVE_COLOR /* we're running without curses */ option (OPTNOCURSES) || /* we're parsing an uncolor command, and have no colors */ (parse_uncolor && !has_colors()) /* we're parsing an unmono command, and have colors */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -