Prepare for release 1.11.2.
[xxxterm.git] / settings.c
blob5f68b3ffc0aa0f3d1ca6db5b0a662667b7280cbe
1 /*
2 * Copyright (c) 2010, 2011 Marco Peereboom <marco@peereboom.us>
3 * Copyright (c) 2011 Stevan Andjelkovic <stevan@student.chalmers.se>
4 * Copyright (c) 2010, 2011 Edd Barrett <vext01@gmail.com>
5 * Copyright (c) 2011 Todd T. Fries <todd@fries.net>
6 * Copyright (c) 2011 Raphael Graf <r@undefined.ch>
7 * Copyright (c) 2011 Michal Mazurek <akfaew@jasminek.net>
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 #include <xxxterm.h>
24 /* globals */
25 SoupURI *proxy_uri = NULL;
26 PangoFontDescription *cmd_font;
27 PangoFontDescription *oops_font;
28 PangoFontDescription *statusbar_font;
29 PangoFontDescription *tabbar_font;
31 /* settings that require restart */
32 int tabless = 0; /* allow only 1 tab */
33 int enable_socket = 0;
34 int single_instance = 0; /* only allow one xxxterm to run */
35 int fancy_bar = 1; /* fancy toolbar */
36 int browser_mode = XT_BM_NORMAL;
37 int gui_mode = XT_GM_CLASSIC;
38 int enable_localstorage = 1;
39 char *statusbar_elems = NULL;
41 /* runtime settings */
42 int show_tabs = 1; /* show tabs on notebook */
43 int tab_style = XT_TABS_NORMAL; /* tab bar style */
44 int show_url = 1; /* show url toolbar on notebook */
45 int show_statusbar = 0; /* vimperator style status bar */
46 int ctrl_click_focus = 0; /* ctrl click gets focus */
47 int cookies_enabled = 1; /* enable cookies */
48 int read_only_cookies = 0; /* enable to not write cookies */
49 int enable_scripts = 1;
50 int enable_plugins = 1;
51 gfloat default_zoom_level = 1.0;
52 char default_script[PATH_MAX];
53 int window_height = 768;
54 int window_width = 1024;
55 int window_maximize = 0;
56 int icon_size = 2; /* 1 = smallest, 2+ = bigger */
57 int refresh_interval = 10; /* download refresh interval */
58 int enable_plugin_whitelist = 0;
59 int enable_cookie_whitelist = 0;
60 int enable_js_whitelist = 0;
61 int session_timeout = 3600; /* cookie session timeout */
62 int cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
63 char *ssl_ca_file = NULL;
64 char *resource_dir = NULL;
65 gboolean ssl_strict_certs = FALSE;
66 gboolean enable_strict_transport = TRUE;
67 int append_next = 1; /* append tab after current tab */
68 char *home = NULL;
69 char *search_string = NULL;
70 char *http_proxy = NULL;
71 char download_dir[PATH_MAX];
72 int download_mode = XT_DM_START;
73 char runtime_settings[PATH_MAX]; /* override of settings */
74 int allow_volatile_cookies = 0;
75 int color_visited_uris = 1;
76 int save_global_history = 0; /* save global history to disk */
77 struct user_agent *user_agent = NULL;
78 int save_rejected_cookies = 0;
79 int session_autosave = 0;
80 int guess_search = 0;
81 int dns_prefetch = FALSE;
82 gint max_connections = 25;
83 gint max_host_connections = 5;
84 gint enable_spell_checking = 0;
85 char *spell_check_languages = NULL;
86 int xterm_workaround = 0;
87 char *url_regex = NULL;
88 int history_autosave = 0;
89 char search_file[PATH_MAX];
90 char command_file[PATH_MAX];
91 char *encoding = NULL;
92 int autofocus_onload = 0;
93 int js_autorun_enabled = 1;
94 int edit_mode = XT_EM_HYBRID;
95 int userstyle_global = 0;
96 int auto_load_images = 1;
97 int enable_autoscroll = 0;
98 int enable_favicon_entry = 1;
99 int enable_favicon_tabs = 0;
100 char *external_editor = NULL;
101 int referer_mode = XT_REFERER_ALWAYS;
102 char *referer_custom = NULL;
104 char *cmd_font_name = NULL;
105 char *oops_font_name = NULL;
106 char *statusbar_font_name = NULL;
107 char *tabbar_font_name = NULL;
109 char *get_download_dir(struct settings *);
110 char *get_default_script(struct settings *);
111 char *get_runtime_dir(struct settings *);
112 char *get_tab_style(struct settings *);
113 char *get_edit_mode(struct settings *);
114 char *get_download_mode(struct settings *);
115 char *get_work_dir(struct settings *);
116 char *get_referer(struct settings *);
118 int add_cookie_wl(struct settings *, char *);
119 int add_js_wl(struct settings *, char *);
120 int add_pl_wl(struct settings *, char *);
121 int add_mime_type(struct settings *, char *);
122 int add_alias(struct settings *, char *);
123 int add_kb(struct settings *, char *);
124 int add_ua(struct settings *, char *);
126 int set_download_dir(struct settings *, char *);
127 int set_default_script(struct settings *, char *);
128 int set_runtime_dir(struct settings *, char *);
129 int set_tab_style(struct settings *, char *);
130 int set_edit_mode(struct settings *, char *);
131 int set_work_dir(struct settings *, char *);
132 int set_auto_load_images(char *value);
133 int set_enable_autoscroll(char *value);
134 int set_enable_favicon_entry(char *value);
135 int set_enable_favicon_tabs(char *value);
136 int set_download_mode(struct settings *, char *);
137 int set_download_mode_rt(char *);
138 int set_referer(struct settings *, char *);
139 int set_referer_rt(char *);
140 int set_external_editor(char *);
142 void walk_mime_type(struct settings *, void (*)(struct settings *,
143 char *, void *), void *);
144 void walk_alias(struct settings *, void (*)(struct settings *,
145 char *, void *), void *);
146 void walk_cookie_wl(struct settings *, void (*)(struct settings *,
147 char *, void *), void *);
148 void walk_js_wl(struct settings *, void (*)(struct settings *,
149 char *, void *), void *);
150 void walk_pl_wl(struct settings *, void (*)(struct settings *,
151 char *, void *), void *);
152 void walk_kb(struct settings *, void (*)(struct settings *, char *,
153 void *), void *);
154 void walk_ua(struct settings *, void (*)(struct settings *, char *,
155 void *), void *);
158 set_http_proxy(char *proxy)
160 SoupURI *uri;
162 if (proxy == NULL)
163 return (1);
165 /* see if we need to clear it instead */
166 if (strlen(proxy) == 0) {
167 setup_proxy(NULL);
168 return (0);
171 uri = soup_uri_new(proxy);
172 if (uri == NULL || !SOUP_URI_VALID_FOR_HTTP(uri))
173 return (1);
175 setup_proxy(proxy);
177 soup_uri_free(uri);
179 return (0);
182 struct special {
183 int (*set)(struct settings *, char *);
184 char *(*get)(struct settings *);
185 void (*walk)(struct settings *,
186 void (*cb)(struct settings *, char *, void *),
187 void *);
190 struct special s_browser_mode = {
191 set_browser_mode,
192 get_browser_mode,
193 NULL
196 struct special s_gui_mode = {
197 set_gui_mode,
198 get_gui_mode,
199 NULL
202 struct special s_cookie = {
203 set_cookie_policy,
204 get_cookie_policy,
205 NULL
208 struct special s_alias = {
209 add_alias,
210 NULL,
211 walk_alias
214 struct special s_mime = {
215 add_mime_type,
216 NULL,
217 walk_mime_type
220 struct special s_js = {
221 add_js_wl,
222 NULL,
223 walk_js_wl
226 struct special s_pl = {
227 add_pl_wl,
228 NULL,
229 walk_pl_wl
232 struct special s_kb = {
233 add_kb,
234 NULL,
235 walk_kb
238 struct special s_cookie_wl = {
239 add_cookie_wl,
240 NULL,
241 walk_cookie_wl
244 struct special s_default_script = {
245 set_default_script,
246 get_default_script,
247 NULL
250 struct special s_download_dir = {
251 set_download_dir,
252 get_download_dir,
253 NULL
256 struct special s_work_dir = {
257 set_work_dir,
258 get_work_dir,
259 NULL
262 struct special s_tab_style = {
263 set_tab_style,
264 get_tab_style,
265 NULL
268 struct special s_edit_mode = {
269 set_edit_mode,
270 get_edit_mode,
271 NULL
274 struct special s_download_mode = {
275 set_download_mode,
276 get_download_mode,
277 NULL
280 struct special s_ua = {
281 add_ua,
282 NULL,
283 walk_ua
286 struct special s_referer = {
287 set_referer,
288 get_referer,
289 NULL
292 struct settings rs[] = {
293 { "allow_volatile_cookies", XT_S_INT, 0, &allow_volatile_cookies, NULL, NULL },
294 { "append_next", XT_S_INT, 0, &append_next, NULL, NULL },
295 { "autofocus_onload", XT_S_INT, 0, &autofocus_onload, NULL, NULL },
296 { "browser_mode", XT_S_INT, 0, NULL, NULL,&s_browser_mode },
297 { "gui_mode", XT_S_INT, 0, NULL, NULL,&s_gui_mode },
298 { "color_visited_uris", XT_S_INT, 0, &color_visited_uris, NULL, NULL },
299 { "cookie_policy", XT_S_INT, 0, NULL, NULL,&s_cookie },
300 { "cookies_enabled", XT_S_INT, 0, &cookies_enabled, NULL, NULL },
301 { "ctrl_click_focus", XT_S_INT, 0, &ctrl_click_focus, NULL, NULL },
302 { "default_zoom_level", XT_S_FLOAT, 0, NULL, NULL, NULL, &default_zoom_level },
303 { "default_script", XT_S_STR, 0, NULL, NULL,&s_default_script },
304 { "download_dir", XT_S_STR, 0, NULL, NULL,&s_download_dir },
305 { "download_mode", XT_S_STR, 0, NULL, NULL,&s_download_mode, NULL, set_download_mode_rt },
306 { "edit_mode", XT_S_STR, 0, NULL, NULL,&s_edit_mode },
307 { "enable_cookie_whitelist", XT_S_INT, 0, &enable_cookie_whitelist, NULL, NULL },
308 { "enable_js_whitelist", XT_S_INT, 0, &enable_js_whitelist, NULL, NULL },
309 { "enable_plugin_whitelist", XT_S_INT, 0, &enable_plugin_whitelist, NULL, NULL },
310 { "enable_localstorage", XT_S_INT, 0, &enable_localstorage, NULL, NULL },
311 { "enable_plugins", XT_S_INT, 0, &enable_plugins, NULL, NULL },
312 { "enable_scripts", XT_S_INT, 0, &enable_scripts, NULL, NULL },
313 { "enable_socket", XT_S_INT, XT_SF_RESTART,&enable_socket, NULL, NULL },
314 { "enable_spell_checking", XT_S_INT, 0, &enable_spell_checking, NULL, NULL },
315 { "encoding", XT_S_STR, 0, NULL, &encoding, NULL },
316 { "external_editor", XT_S_STR,0, NULL, &external_editor, NULL, NULL, set_external_editor },
317 { "fancy_bar", XT_S_INT, XT_SF_RESTART,&fancy_bar, NULL, NULL },
318 { "guess_search", XT_S_INT, 0, &guess_search, NULL, NULL },
319 { "history_autosave", XT_S_INT, 0, &history_autosave, NULL, NULL },
320 { "home", XT_S_STR, 0, NULL, &home, NULL },
321 { "http_proxy", XT_S_STR, 0, NULL, &http_proxy, NULL, NULL, set_http_proxy },
322 { "icon_size", XT_S_INT, 0, &icon_size, NULL, NULL },
323 { "js_autorun_enabled", XT_S_INT, 0, &js_autorun_enabled, NULL, NULL },
324 { "max_connections", XT_S_INT, XT_SF_RESTART,&max_connections, NULL, NULL },
325 { "max_host_connections", XT_S_INT, XT_SF_RESTART,&max_host_connections, NULL, NULL },
326 { "read_only_cookies", XT_S_INT, 0, &read_only_cookies, NULL, NULL },
327 { "refresh_interval", XT_S_INT, 0, &refresh_interval, NULL, NULL },
328 { "resource_dir", XT_S_STR, 0, NULL, &resource_dir, NULL },
329 { "search_string", XT_S_STR, 0, NULL, &search_string, NULL },
330 { "save_global_history", XT_S_INT, XT_SF_RESTART,&save_global_history, NULL, NULL },
331 { "save_rejected_cookies", XT_S_INT, XT_SF_RESTART,&save_rejected_cookies, NULL, NULL },
332 { "session_timeout", XT_S_INT, 0, &session_timeout, NULL, NULL },
333 { "session_autosave", XT_S_INT, 0, &session_autosave, NULL, NULL },
334 { "single_instance", XT_S_INT, XT_SF_RESTART,&single_instance, NULL, NULL },
335 { "show_tabs", XT_S_INT, 0, &show_tabs, NULL, NULL },
336 { "show_url", XT_S_INT, 0, &show_url, NULL, NULL },
337 { "show_statusbar", XT_S_INT, 0, &show_statusbar, NULL, NULL },
338 { "spell_check_languages", XT_S_STR, 0, NULL, &spell_check_languages, NULL },
339 { "ssl_ca_file", XT_S_STR, 0, NULL, &ssl_ca_file, NULL },
340 { "ssl_strict_certs", XT_S_INT, 0, &ssl_strict_certs, NULL, NULL },
341 { "enable_strict_transport", XT_S_INT, 0, &enable_strict_transport, NULL, NULL },
342 { "statusbar_elems", XT_S_STR, 0, NULL, &statusbar_elems, NULL },
343 { "tab_style", XT_S_STR, 0, NULL, NULL,&s_tab_style },
344 { "userstyle_global", XT_S_INT, 0, &userstyle_global, NULL, NULL },
345 { "url_regex", XT_S_STR, 0, NULL, &url_regex, NULL },
346 { "window_height", XT_S_INT, 0, &window_height, NULL, NULL },
347 { "window_width", XT_S_INT, 0, &window_width, NULL, NULL },
348 { "window_maximize", XT_S_INT, 0, &window_maximize, NULL, NULL },
349 { "work_dir", XT_S_STR, 0, NULL, NULL,&s_work_dir },
350 { "xterm_workaround", XT_S_INT, 0, &xterm_workaround, NULL, NULL },
351 { "auto_load_images", XT_S_INT, 0, &auto_load_images, NULL, NULL, NULL, set_auto_load_images },
352 { "enable_autoscroll", XT_S_INT, 0, &enable_autoscroll, NULL, NULL, NULL, set_enable_autoscroll },
353 { "enable_favicon_entry", XT_S_INT, 0, &enable_favicon_entry, NULL, NULL, NULL, set_enable_favicon_entry },
354 { "enable_favicon_tabs", XT_S_INT, 0, &enable_favicon_tabs, NULL, NULL, NULL, set_enable_favicon_tabs },
355 { "referer", XT_S_STR, 0, NULL, NULL,&s_referer, NULL, set_referer_rt },
357 /* font settings */
358 { "cmd_font", XT_S_STR, 0, NULL, &cmd_font_name, NULL },
359 { "oops_font", XT_S_STR, 0, NULL, &oops_font_name, NULL },
360 { "statusbar_font", XT_S_STR, 0, NULL, &statusbar_font_name, NULL },
361 { "tabbar_font", XT_S_STR, 0, NULL, &tabbar_font_name, NULL },
363 /* runtime settings */
364 { "alias", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_alias },
365 { "cookie_wl", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_cookie_wl },
366 { "js_wl", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_js },
367 { "keybinding", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_kb },
368 { "mime_type", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_mime },
369 { "pl_wl", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_pl },
370 { "user_agent", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_ua },
373 size_t
374 get_settings_size(void)
376 return (LENGTH(rs));
379 char *
380 get_setting_name(int i)
382 if (i > LENGTH(rs))
383 return (NULL);
384 return (rs[i].name);
387 char *
388 get_as_string(struct settings *s)
390 char *r = NULL;
392 if (s == NULL)
393 return (NULL);
395 if (s->s) {
396 if (s->s->get)
397 r = s->s->get(s);
398 else
399 warnx("get_as_string skip %s\n", s->name);
400 } else if (s->type == XT_S_INT)
401 r = g_strdup_printf("%d", *s->ival);
402 else if (s->type == XT_S_STR)
403 r = g_strdup(*s->sval);
404 else if (s->type == XT_S_FLOAT)
405 r = g_strdup_printf("%f", *s->fval);
406 else
407 r = g_strdup_printf("INVALID TYPE");
409 return (r);
412 void
413 settings_walk(void (*cb)(struct settings *, char *, void *), void *cb_args)
415 int i;
416 char *s;
418 for (i = 0; i < LENGTH(rs); i++) {
419 if (rs[i].s && rs[i].s->walk)
420 rs[i].s->walk(&rs[i], cb, cb_args);
421 else {
422 s = get_as_string(&rs[i]);
423 cb(&rs[i], s, cb_args);
424 g_free(s);
430 set_browser_mode(struct settings *s, char *val)
432 if (!strcmp(val, "whitelist")) {
433 browser_mode = XT_BM_WHITELIST;
434 allow_volatile_cookies = 0;
435 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY;
436 cookies_enabled = 1;
437 enable_cookie_whitelist = 1;
438 enable_plugin_whitelist = 1;
439 enable_plugins = 0;
440 read_only_cookies = 0;
441 save_rejected_cookies = 0;
442 session_timeout = 3600;
443 enable_scripts = 0;
444 enable_js_whitelist = 1;
445 enable_localstorage = 0;
446 referer_mode = XT_REFERER_SAME_DOMAIN;
447 } else if (!strcmp(val, "normal")) {
448 browser_mode = XT_BM_NORMAL;
449 allow_volatile_cookies = 0;
450 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
451 cookies_enabled = 1;
452 enable_cookie_whitelist = 0;
453 enable_plugin_whitelist = 0;
454 enable_plugins = 1;
455 read_only_cookies = 0;
456 save_rejected_cookies = 0;
457 session_timeout = 3600;
458 enable_scripts = 1;
459 enable_js_whitelist = 0;
460 enable_localstorage = 1;
461 referer_mode = XT_REFERER_ALWAYS;
462 } else if (!strcmp(val, "kiosk")) {
463 browser_mode = XT_BM_KIOSK;
464 allow_volatile_cookies = 0;
465 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
466 cookies_enabled = 1;
467 enable_cookie_whitelist = 0;
468 enable_plugin_whitelist = 0;
469 enable_plugins = 1;
470 read_only_cookies = 0;
471 save_rejected_cookies = 0;
472 session_timeout = 3600;
473 enable_scripts = 1;
474 enable_js_whitelist = 0;
475 enable_localstorage = 1;
476 referer_mode = XT_REFERER_ALWAYS;
477 show_tabs = 0;
478 tabless = 1;
479 } else
480 return (1);
482 return (0);
485 char *
486 get_browser_mode(struct settings *s)
488 char *r = NULL;
490 if (browser_mode == XT_BM_WHITELIST)
491 r = g_strdup("whitelist");
492 else if (browser_mode == XT_BM_NORMAL)
493 r = g_strdup("normal");
494 else if (browser_mode == XT_BM_KIOSK)
495 r = g_strdup("kiosk");
496 else
497 return (NULL);
499 return (r);
503 set_gui_mode(struct settings *s, char *val)
505 if (!strcmp(val, "classic")) {
506 fancy_bar = 1;
507 show_tabs = 1;
508 tab_style = XT_TABS_NORMAL;
509 show_url = 1;
510 show_statusbar = 0;
511 } else if (!strcmp(val, "minimal")) {
512 fancy_bar = 0;
513 show_tabs = 1;
514 tab_style = XT_TABS_COMPACT;
515 show_url = 0;
516 show_statusbar = 1;
517 } else
518 return (1);
520 return (0);
523 char *
524 get_gui_mode(struct settings *s)
526 char *r = NULL;
528 if (gui_mode == XT_GM_CLASSIC)
529 r = g_strdup("classic");
530 else if (browser_mode == XT_GM_MINIMAL)
531 r = g_strdup("minimal");
532 else
533 return (NULL);
535 return (r);
539 set_cookie_policy(struct settings *s, char *val)
541 if (!strcmp(val, "no3rdparty"))
542 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY;
543 else if (!strcmp(val, "accept"))
544 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
545 else if (!strcmp(val, "reject"))
546 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_NEVER;
547 else
548 return (1);
550 return (0);
553 char *
554 get_cookie_policy(struct settings *s)
556 char *r = NULL;
558 if (cookie_policy == SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY)
559 r = g_strdup("no3rdparty");
560 else if (cookie_policy == SOUP_COOKIE_JAR_ACCEPT_ALWAYS)
561 r = g_strdup("accept");
562 else if (cookie_policy == SOUP_COOKIE_JAR_ACCEPT_NEVER)
563 r = g_strdup("reject");
564 else
565 return (NULL);
567 return (r);
570 char *
571 get_default_script(struct settings *s)
573 if (default_script[0] == '\0')
574 return (0);
575 return (g_strdup(default_script));
579 set_default_script(struct settings *s, char *val)
581 if (val[0] == '~')
582 snprintf(default_script, sizeof default_script, "%s" PS "%s",
583 pwd->pw_dir, &val[1]);
584 else
585 strlcpy(default_script, val, sizeof default_script);
587 return (0);
590 char *
591 get_download_dir(struct settings *s)
593 if (download_dir[0] == '\0')
594 return (0);
595 return (g_strdup(download_dir));
599 set_download_dir(struct settings *s, char *val)
601 if (val[0] == '~')
602 snprintf(download_dir, sizeof download_dir, "%s" PS "%s",
603 pwd->pw_dir, &val[1]);
604 else
605 strlcpy(download_dir, val, sizeof download_dir);
607 return (0);
611 add_alias(struct settings *s, char *line)
613 char *l, *alias;
614 struct alias *a = NULL;
616 if (s == NULL || line == NULL) {
617 show_oops(NULL, "add_alias invalid parameters");
618 return (1);
621 l = line;
622 a = g_malloc(sizeof(*a));
624 if ((alias = strsep(&l, " \t,")) == NULL || l == NULL) {
625 show_oops(NULL, "add_alias: incomplete alias definition");
626 goto bad;
628 if (strlen(alias) == 0 || strlen(l) == 0) {
629 show_oops(NULL, "add_alias: invalid alias definition");
630 goto bad;
633 a->a_name = g_strdup(alias);
634 a->a_uri = g_strdup(l);
636 DNPRINTF(XT_D_CONFIG, "add_alias: %s for %s\n", a->a_name, a->a_uri);
638 TAILQ_INSERT_TAIL(&aliases, a, entry);
640 return (0);
641 bad:
642 if (a)
643 g_free(a);
644 return (1);
647 void
648 walk_alias(struct settings *s,
649 void (*cb)(struct settings *, char *, void *), void *cb_args)
651 struct alias *a;
652 char *str;
654 if (s == NULL || cb == NULL) {
655 show_oops(NULL, "walk_alias invalid parameters");
656 return;
659 TAILQ_FOREACH(a, &aliases, entry) {
660 str = g_strdup_printf("%s --> %s", a->a_name, a->a_uri);
661 cb(s, str, cb_args);
662 g_free(str);
667 add_mime_type(struct settings *s, char *line)
669 char *mime_type;
670 char *l;
671 struct mime_type *m = NULL;
672 int downloadfirst = 0;
674 /* XXX this could be smarter */
676 if (line == NULL || strlen(line) == 0) {
677 show_oops(NULL, "add_mime_type invalid parameters");
678 return (1);
681 l = line;
682 if (*l == '@') {
683 downloadfirst = 1;
684 l++;
686 m = g_malloc(sizeof(*m));
688 if ((mime_type = strsep(&l, " \t,")) == NULL || l == NULL) {
689 show_oops(NULL, "add_mime_type: invalid mime_type");
690 goto bad;
692 if (mime_type[strlen(mime_type) - 1] == '*') {
693 mime_type[strlen(mime_type) - 1] = '\0';
694 m->mt_default = 1;
695 } else
696 m->mt_default = 0;
698 if (strlen(mime_type) == 0 || strlen(l) == 0) {
699 show_oops(NULL, "add_mime_type: invalid mime_type");
700 goto bad;
703 m->mt_type = g_strdup(mime_type);
704 m->mt_action = g_strdup(l);
705 m->mt_download = downloadfirst;
707 DNPRINTF(XT_D_CONFIG, "add_mime_type: type %s action %s default %d\n",
708 m->mt_type, m->mt_action, m->mt_default);
710 TAILQ_INSERT_TAIL(&mtl, m, entry);
712 return (0);
713 bad:
714 if (m)
715 g_free(m);
716 return (1);
719 void
720 walk_mime_type(struct settings *s,
721 void (*cb)(struct settings *, char *, void *), void *cb_args)
723 struct mime_type *m;
724 char *str;
726 if (s == NULL || cb == NULL) {
727 show_oops(NULL, "walk_mime_type invalid parameters");
728 return;
731 TAILQ_FOREACH(m, &mtl, entry) {
732 str = g_strdup_printf("%s%s --> %s",
733 m->mt_type,
734 m->mt_default ? "*" : "",
735 m->mt_action);
736 cb(s, str, cb_args);
737 g_free(str);
741 /* inherent to GTK not all keys will be caught at all times */
742 /* XXX sort key bindings */
743 struct key_binding keys[] = {
744 { "command_mode", 0, 1, GDK_Escape },
745 { "insert_mode", 0, 0, GDK_i },
746 { "cookiejar", MOD1, 1, GDK_j },
747 { "downloadmgr", MOD1, 1, GDK_d },
748 { "history", MOD1, 1, GDK_h },
749 { "print", CTRL, 1, GDK_p },
750 { "search", 0, 0, GDK_slash },
751 { "searchb", 0, 0, GDK_question },
752 { "statustoggle", CTRL, 1, GDK_n },
753 { "command", 0, 0, GDK_colon },
754 { "qa", CTRL, 1, GDK_q },
755 { "restart", MOD1, 1, GDK_q },
756 { "js toggle", CTRL, 1, GDK_j },
757 { "plugin toggle", MOD1, 1, GDK_p },
758 { "cookie toggle", MOD1, 1, GDK_c },
759 { "togglesrc", CTRL, 1, GDK_s },
760 { "yankuri", 0, 0, GDK_y },
761 { "pasteuricur", 0, 0, GDK_p },
762 { "pasteurinew", 0, 0, GDK_P },
763 { "toplevel toggle", 0, 1, GDK_F4 },
764 { "help", 0, 1, GDK_F1 },
765 { "run_script", MOD1, 1, GDK_r },
766 { "proxy toggle", 0, 1, GDK_F2 },
767 { "editelement", CTRL, 1, GDK_i },
768 { "passthrough", CTRL, 1, GDK_z },
770 /* search */
771 { "searchnext", 0, 0, GDK_n },
772 { "searchprevious", 0, 0, GDK_N },
774 /* focus */
775 { "focusaddress", 0, 1, GDK_F6 },
776 { "focussearch", 0, 1, GDK_F7 },
778 /* hinting */
779 { "hinting", 0, 0, GDK_f },
780 { "hinting", 0, 0, GDK_period },
781 { "hinting_newtab", SHFT, 0, GDK_F },
782 { "hinting_newtab", 0, 0, GDK_comma },
784 /* custom stylesheet */
785 { "userstyle", 0, 0, GDK_s },
786 { "userstyle_global", SHFT, 0, GDK_S },
788 /* navigation */
789 { "goback", 0, 0, GDK_BackSpace },
790 { "goback", MOD1, 1, GDK_Left },
791 { "goforward", SHFT, 1, GDK_BackSpace },
792 { "goforward", MOD1, 1, GDK_Right },
793 { "reload", 0, 1, GDK_F5 },
794 { "reload", CTRL, 1, GDK_r },
795 { "reload", CTRL, 1, GDK_l },
796 { "favorites", MOD1, 1, GDK_f },
798 /* vertical movement */
799 { "scrolldown", 0, 0, GDK_j },
800 { "scrolldown", 0, 0, GDK_Down },
801 { "scrollup", 0, 0, GDK_Up },
802 { "scrollup", 0, 0, GDK_k },
803 { "scrollbottom", 0, 0, GDK_G },
804 { "scrollbottom", 0, 0, GDK_End },
805 { "scrolltop", 0, 0, GDK_Home },
806 { "scrollpagedown", 0, 0, GDK_space },
807 { "scrollpagedown", CTRL, 1, GDK_f },
808 { "scrollhalfdown", CTRL, 1, GDK_d },
809 { "scrollpagedown", 0, 0, GDK_Page_Down },
810 { "scrollpageup", 0, 0, GDK_Page_Up },
811 { "scrollpageup", CTRL, 1, GDK_b },
812 { "scrollhalfup", CTRL, 1, GDK_u },
813 /* horizontal movement */
814 { "scrollright", 0, 0, GDK_l },
815 { "scrollright", 0, 0, GDK_Right },
816 { "scrollleft", 0, 0, GDK_Left },
817 { "scrollleft", 0, 0, GDK_h },
818 { "scrollfarright", 0, 0, GDK_dollar },
819 { "scrollfarleft", 0, 0, GDK_0 },
821 /* tabs */
822 { "tabnew", CTRL, 1, GDK_t },
823 { "999tabnew", CTRL, 1, GDK_T },
824 { "tabclose", CTRL, 1, GDK_w },
825 { "tabundoclose", 0, 0, GDK_U },
826 { "tabnext 1", CTRL, 1, GDK_1 },
827 { "tabnext 2", CTRL, 1, GDK_2 },
828 { "tabnext 3", CTRL, 1, GDK_3 },
829 { "tabnext 4", CTRL, 1, GDK_4 },
830 { "tabnext 5", CTRL, 1, GDK_5 },
831 { "tabnext 6", CTRL, 1, GDK_6 },
832 { "tabnext 7", CTRL, 1, GDK_7 },
833 { "tabnext 8", CTRL, 1, GDK_8 },
834 { "tabnext 9", CTRL, 1, GDK_9 },
835 { "tabfirst", CTRL, 1, GDK_less },
836 { "tablast", CTRL, 1, GDK_greater },
837 { "tabprevious", CTRL, 1, GDK_Left },
838 { "tabnext", CTRL, 1, GDK_Right },
839 { "focusout", CTRL, 1, GDK_minus },
840 { "focusin", CTRL, 1, GDK_plus },
841 { "focusin", CTRL, 1, GDK_equal },
842 { "focusreset", CTRL, 1, GDK_0 },
844 /* command aliases (handy when -S flag is used) */
845 { "promptopen", 0, 1, GDK_F9 },
846 { "promptopencurrent", 0, 1, GDK_F10 },
847 { "prompttabnew", 0, 1, GDK_F11 },
848 { "prompttabnewcurrent",0, 1, GDK_F12 },
851 void
852 walk_kb(struct settings *s,
853 void (*cb)(struct settings *, char *, void *), void *cb_args)
855 struct key_binding *k;
856 char str[1024];
858 if (s == NULL || cb == NULL) {
859 show_oops(NULL, "walk_kb invalid parameters");
860 return;
863 TAILQ_FOREACH(k, &kbl, entry) {
864 if (k->cmd == NULL)
865 continue;
866 str[0] = '\0';
868 /* sanity */
869 if (gdk_keyval_name(k->key) == NULL)
870 continue;
872 strlcat(str, k->cmd, sizeof str);
873 strlcat(str, ",", sizeof str);
875 if (k->mask & GDK_SHIFT_MASK)
876 strlcat(str, "S-", sizeof str);
877 if (k->mask & GDK_CONTROL_MASK)
878 strlcat(str, "C-", sizeof str);
879 if (k->mask & GDK_MOD1_MASK)
880 strlcat(str, "M1-", sizeof str);
881 if (k->mask & GDK_MOD2_MASK)
882 strlcat(str, "M2-", sizeof str);
883 if (k->mask & GDK_MOD3_MASK)
884 strlcat(str, "M3-", sizeof str);
885 if (k->mask & GDK_MOD4_MASK)
886 strlcat(str, "M4-", sizeof str);
887 if (k->mask & GDK_MOD5_MASK)
888 strlcat(str, "M5-", sizeof str);
890 strlcat(str, gdk_keyval_name(k->key), sizeof str);
891 cb(s, str, cb_args);
895 void
896 init_keybindings(void)
898 int i;
899 struct key_binding *k;
901 for (i = 0; i < LENGTH(keys); i++) {
902 k = g_malloc0(sizeof *k);
903 k->cmd = keys[i].cmd;
904 k->mask = keys[i].mask;
905 k->use_in_entry = keys[i].use_in_entry;
906 k->key = keys[i].key;
907 TAILQ_INSERT_HEAD(&kbl, k, entry);
909 DNPRINTF(XT_D_KEYBINDING, "init_keybindings: added: %s\n",
910 k->cmd ? k->cmd : "unnamed key");
914 void
915 keybinding_clearall(void)
917 struct key_binding *k, *next;
919 for (k = TAILQ_FIRST(&kbl); k; k = next) {
920 next = TAILQ_NEXT(k, entry);
921 if (k->cmd == NULL)
922 continue;
924 DNPRINTF(XT_D_KEYBINDING, "keybinding_clearall: %s\n",
925 k->cmd ? k->cmd : "unnamed key");
926 TAILQ_REMOVE(&kbl, k, entry);
927 g_free(k);
932 keybinding_add(char *cmd, char *key, int use_in_entry)
934 struct key_binding *k;
935 guint keyval, mask = 0;
936 int i;
938 DNPRINTF(XT_D_KEYBINDING, "keybinding_add: %s %s\n", cmd, key);
940 /* Keys which are to be used in entry have been prefixed with an
941 * exclamation mark. */
942 if (use_in_entry)
943 key++;
945 /* find modifier keys */
946 if (strstr(key, "S-"))
947 mask |= GDK_SHIFT_MASK;
948 if (strstr(key, "C-"))
949 mask |= GDK_CONTROL_MASK;
950 if (strstr(key, "M1-"))
951 mask |= GDK_MOD1_MASK;
952 if (strstr(key, "M2-"))
953 mask |= GDK_MOD2_MASK;
954 if (strstr(key, "M3-"))
955 mask |= GDK_MOD3_MASK;
956 if (strstr(key, "M4-"))
957 mask |= GDK_MOD4_MASK;
958 if (strstr(key, "M5-"))
959 mask |= GDK_MOD5_MASK;
961 /* find keyname */
962 for (i = strlen(key) - 1; i > 0; i--)
963 if (key[i] == '-')
964 key = &key[i + 1];
966 /* validate keyname */
967 keyval = gdk_keyval_from_name(key);
968 if (keyval == GDK_VoidSymbol) {
969 warnx("invalid keybinding name %s", key);
970 return (1);
972 /* must run this test too, gtk+ doesn't handle 10 for example */
973 if (gdk_keyval_name(keyval) == NULL) {
974 warnx("invalid keybinding name %s", key);
975 return (1);
978 /* Remove eventual dupes. */
979 TAILQ_FOREACH(k, &kbl, entry)
980 if (k->key == keyval && k->mask == mask) {
981 TAILQ_REMOVE(&kbl, k, entry);
982 g_free(k);
983 break;
986 /* add keyname */
987 k = g_malloc0(sizeof *k);
988 k->cmd = g_strdup(cmd);
989 k->mask = mask;
990 k->use_in_entry = use_in_entry;
991 k->key = keyval;
993 DNPRINTF(XT_D_KEYBINDING, "keybinding_add: %s 0x%x %d 0x%x\n",
994 k->cmd,
995 k->mask,
996 k->use_in_entry,
997 k->key);
998 DNPRINTF(XT_D_KEYBINDING, "keybinding_add: adding: %s %s\n",
999 k->cmd, gdk_keyval_name(keyval));
1001 TAILQ_INSERT_HEAD(&kbl, k, entry);
1003 return (0);
1007 add_kb(struct settings *s, char *entry)
1009 char *kb, *key;
1011 DNPRINTF(XT_D_KEYBINDING, "add_kb: %s\n", entry);
1013 /* clearall is special */
1014 if (!strcmp(entry, "clearall")) {
1015 keybinding_clearall();
1016 return (0);
1019 kb = strstr(entry, ",");
1020 if (kb == NULL)
1021 return (1);
1022 *kb = '\0';
1023 key = kb + 1;
1025 return (keybinding_add(entry, key, key[0] == '!'));
1029 add_ua(struct settings *s, char *value)
1031 struct user_agent *ua;
1033 ua = g_malloc0(sizeof *ua);
1034 ua->value = g_strdup(value);
1036 TAILQ_INSERT_HEAD(&ua_list, ua, entry);
1038 /* use the last added user agent */
1039 user_agent = TAILQ_FIRST(&ua_list);
1040 user_agent_count++;
1042 return (0);
1046 void
1047 walk_ua(struct settings *s,
1048 void (*cb)(struct settings *, char *, void *), void *cb_args)
1050 struct user_agent *ua;
1052 if (s == NULL || cb == NULL) {
1053 show_oops(NULL, "walk_ua invalid parameters");
1054 return;
1057 TAILQ_FOREACH(ua, &ua_list, entry) {
1058 cb(s, ua->value, cb_args);
1063 set_auto_load_images(char *value)
1065 struct tab *t;
1067 auto_load_images = atoi(value);
1068 TAILQ_FOREACH(t, &tabs, entry) {
1069 g_object_set(G_OBJECT(t->settings),
1070 "auto-load-images", auto_load_images, (char *)NULL);
1071 webkit_web_view_set_settings(t->wv, t->settings);
1073 return (0);
1077 set_enable_autoscroll(char *value)
1079 enable_autoscroll = atoi(value);
1080 return (0);
1084 set_enable_favicon_entry(char *value)
1086 enable_favicon_entry = atoi(value);
1087 return (0);
1091 set_enable_favicon_tabs(char *value)
1093 enable_favicon_tabs = atoi(value);
1094 return (0);
1097 char *
1098 get_referer(struct settings *s)
1100 if (referer_mode == XT_REFERER_ALWAYS)
1101 return (g_strdup("always"));
1102 if (referer_mode == XT_REFERER_NEVER)
1103 return (g_strdup("never"));
1104 if (referer_mode == XT_REFERER_SAME_DOMAIN)
1105 return (g_strdup("same-domain"));
1106 if (referer_mode == XT_REFERER_CUSTOM)
1107 return (g_strdup(referer_custom));
1108 return (NULL);
1112 set_referer(struct settings *s, char *value)
1114 if (referer_custom)
1115 g_free(referer_custom);
1117 if (!strcmp(value, "always"))
1118 referer_mode = XT_REFERER_ALWAYS;
1119 else if (!strcmp(value, "never"))
1120 referer_mode = XT_REFERER_NEVER;
1121 else if (!strcmp(value, "same-domain"))
1122 referer_mode = XT_REFERER_SAME_DOMAIN;
1123 else if (!valid_url_type(value)) {
1124 referer_mode = XT_REFERER_CUSTOM;
1125 referer_custom = g_strdup(value);
1126 } else {
1127 /* we've already free'd the custom referer */
1128 if (referer_mode == XT_REFERER_CUSTOM)
1129 referer_mode = XT_REFERER_NEVER;
1130 return (1);
1133 return (0);
1137 set_referer_rt(char *value)
1139 return set_referer(NULL, value);
1143 set_external_editor(char *editor)
1145 if (external_editor)
1146 g_free(external_editor);
1148 external_editor = g_strdup(editor);
1150 return (0);
1153 void
1154 setup_proxy(char *uri)
1156 if (proxy_uri) {
1157 g_object_set(session, "proxy_uri", NULL, (char *)NULL);
1158 soup_uri_free(proxy_uri);
1159 proxy_uri = NULL;
1161 if (http_proxy) {
1162 if (http_proxy != uri) {
1163 g_free(http_proxy);
1164 http_proxy = NULL;
1168 if (uri) {
1169 http_proxy = g_strdup(uri);
1170 DNPRINTF(XT_D_CONFIG, "setup_proxy: %s\n", uri);
1171 proxy_uri = soup_uri_new(http_proxy);
1172 if (!(proxy_uri == NULL || !SOUP_URI_VALID_FOR_HTTP(proxy_uri)))
1173 g_object_set(session, "proxy-uri", proxy_uri,
1174 (char *)NULL);
1178 char *
1179 get_tab_style(struct settings *s)
1181 if (tab_style == XT_TABS_NORMAL)
1182 return (g_strdup("normal"));
1183 else
1184 return (g_strdup("compact"));
1188 set_tab_style(struct settings *s, char *val)
1190 if (!strcmp(val, "normal"))
1191 tab_style = XT_TABS_NORMAL;
1192 else if (!strcmp(val, "compact"))
1193 tab_style = XT_TABS_COMPACT;
1194 else
1195 return (1);
1197 return (0);
1200 char *
1201 get_edit_mode(struct settings *s)
1203 if (edit_mode == XT_EM_HYBRID)
1204 return (g_strdup("hybrid"));
1205 else
1206 return (g_strdup("vi"));
1210 set_edit_mode(struct settings *s, char *val)
1212 if (!strcmp(val, "hybrid"))
1213 edit_mode = XT_EM_HYBRID;
1214 else if (!strcmp(val, "vi"))
1215 edit_mode = XT_EM_VI;
1216 else
1217 return (1);
1219 return (0);
1222 char *
1223 get_download_mode(struct settings *s)
1225 switch (download_mode) {
1226 case XT_DM_START:
1227 return (g_strdup("start"));
1228 break;
1229 case XT_DM_ASK:
1230 return (g_strdup("ask"));
1231 break;
1232 case XT_DM_ADD:
1233 return (g_strdup("add"));
1234 break;
1236 return (g_strdup("unknown"));
1240 set_download_mode(struct settings *s, char *val)
1242 if (!strcmp(val, "start"))
1243 download_mode = XT_DM_START;
1244 else if (!strcmp(val, "ask"))
1245 download_mode = XT_DM_ASK;
1246 else if (!strcmp(val, "add"))
1247 download_mode = XT_DM_ADD;
1248 else
1249 return (1);
1251 return (0);
1255 set_download_mode_rt(char *val)
1257 return set_download_mode(NULL, val);
1260 char *
1261 get_work_dir(struct settings *s)
1263 if (work_dir[0] == '\0')
1264 return (0);
1265 return (g_strdup(work_dir));
1269 set_work_dir(struct settings *s, char *val)
1271 if (val[0] == '~')
1272 snprintf(work_dir, sizeof work_dir, "%s" PS "%s",
1273 pwd->pw_dir, &val[1]);
1274 else
1275 strlcpy(work_dir, val, sizeof work_dir);
1277 return (0);
1280 void
1281 walk_cookie_wl(struct settings *s,
1282 void (*cb)(struct settings *, char *, void *), void *cb_args)
1284 struct domain *d;
1286 if (s == NULL || cb == NULL) {
1287 show_oops(NULL, "walk_cookie_wl invalid parameters");
1288 return;
1291 RB_FOREACH_REVERSE(d, domain_list, &c_wl)
1292 cb(s, d->d, cb_args);
1295 void
1296 walk_js_wl(struct settings *s,
1297 void (*cb)(struct settings *, char *, void *), void *cb_args)
1299 struct domain *d;
1301 if (s == NULL || cb == NULL) {
1302 show_oops(NULL, "walk_js_wl invalid parameters");
1303 return;
1306 RB_FOREACH_REVERSE(d, domain_list, &js_wl)
1307 cb(s, d->d, cb_args);
1310 void
1311 walk_pl_wl(struct settings *s,
1312 void (*cb)(struct settings *, char *, void *), void *cb_args)
1314 struct domain *d;
1316 if (s == NULL || cb == NULL) {
1317 show_oops(NULL, "walk_pl_wl invalid parameters");
1318 return;
1321 RB_FOREACH_REVERSE(d, domain_list, &pl_wl)
1322 cb(s, d->d, cb_args);
1326 settings_add(char *var, char *val)
1328 int i, rv, *p;
1329 gfloat *f;
1330 char **s;
1332 /* get settings */
1333 for (i = 0, rv = 0; i < LENGTH(rs); i++) {
1334 if (strcmp(var, rs[i].name))
1335 continue;
1337 if (rs[i].s) {
1338 if (rs[i].s->set(&rs[i], val))
1339 errx(1, "invalid value for %s: %s", var, val);
1340 rv = 1;
1341 break;
1342 } else
1343 switch (rs[i].type) {
1344 case XT_S_INT:
1345 p = rs[i].ival;
1346 *p = atoi(val);
1347 rv = 1;
1348 break;
1349 case XT_S_STR:
1350 s = rs[i].sval;
1351 if (s == NULL)
1352 errx(1, "invalid sval for %s",
1353 rs[i].name);
1354 if (*s)
1355 g_free(*s);
1356 *s = g_strdup(val);
1357 rv = 1;
1358 break;
1359 case XT_S_FLOAT:
1360 f = rs[i].fval;
1361 *f = atof(val);
1362 rv = 1;
1363 break;
1364 case XT_S_INVALID:
1365 default:
1366 errx(1, "invalid type for %s", var);
1368 break;
1370 return (rv);
1373 #define WS "\n= \t"
1374 void
1375 config_parse(char *filename, int runtime)
1377 FILE *config, *f;
1378 char *line, *cp, *var, *val;
1379 size_t len, lineno = 0;
1380 int handled;
1381 char file[PATH_MAX];
1382 struct stat sb;
1384 DNPRINTF(XT_D_CONFIG, "config_parse: filename %s\n", filename);
1386 if (filename == NULL)
1387 return;
1389 if (runtime && runtime_settings[0] != '\0') {
1390 snprintf(file, sizeof file, "%s" PS "%s",
1391 work_dir, runtime_settings);
1392 if (stat(file, &sb)) {
1393 warnx("runtime file doesn't exist, creating it");
1394 if ((f = fopen(file, "w")) == NULL)
1395 err(1, "runtime");
1396 fprintf(f, "# AUTO GENERATED, DO NOT EDIT\n");
1397 fclose(f);
1399 } else
1400 strlcpy(file, filename, sizeof file);
1402 if ((config = fopen(file, "r")) == NULL) {
1403 warn("config_parse: cannot open %s", filename);
1404 return;
1407 for (;;) {
1408 if ((line = fparseln(config, &len, &lineno, NULL, 0)) == NULL)
1409 if (feof(config) || ferror(config))
1410 break;
1412 cp = line;
1413 cp += (long)strspn(cp, WS);
1414 if (cp[0] == '\0') {
1415 /* empty line */
1416 free(line);
1417 continue;
1420 if ((var = strsep(&cp, WS)) == NULL || cp == NULL)
1421 startpage_add("invalid configuration file entry: %s",
1422 line);
1423 else {
1424 cp += (long)strspn(cp, WS);
1426 if ((val = strsep(&cp, "\0")) == NULL)
1427 break;
1429 DNPRINTF(XT_D_CONFIG, "config_parse: %s=%s\n",
1430 var, val);
1431 handled = settings_add(var, val);
1433 if (handled == 0)
1434 startpage_add("invalid configuration file entry"
1435 ": %s=%s", var, val);
1438 free(line);
1441 fclose(config);
1444 struct settings_args {
1445 char **body;
1446 int i;
1449 void
1450 print_setting(struct settings *s, char *val, void *cb_args)
1452 char *tmp, *color;
1453 struct settings_args *sa = cb_args;
1455 if (sa == NULL)
1456 return;
1458 if (s->flags & XT_SF_RUNTIME)
1459 color = "#22cc22";
1460 else
1461 color = "#cccccc";
1463 tmp = *sa->body;
1464 *sa->body = g_strdup_printf(
1465 "%s\n<tr>"
1466 "<td style='background-color: %s; width: 10%%;word-break:break-all'>%s</td>"
1467 "<td style='background-color: %s; width: 20%%;word-break:break-all'>%s</td>",
1468 *sa->body,
1469 color,
1470 s->name,
1471 color,
1474 g_free(tmp);
1475 sa->i++;
1479 set_show(struct tab *t, struct karg *args)
1481 char *body, *page, *tmp;
1482 int i = 1;
1483 struct settings_args sa;
1485 bzero(&sa, sizeof sa);
1486 sa.body = &body;
1488 /* body */
1489 body = g_strdup_printf("<div align='center'><table><tr>"
1490 "<th align='left'>Setting</th>"
1491 "<th align='left'>Value</th></tr>\n");
1493 settings_walk(print_setting, &sa);
1494 i = sa.i;
1496 /* small message if there are none */
1497 if (i == 1) {
1498 tmp = body;
1499 body = g_strdup_printf("%s\n<tr><td style='text-align:center'"
1500 "colspan='2'>No settings</td></tr>\n", body);
1501 g_free(tmp);
1504 tmp = body;
1505 body = g_strdup_printf("%s</table></div>", body);
1506 g_free(tmp);
1508 page = get_html_page("Settings", body, "", 0);
1510 g_free(body);
1512 load_webkit_string(t, page, XT_URI_ABOUT_SET);
1514 g_free(page);
1516 return (XT_CB_PASSTHROUGH);
1520 set(struct tab *t, struct karg *args)
1522 char *p, *val;
1523 int i;
1525 if (args == NULL || args->s == NULL)
1526 return (set_show(t, args));
1528 /* strip spaces */
1529 p = g_strstrip(args->s);
1531 if (strlen(p) == 0)
1532 return (set_show(t, args));
1534 /* we got some sort of string */
1535 val = g_strrstr(p, "=");
1536 if (val) {
1537 *val++ = '\0';
1538 val = g_strchomp(val);
1539 p = g_strchomp(p);
1541 for (i = 0; i < get_settings_size(); i++) {
1542 if (strcmp(rs[i].name, p))
1543 continue;
1545 if (rs[i].activate) {
1546 if (rs[i].activate(val))
1547 show_oops(t, "%s invalid value %s",
1548 p, val);
1549 else
1550 show_oops(t, ":set %s = %s", p, val);
1551 goto done;
1552 } else {
1553 show_oops(t, "not a runtime option: %s", p);
1554 goto done;
1557 show_oops(t, "unknown option: %s", p);
1558 } else {
1559 p = g_strchomp(p);
1561 for (i = 0; i < get_settings_size(); i++) {
1562 if (strcmp(rs[i].name, p))
1563 continue;
1565 /* XXX this could use some cleanup */
1566 switch (rs[i].type) {
1567 case XT_S_INT:
1568 if (rs[i].ival)
1569 show_oops(t, "%s = %d",
1570 rs[i].name, *rs[i].ival);
1571 else if (rs[i].s && rs[i].s->get)
1572 show_oops(t, "%s = %s",
1573 rs[i].name,
1574 rs[i].s->get(&rs[i]));
1575 else if (rs[i].s && rs[i].s->get == NULL)
1576 show_oops(t, "%s = ...", rs[i].name);
1577 else
1578 show_oops(t, "%s = ", rs[i].name);
1579 break;
1580 case XT_S_FLOAT:
1581 if (rs[i].fval)
1582 show_oops(t, "%s = %f",
1583 rs[i].name, *rs[i].fval);
1584 else if (rs[i].s && rs[i].s->get)
1585 show_oops(t, "%s = %s",
1586 rs[i].name,
1587 rs[i].s->get(&rs[i]));
1588 else if (rs[i].s && rs[i].s->get == NULL)
1589 show_oops(t, "%s = ...", rs[i].name);
1590 else
1591 show_oops(t, "%s = ", rs[i].name);
1592 break;
1593 case XT_S_STR:
1594 if (rs[i].sval && *rs[i].sval)
1595 show_oops(t, "%s = %s",
1596 rs[i].name, *rs[i].sval);
1597 else if (rs[i].s && rs[i].s->get)
1598 show_oops(t, "%s = %s",
1599 rs[i].name,
1600 rs[i].s->get(&rs[i]));
1601 else if (rs[i].s && rs[i].s->get == NULL)
1602 show_oops(t, "%s = ...", rs[i].name);
1603 else
1604 show_oops(t, "%s = ", rs[i].name);
1605 break;
1606 default:
1607 show_oops(t, "unknown type for %s", rs[i].name);
1608 goto done;
1611 goto done;
1613 show_oops(t, "unknown option: %s", p);
1615 done:
1616 return (XT_CB_PASSTHROUGH);