Make append_next a runtime setting.
[xxxterm.git] / settings.c
blob924a7ae2e19922c61deb403b1e285a4d0a530039
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 /* non settings. what are these for? */
32 int dns_prefetch = FALSE;
34 /* settings that require restart */
35 int allow_volatile_cookies = 0;
36 int autofocus_onload = 0;
37 int browser_mode = XT_BM_NORMAL;
38 char *cmd_font_name = NULL; /* 'cmd_font' setting */
39 int color_visited_uris = 1;
40 int cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
41 int cookies_enabled = 1; /* enable cookies */
42 int ctrl_click_focus = 0; /* ctrl click gets focus */
43 char default_script[PATH_MAX];
44 gfloat default_zoom_level = 1.0;
45 char download_dir[PATH_MAX];
46 int edit_mode = XT_EM_HYBRID;
47 int enable_cookie_whitelist = 0;
48 int enable_js_whitelist = 0;
49 int enable_localstorage = 1;
50 int enable_plugin_whitelist = 0;
51 int enable_plugins = 1;
52 int enable_scripts = 1;
53 int enable_socket = 0;
54 gint enable_spell_checking = 0;
55 gboolean enable_strict_transport = TRUE;
56 char *encoding = NULL;
57 int fancy_bar = 1; /* fancy toolbar */
58 int guess_search = 0;
59 int gui_mode = XT_GM_CLASSIC;
60 int history_autosave = 0;
61 char *home = NULL;
62 int icon_size = 2; /* 1 = smallest, 2+ = bigger */
63 int js_autorun_enabled = 1;
64 gint max_connections = 25;
65 gint max_host_connections = 5;
66 char *oops_font_name = NULL; /* 'oops_font' setting */
67 int read_only_cookies = 0; /* enable to not write cookies */
68 int refresh_interval = 10; /* download refresh interval */
69 char *resource_dir = NULL;
70 int save_global_history = 0; /* save global history to disk */
71 int save_rejected_cookies = 0;
72 char *search_string = NULL;
73 int session_autosave = 0;
74 int session_timeout = 3600; /* cookie session timeout */
75 int single_instance = 0; /* only allow one xxxterm to run */
76 int show_statusbar = 0; /* vimperator style status bar */
77 int show_tabs = 1; /* show tabs on notebook */
78 int show_url = 1; /* show url toolbar on notebook -- XXX duplicate of fancy_bar? */
79 char *spell_check_languages = NULL;
80 char *ssl_ca_file = NULL;
81 gboolean ssl_strict_certs = FALSE;
82 char *statusbar_elems = NULL;
83 char *statusbar_font_name = NULL; /* 'statusbar_font' setting */
84 int tab_style = XT_TABS_NORMAL; /* tab bar style */
85 char *tabbar_font_name = NULL; /* 'tabbar_font' setting */
86 int tabless = 0; /* allow only 1 tab */
87 struct user_agent *user_agent = NULL;
88 char *url_regex = NULL;
89 int userstyle_global = 0;
90 int window_height = 768;
91 int window_maximize = 0;
92 int window_width = 1024;
93 int xterm_workaround = 0;
95 /* runtime settings */
96 int append_next = 1; /* append tab after current tab */
97 int auto_load_images = 1;
98 int download_mode = XT_DM_START;
99 int enable_autoscroll = 0; /* XXX: changing this at runtime doesn't change anything */
100 int enable_favicon_entry = 1; /* XXX: only works on new tabs */
101 int enable_favicon_tabs = 0;
102 char *external_editor = NULL;
103 char *http_proxy = NULL;
104 int referer_mode = XT_REFERER_ALWAYS; /* 'referer' setting */
105 char *referer_custom = NULL; /* 'referer' setting */
106 char runtime_settings[PATH_MAX]; /* override of settings */
108 /* unknown */
109 char search_file[PATH_MAX];
110 char command_file[PATH_MAX];
112 char *get_download_dir(struct settings *);
113 char *get_default_script(struct settings *);
114 char *get_runtime_dir(struct settings *);
115 char *get_tab_style(struct settings *);
116 char *get_edit_mode(struct settings *);
117 char *get_download_mode(struct settings *);
118 char *get_work_dir(struct settings *);
119 char *get_referer(struct settings *);
121 int add_cookie_wl(struct settings *, char *);
122 int add_js_wl(struct settings *, char *);
123 int add_pl_wl(struct settings *, char *);
124 int add_mime_type(struct settings *, char *);
125 int add_alias(struct settings *, char *);
126 int add_kb(struct settings *, char *);
127 int add_ua(struct settings *, char *);
129 int set_append_next(char *);
130 int set_download_dir(struct settings *, char *);
131 int set_default_script(struct settings *, char *);
132 int set_runtime_dir(struct settings *, char *);
133 int set_tab_style(struct settings *, char *);
134 int set_edit_mode(struct settings *, char *);
135 int set_work_dir(struct settings *, char *);
136 int set_auto_load_images(char *value);
137 int set_enable_autoscroll(char *value);
138 int set_enable_favicon_entry(char *value);
139 int set_enable_favicon_tabs(char *value);
140 int set_download_mode(struct settings *, char *);
141 int set_download_mode_rt(char *);
142 int set_referer(struct settings *, char *);
143 int set_referer_rt(char *);
144 int set_external_editor(char *);
146 void walk_mime_type(struct settings *, void (*)(struct settings *,
147 char *, void *), void *);
148 void walk_alias(struct settings *, void (*)(struct settings *,
149 char *, void *), void *);
150 void walk_cookie_wl(struct settings *, void (*)(struct settings *,
151 char *, void *), void *);
152 void walk_js_wl(struct settings *, void (*)(struct settings *,
153 char *, void *), void *);
154 void walk_pl_wl(struct settings *, void (*)(struct settings *,
155 char *, void *), void *);
156 void walk_kb(struct settings *, void (*)(struct settings *, char *,
157 void *), void *);
158 void walk_ua(struct settings *, void (*)(struct settings *, char *,
159 void *), void *);
162 set_http_proxy(char *proxy)
164 SoupURI *uri;
166 if (proxy == NULL)
167 return (1);
169 /* see if we need to clear it instead */
170 if (strlen(proxy) == 0) {
171 setup_proxy(NULL);
172 return (0);
175 uri = soup_uri_new(proxy);
176 if (uri == NULL || !SOUP_URI_VALID_FOR_HTTP(uri))
177 return (1);
179 setup_proxy(proxy);
181 soup_uri_free(uri);
183 return (0);
186 struct special {
187 int (*set)(struct settings *, char *);
188 char *(*get)(struct settings *);
189 void (*walk)(struct settings *,
190 void (*cb)(struct settings *, char *, void *),
191 void *);
194 struct special s_browser_mode = {
195 set_browser_mode,
196 get_browser_mode,
197 NULL
200 struct special s_gui_mode = {
201 set_gui_mode,
202 get_gui_mode,
203 NULL
206 struct special s_cookie = {
207 set_cookie_policy,
208 get_cookie_policy,
209 NULL
212 struct special s_alias = {
213 add_alias,
214 NULL,
215 walk_alias
218 struct special s_mime = {
219 add_mime_type,
220 NULL,
221 walk_mime_type
224 struct special s_js = {
225 add_js_wl,
226 NULL,
227 walk_js_wl
230 struct special s_pl = {
231 add_pl_wl,
232 NULL,
233 walk_pl_wl
236 struct special s_kb = {
237 add_kb,
238 NULL,
239 walk_kb
242 struct special s_cookie_wl = {
243 add_cookie_wl,
244 NULL,
245 walk_cookie_wl
248 struct special s_default_script = {
249 set_default_script,
250 get_default_script,
251 NULL
254 struct special s_download_dir = {
255 set_download_dir,
256 get_download_dir,
257 NULL
260 struct special s_work_dir = {
261 set_work_dir,
262 get_work_dir,
263 NULL
266 struct special s_tab_style = {
267 set_tab_style,
268 get_tab_style,
269 NULL
272 struct special s_edit_mode = {
273 set_edit_mode,
274 get_edit_mode,
275 NULL
278 struct special s_download_mode = {
279 set_download_mode,
280 get_download_mode,
281 NULL
284 struct special s_ua = {
285 add_ua,
286 NULL,
287 walk_ua
290 struct special s_referer = {
291 set_referer,
292 get_referer,
293 NULL
296 struct settings rs[] = {
297 { "allow_volatile_cookies", XT_S_INT, 0, &allow_volatile_cookies, NULL, NULL, NULL, NULL},
298 { "append_next", XT_S_INT, 0, &append_next, NULL, NULL, NULL, set_append_next },
299 { "autofocus_onload", XT_S_INT, 0, &autofocus_onload, NULL, NULL, NULL, NULL},
300 { "browser_mode", XT_S_INT, 0, NULL, NULL,&s_browser_mode, NULL, NULL },
301 { "gui_mode", XT_S_INT, 0, NULL, NULL,&s_gui_mode, NULL, NULL },
302 { "color_visited_uris", XT_S_INT, 0, &color_visited_uris , NULL, NULL, NULL, NULL },
303 { "cookie_policy", XT_S_INT, 0, NULL, NULL,&s_cookie },
304 { "cookies_enabled", XT_S_INT, 0, &cookies_enabled, NULL, NULL },
305 { "ctrl_click_focus", XT_S_INT, 0, &ctrl_click_focus, NULL, NULL, NULL, NULL },
306 { "default_zoom_level", XT_S_FLOAT, 0, NULL, NULL, NULL, &default_zoom_level, NULL },
307 { "default_script", XT_S_STR, 0, NULL, NULL,&s_default_script, NULL, NULL },
308 { "download_dir", XT_S_STR, 0, NULL, NULL,&s_download_dir, NULL, NULL },
309 { "download_mode", XT_S_STR, 0, NULL, NULL,&s_download_mode, NULL, set_download_mode_rt },
310 { "edit_mode", XT_S_STR, 0, NULL, NULL,&s_edit_mode, NULL, NULL},
311 { "enable_cookie_whitelist", XT_S_INT, 0, &enable_cookie_whitelist, NULL, NULL, NULL, NULL },
312 { "enable_js_whitelist", XT_S_INT, 0, &enable_js_whitelist, NULL, NULL, NULL, NULL },
313 { "enable_plugin_whitelist", XT_S_INT, 0, &enable_plugin_whitelist, NULL, NULL, NULL, NULL },
314 { "enable_localstorage", XT_S_INT, 0, &enable_localstorage, NULL, NULL, NULL, NULL},
315 { "enable_plugins", XT_S_INT, 0, &enable_plugins, NULL, NULL, NULL, NULL },
316 { "enable_scripts", XT_S_INT, 0, &enable_scripts, NULL, NULL, NULL, NULL },
317 { "enable_socket", XT_S_INT, XT_SF_RESTART,&enable_socket, NULL, NULL, NULL, NULL },
318 { "enable_spell_checking", XT_S_INT, 0, &enable_spell_checking, NULL, NULL, NULL, NULL },
319 { "encoding", XT_S_STR, 0, NULL, &encoding, NULL, NULL, NULL },
320 { "external_editor", XT_S_STR,0, NULL, &external_editor, NULL, NULL, set_external_editor },
321 { "fancy_bar", XT_S_INT, XT_SF_RESTART,&fancy_bar, NULL, NULL, NULL, NULL },
322 { "guess_search", XT_S_INT, 0, &guess_search, NULL, NULL, NULL, NULL },
323 { "history_autosave", XT_S_INT, 0, &history_autosave, NULL, NULL, NULL, NULL },
324 { "home", XT_S_STR, 0, NULL, &home, NULL, NULL, NULL },
325 { "http_proxy", XT_S_STR, 0, NULL, &http_proxy, NULL, NULL, set_http_proxy },
326 { "icon_size", XT_S_INT, 0, &icon_size, NULL, NULL, NULL, NULL },
327 { "js_autorun_enabled", XT_S_INT, 0, &js_autorun_enabled, NULL, NULL, NULL, NULL },
328 { "max_connections", XT_S_INT, XT_SF_RESTART,&max_connections, NULL, NULL, NULL, NULL },
329 { "max_host_connections", XT_S_INT, XT_SF_RESTART,&max_host_connections, NULL, NULL, NULL, NULL },
330 { "read_only_cookies", XT_S_INT, 0, &read_only_cookies, NULL, NULL, NULL, NULL },
331 { "refresh_interval", XT_S_INT, 0, &refresh_interval, NULL, NULL, NULL, NULL },
332 { "resource_dir", XT_S_STR, 0, NULL, &resource_dir, NULL, NULL, NULL },
333 { "search_string", XT_S_STR, 0, NULL, &search_string, NULL, NULL, NULL },
334 { "save_global_history", XT_S_INT, XT_SF_RESTART,&save_global_history, NULL, NULL, NULL, NULL },
335 { "save_rejected_cookies", XT_S_INT, XT_SF_RESTART,&save_rejected_cookies, NULL, NULL, NULL, NULL },
336 { "session_timeout", XT_S_INT, 0, &session_timeout, NULL, NULL, NULL, NULL },
337 { "session_autosave", XT_S_INT, 0, &session_autosave, NULL, NULL, NULL, NULL },
338 { "single_instance", XT_S_INT, XT_SF_RESTART,&single_instance, NULL, NULL, NULL, NULL },
339 { "show_tabs", XT_S_INT, 0, &show_tabs, NULL, NULL, NULL, NULL },
340 { "show_url", XT_S_INT, 0, &show_url, NULL, NULL, NULL, NULL },
341 { "show_statusbar", XT_S_INT, 0, &show_statusbar, NULL, NULL, NULL, NULL },
342 { "spell_check_languages", XT_S_STR, 0, NULL, &spell_check_languages, NULL, NULL, NULL },
343 { "ssl_ca_file", XT_S_STR, 0, NULL, &ssl_ca_file, NULL, NULL, NULL },
344 { "ssl_strict_certs", XT_S_INT, 0, &ssl_strict_certs, NULL, NULL, NULL, NULL },
345 { "enable_strict_transport", XT_S_INT, 0, &enable_strict_transport, NULL, NULL, NULL, NULL },
346 { "statusbar_elems", XT_S_STR, 0, NULL, &statusbar_elems, NULL, NULL, NULL },
347 { "tab_style", XT_S_STR, 0, NULL, NULL,&s_tab_style, NULL, NULL },
348 { "userstyle_global", XT_S_INT, 0, &userstyle_global, NULL, NULL, NULL, NULL },
349 { "url_regex", XT_S_STR, 0, NULL, &url_regex, NULL, NULL, NULL },
350 { "window_height", XT_S_INT, 0, &window_height, NULL, NULL, NULL, NULL },
351 { "window_width", XT_S_INT, 0, &window_width, NULL, NULL, NULL, NULL },
352 { "window_maximize", XT_S_INT, 0, &window_maximize, NULL, NULL, NULL, NULL },
353 { "work_dir", XT_S_STR, 0, NULL, NULL,&s_work_dir, NULL, NULL },
354 { "xterm_workaround", XT_S_INT, 0, &xterm_workaround, NULL, NULL, NULL, NULL },
355 { "auto_load_images", XT_S_INT, 0, &auto_load_images, NULL, NULL, NULL, set_auto_load_images },
356 { "enable_autoscroll", XT_S_INT, 0, &enable_autoscroll, NULL, NULL, NULL, set_enable_autoscroll },
357 { "enable_favicon_entry", XT_S_INT, 0, &enable_favicon_entry, NULL, NULL, NULL, set_enable_favicon_entry },
358 { "enable_favicon_tabs", XT_S_INT, 0, &enable_favicon_tabs, NULL, NULL, NULL, set_enable_favicon_tabs },
359 { "referer", XT_S_STR, 0, NULL, NULL,&s_referer, NULL, set_referer_rt },
361 /* font settings */
362 { "cmd_font", XT_S_STR, 0, NULL, &cmd_font_name, NULL },
363 { "oops_font", XT_S_STR, 0, NULL, &oops_font_name, NULL },
364 { "statusbar_font", XT_S_STR, 0, NULL, &statusbar_font_name, NULL },
365 { "tabbar_font", XT_S_STR, 0, NULL, &tabbar_font_name, NULL },
367 /* runtime settings */
368 { "alias", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_alias, NULL, NULL },
369 { "cookie_wl", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_cookie_wl, NULL, NULL },
370 { "js_wl", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_js, NULL, NULL },
371 { "keybinding", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_kb, NULL, NULL },
372 { "mime_type", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_mime, NULL, NULL },
373 { "pl_wl", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_pl, NULL, NULL },
374 { "user_agent", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_ua, NULL, NULL },
378 set_append_next(char *value)
380 append_next = atoi(value);
381 return 0;
385 size_t
386 get_settings_size(void)
388 return (LENGTH(rs));
391 char *
392 get_setting_name(int i)
394 if (i > LENGTH(rs))
395 return (NULL);
396 return (rs[i].name);
399 char *
400 get_as_string(struct settings *s)
402 char *r = NULL;
404 if (s == NULL)
405 return (NULL);
407 if (s->s) {
408 if (s->s->get)
409 r = s->s->get(s);
410 else
411 warnx("get_as_string skip %s\n", s->name);
412 } else if (s->type == XT_S_INT)
413 r = g_strdup_printf("%d", *s->ival);
414 else if (s->type == XT_S_STR)
415 r = g_strdup(*s->sval);
416 else if (s->type == XT_S_FLOAT)
417 r = g_strdup_printf("%f", *s->fval);
418 else
419 r = g_strdup_printf("INVALID TYPE");
421 return (r);
424 void
425 settings_walk(void (*cb)(struct settings *, char *, void *), void *cb_args)
427 int i;
428 char *s;
430 for (i = 0; i < LENGTH(rs); i++) {
431 if (rs[i].s && rs[i].s->walk)
432 rs[i].s->walk(&rs[i], cb, cb_args);
433 else {
434 s = get_as_string(&rs[i]);
435 cb(&rs[i], s, cb_args);
436 g_free(s);
442 set_browser_mode(struct settings *s, char *val)
444 if (!strcmp(val, "whitelist")) {
445 browser_mode = XT_BM_WHITELIST;
446 allow_volatile_cookies = 0;
447 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY;
448 cookies_enabled = 1;
449 enable_cookie_whitelist = 1;
450 enable_plugin_whitelist = 1;
451 enable_plugins = 0;
452 read_only_cookies = 0;
453 save_rejected_cookies = 0;
454 session_timeout = 3600;
455 enable_scripts = 0;
456 enable_js_whitelist = 1;
457 enable_localstorage = 0;
458 referer_mode = XT_REFERER_SAME_DOMAIN;
459 } else if (!strcmp(val, "normal")) {
460 browser_mode = XT_BM_NORMAL;
461 allow_volatile_cookies = 0;
462 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
463 cookies_enabled = 1;
464 enable_cookie_whitelist = 0;
465 enable_plugin_whitelist = 0;
466 enable_plugins = 1;
467 read_only_cookies = 0;
468 save_rejected_cookies = 0;
469 session_timeout = 3600;
470 enable_scripts = 1;
471 enable_js_whitelist = 0;
472 enable_localstorage = 1;
473 referer_mode = XT_REFERER_ALWAYS;
474 } else if (!strcmp(val, "kiosk")) {
475 browser_mode = XT_BM_KIOSK;
476 allow_volatile_cookies = 0;
477 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
478 cookies_enabled = 1;
479 enable_cookie_whitelist = 0;
480 enable_plugin_whitelist = 0;
481 enable_plugins = 1;
482 read_only_cookies = 0;
483 save_rejected_cookies = 0;
484 session_timeout = 3600;
485 enable_scripts = 1;
486 enable_js_whitelist = 0;
487 enable_localstorage = 1;
488 referer_mode = XT_REFERER_ALWAYS;
489 show_tabs = 0;
490 tabless = 1;
491 } else
492 return (1);
494 return (0);
497 char *
498 get_browser_mode(struct settings *s)
500 char *r = NULL;
502 if (browser_mode == XT_BM_WHITELIST)
503 r = g_strdup("whitelist");
504 else if (browser_mode == XT_BM_NORMAL)
505 r = g_strdup("normal");
506 else if (browser_mode == XT_BM_KIOSK)
507 r = g_strdup("kiosk");
508 else
509 return (NULL);
511 return (r);
515 set_gui_mode(struct settings *s, char *val)
517 if (!strcmp(val, "classic")) {
518 fancy_bar = 1;
519 show_tabs = 1;
520 tab_style = XT_TABS_NORMAL;
521 show_url = 1;
522 show_statusbar = 0;
523 } else if (!strcmp(val, "minimal")) {
524 fancy_bar = 0;
525 show_tabs = 1;
526 tab_style = XT_TABS_COMPACT;
527 show_url = 0;
528 show_statusbar = 1;
529 } else
530 return (1);
532 return (0);
535 char *
536 get_gui_mode(struct settings *s)
538 char *r = NULL;
540 if (gui_mode == XT_GM_CLASSIC)
541 r = g_strdup("classic");
542 else if (browser_mode == XT_GM_MINIMAL)
543 r = g_strdup("minimal");
544 else
545 return (NULL);
547 return (r);
551 set_cookie_policy(struct settings *s, char *val)
553 if (!strcmp(val, "no3rdparty"))
554 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY;
555 else if (!strcmp(val, "accept"))
556 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
557 else if (!strcmp(val, "reject"))
558 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_NEVER;
559 else
560 return (1);
562 return (0);
565 char *
566 get_cookie_policy(struct settings *s)
568 char *r = NULL;
570 if (cookie_policy == SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY)
571 r = g_strdup("no3rdparty");
572 else if (cookie_policy == SOUP_COOKIE_JAR_ACCEPT_ALWAYS)
573 r = g_strdup("accept");
574 else if (cookie_policy == SOUP_COOKIE_JAR_ACCEPT_NEVER)
575 r = g_strdup("reject");
576 else
577 return (NULL);
579 return (r);
582 char *
583 get_default_script(struct settings *s)
585 if (default_script[0] == '\0')
586 return (0);
587 return (g_strdup(default_script));
591 set_default_script(struct settings *s, char *val)
593 if (val[0] == '~')
594 snprintf(default_script, sizeof default_script, "%s" PS "%s",
595 pwd->pw_dir, &val[1]);
596 else
597 strlcpy(default_script, val, sizeof default_script);
599 return (0);
602 char *
603 get_download_dir(struct settings *s)
605 if (download_dir[0] == '\0')
606 return (0);
607 return (g_strdup(download_dir));
611 set_download_dir(struct settings *s, char *val)
613 if (val[0] == '~')
614 snprintf(download_dir, sizeof download_dir, "%s" PS "%s",
615 pwd->pw_dir, &val[1]);
616 else
617 strlcpy(download_dir, val, sizeof download_dir);
619 return (0);
623 add_alias(struct settings *s, char *line)
625 char *l, *alias;
626 struct alias *a = NULL;
628 if (s == NULL || line == NULL) {
629 show_oops(NULL, "add_alias invalid parameters");
630 return (1);
633 l = line;
634 a = g_malloc(sizeof(*a));
636 if ((alias = strsep(&l, " \t,")) == NULL || l == NULL) {
637 show_oops(NULL, "add_alias: incomplete alias definition");
638 goto bad;
640 if (strlen(alias) == 0 || strlen(l) == 0) {
641 show_oops(NULL, "add_alias: invalid alias definition");
642 goto bad;
645 a->a_name = g_strdup(alias);
646 a->a_uri = g_strdup(l);
648 DNPRINTF(XT_D_CONFIG, "add_alias: %s for %s\n", a->a_name, a->a_uri);
650 TAILQ_INSERT_TAIL(&aliases, a, entry);
652 return (0);
653 bad:
654 if (a)
655 g_free(a);
656 return (1);
659 void
660 walk_alias(struct settings *s,
661 void (*cb)(struct settings *, char *, void *), void *cb_args)
663 struct alias *a;
664 char *str;
666 if (s == NULL || cb == NULL) {
667 show_oops(NULL, "walk_alias invalid parameters");
668 return;
671 TAILQ_FOREACH(a, &aliases, entry) {
672 str = g_strdup_printf("%s --> %s", a->a_name, a->a_uri);
673 cb(s, str, cb_args);
674 g_free(str);
679 add_mime_type(struct settings *s, char *line)
681 char *mime_type;
682 char *l;
683 struct mime_type *m = NULL;
684 int downloadfirst = 0;
686 /* XXX this could be smarter */
688 if (line == NULL || strlen(line) == 0) {
689 show_oops(NULL, "add_mime_type invalid parameters");
690 return (1);
693 l = line;
694 if (*l == '@') {
695 downloadfirst = 1;
696 l++;
698 m = g_malloc(sizeof(*m));
700 if ((mime_type = strsep(&l, " \t,")) == NULL || l == NULL) {
701 show_oops(NULL, "add_mime_type: invalid mime_type");
702 goto bad;
704 if (mime_type[strlen(mime_type) - 1] == '*') {
705 mime_type[strlen(mime_type) - 1] = '\0';
706 m->mt_default = 1;
707 } else
708 m->mt_default = 0;
710 if (strlen(mime_type) == 0 || strlen(l) == 0) {
711 show_oops(NULL, "add_mime_type: invalid mime_type");
712 goto bad;
715 m->mt_type = g_strdup(mime_type);
716 m->mt_action = g_strdup(l);
717 m->mt_download = downloadfirst;
719 DNPRINTF(XT_D_CONFIG, "add_mime_type: type %s action %s default %d\n",
720 m->mt_type, m->mt_action, m->mt_default);
722 TAILQ_INSERT_TAIL(&mtl, m, entry);
724 return (0);
725 bad:
726 if (m)
727 g_free(m);
728 return (1);
731 void
732 walk_mime_type(struct settings *s,
733 void (*cb)(struct settings *, char *, void *), void *cb_args)
735 struct mime_type *m;
736 char *str;
738 if (s == NULL || cb == NULL) {
739 show_oops(NULL, "walk_mime_type invalid parameters");
740 return;
743 TAILQ_FOREACH(m, &mtl, entry) {
744 str = g_strdup_printf("%s%s --> %s",
745 m->mt_type,
746 m->mt_default ? "*" : "",
747 m->mt_action);
748 cb(s, str, cb_args);
749 g_free(str);
753 /* inherent to GTK not all keys will be caught at all times */
754 /* XXX sort key bindings */
755 struct key_binding keys[] = {
756 { "command_mode", 0, 1, GDK_Escape },
757 { "insert_mode", 0, 0, GDK_i },
758 { "cookiejar", MOD1, 1, GDK_j },
759 { "downloadmgr", MOD1, 1, GDK_d },
760 { "history", MOD1, 1, GDK_h },
761 { "print", CTRL, 1, GDK_p },
762 { "search", 0, 0, GDK_slash },
763 { "searchb", 0, 0, GDK_question },
764 { "statustoggle", CTRL, 1, GDK_n },
765 { "command", 0, 0, GDK_colon },
766 { "qa", CTRL, 1, GDK_q },
767 { "restart", MOD1, 1, GDK_q },
768 { "js toggle", CTRL, 1, GDK_j },
769 { "plugin toggle", MOD1, 1, GDK_p },
770 { "cookie toggle", MOD1, 1, GDK_c },
771 { "togglesrc", CTRL, 1, GDK_s },
772 { "yankuri", 0, 0, GDK_y },
773 { "pasteuricur", 0, 0, GDK_p },
774 { "pasteurinew", 0, 0, GDK_P },
775 { "toplevel toggle", 0, 1, GDK_F4 },
776 { "help", 0, 1, GDK_F1 },
777 { "run_script", MOD1, 1, GDK_r },
778 { "proxy toggle", 0, 1, GDK_F2 },
779 { "editelement", CTRL, 1, GDK_i },
780 { "passthrough", CTRL, 1, GDK_z },
781 { "modurl", CTRL, 1, GDK_Return },
783 /* search */
784 { "searchnext", 0, 0, GDK_n },
785 { "searchprevious", 0, 0, GDK_N },
787 /* focus */
788 { "focusaddress", 0, 1, GDK_F6 },
789 { "focussearch", 0, 1, GDK_F7 },
791 /* hinting */
792 { "hinting", 0, 0, GDK_f },
793 { "hinting", 0, 0, GDK_period },
794 { "hinting_newtab", SHFT, 0, GDK_F },
795 { "hinting_newtab", 0, 0, GDK_comma },
797 /* custom stylesheet */
798 { "userstyle", 0, 0, GDK_s },
799 { "userstyle_global", SHFT, 0, GDK_S },
801 /* navigation */
802 { "goback", 0, 0, GDK_BackSpace },
803 { "goback", MOD1, 1, GDK_Left },
804 { "goforward", SHFT, 1, GDK_BackSpace },
805 { "goforward", MOD1, 1, GDK_Right },
806 { "reload", 0, 1, GDK_F5 },
807 { "reload", CTRL, 1, GDK_r },
808 { "reload", CTRL, 1, GDK_l },
809 { "favorites", MOD1, 1, GDK_f },
811 /* vertical movement */
812 { "scrolldown", 0, 0, GDK_j },
813 { "scrolldown", 0, 0, GDK_Down },
814 { "scrollup", 0, 0, GDK_Up },
815 { "scrollup", 0, 0, GDK_k },
816 { "scrollbottom", 0, 0, GDK_G },
817 { "scrollbottom", 0, 0, GDK_End },
818 { "scrolltop", 0, 0, GDK_Home },
819 { "scrollpagedown", 0, 0, GDK_space },
820 { "scrollpagedown", CTRL, 1, GDK_f },
821 { "scrollhalfdown", CTRL, 1, GDK_d },
822 { "scrollpagedown", 0, 0, GDK_Page_Down },
823 { "scrollpageup", 0, 0, GDK_Page_Up },
824 { "scrollpageup", CTRL, 1, GDK_b },
825 { "scrollhalfup", CTRL, 1, GDK_u },
826 /* horizontal movement */
827 { "scrollright", 0, 0, GDK_l },
828 { "scrollright", 0, 0, GDK_Right },
829 { "scrollleft", 0, 0, GDK_Left },
830 { "scrollleft", 0, 0, GDK_h },
831 { "scrollfarright", 0, 0, GDK_dollar },
832 { "scrollfarleft", 0, 0, GDK_0 },
834 /* tabs */
835 { "tabnew", CTRL, 1, GDK_t },
836 { "999tabnew", CTRL, 1, GDK_T },
837 { "tabclose", CTRL, 1, GDK_w },
838 { "tabundoclose", 0, 0, GDK_U },
839 { "tabnext 1", CTRL, 1, GDK_1 },
840 { "tabnext 2", CTRL, 1, GDK_2 },
841 { "tabnext 3", CTRL, 1, GDK_3 },
842 { "tabnext 4", CTRL, 1, GDK_4 },
843 { "tabnext 5", CTRL, 1, GDK_5 },
844 { "tabnext 6", CTRL, 1, GDK_6 },
845 { "tabnext 7", CTRL, 1, GDK_7 },
846 { "tabnext 8", CTRL, 1, GDK_8 },
847 { "tabnext 9", CTRL, 1, GDK_9 },
848 { "tabfirst", CTRL, 1, GDK_less },
849 { "tablast", CTRL, 1, GDK_greater },
850 { "tabprevious", CTRL, 1, GDK_Left },
851 { "tabnext", CTRL, 1, GDK_Right },
852 { "focusout", CTRL, 1, GDK_minus },
853 { "focusin", CTRL, 1, GDK_plus },
854 { "focusin", CTRL, 1, GDK_equal },
855 { "focusreset", CTRL, 1, GDK_0 },
857 /* command aliases (handy when -S flag is used) */
858 { "promptopen", 0, 1, GDK_F9 },
859 { "promptopencurrent", 0, 1, GDK_F10 },
860 { "prompttabnew", 0, 1, GDK_F11 },
861 { "prompttabnewcurrent",0, 1, GDK_F12 },
864 void
865 walk_kb(struct settings *s,
866 void (*cb)(struct settings *, char *, void *), void *cb_args)
868 struct key_binding *k;
869 char str[1024];
871 if (s == NULL || cb == NULL) {
872 show_oops(NULL, "walk_kb invalid parameters");
873 return;
876 TAILQ_FOREACH(k, &kbl, entry) {
877 if (k->cmd == NULL)
878 continue;
879 str[0] = '\0';
881 /* sanity */
882 if (gdk_keyval_name(k->key) == NULL)
883 continue;
885 strlcat(str, k->cmd, sizeof str);
886 strlcat(str, ",", sizeof str);
888 if (k->mask & GDK_SHIFT_MASK)
889 strlcat(str, "S-", sizeof str);
890 if (k->mask & GDK_CONTROL_MASK)
891 strlcat(str, "C-", sizeof str);
892 if (k->mask & GDK_MOD1_MASK)
893 strlcat(str, "M1-", sizeof str);
894 if (k->mask & GDK_MOD2_MASK)
895 strlcat(str, "M2-", sizeof str);
896 if (k->mask & GDK_MOD3_MASK)
897 strlcat(str, "M3-", sizeof str);
898 if (k->mask & GDK_MOD4_MASK)
899 strlcat(str, "M4-", sizeof str);
900 if (k->mask & GDK_MOD5_MASK)
901 strlcat(str, "M5-", sizeof str);
903 strlcat(str, gdk_keyval_name(k->key), sizeof str);
904 cb(s, str, cb_args);
908 void
909 init_keybindings(void)
911 int i;
912 struct key_binding *k;
914 for (i = 0; i < LENGTH(keys); i++) {
915 k = g_malloc0(sizeof *k);
916 k->cmd = keys[i].cmd;
917 k->mask = keys[i].mask;
918 k->use_in_entry = keys[i].use_in_entry;
919 k->key = keys[i].key;
920 TAILQ_INSERT_HEAD(&kbl, k, entry);
922 DNPRINTF(XT_D_KEYBINDING, "init_keybindings: added: %s\n",
923 k->cmd ? k->cmd : "unnamed key");
927 void
928 keybinding_clearall(void)
930 struct key_binding *k, *next;
932 for (k = TAILQ_FIRST(&kbl); k; k = next) {
933 next = TAILQ_NEXT(k, entry);
934 if (k->cmd == NULL)
935 continue;
937 DNPRINTF(XT_D_KEYBINDING, "keybinding_clearall: %s\n",
938 k->cmd ? k->cmd : "unnamed key");
939 TAILQ_REMOVE(&kbl, k, entry);
940 g_free(k);
945 keybinding_add(char *cmd, char *key, int use_in_entry)
947 struct key_binding *k;
948 guint keyval, mask = 0;
949 int i;
951 DNPRINTF(XT_D_KEYBINDING, "keybinding_add: %s %s\n", cmd, key);
953 /* Keys which are to be used in entry have been prefixed with an
954 * exclamation mark. */
955 if (use_in_entry)
956 key++;
958 /* find modifier keys */
959 if (strstr(key, "S-"))
960 mask |= GDK_SHIFT_MASK;
961 if (strstr(key, "C-"))
962 mask |= GDK_CONTROL_MASK;
963 if (strstr(key, "M1-"))
964 mask |= GDK_MOD1_MASK;
965 if (strstr(key, "M2-"))
966 mask |= GDK_MOD2_MASK;
967 if (strstr(key, "M3-"))
968 mask |= GDK_MOD3_MASK;
969 if (strstr(key, "M4-"))
970 mask |= GDK_MOD4_MASK;
971 if (strstr(key, "M5-"))
972 mask |= GDK_MOD5_MASK;
974 /* find keyname */
975 for (i = strlen(key) - 1; i > 0; i--)
976 if (key[i] == '-')
977 key = &key[i + 1];
979 /* validate keyname */
980 keyval = gdk_keyval_from_name(key);
981 if (keyval == GDK_VoidSymbol) {
982 warnx("invalid keybinding name %s", key);
983 return (1);
985 /* must run this test too, gtk+ doesn't handle 10 for example */
986 if (gdk_keyval_name(keyval) == NULL) {
987 warnx("invalid keybinding name %s", key);
988 return (1);
991 /* Remove eventual dupes. */
992 TAILQ_FOREACH(k, &kbl, entry)
993 if (k->key == keyval && k->mask == mask) {
994 TAILQ_REMOVE(&kbl, k, entry);
995 g_free(k);
996 break;
999 /* add keyname */
1000 k = g_malloc0(sizeof *k);
1001 k->cmd = g_strdup(cmd);
1002 k->mask = mask;
1003 k->use_in_entry = use_in_entry;
1004 k->key = keyval;
1006 DNPRINTF(XT_D_KEYBINDING, "keybinding_add: %s 0x%x %d 0x%x\n",
1007 k->cmd,
1008 k->mask,
1009 k->use_in_entry,
1010 k->key);
1011 DNPRINTF(XT_D_KEYBINDING, "keybinding_add: adding: %s %s\n",
1012 k->cmd, gdk_keyval_name(keyval));
1014 TAILQ_INSERT_HEAD(&kbl, k, entry);
1016 return (0);
1020 add_kb(struct settings *s, char *entry)
1022 char *kb, *key;
1024 DNPRINTF(XT_D_KEYBINDING, "add_kb: %s\n", entry);
1026 /* clearall is special */
1027 if (!strcmp(entry, "clearall")) {
1028 keybinding_clearall();
1029 return (0);
1032 kb = strstr(entry, ",");
1033 if (kb == NULL)
1034 return (1);
1035 *kb = '\0';
1036 key = kb + 1;
1038 return (keybinding_add(entry, key, key[0] == '!'));
1042 add_ua(struct settings *s, char *value)
1044 struct user_agent *ua;
1046 ua = g_malloc0(sizeof *ua);
1047 ua->value = g_strdup(value);
1049 TAILQ_INSERT_HEAD(&ua_list, ua, entry);
1051 /* use the last added user agent */
1052 user_agent = TAILQ_FIRST(&ua_list);
1053 user_agent_count++;
1055 return (0);
1059 void
1060 walk_ua(struct settings *s,
1061 void (*cb)(struct settings *, char *, void *), void *cb_args)
1063 struct user_agent *ua;
1065 if (s == NULL || cb == NULL) {
1066 show_oops(NULL, "walk_ua invalid parameters");
1067 return;
1070 TAILQ_FOREACH(ua, &ua_list, entry) {
1071 cb(s, ua->value, cb_args);
1076 set_auto_load_images(char *value)
1078 struct tab *t;
1080 auto_load_images = atoi(value);
1081 TAILQ_FOREACH(t, &tabs, entry) {
1082 g_object_set(G_OBJECT(t->settings),
1083 "auto-load-images", auto_load_images, (char *)NULL);
1084 webkit_web_view_set_settings(t->wv, t->settings);
1086 return (0);
1090 set_enable_autoscroll(char *value)
1092 struct tab *t;
1094 enable_autoscroll = atoi(value);
1095 if (enable_autoscroll) {
1096 TAILQ_FOREACH(t, &tabs, entry) {
1097 run_script(t, JS_AUTOSCROLL);
1099 } else {
1100 /* XXX: kill the script if running */
1102 return (0);
1106 set_enable_favicon_entry(char *value)
1108 enable_favicon_entry = atoi(value);
1109 return (0);
1113 set_enable_favicon_tabs(char *value)
1115 enable_favicon_tabs = atoi(value);
1116 return (0);
1119 char *
1120 get_referer(struct settings *s)
1122 if (referer_mode == XT_REFERER_ALWAYS)
1123 return (g_strdup("always"));
1124 if (referer_mode == XT_REFERER_NEVER)
1125 return (g_strdup("never"));
1126 if (referer_mode == XT_REFERER_SAME_DOMAIN)
1127 return (g_strdup("same-domain"));
1128 if (referer_mode == XT_REFERER_SAME_FQDN)
1129 return (g_strdup("same-fqdn"));
1130 if (referer_mode == XT_REFERER_CUSTOM)
1131 return (g_strdup(referer_custom));
1132 return (NULL);
1136 set_referer(struct settings *s, char *value)
1138 if (referer_custom)
1139 g_free(referer_custom);
1141 if (!strcmp(value, "always"))
1142 referer_mode = XT_REFERER_ALWAYS;
1143 else if (!strcmp(value, "never"))
1144 referer_mode = XT_REFERER_NEVER;
1145 else if (!strcmp(value, "same-domain"))
1146 referer_mode = XT_REFERER_SAME_DOMAIN;
1147 else if (!strcmp(value, "same-fqdn"))
1148 referer_mode = XT_REFERER_SAME_FQDN;
1149 else if (!valid_url_type(value)) {
1150 referer_mode = XT_REFERER_CUSTOM;
1151 referer_custom = g_strdup(value);
1152 } else {
1153 /* we've already free'd the custom referer */
1154 if (referer_mode == XT_REFERER_CUSTOM)
1155 referer_mode = XT_REFERER_NEVER;
1156 return (1);
1159 return (0);
1163 set_referer_rt(char *value)
1165 return set_referer(NULL, value);
1169 set_external_editor(char *editor)
1171 if (external_editor)
1172 g_free(external_editor);
1174 external_editor = g_strdup(editor);
1176 return (0);
1179 void
1180 setup_proxy(char *uri)
1182 if (proxy_uri) {
1183 g_object_set(session, "proxy_uri", NULL, (char *)NULL);
1184 soup_uri_free(proxy_uri);
1185 proxy_uri = NULL;
1187 if (http_proxy) {
1188 if (http_proxy != uri) {
1189 g_free(http_proxy);
1190 http_proxy = NULL;
1194 if (uri) {
1195 http_proxy = g_strdup(uri);
1196 DNPRINTF(XT_D_CONFIG, "setup_proxy: %s\n", uri);
1197 proxy_uri = soup_uri_new(http_proxy);
1198 if (!(proxy_uri == NULL || !SOUP_URI_VALID_FOR_HTTP(proxy_uri)))
1199 g_object_set(session, "proxy-uri", proxy_uri,
1200 (char *)NULL);
1204 char *
1205 get_tab_style(struct settings *s)
1207 if (tab_style == XT_TABS_NORMAL)
1208 return (g_strdup("normal"));
1209 else
1210 return (g_strdup("compact"));
1214 set_tab_style(struct settings *s, char *val)
1216 if (!strcmp(val, "normal"))
1217 tab_style = XT_TABS_NORMAL;
1218 else if (!strcmp(val, "compact"))
1219 tab_style = XT_TABS_COMPACT;
1220 else
1221 return (1);
1223 return (0);
1226 char *
1227 get_edit_mode(struct settings *s)
1229 if (edit_mode == XT_EM_HYBRID)
1230 return (g_strdup("hybrid"));
1231 else
1232 return (g_strdup("vi"));
1236 set_edit_mode(struct settings *s, char *val)
1238 if (!strcmp(val, "hybrid"))
1239 edit_mode = XT_EM_HYBRID;
1240 else if (!strcmp(val, "vi"))
1241 edit_mode = XT_EM_VI;
1242 else
1243 return (1);
1245 return (0);
1248 char *
1249 get_download_mode(struct settings *s)
1251 switch (download_mode) {
1252 case XT_DM_START:
1253 return (g_strdup("start"));
1254 break;
1255 case XT_DM_ASK:
1256 return (g_strdup("ask"));
1257 break;
1258 case XT_DM_ADD:
1259 return (g_strdup("add"));
1260 break;
1262 return (g_strdup("unknown"));
1266 set_download_mode(struct settings *s, char *val)
1268 if (!strcmp(val, "start"))
1269 download_mode = XT_DM_START;
1270 else if (!strcmp(val, "ask"))
1271 download_mode = XT_DM_ASK;
1272 else if (!strcmp(val, "add"))
1273 download_mode = XT_DM_ADD;
1274 else
1275 return (1);
1277 return (0);
1281 set_download_mode_rt(char *val)
1283 return set_download_mode(NULL, val);
1286 char *
1287 get_work_dir(struct settings *s)
1289 if (work_dir[0] == '\0')
1290 return (0);
1291 return (g_strdup(work_dir));
1295 set_work_dir(struct settings *s, char *val)
1297 if (val[0] == '~')
1298 snprintf(work_dir, sizeof work_dir, "%s" PS "%s",
1299 pwd->pw_dir, &val[1]);
1300 else
1301 strlcpy(work_dir, val, sizeof work_dir);
1303 return (0);
1306 void
1307 walk_cookie_wl(struct settings *s,
1308 void (*cb)(struct settings *, char *, void *), void *cb_args)
1310 struct domain *d;
1312 if (s == NULL || cb == NULL) {
1313 show_oops(NULL, "walk_cookie_wl invalid parameters");
1314 return;
1317 RB_FOREACH_REVERSE(d, domain_list, &c_wl)
1318 cb(s, d->d, cb_args);
1321 void
1322 walk_js_wl(struct settings *s,
1323 void (*cb)(struct settings *, char *, void *), void *cb_args)
1325 struct domain *d;
1327 if (s == NULL || cb == NULL) {
1328 show_oops(NULL, "walk_js_wl invalid parameters");
1329 return;
1332 RB_FOREACH_REVERSE(d, domain_list, &js_wl)
1333 cb(s, d->d, cb_args);
1336 void
1337 walk_pl_wl(struct settings *s,
1338 void (*cb)(struct settings *, char *, void *), void *cb_args)
1340 struct domain *d;
1342 if (s == NULL || cb == NULL) {
1343 show_oops(NULL, "walk_pl_wl invalid parameters");
1344 return;
1347 RB_FOREACH_REVERSE(d, domain_list, &pl_wl)
1348 cb(s, d->d, cb_args);
1352 settings_add(char *var, char *val)
1354 int i, rv, *p;
1355 gfloat *f;
1356 char **s;
1358 /* get settings */
1359 for (i = 0, rv = 0; i < LENGTH(rs); i++) {
1360 if (strcmp(var, rs[i].name))
1361 continue;
1363 if (rs[i].s) {
1364 if (rs[i].s->set(&rs[i], val))
1365 errx(1, "invalid value for %s: %s", var, val);
1366 rv = 1;
1367 break;
1368 } else
1369 switch (rs[i].type) {
1370 case XT_S_INT:
1371 p = rs[i].ival;
1372 *p = atoi(val);
1373 rv = 1;
1374 break;
1375 case XT_S_STR:
1376 s = rs[i].sval;
1377 if (s == NULL)
1378 errx(1, "invalid sval for %s",
1379 rs[i].name);
1380 if (*s)
1381 g_free(*s);
1382 *s = g_strdup(val);
1383 rv = 1;
1384 break;
1385 case XT_S_FLOAT:
1386 f = rs[i].fval;
1387 *f = atof(val);
1388 rv = 1;
1389 break;
1390 case XT_S_INVALID:
1391 default:
1392 errx(1, "invalid type for %s", var);
1394 break;
1396 return (rv);
1399 #define WS "\n= \t"
1400 void
1401 config_parse(char *filename, int runtime)
1403 FILE *config, *f;
1404 char *line, *cp, *var, *val;
1405 size_t len, lineno = 0;
1406 int handled;
1407 char file[PATH_MAX];
1408 struct stat sb;
1410 DNPRINTF(XT_D_CONFIG, "config_parse: filename %s\n", filename);
1412 if (filename == NULL)
1413 return;
1415 if (runtime && runtime_settings[0] != '\0') {
1416 snprintf(file, sizeof file, "%s" PS "%s",
1417 work_dir, runtime_settings);
1418 if (stat(file, &sb)) {
1419 warnx("runtime file doesn't exist, creating it");
1420 if ((f = fopen(file, "w")) == NULL)
1421 err(1, "runtime");
1422 fprintf(f, "# AUTO GENERATED, DO NOT EDIT\n");
1423 fclose(f);
1425 } else
1426 strlcpy(file, filename, sizeof file);
1428 if ((config = fopen(file, "r")) == NULL) {
1429 warn("config_parse: cannot open %s", filename);
1430 return;
1433 for (;;) {
1434 if ((line = fparseln(config, &len, &lineno, NULL, 0)) == NULL)
1435 if (feof(config) || ferror(config))
1436 break;
1438 cp = line;
1439 cp += (long)strspn(cp, WS);
1440 if (cp[0] == '\0') {
1441 /* empty line */
1442 free(line);
1443 continue;
1446 if ((var = strsep(&cp, WS)) == NULL || cp == NULL)
1447 startpage_add("invalid configuration file entry: %s",
1448 line);
1449 else {
1450 cp += (long)strspn(cp, WS);
1452 if ((val = strsep(&cp, "\0")) == NULL)
1453 break;
1455 DNPRINTF(XT_D_CONFIG, "config_parse: %s=%s\n",
1456 var, val);
1457 handled = settings_add(var, val);
1459 if (handled == 0)
1460 startpage_add("invalid configuration file entry"
1461 ": %s=%s", var, val);
1464 free(line);
1467 fclose(config);
1470 struct settings_args {
1471 char **body;
1472 int i;
1475 void
1476 print_setting(struct settings *s, char *val, void *cb_args)
1478 char *tmp, *color;
1479 struct settings_args *sa = cb_args;
1481 if (sa == NULL)
1482 return;
1484 if (s->flags & XT_SF_RUNTIME)
1485 color = "#22cc22";
1486 else
1487 color = "#cccccc";
1489 tmp = *sa->body;
1490 *sa->body = g_strdup_printf(
1491 "%s\n<tr>"
1492 "<td style='background-color: %s; width: 10%%;word-break:break-all'>%s</td>"
1493 "<td style='background-color: %s; width: 20%%;word-break:break-all'>%s</td>",
1494 *sa->body,
1495 color,
1496 s->name,
1497 color,
1500 g_free(tmp);
1501 sa->i++;
1505 set_show(struct tab *t, struct karg *args)
1507 char *body, *page, *tmp;
1508 int i = 1;
1509 struct settings_args sa;
1511 bzero(&sa, sizeof sa);
1512 sa.body = &body;
1514 /* body */
1515 body = g_strdup_printf("<div align='center'><table><tr>"
1516 "<th align='left'>Setting</th>"
1517 "<th align='left'>Value</th></tr>\n");
1519 settings_walk(print_setting, &sa);
1520 i = sa.i;
1522 /* small message if there are none */
1523 if (i == 1) {
1524 tmp = body;
1525 body = g_strdup_printf("%s\n<tr><td style='text-align:center'"
1526 "colspan='2'>No settings</td></tr>\n", body);
1527 g_free(tmp);
1530 tmp = body;
1531 body = g_strdup_printf("%s</table></div>", body);
1532 g_free(tmp);
1534 page = get_html_page("Settings", body, "", 0);
1536 g_free(body);
1538 load_webkit_string(t, page, XT_URI_ABOUT_SET);
1540 g_free(page);
1542 return (XT_CB_PASSTHROUGH);
1546 set(struct tab *t, struct karg *args)
1548 char *p, *val;
1549 int i;
1551 if (args == NULL || args->s == NULL)
1552 return (set_show(t, args));
1554 /* strip spaces */
1555 p = g_strstrip(args->s);
1557 if (strlen(p) == 0)
1558 return (set_show(t, args));
1560 /* we got some sort of string */
1561 val = g_strrstr(p, "=");
1562 if (val) {
1563 *val++ = '\0';
1564 val = g_strchomp(val);
1565 p = g_strchomp(p);
1567 for (i = 0; i < get_settings_size(); i++) {
1568 if (strcmp(rs[i].name, p))
1569 continue;
1571 if (rs[i].activate) {
1572 if (rs[i].activate(val))
1573 show_oops(t, "%s invalid value %s",
1574 p, val);
1575 else
1576 show_oops(t, ":set %s = %s", p, val);
1577 goto done;
1578 } else {
1579 show_oops(t, "not a runtime option: %s", p);
1580 goto done;
1583 show_oops(t, "unknown option: %s", p);
1584 } else {
1585 p = g_strchomp(p);
1587 for (i = 0; i < get_settings_size(); i++) {
1588 if (strcmp(rs[i].name, p))
1589 continue;
1591 /* XXX this could use some cleanup */
1592 switch (rs[i].type) {
1593 case XT_S_INT:
1594 if (rs[i].ival)
1595 show_oops(t, "%s = %d",
1596 rs[i].name, *rs[i].ival);
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 case XT_S_FLOAT:
1607 if (rs[i].fval)
1608 show_oops(t, "%s = %f",
1609 rs[i].name, *rs[i].fval);
1610 else if (rs[i].s && rs[i].s->get)
1611 show_oops(t, "%s = %s",
1612 rs[i].name,
1613 rs[i].s->get(&rs[i]));
1614 else if (rs[i].s && rs[i].s->get == NULL)
1615 show_oops(t, "%s = ...", rs[i].name);
1616 else
1617 show_oops(t, "%s = ", rs[i].name);
1618 break;
1619 case XT_S_STR:
1620 if (rs[i].sval && *rs[i].sval)
1621 show_oops(t, "%s = %s",
1622 rs[i].name, *rs[i].sval);
1623 else if (rs[i].s && rs[i].s->get)
1624 show_oops(t, "%s = %s",
1625 rs[i].name,
1626 rs[i].s->get(&rs[i]));
1627 else if (rs[i].s && rs[i].s->get == NULL)
1628 show_oops(t, "%s = ...", rs[i].name);
1629 else
1630 show_oops(t, "%s = ", rs[i].name);
1631 break;
1632 default:
1633 show_oops(t, "unknown type for %s", rs[i].name);
1634 goto done;
1637 goto done;
1639 show_oops(t, "unknown option: %s", p);
1641 done:
1642 return (XT_CB_PASSTHROUGH);