finch/libgnt/gntstyle.c

changeset 39360
e7bed293aad5
parent 39302
64aabebb476b
child 39361
a1068caa3600
equal deleted inserted replaced
39302:64aabebb476b 39360:e7bed293aad5
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 "gntinternal.h"
24 #undef GNT_LOG_DOMAIN
25 #define GNT_LOG_DOMAIN "Style"
26
27 #include "gntstyle.h"
28 #include "gntcolors.h"
29 #include "gntws.h"
30
31 #include <glib.h>
32 #include <ctype.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #define MAX_WORKSPACES 99
37
38 static GKeyFile *gkfile;
39
40 static char * str_styles[GNT_STYLES];
41 static int int_styles[GNT_STYLES];
42 static int bool_styles[GNT_STYLES];
43
44 const char *gnt_style_get(GntStyle style)
45 {
46 return str_styles[style];
47 }
48
49 char *gnt_style_get_from_name(const char *group, const char *key)
50 {
51 const char *prg;
52
53 /* gkfile is NULL when run by gtkdoc-scanobj or g-ir-scanner */
54 if (!gkfile)
55 return NULL;
56
57 prg = g_get_prgname();
58 if ((group == NULL || *group == '\0') && prg &&
59 g_key_file_has_group(gkfile, prg))
60 group = prg;
61 if (!group)
62 group = "general";
63 return g_key_file_get_value(gkfile, group, key, NULL);
64 }
65
66 int
67 gnt_style_get_color(char *group, char *key)
68 {
69 int fg = 0, bg = 0;
70 gsize n;
71 char **vals;
72 int ret = 0;
73 vals = gnt_style_get_string_list(group, key, &n);
74 if (vals && n == 2) {
75 fg = gnt_colors_get_color(vals[0]);
76 bg = gnt_colors_get_color(vals[1]);
77 ret = gnt_color_add_pair(fg, bg);
78 }
79 g_strfreev(vals);
80 return ret;
81 }
82
83 char **gnt_style_get_string_list(const char *group, const char *key, gsize *length)
84 {
85 const char *prg = g_get_prgname();
86 if ((group == NULL || *group == '\0') && prg &&
87 g_key_file_has_group(gkfile, prg))
88 group = prg;
89 if (!group)
90 group = "general";
91 return g_key_file_get_string_list(gkfile, group, key, length, NULL);
92 }
93
94 gboolean gnt_style_get_bool(GntStyle style, gboolean def)
95 {
96 const char * str;
97
98 if (bool_styles[style] != -1)
99 return bool_styles[style];
100
101 str = gnt_style_get(style);
102
103 bool_styles[style] = str ? gnt_style_parse_bool(str) : def;
104 return bool_styles[style];
105 }
106
107 gboolean gnt_style_parse_bool(const char *str)
108 {
109 gboolean def = FALSE;
110 int i;
111
112 if (str)
113 {
114 if (g_ascii_strcasecmp(str, "false") == 0)
115 def = FALSE;
116 else if (g_ascii_strcasecmp(str, "true") == 0)
117 def = TRUE;
118 else if (sscanf(str, "%d", &i) == 1)
119 {
120 if (i)
121 def = TRUE;
122 else
123 def = FALSE;
124 }
125 }
126 return def;
127 }
128
129 static void
130 refine(char *text)
131 {
132 char *s = text, *t = text;
133
134 while (*s)
135 {
136 if (*s == '^' && *(s + 1) == '[')
137 {
138 *t = '\033'; /* escape */
139 s++;
140 }
141 else if (*s == '\\')
142 {
143 if (*(s + 1) == '\0')
144 *t = ' ';
145 else
146 {
147 s++;
148 if (*s == 'r' || *s == 'n')
149 *t = '\r';
150 else if (*s == 't')
151 *t = '\t';
152 else
153 *t = *s;
154 }
155 }
156 else
157 *t = *s;
158 t++;
159 s++;
160 }
161 *t = '\0';
162 }
163
164 static char *
165 parse_key(const char *key)
166 {
167 return (char *)gnt_key_translate(key);
168 }
169
170 void gnt_style_read_workspaces(GntWM *wm)
171 {
172 int i;
173 gchar *name;
174 gsize c;
175
176 for (i = 1; i < MAX_WORKSPACES; ++i) {
177 gsize j;
178 GntWS *ws;
179 gchar **titles;
180 char group[32];
181 g_snprintf(group, sizeof(group), "Workspace-%d", i);
182 name = g_key_file_get_value(gkfile, group, "name", NULL);
183 if (!name)
184 return;
185
186 ws = gnt_ws_new(name);
187 gnt_wm_add_workspace(wm, ws);
188 g_free(name);
189
190 titles = g_key_file_get_string_list(gkfile, group, "window-names", &c, NULL);
191 if (titles) {
192 for (j = 0; j < c; ++j)
193 g_hash_table_replace(wm->name_places, g_strdup(titles[j]), ws);
194 g_strfreev(titles);
195 }
196
197 titles = g_key_file_get_string_list(gkfile, group, "window-titles", &c, NULL);
198 if (titles) {
199 for (j = 0; j < c; ++j)
200 g_hash_table_replace(wm->title_places, g_strdup(titles[j]), ws);
201 g_strfreev(titles);
202 }
203 }
204 }
205
206 void gnt_style_read_actions(GType type, GntBindableClass *klass)
207 {
208 char *name;
209 GError *error = NULL;
210
211 /* gkfile is NULL when run by gtkdoc-scanobj or g-ir-scanner */
212 if (!gkfile)
213 return;
214
215 name = g_strdup_printf("%s::binding", g_type_name(type));
216
217 if (g_key_file_has_group(gkfile, name))
218 {
219 gsize len = 0;
220 char **keys;
221
222 keys = g_key_file_get_keys(gkfile, name, &len, &error);
223 if (error)
224 {
225 gnt_warning("%s", error->message);
226 g_error_free(error);
227 g_free(name);
228 return;
229 }
230
231 while (len--)
232 {
233 char *key, *action;
234
235 key = g_strdup(keys[len]);
236 action = g_key_file_get_string(gkfile, name, keys[len], &error);
237
238 if (error)
239 {
240 gnt_warning("%s", error->message);
241 g_error_free(error);
242 error = NULL;
243 }
244 else
245 {
246 const char *keycode = parse_key(key);
247 if (keycode == NULL) {
248 gnt_warning("Invalid key-binding %s", key);
249 } else {
250 gnt_bindable_register_binding(klass, action, keycode, NULL);
251 }
252 }
253 g_free(key);
254 g_free(action);
255 }
256 g_strfreev(keys);
257 }
258 g_free(name);
259 }
260
261 gboolean gnt_style_read_menu_accels(const char *name, GHashTable *table)
262 {
263 char *kname;
264 GError *error = NULL;
265 gboolean ret = FALSE;
266
267 kname = g_strdup_printf("%s::menu", name);
268
269 if (g_key_file_has_group(gkfile, kname))
270 {
271 gsize len = 0;
272 char **keys;
273
274 keys = g_key_file_get_keys(gkfile, kname, &len, &error);
275 if (error)
276 {
277 gnt_warning("%s", error->message);
278 g_error_free(error);
279 g_free(kname);
280 return ret;
281 }
282
283 while (len--)
284 {
285 char *key, *menuid;
286
287 key = g_strdup(keys[len]);
288 menuid = g_key_file_get_string(gkfile, kname, keys[len], &error);
289
290 if (error)
291 {
292 gnt_warning("%s", error->message);
293 g_error_free(error);
294 error = NULL;
295 }
296 else
297 {
298 const char *keycode = parse_key(key);
299 if (keycode == NULL) {
300 gnt_warning("Invalid key-binding %s", key);
301 } else {
302 ret = TRUE;
303 g_hash_table_replace(table, g_strdup(keycode), menuid);
304 menuid = NULL;
305 }
306 }
307 g_free(key);
308 g_free(menuid);
309 }
310 g_strfreev(keys);
311 }
312
313 g_free(kname);
314 return ret;
315 }
316
317 void gnt_styles_get_keyremaps(GType type, GHashTable *hash)
318 {
319 char *name;
320 GError *error = NULL;
321
322 name = g_strdup_printf("%s::remap", g_type_name(type));
323
324 if (g_key_file_has_group(gkfile, name))
325 {
326 gsize len = 0;
327 char **keys;
328
329 keys = g_key_file_get_keys(gkfile, name, &len, &error);
330 if (error)
331 {
332 gnt_warning("%s", error->message);
333 g_error_free(error);
334 g_free(name);
335 return;
336 }
337
338 while (len--)
339 {
340 char *key, *replace;
341
342 key = g_strdup(keys[len]);
343 replace = g_key_file_get_string(gkfile, name, keys[len], &error);
344
345 if (error)
346 {
347 gnt_warning("%s", error->message);
348 g_error_free(error);
349 error = NULL;
350 g_free(key);
351 }
352 else
353 {
354 refine(key);
355 refine(replace);
356 g_hash_table_insert(hash, key, replace);
357 }
358 }
359 g_strfreev(keys);
360 }
361
362 g_free(name);
363 }
364
365 static void
366 read_general_style(GKeyFile *kfile)
367 {
368 GError *error = NULL;
369 gsize nkeys;
370 const char *prgname = g_get_prgname();
371 char **keys = NULL;
372 int i;
373 struct
374 {
375 const char *style;
376 GntStyle en;
377 } styles[] = {{"shadow", GNT_STYLE_SHADOW},
378 {"customcolor", GNT_STYLE_COLOR},
379 {"mouse", GNT_STYLE_MOUSE},
380 {"wm", GNT_STYLE_WM},
381 {"remember_position", GNT_STYLE_REMPOS},
382 {NULL, 0}};
383
384 if (prgname && *prgname)
385 keys = g_key_file_get_keys(kfile, prgname, &nkeys, NULL);
386
387 if (keys == NULL) {
388 prgname = "general";
389 keys = g_key_file_get_keys(kfile, prgname, &nkeys, &error);
390 }
391
392 if (error)
393 {
394 gnt_warning("%s", error->message);
395 g_error_free(error);
396 }
397 else
398 {
399 for (i = 0; styles[i].style; i++)
400 {
401 str_styles[styles[i].en] =
402 g_key_file_get_string(kfile, prgname, styles[i].style, NULL);
403 }
404 }
405 g_strfreev(keys);
406 }
407
408 void gnt_style_read_configure_file(const char *filename)
409 {
410 GError *error = NULL;
411 gkfile = g_key_file_new();
412
413 if (!g_key_file_load_from_file(gkfile, filename,
414 G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error))
415 {
416 gnt_warning("%s", error->message);
417 g_error_free(error);
418 return;
419 }
420 gnt_colors_parse(gkfile);
421 read_general_style(gkfile);
422 }
423
424 void gnt_init_styles()
425 {
426 int i;
427 for (i = 0; i < GNT_STYLES; i++)
428 {
429 str_styles[i] = NULL;
430 int_styles[i] = -1;
431 bool_styles[i] = -1;
432 }
433 }
434
435 void gnt_uninit_styles()
436 {
437 int i;
438 for (i = 0; i < GNT_STYLES; i++) {
439 g_free(str_styles[i]);
440 str_styles[i] = NULL;
441 }
442
443 g_key_file_free(gkfile);
444 gkfile = NULL;
445 }
446

mercurial