>From 02dd2f0537fc625a107d41436a081e78a9a3800b Mon Sep 17 00:00:00 2001 From: Brand Huntsman Date: Thu, 18 Jan 2018 19:59:46 -0700 Subject: [PATCH 1/4] bold, italic, reverse and underline color attributes Signed-off-by: Brand Huntsman --- src/color.c | 23 +++++----- src/nano.h | 2 - src/proto.h | 2 +- src/rcfile.c | 124 +++++++++++++++++++++++++++++++++++++++++---------- syntax/nanorc.nanorc | 4 +- 5 files changed, 115 insertions(+), 40 deletions(-) diff --git a/src/color.c b/src/color.c index f0e8328a..477582eb 100644 --- a/src/color.c +++ b/src/color.c @@ -65,8 +65,9 @@ void set_colorpairs(void) if (combo->bg == -1 && !using_defaults) combo->bg = COLOR_BLACK; init_pair(i + 1, combo->fg, combo->bg); - interface_color_pair[i] = COLOR_PAIR(i + 1) | A_BANDAID | - (combo->bright ? A_BOLD : A_NORMAL); + interface_color_pair[i] = COLOR_PAIR(i + 1) + | combo->attributes + | A_BANDAID; } else { if (i != FUNCTION_TAG) interface_color_pair[i] = hilite_attribute; @@ -84,20 +85,20 @@ void set_colorpairs(void) int new_number = NUMBER_OF_ELEMENTS + 1; for (ink = sint->color; ink != NULL; ink = ink->next) { - const colortype *beforenow = sint->color; + const colortype *prev = sint->color; - while (beforenow != ink && (beforenow->fg != ink->fg || - beforenow->bg != ink->bg || - beforenow->bright != ink->bright)) - beforenow = beforenow->next; + while (prev != ink + && (prev->fg != ink->fg + || prev->bg != ink->bg + || (prev->attributes & 0xFFFF0000) != ink->attributes)) + prev = prev->next; - if (beforenow != ink) - ink->pairnum = beforenow->pairnum; + if (prev != ink) + ink->pairnum = prev->pairnum; else ink->pairnum = new_number++; - ink->attributes = COLOR_PAIR(ink->pairnum) | A_BANDAID | - (ink->bright ? A_BOLD : A_NORMAL); + ink->attributes |= COLOR_PAIR(ink->pairnum) | A_BANDAID; } } } diff --git a/src/nano.h b/src/nano.h index 55abf1e8..ba46f689 100644 --- a/src/nano.h +++ b/src/nano.h @@ -182,8 +182,6 @@ typedef struct colortype { /* This syntax's foreground color. */ short bg; /* This syntax's background color. */ - bool bright; - /* Is this color A_BOLD? */ int pairnum; /* The color pair number used for this foreground color and * background color. */ diff --git a/src/proto.h b/src/proto.h index 77ffc05c..32c267b9 100644 --- a/src/proto.h +++ b/src/proto.h @@ -477,7 +477,7 @@ int do_yesno_prompt(bool all, const char *msg); /* Most functions in rcfile.c. */ #ifdef ENABLE_NANORC #ifdef ENABLE_COLOR -bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright); +bool parse_color_names(char *combostr, short *fg, short *bg, int *attributes); void grab_and_store(const char *kind, char *ptr, regexlisttype **storage); #endif void parse_rcfile(FILE *rcstream, bool syntax_only); diff --git a/src/rcfile.c b/src/rcfile.c index b88d71af..3fbdde3f 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -570,14 +570,16 @@ void parse_includes(char *ptr) } /* Return the short value corresponding to the color named in colorname, - * and set bright to TRUE if that color is bright. */ -short color_to_short(const char *colorname, bool *bright) + * and set bold to TRUE if that color has bright prefix. */ +short color_to_short(const char *colorname, bool *bold) { if (strncasecmp(colorname, "bright", 6) == 0) { - *bright = TRUE; + /* The bright foreground prefix makes the color bold and bright, + * or only bright on terminals without bold support. */ + *bold = TRUE; colorname += 6; } else - *bright = FALSE; + *bold = FALSE; if (strcasecmp(colorname, "green") == 0) return COLOR_GREEN; @@ -606,7 +608,7 @@ short color_to_short(const char *colorname, bool *bright) void parse_colors(char *ptr, int rex_flags) { short fg, bg; - bool bright; + int attributes; char *item; if (!opensyntax) { @@ -622,7 +624,7 @@ void parse_colors(char *ptr, int rex_flags) item = ptr; ptr = parse_next_word(ptr); - if (!parse_color_names(item, &fg, &bg, &bright)) + if (!parse_color_names(item, &fg, &bg, &attributes)) return; if (*ptr == '\0') { @@ -669,7 +671,7 @@ void parse_colors(char *ptr, int rex_flags) newcolor->fg = fg; newcolor->bg = bg; - newcolor->bright = bright; + newcolor->attributes = attributes; newcolor->rex_flags = rex_flags; newcolor->start_regex = mallocstrcpy(NULL, item); @@ -727,29 +729,103 @@ void parse_colors(char *ptr, int rex_flags) } } -/* Parse the color name, or pair of color names, in combostr. */ -bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright) +static char *find_next_comma_word(char *prev_word) { - char *comma = strchr(combostr, ','); + if (prev_word == NULL) + return NULL; + char *comma = strchr(prev_word, ','); if (comma != NULL) { - *bg = color_to_short(comma + 1, bright); - if (*bright) { - rcfile_error(N_("A background color cannot be bright")); - return FALSE; - } *comma = '\0'; - } else - *bg = -1; + return comma + 1; + } + + /* No comma was found. */ + return NULL; +} - if (comma != combostr) { - *fg = color_to_short(combostr, bright); +/* Parse the color name, or pair of color names, in combostr. */ +bool parse_color_names(char *combostr, short *fg, short *bg, int *attributes) +{ + char *word = combostr; + char *next_word = find_next_comma_word(combostr); + + *attributes = A_NORMAL; + + /* Get attributes. */ + while (word != NULL) { + if (strcasecmp(word, "bold") == 0) { + /* The bold attribute makes the color bold and bright, + * or only bright on terminals without bold support, + * or only bold for extended colors. */ + if (*attributes & A_BOLD) + rcfile_error(N_("A color should not use the same attribute more than once")); + *attributes |= A_BOLD; + } else if (strcasecmp(word, "italic") == 0) { + /* The italic attribute makes the color italic + * on terminals with italic support and an italic capable font. */ + #ifdef A_ITALIC + if (*attributes & A_ITALIC) + rcfile_error(N_("A color should not use the same attribute more than once")); + *attributes |= A_ITALIC; + #else + rcfile_error(N_("The italic color attribute requires ncurses >= 6.0")); + #endif + } else if (strcasecmp(word, "reverse") == 0) { + /* The reverse attribute swaps the foreground and background colors. + * Useful when default background color is needed. + * Example: color reverse,blue */ + if (*attributes & A_REVERSE) + rcfile_error(N_("A color should not use the same attribute more than once")); + *attributes |= A_REVERSE; + } else if (strcasecmp(word, "underline") == 0) { + /* The underline attribute makes the color underlined. */ + if (*attributes & A_UNDERLINE) + rcfile_error(N_("A color should not use the same attribute more than once")); + *attributes |= A_UNDERLINE; + } else + break; - /* If the specified foreground color is bad, ignore the regexes. */ - if (*fg == -1) - return FALSE; - } else + word = next_word; + next_word = find_next_comma_word(word); + } + + /* Get foreground color. */ + if (word != NULL) { + if (*word != '\0') { + bool fg_bold; + *fg = color_to_short(word, &fg_bold); + + /* If the specified foreground color is bad, ignore the regexes. */ + if (*fg == -1) + return FALSE; + + if (fg_bold) { + if (*attributes & A_BOLD) + rcfile_error(N_("A foreground color should not be bright with bold attribute")); + *attributes |= A_BOLD; + } + } else + *fg = -1; + + word = next_word; + next_word = find_next_comma_word(word); + + /* Get background color. */ + if (word != NULL && *word != '\0') { + bool bg_bold; + *bg = color_to_short(word, &bg_bold); + + if (bg_bold) { + rcfile_error(N_("A background color cannot be bright")); + return FALSE; + } + } else + *bg = -1; + } else { *fg = -1; + *bg = -1; + } return TRUE; } @@ -759,7 +835,7 @@ colortype *parse_interface_color(char *combostr) { colortype *trio = nmalloc(sizeof(colortype)); - if (parse_color_names(combostr, &trio->fg, &trio->bg, &trio->bright)) { + if (parse_color_names(combostr, &trio->fg, &trio->bg, &trio->attributes)) { free(combostr); return trio; } else { diff --git a/syntax/nanorc.nanorc b/syntax/nanorc.nanorc index 9882d6b0..aa5020ba 100644 --- a/syntax/nanorc.nanorc +++ b/syntax/nanorc.nanorc @@ -8,7 +8,7 @@ icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comm # Keywords icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cutfromcursor|fill[[:space:]]+-?[[:digit:]]+|historylog|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[1-9][0-9]*|tabstospaces|tempfile|trimblanks|unix|view|wordbounds)\>" -icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|selected|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>" +icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|selected|status|title)color)[[:space:]]+((bold|italic|reverse|underline)(,(bold|italic|reverse|underline))*|((bold|italic|reverse|underline),)*((bright)?(white|black|red|blue|green|yellow|magenta|cyan))?(,(white|black|red|blue|green|yellow|magenta|cyan))?)\>" icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|selectedcolor|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+" icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>address@hidden|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+[[:alpha:]]+[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)" icolor brightgreen "^[[:space:]]*unbind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>address@hidden|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)" @@ -20,7 +20,7 @@ icolor green "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment| color brightmagenta "".+"([[:space:]]|$)" # Colors -icolor yellow "^[[:space:]]*i?color[[:space:]]*(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>" +icolor yellow "^[[:space:]]*i?color[[:space:]]+((bold|italic|reverse|underline)(,(bold|italic|reverse|underline))*|((bold|italic|reverse|underline),)*((bright)?(white|black|red|blue|green|yellow|magenta|cyan))?(,(white|black|red|blue|green|yellow|magenta|cyan))?)\>" icolor magenta "^[[:space:]]*i?color\>" "\<(start|end)=" # Comments -- 2.13.6