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