| 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 |
|