From d5757409c13ec0d80171ccc3e0a01bb333c79507 Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Mon, 9 Oct 2023 14:12:32 +0100 Subject: color: move color_dump() Move color_dump() to color/debug.c where it belongs. --- color/command.c | 195 +------------------------------------------------- color/curses2.h | 5 -- color/debug.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++- color/debug.h | 6 ++ color/merged.h | 4 -- color/regex4.h | 18 ----- debug/lib.h | 1 + pager/dlg_pager.c | 2 - pager/lib.h | 5 ++ pager/pager.c | 2 - 10 files changed, 220 insertions(+), 226 deletions(-) diff --git a/color/command.c b/color/command.c index e7e36c9d4..d819fc292 100644 --- a/color/command.c +++ b/color/command.c @@ -36,6 +36,7 @@ #include "config/lib.h" #include "core/lib.h" #include "gui/lib.h" +#include "mutt.h" #include "parse/lib.h" #include "color.h" #include "command2.h" @@ -45,15 +46,6 @@ #include "quoted.h" #include "regex4.h" #include "simple2.h" -#ifdef USE_DEBUG_COLOR -#include -#include "mutt.h" -#include "pager/lib.h" -#include "attr.h" -#include "curses2.h" -#include "merged.h" -#include "pager/private_data.h" // IWYU pragma: keep -#endif /** * ColorFields - Mapping of colour names to their IDs @@ -862,191 +854,6 @@ static enum CommandResult parse_uncolor(struct Buffer *buf, struct Buffer *s, return MUTT_CMD_SUCCESS; } -#ifdef USE_DEBUG_COLOR -/** - * color_dump - Parse 'color' command to display colours - Implements Command::parse() - @ingroup command_parse - */ -static enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, - intptr_t data, struct Buffer *err) -{ - if (MoreArgs(s)) - return MUTT_CMD_ERROR; - - FILE *fp_out = NULL; - struct Buffer *tempfile = buf_pool_get(); - struct Buffer filebuf = buf_make(4096); - char color_fg[32] = { 0 }; - char color_bg[32] = { 0 }; - - buf_mktemp(tempfile); - fp_out = mutt_file_fopen(buf_string(tempfile), "w"); - if (!fp_out) - { - // L10N: '%s' is the file name of the temporary file - buf_printf(err, _("Could not create temporary file %s"), buf_string(tempfile)); - buf_dealloc(&filebuf); - buf_pool_release(&tempfile); - return MUTT_CMD_ERROR; - } - - buf_addstr(&filebuf, "# All Colours\n\n"); - buf_addstr(&filebuf, "# Simple Colours\n"); - for (enum ColorId cid = MT_COLOR_NONE + 1; cid < MT_COLOR_MAX; cid++) - { - struct AttrColor *ac = simple_color_get(cid); - if (!ac) - continue; - - struct CursesColor *cc = ac->curses_color; - if (!cc) - continue; - - const char *name = mutt_map_get_name(cid, ColorFields); - if (!name) - continue; - - const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); - buf_add_printf(&filebuf, "color %-18s %-30s %-8s %-8s # %s\n", name, - color_debug_log_attrs_list(ac->attrs), - color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); - } - - if (NumQuotedColors > 0) - { - buf_addstr(&filebuf, "\n# Quoted Colours\n"); - for (int i = 0; i < NumQuotedColors; i++) - { - struct AttrColor *ac = quoted_colors_get(i); - if (!ac) - continue; - - struct CursesColor *cc = ac->curses_color; - if (!cc) - continue; - - const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); - buf_add_printf(&filebuf, "color quoted%d %-30s %-8s %-8s # %s\n", i, - color_debug_log_attrs_list(ac->attrs), - color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); - } - } - - int rl_count = 0; - for (enum ColorId id = MT_COLOR_NONE; id != MT_COLOR_MAX; ++id) - { - if (!mutt_color_has_pattern(id)) - { - continue; - } - - struct RegexColorList *rcl = regex_colors_get_list(id); - if (!STAILQ_EMPTY(rcl)) - rl_count++; - } - - if (rl_count > 0) - { - for (enum ColorId id = MT_COLOR_NONE; id != MT_COLOR_MAX; ++id) - { - if (!mutt_color_has_pattern(id)) - { - continue; - } - - struct RegexColorList *rcl = regex_colors_get_list(id); - if (STAILQ_EMPTY(rcl)) - continue; - - const char *name = mutt_map_get_name(id, ColorFields); - if (!name) - continue; - - buf_add_printf(&filebuf, "\n# Regex Colour %s\n", name); - - struct RegexColor *rc = NULL; - STAILQ_FOREACH(rc, rcl, entries) - { - struct AttrColor *ac = &rc->attr_color; - struct CursesColor *cc = ac->curses_color; - if (!cc) - continue; - - const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); - buf_add_printf(&filebuf, "color %-14s %-30s %-8s %-8s %-30s # %s\n", - name, color_debug_log_attrs_list(ac->attrs), - color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), - rc->pattern, swatch); - } - } - } - -#ifdef USE_DEBUG_COLOR - if (!TAILQ_EMPTY(&MergedColors)) - { - buf_addstr(&filebuf, "\n# Merged Colours\n"); - struct AttrColor *ac = NULL; - TAILQ_FOREACH(ac, &MergedColors, entries) - { - struct CursesColor *cc = ac->curses_color; - if (!cc) - continue; - - const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); - buf_add_printf(&filebuf, "# %-30s %-8s %-8s # %s\n", - color_debug_log_attrs_list(ac->attrs), - color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); - } - } - - struct MuttWindow *win = window_get_focus(); - if (win && (win->type == WT_CUSTOM) && win->parent && (win->parent->type == WT_PAGER)) - { - struct PagerPrivateData *priv = win->parent->wdata; - if (priv && !TAILQ_EMPTY(&priv->ansi_list)) - { - buf_addstr(&filebuf, "\n# Ansi Colours\n"); - struct AttrColor *ac = NULL; - TAILQ_FOREACH(ac, &priv->ansi_list, entries) - { - struct CursesColor *cc = ac->curses_color; - if (!cc) - continue; - - const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); - buf_add_printf(&filebuf, "# %-30s %-8s %-8s # %s\n", - color_debug_log_attrs_list(ac->attrs), - color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); - } - } - } -#endif - - fputs(filebuf.data, fp_out); - - mutt_file_fclose(&fp_out); - buf_dealloc(&filebuf); - - struct PagerData pdata = { 0 }; - struct PagerView pview = { &pdata }; - - pdata.fname = buf_string(tempfile); - - pview.banner = "color"; - pview.flags = MUTT_SHOWCOLOR; - pview.mode = PAGER_MODE_OTHER; - - mutt_do_pager(&pview, NULL); - buf_pool_release(&tempfile); - - return MUTT_CMD_SUCCESS; -} -#endif - /** * parse_color - Parse a 'color' command * @param buf Temporary Buffer space diff --git a/color/curses2.h b/color/curses2.h index b1b2ec045..100fb20e0 100644 --- a/color/curses2.h +++ b/color/curses2.h @@ -46,11 +46,6 @@ struct CursesColor }; TAILQ_HEAD(CursesColorList, CursesColor); -#ifdef USE_DEBUG_COLOR -extern struct CursesColorList CursesColors; -extern int NumCursesColors; -#endif - void curses_color_free(struct CursesColor **ptr); struct CursesColor *curses_color_new (int fg, int bg); diff --git a/color/debug.c b/color/debug.c index fa20766cd..03e7a7bd7 100644 --- a/color/debug.c +++ b/color/debug.c @@ -31,16 +31,39 @@ #include #include #include "mutt/lib.h" +#include "core/lib.h" #include "gui/lib.h" #include "debug.h" +#include "pager/lib.h" +#include "parse/lib.h" #include "attr.h" #include "color.h" #include "curses2.h" -#include "merged.h" +#include "pager/private_data.h" // IWYU pragma: keep #include "quoted.h" #include "regex4.h" #include "simple2.h" +extern struct AttrColorList MergedColors; +extern struct CursesColorList CursesColors; +extern int NumCursesColors; + +extern struct RegexColorList AttachList; +extern struct RegexColorList BodyList; +extern struct RegexColorList HeaderList; +extern struct RegexColorList IndexAuthorList; +extern struct RegexColorList IndexCollapsedList; +extern struct RegexColorList IndexDateList; +extern struct RegexColorList IndexFlagsList; +extern struct RegexColorList IndexLabelList; +extern struct RegexColorList IndexList; +extern struct RegexColorList IndexNumberList; +extern struct RegexColorList IndexSizeList; +extern struct RegexColorList IndexSubjectList; +extern struct RegexColorList IndexTagList; +extern struct RegexColorList IndexTagsList; +extern struct RegexColorList StatusList; + /** * color_debug - Write to the log file * @param level Logging level, e.g. #LL_DEBUG1 @@ -464,3 +487,186 @@ void merged_colors_dump(void) { attr_color_list_dump(&MergedColors, "MergedColors"); } + +/** + * color_dump - Parse 'color' command to display colours - Implements Command::parse() - @ingroup command_parse + */ +enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, + intptr_t data, struct Buffer *err) +{ + if (MoreArgs(s)) + return MUTT_CMD_ERROR; + + FILE *fp_out = NULL; + struct Buffer *tempfile = buf_pool_get(); + struct Buffer filebuf = buf_make(4096); + char color_fg[32] = { 0 }; + char color_bg[32] = { 0 }; + + buf_mktemp(tempfile); + fp_out = mutt_file_fopen(buf_string(tempfile), "w"); + if (!fp_out) + { + // L10N: '%s' is the file name of the temporary file + buf_printf(err, _("Could not create temporary file %s"), buf_string(tempfile)); + buf_dealloc(&filebuf); + buf_pool_release(&tempfile); + return MUTT_CMD_ERROR; + } + + buf_addstr(&filebuf, "# All Colours\n\n"); + buf_addstr(&filebuf, "# Simple Colours\n"); + for (enum ColorId cid = MT_COLOR_NONE + 1; cid < MT_COLOR_MAX; cid++) + { + struct AttrColor *ac = simple_color_get(cid); + if (!ac) + continue; + + struct CursesColor *cc = ac->curses_color; + if (!cc) + continue; + + const char *name = mutt_map_get_name(cid, ColorFields); + if (!name) + continue; + + const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); + buf_add_printf(&filebuf, "color %-18s %-30s %-8s %-8s # %s\n", name, + color_debug_log_attrs_list(ac->attrs), + color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + } + + if (NumQuotedColors > 0) + { + buf_addstr(&filebuf, "\n# Quoted Colours\n"); + for (int i = 0; i < NumQuotedColors; i++) + { + struct AttrColor *ac = quoted_colors_get(i); + if (!ac) + continue; + + struct CursesColor *cc = ac->curses_color; + if (!cc) + continue; + + const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); + buf_add_printf(&filebuf, "color quoted%d %-30s %-8s %-8s # %s\n", i, + color_debug_log_attrs_list(ac->attrs), + color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + } + } + + int rl_count = 0; + for (enum ColorId id = MT_COLOR_NONE; id != MT_COLOR_MAX; ++id) + { + if (!mutt_color_has_pattern(id)) + { + continue; + } + + struct RegexColorList *rcl = regex_colors_get_list(id); + if (!STAILQ_EMPTY(rcl)) + rl_count++; + } + + if (rl_count > 0) + { + for (enum ColorId id = MT_COLOR_NONE; id != MT_COLOR_MAX; ++id) + { + if (!mutt_color_has_pattern(id)) + { + continue; + } + + struct RegexColorList *rcl = regex_colors_get_list(id); + if (STAILQ_EMPTY(rcl)) + continue; + + const char *name = mutt_map_get_name(id, ColorFields); + if (!name) + continue; + + buf_add_printf(&filebuf, "\n# Regex Colour %s\n", name); + + struct RegexColor *rc = NULL; + STAILQ_FOREACH(rc, rcl, entries) + { + struct AttrColor *ac = &rc->attr_color; + struct CursesColor *cc = ac->curses_color; + if (!cc) + continue; + + const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); + buf_add_printf(&filebuf, "color %-14s %-30s %-8s %-8s %-30s # %s\n", + name, color_debug_log_attrs_list(ac->attrs), + color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), + rc->pattern, swatch); + } + } + } + +#ifdef USE_DEBUG_COLOR + if (!TAILQ_EMPTY(&MergedColors)) + { + buf_addstr(&filebuf, "\n# Merged Colours\n"); + struct AttrColor *ac = NULL; + TAILQ_FOREACH(ac, &MergedColors, entries) + { + struct CursesColor *cc = ac->curses_color; + if (!cc) + continue; + + const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); + buf_add_printf(&filebuf, "# %-30s %-8s %-8s # %s\n", + color_debug_log_attrs_list(ac->attrs), + color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + } + } + + struct MuttWindow *win = window_get_focus(); + if (win && (win->type == WT_CUSTOM) && win->parent && (win->parent->type == WT_PAGER)) + { + struct PagerPrivateData *priv = win->parent->wdata; + if (priv && !TAILQ_EMPTY(&priv->ansi_list)) + { + buf_addstr(&filebuf, "\n# Ansi Colours\n"); + struct AttrColor *ac = NULL; + TAILQ_FOREACH(ac, &priv->ansi_list, entries) + { + struct CursesColor *cc = ac->curses_color; + if (!cc) + continue; + + const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); + buf_add_printf(&filebuf, "# %-30s %-8s %-8s # %s\n", + color_debug_log_attrs_list(ac->attrs), + color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + } + } + } +#endif + + fputs(filebuf.data, fp_out); + + mutt_file_fclose(&fp_out); + buf_dealloc(&filebuf); + + struct PagerData pdata = { 0 }; + struct PagerView pview = { &pdata }; + + pdata.fname = buf_string(tempfile); + + pview.banner = "color"; + pview.flags = MUTT_SHOWCOLOR; + pview.mode = PAGER_MODE_OTHER; + + mutt_do_pager(&pview, NULL); + buf_pool_release(&tempfile); + + return MUTT_CMD_SUCCESS; +} diff --git a/color/debug.h b/color/debug.h index 9df5deda4..50dc525fc 100644 --- a/color/debug.h +++ b/color/debug.h @@ -25,7 +25,9 @@ #include "config.h" #include +#include #include "mutt/lib.h" +#include "core/lib.h" #include "color.h" struct AttrColor; @@ -40,6 +42,8 @@ const char *color_debug_log_attrs_list(int attrs); #ifdef USE_DEBUG_COLOR +enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err); + const char *color_debug_log_attrs(int attrs); const char *color_debug_log_color(int fg, int bg); @@ -66,6 +70,8 @@ int color_debug(enum LogLevel level, const char *format, ...) #else +static inline enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err) { return MUTT_CMD_SUCCESS; } + static inline const char *color_debug_log_attrs(int attrs) { return ""; } static inline const char *color_debug_log_color(int fg, int bg) { return ""; } diff --git a/color/merged.h b/color/merged.h index 7d1b52bef..a1cf0ead6 100644 --- a/color/merged.h +++ b/color/merged.h @@ -27,10 +27,6 @@ struct AttrColor; -#ifdef USE_DEBUG_COLOR -extern struct AttrColorList MergedColors; -#endif - const struct AttrColor * merged_color_overlay(const struct AttrColor *base, const struct AttrColor *over); void merged_colors_cleanup(void); diff --git a/color/regex4.h b/color/regex4.h index 31af406c8..d948ed9cc 100644 --- a/color/regex4.h +++ b/color/regex4.h @@ -47,24 +47,6 @@ struct RegexColor }; STAILQ_HEAD(RegexColorList, RegexColor); -#ifdef USE_DEBUG_COLOR -extern struct RegexColorList AttachList; -extern struct RegexColorList BodyList; -extern struct RegexColorList HeaderList; -extern struct RegexColorList IndexAuthorList; -extern struct RegexColorList IndexCollapsedList; -extern struct RegexColorList IndexDateList; -extern struct RegexColorList IndexFlagsList; -extern struct RegexColorList IndexLabelList; -extern struct RegexColorList IndexList; -extern struct RegexColorList IndexNumberList; -extern struct RegexColorList IndexSizeList; -extern struct RegexColorList IndexSubjectList; -extern struct RegexColorList IndexTagList; -extern struct RegexColorList IndexTagsList; -extern struct RegexColorList StatusList; -#endif - void regex_color_clear(struct RegexColor *rcol); void regex_color_free(struct RegexColorList *list, struct RegexColor **ptr); struct RegexColor * regex_color_new (void); diff --git a/debug/lib.h b/debug/lib.h index 37b76d724..4990111e3 100644 --- a/debug/lib.h +++ b/debug/lib.h @@ -43,6 +43,7 @@ #include #include +#include #include "mutt/lib.h" #include "email/lib.h" #include "core/lib.h" diff --git a/pager/dlg_pager.c b/pager/dlg_pager.c index 703df9bf8..171b4dbcd 100644 --- a/pager/dlg_pager.c +++ b/pager/dlg_pager.c @@ -492,9 +492,7 @@ int dlg_pager(struct PagerView *pview) continue; } -#ifdef USE_DEBUG_COLOR dump_pager(priv); -#endif //------------------------------------------------------------------------- // Finally, read user's key press diff --git a/pager/lib.h b/pager/lib.h index 362d3d15d..5181963a5 100644 --- a/pager/lib.h +++ b/pager/lib.h @@ -210,6 +210,11 @@ struct TextSyntax; struct Line; void dump_text_syntax(struct TextSyntax *ts, int num); void dump_line(int i, struct Line *line); + +#ifdef USE_DEBUG_COLOR void dump_pager(struct PagerPrivateData *priv); +#else +static inline void dump_pager(struct PagerPrivateData *priv) {} +#endif #endif /* MUTT_PAGER_LIB_H */ diff --git a/pager/pager.c b/pager/pager.c index 7dfa3d5b6..e8e77ebc7 100644 --- a/pager/pager.c +++ b/pager/pager.c @@ -133,9 +133,7 @@ static int pager_repaint(struct MuttWindow *win) if (!priv || !priv->pview || !priv->pview->pdata) return 0; -#ifdef USE_DEBUG_COLOR dump_pager(priv); -#endif // We need to populate more lines, but not change position const bool repopulate = (priv->cur_line > priv->lines_used); -- cgit v1.2.3 From 83edd0da0a9771f88162ce89344200786aef3750 Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Mon, 9 Oct 2023 14:12:32 +0100 Subject: color: tidy color_dump() Eliminate an unnecessary intermediate Buffer. Eliminate all the unused parameters. Create an empty inline version for !USE_DEBUG_COLOR. --- color/ansi.c | 4 +++ color/command.c | 7 +++-- color/debug.c | 95 +++++++++++++++++++++++---------------------------------- color/debug.h | 6 ++-- debug/lib.h | 1 - 5 files changed, 49 insertions(+), 64 deletions(-) diff --git a/color/ansi.c b/color/ansi.c index 7dbb259b4..6442885f8 100644 --- a/color/ansi.c +++ b/color/ansi.c @@ -176,6 +176,10 @@ static int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool pos += ansi_skip_sequence(buf + pos); pos += ansi_skip_sequence(buf + pos); } + else + { + return pos; + } } else if ((buf[pos + 1] == '9') && ansi_is_end_char(buf[pos + 2])) { diff --git a/color/command.c b/color/command.c index d819fc292..7eef8ee59 100644 --- a/color/command.c +++ b/color/command.c @@ -879,10 +879,11 @@ static enum CommandResult parse_color(struct Buffer *buf, struct Buffer *s, if (!MoreArgs(s)) { -#ifdef USE_DEBUG_COLOR if (StartupComplete) - return color_dump(buf, s, 0, err); -#endif + { + color_dump(); + return MUTT_CMD_SUCCESS; + } buf_printf(err, _("%s: too few arguments"), "color"); return MUTT_CMD_WARNING; diff --git a/color/debug.c b/color/debug.c index 03e7a7bd7..02e9a560b 100644 --- a/color/debug.c +++ b/color/debug.c @@ -35,7 +35,6 @@ #include "gui/lib.h" #include "debug.h" #include "pager/lib.h" -#include "parse/lib.h" #include "attr.h" #include "color.h" #include "curses2.h" @@ -489,33 +488,26 @@ void merged_colors_dump(void) } /** - * color_dump - Parse 'color' command to display colours - Implements Command::parse() - @ingroup command_parse + * color_dump - Display all the colours in the Pager */ -enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, - intptr_t data, struct Buffer *err) +void color_dump(void) { - if (MoreArgs(s)) - return MUTT_CMD_ERROR; - - FILE *fp_out = NULL; - struct Buffer *tempfile = buf_pool_get(); - struct Buffer filebuf = buf_make(4096); + struct Buffer *tmp_file = buf_pool_get(); char color_fg[32] = { 0 }; char color_bg[32] = { 0 }; - buf_mktemp(tempfile); - fp_out = mutt_file_fopen(buf_string(tempfile), "w"); - if (!fp_out) + buf_mktemp(tmp_file); + FILE *fp = mutt_file_fopen(buf_string(tmp_file), "w"); + if (!fp) { // L10N: '%s' is the file name of the temporary file - buf_printf(err, _("Could not create temporary file %s"), buf_string(tempfile)); - buf_dealloc(&filebuf); - buf_pool_release(&tempfile); - return MUTT_CMD_ERROR; + mutt_error(_("Could not create temporary file %s"), buf_string(tmp_file)); + buf_pool_release(&tmp_file); + return; } - buf_addstr(&filebuf, "# All Colours\n\n"); - buf_addstr(&filebuf, "# Simple Colours\n"); + fputs("# All Colours\n\n", fp); + fputs("# Simple Colours\n", fp); for (enum ColorId cid = MT_COLOR_NONE + 1; cid < MT_COLOR_MAX; cid++) { struct AttrColor *ac = simple_color_get(cid); @@ -531,15 +523,15 @@ enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, continue; const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); - buf_add_printf(&filebuf, "color %-18s %-30s %-8s %-8s # %s\n", name, - color_debug_log_attrs_list(ac->attrs), - color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + fprintf(fp, "color %-18s %-30s %-8s %-8s # %s\n", name, + color_debug_log_attrs_list(ac->attrs), + color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); } if (NumQuotedColors > 0) { - buf_addstr(&filebuf, "\n# Quoted Colours\n"); + fputs("\n# Quoted Colours\n", fp); for (int i = 0; i < NumQuotedColors; i++) { struct AttrColor *ac = quoted_colors_get(i); @@ -551,15 +543,15 @@ enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, continue; const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); - buf_add_printf(&filebuf, "color quoted%d %-30s %-8s %-8s # %s\n", i, - color_debug_log_attrs_list(ac->attrs), - color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + fprintf(fp, "color quoted%d %-30s %-8s %-8s # %s\n", i, + color_debug_log_attrs_list(ac->attrs), + color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); } } int rl_count = 0; - for (enum ColorId id = MT_COLOR_NONE; id != MT_COLOR_MAX; ++id) + for (enum ColorId id = MT_COLOR_NONE; id != MT_COLOR_MAX; id++) { if (!mutt_color_has_pattern(id)) { @@ -573,7 +565,7 @@ enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, if (rl_count > 0) { - for (enum ColorId id = MT_COLOR_NONE; id != MT_COLOR_MAX; ++id) + for (enum ColorId id = MT_COLOR_NONE; id != MT_COLOR_MAX; id++) { if (!mutt_color_has_pattern(id)) { @@ -588,7 +580,7 @@ enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, if (!name) continue; - buf_add_printf(&filebuf, "\n# Regex Colour %s\n", name); + fprintf(fp, "\n# Regex Colour %s\n", name); struct RegexColor *rc = NULL; STAILQ_FOREACH(rc, rcl, entries) @@ -599,19 +591,18 @@ enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, continue; const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); - buf_add_printf(&filebuf, "color %-14s %-30s %-8s %-8s %-30s # %s\n", - name, color_debug_log_attrs_list(ac->attrs), - color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), - rc->pattern, swatch); + fprintf(fp, "color %-14s %-30s %-8s %-8s %-30s # %s\n", name, + color_debug_log_attrs_list(ac->attrs), + color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), + rc->pattern, swatch); } } } -#ifdef USE_DEBUG_COLOR if (!TAILQ_EMPTY(&MergedColors)) { - buf_addstr(&filebuf, "\n# Merged Colours\n"); + fputs("\n# Merged Colours\n", fp); struct AttrColor *ac = NULL; TAILQ_FOREACH(ac, &MergedColors, entries) { @@ -620,10 +611,9 @@ enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, continue; const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); - buf_add_printf(&filebuf, "# %-30s %-8s %-8s # %s\n", - color_debug_log_attrs_list(ac->attrs), - color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + fprintf(fp, "# %-30s %-8s %-8s # %s\n", color_debug_log_attrs_list(ac->attrs), + color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); } } @@ -633,7 +623,7 @@ enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, struct PagerPrivateData *priv = win->parent->wdata; if (priv && !TAILQ_EMPTY(&priv->ansi_list)) { - buf_addstr(&filebuf, "\n# Ansi Colours\n"); + fputs("\n# Ansi Colours\n", fp); struct AttrColor *ac = NULL; TAILQ_FOREACH(ac, &priv->ansi_list, entries) { @@ -642,31 +632,24 @@ enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, continue; const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); - buf_add_printf(&filebuf, "# %-30s %-8s %-8s # %s\n", - color_debug_log_attrs_list(ac->attrs), - color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + fprintf(fp, "# %-30s %-8s %-8s # %s\n", color_debug_log_attrs_list(ac->attrs), + color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); } } } -#endif - fputs(filebuf.data, fp_out); - - mutt_file_fclose(&fp_out); - buf_dealloc(&filebuf); + mutt_file_fclose(&fp); struct PagerData pdata = { 0 }; struct PagerView pview = { &pdata }; - pdata.fname = buf_string(tempfile); + pdata.fname = buf_string(tmp_file); pview.banner = "color"; pview.flags = MUTT_SHOWCOLOR; pview.mode = PAGER_MODE_OTHER; mutt_do_pager(&pview, NULL); - buf_pool_release(&tempfile); - - return MUTT_CMD_SUCCESS; + buf_pool_release(&tmp_file); } diff --git a/color/debug.h b/color/debug.h index 50dc525fc..5c8e62724 100644 --- a/color/debug.h +++ b/color/debug.h @@ -25,9 +25,7 @@ #include "config.h" #include -#include #include "mutt/lib.h" -#include "core/lib.h" #include "color.h" struct AttrColor; @@ -42,7 +40,7 @@ const char *color_debug_log_attrs_list(int attrs); #ifdef USE_DEBUG_COLOR -enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err); +void color_dump(void); const char *color_debug_log_attrs(int attrs); const char *color_debug_log_color(int fg, int bg); @@ -70,7 +68,7 @@ int color_debug(enum LogLevel level, const char *format, ...) #else -static inline enum CommandResult color_dump(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err) { return MUTT_CMD_SUCCESS; } +static inline void color_dump(void) {} static inline const char *color_debug_log_attrs(int attrs) { return ""; } static inline const char *color_debug_log_color(int fg, int bg) { return ""; } diff --git a/debug/lib.h b/debug/lib.h index 4990111e3..37b76d724 100644 --- a/debug/lib.h +++ b/debug/lib.h @@ -43,7 +43,6 @@ #include #include -#include #include "mutt/lib.h" #include "email/lib.h" #include "core/lib.h" -- cgit v1.2.3 From b717d5e7eadc889de776c31c4f43c6fcf0ac40fd Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Mon, 9 Oct 2023 15:18:44 +0100 Subject: color: tidy color_debug_log_color_attrs() Use a Buffer to ease the construction of the colour swatch. --- color/debug.c | 63 +++++++++++++++++++++++++++++++---------------------------- color/debug.h | 4 ---- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/color/debug.c b/color/debug.c index 02e9a560b..dba6970c4 100644 --- a/color/debug.c +++ b/color/debug.c @@ -86,39 +86,36 @@ int color_debug(enum LogLevel level, const char *format, ...) /** * color_debug_log_color_attrs - Get a colourful string to represent a colour in the log - * @param fg Foreground colour - * @param bg Background colour - * @param attrs Attributes, e.g. A_UNDERLINE - * @retval ptr Generated string + * @param fg Foreground colour + * @param bg Background colour + * @param attrs Attributes, e.g. A_UNDERLINE + * @param swatch Buffer for swatch * * @note Do not free the returned string */ -const char *color_debug_log_color_attrs(int fg, int bg, int attrs) +void color_debug_log_color_attrs(int fg, int bg, int attrs, struct Buffer *swatch) { - static char text[64]; - int pos = 0; + buf_reset(swatch); if (attrs & A_BLINK) - pos += snprintf(text + pos, sizeof(text) - pos, "\033[5m"); + buf_add_printf(swatch, "\033[5m"); if (attrs & A_BOLD) - pos += snprintf(text + pos, sizeof(text) - pos, "\033[1m"); + buf_add_printf(swatch, "\033[1m"); if (attrs & A_NORMAL) - pos += snprintf(text + pos, sizeof(text) - pos, "\033[0m"); + buf_add_printf(swatch, "\033[0m"); if (attrs & A_REVERSE) - pos += snprintf(text + pos, sizeof(text) - pos, "\033[7m"); + buf_add_printf(swatch, "\033[7m"); if (attrs & A_STANDOUT) - pos += snprintf(text + pos, sizeof(text) - pos, "\033[1m"); + buf_add_printf(swatch, "\033[1m"); if (attrs & A_UNDERLINE) - pos += snprintf(text + pos, sizeof(text) - pos, "\033[4m"); + buf_add_printf(swatch, "\033[4m"); if (fg >= 0) - pos += snprintf(text + pos, sizeof(text) - pos, "\033[38;5;%dm", fg); + buf_add_printf(swatch, "\033[38;5;%dm", fg); if (bg >= 0) - pos += snprintf(text + pos, sizeof(text) - pos, "\033[48;5;%dm", bg); - - snprintf(text + pos, sizeof(text) - pos, "XXXXXX\033[0m"); + buf_add_printf(swatch, "\033[48;5;%dm", bg); - return text; + buf_addstr(swatch, "XXXXXX\033[0m"); } /** @@ -493,8 +490,6 @@ void merged_colors_dump(void) void color_dump(void) { struct Buffer *tmp_file = buf_pool_get(); - char color_fg[32] = { 0 }; - char color_bg[32] = { 0 }; buf_mktemp(tmp_file); FILE *fp = mutt_file_fopen(buf_string(tmp_file), "w"); @@ -506,6 +501,10 @@ void color_dump(void) return; } + struct Buffer *swatch = buf_pool_get(); + char color_fg[32] = { 0 }; + char color_bg[32] = { 0 }; + fputs("# All Colours\n\n", fp); fputs("# Simple Colours\n", fp); for (enum ColorId cid = MT_COLOR_NONE + 1; cid < MT_COLOR_MAX; cid++) @@ -522,11 +521,11 @@ void color_dump(void) if (!name) continue; - const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); + color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs, swatch); fprintf(fp, "color %-18s %-30s %-8s %-8s # %s\n", name, color_debug_log_attrs_list(ac->attrs), color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), buf_string(swatch)); } if (NumQuotedColors > 0) @@ -542,11 +541,12 @@ void color_dump(void) if (!cc) continue; - const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); + color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs, swatch); fprintf(fp, "color quoted%d %-30s %-8s %-8s # %s\n", i, color_debug_log_attrs_list(ac->attrs), color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), + buf_string(swatch)); } } @@ -590,12 +590,12 @@ void color_dump(void) if (!cc) continue; - const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); + color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs, swatch); fprintf(fp, "color %-14s %-30s %-8s %-8s %-30s # %s\n", name, color_debug_log_attrs_list(ac->attrs), color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), - rc->pattern, swatch); + rc->pattern, buf_string(swatch)); } } } @@ -610,10 +610,11 @@ void color_dump(void) if (!cc) continue; - const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); + color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs, swatch); fprintf(fp, "# %-30s %-8s %-8s # %s\n", color_debug_log_attrs_list(ac->attrs), color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), + buf_string(swatch)); } } @@ -631,10 +632,11 @@ void color_dump(void) if (!cc) continue; - const char *swatch = color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs); + color_debug_log_color_attrs(cc->fg, cc->bg, ac->attrs, swatch); fprintf(fp, "# %-30s %-8s %-8s # %s\n", color_debug_log_attrs_list(ac->attrs), color_debug_log_name(color_fg, sizeof(color_fg), cc->fg), - color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), swatch); + color_debug_log_name(color_bg, sizeof(color_bg), cc->bg), + buf_string(swatch)); } } } @@ -652,4 +654,5 @@ void color_dump(void) mutt_do_pager(&pview, NULL); buf_pool_release(&tmp_file); + buf_pool_release(&swatch); } diff --git a/color/debug.h b/color/debug.h index 5c8e62724..1f076644c 100644 --- a/color/debug.h +++ b/color/debug.h @@ -34,10 +34,6 @@ struct CursesColor; struct RegexColor; struct RegexColorList; -const char *color_debug_log_color_attrs(int fg, int bg, int attrs); -const char *color_debug_log_name(char *buf, int buflen, int color); -const char *color_debug_log_attrs_list(int attrs); - #ifdef USE_DEBUG_COLOR void color_dump(void); -- cgit v1.2.3 From 0c0deef9a4170b7dc8f22de73e5834969c9e082e Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Mon, 9 Oct 2023 17:24:22 +0100 Subject: color: define a type for colours Be specific about the type of a Colour. It needs to be larger than 24-bits and signed (to allow -1 for "default"). --- color/ansi.c | 14 +++++++------- color/ansi.h | 5 +++-- color/attr.c | 5 ++--- color/attr.h | 4 ++-- color/color.h | 5 ++--- color/command.c | 55 ++++++++++++++++++++++++++++++------------------------- color/command2.h | 9 +++++---- color/curses.c | 6 +++--- color/curses2.h | 13 +++++++------ color/debug.c | 20 ++++++++++---------- color/debug.h | 6 +++--- color/merged.c | 7 +++---- color/quoted.c | 3 +-- color/quoted.h | 4 ++-- color/regex.c | 10 +++++----- color/regex4.h | 8 ++++---- color/simple.c | 2 +- color/simple2.h | 3 ++- 18 files changed, 92 insertions(+), 87 deletions(-) diff --git a/color/ansi.c b/color/ansi.c index 6442885f8..676c7b790 100644 --- a/color/ansi.c +++ b/color/ansi.c @@ -146,7 +146,7 @@ static int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool } else if (buf[pos] == '3') { - // 30-37 basic fg + // 30-37 basic foreground if ((buf[pos + 1] >= '0') && (buf[pos + 1] < '8') && ansi_is_end_char(buf[pos + 2])) { ansi->fg = buf[pos + 1] - '0'; @@ -156,7 +156,7 @@ static int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool { if (mutt_str_startswith(buf + pos, "38;5;") && isdigit(buf[pos + 5])) { - // 38;5;n palette fg + // 38;5;n palette foreground char *end = NULL; int value = strtoul(buf + pos + 5, &end, 10); if ((value >= 0) && (value < 256) && end && ansi_is_end_char(end[0])) @@ -171,7 +171,7 @@ static int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool } else if (mutt_str_startswith(buf + pos, "38;2;") && isdigit(buf[pos + 5])) { - // 38;2;R;G;B true colour fg + // 38;2;R;G;B true colour foreground pos += ansi_skip_sequence(buf + pos + 5); pos += ansi_skip_sequence(buf + pos); pos += ansi_skip_sequence(buf + pos); @@ -199,7 +199,7 @@ static int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool } else if (buf[pos] == '4') { - // 40-47 basic bg + // 40-47 basic background if ((buf[pos + 1] >= '0') && (buf[pos + 1] < '8')) { ansi->bg = buf[pos + 1] - '0'; @@ -209,7 +209,7 @@ static int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool { if (mutt_str_startswith(buf + pos, "48;5;") && isdigit(buf[pos + 5])) { - // 48;5;n palette bg + // 48;5;n palette background char *end = NULL; int value = strtoul(buf + pos + 5, &end, 10); if ((value >= 0) && (value < 256) && end && ansi_is_end_char(end[0])) @@ -224,7 +224,7 @@ static int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool } else if (mutt_str_startswith(buf + pos, "48;2;") && isdigit(buf[pos + 5])) { - // 48;2;R;G;B true colour bg + // 48;2;R;G;B true colour background pos += ansi_skip_sequence(buf + pos + 5); pos += ansi_skip_sequence(buf + pos); pos += ansi_skip_sequence(buf + pos); @@ -236,7 +236,7 @@ static int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool } else if ((buf[pos + 1] == '9') && ansi_is_end_char(buf[pos + 2])) { - // default bg + // default background ansi->bg = COLOR_DEFAULT; pos += 2; } diff --git a/color/ansi.h b/color/ansi.h index ccd189f28..b78b4427d 100644 --- a/color/ansi.h +++ b/color/ansi.h @@ -24,6 +24,7 @@ #define MUTT_COLOR_ANSI_H #include +#include "curses2.h" struct AttrColorList; @@ -34,8 +35,8 @@ struct AnsiColor { const struct AttrColor *attr_color; ///< Curses colour of text int attrs; ///< Attributes, e.g. A_BOLD - int fg; ///< Foreground colour - int bg; ///< Background colour + color_t fg; ///< Foreground colour + color_t bg; ///< Background colour }; int ansi_color_parse (const char *str, struct AnsiColor *ansi, struct AttrColorList *acl, bool dry_run); diff --git a/color/attr.c b/color/attr.c index b4db66545..e616871d7 100644 --- a/color/attr.c +++ b/color/attr.c @@ -29,7 +29,6 @@ #include "config.h" #include -#include #include "mutt/lib.h" #include "attr.h" #include "curses2.h" @@ -116,8 +115,8 @@ void attr_color_list_clear(struct AttrColorList *acl) * @param attrs Attributes, e.g. A_UNDERLINE * @retval ptr Matching AttrColor */ -struct AttrColor *attr_color_list_find(struct AttrColorList *acl, uint32_t fg, - uint32_t bg, int attrs) +struct AttrColor *attr_color_list_find(struct AttrColorList *acl, color_t fg, + color_t bg, int attrs) { if (!acl) return NULL; diff --git a/color/attr.h b/color/attr.h index 0a3f5aec2..1657c2efd 100644 --- a/color/attr.h +++ b/color/attr.h @@ -25,8 +25,8 @@ #include "config.h" #include -#include #include "mutt/lib.h" +#include "curses2.h" /** * struct AttrColor - A curses colour and its attributes @@ -48,6 +48,6 @@ bool attr_color_match (struct AttrColor *ac1, struct AttrColor *ac2 struct AttrColor *attr_color_new (void); void attr_color_list_clear(struct AttrColorList *acl); -struct AttrColor *attr_color_list_find (struct AttrColorList *acl, uint32_t fg, uint32_t bg, int attrs); +struct AttrColor *attr_color_list_find (struct AttrColorList *acl, color_t fg, color_t bg, int attrs); #endif /* MUTT_COLOR_ATTR_H */ diff --git a/color/color.h b/color/color.h index c2405cd4d..b280889a5 100644 --- a/color/color.h +++ b/color/color.h @@ -25,7 +25,9 @@ #define MUTT_COLOR_COLOR_H #include "config.h" +#include "mutt/lib.h" #include +#include /** * enum ColorId - List of all colored objects @@ -94,9 +96,6 @@ enum ColorId MT_COLOR_MAX, }; -#include -#include "mutt/lib.h" - extern const struct Mapping ColorNames[]; extern const struct Mapping ColorFields[]; extern const struct Mapping ComposeColorFields[]; diff --git a/color/command.c b/color/command.c index 7eef8ee59..c02b50520 100644 --- a/color/command.c +++ b/color/command.c @@ -40,6 +40,7 @@ #include "parse/lib.h" #include "color.h" #include "command2.h" +#include "curses2.h" #include "debug.h" #include "globals.h" #include "notify2.h" @@ -200,9 +201,9 @@ enum ColorPrefix * | 240 | `#585858` | 241 | `#606060` | 242 | `#666666` | 243 | `#767676` | 244 | `#808080` | 245 | `#8a8a8a` | 246 | `#949494` | 247 | `#9e9e9e` | * | 248 | `#a8a8a8` | 249 | `#b2b2b2` | 250 | `#bcbcbc` | 251 | `#c6c6c6` | 252 | `#d0d0d0` | 253 | `#dadada` | 254 | `#e4e4e4` | 255 | `#eeeeee` | */ -static uint32_t color_xterm256_to_24bit(const uint32_t color) +static color_t color_xterm256_to_24bit(const color_t color) { - static const uint32_t basic[] = { + static const color_t basic[] = { 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 0xc0c0c0, 0x808080, 0xff0000, 0x00ff00, 0xffff00, 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff, @@ -210,6 +211,9 @@ static uint32_t color_xterm256_to_24bit(const uint32_t color) assert(color < 256); + if (color < 0) + return color; + if (color < 16) { color_debug(LL_DEBUG5, "Converted color 0-15: %d\n", color); @@ -236,26 +240,26 @@ static uint32_t color_xterm256_to_24bit(const uint32_t color) * value for red, green, and blue, respectively. */ - uint32_t normalised_color = color - 16; - uint32_t vr = (normalised_color % 216) / 36; /* 216 = 6*6*6 */ - uint32_t vg = (normalised_color % 36) / 6; - uint32_t vb = (normalised_color % 6) / 1; + color_t normalised_color = color - 16; + color_t vr = (normalised_color % 216) / 36; /* 216 = 6*6*6 */ + color_t vg = (normalised_color % 36) / 6; + color_t vb = (normalised_color % 6) / 1; /* First step is wider than the other ones, so add the difference if needed */ - uint32_t r = vr * 0x28 + ((vr > 0) ? (0x5f - 0x40) : 0); - uint32_t g = vg * 0x28 + ((vg > 0) ? (0x5f - 0x40) : 0); - uint32_t b = vb * 0x28 + ((vb > 0) ? (0x5f - 0x40) : 0); + color_t r = vr * 0x28 + ((vr > 0) ? (0x5f - 0x40) : 0); + color_t g = vg * 0x28 + ((vg > 0) ? (0x5f - 0x40) : 0); + color_t b = vb * 0x28 + ((vb > 0) ? (0x5f - 0x40) : 0); - uint32_t rgb = (r << 16) + (g << 8) + (b << 0); + color_t rgb = (r << 16) + (g << 8) + (b << 0); color_debug(LL_DEBUG5, "Converted xterm color %d to RGB #%x:\n", color, rgb); return rgb; } /* Grey scale starts at 0x08 and adds 0xa = 10 in very step ending in 0xee. * There are a total of 6*4 = 24 grey colors in total. */ - uint32_t steps = color - 232; - uint32_t grey = (steps * 0x0a) + 0x08; - uint32_t rgb = (grey << 16) + (grey << 8) + (grey << 0); + color_t steps = color - 232; + color_t grey = (steps * 0x0a) + 0x08; + color_t rgb = (grey << 16) + (grey << 8) + (grey << 0); color_debug(LL_DEBUG5, "Converted xterm color %d to RGB #%x:\n", color, rgb); return rgb; } @@ -269,7 +273,7 @@ static uint32_t color_xterm256_to_24bit(const uint32_t color) * @param[in,out] attrs attributes to modify */ static void modify_color_by_prefix(enum ColorPrefix prefix, bool is_fg, - uint32_t *col, int *attrs) + color_t *col, int *attrs) { if (prefix == COLOR_PREFIX_NONE) return; // nothing to do here @@ -353,7 +357,7 @@ static int parse_color_prefix(const char *s, enum ColorPrefix *prefix) * @retval #MUTT_CMD_SUCCESS Colour parsed successfully * @retval #MUTT_CMD_WARNING Unknown colour, try other parsers */ -static enum CommandResult parse_color_namedcolor(const char *s, uint32_t *col, int *attrs, +static enum CommandResult parse_color_namedcolor(const char *s, color_t *col, int *attrs, bool is_fg, struct Buffer *err) { enum ColorPrefix prefix = COLOR_PREFIX_NONE; @@ -400,7 +404,7 @@ static enum CommandResult parse_color_namedcolor(const char *s, uint32_t *col, i * * On #MUTT_CMD_ERROR, an error message will be written to err. */ -static enum CommandResult parse_color_colornnn(const char *s, uint32_t *col, int *attrs, +static enum CommandResult parse_color_colornnn(const char *s, color_t *col, int *attrs, bool is_fg, struct Buffer *err) { /* prefixes bright, alert, light are only allowed for named colours and @@ -458,7 +462,7 @@ static enum CommandResult parse_color_colornnn(const char *s, uint32_t *col, int * * On #MUTT_CMD_ERROR, an error message will be written to err. */ -static enum CommandResult parse_color_rrggbb(const char *s, uint32_t *col, int *attrs, +static enum CommandResult parse_color_rrggbb(const char *s, color_t *col, int *attrs, bool is_fg, struct Buffer *err) { /* parse #RRGGBB colours */ @@ -504,7 +508,7 @@ static enum CommandResult parse_color_rrggbb(const char *s, uint32_t *col, int * * * Parse a colour name, such as "red", "brightgreen", "color123", "#12FE45" */ -static enum CommandResult parse_color_name(const char *s, uint32_t *col, int *attrs, +static enum CommandResult parse_color_name(const char *s, color_t *col, int *attrs, bool is_fg, struct Buffer *err) { mutt_debug(LL_DEBUG5, "Parsing color name: %s\n", s); @@ -534,8 +538,8 @@ static enum CommandResult parse_color_name(const char *s, uint32_t *col, int *at * parse_attr_spec - Parse an attribute description - Implements ::parser_callback_t - @ingroup parser_callback_api */ static enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s, - uint32_t *fg, uint32_t *bg, - int *attrs, struct Buffer *err) + color_t *fg, color_t *bg, int *attrs, + struct Buffer *err) { if (fg) *fg = COLOR_UNSET; @@ -593,8 +597,8 @@ static enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s, * Parse a pair of colours, e.g. "red default" */ static enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s, - uint32_t *fg, uint32_t *bg, - int *attrs, struct Buffer *err) + color_t *fg, color_t *bg, int *attrs, + struct Buffer *err) { while (true) { @@ -873,7 +877,8 @@ static enum CommandResult parse_color(struct Buffer *buf, struct Buffer *s, bool dry_run, bool color) { int attrs = 0, q_level = 0; - uint32_t fg = 0, bg = 0, match = 0; + color_t fg = 0, bg = 0; + unsigned int match = 0; enum ColorId cid = MT_COLOR_NONE; enum CommandResult rc; @@ -902,7 +907,7 @@ static enum CommandResult parse_color(struct Buffer *buf, struct Buffer *s, /* extract a regular expression if needed */ - if (mutt_color_has_pattern(cid) && cid != MT_COLOR_STATUS) + if (mutt_color_has_pattern(cid) && (cid != MT_COLOR_STATUS)) { color_debug(LL_DEBUG5, "regex needed\n"); if (MoreArgs(s)) @@ -1049,5 +1054,5 @@ enum CommandResult mutt_parse_color(struct Buffer *buf, struct Buffer *s, enum CommandResult mutt_parse_mono(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err) { - return parse_color(buf, s, err, parse_attr_spec, true, false); + return parse_color(buf, s, err, parse_attr_spec, false, false); } diff --git a/color/command2.h b/color/command2.h index 87c754e82..f3ff74e4e 100644 --- a/color/command2.h +++ b/color/command2.h @@ -26,6 +26,7 @@ #include "config.h" #include #include "core/lib.h" +#include "curses2.h" struct Buffer; @@ -36,15 +37,15 @@ struct Buffer; * * @param[in] buf Temporary Buffer space * @param[in] s Buffer containing string to be parsed - * @param[out] fg Foreground colour (set to -1) - * @param[out] bg Background colour (set to -1) + * @param[out] fg Foreground colour + * @param[out] bg Background colour * @param[out] attrs Attributes, e.g. A_UNDERLINE * @param[out] err Buffer for error messages * @retval 0 Success * @retval -1 Error */ -typedef int (*parser_callback_t)(struct Buffer *buf, struct Buffer *s, uint32_t *fg, - uint32_t *bg, int *attrs, struct Buffer *err); +typedef int (*parser_callback_t)(struct Buffer *buf, struct Buffer *s, color_t *fg, + color_t *bg, int *attrs, struct Buffer *err); enum CommandResult mutt_parse_color (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err); enum CommandResult mutt_parse_mono (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err); diff --git a/color/curses.c b/color/curses.c index 96c18a102..a3bed5338 100644 --- a/color/curses.c +++ b/color/curses.c @@ -54,7 +54,7 @@ void curses_colors_init(void) * @param bg Background colour * @retval ptr Curses colour */ -struct CursesColor *curses_colors_find(int fg, int bg) +struct CursesColor *curses_colors_find(color_t fg, color_t bg) { struct CursesColor *cc = NULL; TAILQ_FOREACH(cc, &CursesColors, entries) @@ -74,7 +74,7 @@ struct CursesColor *curses_colors_find(int fg, int bg) * @param bg Background colour * @retval num Index of Curses colour */ -static int curses_color_init(int fg, int bg) +static int curses_color_init(color_t fg, color_t bg) { color_debug(LL_DEBUG5, "find lowest index\n"); int index = 16; @@ -148,7 +148,7 @@ void curses_color_free(struct CursesColor **ptr) * If the colour already exists, this function will return a pointer to the * object (and increase its ref-count). */ -struct CursesColor *curses_color_new(int fg, int bg) +struct CursesColor *curses_color_new(color_t fg, color_t bg) { color_debug(LL_DEBUG5, "fg %d, bg %d\n", fg, bg); if (((fg == COLOR_UNSET) && (bg == COLOR_UNSET)) || diff --git a/color/curses2.h b/color/curses2.h index 100fb20e0..8b033689c 100644 --- a/color/curses2.h +++ b/color/curses2.h @@ -27,6 +27,9 @@ #include #include "mutt/lib.h" +/// Type for 24-bit colour value +typedef int32_t color_t; + /** * struct CursesColor - Colour in the ncurses palette * @@ -36,10 +39,8 @@ */ struct CursesColor { - /* TrueColor uses 24bit. Use fixed-width integer type to make sure it fits. - * Use the upper 8 bits to store flags. */ - uint32_t fg; ///< Foreground colour - uint32_t bg; ///< Background colour + color_t fg; ///< Foreground colour + color_t bg; ///< Background colour short index; ///< Index number short ref_count; ///< Number of users TAILQ_ENTRY(CursesColor) entries; ///< Linked list @@ -47,9 +48,9 @@ struct CursesColor TAILQ_HEAD(CursesColorList, CursesColor); void curses_color_free(struct CursesColor **ptr); -struct CursesColor *curses_color_new (int fg, int bg); +struct CursesColor *curses_color_new (color_t fg, color_t bg); void curses_colors_init(void); -struct CursesColor *curses_colors_find (int fg, int bg); +struct CursesColor *curses_colors_find(color_t fg, color_t bg); #endif /* MUTT_COLOR_CURSES2_H */ diff --git a/color/debug.c b/color/debug.c index dba6970c4..a592a76cf 100644 --- a/color/debug.c +++ b/color/debug.c @@ -93,7 +93,7 @@ int color_debug(enum LogLevel level, const char *format, ...) * * @note Do not free the returned string */ -void color_debug_log_color_attrs(int fg, int bg, int attrs, struct Buffer *swatch) +void color_debug_log_color_attrs(color_t fg, color_t bg, int attrs, struct Buffer *swatch) { buf_reset(swatch); @@ -126,7 +126,7 @@ void color_debug_log_color_attrs(int fg, int bg, int attrs, struct Buffer *swatc * * @note Do not free the returned string */ -const char *color_debug_log_color(int fg, int bg) +const char *color_debug_log_color(color_t fg, color_t bg) { static char text[64]; snprintf(text, sizeof(text), "\033[38;5;%dm\033[48;5;%dmXXXXXX\033[0m", fg, bg); @@ -229,8 +229,8 @@ void attr_color_dump(struct AttrColor *ac, const char *prefix) int index = ac->curses_color ? ac->curses_color->index : -1; - int fg = COLOR_DEFAULT; - int bg = COLOR_DEFAULT; + color_t fg = COLOR_DEFAULT; + color_t bg = COLOR_DEFAULT; struct CursesColor *cc = ac->curses_color; if (cc) { @@ -318,8 +318,8 @@ void quoted_color_dump(struct AttrColor *ac, int q_level, const char *prefix) int index = ac->curses_color ? ac->curses_color->index : -1; - int fg = COLOR_DEFAULT; - int bg = COLOR_DEFAULT; + color_t fg = COLOR_DEFAULT; + color_t bg = COLOR_DEFAULT; struct CursesColor *cc = ac->curses_color; if (cc) { @@ -358,8 +358,8 @@ void regex_color_dump(struct RegexColor *rcol, const char *prefix) struct AttrColor *ac = &rcol->attr_color; int index = ac->curses_color ? ac->curses_color->index : -1; - int fg = COLOR_DEFAULT; - int bg = COLOR_DEFAULT; + color_t fg = COLOR_DEFAULT; + color_t bg = COLOR_DEFAULT; struct CursesColor *cc = ac->curses_color; if (cc) { @@ -444,8 +444,8 @@ void simple_color_dump(enum ColorId cid, const char *prefix) } } - int fg = COLOR_DEFAULT; - int bg = COLOR_DEFAULT; + color_t fg = COLOR_DEFAULT; + color_t bg = COLOR_DEFAULT; struct CursesColor *cc = ac->curses_color; if (cc) { diff --git a/color/debug.h b/color/debug.h index 1f076644c..96c4f6d54 100644 --- a/color/debug.h +++ b/color/debug.h @@ -27,10 +27,10 @@ #include #include "mutt/lib.h" #include "color.h" +#include "curses2.h" struct AttrColor; struct AttrColorList; -struct CursesColor; struct RegexColor; struct RegexColorList; @@ -39,7 +39,7 @@ struct RegexColorList; void color_dump(void); const char *color_debug_log_attrs(int attrs); -const char *color_debug_log_color(int fg, int bg); +const char *color_debug_log_color(color_t fg, color_t bg); void attr_color_dump (struct AttrColor *ac, const char *prefix); void attr_color_list_dump (struct AttrColorList *acl, const char *title); @@ -67,7 +67,7 @@ int color_debug(enum LogLevel level, const char *format, ...) static inline void color_dump(void) {} static inline const char *color_debug_log_attrs(int attrs) { return ""; } -static inline const char *color_debug_log_color(int fg, int bg) { return ""; } +static inline const char *color_debug_log_color(color_t fg, color_t bg) { return ""; } static inline void attr_color_dump (struct AttrColor *ac, const char *prefix) {} static inline void attr_color_list_dump (struct AttrColorList *acl, const char *title) {} diff --git a/color/merged.c b/color/merged.c index da4f41708..3cb8573f2 100644 --- a/color/merged.c +++ b/color/merged.c @@ -31,7 +31,6 @@ #include "config.h" #include #include -#include #include "mutt/lib.h" #include "attr.h" #include "color.h" @@ -71,7 +70,7 @@ void merged_colors_cleanup(void) * @param attrs Attributes, e.g. A_UNDERLINE * @retval ptr Matching Merged colour */ -static struct AttrColor *merged_colors_find(int fg, int bg, int attrs) +static struct AttrColor *merged_colors_find(color_t fg, color_t bg, int attrs) { struct AttrColor *ac = NULL; TAILQ_FOREACH(ac, &MergedColors, entries) @@ -117,8 +116,8 @@ const struct AttrColor *merged_color_overlay(const struct AttrColor *base, struct CursesColor *cc_base = base->curses_color; struct CursesColor *cc_over = over->curses_color; - uint32_t fg = COLOR_DEFAULT; - uint32_t bg = COLOR_DEFAULT; + color_t fg = COLOR_DEFAULT; + color_t bg = COLOR_DEFAULT; if (cc_over) { diff --git a/color/quoted.c b/color/quoted.c index aeebd5441..135e28f8d 100644 --- a/color/quoted.c +++ b/color/quoted.c @@ -29,7 +29,6 @@ #include "config.h" #include #include -#include #include "mutt/lib.h" #include "core/lib.h" #include "quoted.h" @@ -103,7 +102,7 @@ int quoted_colors_num_used(void) * @param err Buffer for error messages * @retval true Colour was parsed */ -bool quoted_colors_parse_color(enum ColorId cid, uint32_t fg, uint32_t bg, +bool quoted_colors_parse_color(enum ColorId cid, color_t fg, color_t bg, int attrs, int q_level, int *rc, struct Buffer *err) { if (cid != MT_COLOR_QUOTED) diff --git a/color/quoted.h b/color/quoted.h index 611071d12..ccca2c4cb 100644 --- a/color/quoted.h +++ b/color/quoted.h @@ -26,10 +26,10 @@ #include "config.h" #include #include -#include #include "core/lib.h" #include "attr.h" #include "color.h" +#include "curses2.h" struct Buffer; @@ -78,7 +78,7 @@ void quoted_colors_cleanup(void); struct AttrColor * quoted_colors_get(int q); int quoted_colors_num_used(void); -bool quoted_colors_parse_color (enum ColorId cid, uint32_t fg, uint32_t bg, int attrs, int q_level, int *rc, struct Buffer *err); +bool quoted_colors_parse_color (enum ColorId cid, color_t fg, color_t bg, int attrs, int q_level, int *rc, struct Buffer *err); enum CommandResult quoted_colors_parse_uncolor(enum ColorId cid, int q_level, struct Buffer *err); struct QuoteStyle *qstyle_classify (struct QuoteStyle **quote_list, const char *qptr, size_t length, bool *force_redraw, int *q_level); diff --git a/color/regex.c b/color/regex.c index c8a1f5978..28775e6ae 100644 --- a/color/regex.c +++ b/color/regex.c @@ -237,7 +237,7 @@ struct RegexColorList *regex_colors_get_list(enum ColorId cid) * called from mutt_parse_color() */ static enum CommandResult add_pattern(struct RegexColorList *rcl, const char *s, - bool sensitive, uint32_t fg, uint32_t bg, int attrs, + bool sensitive, color_t fg, color_t bg, int attrs, struct Buffer *err, bool is_index, int match) { struct RegexColor *rcol = NULL; @@ -337,8 +337,8 @@ static enum CommandResult add_pattern(struct RegexColorList *rcl, const char *s, * * Parse a Regex 'color' command, e.g. "color index green default pattern" */ -bool regex_colors_parse_color_list(enum ColorId cid, const char *pat, uint32_t fg, - uint32_t bg, int attrs, int *rc, struct Buffer *err) +bool regex_colors_parse_color_list(enum ColorId cid, const char *pat, color_t fg, + color_t bg, int attrs, int *rc, struct Buffer *err) { if (cid == MT_COLOR_STATUS) @@ -407,8 +407,8 @@ bool regex_colors_parse_color_list(enum ColorId cid, const char *pat, uint32_t f * @param err Buffer for error messages * @retval #CommandResult Result e.g. #MUTT_CMD_SUCCESS */ -int regex_colors_parse_status_list(enum ColorId cid, const char *pat, uint32_t fg, - uint32_t bg, int attrs, int match, struct Buffer *err) +int regex_colors_parse_status_list(enum ColorId cid, const char *pat, color_t fg, + color_t bg, int attrs, int match, struct Buffer *err) { if (cid != MT_COLOR_STATUS) return MUTT_CMD_ERROR; diff --git a/color/regex4.h b/color/regex4.h index d948ed9cc..dea7fc50d 100644 --- a/color/regex4.h +++ b/color/regex4.h @@ -25,10 +25,10 @@ #include "config.h" #include -#include #include "mutt/lib.h" #include "attr.h" #include "color.h" +#include "curses2.h" /** * struct RegexColor - A regular expression and a color to highlight a line @@ -43,7 +43,7 @@ struct RegexColor bool stop_matching : 1; ///< Used by the pager for body patterns, to prevent the color from being retried once it fails - STAILQ_ENTRY(RegexColor) entries; ///< Linked list + STAILQ_ENTRY(RegexColor) entries; ///< Linked list }; STAILQ_HEAD(RegexColorList, RegexColor); @@ -57,8 +57,8 @@ void regex_colors_init(void); void regex_color_list_clear(struct RegexColorList *rcl); -bool regex_colors_parse_color_list (enum ColorId cid, const char *pat, uint32_t fg, uint32_t bg, int attrs, int *rc, struct Buffer *err); -int regex_colors_parse_status_list(enum ColorId cid, const char *pat, uint32_t fg, uint32_t bg, int attrs, int match, struct Buffer *err); +bool regex_colors_parse_color_list (enum ColorId cid, const char *pat, color_t fg, color_t bg, int attrs, int *rc, struct Buffer *err); +int regex_colors_parse_status_list(enum ColorId cid, const char *pat, color_t fg, color_t bg, int attrs, int match, struct Buffer *err); bool regex_colors_parse_uncolor (enum ColorId cid, const char *pat, bool uncolor); #endif /* MUTT_COLOR_REGEX4_H */ diff --git a/color/simple.c b/color/simple.c index bb1aec3c9..cdf57db7a 100644 --- a/color/simple.c +++ b/color/simple.c @@ -122,7 +122,7 @@ bool simple_color_is_header(enum ColorId cid) * @param attrs Attributes, e.g. A_UNDERLINE * @retval ptr Colour */ -struct AttrColor *simple_color_set(enum ColorId cid, int fg, int bg, int attrs) +struct AttrColor *simple_color_set(enum ColorId cid, color_t fg, color_t bg, int attrs) { struct AttrColor *ac = simple_color_get(cid); if (!ac) diff --git a/color/simple2.h b/color/simple2.h index b250eca45..62fcab464 100644 --- a/color/simple2.h +++ b/color/simple2.h @@ -27,6 +27,7 @@ #include #include "attr.h" #include "color.h" +#include "curses2.h" extern struct AttrColor SimpleColors[]; @@ -34,7 +35,7 @@ struct AttrColor *simple_color_get (enum ColorId cid); bool simple_color_is_header(enum ColorId cid); bool simple_color_is_set (enum ColorId cid); void simple_color_reset (enum ColorId cid); -struct AttrColor *simple_color_set (enum ColorId cid, int fg, int bg, int attrs); +struct AttrColor *simple_color_set (enum ColorId cid, color_t fg, color_t bg, int attrs); void simple_colors_cleanup(void); void simple_colors_init(void); -- cgit v1.2.3 From a33ad01e25ac20495a1426de95e406dc8494ca72 Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Tue, 10 Oct 2023 12:32:03 +0100 Subject: color: drop COLOR_UNSET Some code was using COLOR_UNSET, but elsewhere code used COLOR_DEFAULT. Since they mean the same, only use COLOR_DEFAULT (-1), which is what ncurses is expecting. --- color/color.h | 3 +-- color/command.c | 13 ++++++++++--- color/curses.c | 8 +------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/color/color.h b/color/color.h index b280889a5..b13a75892 100644 --- a/color/color.h +++ b/color/color.h @@ -100,8 +100,7 @@ extern const struct Mapping ColorNames[]; extern const struct Mapping ColorFields[]; extern const struct Mapping ComposeColorFields[]; -#define COLOR_DEFAULT (-2) -#define COLOR_UNSET UINT32_MAX +#define COLOR_DEFAULT -1 void mutt_colors_init(void); void mutt_colors_cleanup(void); diff --git a/color/command.c b/color/command.c index c02b50520..03366e4f5 100644 --- a/color/command.c +++ b/color/command.c @@ -363,8 +363,15 @@ static enum CommandResult parse_color_namedcolor(const char *s, color_t *col, in enum ColorPrefix prefix = COLOR_PREFIX_NONE; s += parse_color_prefix(s, &prefix); - if ((*col = mutt_map_get_value(s, ColorNames)) == -1) + // COLOR_DEFAULT (-1) interferes with mutt_map_get_value() + if (mutt_str_equal(s, "default")) + { + *col = COLOR_DEFAULT; + } + else if ((*col = mutt_map_get_value(s, ColorNames)) == -1) + { return MUTT_CMD_WARNING; + } const char *name = mutt_map_get_name(*col, ColorNames); if (name) @@ -542,9 +549,9 @@ static enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s, struct Buffer *err) { if (fg) - *fg = COLOR_UNSET; + *fg = COLOR_DEFAULT; if (bg) - *bg = COLOR_UNSET; + *bg = COLOR_DEFAULT; if (!MoreArgs(s)) { diff --git a/color/curses.c b/color/curses.c index a3bed5338..3af271946 100644 --- a/color/curses.c +++ b/color/curses.c @@ -98,11 +98,6 @@ static int curses_color_init(color_t fg, color_t bg) return 0; } - if (fg == COLOR_DEFAULT) - fg = COLOR_UNSET; - if (bg == COLOR_DEFAULT) - bg = COLOR_UNSET; - #ifdef NEOMUTT_DIRECT_COLORS int rc = init_extended_pair(index, fg, bg); color_debug(LL_DEBUG5, "init_extended_pair(%d,%d,%d) -> %d\n", index, fg, bg, rc); @@ -151,8 +146,7 @@ void curses_color_free(struct CursesColor **ptr) struct CursesColor *curses_color_new(color_t fg, color_t bg) { color_debug(LL_DEBUG5, "fg %d, bg %d\n", fg, bg); - if (((fg == COLOR_UNSET) && (bg == COLOR_UNSET)) || - ((fg == COLOR_DEFAULT) && (bg == COLOR_DEFAULT))) + if ((fg == COLOR_DEFAULT) && (bg == COLOR_DEFAULT)) { color_debug(LL_DEBUG5, "both unset\n"); return NULL; -- cgit v1.2.3 From d6c50a69943e1749a43eab095819b0980ce55f56 Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Sun, 15 Oct 2023 01:13:03 +0100 Subject: color: split out ANSI parsing code Move the pure ANSI parsing functions into a separate file so that they can be tested. - ansi_color_parse_single() - ansi_color_seq_length() - ansi_is_end_char() - ansi_skip_sequence() --- Makefile.autosetup | 3 +- color/ansi.c | 225 +--------------------------------------------- color/color.h | 1 - color/lib.h | 2 + color/parse_ansi.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++ color/parse_ansi.h | 35 ++++++++ debug/lib.h | 1 + 7 files changed, 301 insertions(+), 226 deletions(-) create mode 100644 color/parse_ansi.c create mode 100644 color/parse_ansi.h diff --git a/Makefile.autosetup b/Makefile.autosetup index ec158febb..2b731687a 100644 --- a/Makefile.autosetup +++ b/Makefile.autosetup @@ -181,7 +181,8 @@ $(PWD)/browser: # libcolor LIBCOLOR= libcolor.a LIBCOLOROBJS= color/ansi.o color/attr.o color/color.o color/command.o \ - color/curses.o color/merged.o color/notify.o color/quoted.o \ + color/curses.o color/merged.o color/notify.o \ + color/parse_ansi.o color/quoted.o \ color/regex.o color/simple.o @if USE_DEBUG_COLOR LIBCOLOROBJS+= color/debug.o diff --git a/color/ansi.c b/color/ansi.c index 676c7b790..eb0b075a3 100644 --- a/color/ansi.c +++ b/color/ansi.c @@ -27,10 +27,7 @@ */ #include "config.h" -#include -#include #include -#include #include "mutt/lib.h" #include "gui/lib.h" #include "ansi.h" @@ -38,229 +35,9 @@ #include "color.h" #include "curses2.h" #include "debug.h" +#include "parse_ansi.h" #include "simple2.h" -/** - * ansi_is_end_char - Is this the end of a sequence? - * @param c Character to test - * @retval true Is it a valid end char - */ -static inline bool ansi_is_end_char(char c) -{ - return ((c == 'm') || (c == ';')); -} - -/** - * ansi_skip_sequence - Skip an unrecognised sequence - * @param str String to examine - * @retval num Number of characters to skip over - */ -static int ansi_skip_sequence(const char *str) -{ - if (!str || (str[0] == '\0')) - return 0; - - int count = 1; - while ((str[0] != '\0') && !ansi_is_end_char(str[0])) - { - str++; - count++; - } - - return count; -} - -/** - * ansi_color_seq_length - Is this an ANSI escape sequence? - * @param str String to test - * @retval 0 No, not an ANSI sequence - * @retval >0 Length of the ANSI sequence - * - * Match ANSI escape sequences of type 'm', e.g. - * - `[1;32m` - */ -int ansi_color_seq_length(const char *str) -{ - if (!str || !*str) - return 0; - - if ((str[0] != '\033') || (str[1] != '[')) // Escape - return 0; - - int i = 2; - while ((str[i] != '\0') && (isdigit(str[i]) || (str[i] == ';'))) - { - i++; - } - - if (str[i] == 'm') - return i + 1; - - return 0; -} - -/** - * ansi_color_parse_single - Parse a single ANSI escape sequence - * @param buf String to parse - * @param ansi AnsiColor for the result - * @param dry_run Don't parse anything, just skip over - * @retval num Length of the escape sequence - * - * Parse an ANSI escape sequence into @a ansi. - * Calling this function repeatedly, will accumulate sequences in @a ansi. - */ -static int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool dry_run) -{ - int seq_len = ansi_color_seq_length(buf); - if (seq_len == 0) - return 0; - - if (dry_run || !ansi) - return seq_len; - - int pos = 2; // Skip '[' - - while (pos < seq_len) - { - if ((buf[pos] == '0') && isdigit(buf[pos + 1])) - { - pos++; // Skip the leading zero - } - else if ((buf[pos] == '0') && ansi_is_end_char(buf[pos + 1])) - { - ansi->fg = COLOR_DEFAULT; - ansi->bg = COLOR_DEFAULT; - ansi->attrs = 0; - ansi->attr_color = NULL; - pos += 2; - } - else if ((buf[pos] == '1') && ansi_is_end_char(buf[pos + 1])) - { - ansi->attrs |= A_BOLD; - pos += 2; - } - else if ((buf[pos] == '3') && ansi_is_end_char(buf[pos + 1])) - { - ansi->attrs |= A_ITALIC; - pos += 2; - } - else if (buf[pos] == '3') - { - // 30-37 basic foreground - if ((buf[pos + 1] >= '0') && (buf[pos + 1] < '8') && ansi_is_end_char(buf[pos + 2])) - { - ansi->fg = buf[pos + 1] - '0'; - pos += 3; - } - else if (buf[pos + 1] == '8') - { - if (mutt_str_startswith(buf + pos, "38;5;") && isdigit(buf[pos + 5])) - { - // 38;5;n palette foreground - char *end = NULL; - int value = strtoul(buf + pos + 5, &end, 10); - if ((value >= 0) && (value < 256) && end && ansi_is_end_char(end[0])) - { - ansi->fg = value; - pos += end - &buf[pos]; - } - else - { - pos += ansi_skip_sequence(buf + pos); - } - } - else if (mutt_str_startswith(buf + pos, "38;2;") && isdigit(buf[pos + 5])) - { - // 38;2;R;G;B true colour foreground - pos += ansi_skip_sequence(buf + pos + 5); - pos += ansi_skip_sequence(buf + pos); - pos += ansi_skip_sequence(buf + pos); - } - else - { - return pos; - } - } - else if ((buf[pos + 1] == '9') && ansi_is_end_char(buf[pos + 2])) - { - // default fg - ansi->fg = COLOR_DEFAULT; - pos += 2; - } - else - { - pos += ansi_skip_sequence(buf + pos); - } - } - else if ((buf[pos] == '4') && ansi_is_end_char(buf[pos + 1])) - { - ansi->attrs |= A_UNDERLINE; - pos += 2; - } - else if (buf[pos] == '4') - { - // 40-47 basic background - if ((buf[pos + 1] >= '0') && (buf[pos + 1] < '8')) - { - ansi->bg = buf[pos + 1] - '0'; - pos += 3; - } - else if (buf[pos + 1] == '8') - { - if (mutt_str_startswith(buf + pos, "48;5;") && isdigit(buf[pos + 5])) - { - // 48;5;n palette background - char *end = NULL; - int value = strtoul(buf + pos + 5, &end, 10); - if ((value >= 0) && (value < 256) && end && ansi_is_end_char(end[0])) - { - ansi->bg = value; - pos += end - &buf[pos]; - } - else - { - pos += ansi_skip_sequence(buf + pos); - } - } - else if (mutt_str_startswith(buf + pos, "48;2;") && isdigit(buf[pos + 5])) - { - // 48;2;R;G;B true colour background - pos += ansi_skip_sequence(buf + pos + 5); - pos += ansi_skip_sequence(buf + pos); - pos += ansi_skip_sequence(buf + pos); - } - else - { - pos += ansi_skip_sequence(buf + pos); - } - } - else if ((buf[pos + 1] == '9') && ansi_is_end_char(buf[pos + 2])) - { - // default background - ansi->bg = COLOR_DEFAULT; - pos += 2; - } - } - else if ((buf[pos] == '5') && ansi_is_end_char(buf[pos + 1])) - { - ansi->attrs |= A_BLINK; - pos += 2; - } - else if ((buf[pos] == '7') && ansi_is_end_char(buf[pos + 1])) - { - ansi->attrs |= A_REVERSE; - pos += 2; - } - else - { - while ((pos < seq_len) && (buf[pos] != ';')) - pos++; - } - } - - return pos; -} - /** * ansi_color_list_add - Add an Ansi colour to the list * @param acl List of unique colours diff --git a/color/color.h b/color/color.h index b13a75892..fd29263b6 100644 --- a/color/color.h +++ b/color/color.h @@ -27,7 +27,6 @@ #include "config.h" #include "mutt/lib.h" #include -#include /** * enum ColorId - List of all colored objects diff --git a/color/lib.h b/color/lib.h index 29d1a09c3..41dcaa05d 100644 --- a/color/lib.h +++ b/color/lib.h @@ -35,6 +35,7 @@ * | color/debug.c | @subpage color_debug | * | color/merged.c | @subpage color_merge | * | color/notify.c | @subpage color_notify | + * | color/parse_ansi.c | @subpage color_parse_ansi | * | color/quoted.c | @subpage color_quote | * | color/regex.c | @subpage color_regex | * | color/simple.c | @subpage color_simple | @@ -52,6 +53,7 @@ #include "debug.h" #include "merged.h" #include "notify2.h" +#include "parse_ansi.h" #include "quoted.h" #include "regex4.h" #include "simple2.h" diff --git a/color/parse_ansi.c b/color/parse_ansi.c new file mode 100644 index 000000000..1544e712b --- /dev/null +++ b/color/parse_ansi.c @@ -0,0 +1,260 @@ +/** + * @file + * Parse ANSI Sequences + * + * @authors + * Copyright (C) 2023 Richard Russon + * + * @copyright + * 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, see . + */ + +/** + * @page color_parse_ansi Parse ANSI Sequences + * + * Parse ANSI Sequences + */ + +#include "config.h" +#include +#include +#include +#include +#include "mutt/lib.h" +#include "gui/lib.h" +#include "parse_ansi.h" +#include "ansi.h" +#include "color.h" + + +/** + * ansi_is_end_char - Is this the end of a sequence? + * @param c Character to test + * @retval true Is it a valid end char + */ +static inline bool ansi_is_end_char(char c) +{ + return ((c == 'm') || (c == ';')); +} + +/** + * ansi_skip_sequence - Skip an unrecognised sequence + * @param str String to examine + * @retval num Number of characters to skip over + */ +int ansi_skip_sequence(const char *str) +{ + if (!str || (str[0] == '\0')) + return 0; + + int count = 1; + while ((str[0] != '\0') && !ansi_is_end_char(str[0])) + { + str++; + count++; + } + + return count; +} + +/** + * ansi_color_seq_length - Is this an ANSI escape sequence? + * @param str String to test + * @retval 0 No, not an ANSI sequence + * @retval >0 Length of the ANSI sequence + * + * Match ANSI escape sequences of type 'm', e.g. + * - `[1;32m` + */ +int ansi_color_seq_length(const char *str) +{ + if (!str || !*str) + return 0; + + if ((str[0] != '\033') || (str[1] != '[')) // Escape + return 0; + + int i = 2; + while ((str[i] != '\0') && (isdigit(str[i]) || (str[i] == ';'))) + { + i++; + } + + if (str[i] == 'm') + return i + 1; + + return 0; +} + +/** + * ansi_color_parse_single - Parse a single ANSI escape sequence + * @param buf String to parse + * @param ansi AnsiColor for the result + * @param dry_run Don't parse anything, just skip over + * @retval num Length of the escape sequence + * + * Parse an ANSI escape sequence into @a ansi. + * Calling this function repeatedly, will accumulate sequences in @a ansi. + */ +int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool dry_run) +{ + int seq_len = ansi_color_seq_length(buf); + if (seq_len == 0) + return 0; + + if (dry_run || !ansi) + return seq_len; + + int pos = 2; // Skip '[' + + while (pos < seq_len) + { + if ((buf[pos] == '0') && isdigit(buf[pos + 1])) + { + pos++; // Skip the leading zero + } + else if ((buf[pos] == '0') && ansi_is_end_char(buf[pos + 1])) + { + ansi->fg = COLOR_DEFAULT; + ansi->bg = COLOR_DEFAULT; + ansi->attrs = 0; + ansi->attr_color = NULL; + pos += 2; + } + else if ((buf[pos] == '1') && ansi_is_end_char(buf[pos + 1])) + { + ansi->attrs |= A_BOLD; + pos += 2; + } + else if ((buf[pos] == '3') && ansi_is_end_char(buf[pos + 1])) + { + ansi->attrs |= A_ITALIC; + pos += 2; + } + else if (buf[pos] == '3') + { + // 30-37 basic foreground + if ((buf[pos + 1] >= '0') && (buf[pos + 1] < '8') && ansi_is_end_char(buf[pos + 2])) + { + ansi->fg = buf[pos + 1] - '0'; + pos += 3; + } + else if (buf[pos + 1] == '8') + { + if (mutt_str_startswith(buf + pos, "38;5;") && isdigit(buf[pos + 5])) + { + // 38;5;n palette foreground + char *end = NULL; + int value = strtoul(buf + pos + 5, &end, 10); + if ((value >= 0) && (value < 256) && end && ansi_is_end_char(end[0])) + { + ansi->fg = value; + pos += end - &buf[pos]; + } + else + { + pos += ansi_skip_sequence(buf + pos); + } + } + else if (mutt_str_startswith(buf + pos, "38;2;") && isdigit(buf[pos + 5])) + { + // 38;2;R;G;B true colour foreground + pos += ansi_skip_sequence(buf + pos + 5); + pos += ansi_skip_sequence(buf + pos); + pos += ansi_skip_sequence(buf + pos); + } + else + { + return pos; + } + } + else if ((buf[pos + 1] == '9') && ansi_is_end_char(buf[pos + 2])) + { + // default fg + ansi->fg = COLOR_DEFAULT; + pos += 2; + } + else + { + pos += ansi_skip_sequence(buf + pos); + } + } + else if ((buf[pos] == '4') && ansi_is_end_char(buf[pos + 1])) + { + ansi->attrs |= A_UNDERLINE; + pos += 2; + } + else if (buf[pos] == '4') + { + // 40-47 basic background + if ((buf[pos + 1] >= '0') && (buf[pos + 1] < '8')) + { + ansi->bg = buf[pos + 1] - '0'; + pos += 3; + } + else if (buf[pos + 1] == '8') + { + if (mutt_str_startswith(buf + pos, "48;5;") && isdigit(buf[pos + 5])) + { + // 48;5;n palette background + char *end = NULL; + int value = strtoul(buf + pos + 5, &end, 10); + if ((value >= 0) && (value < 256) && end && ansi_is_end_char(end[0])) + { + ansi->bg = value; + pos += end - &buf[pos]; + } + else + { + pos += ansi_skip_sequence(buf + pos); + } + } + else if (mutt_str_startswith(buf + pos, "48;2;") && isdigit(buf[pos + 5])) + { + // 48;2;R;G;B true colour background + pos += ansi_skip_sequence(buf + pos + 5); + pos += ansi_skip_sequence(buf + pos); + pos += ansi_skip_sequence(buf + pos); + } + else + { + pos += ansi_skip_sequence(buf + pos); + } + } + else if ((buf[pos + 1] == '9') && ansi_is_end_char(buf[pos + 2])) + { + // default background + ansi->bg = COLOR_DEFAULT; + pos += 2; + } + } + else if ((buf[pos] == '5') && ansi_is_end_char(buf[pos + 1])) + { + ansi->attrs |= A_BLINK; + pos += 2; + } + else if ((buf[pos] == '7') && ansi_is_end_char(buf[pos + 1])) + { + ansi->attrs |= A_REVERSE; + pos += 2; + } + else + { + while ((pos < seq_len) && (buf[pos] != ';')) + pos++; + } + } + + return pos; +} diff --git a/color/parse_ansi.h b/color/parse_ansi.h new file mode 100644 index 000000000..599335a7f --- /dev/null +++ b/color/parse_ansi.h @@ -0,0 +1,35 @@ +/** + * @file + * Parse ANSI Sequences + * + * @authors + * Copyright (C) 2023 Richard Russon + * + * @copyright + * 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, see . + */ + +#ifndef MUTT_COLOR_PARSE_ANSI_H +#define MUTT_COLOR_PARSE_ANSI_H + +#include + +struct AnsiColor; + +int ansi_color_parse_single(const char *buf, struct AnsiColor *ansi, bool dry_run); +int ansi_color_seq_length (const char *str); + +#endif /* MUTT_COLOR_PARSE_ANSI_H */ + + diff --git a/debug/lib.h b/debug/lib.h index 37b76d724..4990111e3 100644 --- a/debug/lib.h +++ b/debug/lib.h @@ -43,6 +43,7 @@ #include #include +#include #include "mutt/lib.h" #include "email/lib.h" #include "core/lib.h" -- cgit v1.2.3 From 58a490842702d70c178d91c3c4d361597a2081a3 Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Sat, 14 Oct 2023 15:00:47 +0100 Subject: color: split out Colour parsing code Move the pure Colour parsing functions into a separate file so that they can be tested. - parse_attr_spec() - parse_color_colornnn() - parse_color_name() - parse_color_namedcolor() - parse_color_pair() - parse_color_prefix() - parse_color_rrggbb() --- Makefile.autosetup | 2 +- color/attr.h | 11 ++ color/color.c | 16 --- color/color.h | 1 - color/command.c | 329 +--------------------------------------------- color/lib.h | 2 + color/parse_color.c | 365 ++++++++++++++++++++++++++++++++++++++++++++++++++++ color/parse_color.h | 34 +++++ 8 files changed, 419 insertions(+), 341 deletions(-) create mode 100644 color/parse_color.c create mode 100644 color/parse_color.h diff --git a/Makefile.autosetup b/Makefile.autosetup index 2b731687a..908727e2d 100644 --- a/Makefile.autosetup +++ b/Makefile.autosetup @@ -182,7 +182,7 @@ $(PWD)/browser: LIBCOLOR= libcolor.a LIBCOLOROBJS= color/ansi.o color/attr.o color/color.o color/command.o \ color/curses.o color/merged.o color/notify.o \ - color/parse_ansi.o color/quoted.o \ + color/parse_ansi.o color/parse_color.o color/quoted.o \ color/regex.o color/simple.o @if USE_DEBUG_COLOR LIBCOLOROBJS+= color/debug.o diff --git a/color/attr.h b/color/attr.h index 1657c2efd..9d6e2970a 100644 --- a/color/attr.h +++ b/color/attr.h @@ -28,6 +28,17 @@ #include "mutt/lib.h" #include "curses2.h" +/** + * ColorPrefix - Constants for colour prefixes of named colours + */ +enum ColorPrefix +{ + COLOR_PREFIX_NONE, ///< no prefix + COLOR_PREFIX_ALERT, ///< "alert" colour prefix + COLOR_PREFIX_BRIGHT, ///< "bright" colour prefix + COLOR_PREFIX_LIGHT, ///< "light" colour prefix +}; + /** * struct AttrColor - A curses colour and its attributes */ diff --git a/color/color.c b/color/color.c index 947bbb689..7db81983c 100644 --- a/color/color.c +++ b/color/color.c @@ -42,22 +42,6 @@ #include "regex4.h" #include "simple2.h" -/// Mapping between a colour name and an ncurses colour -const struct Mapping ColorNames[] = { - // clang-format off - { "black", COLOR_BLACK }, - { "blue", COLOR_BLUE }, - { "cyan", COLOR_CYAN }, - { "green", COLOR_GREEN }, - { "magenta", COLOR_MAGENTA }, - { "red", COLOR_RED }, - { "white", COLOR_WHITE }, - { "yellow", COLOR_YELLOW }, - { "default", COLOR_DEFAULT }, - { 0, 0 }, - // clang-format on -}; - /** * colors_cleanup - Reset all the simple, quoted and regex colours */ diff --git a/color/color.h b/color/color.h index fd29263b6..010c982fc 100644 --- a/color/color.h +++ b/color/color.h @@ -95,7 +95,6 @@ enum ColorId MT_COLOR_MAX, }; -extern const struct Mapping ColorNames[]; extern const struct Mapping ColorFields[]; extern const struct Mapping ComposeColorFields[]; diff --git a/color/command.c b/color/command.c index 03366e4f5..67e44d97d 100644 --- a/color/command.c +++ b/color/command.c @@ -31,19 +31,19 @@ #include #include #include -#include #include "mutt/lib.h" -#include "config/lib.h" #include "core/lib.h" #include "gui/lib.h" #include "mutt.h" #include "parse/lib.h" +#include "attr.h" #include "color.h" #include "command2.h" #include "curses2.h" #include "debug.h" #include "globals.h" #include "notify2.h" +#include "parse_color.h" #include "quoted.h" #include "regex4.h" #include "simple2.h" @@ -119,17 +119,6 @@ const struct Mapping ComposeColorFields[] = { // clang-format on }; -/** - * ColorPrefix - Constants for colour prefixes of named colours - */ -enum ColorPrefix -{ - COLOR_PREFIX_NONE, ///< no prefix - COLOR_PREFIX_ALERT, ///< "alert" colour prefix - COLOR_PREFIX_BRIGHT, ///< "bright" colour prefix - COLOR_PREFIX_LIGHT, ///< "light" colour prefix -}; - #ifdef NEOMUTT_DIRECT_COLORS /** * color_xterm256_to_24bit - Convert a xterm color to its RGB value @@ -201,7 +190,7 @@ enum ColorPrefix * | 240 | `#585858` | 241 | `#606060` | 242 | `#666666` | 243 | `#767676` | 244 | `#808080` | 245 | `#8a8a8a` | 246 | `#949494` | 247 | `#9e9e9e` | * | 248 | `#a8a8a8` | 249 | `#b2b2b2` | 250 | `#bcbcbc` | 251 | `#c6c6c6` | 252 | `#d0d0d0` | 253 | `#dadada` | 254 | `#e4e4e4` | 255 | `#eeeeee` | */ -static color_t color_xterm256_to_24bit(const color_t color) +color_t color_xterm256_to_24bit(const color_t color) { static const color_t basic[] = { 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, @@ -272,8 +261,7 @@ static color_t color_xterm256_to_24bit(const color_t color) * @param[in,out] col colour to modify * @param[in,out] attrs attributes to modify */ -static void modify_color_by_prefix(enum ColorPrefix prefix, bool is_fg, - color_t *col, int *attrs) +void modify_color_by_prefix(enum ColorPrefix prefix, bool is_fg, color_t *col, int *attrs) { if (prefix == COLOR_PREFIX_NONE) return; // nothing to do here @@ -311,242 +299,11 @@ static void modify_color_by_prefix(enum ColorPrefix prefix, bool is_fg, } } -/** - * parse_color_prefix - Parse a colour prefix, e.g. "bright" - * @param[in] s String to parse - * @param[out] prefix parsed prefix, see #ColorPrefix - * @retval num Length of the matched prefix - * @retval 0 No prefix matched - * - * If prefixes should be parsed, but their value is irrelevant, NULL can be - * passed as 'prefix'. - */ -static int parse_color_prefix(const char *s, enum ColorPrefix *prefix) -{ - int clen = 0; - - if ((clen = mutt_istr_startswith(s, "bright"))) - { - color_debug(LL_DEBUG5, "bright\n"); - if (prefix) - *prefix = COLOR_PREFIX_BRIGHT; - } - else if ((clen = mutt_istr_startswith(s, "alert"))) - { - color_debug(LL_DEBUG5, "alert\n"); - if (prefix) - *prefix = COLOR_PREFIX_ALERT; - } - else if ((clen = mutt_istr_startswith(s, "light"))) - { - color_debug(LL_DEBUG5, "light\n"); - if (prefix) - *prefix = COLOR_PREFIX_LIGHT; - } - - return clen; -} - -/** - * parse_color_namedcolor - Parse a named colour, e.g. "brightred" - * @param[in] s String to parse - * @param[out] col Number for 'colorNNN' colours - * @param[out] attrs Attributes, e.g. A_UNDERLINE - * @param[in] is_fg true if this is a foreground colour - * @param[out] err Buffer for error messages - * @retval #MUTT_CMD_SUCCESS Colour parsed successfully - * @retval #MUTT_CMD_WARNING Unknown colour, try other parsers - */ -static enum CommandResult parse_color_namedcolor(const char *s, color_t *col, int *attrs, - bool is_fg, struct Buffer *err) -{ - enum ColorPrefix prefix = COLOR_PREFIX_NONE; - s += parse_color_prefix(s, &prefix); - - // COLOR_DEFAULT (-1) interferes with mutt_map_get_value() - if (mutt_str_equal(s, "default")) - { - *col = COLOR_DEFAULT; - } - else if ((*col = mutt_map_get_value(s, ColorNames)) == -1) - { - return MUTT_CMD_WARNING; - } - - const char *name = mutt_map_get_name(*col, ColorNames); - if (name) - color_debug(LL_DEBUG5, "color: %s\n", name); - - modify_color_by_prefix(prefix, is_fg, col, attrs); - -#ifdef NEOMUTT_DIRECT_COLORS - /* If we are running in direct color mode, we must convert the color - * number 0-15 to an RGB value. - * The first 16 colours of the xterm palette correspond to the terminal - * colours. Note that this replace the colour with a predefined RGB value - * and not the RGB value the terminal configured to use. - * - * Note that some colors are "special" e.g. "default" and do not fall in - * the range from 0 to 15. These must not be converted. - */ - const bool c_color_directcolor = cs_subset_bool(NeoMutt->sub, "color_directcolor"); - if (c_color_directcolor && (*col < 16)) - { - *col = color_xterm256_to_24bit(*col); - } -#endif - return MUTT_CMD_SUCCESS; -} - -/** - * parse_color_colornnn - Parse a colorNNN, e.g. "color123". - * @param[in] s String to parse - * @param[out] col Number for 'colorNNN' colours - * @param[out] attrs Attributes, e.g. A_UNDERLINE - * @param[in] is_fg true if this is a foreground colour - * @param[out] err Buffer for error messages - * @retval #MUTT_CMD_SUCCESS Colour parsed successfully - * @retval #MUTT_CMD_WARNING Unknown colour, try other parsers - * @retval #MUTT_CMD_ERROR Error, colour could not be parsed - * - * On #MUTT_CMD_ERROR, an error message will be written to err. - */ -static enum CommandResult parse_color_colornnn(const char *s, color_t *col, int *attrs, - bool is_fg, struct Buffer *err) -{ - /* prefixes bright, alert, light are only allowed for named colours and - * colorNNN for backwards compatibility. */ - enum ColorPrefix prefix = COLOR_PREFIX_NONE; - s += parse_color_prefix(s, &prefix); - - int clen = 0; - /* allow aliases for xterm color resources */ - if ((clen = mutt_istr_startswith(s, "color")) == 0) - return MUTT_CMD_WARNING; - - s += clen; - char *eptr = NULL; - *col = strtoul(s, &eptr, 10); - /* There are only 256 xterm colors. Do not confuse with COLORS which is - * the number of colours the terminal supports (usually one of 16, 256, - * 16777216 (=24bit)). */ - if ((*s == '\0') || (*eptr != '\0') || (*col >= 256) || ((*col >= COLORS) && !OptNoCurses)) - { - buf_printf(err, _("%s: color not supported by term"), s); - return MUTT_CMD_ERROR; - } - - modify_color_by_prefix(prefix, is_fg, col, attrs); - -#ifdef NEOMUTT_DIRECT_COLORS - const bool c_color_directcolor = cs_subset_bool(NeoMutt->sub, "color_directcolor"); - if (c_color_directcolor) - { - /* If we are running in direct color mode, we must convert the xterm - * color numbers 0-255 to an RGB value. */ - *col = color_xterm256_to_24bit(*col); - /* FIXME: The color values 0 to 7 (both inclusive) are still occupied by - * the default terminal colours. As a workaround we round them up to - * #000008 which is the blackest black we can produce. */ - if (*col < 8) - *col = 8; - } -#endif - color_debug(LL_DEBUG5, "colorNNN %d\n", *col); - return MUTT_CMD_SUCCESS; -} - -/** - * parse_color_rrggbb - Parse an RGB colour, e.g. "#12FE45" - * @param[in] s String to parse - * @param[out] col Number for 'colorNNN' colours - * @param[out] attrs Attributes, e.g. A_UNDERLINE - * @param[in] is_fg true if this is a foreground colour - * @param[out] err Buffer for error messages - * @retval #MUTT_CMD_SUCCESS Colour parsed successfully - * @retval #MUTT_CMD_WARNING Unknown colour, try other parsers - * @retval #MUTT_CMD_ERROR Error, colour could not be parsed - * - * On #MUTT_CMD_ERROR, an error message will be written to err. - */ -static enum CommandResult parse_color_rrggbb(const char *s, color_t *col, int *attrs, - bool is_fg, struct Buffer *err) -{ - /* parse #RRGGBB colours */ - if (s[0] != '#') - return MUTT_CMD_WARNING; - -#ifndef NEOMUTT_DIRECT_COLORS - buf_printf(err, _("Direct colors support not compiled in: %s"), s); - return MUTT_CMD_ERROR; -#endif - const bool c_color_directcolor = cs_subset_bool(NeoMutt->sub, "color_directcolor"); - if (!c_color_directcolor) - { - buf_printf(err, _("Direct colors support disabled: %s"), s); - return MUTT_CMD_ERROR; - } - s++; - char *eptr = NULL; - *col = strtoul(s, &eptr, 16); - if ((*s == '\0') || (*eptr != '\0') || ((*col >= COLORS) && !OptNoCurses)) - { - buf_printf(err, _("%s: color not supported by term"), s); - return MUTT_CMD_ERROR; - } - /* FIXME: The color values 0 to 7 (both inclusive) are still occupied by - * the default terminal colours. As a workaround we round them up to - * #000008 which is the blackest black we can produce. */ - if (*col < 8) - *col = 8; - - color_debug(LL_DEBUG5, "#RRGGBB: %d\n", *col); - return MUTT_CMD_SUCCESS; -} - -/** - * parse_color_name - Parse a colour name - * @param[in] s String to parse - * @param[out] col Number for 'colorNNN' colours - * @param[out] attrs Attributes, e.g. A_UNDERLINE - * @param[in] is_fg true if this is a foreground colour - * @param[out] err Buffer for error messages - * @retval #CommandResult Result e.g. #MUTT_CMD_SUCCESS - * - * Parse a colour name, such as "red", "brightgreen", "color123", "#12FE45" - */ -static enum CommandResult parse_color_name(const char *s, color_t *col, int *attrs, - bool is_fg, struct Buffer *err) -{ - mutt_debug(LL_DEBUG5, "Parsing color name: %s\n", s); - - /* Try the different colour syntaxes. A return value of MUTT_CMD_WARNING - * means, we should try the next syntax. */ - enum CommandResult cr; - - /* #RRGGBB */ - cr = parse_color_rrggbb(s, col, attrs, is_fg, err); - if (cr != MUTT_CMD_WARNING) - return cr; - /* color123 */ - cr = parse_color_colornnn(s, col, attrs, is_fg, err); - if (cr != MUTT_CMD_WARNING) - return cr; - /* named color, e.g. "brightred" */ - cr = parse_color_namedcolor(s, col, attrs, is_fg, err); - if (cr != MUTT_CMD_WARNING) - return cr; - - buf_printf(err, _("%s: no such color"), s); - return MUTT_CMD_WARNING; -} - /** * parse_attr_spec - Parse an attribute description - Implements ::parser_callback_t - @ingroup parser_callback_api */ -static enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s, - color_t *fg, color_t *bg, int *attrs, - struct Buffer *err) +enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s, color_t *fg, + color_t *bg, int *attrs, struct Buffer *err) { if (fg) *fg = COLOR_DEFAULT; @@ -598,80 +355,6 @@ static enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s, return MUTT_CMD_SUCCESS; } -/** - * parse_color_pair - Parse a pair of colours - Implements ::parser_callback_t - @ingroup parser_callback_api - * - * Parse a pair of colours, e.g. "red default" - */ -static enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s, - color_t *fg, color_t *bg, int *attrs, - struct Buffer *err) -{ - while (true) - { - if (!MoreArgsF(s, TOKEN_COMMENT)) - { - buf_printf(err, _("%s: too few arguments"), "color"); - return MUTT_CMD_WARNING; - } - - parse_extract_token(buf, s, TOKEN_COMMENT); - - if (mutt_istr_equal("bold", buf->data)) - { - *attrs |= A_BOLD; - color_debug(LL_DEBUG5, "bold\n"); - } - else if (mutt_istr_equal("italic", buf->data)) - { - *attrs |= A_ITALIC; - color_debug(LL_DEBUG5, "italic\n"); - } - else if (mutt_istr_equal("none", buf->data)) - { - *attrs = A_NORMAL; // Use '=' to clear other bits - color_debug(LL_DEBUG5, "none\n"); - } - else if (mutt_istr_equal("normal", buf->data)) - { - *attrs = A_NORMAL; // Use '=' to clear other bits - color_debug(LL_DEBUG5, "normal\n"); - } - else if (mutt_istr_equal("reverse", buf->data)) - { - *attrs |= A_REVERSE; - color_debug(LL_DEBUG5, "reverse\n"); - } - else if (mutt_istr_equal("standout", buf->data)) - { - *attrs |= A_STANDOUT; - color_debug(LL_DEBUG5, "standout\n"); - } - else if (mutt_istr_equal("underline", buf->data)) - { - *attrs |= A_UNDERLINE; - color_debug(LL_DEBUG5, "underline\n"); - } - else - { - enum CommandResult rc = parse_color_name(buf->data, fg, attrs, true, err); - if (rc != MUTT_CMD_SUCCESS) - return rc; - break; - } - } - - if (!MoreArgsF(s, TOKEN_COMMENT)) - { - buf_printf(err, _("%s: too few arguments"), "color"); - return MUTT_CMD_WARNING; - } - - parse_extract_token(buf, s, TOKEN_COMMENT); - - return parse_color_name(buf->data, bg, attrs, false, err); -} - /** * get_colorid_name - Get the name of a color id * @param cid Colour, e.g. #MT_COLOR_HEADER diff --git a/color/lib.h b/color/lib.h index 41dcaa05d..3e44d6de9 100644 --- a/color/lib.h +++ b/color/lib.h @@ -36,6 +36,7 @@ * | color/merged.c | @subpage color_merge | * | color/notify.c | @subpage color_notify | * | color/parse_ansi.c | @subpage color_parse_ansi | + * | color/parse_color.c | @subpage color_parse_color | * | color/quoted.c | @subpage color_quote | * | color/regex.c | @subpage color_regex | * | color/simple.c | @subpage color_simple | @@ -54,6 +55,7 @@ #include "merged.h" #include "notify2.h" #include "parse_ansi.h" +#include "parse_color.h" #include "quoted.h" #include "regex4.h" #include "simple2.h" diff --git a/color/parse_color.c b/color/parse_color.c new file mode 100644 index 000000000..a60ba0605 --- /dev/null +++ b/color/parse_color.c @@ -0,0 +1,365 @@ +/** + * @file + * Parse colours + * + * @authors + * Copyright (C) 2023 Richard Russon + * + * @copyright + * 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, see . + */ + +/** + * @page color_parse_color Parse colours + */ + +#include "config.h" +#include +#include +#include +#include "mutt/lib.h" +#include "config/lib.h" +#include "core/lib.h" +#include "gui/lib.h" +#include "parse_color.h" +#include "parse/lib.h" +#include "attr.h" +#include "color.h" +#include "curses2.h" +#include "debug.h" +#include "globals.h" + +color_t color_xterm256_to_24bit(const color_t color); +void modify_color_by_prefix(enum ColorPrefix prefix, bool is_fg, color_t *col, int *attrs); + +/// Mapping between a colour name and an ncurses colour +const struct Mapping ColorNames[] = { + // clang-format off + { "black", COLOR_BLACK }, + { "blue", COLOR_BLUE }, + { "cyan", COLOR_CYAN }, + { "green", COLOR_GREEN }, + { "magenta", COLOR_MAGENTA }, + { "red", COLOR_RED }, + { "white", COLOR_WHITE }, + { "yellow", COLOR_YELLOW }, + { "default", COLOR_DEFAULT }, + { 0, 0 }, + // clang-format on +}; + +/** + * parse_color_prefix - Parse a colour prefix, e.g. "bright" + * @param[in] s String to parse + * @param[out] prefix parsed prefix, see #ColorPrefix + * @retval num Length of the matched prefix + * @retval 0 No prefix matched + * + * If prefixes should be parsed, but their value is irrelevant, NULL can be + * passed as 'prefix'. + */ +int parse_color_prefix(const char *s, enum ColorPrefix *prefix) +{ + int clen = 0; + + if ((clen = mutt_istr_startswith(s, "bright"))) + { + color_debug(LL_DEBUG5, "bright\n"); + if (prefix) + *prefix = COLOR_PREFIX_BRIGHT; + } + else if ((clen = mutt_istr_startswith(s, "alert"))) + { + color_debug(LL_DEBUG5, "alert\n"); + if (prefix) + *prefix = COLOR_PREFIX_ALERT; + } + else if ((clen = mutt_istr_startswith(s, "light"))) + { + color_debug(LL_DEBUG5, "light\n"); + if (prefix) + *prefix = COLOR_PREFIX_LIGHT; + } + + return clen; +} + +/** + * parse_color_namedcolor - Parse a named colour, e.g. "brightred" + * @param[in] s String to parse + * @param[out] col Number for 'colorNNN' colours + * @param[out] attrs Attributes, e.g. A_UNDERLINE + * @param[in] is_fg true if this is a foreground colour + * @param[out] err Buffer for error messages + * @retval #MUTT_CMD_SUCCESS Colour parsed successfully + * @retval #MUTT_CMD_WARNING Unknown colour, try other parsers + */ +enum CommandResult parse_color_namedcolor(const char *s, color_t *col, int *attrs, + bool is_fg, struct Buffer *err) +{ + enum ColorPrefix prefix = COLOR_PREFIX_NONE; + s += parse_color_prefix(s, &prefix); + + // COLOR_DEFAULT (-1) interferes with mutt_map_get_value() + if (mutt_str_equal(s, "default")) + { + *col = COLOR_DEFAULT; + } + else if ((*col = mutt_map_get_value(s, ColorNames)) == -1) + { + return MUTT_CMD_WARNING; + } + + const char *name = mutt_map_get_name(*col, ColorNames); + if (name) + color_debug(LL_DEBUG5, "color: %s\n", name); + + modify_color_by_prefix(prefix, is_fg, col, attrs); + +#ifdef NEOMUTT_DIRECT_COLORS + /* If we are running in direct color mode, we must convert the color + * number 0-15 to an RGB value. + * The first 16 colours of the xterm palette correspond to the terminal + * colours. Note that this replace the colour with a predefined RGB value + * and not the RGB value the terminal configured to use. + * + * Note that some colors are "special" e.g. "default" and do not fall in + * the range from 0 to 15. These must not be converted. + */ + const bool c_color_directcolor = cs_subset_bool(NeoMutt->sub, "color_directcolor"); + if (c_color_directcolor && (*col < 16)) + { + *col = color_xterm256_to_24bit(*col); + } +#endif + return MUTT_CMD_SUCCESS; +} + +/** + * parse_color_colornnn - Parse a colorNNN, e.g. "color123". + * @param[in] s String to parse + * @param[out] col Number for 'colorNNN' colours + * @param[out] attrs Attributes, e.g. A_UNDERLINE + * @param[in] is_fg true if this is a foreground colour + * @param[out] err Buffer for error messages + * @retval #MUTT_CMD_SUCCESS Colour parsed successfully + * @retval #MUTT_CMD_WARNING Unknown colour, try other parsers + * @retval #MUTT_CMD_ERROR Error, colour could not be parsed + * + * On #MUTT_CMD_ERROR, an error message will be written to err. + */ +enum CommandResult parse_color_colornnn(const char *s, color_t *col, int *attrs, + bool is_fg, struct Buffer *err) +{ + /* prefixes bright, alert, light are only allowed for named colours and + * colorNNN for backwards compatibility. */ + enum ColorPrefix prefix = COLOR_PREFIX_NONE; + s += parse_color_prefix(s, &prefix); + + int clen = 0; + /* allow aliases for xterm color resources */ + if ((clen = mutt_istr_startswith(s, "color")) == 0) + return MUTT_CMD_WARNING; + + s += clen; + char *eptr = NULL; + *col = strtoul(s, &eptr, 10); + /* There are only 256 xterm colors. Do not confuse with COLORS which is + * the number of colours the terminal supports (usually one of 16, 256, + * 16777216 (=24bit)). */ + if ((*s == '\0') || (*eptr != '\0') || (*col >= 256) || ((*col >= COLORS) && !OptNoCurses)) + { + buf_printf(err, _("%s: color not supported by term"), s); + return MUTT_CMD_ERROR; + } + + modify_color_by_prefix(prefix, is_fg, col, attrs); + +#ifdef NEOMUTT_DIRECT_COLORS + const bool c_color_directcolor = cs_subset_bool(NeoMutt->sub, "color_directcolor"); + if (c_color_directcolor) + { + /* If we are running in direct color mode, we must convert the xterm + * color numbers 0-255 to an RGB value. */ + *col = color_xterm256_to_24bit(*col); + /* FIXME: The color values 0 to 7 (both inclusive) are still occupied by + * the default terminal colours. As a workaround we round them up to + * #000008 which is the blackest black we can produce. */ + if (*col < 8) + *col = 8; + } +#endif + color_debug(LL_DEBUG5, "colorNNN %d\n", *col); + return MUTT_CMD_SUCCESS; +} + +/** + * parse_color_rrggbb - Parse an RGB colour, e.g. "#12FE45" + * @param[in] s String to parse + * @param[out] col Number for 'colorNNN' colours + * @param[out] attrs Attributes, e.g. A_UNDERLINE + * @param[in] is_fg true if this is a foreground colour + * @param[out] err Buffer for error messages + * @retval #MUTT_CMD_SUCCESS Colour parsed successfully + * @retval #MUTT_CMD_WARNING Unknown colour, try other parsers + * @retval #MUTT_CMD_ERROR Error, colour could not be parsed + * + * On #MUTT_CMD_ERROR, an error message will be written to err. + */ +enum CommandResult parse_color_rrggbb(const char *s, color_t *col, int *attrs, + bool is_fg, struct Buffer *err) +{ + /* parse #RRGGBB colours */ + if (s[0] != '#') + return MUTT_CMD_WARNING; + +#ifndef NEOMUTT_DIRECT_COLORS + buf_printf(err, _("Direct colors support not compiled in: %s"), s); + return MUTT_CMD_ERROR; +#endif + const bool c_color_directcolor = cs_subset_bool(NeoMutt->sub, "color_directcolor"); + if (!c_color_directcolor) + { + buf_printf(err, _("Direct colors support disabled: %s"), s); + return MUTT_CMD_ERROR; + } + s++; + char *eptr = NULL; + *col = strtoul(s, &eptr, 16); + if ((*s == '\0') || (*eptr != '\0') || ((*col >= COLORS) && !OptNoCurses)) + { + buf_printf(err, _("%s: color not supported by term"), s); + return MUTT_CMD_ERROR; + } + /* FIXME: The color values 0 to 7 (both inclusive) are still occupied by + * the default terminal colours. As a workaround we round them up to + * #000008 which is the blackest black we can produce. */ + if (*col < 8) + *col = 8; + + color_debug(LL_DEBUG5, "#RRGGBB: %d\n", *col); + return MUTT_CMD_SUCCESS; +} + +/** + * parse_color_name - Parse a colour name + * @param[in] s String to parse + * @param[out] col Number for 'colorNNN' colours + * @param[out] attrs Attributes, e.g. A_UNDERLINE + * @param[in] is_fg true if this is a foreground colour + * @param[out] err Buffer for error messages + * @retval #CommandResult Result e.g. #MUTT_CMD_SUCCESS + * + * Parse a colour name, such as "red", "brightgreen", "color123", "#12FE45" + */ +enum CommandResult parse_color_name(const char *s, color_t *col, int *attrs, + bool is_fg, struct Buffer *err) +{ + mutt_debug(LL_DEBUG5, "Parsing color name: %s\n", s); + + /* Try the different colour syntaxes. A return value of MUTT_CMD_WARNING + * means, we should try the next syntax. */ + enum CommandResult cr; + + /* #RRGGBB */ + cr = parse_color_rrggbb(s, col, attrs, is_fg, err); + if (cr != MUTT_CMD_WARNING) + return cr; + + /* color123 */ + cr = parse_color_colornnn(s, col, attrs, is_fg, err); + if (cr != MUTT_CMD_WARNING) + return cr; + + /* named color, e.g. "brightred" */ + cr = parse_color_namedcolor(s, col, attrs, is_fg, err); + if (cr != MUTT_CMD_WARNING) + return cr; + + buf_printf(err, _("%s: no such color"), s); + return MUTT_CMD_WARNING; +} + +/** + * parse_color_pair - Parse a pair of colours - Implements ::parser_callback_t - @ingroup parser_callback_api + * + * Parse a pair of colours, e.g. "red default" + */ +enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s, color_t *fg, + color_t *bg, int *attrs, struct Buffer *err) +{ + while (true) + { + if (!MoreArgsF(s, TOKEN_COMMENT)) + { + buf_printf(err, _("%s: too few arguments"), "color"); + return MUTT_CMD_WARNING; + } + + parse_extract_token(buf, s, TOKEN_COMMENT); + + if (mutt_istr_equal("bold", buf->data)) + { + *attrs |= A_BOLD; + color_debug(LL_DEBUG5, "bold\n"); + } + else if (mutt_istr_equal("italic", buf->data)) + { + *attrs |= A_ITALIC; + color_debug(LL_DEBUG5, "italic\n"); + } + else if (mutt_istr_equal("none", buf->data)) + { + *attrs = A_NORMAL; // Use '=' to clear other bits + color_debug(LL_DEBUG5, "none\n"); + } + else if (mutt_istr_equal("normal", buf->data)) + { + *attrs = A_NORMAL; // Use '=' to clear other bits + color_debug(LL_DEBUG5, "normal\n"); + } + else if (mutt_istr_equal("reverse", buf->data)) + { + *attrs |= A_REVERSE; + color_debug(LL_DEBUG5, "reverse\n"); + } + else if (mutt_istr_equal("standout", buf->data)) + { + *attrs |= A_STANDOUT; + color_debug(LL_DEBUG5, "standout\n"); + } + else if (mutt_istr_equal("underline", buf->data)) + { + *attrs |= A_UNDERLINE; + color_debug(LL_DEBUG5, "underline\n"); + } + else + { + enum CommandResult rc = parse_color_name(buf->data, fg, attrs, true, err); + if (rc != MUTT_CMD_SUCCESS) + return rc; + break; + } + } + + if (!MoreArgsF(s, TOKEN_COMMENT)) + { + buf_printf(err, _("%s: too few arguments"), "color"); + return MUTT_CMD_WARNING; + } + + parse_extract_token(buf, s, TOKEN_COMMENT); + + return parse_color_name(buf->data, bg, attrs, false, err); +} diff --git a/color/parse_color.h b/color/parse_color.h new file mode 100644 index 000000000..92adfa308 --- /dev/null +++ b/color/parse_color.h @@ -0,0 +1,34 @@ +/** + * @file + * Parse colour commands + * + * @authors + * Copyright (C) 2023 Richard Russon + * + * @copyright + * 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, see . + */ + +#ifndef MUTT_COLOR_PARSE_COLOR_H +#define MUTT_COLOR_PARSE_COLOR_H + +#include "core/lib.h" +#include "curses2.h" + +struct Buffer; + +enum CommandResult parse_attr_spec (struct Buffer *buf, struct Buffer *s, color_t *fg, color_t *bg, int *attrs, struct Buffer *err); +enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s, color_t *fg, color_t *bg, int *attrs, struct Buffer *err); + +#endif /* MUTT_COLOR_PARSE_COLOR_H */ -- cgit v1.2.3 From 39f151c665222ba50bd6916119404fe4203cb834 Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Sun, 15 Oct 2023 23:18:31 +0100 Subject: color: move colour helper functions Move two colour helper functions closer to their callers. - color_xterm256_to_24bit() - modify_color_by_prefix() --- color/attr.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++ color/command.c | 180 ---------------------------------------------------- color/parse_ansi.c | 1 - 3 files changed, 182 insertions(+), 181 deletions(-) diff --git a/color/attr.c b/color/attr.c index e616871d7..cc1b06c65 100644 --- a/color/attr.c +++ b/color/attr.c @@ -29,7 +29,9 @@ #include "config.h" #include +#include #include "mutt/lib.h" +#include "gui/lib.h" #include "attr.h" #include "curses2.h" #include "debug.h" @@ -180,3 +182,183 @@ bool attr_color_match(struct AttrColor *ac1, struct AttrColor *ac2) return ((ac1->curses_color == ac2->curses_color) && (ac1->attrs == ac2->attrs)); } + +/** + * modify_color_by_prefix - Modify a colour/attributes based on a prefix, e.g. "bright" + * @param[in] prefix prefix to apply + * @param[in] is_fg true if a foreground colour should be modified + * @param[in,out] col colour to modify + * @param[in,out] attrs attributes to modify + */ +void modify_color_by_prefix(enum ColorPrefix prefix, bool is_fg, color_t *col, int *attrs) +{ + if (prefix == COLOR_PREFIX_NONE) + return; // nothing to do here + + if (prefix == COLOR_PREFIX_ALERT) + { + *attrs |= A_BOLD; + *attrs |= A_BLINK; + } + else if (is_fg) + { + if ((COLORS >= 16) && (prefix == COLOR_PREFIX_LIGHT)) + { + if (*col <= 7) + { + /* Advance the color 0-7 by 8 to get the light version */ + *col += 8; + } + } + else + { + *attrs |= A_BOLD; + } + } + else + { + if (COLORS >= 16) + { + if (*col <= 7) + { + /* Advance the color 0-7 by 8 to get the light version */ + *col += 8; + } + } + } +} + +#ifdef NEOMUTT_DIRECT_COLORS +/** + * color_xterm256_to_24bit - Convert a xterm color to its RGB value + * @param[in] color xterm color number to be converted + * @retval num The color's RGB value as number with value 0xRRGGBB + * + * There are 256 xterm colors numbered 0 to 255. + * + * Caller contract: color must be between 0 and 255. + * + * ## Xterm Color Codes + * + * ### Basic and Bright Colors + * + * - 0-7 correspond to the 8 terminal colours + * - 8-15 are the bright variants of 0-7 + * + * | | | | | | | | | | | | | | | | | + * | :-- | :-------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :- | :------- | :- | :-------- | + * | 0 | `#000000` | 1 | `#800000` | 2 | `#008000` | 3 | `#808000` | 4 | `#000080` | 5 | `#800080` | 6 | `#008080` | 7 | `#c0c0c0` | + * | 8 | `#808080` | 9 | `#ff0000` | 10 | `#00ff00` | 11 | `#ffff00` | 12 | `#0000ff` | 13 | `#ff00ff` | 14 | `#00ffff` | 15 | `#ffffff` | + * + * ### Color palette + * + * | | | | | | | | | | | | | + * | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | + * | 16 | `#000000` | 17 | `#00005f` | 18 | `#000087` | 19 | `#0000af` | 20 | `#0000d7` | 21 | `#0000ff` | + * | 22 | `#005f00` | 23 | `#005f5f` | 24 | `#005f87` | 25 | `#005faf` | 26 | `#005fd7` | 27 | `#005fff` | + * | 28 | `#008700` | 29 | `#00875f` | 30 | `#008787` | 31 | `#0087af` | 32 | `#0087d7` | 33 | `#0087ff` | + * | 34 | `#00af00` | 35 | `#00af5f` | 36 | `#00af87` | 37 | `#00afaf` | 38 | `#00afd7` | 39 | `#00afff` | + * | 40 | `#00d700` | 41 | `#00d75f` | 42 | `#00d787` | 43 | `#00d7af` | 44 | `#00d7d7` | 45 | `#00d7ff` | + * | 46 | `#00ff00` | 47 | `#00ff5f` | 48 | `#00ff87` | 49 | `#00ffaf` | 50 | `#00ffd7` | 51 | `#00ffff` | + * | 52 | `#5f0000` | 53 | `#5f005f` | 54 | `#5f0087` | 55 | `#5f00af` | 56 | `#5f00d7` | 57 | `#5f00ff` | + * | 58 | `#5f5f00` | 59 | `#5f5f5f` | 60 | `#5f5f87` | 61 | `#5f5faf` | 62 | `#5f5fd7` | 63 | `#5f5fff` | + * | 64 | `#5f8700` | 65 | `#5f875f` | 66 | `#5f8787` | 67 | `#5f87af` | 68 | `#5f87d7` | 69 | `#5f87ff` | + * | 70 | `#5faf00` | 71 | `#5faf5f` | 72 | `#5faf87` | 73 | `#5fafaf` | 74 | `#5fafd7` | 75 | `#5fafff` | + * | 76 | `#5fd700` | 77 | `#5fd75f` | 78 | `#5fd787` | 79 | `#5fd7af` | 80 | `#5fd7d7` | 81 | `#5fd7ff` | + * | 82 | `#5fff00` | 83 | `#5fff5f` | 84 | `#5fff87` | 85 | `#5fffaf` | 86 | `#5fffd7` | 87 | `#5fffff` | + * | 88 | `#870000` | 89 | `#87005f` | 90 | `#870087` | 91 | `#8700af` | 92 | `#8700d7` | 93 | `#8700ff` | + * | 94 | `#875f00` | 95 | `#875f5f` | 96 | `#875f87` | 97 | `#875faf` | 98 | `#875fd7` | 99 | `#875fff` | + * | 100 | `#878700` | 101 | `#87875f` | 102 | `#878787` | 103 | `#8787af` | 104 | `#8787d7` | 105 | `#8787ff` | + * | 106 | `#87af00` | 107 | `#87af5f` | 108 | `#87af87` | 109 | `#87afaf` | 110 | `#87afd7` | 111 | `#87afff` | + * | 112 | `#87d700` | 113 | `#87d75f` | 114 | `#87d787` | 115 | `#87d7af` | 116 | `#87d7d7` | 117 | `#87d7ff` | + * | 118 | `#87ff00` | 119 | `#87ff5f` | 120 | `#87ff87` | 121 | `#87ffaf` | 122 | `#87ffd7` | 123 | `#87ffff` | + * | 124 | `#af0000` | 125 | `#af005f` | 126 | `#af0087` | 127 | `#af00af` | 128 | `#af00d7` | 129 | `#af00ff` | + * | 130 | `#af5f00` | 131 | `#af5f5f` | 132 | `#af5f87` | 133 | `#af5faf` | 134 | `#af5fd7` | 135 | `#af5fff` | + * | 136 | `#af8700` | 137 | `#af875f` | 138 | `#af8787` | 139 | `#af87af` | 140 | `#af87d7` | 141 | `#af87ff` | + * | 142 | `#afaf00` | 143 | `#afaf5f` | 144 | `#afaf87` | 145 | `#afafaf` | 146 | `#afafd7` | 147 | `#afafff` | + * | 148 | `#afd700` | 149 | `#afd75f` | 150 | `#afd787` | 151 | `#afd7af` | 152 | `#afd7d7` | 153 | `#afd7ff` | + * | 154 | `#afff00` | 155 | `#afff5f` | 156 | `#afff87` | 157 | `#afffaf` | 158 | `#afffd7` | 159 | `#afffff` | + * | 160 | `#d70000` | 161 | `#d7005f` | 162 | `#d70087` | 163 | `#d700af` | 164 | `#d700d7` | 165 | `#d700ff` | + * | 166 | `#d75f00` | 167 | `#d75f5f` | 168 | `#d75f87` | 169 | `#d75faf` | 170 | `#d75fd7` | 171 | `#d75fff` | + * | 172 | `#d78700` | 173 | `#d7875f` | 174 | `#d78787` | 175 | `#d787af` | 176 | `#d787d7` | 177 | `#d787ff` | + * | 178 | `#d7af00` | 179 | `#d7af5f` | 180 | `#d7af87` | 181 | `#d7afaf` | 182 | `#d7afd7` | 183 | `#d7afff` | + * | 184 | `#d7d700` | 185 | `#d7d75f` | 186 | `#d7d787` | 187 | `#d7d7af` | 188 | `#d7d7d7` | 189 | `#d7d7ff` | + * | 190 | `#d7ff00` | 191 | `#d7ff5f` | 192 | `#d7ff87` | 193 | `#d7ffaf` | 194 | `#d7ffd7` | 195 | `#d7ffff` | + * | 196 | `#ff0000` | 197 | `#ff005f` | 198 | `#ff0087` | 199 | `#ff00af` | 200 | `#ff00d7` | 201 | `#ff00ff` | + * | 202 | `#ff5f00` | 203 | `#ff5f5f` | 204 | `#ff5f87` | 205 | `#ff5faf` | 206 | `#ff5fd7` | 207 | `#ff5fff` | + * | 208 | `#ff8700` | 209 | `#ff875f` | 210 | `#ff8787` | 211 | `#ff87af` | 212 | `#ff87d7` | 213 | `#ff87ff` | + * | 214 | `#ffaf00` | 215 | `#ffaf5f` | 216 | `#ffaf87` | 217 | `#ffafaf` | 218 | `#ffafd7` | 219 | `#ffafff` | + * | 220 | `#ffd700` | 221 | `#ffd75f` | 222 | `#ffd787` | 223 | `#ffd7af` | 224 | `#ffd7d7` | 225 | `#ffd7ff` | + * | 226 | `#ffff00` | 227 | `#ffff5f` | 228 | `#ffff87` | 229 | `#ffffaf` | 230 | `#ffffd7` | 231 | `#ffffff` | + * + * ### Grey Scale Ramp + * + * | | | | | | | | | | | | | | | | | + * | :-- | :-------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :-------- | + * | 232 | `#080808` | 233 | `#121212` | 234 | `#1c1c1c` | 235 | `#262626` | 236 | `#303030` | 237 | `#3a3a3a` | 238 | `#444444` | 239 | `#4e4e4e` | + * | 240 | `#585858` | 241 | `#606060` | 242 | `#666666` | 243 | `#767676` | 244 | `#808080` | 245 | `#8a8a8a` | 246 | `#949494` | 247 | `#9e9e9e` | + * | 248 | `#a8a8a8` | 249 | `#b2b2b2` | 250 | `#bcbcbc` | 251 | `#c6c6c6` | 252 | `#d0d0d0` | 253 | `#dadada` | 254 | `#e4e4e4` | 255 | `#eeeeee` | + */ +color_t color_xterm256_to_24bit(const color_t color) +{ + static const color_t basic[] = { + 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, + 0x008080, 0xc0c0c0, 0x808080, 0xff0000, 0x00ff00, 0xffff00, + 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff, + }; + + assert(color < 256); + + if (color < 0) + return color; + + if (color < 16) + { + color_debug(LL_DEBUG5, "Converted color 0-15: %d\n", color); + /* The first 16 colours are the "usual" terminal colours */ + return basic[color]; + } + + if (color < 232) + { + /* The Color palette is divided in 6x6x6 colours, i.e. each R, G, B channel + * has six values: + * + * value: 1 2 3 4 5 6 + * color: 0x00 0x5f 0x87 0xaf 0xd7 0xff + * + * The steps between the values is 0x28 = 40, the EXCEPT for the first one + * where it is 0x5f = 95. + * + * If we express the xterm color number minus 16 to base 6, i.e. + * + * color - 16 = (vr * 36) + (vg * 6) + (vb * 1) + * + * with vr, vg, vb integers between 0 and 5, then vr, vg, vb is the channel + * value for red, green, and blue, respectively. + */ + + color_t normalised_color = color - 16; + color_t vr = (normalised_color % 216) / 36; /* 216 = 6*6*6 */ + color_t vg = (normalised_color % 36) / 6; + color_t vb = (normalised_color % 6) / 1; + + /* First step is wider than the other ones, so add the difference if needed */ + color_t r = vr * 0x28 + ((vr > 0) ? (0x5f - 0x40) : 0); + color_t g = vg * 0x28 + ((vg > 0) ? (0x5f - 0x40) : 0); + color_t b = vb * 0x28 + ((vb > 0) ? (0x5f - 0x40) : 0); + + color_t rgb = (r << 16) + (g << 8) + (b << 0); + color_debug(LL_DEBUG5, "Converted xterm color %d to RGB #%x:\n", color, rgb); + return rgb; + } + + /* Grey scale starts at 0x08 and adds 0xa = 10 in very step ending in 0xee. + * There are a total of 6*4 = 24 grey colors in total. */ + color_t steps = color - 232; + color_t grey = (steps * 0x0a) + 0x08; + color_t rgb = (grey << 16) + (grey << 8) + (grey << 0); + color_debug(LL_DEBUG5, "Converted xterm color %d to RGB #%x:\n", color, rgb); + return rgb; +} +#endif diff --git a/color/command.c b/color/command.c index 67e44d97d..574772921 100644 --- a/color/command.c +++ b/color/command.c @@ -119,186 +119,6 @@ const struct Mapping ComposeColorFields[] = { // clang-format on }; -#ifdef NEOMUTT_DIRECT_COLORS -/** - * color_xterm256_to_24bit - Convert a xterm color to its RGB value - * @param[in] color xterm color number to be converted - * @retval num The color's RGB value as number with value 0xRRGGBB - * - * There are 256 xterm colors numbered 0 to 255. - * - * Caller contract: color must be between 0 and 255. - * - * ## Xterm Color Codes - * - * ### Basic and Bright Colors - * - * - 0-7 correspond to the 8 terminal colours - * - 8-15 are the bright variants of 0-7 - * - * | | | | | | | | | | | | | | | | | - * | :-- | :-------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :- | :------- | :- | :-------- | - * | 0 | `#000000` | 1 | `#800000` | 2 | `#008000` | 3 | `#808000` | 4 | `#000080` | 5 | `#800080` | 6 | `#008080` | 7 | `#c0c0c0` | - * | 8 | `#808080` | 9 | `#ff0000` | 10 | `#00ff00` | 11 | `#ffff00` | 12 | `#0000ff` | 13 | `#ff00ff` | 14 | `#00ffff` | 15 | `#ffffff` | - * - * ### Color palette - * - * | | | | | | | | | | | | | - * | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | - * | 16 | `#000000` | 17 | `#00005f` | 18 | `#000087` | 19 | `#0000af` | 20 | `#0000d7` | 21 | `#0000ff` | - * | 22 | `#005f00` | 23 | `#005f5f` | 24 | `#005f87` | 25 | `#005faf` | 26 | `#005fd7` | 27 | `#005fff` | - * | 28 | `#008700` | 29 | `#00875f` | 30 | `#008787` | 31 | `#0087af` | 32 | `#0087d7` | 33 | `#0087ff` | - * | 34 | `#00af00` | 35 | `#00af5f` | 36 | `#00af87` | 37 | `#00afaf` | 38 | `#00afd7` | 39 | `#00afff` | - * | 40 | `#00d700` | 41 | `#00d75f` | 42 | `#00d787` | 43 | `#00d7af` | 44 | `#00d7d7` | 45 | `#00d7ff` | - * | 46 | `#00ff00` | 47 | `#00ff5f` | 48 | `#00ff87` | 49 | `#00ffaf` | 50 | `#00ffd7` | 51 | `#00ffff` | - * | 52 | `#5f0000` | 53 | `#5f005f` | 54 | `#5f0087` | 55 | `#5f00af` | 56 | `#5f00d7` | 57 | `#5f00ff` | - * | 58 | `#5f5f00` | 59 | `#5f5f5f` | 60 | `#5f5f87` | 61 | `#5f5faf` | 62 | `#5f5fd7` | 63 | `#5f5fff` | - * | 64 | `#5f8700` | 65 | `#5f875f` | 66 | `#5f8787` | 67 | `#5f87af` | 68 | `#5f87d7` | 69 | `#5f87ff` | - * | 70 | `#5faf00` | 71 | `#5faf5f` | 72 | `#5faf87` | 73 | `#5fafaf` | 74 | `#5fafd7` | 75 | `#5fafff` | - * | 76 | `#5fd700` | 77 | `#5fd75f` | 78 | `#5fd787` | 79 | `#5fd7af` | 80 | `#5fd7d7` | 81 | `#5fd7ff` | - * | 82 | `#5fff00` | 83 | `#5fff5f` | 84 | `#5fff87` | 85 | `#5fffaf` | 86 | `#5fffd7` | 87 | `#5fffff` | - * | 88 | `#870000` | 89 | `#87005f` | 90 | `#870087` | 91 | `#8700af` | 92 | `#8700d7` | 93 | `#8700ff` | - * | 94 | `#875f00` | 95 | `#875f5f` | 96 | `#875f87` | 97 | `#875faf` | 98 | `#875fd7` | 99 | `#875fff` | - * | 100 | `#878700` | 101 | `#87875f` | 102 | `#878787` | 103 | `#8787af` | 104 | `#8787d7` | 105 | `#8787ff` | - * | 106 | `#87af00` | 107 | `#87af5f` | 108 | `#87af87` | 109 | `#87afaf` | 110 | `#87afd7` | 111 | `#87afff` | - * | 112 | `#87d700` | 113 | `#87d75f` | 114 | `#87d787` | 115 | `#87d7af` | 116 | `#87d7d7` | 117 | `#87d7ff` | - * | 118 | `#87ff00` | 119 | `#87ff5f` | 120 | `#87ff87` | 121 | `#87ffaf` | 122 | `#87ffd7` | 123 | `#87ffff` | - * | 124 | `#af0000` | 125 | `#af005f` | 126 | `#af0087` | 127 | `#af00af` | 128 | `#af00d7` | 129 | `#af00ff` | - * | 130 | `#af5f00` | 131 | `#af5f5f` | 132 | `#af5f87` | 133 | `#af5faf` | 134 | `#af5fd7` | 135 | `#af5fff` | - * | 136 | `#af8700` | 137 | `#af875f` | 138 | `#af8787` | 139 | `#af87af` | 140 | `#af87d7` | 141 | `#af87ff` | - * | 142 | `#afaf00` | 143 | `#afaf5f` | 144 | `#afaf87` | 145 | `#afafaf` | 146 | `#afafd7` | 147 | `#afafff` | - * | 148 | `#afd700` | 149 | `#afd75f` | 150 | `#afd787` | 151 | `#afd7af` | 152 | `#afd7d7` | 153 | `#afd7ff` | - * | 154 | `#afff00` | 155 | `#afff5f` | 156 | `#afff87` | 157 | `#afffaf` | 158 | `#afffd7` | 159 | `#afffff` | - * | 160 | `#d70000` | 161 | `#d7005f` | 162 | `#d70087` | 163 | `#d700af` | 164 | `#d700d7` | 165 | `#d700ff` | - * | 166 | `#d75f00` | 167 | `#d75f5f` | 168 | `#d75f87` | 169 | `#d75faf` | 170 | `#d75fd7` | 171 | `#d75fff` | - * | 172 | `#d78700` | 173 | `#d7875f` | 174 | `#d78787` | 175 | `#d787af` | 176 | `#d787d7` | 177 | `#d787ff` | - * | 178 | `#d7af00` | 179 | `#d7af5f` | 180 | `#d7af87` | 181 | `#d7afaf` | 182 | `#d7afd7` | 183 | `#d7afff` | - * | 184 | `#d7d700` | 185 | `#d7d75f` | 186 | `#d7d787` | 187 | `#d7d7af` | 188 | `#d7d7d7` | 189 | `#d7d7ff` | - * | 190 | `#d7ff00` | 191 | `#d7ff5f` | 192 | `#d7ff87` | 193 | `#d7ffaf` | 194 | `#d7ffd7` | 195 | `#d7ffff` | - * | 196 | `#ff0000` | 197 | `#ff005f` | 198 | `#ff0087` | 199 | `#ff00af` | 200 | `#ff00d7` | 201 | `#ff00ff` | - * | 202 | `#ff5f00` | 203 | `#ff5f5f` | 204 | `#ff5f87` | 205 | `#ff5faf` | 206 | `#ff5fd7` | 207 | `#ff5fff` | - * | 208 | `#ff8700` | 209 | `#ff875f` | 210 | `#ff8787` | 211 | `#ff87af` | 212 | `#ff87d7` | 213 | `#ff87ff` | - * | 214 | `#ffaf00` | 215 | `#ffaf5f` | 216 | `#ffaf87` | 217 | `#ffafaf` | 218 | `#ffafd7` | 219 | `#ffafff` | - * | 220 | `#ffd700` | 221 | `#ffd75f` | 222 | `#ffd787` | 223 | `#ffd7af` | 224 | `#ffd7d7` | 225 | `#ffd7ff` | - * | 226 | `#ffff00` | 227 | `#ffff5f` | 228 | `#ffff87` | 229 | `#ffffaf` | 230 | `#ffffd7` | 231 | `#ffffff` | - * - * ### Grey Scale Ramp - * - * | | | | | | | | | | | | | | | | | - * | :-- | :-------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :------- | :-- | :-------- | - * | 232 | `#080808` | 233 | `#121212` | 234 | `#1c1c1c` | 235 | `#262626` | 236 | `#303030` | 237 | `#3a3a3a` | 238 | `#444444` | 239 | `#4e4e4e` | - * | 240 | `#585858` | 241 | `#606060` | 242 | `#666666` | 243 | `#767676` | 244 | `#808080` | 245 | `#8a8a8a` | 246 | `#949494` | 247 | `#9e9e9e` | - * | 248 | `#a8a8a8` | 249 | `#b2b2b2` | 250 | `#bcbcbc` | 251 | `#c6c6c6` | 252 | `#d0d0d0` | 253 | `#dadada` | 254 | `#e4e4e4` | 255 | `#eeeeee` | - */ -color_t color_xterm256_to_24bit(const color_t color) -{ - static const color_t basic[] = { - 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, - 0x008080, 0xc0c0c0, 0x808080, 0xff0000, 0x00ff00, 0xffff00, - 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff, - }; - - assert(color < 256); - - if (color < 0) - return color; - - if (color < 16) - { - color_debug(LL_DEBUG5, "Converted color 0-15: %d\n", color); - /* The first 16 colours are the "usual" terminal colours */ - return basic[color]; - } - - if (color < 232) - { - /* The Color palette is divided in 6x6x6 colours, i.e. each R, G, B channel - * has six values: - * - * value: 1 2 3 4 5 6 - * color: 0x00 0x5f 0x87 0xaf 0xd7 0xff - * - * The steps between the values is 0x28 = 40, the EXCEPT for the first one - * where it is 0x5f = 95. - * - * If we express the xterm color number minus 16 to base 6, i.e. - * - * color - 16 = (vr * 36) + (vg * 6) + (vb * 1) - * - * with vr, vg, vb integers between 0 and 5, then vr, vg, vb is the channel - * value for red, green, and blue, respectively. - */ - - color_t normalised_color = color - 16; - color_t vr = (normalised_color % 216) / 36; /* 216 = 6*6*6 */ - color_t vg = (normalised_color % 36) / 6; - color_t vb = (normalised_color % 6) / 1; - - /* First step is wider than the other ones, so add the difference if needed */ - color_t r = vr * 0x28 + ((vr > 0) ? (0x5f - 0x40) : 0); - color_t g = vg * 0x28 + ((vg > 0) ? (0x5f - 0x40) : 0); - color_t b = vb * 0x28 + ((vb > 0) ? (0x5f - 0x40) : 0); - - color_t rgb = (r << 16) + (g << 8) + (b << 0); - color_debug(LL_DEBUG5, "Converted xterm color %d to RGB #%x:\n", color, rgb); - return rgb; - } - - /* Grey scale starts at 0x08 and adds 0xa = 10 in very step ending in 0xee. - * There are a total of 6*4 = 24 grey colors in total. */ - color_t steps = color - 232; - color_t grey = (steps * 0x0a) + 0x08; - color_t rgb = (grey << 16) + (grey << 8) + (grey << 0); - color_debug(LL_DEBUG5, "Converted xterm color %d to RGB #%x:\n", color, rgb); - return rgb; -} -#endif - -/** - * modify_color_by_prefix - Modify a colour/attributes based on a prefix, e.g. "bright" - * @param[in] prefix prefix to apply - * @param[in] is_fg true if a foreground colour should be modified - * @param[in,out] col colour to modify - * @param[in,out] attrs attributes to modify - */ -void modify_color_by_prefix(enum ColorPrefix prefix, bool is_fg, color_t *col, int *attrs) -{ - if (prefix == COLOR_PREFIX_NONE) - return; // nothing to do here - - if (prefix == COLOR_PREFIX_ALERT) - { - *attrs |= A_BOLD; - *attrs |= A_BLINK; - } - else if (is_fg) - { - if ((COLORS >= 16) && (prefix == COLOR_PREFIX_LIGHT)) - { - if (*col <= 7) - { - /* Advance the color 0-7 by 8 to get the light version */ - *col += 8; - } - } - else - { - *attrs |= A_BOLD; - } - } - else - { - if (COLORS >= 16) - { - if (*col <= 7) - { - /* Advance the color 0-7 by 8 to get the light version */ - *col += 8; - } - } - } -} - /** * parse_attr_spec - Parse an attribute description - Implements ::parser_callback_t - @ingroup parser_callback_api */ diff --git a/color/parse_ansi.c b/color/parse_ansi.c index 1544e712b..d61570875 100644 --- a/color/parse_ansi.c +++ b/color/parse_ansi.c @@ -37,7 +37,6 @@ #include "ansi.h" #include "color.h" - /** * ansi_is_end_char - Is this the end of a sequence? * @param c Character to test -- cgit v1.2.3 From c3a93354b75f4e2e09605b820c40c40e92591d77 Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Mon, 16 Oct 2023 00:58:07 +0100 Subject: color: refactor the attribute handling Refactor the common code out of two attribute handling functions. Create a Mapping table, AttributeNames. - parse_attr_spec() - parse_color_pair() --- color/command.c | 58 --------------------------------- color/parse_color.c | 93 ++++++++++++++++++++++++++++++++--------------------- 2 files changed, 57 insertions(+), 94 deletions(-) diff --git a/color/command.c b/color/command.c index 574772921..85765183d 100644 --- a/color/command.c +++ b/color/command.c @@ -28,7 +28,6 @@ #include "config.h" #include -#include #include #include #include "mutt/lib.h" @@ -36,7 +35,6 @@ #include "gui/lib.h" #include "mutt.h" #include "parse/lib.h" -#include "attr.h" #include "color.h" #include "command2.h" #include "curses2.h" @@ -119,62 +117,6 @@ const struct Mapping ComposeColorFields[] = { // clang-format on }; -/** - * parse_attr_spec - Parse an attribute description - Implements ::parser_callback_t - @ingroup parser_callback_api - */ -enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s, color_t *fg, - color_t *bg, int *attrs, struct Buffer *err) -{ - if (fg) - *fg = COLOR_DEFAULT; - if (bg) - *bg = COLOR_DEFAULT; - - if (!MoreArgs(s)) - { - buf_printf(err, _("%s: too few arguments"), "mono"); - return MUTT_CMD_WARNING; - } - - parse_extract_token(buf, s, TOKEN_NO_FLAGS); - - if (mutt_istr_equal("bold", buf->data)) - { - *attrs |= A_BOLD; - } - else if (mutt_istr_equal("italic", buf->data)) - { - *attrs |= A_ITALIC; - } - else if (mutt_istr_equal("none", buf->data)) - { - *attrs = A_NORMAL; // Use '=' to clear other bits - } - else if (mutt_istr_equal("normal", buf->data)) - { - *attrs = A_NORMAL; // Use '=' to clear other bits - } - else if (mutt_istr_equal("reverse", buf->data)) - { - *attrs |= A_REVERSE; - } - else if (mutt_istr_equal("standout", buf->data)) - { - *attrs |= A_STANDOUT; - } - else if (mutt_istr_equal("underline", buf->data)) - { - *attrs |= A_UNDERLINE; - } - else - { - buf_printf(err, _("%s: no such attribute"), buf->data); - return MUTT_CMD_WARNING; - } - - return MUTT_CMD_SUCCESS; -} - /** * get_colorid_name - Get the name of a color id * @param cid Colour, e.g. #MT_COLOR_HEADER diff --git a/color/parse_color.c b/color/parse_color.c index a60ba0605..2cfa393f9 100644 --- a/color/parse_color.c +++ b/color/parse_color.c @@ -59,6 +59,22 @@ const struct Mapping ColorNames[] = { // clang-format on }; +/** + * AttributeNames - Mapping of attribute names to their IDs + */ +static struct Mapping AttributeNames[] = { + // clang-format off + { "bold", A_BOLD }, + { "italic", A_ITALIC }, + { "none", A_NORMAL }, + { "normal", A_NORMAL }, + { "reverse", A_REVERSE }, + { "standout", A_STANDOUT }, + { "underline", A_UNDERLINE }, + { NULL, 0 }, + // clang-format on +}; + /** * parse_color_prefix - Parse a colour prefix, e.g. "bright" * @param[in] s String to parse @@ -309,48 +325,19 @@ enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s, color_ parse_extract_token(buf, s, TOKEN_COMMENT); - if (mutt_istr_equal("bold", buf->data)) - { - *attrs |= A_BOLD; - color_debug(LL_DEBUG5, "bold\n"); - } - else if (mutt_istr_equal("italic", buf->data)) - { - *attrs |= A_ITALIC; - color_debug(LL_DEBUG5, "italic\n"); - } - else if (mutt_istr_equal("none", buf->data)) - { - *attrs = A_NORMAL; // Use '=' to clear other bits - color_debug(LL_DEBUG5, "none\n"); - } - else if (mutt_istr_equal("normal", buf->data)) - { - *attrs = A_NORMAL; // Use '=' to clear other bits - color_debug(LL_DEBUG5, "normal\n"); - } - else if (mutt_istr_equal("reverse", buf->data)) - { - *attrs |= A_REVERSE; - color_debug(LL_DEBUG5, "reverse\n"); - } - else if (mutt_istr_equal("standout", buf->data)) - { - *attrs |= A_STANDOUT; - color_debug(LL_DEBUG5, "standout\n"); - } - else if (mutt_istr_equal("underline", buf->data)) - { - *attrs |= A_UNDERLINE; - color_debug(LL_DEBUG5, "underline\n"); - } - else + int attr = mutt_map_get_value(buf->data, AttributeNames); + if (attr == -1) { enum CommandResult rc = parse_color_name(buf->data, fg, attrs, true, err); if (rc != MUTT_CMD_SUCCESS) return rc; break; } + + if (attr == A_NORMAL) + *attrs = attr; // Clear all attributes + else + *attrs |= attr; // Merge with other attributes } if (!MoreArgsF(s, TOKEN_COMMENT)) @@ -363,3 +350,37 @@ enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s, color_ return parse_color_name(buf->data, bg, attrs, false, err); } + +/** + * parse_attr_spec - Parse an attribute description - Implements ::parser_callback_t - @ingroup parser_callback_api + */ +enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s, color_t *fg, + color_t *bg, int *attrs, struct Buffer *err) +{ + if (fg) + *fg = COLOR_DEFAULT; + if (bg) + *bg = COLOR_DEFAULT; + + if (!MoreArgs(s)) + { + buf_printf(err, _("%s: too few arguments"), "mono"); + return MUTT_CMD_WARNING; + } + + parse_extract_token(buf, s, TOKEN_NO_FLAGS); + + int attr = mutt_map_get_value(buf->data, AttributeNames); + if (attr == -1) + { + buf_printf(err, _("%s: no such attribute"), buf->data); + return MUTT_CMD_WARNING; + } + + if (attr == A_NORMAL) + *attrs = attr; // Clear all attributes + else + *attrs |= attr; // Merge with other attributes + + return MUTT_CMD_SUCCESS; +} -- cgit v1.2.3 From e28295faa44349ace4baad4a026fc3401d1b0516 Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Wed, 18 Oct 2023 13:41:33 +0100 Subject: color: add +truecolor to version string If NeoMutt supports RGB colours, display +truecolor in the version string. --- version.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/version.c b/version.c index b96a1d774..2e1a13c4c 100644 --- a/version.c +++ b/version.c @@ -294,6 +294,11 @@ static const struct CompileOptions CompOpts[] = { { "sun_attachment", 1 }, #else { "sun_attachment", 0 }, +#endif +#ifdef NEOMUTT_DIRECT_COLORS + { "truecolor", 1 }, +#else + { "truecolor", 0 }, #endif { NULL, 0 }, }; @@ -318,6 +323,9 @@ static const struct CompileOptions DebugOpts[] = { #ifdef USE_DEBUG_KEYMAP { "keymap", 2 }, #endif +#ifdef USE_DEBUG_LOGGING + { "logging", 2 }, +#endif #ifdef USE_DEBUG_NAMES { "names", 2 }, #endif -- cgit v1.2.3