1 /*
2  * GNT - The GLib Ncurses Toolkit
3  *
4  * GNT is the legal property of its developers, whose names are too numerous
5  * to list here.  Please refer to the COPYRIGHT file distributed with this
6  * source distribution.
7  *
8  * This library is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
21  */
22 
23 #include "gntconfig.h"
24 
25 #include <ncurses.h>
26 
27 #include "gntinternal.h"
28 #undef GNT_LOG_DOMAIN
29 #define GNT_LOG_DOMAIN "Colors"
30 
31 #include "gntcolors.h"
32 #include "gntstyle.h"
33 
34 #include <glib.h>
35 
36 #include <errno.h>
37 #include <stdlib.h>
38 #include <string.h>
39 
40 static gboolean hascolors;
41 static int custom_type = GNT_COLORS;
42 static struct
43 {
44 	short r, g, b;
45 } colors[GNT_TOTAL_COLORS];
46 
47 static void
backup_colors(void)48 backup_colors(void)
49 {
50 	short i;
51 	for (i = 0; i < GNT_TOTAL_COLORS; i++)
52 	{
53 		color_content(i, &colors[i].r,
54 				&colors[i].g, &colors[i].b);
55 	}
56 }
57 
58 static gboolean
can_use_custom_color(void)59 can_use_custom_color(void)
60 {
61 	return (gnt_style_get_bool(GNT_STYLE_COLOR, FALSE) && can_change_color());
62 }
63 
64 static void
restore_colors(void)65 restore_colors(void)
66 {
67 	short i;
68 	for (i = 0; i < GNT_TOTAL_COLORS; i++)
69 	{
70 		init_color(i, colors[i].r,
71 				colors[i].g, colors[i].b);
72 	}
73 }
74 
gnt_init_colors()75 void gnt_init_colors()
76 {
77 	static gboolean init = FALSE;
78 	int defaults;
79 
80 	if (init)
81 		return;
82 	init = TRUE;
83 
84 	start_color();
85 	if (!(hascolors = has_colors()))
86 		return;
87 	defaults = use_default_colors();
88 
89 	if (can_use_custom_color())
90 	{
91 		backup_colors();
92 
93 		/* Do some init_color()s */
94 		init_color(GNT_COLOR_BLACK, 0, 0, 0);
95 		init_color(GNT_COLOR_RED, 1000, 0, 0);
96 		init_color(GNT_COLOR_GREEN, 0, 1000, 0);
97 		init_color(GNT_COLOR_BLUE, 250, 250, 700);
98 		init_color(GNT_COLOR_WHITE, 1000, 1000, 1000);
99 		init_color(GNT_COLOR_GRAY, 699, 699, 699);
100 		init_color(GNT_COLOR_DARK_GRAY, 256, 256, 256);
101 
102 		/* Now some init_pair()s */
103 		init_pair(GNT_COLOR_NORMAL, GNT_COLOR_BLACK, GNT_COLOR_WHITE);
104 		init_pair(GNT_COLOR_HIGHLIGHT, GNT_COLOR_WHITE, GNT_COLOR_BLUE);
105 		init_pair(GNT_COLOR_SHADOW, GNT_COLOR_BLACK, GNT_COLOR_DARK_GRAY);
106 
107 		init_pair(GNT_COLOR_TITLE, GNT_COLOR_WHITE, GNT_COLOR_BLUE);
108 		init_pair(GNT_COLOR_TITLE_D, GNT_COLOR_WHITE, GNT_COLOR_GRAY);
109 
110 		init_pair(GNT_COLOR_TEXT_NORMAL, GNT_COLOR_WHITE, GNT_COLOR_BLUE);
111 		init_pair(GNT_COLOR_HIGHLIGHT_D, GNT_COLOR_BLACK, GNT_COLOR_GRAY);
112 		init_pair(GNT_COLOR_DISABLED, GNT_COLOR_GRAY, GNT_COLOR_WHITE);
113 		init_pair(GNT_COLOR_URGENT, GNT_COLOR_WHITE, GNT_COLOR_RED);
114 	}
115 	else
116 	{
117 		int bg;
118 
119 		if (defaults == OK) {
120 			init_pair(GNT_COLOR_NORMAL, -1, -1);
121 			bg = -1;
122 		} else {
123 			init_pair(GNT_COLOR_NORMAL, COLOR_BLACK, COLOR_WHITE);
124 			bg = COLOR_WHITE;
125 		}
126 		init_pair(GNT_COLOR_DISABLED, COLOR_YELLOW, bg);
127 		init_pair(GNT_COLOR_URGENT, COLOR_GREEN, bg);
128 
129 		init_pair(GNT_COLOR_HIGHLIGHT, COLOR_WHITE, COLOR_BLUE);
130 		init_pair(GNT_COLOR_SHADOW, COLOR_BLACK, COLOR_BLACK);
131 		init_pair(GNT_COLOR_TITLE, COLOR_WHITE, COLOR_BLUE);
132 		init_pair(GNT_COLOR_TITLE_D, COLOR_WHITE, COLOR_BLACK);
133 		init_pair(GNT_COLOR_TEXT_NORMAL, COLOR_WHITE, COLOR_BLUE);
134 		init_pair(GNT_COLOR_HIGHLIGHT_D, COLOR_CYAN, COLOR_BLACK);
135 	}
136 }
137 
138 void
gnt_uninit_colors()139 gnt_uninit_colors()
140 {
141 	if (can_use_custom_color())
142 		restore_colors();
143 }
144 
145 int
gnt_colors_get_color(char * key)146 gnt_colors_get_color(char *key)
147 {
148 	int color;
149 	gboolean custom = can_use_custom_color();
150 
151 	key = g_strstrip(key);
152 
153 	if (strcmp(key, "black") == 0)
154 		color = custom ? GNT_COLOR_BLACK : COLOR_BLACK;
155 	else if (strcmp(key, "red") == 0)
156 		color = custom ? GNT_COLOR_RED : COLOR_RED;
157 	else if (strcmp(key, "green") == 0)
158 		color = custom ? GNT_COLOR_GREEN : COLOR_GREEN;
159 	else if (strcmp(key, "blue") == 0)
160 		color = custom ? GNT_COLOR_BLUE : COLOR_BLUE;
161 	else if (strcmp(key, "white") == 0)
162 		color = custom ? GNT_COLOR_WHITE : COLOR_WHITE;
163 	else if (strcmp(key, "gray") == 0 || strcmp(key, "grey") == 0)
164 		color = custom ? GNT_COLOR_GRAY : COLOR_YELLOW;  /* eh? */
165 	else if (strcmp(key, "darkgray") == 0 || strcmp(key, "darkgrey") == 0)
166 		color = custom ? GNT_COLOR_DARK_GRAY : COLOR_BLACK;
167 	else if (strcmp(key, "magenta") == 0)
168 		color = COLOR_MAGENTA;
169 	else if (strcmp(key, "cyan") == 0)
170 		color = COLOR_CYAN;
171 	else if (strcmp(key, "default") == 0)
172 		color = -1;
173 	else {
174 		g_warning("Invalid color name: %s\n", key);
175 		color = -EINVAL;
176 	}
177 	return color;
178 }
179 
gnt_colors_parse(GKeyFile * kfile)180 void gnt_colors_parse(GKeyFile *kfile)
181 {
182 	GError *error = NULL;
183 	gsize nkeys;
184 	char **keys = g_key_file_get_keys(kfile, "colors", &nkeys, &error);
185 
186 	if (error)
187 	{
188 		gnt_warning("%s", error->message);
189 		g_error_free(error);
190 		error = NULL;
191 	}
192 	else if (nkeys)
193 	{
194 		gnt_init_colors();
195 		while (nkeys--)
196 		{
197 			gsize len;
198 			gchar *key = keys[nkeys];
199 			char **list = g_key_file_get_string_list(kfile, "colors", key, &len, NULL);
200 			if (len == 3)
201 			{
202 				int r = atoi(list[0]);
203 				int g = atoi(list[1]);
204 				int b = atoi(list[2]);
205 				int color = -1;
206 
207 				key = g_ascii_strdown(key, -1);
208 				color = gnt_colors_get_color(key);
209 				g_free(key);
210 				if (color == -EINVAL) {
211 					g_strfreev(list);
212 					continue;
213 				}
214 
215 				init_color(color, r, g, b);
216 			}
217 			g_strfreev(list);
218 		}
219 
220 		g_strfreev(keys);
221 	}
222 
223 	gnt_color_pairs_parse(kfile);
224 }
225 
gnt_color_pairs_parse(GKeyFile * kfile)226 void gnt_color_pairs_parse(GKeyFile *kfile)
227 {
228 	GError *error = NULL;
229 	gsize nkeys;
230 	char **keys = g_key_file_get_keys(kfile, "colorpairs", &nkeys, &error);
231 
232 	if (error)
233 	{
234 		gnt_warning("%s", error->message);
235 		g_error_free(error);
236 		return;
237 	}
238 	else if (nkeys)
239 		gnt_init_colors();
240 
241 	while (nkeys--)
242 	{
243 		gsize len;
244 		gchar *key = keys[nkeys];
245 		char **list = g_key_file_get_string_list(kfile, "colorpairs", key, &len, NULL);
246 		if (len == 2)
247 		{
248 			GntColorType type = 0;
249 			gchar *fgc = g_ascii_strdown(list[0], -1);
250 			gchar *bgc = g_ascii_strdown(list[1], -1);
251 			int fg = gnt_colors_get_color(fgc);
252 			int bg = gnt_colors_get_color(bgc);
253 			g_free(fgc);
254 			g_free(bgc);
255 			if (fg == -EINVAL || bg == -EINVAL) {
256 				g_strfreev(list);
257 				continue;
258 			}
259 
260 			key = g_ascii_strdown(key, -1);
261 
262 			if (strcmp(key, "normal") == 0)
263 				type = GNT_COLOR_NORMAL;
264 			else if (strcmp(key, "highlight") == 0)
265 				type = GNT_COLOR_HIGHLIGHT;
266 			else if (strcmp(key, "highlightd") == 0)
267 				type = GNT_COLOR_HIGHLIGHT_D;
268 			else if (strcmp(key, "shadow") == 0)
269 				type = GNT_COLOR_SHADOW;
270 			else if (strcmp(key, "title") == 0)
271 				type = GNT_COLOR_TITLE;
272 			else if (strcmp(key, "titled") == 0)
273 				type = GNT_COLOR_TITLE_D;
274 			else if (strcmp(key, "text") == 0)
275 				type = GNT_COLOR_TEXT_NORMAL;
276 			else if (strcmp(key, "disabled") == 0)
277 				type = GNT_COLOR_DISABLED;
278 			else if (strcmp(key, "urgent") == 0)
279 				type = GNT_COLOR_URGENT;
280 			else {
281 				g_strfreev(list);
282 				g_free(key);
283 				continue;
284 			}
285 			g_free(key);
286 
287 			init_pair(type, fg, bg);
288 		}
289 		g_strfreev(list);
290 	}
291 
292 	g_strfreev(keys);
293 }
294 
gnt_color_pair(int pair)295 int gnt_color_pair(int pair)
296 {
297 	return (hascolors ? COLOR_PAIR(pair) :
298 		((pair == GNT_COLOR_NORMAL || pair == GNT_COLOR_HIGHLIGHT_D ||
299 		  pair == GNT_COLOR_TITLE_D || pair == GNT_COLOR_DISABLED) ? 0 : (int)A_STANDOUT));
300 }
301 
gnt_color_add_pair(int fg,int bg)302 int gnt_color_add_pair(int fg, int bg)
303 {
304 	init_pair(custom_type, fg, bg);
305 	return custom_type++;
306 }
307