X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fcolors.c;h=5a79fd9bbfff8b2c6a7967e499af18df19c98544;hb=8a4cbdf7b257d0cefb5af6ad5a964736f08ef17f;hp=f7096939097d2e20b9a5e1f62fb4772c2246e88e;hpb=f55a67b3f882641abe5a9b14b045d7ce71964af7;p=ncmpc.git diff --git a/src/colors.c b/src/colors.c index f709693..5a79fd9 100644 --- a/src/colors.c +++ b/src/colors.c @@ -1,5 +1,6 @@ -/* - * (c) 2004 by Kalle Wallin (kaw@linux.se) +/* ncmpc (Ncurses MPD Client) + * (c) 2004-2017 The Music Player Daemon Project + * Project homepage: http://musicpd.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,327 +11,263 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "colors.h" +#include "i18n.h" +#include "ncfix.h" + +#ifdef ENABLE_COLORS +#include "options.h" +#endif + +#include #include #include #include -#include #include -#include "config.h" -#include "options.h" -#include "support.h" -#include "colors.h" - -#ifdef DEBUG -#define D(x) x -#else -#define D(x) -#endif - -#define COLOR_BRIGHT_MASK (1<<7) - -#define COLOR_BRIGHT_BLACK (COLOR_BLACK | COLOR_BRIGHT_MASK) -#define COLOR_BRIGHT_RED (COLOR_RED | COLOR_BRIGHT_MASK) -#define COLOR_BRIGHT_GREEN (COLOR_GREEN | COLOR_BRIGHT_MASK) -#define COLOR_BRIGHT_YELLOW (COLOR_YELLOW | COLOR_BRIGHT_MASK) -#define COLOR_BRIGHT_BLUE (COLOR_BLUE | COLOR_BRIGHT_MASK) -#define COLOR_BRIGHT_MAGENTA (COLOR_MAGENTA | COLOR_BRIGHT_MASK) -#define COLOR_BRIGHT_CYAN (COLOR_CYAN | COLOR_BRIGHT_MASK) -#define COLOR_BRIGHT_WHITE (COLOR_WHITE | COLOR_BRIGHT_MASK) - -#define IS_BRIGHT(color) (color & COLOR_BRIGHT_MASK) - -/* name of the color fields */ -#define NAME_TITLE "title" -#define NAME_TITLE_BOLD "title-bold" -#define NAME_LINE "line" -#define NAME_LINE_BOLD "line-flags" -#define NAME_LIST "list" -#define NAME_LIST_BOLD "list-bold" -#define NAME_PROGRESS "progressbar" -#define NAME_STATUS "status-song" -#define NAME_STATUS_BOLD "status-state" -#define NAME_STATUS_TIME "status-time" -#define NAME_ALERT "alert" -#define NAME_BGCOLOR "background" +#define COLOR_NONE G_MININT /* left most bit only */ +#define COLOR_ERROR -2 +#ifdef ENABLE_COLORS typedef struct { - short color; - short r,g,b; + short color; + short r,g,b; } color_definition_entry_t; +#endif typedef struct { - int id; - char *name; - short fg; - attr_t attrs; + const char *name; + int color; + int mono; } color_entry_t; -static color_entry_t colors[] = { - - /* color pair, field name, color, mono attribute */ - /*-------------------------------------------------------------------------*/ - { COLOR_TITLE, NAME_TITLE, COLOR_YELLOW, A_NORMAL }, - { COLOR_TITLE_BOLD, NAME_TITLE_BOLD, COLOR_BRIGHT_YELLOW, A_BOLD }, - { COLOR_LINE, NAME_LINE, COLOR_WHITE, A_NORMAL }, - { COLOR_LINE_BOLD, NAME_LINE_BOLD, COLOR_BRIGHT_WHITE, A_BOLD }, - { COLOR_LIST, NAME_LIST, COLOR_GREEN, A_NORMAL }, - { COLOR_LIST_BOLD, NAME_LIST_BOLD, COLOR_BRIGHT_GREEN, A_BOLD }, - { COLOR_PROGRESSBAR, NAME_PROGRESS, COLOR_WHITE, A_NORMAL }, - { COLOR_STATUS, NAME_STATUS, COLOR_YELLOW, A_NORMAL }, - { COLOR_STATUS_BOLD, NAME_STATUS_BOLD, COLOR_BRIGHT_YELLOW, A_BOLD }, - { COLOR_STATUS_TIME, NAME_STATUS_TIME, COLOR_RED, A_NORMAL }, - { COLOR_STATUS_ALERT, NAME_ALERT, COLOR_BRIGHT_RED, A_BOLD }, - { 0, NULL, 0, 0 } +static color_entry_t colors[COLOR_END] = { + /* color pair = field name, color, mono */ + [COLOR_TITLE] = {"title", COLOR_YELLOW, A_NORMAL}, + [COLOR_TITLE_BOLD] = {"title-bold", COLOR_YELLOW | A_BOLD, A_BOLD }, + [COLOR_LINE] = {"line", COLOR_WHITE, A_NORMAL}, + [COLOR_LINE_BOLD] = {"line-bold", COLOR_WHITE | A_BOLD, A_BOLD }, + [COLOR_LINE_FLAGS] = {"line-flags", COLOR_YELLOW, A_NORMAL}, + [COLOR_LIST] = {"list", COLOR_GREEN, A_NORMAL}, + [COLOR_LIST_BOLD] = {"list-bold", COLOR_GREEN | A_BOLD, A_BOLD }, + [COLOR_PROGRESSBAR] = {"progressbar", COLOR_WHITE, A_NORMAL}, + [COLOR_STATUS] = {"status-song", COLOR_YELLOW, A_NORMAL}, + [COLOR_STATUS_BOLD] = {"status-state", COLOR_YELLOW | A_BOLD, A_BOLD }, + [COLOR_STATUS_TIME] = {"status-time", COLOR_RED, A_NORMAL}, + [COLOR_STATUS_ALERT] = {"alert", COLOR_RED | A_BOLD, A_BOLD }, + [COLOR_DIRECTORY] = {"browser-directory", COLOR_YELLOW, A_NORMAL}, + [COLOR_PLAYLIST] = {"browser-playlist", COLOR_RED, A_NORMAL}, + [COLOR_BACKGROUND] = {"background", COLOR_BLACK, A_NORMAL}, }; -/* background color */ -static short bg = COLOR_BLACK; +#ifdef ENABLE_COLORS static GList *color_definition_list = NULL; static color_entry_t * -colors_lookup(int id) +colors_lookup_by_name(const char *name) { - int i; - - i=0; - while( colors[i].name != NULL ) - { - if( colors[i].id == id ) - return &colors[i]; - i++; - } - return NULL; -} + for (enum color i = 1; i < COLOR_END; ++i) + if (!strcasecmp(colors[i].name, name)) + return &colors[i]; -static color_entry_t * -colors_lookup_by_name(char *name) -{ - int i; - - i=0; - while( colors[i].name != NULL ) - { - if( !strcasecmp(colors[i].name, name) ) - return &colors[i]; - i++; - } - return NULL; + return NULL; } -static int -colors_update_pair(int id) +static void +colors_update_pair(enum color id) { - color_entry_t *entry = colors_lookup(id); - short fg = -1; - - if( !entry ) - return -1; - - if( IS_BRIGHT(entry->fg) ) - { - entry->attrs = A_BOLD; - fg = entry->fg & ~COLOR_BRIGHT_MASK; - } - else - { - entry->attrs = A_NORMAL; - fg = entry->fg; - } - - init_pair(entry->id, fg, bg); - - return 0; + assert(id > 0 && id < COLOR_END); + + int fg = colors[id].color; + int bg = colors[COLOR_BACKGROUND].color; + + /* If color == COLOR_NONE (negative), + * pass -1 to avoid cast errors */ + init_pair(id, + (fg < 0 ? -1 : fg), + (bg < 0 ? -1 : bg)); } -short -colors_str2color(char *str) +int +colors_str2color(const char *str) { - if( !strcasecmp(str,"black") ) - return COLOR_BLACK; - else if( !strcasecmp(str,"red") ) - return COLOR_RED; - else if( !strcasecmp(str,"green") ) - return COLOR_GREEN; - else if( !strcasecmp(str,"yellow") ) - return COLOR_YELLOW; - else if( !strcasecmp(str,"blue") ) - return COLOR_BLUE; - else if( !strcasecmp(str,"magenta") ) - return COLOR_MAGENTA; - else if( !strcasecmp(str,"cyan") ) - return COLOR_CYAN; - else if( !strcasecmp(str,"white") ) - return COLOR_WHITE; - else if( !strcasecmp(str,"brightred") ) - return COLOR_BRIGHT_RED; - else if( !strcasecmp(str,"brightgreen") ) - return COLOR_BRIGHT_GREEN; - else if( !strcasecmp(str,"brightyellow") ) - return COLOR_BRIGHT_YELLOW; - else if( !strcasecmp(str,"brightblue") ) - return COLOR_BRIGHT_BLUE; - else if( !strcasecmp(str,"brightmagenta") ) - return COLOR_BRIGHT_MAGENTA; - else if( !strcasecmp(str,"brightcyan") ) - return COLOR_BRIGHT_CYAN; - else if( !strcasecmp(str,"brightwhite") ) - return COLOR_BRIGHT_WHITE; - else if( !strcasecmp(str,"grey") || !strcasecmp(str,"gray") ) - return COLOR_BRIGHT_BLACK; - else if( !strcasecmp(str,"none") ) - return -1; - fprintf(stderr,"Warning: Unknown color - %s\n", str); - return -2; + int color = 0; + char **parts = g_strsplit(str, ",", 0); + for (int i = 0; parts[i]; i++) { + char *cur = parts[i]; + + /* Legacy colors (brightblue,etc) */ + if (!strncasecmp(cur, "bright", 6)) { + color |= A_BOLD; + cur += 6; + } + + /* Colors */ + if (!strcasecmp(cur, "none")) + color |= COLOR_NONE; + else if (!strcasecmp(cur, "black")) + color |= COLOR_BLACK; + else if (!strcasecmp(cur, "red")) + color |= COLOR_RED; + else if (!strcasecmp(cur, "green")) + color |= COLOR_GREEN; + else if (!strcasecmp(cur, "yellow")) + color |= COLOR_YELLOW; + else if (!strcasecmp(cur, "blue")) + color |= COLOR_BLUE; + else if (!strcasecmp(cur, "magenta")) + color |= COLOR_MAGENTA; + else if (!strcasecmp(cur, "cyan")) + color |= COLOR_CYAN; + else if (!strcasecmp(cur, "white")) + color |= COLOR_WHITE; + else if (!strcasecmp(cur, "grey") || !strcasecmp(cur, "gray")) + color |= COLOR_BLACK | A_BOLD; + + /* Attributes */ + else if (!strcasecmp(cur, "standout")) + color |= A_STANDOUT; + else if (!strcasecmp(cur, "underline")) + color |= A_UNDERLINE; + else if (!strcasecmp(cur, "reverse")) + color |= A_REVERSE; + else if (!strcasecmp(cur, "blink")) + color |= A_BLINK; + else if (!strcasecmp(cur, "dim")) + color |= A_DIM; + else if (!strcasecmp(cur, "bold")) + color |= A_BOLD; + else { + /* Numerical colors */ + char *endptr; + int tmp = strtol(cur, &endptr, 10); + if (cur != endptr && endptr[0] == '\0') { + color |= tmp; + } else { + fprintf(stderr, "%s: %s\n", + _("Unknown color"), str); + return COLOR_ERROR; + } + } + + } + g_strfreev(parts); + return color; } /* This function is called from conf.c before curses have been started, - * it adds the definition to the color_definition_list and init_color() is + * it adds the definition to the color_definition_list and init_color() is * done in colors_start() */ -int -colors_define(char *name, short r, short g, short b) +bool +colors_define(const char *name, short r, short g, short b) { - color_definition_entry_t *entry; - short color = colors_str2color(name); + int color = colors_str2color(name); - if( color<0 ) - return -1; + if (color < 0) + return false; - entry = g_malloc(sizeof(color_definition_entry_t)); - entry->color = color; - entry->r = r; - entry->g = g; - entry->b = b; + color_definition_entry_t *entry = + g_malloc(sizeof(color_definition_entry_t)); + entry->color = color; + entry->r = r; + entry->g = g; + entry->b = b; - color_definition_list = g_list_append(color_definition_list, entry); + color_definition_list = g_list_append(color_definition_list, entry); - return 0; + return true; } - -int -colors_assign(char *name, char *value) +bool +colors_assign(const char *name, const char *value) { - color_entry_t *entry = colors_lookup_by_name(name); - short color; - - if( !entry ) - { - if( !strcasecmp(NAME_BGCOLOR, name) ) - { - if( (color=colors_str2color(value)) < -1 ) - return -1; - if( color > COLORS ) - color = color & ~COLOR_BRIGHT_MASK; - bg = color; - return 0; + color_entry_t *entry = colors_lookup_by_name(name); + + if (!entry) { + fprintf(stderr, "%s: %s", + _("Unknown color field"), name); + return false; } - fprintf(stderr,"Warning: Unknown color field - %s\n", name); - return -1; - } - if( (color=colors_str2color(value)) < -1 ) - return -1; - entry->fg = color; + const int color = colors_str2color(value); + if (color == COLOR_ERROR) + return false; - return 0; + entry->color = color; + return true; } - -int +void colors_start(void) { - if( has_colors() ) - { - /* initialize color support */ - start_color(); - use_default_colors(); - /* define any custom colors defined in the configuration file */ - if( color_definition_list && can_change_color() ) - { - GList *list = color_definition_list; - - while( list ) - { - color_definition_entry_t *entry = list->data; - - if( entry->color <= COLORS ) - init_color(entry->color, entry->r, entry->g, entry->b); - list=list->next; - } + if (has_colors()) { + /* initialize color support */ + start_color(); + use_default_colors(); + /* define any custom colors defined in the configuration file */ + if (color_definition_list && can_change_color()) { + GList *list = color_definition_list; + + while (list) { + color_definition_entry_t *entry = list->data; + + if (entry->color <= COLORS) + init_color(entry->color, entry->r, + entry->g, entry->b); + list = list->next; + } + } else if (color_definition_list && !can_change_color()) + fprintf(stderr, "%s\n", + _("Terminal lacks support for changing colors")); + + if (options.enable_colors) { + for (enum color i = 1; i < COLOR_END; ++i) + /* update the color pairs */ + colors_update_pair(i); + } + } else if (options.enable_colors) { + fprintf(stderr, "%s\n", + _("Terminal lacks color capabilities")); + options.enable_colors = 0; } - else if( !can_change_color() ) - fprintf(stderr, "Terminal lacks support for changing colors!\n"); - if( options.enable_colors ) - { - int i = 0; - - while(colors[i].name) - { - /* update the color pairs */ - colors_update_pair(colors[i].id); - i++; - } - - } - } - else if( options.enable_colors ) - { - fprintf(stderr, "Terminal lacks color capabilities!\n"); - options.enable_colors = 0; - } - - /* free the color_definition_list */ - if( color_definition_list ) - { - GList *list = color_definition_list; - - while( list ) - { - g_free(list->data); - list=list->next; + /* free the color_definition_list */ + if (color_definition_list) { + g_list_free_full(color_definition_list, g_free); + color_definition_list = NULL; } - g_list_free(color_definition_list); - color_definition_list = NULL; - } - - return 0; } +#endif - -int -colors_use(WINDOW *w, int id) +void +colors_use(WINDOW *w, enum color id) { - color_entry_t *entry = colors_lookup(id); - short pair; - attr_t attrs; - - if( !entry ) - return -1; - - wattr_get(w, &attrs, &pair, NULL); - - if( options.enable_colors ) - { - /* color mode */ - if( attrs != entry->attrs || id!=pair ) - wattr_set(w, entry->attrs, id, NULL); - } - else - { - /* mono mode */ - if( attrs != entry->attrs ) - wattrset(w, entry->attrs); - } - - return 0; -} + color_entry_t *entry = &colors[id]; + + assert(id > 0 && id < COLOR_END); + + attr_t attrs; + short pair; + fix_wattr_get(w, &attrs, &pair, NULL); +#ifdef ENABLE_COLORS + if (options.enable_colors) { + /* color mode */ + if ((int)attrs != entry->color || (short)id != pair) + wattr_set(w, entry->color, id, NULL); + } else { +#endif + /* mono mode */ + if ((int)attrs != entry->mono) + (void)wattrset(w, entry->mono); +#ifdef ENABLE_COLORS + } +#endif +}