diff --git a/src/colors.c b/src/colors.c
index 692f01ecd0493350d69545b79e9ec79d82b06598..5a79fd9bbfff8b2c6a7967e499af18df19c98544 100644 (file)
--- a/src/colors.c
+++ b/src/colors.c
-/*
- * $Id$
- *
- * (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
* 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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <ncurses.h>
#include <glib.h>
-#include "config.h"
-#include "ncmpc.h"
-#include "options.h"
-#include "support.h"
-#include "colors.h"
-
-#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( color_definition_list && !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
}
-