Code

bfb4c316cc77626386314a36261c93db78a22315
[ncmpc.git] / src / colors.c
1 /* 
2  * (c) 2004 by Kalle Wallin (kaw@linux.se)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  *
17  */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ncurses.h>
23 #include <glib.h>
25 #include "config.h"
26 #include "ncmpc.h"
27 #include "options.h"
28 #include "support.h"
29 #include "colors.h"
31 #ifdef DEBUG
32 #define D(x) x
33 #else
34 #define D(x)
35 #endif
37 #define COLOR_BRIGHT_MASK   (1<<7)
39 #define COLOR_BRIGHT_BLACK    (COLOR_BLACK | COLOR_BRIGHT_MASK)
40 #define COLOR_BRIGHT_RED      (COLOR_RED   | COLOR_BRIGHT_MASK)
41 #define COLOR_BRIGHT_GREEN    (COLOR_GREEN | COLOR_BRIGHT_MASK)
42 #define COLOR_BRIGHT_YELLOW   (COLOR_YELLOW | COLOR_BRIGHT_MASK)
43 #define COLOR_BRIGHT_BLUE     (COLOR_BLUE | COLOR_BRIGHT_MASK)
44 #define COLOR_BRIGHT_MAGENTA  (COLOR_MAGENTA | COLOR_BRIGHT_MASK)
45 #define COLOR_BRIGHT_CYAN     (COLOR_CYAN | COLOR_BRIGHT_MASK)
46 #define COLOR_BRIGHT_WHITE    (COLOR_WHITE | COLOR_BRIGHT_MASK)
48 #define IS_BRIGHT(color) (color & COLOR_BRIGHT_MASK)
50 /* name of the color fields */
51 #define NAME_TITLE        "title"
52 #define NAME_TITLE_BOLD   "title-bold"
53 #define NAME_LINE         "line"
54 #define NAME_LINE_BOLD    "line-flags"
55 #define NAME_LIST         "list"
56 #define NAME_LIST_BOLD    "list-bold"
57 #define NAME_PROGRESS     "progressbar"
58 #define NAME_STATUS       "status-song"
59 #define NAME_STATUS_BOLD  "status-state"
60 #define NAME_STATUS_TIME  "status-time"
61 #define NAME_ALERT        "alert"
62 #define NAME_BGCOLOR      "background"
64 typedef struct {
65   short color;
66   short r,g,b;
67 } color_definition_entry_t;
69 typedef struct {
70   int    id;
71   char   *name;
72   short  fg;
73   attr_t attrs;
74 } color_entry_t;
76 static color_entry_t colors[] = {
78   /* color pair,        field name,        color,            mono attribute */
79   /*-------------------------------------------------------------------------*/
80   { COLOR_TITLE,        NAME_TITLE,        COLOR_YELLOW,         A_NORMAL },
81   { COLOR_TITLE_BOLD,   NAME_TITLE_BOLD,   COLOR_BRIGHT_YELLOW,  A_BOLD },
82   { COLOR_LINE,         NAME_LINE,         COLOR_WHITE,          A_NORMAL },
83   { COLOR_LINE_BOLD,    NAME_LINE_BOLD,    COLOR_BRIGHT_WHITE,   A_BOLD },
84   { COLOR_LIST,         NAME_LIST,         COLOR_GREEN,          A_NORMAL },
85   { COLOR_LIST_BOLD,    NAME_LIST_BOLD,    COLOR_BRIGHT_GREEN,   A_BOLD },
86   { COLOR_PROGRESSBAR,  NAME_PROGRESS,     COLOR_WHITE,          A_NORMAL },
87   { COLOR_STATUS,       NAME_STATUS,       COLOR_YELLOW,         A_NORMAL },
88   { COLOR_STATUS_BOLD,  NAME_STATUS_BOLD,  COLOR_BRIGHT_YELLOW,  A_BOLD },
89   { COLOR_STATUS_TIME,  NAME_STATUS_TIME,  COLOR_RED,            A_NORMAL },
90   { COLOR_STATUS_ALERT, NAME_ALERT,        COLOR_BRIGHT_RED,     A_BOLD },
91   { 0,                  NULL,              0,                    0 }
92 };
94 /* background color */
95 static short bg = COLOR_BLACK;
97 static GList *color_definition_list = NULL;
99 static color_entry_t *
100 colors_lookup(int id)
102   int i;
104   i=0;
105   while( colors[i].name != NULL )
106     {
107       if( colors[i].id == id )
108         return &colors[i];
109       i++;
110     }
111   return NULL;
114 static color_entry_t *
115 colors_lookup_by_name(char *name)
117   int i;
119   i=0;
120   while( colors[i].name != NULL )
121     {
122       if( !strcasecmp(colors[i].name, name) )
123         return &colors[i];
124       i++;
125     }
126   return NULL;
129 static int
130 colors_update_pair(int id)
132   color_entry_t *entry = colors_lookup(id);
133   short fg = -1;
135   if( !entry )
136     return -1;
138   if( IS_BRIGHT(entry->fg) )
139     {
140       entry->attrs = A_BOLD;
141       fg = entry->fg & ~COLOR_BRIGHT_MASK;
142     }
143   else
144     {
145       entry->attrs = A_NORMAL;
146       fg = entry->fg;
147     }
149   init_pair(entry->id, fg, bg);
150   
151   return 0;
154 short
155 colors_str2color(char *str)
157   if( !strcasecmp(str,"black") )
158     return COLOR_BLACK;
159   else if( !strcasecmp(str,"red") )
160     return COLOR_RED;
161   else if( !strcasecmp(str,"green") )
162     return COLOR_GREEN;
163   else if( !strcasecmp(str,"yellow") )
164     return COLOR_YELLOW;
165   else if( !strcasecmp(str,"blue") )
166     return COLOR_BLUE;
167   else if( !strcasecmp(str,"magenta") )
168     return COLOR_MAGENTA;
169   else if( !strcasecmp(str,"cyan") )
170     return COLOR_CYAN;
171   else if( !strcasecmp(str,"white") )
172     return COLOR_WHITE;
173   else if( !strcasecmp(str,"brightred") )
174     return COLOR_BRIGHT_RED;
175   else if( !strcasecmp(str,"brightgreen") )
176     return COLOR_BRIGHT_GREEN;
177   else if( !strcasecmp(str,"brightyellow") )
178     return COLOR_BRIGHT_YELLOW;
179   else if( !strcasecmp(str,"brightblue") )
180     return COLOR_BRIGHT_BLUE;
181   else if( !strcasecmp(str,"brightmagenta") )
182     return COLOR_BRIGHT_MAGENTA;
183   else if( !strcasecmp(str,"brightcyan") )
184     return COLOR_BRIGHT_CYAN;
185   else if( !strcasecmp(str,"brightwhite") )
186     return COLOR_BRIGHT_WHITE;
187   else if( !strcasecmp(str,"grey") || !strcasecmp(str,"gray") )
188     return COLOR_BRIGHT_BLACK;
189   else if( !strcasecmp(str,"none") )
190     return -1;
191   fprintf(stderr,_("Warning: Unknown color - %s\n"), str);
192   return -2;
195 /* This function is called from conf.c before curses have been started,
196  * it adds the definition to the color_definition_list and init_color() is 
197  * done in colors_start() */
198 int
199 colors_define(char *name, short r, short g, short b)
201   color_definition_entry_t *entry;
202   short color = colors_str2color(name);
204   if( color<0 )
205     return -1;
207   entry = g_malloc(sizeof(color_definition_entry_t));
208   entry->color = color;
209   entry->r = r;
210   entry->g = g;
211   entry->b = b;
213   color_definition_list = g_list_append(color_definition_list, entry);
215   return 0;
219 int
220 colors_assign(char *name, char *value)
222   color_entry_t *entry = colors_lookup_by_name(name);
223   short color;
225   if( !entry )
226     {
227       if( !strcasecmp(NAME_BGCOLOR, name) )
228         {
229           if( (color=colors_str2color(value)) < -1 )
230             return -1;
231           if( color > COLORS )
232             color = color & ~COLOR_BRIGHT_MASK;
233           bg = color;
234           return 0;
235         }
236       fprintf(stderr,_("Warning: Unknown color field - %s\n"), name);
237       return -1;
238     }
240   if( (color=colors_str2color(value)) < -1 )
241     return -1;
242   entry->fg = color;
244   return 0;
248 int
249 colors_start(void)
251   if( has_colors() )
252     {
253       /* initialize color support */
254       start_color();
255       use_default_colors();
256       /* define any custom colors defined in the configuration file */
257       if( color_definition_list && can_change_color() )
258         {
259           GList *list = color_definition_list;
261           while( list )
262             {
263               color_definition_entry_t *entry = list->data;
265               if( entry->color <= COLORS )
266                 init_color(entry->color, entry->r, entry->g, entry->b);
267               list=list->next;
268             }
269         }
270       else if( !can_change_color() )
271         fprintf(stderr, _("Terminal lacks support for changing colors!\n"));
273       if( options.enable_colors )
274         {
275           int i = 0;
277           while(colors[i].name)
278             {
279               /* update the color pairs */
280               colors_update_pair(colors[i].id);
281               i++;
282             }
284         }
285     }
286   else if( options.enable_colors )
287     {
288       fprintf(stderr, _("Terminal lacks color capabilities!\n"));
289       options.enable_colors = 0;
290     }
292   /* free the color_definition_list */
293   if( color_definition_list )
294     {
295       GList *list = color_definition_list;
297       while( list )
298         {
299           g_free(list->data);
300           list=list->next;
301         }
302       g_list_free(color_definition_list);
303       color_definition_list = NULL;
304     }
306   return 0;
310 int
311 colors_use(WINDOW *w, int id)
313   color_entry_t *entry = colors_lookup(id);
314   short pair;
315   attr_t attrs;
317   if( !entry )
318     return -1;
320   wattr_get(w, &attrs, &pair, NULL);
322   if( options.enable_colors )
323     {
324       /* color mode */
325       if( attrs != entry->attrs || id!=pair )
326         wattr_set(w, entry->attrs, id, NULL);
327     }
328   else
329     {
330       /* mono mode */
331       if( attrs != entry->attrs )
332         wattrset(w, entry->attrs);
333     }
334   
335   return 0;