1 /*
2 roxterm - VTE/GTK terminal emulator with tabs
3 Copyright (C) 2004-2015 Tony Houghton <h@realh.co.uk>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
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
20
21 #include "colourscheme.h"
22 #include "dlg.h"
23 #include "dynopts.h"
24
25 #define COLOURSCHEME_GROUP "roxterm colour scheme"
26
27 typedef struct {
28 GdkRGBA *foreground, *background, *cursor, *cursorfg, *bold, *dim;
29 GdkRGBA *palette;
30 int palette_size;
31 } ColourScheme;
32
33 static DynamicOptions *colour_scheme_dynopts = NULL;
34
delete_scheme(ColourScheme * scheme)35 static void delete_scheme(ColourScheme *scheme)
36 {
37 g_free(scheme->foreground);
38 g_free(scheme->background);
39 g_free(scheme->cursor);
40 g_free(scheme->bold);
41 g_free(scheme->dim);
42 g_free(scheme->palette);
43 g_free(scheme);
44 }
45
colour_scheme_reset_cached_data(Options * opts)46 void colour_scheme_reset_cached_data(Options *opts)
47 {
48 ColourScheme *scheme = options_get_data(opts);
49
50 if (scheme)
51 delete_scheme(scheme);
52 scheme = g_new0(ColourScheme, 1);
53 options_associate_data(opts, scheme);
54 }
55
colour_scheme_lookup_and_ref(const char * scheme_name)56 Options *colour_scheme_lookup_and_ref(const char *scheme_name)
57 {
58 Options *opts;
59
60 if (!colour_scheme_dynopts)
61 colour_scheme_dynopts = dynamic_options_get("Colours");
62 opts = dynamic_options_lookup_and_ref(colour_scheme_dynopts,
63 scheme_name, COLOURSCHEME_GROUP);
64 colour_scheme_reset_cached_data(opts);
65 return opts;
66 }
67
colour_scheme_unref(Options * opts)68 gboolean colour_scheme_unref(Options * opts)
69 {
70 ColourScheme *scheme;
71
72 g_return_val_if_fail(opts, FALSE);
73 scheme = options_get_data(opts);
74 g_return_val_if_fail(scheme, FALSE);
75
76 if (dynamic_options_unref(colour_scheme_dynopts,
77 options_get_leafname(opts)))
78 {
79 delete_scheme(scheme);
80 return TRUE;
81 }
82 return FALSE;
83 }
84
colour_scheme_choose_default(int palette_entry)85 static const char *colour_scheme_choose_default(int palette_entry)
86 {
87 static const char *default_colours[16] = {
88 "#2c2c2c", "#c00000", "#00c000", "#c0c000",
89 "#5555ff", "#aa00aa", "#00aaaa", "#e8e8e8",
90 "#000000", "#ff0000", "#00ff00", "#ffff00",
91 "#2666ff", "#ff00ff", "#00ffff", "#ffffff"
92 };
93
94 return default_colours[palette_entry];
95 }
96
97 static gboolean
colour_scheme_parse(ColourScheme * scheme,GdkRGBA * colour,const char * colour_name)98 colour_scheme_parse(ColourScheme * scheme, GdkRGBA *colour,
99 const char *colour_name)
100 {
101 (void) scheme;
102 if (gdk_rgba_parse(colour, colour_name))
103 {
104 return TRUE;
105 }
106 return FALSE;
107 }
108
colour_scheme_lookup_and_parse(Options * opts,ColourScheme * scheme,GdkRGBA * colour,const char * key,const char * default_colour,gboolean warn)109 static gboolean colour_scheme_lookup_and_parse(Options * opts,
110 ColourScheme * scheme, GdkRGBA * colour, const char *key,
111 const char *default_colour, gboolean warn)
112 {
113 char *name = options_lookup_string(opts, key);
114 gboolean result = TRUE;
115
116 if (!name || !colour_scheme_parse(scheme, colour, name))
117 {
118 if (warn && name)
119 {
120 dlg_warning(NULL,
121 _("Unable to parse colour '%s' for %s in scheme %s"),
122 name, key, options_get_leafname(opts));
123 }
124 if (default_colour)
125 result = colour_scheme_parse(scheme, colour, default_colour);
126 else
127 result = FALSE;
128 }
129 if (name)
130 g_free(name);
131 return result;
132 }
133
134 static void
colour_scheme_parse_palette_range(Options * opts,ColourScheme * scheme,int start,int end)135 colour_scheme_parse_palette_range(Options * opts, ColourScheme * scheme,
136 int start, int end)
137 {
138 int n;
139
140 for (n = start; n < 16; ++n)
141 {
142 char key[8];
143 sprintf(key, "%d", n);
144
145 colour_scheme_lookup_and_parse(opts, scheme, &scheme->palette[n], key,
146 colour_scheme_choose_default(n), n < end);
147 }
148 }
149
colour_scheme_parse_palette(Options * opts,ColourScheme * scheme)150 static void colour_scheme_parse_palette(Options * opts, ColourScheme * scheme)
151 {
152 if (!scheme->palette)
153 scheme->palette = g_new0(GdkRGBA, 16);
154 scheme->palette_size = options_lookup_int(opts, "palette_size");
155 switch (scheme->palette_size)
156 {
157 case 8:
158 case 16:
159 /* No problem */
160 break;
161 case 24:
162 /* No longer supported, use 16 */
163 scheme->palette_size = 16;
164 break;
165 case -1:
166 /* Not given, probably fine */
167 scheme->palette_size = 0;
168 break;
169 case 0:
170 break;
171 default:
172 dlg_warning(NULL,
173 _("Invalid palette size %d in colour scheme %s"),
174 scheme->palette_size, options_get_leafname(opts));
175 scheme->palette_size = 0;
176 break;
177 }
178 colour_scheme_parse_palette_range(opts, scheme, 0, scheme->palette_size);
179 }
180
colour_scheme_get_palette(Options * opts)181 GdkRGBA *colour_scheme_get_palette(Options * opts)
182 {
183 ColourScheme *scheme;
184
185 g_return_val_if_fail(opts, NULL);
186 scheme = options_get_data(opts);
187 g_return_val_if_fail(scheme, NULL);
188
189 colour_scheme_parse_palette(opts, scheme);
190 return scheme->palette;
191 }
192
colour_scheme_get_palette_size(Options * opts)193 int colour_scheme_get_palette_size(Options * opts)
194 {
195 ColourScheme *scheme;
196
197 g_return_val_if_fail(opts, 0);
198 scheme = options_get_data(opts);
199 g_return_val_if_fail(scheme, 0);
200
201 colour_scheme_parse_palette(opts, scheme);
202 return scheme->palette_size;
203 }
204
colour_scheme_get_named_colour(Options * opts,const char * name,const char * dflt,size_t member_offset,gboolean allow_null)205 static GdkRGBA *colour_scheme_get_named_colour(Options *opts,
206 const char *name, const char *dflt,
207 size_t member_offset, gboolean allow_null)
208 {
209 ColourScheme *scheme;
210 GdkRGBA **member;
211
212 g_return_val_if_fail(opts, NULL);
213 scheme = options_get_data(opts);
214 g_return_val_if_fail(scheme, NULL);
215
216 member = (GdkRGBA **) (((char *) scheme) + member_offset);
217 if (!*member)
218 {
219 *member = g_new0(GdkRGBA, 1);
220 if (!colour_scheme_lookup_and_parse(opts, scheme, *member,
221 name, allow_null ? NULL : dflt, TRUE))
222 {
223 g_free(*member);
224 *member = NULL;
225 }
226 }
227 return *member;
228 }
229
colour_scheme_get_cursor_colour(Options * opts,gboolean allow_null)230 GdkRGBA *colour_scheme_get_cursor_colour(Options *opts,
231 gboolean allow_null)
232 {
233 return colour_scheme_get_named_colour(opts, "cursor", "#ccc",
234 offsetof(ColourScheme, cursor), allow_null);
235 }
236
colour_scheme_get_cursorfg_colour(Options * opts,gboolean allow_null)237 GdkRGBA *colour_scheme_get_cursorfg_colour(Options * opts,
238 gboolean allow_null)
239 {
240 return colour_scheme_get_named_colour(opts, "cursorfg", "#000",
241 offsetof(ColourScheme, cursorfg), allow_null);
242 }
243
colour_scheme_get_foreground_colour(Options * opts,gboolean allow_null)244 GdkRGBA *colour_scheme_get_foreground_colour(Options * opts,
245 gboolean allow_null)
246 {
247 return colour_scheme_get_named_colour(opts, "foreground", "#ccc",
248 offsetof(ColourScheme, foreground), allow_null);
249 }
250
colour_scheme_get_background_colour(Options * opts,gboolean allow_null)251 GdkRGBA *colour_scheme_get_background_colour(Options * opts,
252 gboolean allow_null)
253 {
254 return colour_scheme_get_named_colour(opts, "background", "#000",
255 offsetof(ColourScheme, background), allow_null);
256 }
257
colour_scheme_get_bold_colour(Options * opts,gboolean allow_null)258 GdkRGBA *colour_scheme_get_bold_colour(Options * opts,
259 gboolean allow_null)
260 {
261 return colour_scheme_get_named_colour(opts, "bold", "#fff",
262 offsetof(ColourScheme, bold), allow_null);
263 }
264
colour_scheme_set_palette_size(Options * opts,int size)265 void colour_scheme_set_palette_size(Options * opts, int size)
266 {
267 ColourScheme *scheme;
268
269 g_return_if_fail(opts);
270 scheme = options_get_data(opts);
271 g_return_if_fail(scheme);
272 scheme->palette_size = size;
273 }
274
colour_scheme_set_colour(Options * opts,ColourScheme * scheme,GdkRGBA ** colour,const char * key,const char * colour_name)275 static void colour_scheme_set_colour(Options *opts, ColourScheme *scheme,
276 GdkRGBA **colour, const char *key, const char *colour_name)
277 {
278 if (!*colour)
279 *colour = g_new(GdkRGBA, 1);
280 if (!colour_name || colour_scheme_parse(scheme, *colour, colour_name))
281 options_set_string(opts, key, colour_name);
282 if (!colour_name)
283 {
284 g_free(*colour);
285 *colour = NULL;
286 }
287 }
288
colour_scheme_set_palette_entry(Options * opts,int index,const char * colour_name)289 void colour_scheme_set_palette_entry(Options * opts, int index,
290 const char *colour_name)
291 {
292 ColourScheme *scheme;
293 char key[8];
294 GdkRGBA *colour;
295
296 g_return_if_fail(opts);
297 g_return_if_fail(colour_name);
298 g_return_if_fail(index >= 0 && index < 16);
299 scheme = options_get_data(opts);
300 g_return_if_fail(scheme);
301 colour = &scheme->palette[index];
302 sprintf(key, "%d", index);
303 colour_scheme_set_colour(opts, scheme, &colour, key, colour_name);
304 }
305
colour_scheme_set_named_colour(Options * opts,const char * field_name,const char * colour_name,size_t member_offset)306 static void colour_scheme_set_named_colour(Options *opts,
307 const char *field_name,
308 const char *colour_name, size_t member_offset)
309 {
310 ColourScheme *scheme;
311 GdkRGBA **member;
312
313 g_return_if_fail(opts);
314 scheme = options_get_data(opts);
315 g_return_if_fail(scheme);
316 member = (GdkRGBA **) (((char *) scheme) + member_offset);
317 colour_scheme_set_colour(opts, scheme, member,
318 field_name, colour_name);
319 }
320
colour_scheme_set_cursor_colour(Options * opts,const char * colour_name)321 void colour_scheme_set_cursor_colour(Options * opts, const char *colour_name)
322 {
323 colour_scheme_set_named_colour(opts, "cursor", colour_name,
324 offsetof(ColourScheme, cursor));
325 }
326
colour_scheme_set_cursorfg_colour(Options * opts,const char * colour_name)327 void colour_scheme_set_cursorfg_colour(Options * opts, const char *colour_name)
328 {
329 colour_scheme_set_named_colour(opts, "cursorfg", colour_name,
330 offsetof(ColourScheme, cursorfg));
331 }
332
colour_scheme_set_foreground_colour(Options * opts,const char * colour_name)333 void colour_scheme_set_foreground_colour(Options * opts,
334 const char *colour_name)
335 {
336 colour_scheme_set_named_colour(opts, "foreground", colour_name,
337 offsetof(ColourScheme, foreground));
338 }
339
colour_scheme_set_background_colour(Options * opts,const char * colour_name)340 void colour_scheme_set_background_colour(Options * opts,
341 const char *colour_name)
342 {
343 colour_scheme_set_named_colour(opts, "background", colour_name,
344 offsetof(ColourScheme, background));
345 }
346
colour_scheme_set_bold_colour(Options * opts,const char * colour_name)347 void colour_scheme_set_bold_colour(Options * opts,
348 const char *colour_name)
349 {
350 colour_scheme_set_named_colour(opts, "bold", colour_name,
351 offsetof(ColourScheme, bold));
352 }
353
354 /* vi:set sw=4 ts=4 noet cindent cino= */
355