diff --git a/ChangeLog b/ChangeLog index 98a4035c..01c8141d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-05-03 Benno Schulenberg + * src/*.h, src/*.c: Add the ability to colour four elements of + nano's interface differently: title bar, status bar, key combo, + and function tag. Idea and original patch by Mark Majeres. + 2014-04-30 Benno Schulenberg * src/*, doc/*: Update the years in the copyright notices -- there were releases in 2010, 2011, and 2013, and there will be in 2014. diff --git a/src/color.c b/src/color.c index 3235f972..f0f8a489 100644 --- a/src/color.c +++ b/src/color.c @@ -38,10 +38,38 @@ void set_colorpairs(void) { const syntaxtype *this_syntax = syntaxes; + bool bright = FALSE, defok = FALSE; + short fg, bg; + size_t i; + + start_color(); + +#ifdef HAVE_USE_DEFAULT_COLORS + /* Use the default colors, if available. */ + defok = (use_default_colors() != ERR); +#endif + + for (i = 0; i < NUMBER_OF_ELEMENTS; i++) { + if (parse_color_names(specified_color_combo[i], &fg, &bg, &bright)) { + if (fg == -1 && !defok) + fg = COLOR_WHITE; + if (bg == -1 && !defok) + bg = COLOR_BLACK; + init_pair(i + 1, fg, bg); + interface_color_pair[i] = COLOR_PAIR(i + 1); + } + else if (i != FUNCTION_TAG) + interface_color_pair[i] = reverse_attr; + + if (specified_color_combo[i] != NULL) { + free(specified_color_combo[i]); + specified_color_combo[i] = NULL; + } + } for (; this_syntax != NULL; this_syntax = this_syntax->next) { colortype *this_color = this_syntax->color; - int color_pair = 1; + int color_pair = NUMBER_OF_ELEMENTS + 1; for (; this_color != NULL; this_color = this_color->next) { const colortype *beforenow = this_syntax->color; @@ -70,15 +98,9 @@ void color_init(void) if (has_colors()) { const colortype *tmpcolor; -#ifdef HAVE_USE_DEFAULT_COLORS - bool defok; -#endif - - start_color(); - #ifdef HAVE_USE_DEFAULT_COLORS /* Use the default colors, if available. */ - defok = (use_default_colors() != ERR); + bool defok = (use_default_colors() != ERR); #endif for (tmpcolor = openfile->colorstrings; tmpcolor != NULL; diff --git a/src/global.c b/src/global.c index 122af39c..7d70f3fe 100644 --- a/src/global.c +++ b/src/global.c @@ -205,6 +205,12 @@ regmatch_t regmatches[10]; int reverse_attr = A_REVERSE; /* The curses attribute we use for reverse video. */ +#ifndef DISABLE_COLOR +char* specified_color_combo[] = {}; + /* The color combinations as specified in the rcfile. */ +#endif +int interface_color_pair[] = {}; + /* The processed color pairs for the interface elements. */ char *homedir = NULL; /* The user's home directory, from $HOME or /etc/passwd. */ diff --git a/src/nano.c b/src/nano.c index 596cc322..4ab10ddf 100644 --- a/src/nano.c +++ b/src/nano.c @@ -2657,6 +2657,15 @@ int main(int argc, char **argv) mouse_init(); #endif +#ifndef DISABLE_COLOR + set_colorpairs(); +#else + interface_color_pair[TITLE_BAR] = reverse_attr; + interface_color_pair[STATUS_BAR] = reverse_attr; + interface_color_pair[KEY_COMBO] = reverse_attr; + interface_color_pair[FUNCTION_TAG] = A_NORMAL; +#endif + #ifdef DEBUG fprintf(stderr, "Main: open file\n"); #endif diff --git a/src/nano.h b/src/nano.h index 83a200bb..7e97ffe7 100644 --- a/src/nano.h +++ b/src/nano.h @@ -479,6 +479,15 @@ typedef struct subnfunc { /* Next item in the list. */ } subnfunc; +/* The elements of the interface that can be colored differently. */ +enum +{ + TITLE_BAR = 0, + STATUS_BAR, + KEY_COMBO, + FUNCTION_TAG, + NUMBER_OF_ELEMENTS +}; /* Enumeration to be used in flags table. See FLAGBIT and FLAGOFF * definitions. */ diff --git a/src/prompt.c b/src/prompt.c index 6bd06606..e8bbb868 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -853,7 +853,7 @@ void update_statusbar_line(const char *curranswer, size_t index) index = strnlenpt(curranswer, index); page_start = get_statusbar_page_start(start_col, start_col + index); - wattron(bottomwin, reverse_attr); + wattron(bottomwin, interface_color_pair[TITLE_BAR]); blank_statusbar(); @@ -866,7 +866,7 @@ void update_statusbar_line(const char *curranswer, size_t index) waddstr(bottomwin, expanded); free(expanded); - wattroff(bottomwin, reverse_attr); + wattroff(bottomwin, interface_color_pair[TITLE_BAR]); statusbar_pww = statusbar_xplustabs(); reset_statusbar_cursor(); wnoutrefresh(bottomwin); @@ -1273,12 +1273,12 @@ int do_yesno_prompt(bool all, const char *msg) onekey("^C", _("Cancel"), width); } - wattron(bottomwin, reverse_attr); + wattron(bottomwin, interface_color_pair[TITLE_BAR]); blank_statusbar(); mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1)); - wattroff(bottomwin, reverse_attr); + wattroff(bottomwin, interface_color_pair[TITLE_BAR]); /* Refresh the edit window and the statusbar before getting * input. */ diff --git a/src/proto.h b/src/proto.h index 52554857..308c7e0d 100644 --- a/src/proto.h +++ b/src/proto.h @@ -131,6 +131,10 @@ extern regmatch_t regmatches[10]; #endif extern int reverse_attr; +#ifndef DISABLE_COLOR +extern char* specified_color_combo[NUMBER_OF_ELEMENTS]; +#endif +extern int interface_color_pair[NUMBER_OF_ELEMENTS]; extern char *homedir; @@ -551,6 +555,7 @@ void parse_magic_syntax(char *ptr); void parse_include(char *ptr); short color_to_short(const char *colorname, bool *bright); void parse_colors(char *ptr, bool icase); +bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright); void reset_multis(filestruct *fileptr, bool force); void alloc_multidata_if_needed(filestruct *fileptr); #endif diff --git a/src/rcfile.c b/src/rcfile.c index 31a56348..a11f8c05 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -99,6 +99,12 @@ static const rcoption rcopts[] = { {"whitespace", 0}, {"wordbounds", WORD_BOUNDS}, {"softwrap", SOFTWRAP}, +#endif +#ifndef DISABLE_COLOR + {"titlecolor", 0}, + {"statuscolor", 0}, + {"keycolor", 0}, + {"functioncolor", 0}, #endif {NULL, 0} }; @@ -703,7 +709,7 @@ short color_to_short(const char *colorname, bool *bright) void parse_colors(char *ptr, bool icase) { short fg, bg; - bool bright = FALSE, no_fgcolor = FALSE; + bool bright = FALSE; char *fgstr; assert(ptr != NULL); @@ -721,36 +727,8 @@ void parse_colors(char *ptr, bool icase) fgstr = ptr; ptr = parse_next_word(ptr); - - if (strchr(fgstr, ',') != NULL) { - char *bgcolorname; - - strtok(fgstr, ","); - bgcolorname = strtok(NULL, ","); - if (bgcolorname == NULL) { - /* If we have a background color without a foreground color, - * parse it properly. */ - bgcolorname = fgstr + 1; - no_fgcolor = TRUE; - } - if (strncasecmp(bgcolorname, "bright", 6) == 0) { - rcfile_error( - N_("Background color \"%s\" cannot be bright"), - bgcolorname); - return; - } - bg = color_to_short(bgcolorname, &bright); - } else - bg = -1; - - if (!no_fgcolor) { - fg = color_to_short(fgstr, &bright); - - /* Don't try to parse screwed-up foreground colors. */ - if (fg == -1) - return; - } else - fg = -1; + if (!parse_color_names(fgstr, &fg, &bg, &bright)) + return; if (*ptr == '\0') { rcfile_error(N_("Missing regex string")); @@ -862,6 +840,44 @@ void parse_colors(char *ptr, bool icase) } } +/* Parse the color name, or pair of color names, in combostr. */ +bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright) +{ + bool no_fgcolor = FALSE; + + if (combostr == NULL) + return false; + + if (strchr(combostr, ',') != NULL) { + char *bgcolorname; + strtok(combostr, ","); + bgcolorname = strtok(NULL, ","); + if (bgcolorname == NULL) { + /* If we have a background color without a foreground color, + * parse it properly. */ + bgcolorname = combostr + 1; + no_fgcolor = TRUE; + } + if (strncasecmp(bgcolorname, "bright", 6) == 0) { + rcfile_error(N_("Background color \"%s\" cannot be bright"), bgcolorname); + return false; + } + *bg = color_to_short(bgcolorname, bright); + } else + *bg = -1; + + if (!no_fgcolor) { + *fg = color_to_short(combostr, bright); + + /* Don't try to parse screwed-up foreground colors. */ + if (*fg == -1) + return false; + } else + *fg = -1; + + return true; +} + /* Parse the header-line regex that may influence the choice of syntax. */ void parse_headers(char *ptr) { @@ -1149,6 +1165,17 @@ void parse_rcfile(FILE *rcstream break; } +#ifndef DISABLE_COLOR + if (strcasecmp(rcopts[i].name, "titlecolor") == 0) + specified_color_combo[TITLE_BAR] = option; + else if (strcasecmp(rcopts[i].name, "statuscolor") == 0) + specified_color_combo[STATUS_BAR] = option; + else if (strcasecmp(rcopts[i].name, "keycolor") == 0) + specified_color_combo[KEY_COMBO] = option; + else if (strcasecmp(rcopts[i].name, "functioncolor") == 0) + specified_color_combo[FUNCTION_TAG] = option; + else +#endif #ifndef DISABLE_OPERATINGDIR if (strcasecmp(rcopts[i].name, "operatingdir") == 0) operating_dir = option; @@ -1357,10 +1384,6 @@ void do_rcfile(void) while (getchar() != '\n') ; } - -#ifndef DISABLE_COLOR - set_colorpairs(); -#endif } #endif /* !DISABLE_NANORC */ diff --git a/src/winio.c b/src/winio.c index 1c5dc3af..e60fe1b5 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2104,7 +2104,7 @@ void titlebar(const char *path) assert(path != NULL || openfile->filename != NULL); - wattron(topwin, reverse_attr); + wattron(topwin, interface_color_pair[TITLE_BAR]); blank_titlebar(); @@ -2235,7 +2235,7 @@ void titlebar(const char *path) } } - wattroff(topwin, reverse_attr); + wattroff(topwin, interface_color_pair[TITLE_BAR]); wnoutrefresh(topwin); reset_cursor(); @@ -2306,12 +2306,12 @@ void statusbar(const char *msg, ...) start_x = (COLS - foo_len - 4) / 2; wmove(bottomwin, 0, start_x); - wattron(bottomwin, reverse_attr); + wattron(bottomwin, interface_color_pair[STATUS_BAR]); waddstr(bottomwin, "[ "); waddstr(bottomwin, foo); free(foo); waddstr(bottomwin, " ]"); - wattroff(bottomwin, reverse_attr); + wattroff(bottomwin, interface_color_pair[STATUS_BAR]); wnoutrefresh(bottomwin); reset_cursor(); wnoutrefresh(edit); @@ -2411,9 +2411,9 @@ void onekey(const char *keystroke, const char *desc, size_t len) assert(keystroke != NULL && desc != NULL); - wattron(bottomwin, reverse_attr); + wattron(bottomwin, interface_color_pair[KEY_COMBO]); waddnstr(bottomwin, keystroke, actual_x(keystroke, len)); - wattroff(bottomwin, reverse_attr); + wattroff(bottomwin, interface_color_pair[KEY_COMBO]); if (len > keystroke_len) len -= keystroke_len; @@ -2421,8 +2421,10 @@ void onekey(const char *keystroke, const char *desc, size_t len) len = 0; if (len > 0) { + wattron(bottomwin, interface_color_pair[FUNCTION_TAG]); waddch(bottomwin, ' '); waddnstr(bottomwin, desc, actual_x(desc, len)); + wattroff(bottomwin, interface_color_pair[FUNCTION_TAG]); } }