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.
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 enable_localstorage
= 1;
38 char *statusbar_elems
= NULL
;
40 /* runtime settings */
41 int show_tabs
= 1; /* show tabs on notebook */
42 int tab_style
= XT_TABS_NORMAL
; /* tab bar style */
43 int show_url
= 1; /* show url toolbar on notebook */
44 int show_statusbar
= 0; /* vimperator style status bar */
45 int ctrl_click_focus
= 0; /* ctrl click gets focus */
46 int cookies_enabled
= 1; /* enable cookies */
47 int read_only_cookies
= 0; /* enable to not write cookies */
48 int enable_scripts
= 1;
49 int enable_plugins
= 1;
50 gfloat default_zoom_level
= 1.0;
51 char default_script
[PATH_MAX
];
52 int window_height
= 768;
53 int window_width
= 1024;
54 int icon_size
= 2; /* 1 = smallest, 2+ = bigger */
55 int refresh_interval
= 10; /* download refresh interval */
56 int enable_plugin_whitelist
= 0;
57 int enable_cookie_whitelist
= 0;
58 int enable_js_whitelist
= 0;
59 int session_timeout
= 3600; /* cookie session timeout */
60 int cookie_policy
= SOUP_COOKIE_JAR_ACCEPT_ALWAYS
;
61 char *ssl_ca_file
= NULL
;
62 char *resource_dir
= NULL
;
63 gboolean ssl_strict_certs
= FALSE
;
64 int append_next
= 1; /* append tab after current tab */
66 char *search_string
= NULL
;
67 char *http_proxy
= NULL
;
68 char download_dir
[PATH_MAX
];
69 char runtime_settings
[PATH_MAX
]; /* override of settings */
70 int allow_volatile_cookies
= 0;
71 int save_global_history
= 0; /* save global history to disk */
72 char *user_agent
= NULL
;
73 int save_rejected_cookies
= 0;
74 int session_autosave
= 0;
76 int dns_prefetch
= FALSE
;
77 gint max_connections
= 25;
78 gint max_host_connections
= 5;
79 gint enable_spell_checking
= 0;
80 char *spell_check_languages
= NULL
;
81 int xterm_workaround
= 0;
82 char *url_regex
= NULL
;
83 int history_autosave
= 0;
84 char search_file
[PATH_MAX
];
85 char command_file
[PATH_MAX
];
86 char *encoding
= NULL
;
87 int autofocus_onload
= 0;
88 int js_autorun_enabled
= 1;
89 int edit_mode
= XT_EM_HYBRID
;
91 char *cmd_font_name
= NULL
;
92 char *oops_font_name
= NULL
;
93 char *statusbar_font_name
= NULL
;
94 char *tabbar_font_name
= NULL
;
96 char *get_download_dir(struct settings
*);
97 char *get_default_script(struct settings
*);
98 char *get_runtime_dir(struct settings
*);
99 char *get_tab_style(struct settings
*);
100 char *get_edit_mode(struct settings
*);
101 char *get_work_dir(struct settings
*);
103 int add_cookie_wl(struct settings
*, char *);
104 int add_js_wl(struct settings
*, char *);
105 int add_pl_wl(struct settings
*, char *);
106 int add_mime_type(struct settings
*, char *);
107 int add_alias(struct settings
*, char *);
108 int add_kb(struct settings
*, char *);
110 int set_download_dir(struct settings
*, char *);
111 int set_default_script(struct settings
*, char *);
112 int set_runtime_dir(struct settings
*, char *);
113 int set_tab_style(struct settings
*, char *);
114 int set_edit_mode(struct settings
*, char *);
115 int set_work_dir(struct settings
*, char *);
117 void walk_mime_type(struct settings
*, void (*)(struct settings
*,
118 char *, void *), void *);
119 void walk_alias(struct settings
*, void (*)(struct settings
*,
120 char *, void *), void *);
121 void walk_cookie_wl(struct settings
*, void (*)(struct settings
*,
122 char *, void *), void *);
123 void walk_js_wl(struct settings
*, void (*)(struct settings
*,
124 char *, void *), void *);
125 void walk_pl_wl(struct settings
*, void (*)(struct settings
*,
126 char *, void *), void *);
127 void walk_kb(struct settings
*, void (*)(struct settings
*, char *,
131 set_http_proxy(char *proxy
)
138 /* see if we need to clear it instead */
139 if (strlen(proxy
) == 0) {
144 uri
= soup_uri_new(proxy
);
145 if (uri
== NULL
|| !SOUP_URI_VALID_FOR_HTTP(uri
))
156 int (*set
)(struct settings
*, char *);
157 char *(*get
)(struct settings
*);
158 void (*walk
)(struct settings
*,
159 void (*cb
)(struct settings
*, char *, void *),
163 struct special s_browser_mode
= {
169 struct special s_cookie
= {
175 struct special s_alias
= {
181 struct special s_mime
= {
187 struct special s_js
= {
193 struct special s_pl
= {
199 struct special s_kb
= {
205 struct special s_cookie_wl
= {
211 struct special s_default_script
= {
217 struct special s_download_dir
= {
223 struct special s_work_dir
= {
229 struct special s_tab_style
= {
235 struct special s_edit_mode
= {
241 struct settings rs
[] = {
242 { "allow_volatile_cookies", XT_S_INT
, 0, &allow_volatile_cookies
, NULL
, NULL
},
243 { "append_next", XT_S_INT
, 0, &append_next
, NULL
, NULL
},
244 { "autofocus_onload", XT_S_INT
, 0, &autofocus_onload
, NULL
, NULL
},
245 { "browser_mode", XT_S_INT
, 0, NULL
, NULL
,&s_browser_mode
},
246 { "cookie_policy", XT_S_INT
, 0, NULL
, NULL
,&s_cookie
},
247 { "cookies_enabled", XT_S_INT
, 0, &cookies_enabled
, NULL
, NULL
},
248 { "ctrl_click_focus", XT_S_INT
, 0, &ctrl_click_focus
, NULL
, NULL
},
249 { "default_zoom_level", XT_S_FLOAT
, 0, NULL
, NULL
, NULL
, &default_zoom_level
},
250 { "default_script", XT_S_STR
, 0, NULL
, NULL
,&s_default_script
},
251 { "download_dir", XT_S_STR
, 0, NULL
, NULL
,&s_download_dir
},
252 { "edit_mode", XT_S_STR
, 0, NULL
, NULL
,&s_edit_mode
},
253 { "enable_cookie_whitelist", XT_S_INT
, 0, &enable_cookie_whitelist
, NULL
, NULL
},
254 { "enable_js_whitelist", XT_S_INT
, 0, &enable_js_whitelist
, NULL
, NULL
},
255 { "enable_plugin_whitelist", XT_S_INT
, 0, &enable_plugin_whitelist
, NULL
, NULL
},
256 { "enable_localstorage", XT_S_INT
, 0, &enable_localstorage
, NULL
, NULL
},
257 { "enable_plugins", XT_S_INT
, 0, &enable_plugins
, NULL
, NULL
},
258 { "enable_scripts", XT_S_INT
, 0, &enable_scripts
, NULL
, NULL
},
259 { "enable_socket", XT_S_INT
, XT_SF_RESTART
,&enable_socket
, NULL
, NULL
},
260 { "enable_spell_checking", XT_S_INT
, 0, &enable_spell_checking
, NULL
, NULL
},
261 { "encoding", XT_S_STR
, 0, NULL
, &encoding
, NULL
},
262 { "fancy_bar", XT_S_INT
, XT_SF_RESTART
,&fancy_bar
, NULL
, NULL
},
263 { "guess_search", XT_S_INT
, 0, &guess_search
, NULL
, NULL
},
264 { "history_autosave", XT_S_INT
, 0, &history_autosave
, NULL
, NULL
},
265 { "home", XT_S_STR
, 0, NULL
, &home
, NULL
},
266 { "http_proxy", XT_S_STR
, 0, NULL
, &http_proxy
, NULL
, NULL
, set_http_proxy
},
267 { "icon_size", XT_S_INT
, 0, &icon_size
, NULL
, NULL
},
268 { "js_autorun_enabled", XT_S_INT
, 0, &js_autorun_enabled
, NULL
, NULL
},
269 { "max_connections", XT_S_INT
, XT_SF_RESTART
,&max_connections
, NULL
, NULL
},
270 { "max_host_connections", XT_S_INT
, XT_SF_RESTART
,&max_host_connections
, NULL
, NULL
},
271 { "read_only_cookies", XT_S_INT
, 0, &read_only_cookies
, NULL
, NULL
},
272 { "refresh_interval", XT_S_INT
, 0, &refresh_interval
, NULL
, NULL
},
273 { "resource_dir", XT_S_STR
, 0, NULL
, &resource_dir
, NULL
},
274 { "search_string", XT_S_STR
, 0, NULL
, &search_string
, NULL
},
275 { "save_global_history", XT_S_INT
, XT_SF_RESTART
,&save_global_history
, NULL
, NULL
},
276 { "save_rejected_cookies", XT_S_INT
, XT_SF_RESTART
,&save_rejected_cookies
, NULL
, NULL
},
277 { "session_timeout", XT_S_INT
, 0, &session_timeout
, NULL
, NULL
},
278 { "session_autosave", XT_S_INT
, 0, &session_autosave
, NULL
, NULL
},
279 { "single_instance", XT_S_INT
, XT_SF_RESTART
,&single_instance
, NULL
, NULL
},
280 { "show_tabs", XT_S_INT
, 0, &show_tabs
, NULL
, NULL
},
281 { "show_url", XT_S_INT
, 0, &show_url
, NULL
, NULL
},
282 { "show_statusbar", XT_S_INT
, 0, &show_statusbar
, NULL
, NULL
},
283 { "spell_check_languages", XT_S_STR
, 0, NULL
, &spell_check_languages
, NULL
},
284 { "ssl_ca_file", XT_S_STR
, 0, NULL
, &ssl_ca_file
, NULL
},
285 { "ssl_strict_certs", XT_S_INT
, 0, &ssl_strict_certs
, NULL
, NULL
},
286 { "statusbar_elems", XT_S_STR
, 0, NULL
, &statusbar_elems
, NULL
},
287 { "tab_style", XT_S_STR
, 0, NULL
, NULL
,&s_tab_style
},
288 { "url_regex", XT_S_STR
, 0, NULL
, &url_regex
, NULL
},
289 { "user_agent", XT_S_STR
, 0, NULL
, &user_agent
, NULL
},
290 { "window_height", XT_S_INT
, 0, &window_height
, NULL
, NULL
},
291 { "window_width", XT_S_INT
, 0, &window_width
, NULL
, NULL
},
292 { "work_dir", XT_S_STR
, 0, NULL
, NULL
,&s_work_dir
},
293 { "xterm_workaround", XT_S_INT
, 0, &xterm_workaround
, NULL
, NULL
},
296 { "cmd_font", XT_S_STR
, 0, NULL
, &cmd_font_name
, NULL
},
297 { "oops_font", XT_S_STR
, 0, NULL
, &oops_font_name
, NULL
},
298 { "statusbar_font", XT_S_STR
, 0, NULL
, &statusbar_font_name
, NULL
},
299 { "tabbar_font", XT_S_STR
, 0, NULL
, &tabbar_font_name
, NULL
},
301 /* runtime settings */
302 { "alias", XT_S_STR
, XT_SF_RUNTIME
, NULL
, NULL
, &s_alias
},
303 { "cookie_wl", XT_S_STR
, XT_SF_RUNTIME
, NULL
, NULL
, &s_cookie_wl
},
304 { "js_wl", XT_S_STR
, XT_SF_RUNTIME
, NULL
, NULL
, &s_js
},
305 { "keybinding", XT_S_STR
, XT_SF_RUNTIME
, NULL
, NULL
, &s_kb
},
306 { "mime_type", XT_S_STR
, XT_SF_RUNTIME
, NULL
, NULL
, &s_mime
},
307 { "pl_wl", XT_S_STR
, XT_SF_RUNTIME
, NULL
, NULL
, &s_pl
},
311 get_settings_size(void)
317 get_setting_name(int i
)
325 get_as_string(struct settings
*s
)
336 warnx("get_as_string skip %s\n", s
->name
);
337 } else if (s
->type
== XT_S_INT
)
338 r
= g_strdup_printf("%d", *s
->ival
);
339 else if (s
->type
== XT_S_STR
)
340 r
= g_strdup(*s
->sval
);
341 else if (s
->type
== XT_S_FLOAT
)
342 r
= g_strdup_printf("%f", *s
->fval
);
344 r
= g_strdup_printf("INVALID TYPE");
350 settings_walk(void (*cb
)(struct settings
*, char *, void *), void *cb_args
)
355 for (i
= 0; i
< LENGTH(rs
); i
++) {
356 if (rs
[i
].s
&& rs
[i
].s
->walk
)
357 rs
[i
].s
->walk(&rs
[i
], cb
, cb_args
);
359 s
= get_as_string(&rs
[i
]);
360 cb(&rs
[i
], s
, cb_args
);
367 set_browser_mode(struct settings
*s
, char *val
)
369 if (!strcmp(val
, "whitelist")) {
370 browser_mode
= XT_BM_WHITELIST
;
371 allow_volatile_cookies
= 0;
372 cookie_policy
= SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY
;
374 enable_cookie_whitelist
= 1;
375 enable_plugin_whitelist
= 1;
377 read_only_cookies
= 0;
378 save_rejected_cookies
= 0;
379 session_timeout
= 3600;
381 enable_js_whitelist
= 1;
382 enable_localstorage
= 0;
383 } else if (!strcmp(val
, "normal")) {
384 browser_mode
= XT_BM_NORMAL
;
385 allow_volatile_cookies
= 0;
386 cookie_policy
= SOUP_COOKIE_JAR_ACCEPT_ALWAYS
;
388 enable_cookie_whitelist
= 0;
389 enable_plugin_whitelist
= 0;
391 read_only_cookies
= 0;
392 save_rejected_cookies
= 0;
393 session_timeout
= 3600;
395 enable_js_whitelist
= 0;
396 enable_localstorage
= 1;
397 } else if (!strcmp(val
, "kiosk")) {
398 browser_mode
= XT_BM_KIOSK
;
399 allow_volatile_cookies
= 0;
400 cookie_policy
= SOUP_COOKIE_JAR_ACCEPT_ALWAYS
;
402 enable_cookie_whitelist
= 0;
403 enable_plugin_whitelist
= 0;
405 read_only_cookies
= 0;
406 save_rejected_cookies
= 0;
407 session_timeout
= 3600;
409 enable_js_whitelist
= 0;
410 enable_localstorage
= 1;
420 get_browser_mode(struct settings
*s
)
424 if (browser_mode
== XT_BM_WHITELIST
)
425 r
= g_strdup("whitelist");
426 else if (browser_mode
== XT_BM_NORMAL
)
427 r
= g_strdup("normal");
428 else if (browser_mode
== XT_BM_KIOSK
)
429 r
= g_strdup("kiosk");
437 set_cookie_policy(struct settings
*s
, char *val
)
439 if (!strcmp(val
, "no3rdparty"))
440 cookie_policy
= SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY
;
441 else if (!strcmp(val
, "accept"))
442 cookie_policy
= SOUP_COOKIE_JAR_ACCEPT_ALWAYS
;
443 else if (!strcmp(val
, "reject"))
444 cookie_policy
= SOUP_COOKIE_JAR_ACCEPT_NEVER
;
452 get_cookie_policy(struct settings
*s
)
456 if (cookie_policy
== SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY
)
457 r
= g_strdup("no3rdparty");
458 else if (cookie_policy
== SOUP_COOKIE_JAR_ACCEPT_ALWAYS
)
459 r
= g_strdup("accept");
460 else if (cookie_policy
== SOUP_COOKIE_JAR_ACCEPT_NEVER
)
461 r
= g_strdup("reject");
469 get_default_script(struct settings
*s
)
471 if (default_script
[0] == '\0')
473 return (g_strdup(default_script
));
477 set_default_script(struct settings
*s
, char *val
)
480 snprintf(default_script
, sizeof default_script
, "%s/%s",
481 pwd
->pw_dir
, &val
[1]);
483 strlcpy(default_script
, val
, sizeof default_script
);
489 get_download_dir(struct settings
*s
)
491 if (download_dir
[0] == '\0')
493 return (g_strdup(download_dir
));
497 set_download_dir(struct settings
*s
, char *val
)
500 snprintf(download_dir
, sizeof download_dir
, "%s/%s",
501 pwd
->pw_dir
, &val
[1]);
503 strlcpy(download_dir
, val
, sizeof download_dir
);
509 add_alias(struct settings
*s
, char *line
)
512 struct alias
*a
= NULL
;
514 if (s
== NULL
|| line
== NULL
) {
515 show_oops(NULL
, "add_alias invalid parameters");
520 a
= g_malloc(sizeof(*a
));
522 if ((alias
= strsep(&l
, " \t,")) == NULL
|| l
== NULL
) {
523 show_oops(NULL
, "add_alias: incomplete alias definition");
526 if (strlen(alias
) == 0 || strlen(l
) == 0) {
527 show_oops(NULL
, "add_alias: invalid alias definition");
531 a
->a_name
= g_strdup(alias
);
532 a
->a_uri
= g_strdup(l
);
534 DNPRINTF(XT_D_CONFIG
, "add_alias: %s for %s\n", a
->a_name
, a
->a_uri
);
536 TAILQ_INSERT_TAIL(&aliases
, a
, entry
);
546 walk_alias(struct settings
*s
,
547 void (*cb
)(struct settings
*, char *, void *), void *cb_args
)
552 if (s
== NULL
|| cb
== NULL
) {
553 show_oops(NULL
, "walk_alias invalid parameters");
557 TAILQ_FOREACH(a
, &aliases
, entry
) {
558 str
= g_strdup_printf("%s --> %s", a
->a_name
, a
->a_uri
);
565 add_mime_type(struct settings
*s
, char *line
)
569 struct mime_type
*m
= NULL
;
570 int downloadfirst
= 0;
572 /* XXX this could be smarter */
574 if (line
== NULL
|| strlen(line
) == 0) {
575 show_oops(NULL
, "add_mime_type invalid parameters");
584 m
= g_malloc(sizeof(*m
));
586 if ((mime_type
= strsep(&l
, " \t,")) == NULL
|| l
== NULL
) {
587 show_oops(NULL
, "add_mime_type: invalid mime_type");
590 if (mime_type
[strlen(mime_type
) - 1] == '*') {
591 mime_type
[strlen(mime_type
) - 1] = '\0';
596 if (strlen(mime_type
) == 0 || strlen(l
) == 0) {
597 show_oops(NULL
, "add_mime_type: invalid mime_type");
601 m
->mt_type
= g_strdup(mime_type
);
602 m
->mt_action
= g_strdup(l
);
603 m
->mt_download
= downloadfirst
;
605 DNPRINTF(XT_D_CONFIG
, "add_mime_type: type %s action %s default %d\n",
606 m
->mt_type
, m
->mt_action
, m
->mt_default
);
608 TAILQ_INSERT_TAIL(&mtl
, m
, entry
);
618 walk_mime_type(struct settings
*s
,
619 void (*cb
)(struct settings
*, char *, void *), void *cb_args
)
624 if (s
== NULL
|| cb
== NULL
) {
625 show_oops(NULL
, "walk_mime_type invalid parameters");
629 TAILQ_FOREACH(m
, &mtl
, entry
) {
630 str
= g_strdup_printf("%s%s --> %s",
632 m
->mt_default
? "*" : "",
639 /* inherent to GTK not all keys will be caught at all times */
640 /* XXX sort key bindings */
641 struct key_binding keys
[] = {
642 { "command_mode", 0, 1, GDK_Escape
},
643 { "insert_mode", 0, 0, GDK_i
},
644 { "cookiejar", MOD1
, 1, GDK_j
},
645 { "downloadmgr", MOD1
, 1, GDK_d
},
646 { "history", MOD1
, 1, GDK_h
},
647 { "print", CTRL
, 1, GDK_p
},
648 { "search", 0, 0, GDK_slash
},
649 { "searchb", 0, 0, GDK_question
},
650 { "statustoggle", CTRL
, 1, GDK_n
},
651 { "command", 0, 0, GDK_colon
},
652 { "qa", CTRL
, 1, GDK_q
},
653 { "restart", MOD1
, 1, GDK_q
},
654 { "js toggle", CTRL
, 1, GDK_j
},
655 { "plugin toggle", MOD1
, 1, GDK_p
},
656 { "cookie toggle", MOD1
, 1, GDK_c
},
657 { "togglesrc", CTRL
, 1, GDK_s
},
658 { "yankuri", 0, 0, GDK_y
},
659 { "pasteuricur", 0, 0, GDK_p
},
660 { "pasteurinew", 0, 0, GDK_P
},
661 { "toplevel toggle", 0, 1, GDK_F4
},
662 { "help", 0, 1, GDK_F1
},
663 { "run_script", MOD1
, 1, GDK_r
},
664 { "proxy toggle", 0, 1, GDK_F2
},
667 { "searchnext", 0, 0, GDK_n
},
668 { "searchprevious", 0, 0, GDK_N
},
671 { "focusaddress", 0, 1, GDK_F6
},
672 { "focussearch", 0, 1, GDK_F7
},
675 { "hinting", 0, 0, GDK_f
},
676 { "hinting", 0, 0, GDK_period
},
677 { "hinting_newtab", SHFT
, 0, GDK_F
},
678 { "hinting_newtab", 0, 0, GDK_comma
},
680 /* custom stylesheet */
681 { "userstyle", 0, 0, GDK_s
},
684 { "goback", 0, 0, GDK_BackSpace
},
685 { "goback", MOD1
, 1, GDK_Left
},
686 { "goforward", SHFT
, 1, GDK_BackSpace
},
687 { "goforward", MOD1
, 1, GDK_Right
},
688 { "reload", 0, 1, GDK_F5
},
689 { "reload", CTRL
, 1, GDK_r
},
690 { "reload", CTRL
, 1, GDK_l
},
691 { "favorites", MOD1
, 1, GDK_f
},
693 /* vertical movement */
694 { "scrolldown", 0, 0, GDK_j
},
695 { "scrolldown", 0, 0, GDK_Down
},
696 { "scrollup", 0, 0, GDK_Up
},
697 { "scrollup", 0, 0, GDK_k
},
698 { "scrollbottom", 0, 0, GDK_G
},
699 { "scrollbottom", 0, 0, GDK_End
},
700 { "scrolltop", 0, 0, GDK_Home
},
701 { "scrollpagedown", 0, 0, GDK_space
},
702 { "scrollpagedown", CTRL
, 1, GDK_f
},
703 { "scrollhalfdown", CTRL
, 1, GDK_d
},
704 { "scrollpagedown", 0, 0, GDK_Page_Down
},
705 { "scrollpageup", 0, 0, GDK_Page_Up
},
706 { "scrollpageup", CTRL
, 1, GDK_b
},
707 { "scrollhalfup", CTRL
, 1, GDK_u
},
708 /* horizontal movement */
709 { "scrollright", 0, 0, GDK_l
},
710 { "scrollright", 0, 0, GDK_Right
},
711 { "scrollleft", 0, 0, GDK_Left
},
712 { "scrollleft", 0, 0, GDK_h
},
713 { "scrollfarright", 0, 0, GDK_dollar
},
714 { "scrollfarleft", 0, 0, GDK_0
},
717 { "tabnew", CTRL
, 1, GDK_t
},
718 { "999tabnew", CTRL
, 1, GDK_T
},
719 { "tabclose", CTRL
, 1, GDK_w
},
720 { "tabundoclose", 0, 0, GDK_U
},
721 { "tabnext 1", CTRL
, 1, GDK_1
},
722 { "tabnext 2", CTRL
, 1, GDK_2
},
723 { "tabnext 3", CTRL
, 1, GDK_3
},
724 { "tabnext 4", CTRL
, 1, GDK_4
},
725 { "tabnext 5", CTRL
, 1, GDK_5
},
726 { "tabnext 6", CTRL
, 1, GDK_6
},
727 { "tabnext 7", CTRL
, 1, GDK_7
},
728 { "tabnext 8", CTRL
, 1, GDK_8
},
729 { "tabnext 9", CTRL
, 1, GDK_9
},
730 { "tabfirst", CTRL
, 1, GDK_less
},
731 { "tablast", CTRL
, 1, GDK_greater
},
732 { "tabprevious", CTRL
, 1, GDK_Left
},
733 { "tabnext", CTRL
, 1, GDK_Right
},
734 { "focusout", CTRL
, 1, GDK_minus
},
735 { "focusin", CTRL
, 1, GDK_plus
},
736 { "focusin", CTRL
, 1, GDK_equal
},
737 { "focusreset", CTRL
, 1, GDK_0
},
739 /* command aliases (handy when -S flag is used) */
740 { "promptopen", 0, 1, GDK_F9
},
741 { "promptopencurrent", 0, 1, GDK_F10
},
742 { "prompttabnew", 0, 1, GDK_F11
},
743 { "prompttabnewcurrent",0, 1, GDK_F12
},
747 walk_kb(struct settings
*s
,
748 void (*cb
)(struct settings
*, char *, void *), void *cb_args
)
750 struct key_binding
*k
;
753 if (s
== NULL
|| cb
== NULL
) {
754 show_oops(NULL
, "walk_kb invalid parameters");
758 TAILQ_FOREACH(k
, &kbl
, entry
) {
764 if (gdk_keyval_name(k
->key
) == NULL
)
767 strlcat(str
, k
->cmd
, sizeof str
);
768 strlcat(str
, ",", sizeof str
);
770 if (k
->mask
& GDK_SHIFT_MASK
)
771 strlcat(str
, "S-", sizeof str
);
772 if (k
->mask
& GDK_CONTROL_MASK
)
773 strlcat(str
, "C-", sizeof str
);
774 if (k
->mask
& GDK_MOD1_MASK
)
775 strlcat(str
, "M1-", sizeof str
);
776 if (k
->mask
& GDK_MOD2_MASK
)
777 strlcat(str
, "M2-", sizeof str
);
778 if (k
->mask
& GDK_MOD3_MASK
)
779 strlcat(str
, "M3-", sizeof str
);
780 if (k
->mask
& GDK_MOD4_MASK
)
781 strlcat(str
, "M4-", sizeof str
);
782 if (k
->mask
& GDK_MOD5_MASK
)
783 strlcat(str
, "M5-", sizeof str
);
785 strlcat(str
, gdk_keyval_name(k
->key
), sizeof str
);
791 init_keybindings(void)
794 struct key_binding
*k
;
796 for (i
= 0; i
< LENGTH(keys
); i
++) {
797 k
= g_malloc0(sizeof *k
);
798 k
->cmd
= keys
[i
].cmd
;
799 k
->mask
= keys
[i
].mask
;
800 k
->use_in_entry
= keys
[i
].use_in_entry
;
801 k
->key
= keys
[i
].key
;
802 TAILQ_INSERT_HEAD(&kbl
, k
, entry
);
804 DNPRINTF(XT_D_KEYBINDING
, "init_keybindings: added: %s\n",
805 k
->cmd
? k
->cmd
: "unnamed key");
810 keybinding_clearall(void)
812 struct key_binding
*k
, *next
;
814 for (k
= TAILQ_FIRST(&kbl
); k
; k
= next
) {
815 next
= TAILQ_NEXT(k
, entry
);
819 DNPRINTF(XT_D_KEYBINDING
, "keybinding_clearall: %s\n",
820 k
->cmd
? k
->cmd
: "unnamed key");
821 TAILQ_REMOVE(&kbl
, k
, entry
);
827 keybinding_add(char *cmd
, char *key
, int use_in_entry
)
829 struct key_binding
*k
;
830 guint keyval
, mask
= 0;
833 DNPRINTF(XT_D_KEYBINDING
, "keybinding_add: %s %s\n", cmd
, key
);
835 /* Keys which are to be used in entry have been prefixed with an
836 * exclamation mark. */
840 /* find modifier keys */
841 if (strstr(key
, "S-"))
842 mask
|= GDK_SHIFT_MASK
;
843 if (strstr(key
, "C-"))
844 mask
|= GDK_CONTROL_MASK
;
845 if (strstr(key
, "M1-"))
846 mask
|= GDK_MOD1_MASK
;
847 if (strstr(key
, "M2-"))
848 mask
|= GDK_MOD2_MASK
;
849 if (strstr(key
, "M3-"))
850 mask
|= GDK_MOD3_MASK
;
851 if (strstr(key
, "M4-"))
852 mask
|= GDK_MOD4_MASK
;
853 if (strstr(key
, "M5-"))
854 mask
|= GDK_MOD5_MASK
;
857 for (i
= strlen(key
) - 1; i
> 0; i
--)
861 /* validate keyname */
862 keyval
= gdk_keyval_from_name(key
);
863 if (keyval
== GDK_VoidSymbol
) {
864 warnx("invalid keybinding name %s", key
);
867 /* must run this test too, gtk+ doesn't handle 10 for example */
868 if (gdk_keyval_name(keyval
) == NULL
) {
869 warnx("invalid keybinding name %s", key
);
873 /* Remove eventual dupes. */
874 TAILQ_FOREACH(k
, &kbl
, entry
)
875 if (k
->key
== keyval
&& k
->mask
== mask
) {
876 TAILQ_REMOVE(&kbl
, k
, entry
);
882 k
= g_malloc0(sizeof *k
);
883 k
->cmd
= g_strdup(cmd
);
885 k
->use_in_entry
= use_in_entry
;
888 DNPRINTF(XT_D_KEYBINDING
, "keybinding_add: %s 0x%x %d 0x%x\n",
893 DNPRINTF(XT_D_KEYBINDING
, "keybinding_add: adding: %s %s\n",
894 k
->cmd
, gdk_keyval_name(keyval
));
896 TAILQ_INSERT_HEAD(&kbl
, k
, entry
);
902 add_kb(struct settings
*s
, char *entry
)
906 DNPRINTF(XT_D_KEYBINDING
, "add_kb: %s\n", entry
);
908 /* clearall is special */
909 if (!strcmp(entry
, "clearall")) {
910 keybinding_clearall();
914 kb
= strstr(entry
, ",");
920 return (keybinding_add(entry
, key
, key
[0] == '!'));
924 setup_proxy(char *uri
)
927 g_object_set(session
, "proxy_uri", NULL
, (char *)NULL
);
928 soup_uri_free(proxy_uri
);
932 if (http_proxy
!= uri
) {
939 http_proxy
= g_strdup(uri
);
940 DNPRINTF(XT_D_CONFIG
, "setup_proxy: %s\n", uri
);
941 proxy_uri
= soup_uri_new(http_proxy
);
942 if (!(proxy_uri
== NULL
|| !SOUP_URI_VALID_FOR_HTTP(proxy_uri
)))
943 g_object_set(session
, "proxy-uri", proxy_uri
,
949 get_tab_style(struct settings
*s
)
951 if (tab_style
== XT_TABS_NORMAL
)
952 return (g_strdup("normal"));
954 return (g_strdup("compact"));
958 set_tab_style(struct settings
*s
, char *val
)
960 if (!strcmp(val
, "normal"))
961 tab_style
= XT_TABS_NORMAL
;
962 else if (!strcmp(val
, "compact"))
963 tab_style
= XT_TABS_COMPACT
;
971 get_edit_mode(struct settings
*s
)
973 if (edit_mode
== XT_EM_HYBRID
)
974 return (g_strdup("hybrid"));
976 return (g_strdup("vi"));
980 set_edit_mode(struct settings
*s
, char *val
)
982 if (!strcmp(val
, "hybrid"))
983 edit_mode
= XT_EM_HYBRID
;
984 else if (!strcmp(val
, "vi"))
985 edit_mode
= XT_EM_VI
;
993 get_work_dir(struct settings
*s
)
995 if (work_dir
[0] == '\0')
997 return (g_strdup(work_dir
));
1001 set_work_dir(struct settings
*s
, char *val
)
1004 snprintf(work_dir
, sizeof work_dir
, "%s/%s",
1005 pwd
->pw_dir
, &val
[1]);
1007 strlcpy(work_dir
, val
, sizeof work_dir
);
1013 walk_cookie_wl(struct settings
*s
,
1014 void (*cb
)(struct settings
*, char *, void *), void *cb_args
)
1018 if (s
== NULL
|| cb
== NULL
) {
1019 show_oops(NULL
, "walk_cookie_wl invalid parameters");
1023 RB_FOREACH_REVERSE(d
, domain_list
, &c_wl
)
1024 cb(s
, d
->d
, cb_args
);
1028 walk_js_wl(struct settings
*s
,
1029 void (*cb
)(struct settings
*, char *, void *), void *cb_args
)
1033 if (s
== NULL
|| cb
== NULL
) {
1034 show_oops(NULL
, "walk_js_wl invalid parameters");
1038 RB_FOREACH_REVERSE(d
, domain_list
, &js_wl
)
1039 cb(s
, d
->d
, cb_args
);
1043 walk_pl_wl(struct settings
*s
,
1044 void (*cb
)(struct settings
*, char *, void *), void *cb_args
)
1048 if (s
== NULL
|| cb
== NULL
) {
1049 show_oops(NULL
, "walk_pl_wl invalid parameters");
1053 RB_FOREACH_REVERSE(d
, domain_list
, &pl_wl
)
1054 cb(s
, d
->d
, cb_args
);
1058 settings_add(char *var
, char *val
)
1065 for (i
= 0, rv
= 0; i
< LENGTH(rs
); i
++) {
1066 if (strcmp(var
, rs
[i
].name
))
1070 if (rs
[i
].s
->set(&rs
[i
], val
))
1071 errx(1, "invalid value for %s: %s", var
, val
);
1075 switch (rs
[i
].type
) {
1084 errx(1, "invalid sval for %s",
1098 errx(1, "invalid type for %s", var
);
1107 config_parse(char *filename
, int runtime
)
1110 char *line
, *cp
, *var
, *val
;
1111 size_t len
, lineno
= 0;
1113 char file
[PATH_MAX
];
1116 DNPRINTF(XT_D_CONFIG
, "config_parse: filename %s\n", filename
);
1118 if (filename
== NULL
)
1121 if (runtime
&& runtime_settings
[0] != '\0') {
1122 snprintf(file
, sizeof file
, "%s/%s",
1123 work_dir
, runtime_settings
);
1124 if (stat(file
, &sb
)) {
1125 warnx("runtime file doesn't exist, creating it");
1126 if ((f
= fopen(file
, "w")) == NULL
)
1128 fprintf(f
, "# AUTO GENERATED, DO NOT EDIT\n");
1132 strlcpy(file
, filename
, sizeof file
);
1134 if ((config
= fopen(file
, "r")) == NULL
) {
1135 warn("config_parse: cannot open %s", filename
);
1140 if ((line
= fparseln(config
, &len
, &lineno
, NULL
, 0)) == NULL
)
1141 if (feof(config
) || ferror(config
))
1145 cp
+= (long)strspn(cp
, WS
);
1146 if (cp
[0] == '\0') {
1152 if ((var
= strsep(&cp
, WS
)) == NULL
|| cp
== NULL
)
1153 startpage_add("invalid configuration file entry: %s",
1156 cp
+= (long)strspn(cp
, WS
);
1158 if ((val
= strsep(&cp
, "\0")) == NULL
)
1161 DNPRINTF(XT_D_CONFIG
, "config_parse: %s=%s\n",
1163 handled
= settings_add(var
, val
);
1166 startpage_add("invalid configuration file entry"
1167 ": %s=%s", var
, val
);
1176 struct settings_args
{
1182 print_setting(struct settings
*s
, char *val
, void *cb_args
)
1185 struct settings_args
*sa
= cb_args
;
1190 if (s
->flags
& XT_SF_RUNTIME
)
1196 *sa
->body
= g_strdup_printf(
1198 "<td style='background-color: %s; width: 10%%;word-break:break-all'>%s</td>"
1199 "<td style='background-color: %s; width: 20%%;word-break:break-all'>%s</td>",
1211 set_show(struct tab
*t
, struct karg
*args
)
1213 char *body
, *page
, *tmp
;
1215 struct settings_args sa
;
1217 bzero(&sa
, sizeof sa
);
1221 body
= g_strdup_printf("<div align='center'><table><tr>"
1222 "<th align='left'>Setting</th>"
1223 "<th align='left'>Value</th></tr>\n");
1225 settings_walk(print_setting
, &sa
);
1228 /* small message if there are none */
1231 body
= g_strdup_printf("%s\n<tr><td style='text-align:center'"
1232 "colspan='2'>No settings</td></tr>\n", body
);
1237 body
= g_strdup_printf("%s</table></div>", body
);
1240 page
= get_html_page("Settings", body
, "", 0);
1244 load_webkit_string(t
, page
, XT_URI_ABOUT_SET
);
1248 return (XT_CB_PASSTHROUGH
);
1252 set(struct tab
*t
, struct karg
*args
)
1257 if (args
== NULL
|| args
->s
== NULL
)
1258 return (set_show(t
, args
));
1261 p
= g_strstrip(args
->s
);
1264 return (set_show(t
, args
));
1266 /* we got some sort of string */
1267 val
= g_strrstr(p
, "=");
1270 val
= g_strchomp(val
);
1273 for (i
= 0; i
< get_settings_size(); i
++) {
1274 if (strcmp(rs
[i
].name
, p
))
1277 if (rs
[i
].activate
) {
1278 if (rs
[i
].activate(val
))
1279 show_oops(t
, "%s invalid value %s",
1282 show_oops(t
, ":set %s = %s", p
, val
);
1285 show_oops(t
, "not a runtime option: %s", p
);
1289 show_oops(t
, "unknown option: %s", p
);
1293 for (i
= 0; i
< get_settings_size(); i
++) {
1294 if (strcmp(rs
[i
].name
, p
))
1297 /* XXX this could use some cleanup */
1298 switch (rs
[i
].type
) {
1301 show_oops(t
, "%s = %d",
1302 rs
[i
].name
, *rs
[i
].ival
);
1303 else if (rs
[i
].s
&& rs
[i
].s
->get
)
1304 show_oops(t
, "%s = %s",
1306 rs
[i
].s
->get(&rs
[i
]));
1307 else if (rs
[i
].s
&& rs
[i
].s
->get
== NULL
)
1308 show_oops(t
, "%s = ...", rs
[i
].name
);
1310 show_oops(t
, "%s = ", rs
[i
].name
);
1314 show_oops(t
, "%s = %f",
1315 rs
[i
].name
, *rs
[i
].fval
);
1316 else if (rs
[i
].s
&& rs
[i
].s
->get
)
1317 show_oops(t
, "%s = %s",
1319 rs
[i
].s
->get(&rs
[i
]));
1320 else if (rs
[i
].s
&& rs
[i
].s
->get
== NULL
)
1321 show_oops(t
, "%s = ...", rs
[i
].name
);
1323 show_oops(t
, "%s = ", rs
[i
].name
);
1326 if (rs
[i
].sval
&& *rs
[i
].sval
)
1327 show_oops(t
, "%s = %s",
1328 rs
[i
].name
, *rs
[i
].sval
);
1329 else if (rs
[i
].s
&& rs
[i
].s
->get
)
1330 show_oops(t
, "%s = %s",
1332 rs
[i
].s
->get(&rs
[i
]));
1333 else if (rs
[i
].s
&& rs
[i
].s
->get
== NULL
)
1334 show_oops(t
, "%s = ...", rs
[i
].name
);
1336 show_oops(t
, "%s = ", rs
[i
].name
);
1339 show_oops(t
, "unknown type for %s", rs
[i
].name
);
1345 show_oops(t
, "unknown option: %s", p
);
1348 return (XT_CB_PASSTHROUGH
);