1 /* -*- c-basic-offset: 4; -*- */
2 // Original code taken from the example webkit-gtk+ application. see notice below.
3 // Modified code is licensed under the GPL 3. See LICENSE file.
7 * Copyright (C) 2006, 2007 Apple Inc.
8 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
27 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #define LENGTH(x) (sizeof x / sizeof x[0])
34 #define MAX_BINDINGS 256
38 #include <gdk/gdkkeysyms.h>
39 #include <sys/socket.h>
41 #include <sys/types.h>
43 #include <sys/utsname.h>
45 #include <webkit/webkit.h>
53 #include <sys/socket.h>
55 #include <libsoup/soup.h>
61 typedef void (*Command)(WebKitWebView*, GArray *argv);
65 /* commandline arguments (set initial values for the state variables) */
67 GOptionEntry entries[] =
69 { "uri", 'u', 0, G_OPTION_ARG_STRING, &uzbl.state.uri,
70 "Uri to load at startup (equivalent to 'set uri = URI')", "URI" },
71 { "verbose", 'v', 0, G_OPTION_ARG_NONE, &uzbl.state.verbose,
72 "Whether to print all messages or just errors.", NULL },
73 { "name", 'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name,
74 "Name of the current instance (defaults to Xorg window id)", "NAME" },
75 { "config", 'c', 0, G_OPTION_ARG_STRING, &uzbl.state.config_file,
76 "Config file (this is pretty much equivalent to uzbl < FILE )", "FILE" },
77 { NULL, 0, 0, 0, NULL, NULL, NULL }
80 /* associate command names to their properties */
81 typedef const struct {
88 enum {TYPE_INT, TYPE_STR};
90 /* an abbreviation to help keep the table's width humane */
91 #define PTR(var, t, d, fun) { .ptr = (void*)&(var), .type = TYPE_##t, .dump = d, .func = fun }
96 } var_name_to_ptr[] = {
97 /* variable name pointer to variable in code type dump callback function */
98 /* --------------------------------------------------------------------------------------- */
99 { "uri", PTR(uzbl.state.uri, STR, 1, cmd_load_uri)},
102 { "verbose", PTR(uzbl.state.verbose, INT, 1, NULL)},
103 >>>>>>> dieterbe/experimental:uzbl.c
104 { "mode", PTR(uzbl.behave.mode, INT, 0, NULL)},
105 { "inject_html", PTR(uzbl.behave.inject_html, STR, 0, cmd_inject_html)},
106 { "base_url", PTR(uzbl.behave.base_url, STR, 1, NULL)},
107 { "html_endmarker", PTR(uzbl.behave.html_endmarker, STR, 1, NULL)},
108 { "html_mode_timeout", PTR(uzbl.behave.html_timeout, INT, 1, NULL)},
109 { "status_message", PTR(uzbl.gui.sbar.msg, STR, 1, update_title)},
110 { "show_status", PTR(uzbl.behave.show_status, INT, 1, cmd_set_status)},
111 { "status_top", PTR(uzbl.behave.status_top, INT, 1, move_statusbar)},
112 { "status_format", PTR(uzbl.behave.status_format, STR, 1, update_title)},
113 { "status_pbar_done", PTR(uzbl.gui.sbar.progress_s, STR, 1, update_title)},
114 { "status_pbar_pending", PTR(uzbl.gui.sbar.progress_u, STR, 1, update_title)},
115 { "status_pbar_width", PTR(uzbl.gui.sbar.progress_w, INT, 1, update_title)},
116 { "status_background", PTR(uzbl.behave.status_background, STR, 1, update_title)},
117 { "insert_indicator", PTR(uzbl.behave.insert_indicator, STR, 1, update_title)},
118 { "command_indicator", PTR(uzbl.behave.cmd_indicator, STR, 1, update_title)},
119 { "title_format_long", PTR(uzbl.behave.title_format_long, STR, 1, update_title)},
120 { "title_format_short", PTR(uzbl.behave.title_format_short, STR, 1, update_title)},
121 { "insert_mode", PTR(uzbl.behave.insert_mode, INT, 1, NULL)},
122 { "always_insert_mode", PTR(uzbl.behave.always_insert_mode, INT, 1, cmd_always_insert_mode)},
123 { "reset_command_mode", PTR(uzbl.behave.reset_command_mode, INT, 1, NULL)},
124 { "modkey", PTR(uzbl.behave.modkey, STR, 1, cmd_modkey)},
125 { "load_finish_handler", PTR(uzbl.behave.load_finish_handler, STR, 1, NULL)},
126 { "load_start_handler", PTR(uzbl.behave.load_start_handler, STR, 1, NULL)},
127 { "load_commit_handler", PTR(uzbl.behave.load_commit_handler, STR, 1, NULL)},
128 { "history_handler", PTR(uzbl.behave.history_handler, STR, 1, NULL)},
129 { "download_handler", PTR(uzbl.behave.download_handler, STR, 1, NULL)},
130 { "cookie_handler", PTR(uzbl.behave.cookie_handler, STR, 1, cmd_cookie_handler)},
131 { "fifo_dir", PTR(uzbl.behave.fifo_dir, STR, 1, cmd_fifo_dir)},
132 { "socket_dir", PTR(uzbl.behave.socket_dir, STR, 1, cmd_socket_dir)},
133 { "http_debug", PTR(uzbl.behave.http_debug, INT, 1, cmd_http_debug)},
134 { "shell_cmd", PTR(uzbl.behave.shell_cmd, STR, 1, NULL)},
135 { "proxy_url", PTR(uzbl.net.proxy_url, STR, 1, set_proxy_url)},
136 { "max_conns", PTR(uzbl.net.max_conns, INT, 1, cmd_max_conns)},
137 { "max_conns_host", PTR(uzbl.net.max_conns_host, INT, 1, cmd_max_conns_host)},
138 { "useragent", PTR(uzbl.net.useragent, STR, 1, cmd_useragent)},
139 /* exported WebKitWebSettings properties*/
140 { "font_size", PTR(uzbl.behave.font_size, INT, 1, cmd_font_size)},
141 { "monospace_size", PTR(uzbl.behave.monospace_size, INT, 1, cmd_font_size)},
142 { "minimum_font_size", PTR(uzbl.behave.minimum_font_size, INT, 1, cmd_minimum_font_size)},
143 { "disable_plugins", PTR(uzbl.behave.disable_plugins, INT, 1, cmd_disable_plugins)},
144 { "disable_scripts", PTR(uzbl.behave.disable_scripts, INT, 1, cmd_disable_scripts)},
145 { "autoload_images", PTR(uzbl.behave.autoload_img, INT, 1, cmd_autoload_img)},
146 { "autoshrink_images", PTR(uzbl.behave.autoshrink_img, INT, 1, cmd_autoshrink_img)},
147 { "enable_spellcheck", PTR(uzbl.behave.enable_spellcheck, INT, 1, cmd_enable_spellcheck)},
148 { "enable_private", PTR(uzbl.behave.enable_private, INT, 1, cmd_enable_private)},
149 { "print_backgrounds", PTR(uzbl.behave.print_bg, INT, 1, cmd_print_bg)},
150 { "stylesheet_uri", PTR(uzbl.behave.style_uri, STR, 1, cmd_style_uri)},
151 { "resizable_text_areas",PTR(uzbl.behave.resizable_txt, INT, 1, cmd_resizable_txt)},
152 { "default_encoding", PTR(uzbl.behave.default_encoding, STR, 1, cmd_default_encoding)},
153 { "enforce_96_dpi", PTR(uzbl.behave.enforce_96dpi, INT, 1, cmd_enforce_96dpi)},
154 { "caret_browsing", PTR(uzbl.behave.caret_browsing, INT, 1, cmd_caret_browsing)},
156 { NULL, {.ptr = NULL, .type = TYPE_INT, .dump = 0, .func = NULL}}
157 }, *n2v_p = var_name_to_ptr;
163 { "SHIFT", GDK_SHIFT_MASK }, // shift
164 { "LOCK", GDK_LOCK_MASK }, // capslock or shiftlock, depending on xserver's modmappings
165 { "CONTROL", GDK_CONTROL_MASK }, // control
166 { "MOD1", GDK_MOD1_MASK }, // 4th mod - normally alt but depends on modmappings
167 { "MOD2", GDK_MOD2_MASK }, // 5th mod
168 { "MOD3", GDK_MOD3_MASK }, // 6th mod
169 { "MOD4", GDK_MOD4_MASK }, // 7th mod
170 { "MOD5", GDK_MOD5_MASK }, // 8th mod
171 { "BUTTON1", GDK_BUTTON1_MASK }, // 1st mouse button
172 { "BUTTON2", GDK_BUTTON2_MASK }, // 2nd mouse button
173 { "BUTTON3", GDK_BUTTON3_MASK }, // 3rd mouse button
174 { "BUTTON4", GDK_BUTTON4_MASK }, // 4th mouse button
175 { "BUTTON5", GDK_BUTTON5_MASK }, // 5th mouse button
176 { "SUPER", GDK_SUPER_MASK }, // super (since 2.10)
177 { "HYPER", GDK_HYPER_MASK }, // hyper (since 2.10)
178 { "META", GDK_META_MASK }, // meta (since 2.10)
183 /* construct a hash from the var_name_to_ptr array for quick access */
185 make_var_to_name_hash() {
186 uzbl.comm.proto_var = g_hash_table_new(g_str_hash, g_str_equal);
188 g_hash_table_insert(uzbl.comm.proto_var, n2v_p->name, (gpointer) &n2v_p->cp);
193 /* --- UTILITY FUNCTIONS --- */
195 expand_vars(char *s) {
198 char ret[256], *vend;
199 GString *buf = g_string_new("");
204 g_string_append_c(buf, *++s);
212 if( (vend = strchr(s, upto)) ||
213 (vend = strchr(s, '\0')) ) {
214 strncpy(ret, s, vend-s);
216 if( (c = g_hash_table_lookup(uzbl.comm.proto_var, ret)) ) {
217 if(c->type == TYPE_STR)
218 g_string_append(buf, (gchar *)*c->ptr);
219 else if(c->type == TYPE_INT) {
220 char *b = itos((int)*c->ptr);
221 g_string_append(buf, b);
225 if(upto == ' ') s = vend;
231 g_string_append_c(buf, *s);
236 return g_string_free(buf, FALSE);
243 snprintf(tmp, sizeof(tmp), "%i", val);
244 return g_strdup(tmp);
248 strfree(gchar *str) { g_free(str); return NULL; } // for freeing & setting to null in one go
251 argv_idx(const GArray *a, const guint idx) { return g_array_index(a, gchar*, idx); }
254 str_replace (const char* search, const char* replace, const char* string) {
258 buf = g_strsplit (string, search, -1);
259 ret = g_strjoinv (replace, buf);
260 g_strfreev(buf); // somebody said this segfaults
266 read_file_by_line (gchar *path) {
267 GIOChannel *chan = NULL;
268 gchar *readbuf = NULL;
270 GArray *lines = g_array_new(TRUE, FALSE, sizeof(gchar*));
273 chan = g_io_channel_new_file(path, "r", NULL);
276 while (g_io_channel_read_line(chan, &readbuf, &len, NULL, NULL) == G_IO_STATUS_NORMAL) {
277 const gchar* val = g_strdup (readbuf);
278 g_array_append_val (lines, val);
283 g_io_channel_unref (chan);
285 fprintf(stderr, "File '%s' not be read.\n", path);
292 gchar* parseenv (char* string) {
293 extern char** environ;
294 gchar* tmpstr = NULL;
298 while (environ[i] != NULL) {
299 gchar** env = g_strsplit (environ[i], "=", 2);
300 gchar* envname = g_strconcat ("$", env[0], NULL);
302 if (g_strrstr (string, envname) != NULL) {
303 tmpstr = g_strdup(string);
305 string = str_replace(envname, env[1], tmpstr);
310 g_strfreev (env); // somebody said this breaks uzbl
318 setup_signal(int signr, sigfunc *shandler) {
319 struct sigaction nh, oh;
321 nh.sa_handler = shandler;
322 sigemptyset(&nh.sa_mask);
325 if(sigaction(signr, &nh, &oh) < 0)
333 if (uzbl.behave.fifo_dir)
334 unlink (uzbl.comm.fifo_path);
335 if (uzbl.behave.socket_dir)
336 unlink (uzbl.comm.socket_path);
338 g_free(uzbl.state.executable_path);
339 g_string_free(uzbl.state.keycmd, TRUE);
340 g_hash_table_destroy(uzbl.bindings);
341 g_hash_table_destroy(uzbl.behave.commands);
344 /* used for html_mode_timeout
345 * be sure to extend this function to use
346 * more timers if needed in other places
349 set_timeout(int seconds) {
351 memset(&t, 0, sizeof t);
353 t.it_value.tv_sec = seconds;
354 t.it_value.tv_usec = 0;
355 setitimer(ITIMER_REAL, &t, NULL);
358 /* --- SIGNAL HANDLER --- */
361 catch_sigterm(int s) {
367 catch_sigint(int s) {
377 set_var_value("mode", "0");
382 /* --- CALLBACKS --- */
385 new_window_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *navigation_action, WebKitWebPolicyDecision *policy_decision, gpointer user_data) {
388 (void) navigation_action;
389 (void) policy_decision;
391 const gchar* uri = webkit_network_request_get_uri (request);
392 if (uzbl.state.verbose)
393 printf("New window requested -> %s \n", uri);
394 new_window_load_uri(uri);
399 create_web_view_cb (WebKitWebView *web_view, WebKitWebFrame *frame, gpointer user_data) {
403 if (uzbl.state.selected_url != NULL) {
404 if (uzbl.state.verbose)
405 printf("\nNew web view -> %s\n",uzbl.state.selected_url);
406 new_window_load_uri(uzbl.state.selected_url);
408 if (uzbl.state.verbose)
409 printf("New web view -> %s\n","Nothing to open, exiting");
415 download_cb (WebKitWebView *web_view, GObject *download, gpointer user_data) {
418 if (uzbl.behave.download_handler) {
419 const gchar* uri = webkit_download_get_uri ((WebKitDownload*)download);
420 if (uzbl.state.verbose)
421 printf("Download -> %s\n",uri);
422 /* if urls not escaped, we may have to escape and quote uri before this call */
423 run_handler(uzbl.behave.download_handler, uri);
428 /* scroll a bar in a given direction */
430 scroll (GtkAdjustment* bar, GArray *argv) {
434 amount = g_ascii_strtod(g_array_index(argv, gchar*, 0), &end);
435 if (*end == '%') amount = gtk_adjustment_get_page_size(bar) * amount * 0.01;
436 gtk_adjustment_set_value (bar, gtk_adjustment_get_value(bar)+amount);
440 scroll_begin(WebKitWebView* page, GArray *argv) {
441 (void) page; (void) argv;
442 gtk_adjustment_set_value (uzbl.gui.bar_v, gtk_adjustment_get_lower(uzbl.gui.bar_v));
446 scroll_end(WebKitWebView* page, GArray *argv) {
447 (void) page; (void) argv;
448 gtk_adjustment_set_value (uzbl.gui.bar_v, gtk_adjustment_get_upper(uzbl.gui.bar_v) -
449 gtk_adjustment_get_page_size(uzbl.gui.bar_v));
453 scroll_vert(WebKitWebView* page, GArray *argv) {
455 scroll(uzbl.gui.bar_v, argv);
459 scroll_horz(WebKitWebView* page, GArray *argv) {
461 scroll(uzbl.gui.bar_h, argv);
466 if (!uzbl.behave.show_status) {
467 gtk_widget_hide(uzbl.gui.mainbar);
469 gtk_widget_show(uzbl.gui.mainbar);
475 toggle_status_cb (WebKitWebView* page, GArray *argv) {
479 if (uzbl.behave.show_status) {
480 gtk_widget_hide(uzbl.gui.mainbar);
482 gtk_widget_show(uzbl.gui.mainbar);
484 uzbl.behave.show_status = !uzbl.behave.show_status;
489 link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpointer data) {
493 //Set selected_url state variable
494 g_free(uzbl.state.selected_url);
495 uzbl.state.selected_url = NULL;
497 uzbl.state.selected_url = g_strdup(link);
503 title_change_cb (WebKitWebView* web_view, WebKitWebFrame* web_frame, const gchar* title, gpointer data) {
507 if (uzbl.gui.main_title)
508 g_free (uzbl.gui.main_title);
509 uzbl.gui.main_title = g_strdup (title);
514 progress_change_cb (WebKitWebView* page, gint progress, gpointer data) {
517 uzbl.gui.sbar.load_progress = progress;
522 load_finish_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
526 if (uzbl.behave.load_finish_handler)
527 run_handler(uzbl.behave.load_finish_handler, "");
531 load_start_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
535 g_string_truncate(uzbl.state.keycmd, 0); // don't need old commands to remain on new page?
536 if (uzbl.behave.load_start_handler)
537 run_handler(uzbl.behave.load_start_handler, "");
541 load_commit_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
544 g_free (uzbl.state.uri);
545 GString* newuri = g_string_new (webkit_web_frame_get_uri (frame));
546 uzbl.state.uri = g_string_free (newuri, FALSE);
547 if (uzbl.behave.reset_command_mode && uzbl.behave.insert_mode) {
548 uzbl.behave.insert_mode = uzbl.behave.always_insert_mode;
551 if (uzbl.behave.load_commit_handler)
552 run_handler(uzbl.behave.load_commit_handler, uzbl.state.uri);
556 destroy_cb (GtkWidget* widget, gpointer data) {
564 if (uzbl.behave.history_handler) {
566 struct tm * timeinfo;
569 timeinfo = localtime ( &rawtime );
570 strftime (date, 80, "\"%Y-%m-%d %H:%M:%S\"", timeinfo);
571 run_handler(uzbl.behave.history_handler, date);
576 /* VIEW funcs (little webkit wrappers) */
577 #define VIEWFUNC(name) static void view_##name(WebKitWebView *page, GArray *argv){(void)argv; webkit_web_view_##name(page);}
579 VIEWFUNC(reload_bypass_cache)
580 VIEWFUNC(stop_loading)
587 /* -- command to callback/function map for things we cannot attach to any signals */
589 static struct {char *name; Command command[2];} cmdlist[] =
590 { /* key function no_split */
591 { "back", {view_go_back, 0} },
592 { "forward", {view_go_forward, 0} },
593 { "scroll_vert", {scroll_vert, 0} },
594 { "scroll_horz", {scroll_horz, 0} },
595 { "scroll_begin", {scroll_begin, 0} },
596 { "scroll_end", {scroll_end, 0} },
597 { "reload", {view_reload, 0}, },
598 { "reload_ign_cache", {view_reload_bypass_cache, 0} },
599 { "stop", {view_stop_loading, 0}, },
600 { "zoom_in", {view_zoom_in, 0}, }, //Can crash (when max zoom reached?).
601 { "zoom_out", {view_zoom_out, 0}, },
602 { "uri", {load_uri, NOSPLIT} },
603 { "js", {run_js, NOSPLIT} },
604 { "script", {run_external_js, 0} },
605 { "toggle_status", {toggle_status_cb, 0} },
606 { "spawn", {spawn, 0} },
607 { "sync_spawn", {spawn_sync, 0} }, // needed for cookie handler
608 { "sh", {spawn_sh, 0} },
609 { "sync_sh", {spawn_sh_sync, 0} }, // needed for cookie handler
610 { "exit", {close_uzbl, 0} },
611 { "search", {search_forward_text, NOSPLIT} },
612 { "search_reverse", {search_reverse_text, NOSPLIT} },
613 { "dehilight", {dehilight, 0} },
614 { "toggle_insert_mode", {toggle_insert_mode, 0} },
616 { "runcmd", {runcmd, NOSPLIT} },
617 { "set", {set_var, NOSPLIT} },
618 { "dump_config", {act_dump_config, 0} }
620 { "set", {set_var, NOSPLIT} },
621 //{ "get", {get_var, NOSPLIT} },
622 { "bind", {act_bind, NOSPLIT} },
623 { "dump_config", {act_dump_config, 0} },
624 { "keycmd", {keycmd, NOSPLIT} },
625 { "keycmd_nl", {keycmd_nl, NOSPLIT} },
626 { "keycmd_bs", {keycmd_bs, 0} },
627 { "chain", {chain, 0} },
628 { "print", {print, NOSPLIT} }
629 >>>>>>> dieterbe/experimental:uzbl.c
636 uzbl.behave.commands = g_hash_table_new(g_str_hash, g_str_equal);
638 for (i = 0; i < LENGTH(cmdlist); i++)
639 g_hash_table_insert(uzbl.behave.commands, cmdlist[i].name, cmdlist[i].command);
642 /* -- CORE FUNCTIONS -- */
645 free_action(gpointer act) {
646 Action *action = (Action*)act;
647 g_free(action->name);
649 g_free(action->param);
654 new_action(const gchar *name, const gchar *param) {
655 Action *action = g_new(Action, 1);
657 action->name = g_strdup(name);
659 action->param = g_strdup(param);
661 action->param = NULL;
667 file_exists (const char * filename) {
668 return (access(filename, F_OK) == 0);
672 set_var(WebKitWebView *page, GArray *argv) {
674 gchar **split = g_strsplit(argv_idx(argv, 0), "=", 2);
675 gchar *value = parseenv(g_strdup(split[1] ? g_strchug(split[1]) : " "));
676 set_var_value(g_strstrip(split[0]), value);
682 print(WebKitWebView *page, GArray *argv) {
686 buf = expand_vars(argv_idx(argv, 0));
692 act_bind(WebKitWebView *page, GArray *argv) {
694 gchar **split = g_strsplit(argv_idx(argv, 0), " = ", 2);
695 gchar *value = parseenv(g_strdup(split[1] ? g_strchug(split[1]) : " "));
696 add_binding(g_strstrip(split[0]), value);
713 toggle_insert_mode(WebKitWebView *page, GArray *argv) {
716 if (argv_idx(argv, 0)) {
717 if (strcmp (argv_idx(argv, 0), "0") == 0) {
718 uzbl.behave.insert_mode = FALSE;
720 uzbl.behave.insert_mode = TRUE;
723 uzbl.behave.insert_mode = ! uzbl.behave.insert_mode;
730 load_uri (WebKitWebView *web_view, GArray *argv) {
731 if (argv_idx(argv, 0)) {
732 GString* newuri = g_string_new (argv_idx(argv, 0));
733 if (g_strrstr (argv_idx(argv, 0), "://") == NULL)
734 g_string_prepend (newuri, "http://");
735 /* if we do handle cookies, ask our handler for them */
736 webkit_web_view_load_uri (web_view, newuri->str);
737 g_string_free (newuri, TRUE);
742 run_js (WebKitWebView * web_view, GArray *argv) {
743 if (argv_idx(argv, 0))
744 webkit_web_view_execute_script (web_view, argv_idx(argv, 0));
748 run_external_js (WebKitWebView * web_view, GArray *argv) {
749 if (argv_idx(argv, 0)) {
750 GArray* lines = read_file_by_line (argv_idx (argv, 0));
755 while ((line = g_array_index(lines, gchar*, i))) {
757 js = g_strdup (line);
759 gchar* newjs = g_strconcat (js, line, NULL);
766 if (uzbl.state.verbose)
767 printf ("External JavaScript file %s loaded\n", argv_idx(argv, 0));
769 if (argv_idx (argv, 1)) {
770 gchar* newjs = str_replace("%s", argv_idx (argv, 1), js);
774 webkit_web_view_execute_script (web_view, js);
776 g_array_free (lines, TRUE);
781 search_text (WebKitWebView *page, GArray *argv, const gboolean forward) {
782 if (argv_idx(argv, 0) && (*argv_idx(argv, 0) != '\0')) {
783 if (g_strcmp0 (uzbl.state.searchtx, argv_idx(argv, 0)) != 0) {
784 webkit_web_view_unmark_text_matches (page);
785 webkit_web_view_mark_text_matches (page, argv_idx(argv, 0), FALSE, 0);
786 uzbl.state.searchtx = g_strdup(argv_idx(argv, 0));
790 if (uzbl.state.searchtx) {
791 if (uzbl.state.verbose)
792 printf ("Searching: %s\n", uzbl.state.searchtx);
793 webkit_web_view_set_highlight_text_matches (page, TRUE);
794 webkit_web_view_search_text (page, uzbl.state.searchtx, FALSE, forward, TRUE);
799 search_forward_text (WebKitWebView *page, GArray *argv) {
800 search_text(page, argv, TRUE);
804 search_reverse_text (WebKitWebView *page, GArray *argv) {
805 search_text(page, argv, FALSE);
809 dehilight (WebKitWebView *page, GArray *argv) {
811 webkit_web_view_set_highlight_text_matches (page, FALSE);
816 new_window_load_uri (const gchar * uri) {
817 GString* to_execute = g_string_new ("");
818 g_string_append_printf (to_execute, "%s --uri '%s'", uzbl.state.executable_path, uri);
820 for (i = 0; entries[i].long_name != NULL; i++) {
821 if ((entries[i].arg == G_OPTION_ARG_STRING) && (strcmp(entries[i].long_name,"uri")!=0) && (strcmp(entries[i].long_name,"name")!=0)) {
822 gchar** str = (gchar**)entries[i].arg_data;
824 g_string_append_printf (to_execute, " --%s '%s'", entries[i].long_name, *str);
828 if (uzbl.state.verbose)
829 printf("\n%s\n", to_execute->str);
830 g_spawn_command_line_async (to_execute->str, NULL);
831 g_string_free (to_execute, TRUE);
835 chain (WebKitWebView *page, GArray *argv) {
838 gchar **parts = NULL;
840 while ((a = argv_idx(argv, i++))) {
841 parts = g_strsplit (a, " ", 2);
842 parse_command(parts[0], parts[1]);
848 keycmd (WebKitWebView *page, GArray *argv) {
851 g_string_assign(uzbl.state.keycmd, argv_idx(argv, 0));
857 keycmd_nl (WebKitWebView *page, GArray *argv) {
860 g_string_assign(uzbl.state.keycmd, argv_idx(argv, 0));
866 keycmd_bs (WebKitWebView *page, GArray *argv) {
869 g_string_truncate(uzbl.state.keycmd, uzbl.state.keycmd->len - 1);
874 close_uzbl (WebKitWebView *page, GArray *argv) {
880 /* --Statusbar functions-- */
882 build_progressbar_ascii(int percent) {
883 int width=uzbl.gui.sbar.progress_w;
886 GString *bar = g_string_new("");
888 l = (double)percent*((double)width/100.);
889 l = (int)(l+.5)>=(int)l ? l+.5 : l;
891 for(i=0; i<(int)l; i++)
892 g_string_append(bar, uzbl.gui.sbar.progress_s);
895 g_string_append(bar, uzbl.gui.sbar.progress_u);
897 return g_string_free(bar, FALSE);
902 const GScannerConfig scan_config = {
905 ) /* cset_skip_characters */,
910 ) /* cset_identifier_first */,
917 ) /* cset_identifier_nth */,
918 ( "" ) /* cpair_comment_single */,
920 TRUE /* case_sensitive */,
922 FALSE /* skip_comment_multi */,
923 FALSE /* skip_comment_single */,
924 FALSE /* scan_comment_multi */,
925 TRUE /* scan_identifier */,
926 TRUE /* scan_identifier_1char */,
927 FALSE /* scan_identifier_NULL */,
928 TRUE /* scan_symbols */,
929 FALSE /* scan_binary */,
930 FALSE /* scan_octal */,
931 FALSE /* scan_float */,
932 FALSE /* scan_hex */,
933 FALSE /* scan_hex_dollar */,
934 FALSE /* scan_string_sq */,
935 FALSE /* scan_string_dq */,
936 TRUE /* numbers_2_int */,
937 FALSE /* int_2_float */,
938 FALSE /* identifier_2_string */,
939 FALSE /* char_2_token */,
940 FALSE /* symbol_2_token */,
941 TRUE /* scope_0_fallback */,
946 uzbl.scan = g_scanner_new(&scan_config);
947 while(symp->symbol_name) {
948 g_scanner_scope_add_symbol(uzbl.scan, 0,
950 GINT_TO_POINTER(symp->symbol_token));
956 expand_template(const char *template, gboolean escape_markup) {
957 if(!template) return NULL;
959 GTokenType token = G_TOKEN_NONE;
960 GString *ret = g_string_new("");
964 g_scanner_input_text(uzbl.scan, template, strlen(template));
965 while(!g_scanner_eof(uzbl.scan) && token != G_TOKEN_LAST) {
966 token = g_scanner_get_next_token(uzbl.scan);
968 if(token == G_TOKEN_SYMBOL) {
969 sym = (int)g_scanner_cur_value(uzbl.scan).v_symbol;
973 buf = uzbl.state.uri?
974 g_markup_printf_escaped("%s", uzbl.state.uri):g_strdup("");
975 g_string_append(ret, buf);
979 g_string_append(ret, uzbl.state.uri?
980 uzbl.state.uri:g_strdup(""));
983 buf = itos(uzbl.gui.sbar.load_progress);
984 g_string_append(ret, buf);
987 case SYM_LOADPRGSBAR:
988 buf = build_progressbar_ascii(uzbl.gui.sbar.load_progress);
989 g_string_append(ret, buf);
994 buf = uzbl.gui.main_title?
995 g_markup_printf_escaped("%s", uzbl.gui.main_title):g_strdup("");
996 g_string_append(ret, buf);
1000 g_string_append(ret, uzbl.gui.main_title?
1001 uzbl.gui.main_title:g_strdup(""));
1003 case SYM_SELECTED_URI:
1005 buf = uzbl.state.selected_url?
1006 g_markup_printf_escaped("%s", uzbl.state.selected_url):g_strdup("");
1007 g_string_append(ret, buf);
1011 g_string_append(ret, uzbl.state.selected_url?
1012 uzbl.state.selected_url:g_strdup(""));
1015 buf = itos(uzbl.xwin);
1016 g_string_append(ret,
1017 uzbl.state.instance_name?uzbl.state.instance_name:buf);
1022 buf = uzbl.state.keycmd->str?
1023 g_markup_printf_escaped("%s", uzbl.state.keycmd->str):g_strdup("");
1024 g_string_append(ret, buf);
1028 g_string_append(ret, uzbl.state.keycmd->str?
1029 uzbl.state.keycmd->str:g_strdup(""));
1032 g_string_append(ret,
1033 uzbl.behave.insert_mode?
1034 uzbl.behave.insert_indicator:uzbl.behave.cmd_indicator);
1037 g_string_append(ret,
1038 uzbl.gui.sbar.msg?uzbl.gui.sbar.msg:"");
1040 /* useragent syms */
1042 buf = itos(WEBKIT_MAJOR_VERSION);
1043 g_string_append(ret, buf);
1047 buf = itos(WEBKIT_MINOR_VERSION);
1048 g_string_append(ret, buf);
1052 buf = itos(WEBKIT_MICRO_VERSION);
1053 g_string_append(ret, buf);
1057 g_string_append(ret, uzbl.state.unameinfo.sysname);
1060 g_string_append(ret, uzbl.state.unameinfo.nodename);
1063 g_string_append(ret, uzbl.state.unameinfo.release);
1066 g_string_append(ret, uzbl.state.unameinfo.version);
1069 g_string_append(ret, uzbl.state.unameinfo.machine);
1072 g_string_append(ret, ARCH);
1075 case SYM_DOMAINNAME:
1076 g_string_append(ret, uzbl.state.unameinfo.domainname);
1080 g_string_append(ret, COMMIT);
1086 else if(token == G_TOKEN_INT) {
1087 buf = itos(g_scanner_cur_value(uzbl.scan).v_int);
1088 g_string_append(ret, buf);
1091 else if(token == G_TOKEN_IDENTIFIER) {
1092 g_string_append(ret, (gchar *)g_scanner_cur_value(uzbl.scan).v_identifier);
1094 else if(token == G_TOKEN_CHAR) {
1095 g_string_append_c(ret, (gchar)g_scanner_cur_value(uzbl.scan).v_char);
1099 return g_string_free(ret, FALSE);
1101 /* --End Statusbar functions-- */
1104 sharg_append(GArray *a, const gchar *str) {
1105 const gchar *s = (str ? str : "");
1106 g_array_append_val(a, s);
1109 // make sure that the args string you pass can properly be interpreted (eg properly escaped against whitespace, quotes etc)
1111 run_command (const gchar *command, const guint npre, const gchar **args,
1112 const gboolean sync, char **stdout) {
1113 //command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl fifo file> <uzbl socket file> [args]
1116 GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*));
1117 gchar *pid = itos(getpid());
1118 gchar *xwin = itos(uzbl.xwin);
1120 sharg_append(a, command);
1121 for (i = 0; i < npre; i++) /* add n args before the default vars */
1122 sharg_append(a, args[i]);
1123 sharg_append(a, uzbl.state.config_file);
1124 sharg_append(a, pid);
1125 sharg_append(a, xwin);
1126 sharg_append(a, uzbl.comm.fifo_path);
1127 sharg_append(a, uzbl.comm.socket_path);
1128 sharg_append(a, uzbl.state.uri);
1129 sharg_append(a, uzbl.gui.main_title);
1131 for (i = npre; i < g_strv_length((gchar**)args); i++)
1132 sharg_append(a, args[i]);
1136 if (*stdout) *stdout = strfree(*stdout);
1138 result = g_spawn_sync(NULL, (gchar **)a->data, NULL, G_SPAWN_SEARCH_PATH,
1139 NULL, NULL, stdout, NULL, NULL, &err);
1140 } else result = g_spawn_async(NULL, (gchar **)a->data, NULL, G_SPAWN_SEARCH_PATH,
1141 NULL, NULL, NULL, &err);
1143 if (uzbl.state.verbose) {
1144 GString *s = g_string_new("spawned:");
1145 for (i = 0; i < (a->len); i++) {
1146 gchar *qarg = g_shell_quote(g_array_index(a, gchar*, i));
1147 g_string_append_printf(s, " %s", qarg);
1150 g_string_append_printf(s, " -- result: %s", (result ? "true" : "false"));
1151 printf("%s\n", s->str);
1152 g_string_free(s, TRUE);
1154 printf("Stdout: %s\n", *stdout);
1158 g_printerr("error on run_command: %s\n", err->message);
1163 g_array_free (a, TRUE);
1168 split_quoted(const gchar* src, const gboolean unquote) {
1169 /* split on unquoted space, return array of strings;
1170 remove a layer of quotes and backslashes if unquote */
1171 if (!src) return NULL;
1173 gboolean dq = FALSE;
1174 gboolean sq = FALSE;
1175 GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*));
1176 GString *s = g_string_new ("");
1180 for (p = src; *p != '\0'; p++) {
1181 if ((*p == '\\') && unquote) g_string_append_c(s, *++p);
1182 else if (*p == '\\') { g_string_append_c(s, *p++);
1183 g_string_append_c(s, *p); }
1184 else if ((*p == '"') && unquote && !sq) dq = !dq;
1185 else if (*p == '"' && !sq) { g_string_append_c(s, *p);
1187 else if ((*p == '\'') && unquote && !dq) sq = !sq;
1188 else if (*p == '\'' && !dq) { g_string_append_c(s, *p);
1190 else if ((*p == ' ') && !dq && !sq) {
1191 dup = g_strdup(s->str);
1192 g_array_append_val(a, dup);
1193 g_string_truncate(s, 0);
1194 } else g_string_append_c(s, *p);
1196 dup = g_strdup(s->str);
1197 g_array_append_val(a, dup);
1198 ret = (gchar**)a->data;
1199 g_array_free (a, FALSE);
1200 g_string_free (s, TRUE);
1205 spawn(WebKitWebView *web_view, GArray *argv) {
1207 //TODO: allow more control over argument order so that users can have some arguments before the default ones from run_command, and some after
1208 if (argv_idx(argv, 0))
1209 run_command(argv_idx(argv, 0), 0, ((const gchar **) (argv->data + sizeof(gchar*))), FALSE, NULL);
1213 spawn_sync(WebKitWebView *web_view, GArray *argv) {
1216 if (argv_idx(argv, 0))
1217 run_command(argv_idx(argv, 0), 0, ((const gchar **) (argv->data + sizeof(gchar*))),
1218 TRUE, &uzbl.comm.sync_stdout);
1222 spawn_sh(WebKitWebView *web_view, GArray *argv) {
1224 if (!uzbl.behave.shell_cmd) {
1225 g_printerr ("spawn_sh: shell_cmd is not set!\n");
1230 gchar *spacer = g_strdup("");
1231 g_array_insert_val(argv, 1, spacer);
1232 gchar **cmd = split_quoted(uzbl.behave.shell_cmd, TRUE);
1234 for (i = 1; i < g_strv_length(cmd); i++)
1235 g_array_prepend_val(argv, cmd[i]);
1237 if (cmd) run_command(cmd[0], g_strv_length(cmd) + 1, (const gchar **) argv->data, FALSE, NULL);
1243 spawn_sh_sync(WebKitWebView *web_view, GArray *argv) {
1245 if (!uzbl.behave.shell_cmd) {
1246 g_printerr ("spawn_sh_sync: shell_cmd is not set!\n");
1251 gchar *spacer = g_strdup("");
1252 g_array_insert_val(argv, 1, spacer);
1253 gchar **cmd = split_quoted(uzbl.behave.shell_cmd, TRUE);
1255 for (i = 1; i < g_strv_length(cmd); i++)
1256 g_array_prepend_val(argv, cmd[i]);
1258 if (cmd) run_command(cmd[0], g_strv_length(cmd) + 1, (const gchar **) argv->data,
1259 TRUE, &uzbl.comm.sync_stdout);
1265 parse_command(const char *cmd, const char *param) {
1268 if ((c = g_hash_table_lookup(uzbl.behave.commands, cmd))) {
1271 gchar **par = split_quoted(param, TRUE);
1272 GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*));
1274 if (c[1] == NOSPLIT) { /* don't split */
1275 sharg_append(a, param);
1277 for (i = 0; i < g_strv_length(par); i++)
1278 sharg_append(a, par[i]);
1280 c[0](uzbl.gui.web_view, a);
1282 g_array_free (a, TRUE);
1285 g_printerr ("command \"%s\" not understood. ignoring.\n", cmd);
1292 if(*uzbl.net.proxy_url == ' '
1293 || uzbl.net.proxy_url == NULL) {
1294 soup_session_remove_feature_by_type(uzbl.net.soup_session,
1295 (GType) SOUP_SESSION_PROXY_URI);
1298 suri = soup_uri_new(uzbl.net.proxy_url);
1299 g_object_set(G_OBJECT(uzbl.net.soup_session),
1300 SOUP_SESSION_PROXY_URI,
1302 soup_uri_free(suri);
1309 GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*));
1310 g_array_append_val (a, uzbl.state.uri);
1311 load_uri(uzbl.gui.web_view, a);
1312 g_array_free (a, TRUE);
1316 cmd_always_insert_mode() {
1317 uzbl.behave.insert_mode =
1318 uzbl.behave.always_insert_mode ? TRUE : FALSE;
1324 g_object_set(G_OBJECT(uzbl.net.soup_session),
1325 SOUP_SESSION_MAX_CONNS, uzbl.net.max_conns, NULL);
1329 cmd_max_conns_host() {
1330 g_object_set(G_OBJECT(uzbl.net.soup_session),
1331 SOUP_SESSION_MAX_CONNS_PER_HOST, uzbl.net.max_conns_host, NULL);
1336 soup_session_remove_feature
1337 (uzbl.net.soup_session, SOUP_SESSION_FEATURE(uzbl.net.soup_logger));
1338 /* do we leak if this doesn't get freed? why does it occasionally crash if freed? */
1339 /*g_free(uzbl.net.soup_logger);*/
1341 uzbl.net.soup_logger = soup_logger_new(uzbl.behave.http_debug, -1);
1342 soup_session_add_feature(uzbl.net.soup_session,
1343 SOUP_SESSION_FEATURE(uzbl.net.soup_logger));
1346 static WebKitWebSettings*
1348 return webkit_web_view_get_settings(uzbl.gui.web_view);
1353 WebKitWebSettings *ws = view_settings();
1354 if (uzbl.behave.font_size > 0) {
1355 g_object_set (G_OBJECT(ws), "default-font-size", uzbl.behave.font_size, NULL);
1358 if (uzbl.behave.monospace_size > 0) {
1359 g_object_set (G_OBJECT(ws), "default-monospace-font-size",
1360 uzbl.behave.monospace_size, NULL);
1362 g_object_set (G_OBJECT(ws), "default-monospace-font-size",
1363 uzbl.behave.font_size, NULL);
1368 cmd_disable_plugins() {
1369 g_object_set (G_OBJECT(view_settings()), "enable-plugins",
1370 !uzbl.behave.disable_plugins, NULL);
1374 cmd_disable_scripts() {
1375 g_object_set (G_OBJECT(view_settings()), "enable-scripts",
1376 !uzbl.behave.disable_scripts, NULL);
1380 cmd_minimum_font_size() {
1381 g_object_set (G_OBJECT(view_settings()), "minimum-font-size",
1382 uzbl.behave.minimum_font_size, NULL);
1385 cmd_autoload_img() {
1386 g_object_set (G_OBJECT(view_settings()), "auto-load-images",
1387 uzbl.behave.autoload_img, NULL);
1392 cmd_autoshrink_img() {
1393 g_object_set (G_OBJECT(view_settings()), "auto-shrink-images",
1394 uzbl.behave.autoshrink_img, NULL);
1399 cmd_enable_spellcheck() {
1400 g_object_set (G_OBJECT(view_settings()), "enable-spell-checking",
1401 uzbl.behave.enable_spellcheck, NULL);
1405 cmd_enable_private() {
1406 g_object_set (G_OBJECT(view_settings()), "enable-private-browsing",
1407 uzbl.behave.enable_private, NULL);
1412 g_object_set (G_OBJECT(view_settings()), "print-backgrounds",
1413 uzbl.behave.print_bg, NULL);
1418 g_object_set (G_OBJECT(view_settings()), "user-stylesheet-uri",
1419 uzbl.behave.style_uri, NULL);
1423 cmd_resizable_txt() {
1424 g_object_set (G_OBJECT(view_settings()), "resizable-text-areas",
1425 uzbl.behave.resizable_txt, NULL);
1429 cmd_default_encoding() {
1430 g_object_set (G_OBJECT(view_settings()), "default-encoding",
1431 uzbl.behave.default_encoding, NULL);
1435 cmd_enforce_96dpi() {
1436 g_object_set (G_OBJECT(view_settings()), "enforce-96-dpi",
1437 uzbl.behave.enforce_96dpi, NULL);
1441 cmd_caret_browsing() {
1442 g_object_set (G_OBJECT(view_settings()), "enable-caret-browsing",
1443 uzbl.behave.caret_browsing, NULL);
1447 cmd_cookie_handler() {
1448 gchar **split = g_strsplit(uzbl.behave.cookie_handler, " ", 2);
1449 /* pitfall: doesn't handle chain actions; must the sync_ action manually */
1450 if ((g_strcmp0(split[0], "sh") == 0) ||
1451 (g_strcmp0(split[0], "spawn") == 0)) {
1452 g_free (uzbl.behave.cookie_handler);
1453 uzbl.behave.cookie_handler =
1454 g_strdup_printf("sync_%s %s", split[0], split[1]);
1461 uzbl.behave.fifo_dir = init_fifo(uzbl.behave.fifo_dir);
1466 uzbl.behave.socket_dir = init_socket(uzbl.behave.socket_dir);
1471 if(uzbl.behave.inject_html) {
1472 webkit_web_view_load_html_string (uzbl.gui.web_view,
1473 uzbl.behave.inject_html, NULL);
1482 buf = g_utf8_strup(uzbl.behave.modkey, -1);
1483 uzbl.behave.modmask = 0;
1485 if(uzbl.behave.modkey)
1486 g_free(uzbl.behave.modkey);
1487 uzbl.behave.modkey = buf;
1489 for (i = 0; modkeys[i].key != NULL; i++) {
1490 if (g_strrstr(buf, modkeys[i].key))
1491 uzbl.behave.modmask |= modkeys[i].mask;
1497 if (*uzbl.net.useragent == ' ') {
1498 g_free (uzbl.net.useragent);
1499 uzbl.net.useragent = NULL;
1501 gchar *ua = expand_template(uzbl.net.useragent, FALSE);
1503 g_object_set(G_OBJECT(uzbl.net.soup_session), SOUP_SESSION_USER_AGENT, ua, NULL);
1504 g_free(uzbl.net.useragent);
1505 uzbl.net.useragent = ua;
1511 gtk_widget_ref(uzbl.gui.scrolled_win);
1512 gtk_widget_ref(uzbl.gui.mainbar);
1513 gtk_container_remove(GTK_CONTAINER(uzbl.gui.vbox), uzbl.gui.scrolled_win);
1514 gtk_container_remove(GTK_CONTAINER(uzbl.gui.vbox), uzbl.gui.mainbar);
1516 if(uzbl.behave.status_top) {
1517 gtk_box_pack_start (GTK_BOX (uzbl.gui.vbox), uzbl.gui.mainbar, FALSE, TRUE, 0);
1518 gtk_box_pack_start (GTK_BOX (uzbl.gui.vbox), uzbl.gui.scrolled_win, TRUE, TRUE, 0);
1521 gtk_box_pack_start (GTK_BOX (uzbl.gui.vbox), uzbl.gui.scrolled_win, TRUE, TRUE, 0);
1522 gtk_box_pack_start (GTK_BOX (uzbl.gui.vbox), uzbl.gui.mainbar, FALSE, TRUE, 0);
1524 gtk_widget_unref(uzbl.gui.scrolled_win);
1525 gtk_widget_unref(uzbl.gui.mainbar);
1526 gtk_widget_grab_focus (GTK_WIDGET (uzbl.gui.web_view));
1531 set_var_value(gchar *name, gchar *val) {
1532 uzbl_cmdprop *c = NULL;
1536 if( (c = g_hash_table_lookup(uzbl.comm.proto_var, name)) ) {
1537 /* check for the variable type */
1538 if (c->type == TYPE_STR) {
1539 buf = expand_vars(val);
1542 } else if(c->type == TYPE_INT) {
1543 int *ip = (int *)c->ptr;
1544 buf = expand_vars(val);
1545 *ip = (int)strtoul(buf, &endp, 10);
1549 /* invoke a command specific function */
1550 if(c->func) c->func();
1557 Behaviour *b = &uzbl.behave;
1559 if(b->html_buffer->str) {
1560 webkit_web_view_load_html_string (uzbl.gui.web_view,
1561 b->html_buffer->str, b->base_url);
1562 g_string_free(b->html_buffer, TRUE);
1563 b->html_buffer = g_string_new("");
1567 enum {M_CMD, M_HTML};
1569 parse_cmd_line(const char *ctl_line) {
1570 Behaviour *b = &uzbl.behave;
1573 if(b->mode == M_HTML) {
1574 len = strlen(b->html_endmarker);
1575 /* ctl_line has trailing '\n' so we check for strlen(ctl_line)-1 */
1576 if(len == strlen(ctl_line)-1 &&
1577 !strncmp(b->html_endmarker, ctl_line, len)) {
1579 set_var_value("mode", "0");
1584 set_timeout(b->html_timeout);
1585 g_string_append(b->html_buffer, ctl_line);
1588 else if((ctl_line[0] == '#') /* Comments */
1589 || (ctl_line[0] == ' ')
1590 || (ctl_line[0] == '\n'))
1591 ; /* ignore these lines */
1592 else { /* parse a command */
1594 gchar **tokens = NULL;
1595 len = strlen(ctl_line);
1597 if (ctl_line[len - 1] == '\n') /* strip trailing newline */
1598 ctlstrip = g_strndup(ctl_line, len - 1);
1599 else ctlstrip = g_strdup(ctl_line);
1601 tokens = g_strsplit(ctlstrip, " ", 2);
1602 parse_command(tokens[0], tokens[1]);
1609 build_stream_name(int type, const gchar* dir) {
1611 State *s = &uzbl.state;
1614 xwin_str = itos((int)uzbl.xwin);
1616 str = g_strdup_printf
1617 ("%s/uzbl_fifo_%s", dir,
1618 s->instance_name ? s->instance_name : xwin_str);
1619 } else if (type == SOCKET) {
1620 str = g_strdup_printf
1621 ("%s/uzbl_socket_%s", dir,
1622 s->instance_name ? s->instance_name : xwin_str );
1629 control_fifo(GIOChannel *gio, GIOCondition condition) {
1630 if (uzbl.state.verbose)
1631 printf("triggered\n");
1636 if (condition & G_IO_HUP)
1637 g_error ("Fifo: Read end of pipe died!\n");
1640 g_error ("Fifo: GIOChannel broke\n");
1642 ret = g_io_channel_read_line(gio, &ctl_line, NULL, NULL, &err);
1643 if (ret == G_IO_STATUS_ERROR) {
1644 g_error ("Fifo: Error reading: %s\n", err->message);
1648 parse_cmd_line(ctl_line);
1655 init_fifo(gchar *dir) { /* return dir or, on error, free dir and return NULL */
1656 if (uzbl.comm.fifo_path) { /* get rid of the old fifo if one exists */
1657 if (unlink(uzbl.comm.fifo_path) == -1)
1658 g_warning ("Fifo: Can't unlink old fifo at %s\n", uzbl.comm.fifo_path);
1659 g_free(uzbl.comm.fifo_path);
1660 uzbl.comm.fifo_path = NULL;
1663 if (*dir == ' ') { /* space unsets the variable */
1668 GIOChannel *chan = NULL;
1669 GError *error = NULL;
1670 gchar *path = build_stream_name(FIFO, dir);
1672 if (!file_exists(path)) {
1673 if (mkfifo (path, 0666) == 0) {
1674 // we don't really need to write to the file, but if we open the file as 'r' we will block here, waiting for a writer to open the file.
1675 chan = g_io_channel_new_file(path, "r+", &error);
1677 if (g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_fifo, NULL)) {
1678 if (uzbl.state.verbose)
1679 printf ("init_fifo: created successfully as %s\n", path);
1680 uzbl.comm.fifo_path = path;
1682 } else g_warning ("init_fifo: could not add watch on %s\n", path);
1683 } else g_warning ("init_fifo: can't open: %s\n", error->message);
1684 } else g_warning ("init_fifo: can't create %s: %s\n", path, strerror(errno));
1685 } else g_warning ("init_fifo: can't create %s: file exists\n", path);
1687 /* if we got this far, there was an error; cleanup */
1688 if (error) g_error_free (error);
1695 control_stdin(GIOChannel *gio, GIOCondition condition) {
1697 gchar *ctl_line = NULL;
1700 ret = g_io_channel_read_line(gio, &ctl_line, NULL, NULL, NULL);
1701 if ( (ret == G_IO_STATUS_ERROR) || (ret == G_IO_STATUS_EOF) )
1704 parse_cmd_line(ctl_line);
1712 GIOChannel *chan = NULL;
1713 GError *error = NULL;
1715 chan = g_io_channel_unix_new(fileno(stdin));
1717 if (!g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_stdin, NULL)) {
1718 g_error ("Stdin: could not add watch\n");
1720 if (uzbl.state.verbose)
1721 printf ("Stdin: watch added successfully\n");
1724 g_error ("Stdin: Error while opening: %s\n", error->message);
1726 if (error) g_error_free (error);
1730 control_socket(GIOChannel *chan) {
1731 struct sockaddr_un remote;
1732 char buffer[512], *ctl_line;
1734 int sock, clientsock, n, done;
1737 sock = g_io_channel_unix_get_fd(chan);
1739 memset (buffer, 0, sizeof (buffer));
1741 t = sizeof (remote);
1742 clientsock = accept (sock, (struct sockaddr *) &remote, &t);
1746 memset (temp, 0, sizeof (temp));
1747 n = recv (clientsock, temp, 128, 0);
1749 buffer[strlen (buffer)] = '\0';
1753 strcat (buffer, temp);
1756 if (strcmp (buffer, "\n") < 0) {
1757 buffer[strlen (buffer) - 1] = '\0';
1759 buffer[strlen (buffer)] = '\0';
1762 ctl_line = g_strdup(buffer);
1763 parse_cmd_line (ctl_line);
1766 TODO: we should be able to do it with this. but glib errors out with "Invalid argument"
1767 GError *error = NULL;
1770 ret = g_io_channel_read_line(chan, &ctl_line, &len, NULL, &error);
1771 if (ret == G_IO_STATUS_ERROR)
1772 g_error ("Error reading: %s\n", error->message);
1774 printf("Got line %s (%u bytes) \n",ctl_line, len);
1776 parse_line(ctl_line);
1784 init_socket(gchar *dir) { /* return dir or, on error, free dir and return NULL */
1785 if (uzbl.comm.socket_path) { /* remove an existing socket should one exist */
1786 if (unlink(uzbl.comm.socket_path) == -1)
1787 g_warning ("init_socket: couldn't unlink socket at %s\n", uzbl.comm.socket_path);
1788 g_free(uzbl.comm.socket_path);
1789 uzbl.comm.socket_path = NULL;
1797 GIOChannel *chan = NULL;
1799 struct sockaddr_un local;
1800 gchar *path = build_stream_name(SOCKET, dir);
1802 sock = socket (AF_UNIX, SOCK_STREAM, 0);
1804 local.sun_family = AF_UNIX;
1805 strcpy (local.sun_path, path);
1806 unlink (local.sun_path);
1808 len = strlen (local.sun_path) + sizeof (local.sun_family);
1809 if (bind (sock, (struct sockaddr *) &local, len) != -1) {
1810 if (uzbl.state.verbose)
1811 printf ("init_socket: opened in %s\n", path);
1814 if( (chan = g_io_channel_unix_new(sock)) ) {
1815 g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_socket, chan);
1816 uzbl.comm.socket_path = path;
1819 } else g_warning ("init_socket: could not open in %s: %s\n", path, strerror(errno));
1821 /* if we got this far, there was an error; cleanup */
1828 NOTE: we want to keep variables like b->title_format_long in their "unprocessed" state
1829 it will probably improve performance if we would "cache" the processed variant, but for now it works well enough...
1831 // this function may be called very early when the templates are not set (yet), hence the checks
1833 update_title (void) {
1834 Behaviour *b = &uzbl.behave;
1837 if (b->show_status) {
1838 if (b->title_format_short) {
1839 parsed = expand_template(b->title_format_short, FALSE);
1840 gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed);
1843 if (b->status_format) {
1844 parsed = expand_template(b->status_format, TRUE);
1845 gtk_label_set_markup(GTK_LABEL(uzbl.gui.mainbar_label), parsed);
1848 if (b->status_background) {
1850 gdk_color_parse (b->status_background, &color);
1851 //labels and hboxes do not draw their own background. applying this on the window is ok as we the statusbar is the only affected widget. (if not, we could also use GtkEventBox)
1852 gtk_widget_modify_bg (uzbl.gui.main_window, GTK_STATE_NORMAL, &color);
1855 if (b->title_format_long) {
1856 parsed = expand_template(b->title_format_long, FALSE);
1857 gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed);
1864 key_press_cb (GtkWidget* window, GdkEventKey* event)
1866 //TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1870 if (event->type != GDK_KEY_PRESS || event->keyval == GDK_Page_Up || event->keyval == GDK_Page_Down
1871 || event->keyval == GDK_Up || event->keyval == GDK_Down || event->keyval == GDK_Left || event->keyval == GDK_Right || event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R)
1874 /* turn off insert mode (if always_insert_mode is not used) */
1875 if (uzbl.behave.insert_mode && (event->keyval == GDK_Escape)) {
1876 uzbl.behave.insert_mode = uzbl.behave.always_insert_mode;
1881 if (uzbl.behave.insert_mode && (((event->state & uzbl.behave.modmask) != uzbl.behave.modmask) || (!uzbl.behave.modmask)))
1884 if (event->keyval == GDK_Escape) {
1885 g_string_truncate(uzbl.state.keycmd, 0);
1887 dehilight(uzbl.gui.web_view, NULL);
1891 //Insert without shift - insert from clipboard; Insert with shift - insert from primary
1892 if (event->keyval == GDK_Insert) {
1894 if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) {
1895 str = gtk_clipboard_wait_for_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY));
1897 str = gtk_clipboard_wait_for_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD));
1900 g_string_append (uzbl.state.keycmd, str);
1907 if (event->keyval == GDK_BackSpace)
1908 keycmd_bs(NULL, NULL);
1910 gboolean key_ret = FALSE;
1911 if ((event->keyval == GDK_Return) || (event->keyval == GDK_KP_Enter))
1913 if (!key_ret) g_string_append(uzbl.state.keycmd, event->string);
1915 run_keycmd(key_ret);
1917 if (key_ret) return (!uzbl.behave.insert_mode);
1922 run_keycmd(const gboolean key_ret) {
1923 /* run the keycmd immediately if it isn't incremental and doesn't take args */
1925 if ((act = g_hash_table_lookup(uzbl.bindings, uzbl.state.keycmd->str))) {
1926 g_string_truncate(uzbl.state.keycmd, 0);
1927 parse_command(act->name, act->param);
1931 /* try if it's an incremental keycmd or one that takes args, and run it */
1932 GString* short_keys = g_string_new ("");
1933 GString* short_keys_inc = g_string_new ("");
1935 for (i=0; i<(uzbl.state.keycmd->len); i++) {
1936 g_string_append_c(short_keys, uzbl.state.keycmd->str[i]);
1937 g_string_assign(short_keys_inc, short_keys->str);
1938 g_string_append_c(short_keys, '_');
1939 g_string_append_c(short_keys_inc, '*');
1941 if (key_ret && (act = g_hash_table_lookup(uzbl.bindings, short_keys->str))) {
1942 /* run normal cmds only if return was pressed */
1943 exec_paramcmd(act, i);
1944 g_string_truncate(uzbl.state.keycmd, 0);
1946 } else if ((act = g_hash_table_lookup(uzbl.bindings, short_keys_inc->str))) {
1947 if (key_ret) /* just quit the incremental command on return */
1948 g_string_truncate(uzbl.state.keycmd, 0);
1949 else exec_paramcmd(act, i); /* otherwise execute the incremental */
1953 g_string_truncate(short_keys, short_keys->len - 1);
1955 g_string_free (short_keys, TRUE);
1956 g_string_free (short_keys_inc, TRUE);
1960 exec_paramcmd(const Action *act, const guint i) {
1961 GString *parampart = g_string_new (uzbl.state.keycmd->str);
1962 GString *actionname = g_string_new ("");
1963 GString *actionparam = g_string_new ("");
1964 g_string_erase (parampart, 0, i+1);
1966 g_string_printf (actionname, act->name, parampart->str);
1968 g_string_printf (actionparam, act->param, parampart->str);
1969 parse_command(actionname->str, actionparam->str);
1970 g_string_free(actionname, TRUE);
1971 g_string_free(actionparam, TRUE);
1972 g_string_free(parampart, TRUE);
1980 GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL);
1981 //main_window_ref = g_object_ref(scrolled_window);
1982 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_NEVER); //todo: some sort of display of position/total length. like what emacs does
1984 g->web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ());
1985 gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (g->web_view));
1987 g_signal_connect (G_OBJECT (g->web_view), "title-changed", G_CALLBACK (title_change_cb), g->web_view);
1988 g_signal_connect (G_OBJECT (g->web_view), "load-progress-changed", G_CALLBACK (progress_change_cb), g->web_view);
1989 g_signal_connect (G_OBJECT (g->web_view), "load-committed", G_CALLBACK (load_commit_cb), g->web_view);
1990 g_signal_connect (G_OBJECT (g->web_view), "load-started", G_CALLBACK (load_start_cb), g->web_view);
1991 g_signal_connect (G_OBJECT (g->web_view), "load-finished", G_CALLBACK (log_history_cb), g->web_view);
1992 g_signal_connect (G_OBJECT (g->web_view), "load-finished", G_CALLBACK (load_finish_cb), g->web_view);
1993 g_signal_connect (G_OBJECT (g->web_view), "hovering-over-link", G_CALLBACK (link_hover_cb), g->web_view);
1994 g_signal_connect (G_OBJECT (g->web_view), "new-window-policy-decision-requested", G_CALLBACK (new_window_cb), g->web_view);
1995 g_signal_connect (G_OBJECT (g->web_view), "download-requested", G_CALLBACK (download_cb), g->web_view);
1996 g_signal_connect (G_OBJECT (g->web_view), "create-web-view", G_CALLBACK (create_web_view_cb), g->web_view);
1998 return scrolled_window;
2005 g->mainbar = gtk_hbox_new (FALSE, 0);
2007 /* keep a reference to the bar so we can re-pack it at runtime*/
2008 //sbar_ref = g_object_ref(g->mainbar);
2010 g->mainbar_label = gtk_label_new ("");
2011 gtk_label_set_selectable((GtkLabel *)g->mainbar_label, TRUE);
2012 gtk_label_set_ellipsize(GTK_LABEL(g->mainbar_label), PANGO_ELLIPSIZE_END);
2013 gtk_misc_set_alignment (GTK_MISC(g->mainbar_label), 0, 0);
2014 gtk_misc_set_padding (GTK_MISC(g->mainbar_label), 2, 2);
2015 gtk_box_pack_start (GTK_BOX (g->mainbar), g->mainbar_label, TRUE, TRUE, 0);
2020 GtkWidget* create_window () {
2021 GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2022 gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
2023 gtk_widget_set_name (window, "Uzbl browser");
2024 g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy_cb), NULL);
2025 g_signal_connect (G_OBJECT (window), "key-press-event", G_CALLBACK (key_press_cb), NULL);
2031 inject_handler_args(const gchar *actname, const gchar *origargs, const gchar *newargs) {
2033 If actname is one that calls an external command, this function will inject
2034 newargs in front of the user-provided args in that command line. They will
2035 come become after the body of the script (in sh) or after the name of
2036 the command to execute (in spawn).
2037 i.e. sh <body> <userargs> becomes sh <body> <ARGS> <userargs> and
2038 span <command> <userargs> becomes spawn <command> <ARGS> <userargs>.
2040 The return value consist of two strings: the action (sh, ...) and its args.
2042 If act is not one that calls an external command, then the given action merely
2045 GArray *rets = g_array_new(TRUE, FALSE, sizeof(gchar*));
2046 gchar *actdup = g_strdup(actname);
2047 g_array_append_val(rets, actdup);
2049 if ((g_strcmp0(actname, "spawn") == 0) ||
2050 (g_strcmp0(actname, "sh") == 0) ||
2051 (g_strcmp0(actname, "sync_spawn") == 0) ||
2052 (g_strcmp0(actname, "sync_sh") == 0)) {
2054 GString *a = g_string_new("");
2055 gchar **spawnparts = split_quoted(origargs, FALSE);
2056 g_string_append_printf(a, "%s", spawnparts[0]); /* sh body or script name */
2057 if (newargs) g_string_append_printf(a, " %s", newargs); /* handler args */
2059 for (i = 1; i < g_strv_length(spawnparts); i++) /* user args */
2060 if (spawnparts[i]) g_string_append_printf(a, " %s", spawnparts[i]);
2062 g_array_append_val(rets, a->str);
2063 g_string_free(a, FALSE);
2064 g_strfreev(spawnparts);
2066 gchar *origdup = g_strdup(origargs);
2067 g_array_append_val(rets, origdup);
2069 return (gchar**)g_array_free(rets, FALSE);
2073 run_handler (const gchar *act, const gchar *args) {
2074 /* Consider this code a temporary hack to make the handlers usable.
2075 In practice, all this splicing, injection, and reconstruction is
2076 inefficient, annoying and hard to manage. Potential pitfalls arise
2077 when the handler specific args 1) are not quoted (the handler
2078 callbacks should take care of this) 2) are quoted but interfere
2079 with the users' own quotation. A more ideal solution is
2080 to refactor parse_command so that it doesn't just take a string
2081 and execute it; rather than that, we should have a function which
2082 returns the argument vector parsed from the string. This vector
2083 could be modified (e.g. insert additional args into it) before
2084 passing it to the next function that actually executes it. Though
2085 it still isn't perfect for chain actions.. will reconsider & re-
2086 factor when I have the time. -duc */
2088 char **parts = g_strsplit(act, " ", 2);
2090 if (g_strcmp0(parts[0], "chain") == 0) {
2091 GString *newargs = g_string_new("");
2092 gchar **chainparts = split_quoted(parts[1], FALSE);
2094 /* for every argument in the chain, inject the handler args
2095 and make sure the new parts are wrapped in quotes */
2096 gchar **cp = chainparts;
2098 gchar *quotless = NULL;
2099 gchar **spliced_quotless = NULL; // sigh -_-;
2100 gchar **inpart = NULL;
2103 if ((**cp == '\'') || (**cp == '\"')) { /* strip old quotes */
2105 quotless = g_strndup(&(*cp)[1], strlen(*cp) - 2);
2106 } else quotless = g_strdup(*cp);
2108 spliced_quotless = g_strsplit(quotless, " ", 2);
2109 inpart = inject_handler_args(spliced_quotless[0], spliced_quotless[1], args);
2110 g_strfreev(spliced_quotless);
2112 g_string_append_printf(newargs, " %c%s %s%c", quot, inpart[0], inpart[1], quot);
2118 parse_command(parts[0], &(newargs->str[1]));
2119 g_string_free(newargs, TRUE);
2120 g_strfreev(chainparts);
2123 gchar **inparts = inject_handler_args(parts[0], parts[1], args);
2124 parse_command(inparts[0], inparts[1]);
2132 add_binding (const gchar *key, const gchar *act) {
2133 char **parts = g_strsplit(act, " ", 2);
2140 if (uzbl.state.verbose)
2141 printf ("Binding %-10s : %s\n", key, act);
2142 action = new_action(parts[0], parts[1]);
2144 g_hash_table_replace(uzbl.bindings, g_strdup(key), action);
2149 get_xdg_var (XDG_Var xdg) {
2150 const gchar* actual_value = getenv (xdg.environmental);
2151 const gchar* home = getenv ("HOME");
2153 gchar* return_value = str_replace ("~", home, actual_value);
2155 if (! actual_value || strcmp (actual_value, "") == 0) {
2156 if (xdg.default_value) {
2157 return_value = str_replace ("~", home, xdg.default_value);
2159 return_value = NULL;
2162 return return_value;
2166 find_xdg_file (int xdg_type, char* filename) {
2167 /* xdg_type = 0 => config
2168 xdg_type = 1 => data
2169 xdg_type = 2 => cache*/
2171 gchar* xdgv = get_xdg_var (XDG[xdg_type]);
2172 gchar* temporary_file = g_strconcat (xdgv, filename, NULL);
2175 gchar* temporary_string;
2179 if (! file_exists (temporary_file) && xdg_type != 2) {
2180 buf = get_xdg_var (XDG[3 + xdg_type]);
2181 temporary_string = (char *) strtok_r (buf, ":", &saveptr);
2184 while ((temporary_string = (char * ) strtok_r (NULL, ":", &saveptr)) && ! file_exists (temporary_file)) {
2185 g_free (temporary_file);
2186 temporary_file = g_strconcat (temporary_string, filename, NULL);
2190 //g_free (temporary_string); - segfaults.
2192 if (file_exists (temporary_file)) {
2193 return temporary_file;
2200 State *s = &uzbl.state;
2201 Network *n = &uzbl.net;
2203 for (i = 0; default_config[i].command != NULL; i++) {
2204 parse_cmd_line(default_config[i].command);
2207 if (!s->config_file) {
2208 s->config_file = find_xdg_file (0, "/uzbl/config");
2211 if (s->config_file) {
2212 GArray* lines = read_file_by_line (s->config_file);
2216 while ((line = g_array_index(lines, gchar*, i))) {
2217 parse_cmd_line (line);
2221 g_array_free (lines, TRUE);
2223 if (uzbl.state.verbose)
2224 printf ("No configuration file loaded.\n");
2227 g_signal_connect(n->soup_session, "request-queued", G_CALLBACK(handle_cookies), NULL);
2230 static void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data){
2233 if (!uzbl.behave.cookie_handler)
2236 soup_message_add_header_handler(msg, "got-headers", "Set-Cookie", G_CALLBACK(save_cookies), NULL);
2237 GString *s = g_string_new ("");
2238 SoupURI * soup_uri = soup_message_get_uri(msg);
2239 g_string_printf(s, "GET '%s' '%s'", soup_uri->host, soup_uri->path);
2240 run_handler(uzbl.behave.cookie_handler, s->str);
2242 if(uzbl.comm.sync_stdout && strcmp (uzbl.comm.sync_stdout, "") != 0) {
2243 char *p = strchr(uzbl.comm.sync_stdout, '\n' );
2244 if ( p != NULL ) *p = '\0';
2245 soup_message_headers_replace (msg->request_headers, "Cookie", (const char *) uzbl.comm.sync_stdout);
2247 if (uzbl.comm.sync_stdout)
2248 uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
2250 g_string_free(s, TRUE);
2254 save_cookies (SoupMessage *msg, gpointer user_data){
2258 for (ck = soup_cookies_from_response(msg); ck; ck = ck->next){
2259 cookie = soup_cookie_to_set_cookie_header(ck->data);
2260 SoupURI * soup_uri = soup_message_get_uri(msg);
2261 GString *s = g_string_new ("");
2262 g_string_printf(s, "PUT '%s' '%s' '%s'", soup_uri->host, soup_uri->path, cookie);
2263 run_handler(uzbl.behave.cookie_handler, s->str);
2265 g_string_free(s, TRUE);
2270 /* --- WEBINSPECTOR --- */
2272 hide_window_cb(GtkWidget *widget, gpointer data) {
2275 gtk_widget_hide(widget);
2278 static WebKitWebView*
2279 create_inspector_cb (WebKitWebInspector* web_inspector, WebKitWebView* page, gpointer data){
2282 (void) web_inspector;
2283 GtkWidget* scrolled_window;
2284 GtkWidget* new_web_view;
2287 g->inspector_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2288 g_signal_connect(G_OBJECT(g->inspector_window), "delete-event",
2289 G_CALLBACK(hide_window_cb), NULL);
2291 gtk_window_set_title(GTK_WINDOW(g->inspector_window), "Uzbl WebInspector");
2292 gtk_window_set_default_size(GTK_WINDOW(g->inspector_window), 400, 300);
2293 gtk_widget_show(g->inspector_window);
2295 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
2296 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
2297 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2298 gtk_container_add(GTK_CONTAINER(g->inspector_window), scrolled_window);
2299 gtk_widget_show(scrolled_window);
2301 new_web_view = webkit_web_view_new();
2302 gtk_container_add(GTK_CONTAINER(scrolled_window), new_web_view);
2304 return WEBKIT_WEB_VIEW(new_web_view);
2308 inspector_show_window_cb (WebKitWebInspector* inspector){
2310 gtk_widget_show(uzbl.gui.inspector_window);
2314 /* TODO: Add variables and code to make use of these functions */
2316 inspector_close_window_cb (WebKitWebInspector* inspector){
2322 inspector_attach_window_cb (WebKitWebInspector* inspector){
2328 inspector_dettach_window_cb (WebKitWebInspector* inspector){
2334 inspector_uri_changed_cb (WebKitWebInspector* inspector){
2340 inspector_inspector_destroyed_cb (WebKitWebInspector* inspector){
2346 set_up_inspector() {
2348 WebKitWebSettings *settings = view_settings();
2349 g_object_set(G_OBJECT(settings), "enable-developer-extras", TRUE, NULL);
2351 uzbl.gui.inspector = webkit_web_view_get_inspector(uzbl.gui.web_view);
2352 g_signal_connect (G_OBJECT (g->inspector), "inspect-web-view", G_CALLBACK (create_inspector_cb), NULL);
2353 g_signal_connect (G_OBJECT (g->inspector), "show-window", G_CALLBACK (inspector_show_window_cb), NULL);
2354 g_signal_connect (G_OBJECT (g->inspector), "close-window", G_CALLBACK (inspector_close_window_cb), NULL);
2355 g_signal_connect (G_OBJECT (g->inspector), "attach-window", G_CALLBACK (inspector_attach_window_cb), NULL);
2356 g_signal_connect (G_OBJECT (g->inspector), "dettach-window", G_CALLBACK (inspector_dettach_window_cb), NULL);
2357 g_signal_connect (G_OBJECT (g->inspector), "destroy", G_CALLBACK (inspector_inspector_destroyed_cb), NULL);
2359 g_signal_connect (G_OBJECT (g->inspector), "notify::inspected-uri", G_CALLBACK (inspector_uri_changed_cb), NULL);
2363 dump_var_hash(gpointer k, gpointer v, gpointer ud) {
2365 uzbl_cmdprop *c = v;
2370 if(c->type == TYPE_STR)
2371 printf("set %s = %s\n", (char *)k, *c->ptr?(char *)*c->ptr:" ");
2372 else if(c->type == TYPE_INT)
2373 printf("set %s = %d\n", (char *)k, (int)*c->ptr);
2377 dump_key_hash(gpointer k, gpointer v, gpointer ud) {
2382 printf("bind %s = %s %s\n", (char *)k ,
2383 (char *)a->name, a->param?(char *)a->param:"");
2388 printf("bind %s = %s %s\n", (char *)k ,
2389 (char *)a->name, a->param?(char *)a->param:"");
2392 >>>>>>> dieterbe/experimental:uzbl.c
2395 g_hash_table_foreach(uzbl.comm.proto_var, dump_var_hash, NULL);
2396 g_hash_table_foreach(uzbl.bindings, dump_key_hash, NULL);
2401 main (int argc, char* argv[]) {
2402 gtk_init (&argc, &argv);
2403 if (!g_thread_supported ())
2404 g_thread_init (NULL);
2405 uzbl.state.executable_path = g_strdup(argv[0]);
2406 uzbl.state.selected_url = NULL;
2407 uzbl.state.searchtx = NULL;
2409 GOptionContext* context = g_option_context_new ("- some stuff here maybe someday");
2410 g_option_context_add_main_entries (context, entries, NULL);
2411 g_option_context_add_group (context, gtk_get_option_group (TRUE));
2412 g_option_context_parse (context, &argc, &argv, NULL);
2413 g_option_context_free(context);
2415 gchar *uri_override = (uzbl.state.uri ? g_strdup(uzbl.state.uri) : NULL);
2416 gboolean verbose_override = uzbl.state.verbose;
2418 /* initialize hash table */
2419 uzbl.bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_action);
2421 uzbl.net.soup_session = webkit_get_default_session();
2422 uzbl.state.keycmd = g_string_new("");
2424 if(setup_signal(SIGTERM, catch_sigterm) == SIG_ERR)
2425 fprintf(stderr, "uzbl: error hooking SIGTERM\n");
2426 if(setup_signal(SIGINT, catch_sigint) == SIG_ERR)
2427 fprintf(stderr, "uzbl: error hooking SIGINT\n");
2428 if(setup_signal(SIGALRM, catch_alrm) == SIG_ERR)
2429 fprintf(stderr, "uzbl: error hooking SIGALARM\n");
2432 if(uname(&uzbl.state.unameinfo) == -1)
2433 g_printerr("Can't retrieve unameinfo. Your useragent might appear wrong.\n");
2435 uzbl.gui.sbar.progress_s = g_strdup("=");
2436 uzbl.gui.sbar.progress_u = g_strdup("ยท");
2437 uzbl.gui.sbar.progress_w = 10;
2439 /* HTML mode defaults*/
2440 uzbl.behave.html_buffer = g_string_new("");
2441 uzbl.behave.html_endmarker = g_strdup(".");
2442 uzbl.behave.html_timeout = 60;
2443 uzbl.behave.base_url = g_strdup("http://invalid");
2445 /* default mode indicators */
2446 uzbl.behave.insert_indicator = g_strdup("I");
2447 uzbl.behave.cmd_indicator = g_strdup("C");
2452 >>>>>>> dieterbe/experimental:uzbl.c
2455 make_var_to_name_hash();
2457 uzbl.gui.vbox = gtk_vbox_new (FALSE, 0);
2459 uzbl.gui.scrolled_win = create_browser();
2462 /* initial packing */
2463 gtk_box_pack_start (GTK_BOX (uzbl.gui.vbox), uzbl.gui.scrolled_win, TRUE, TRUE, 0);
2464 gtk_box_pack_start (GTK_BOX (uzbl.gui.vbox), uzbl.gui.mainbar, FALSE, TRUE, 0);
2466 uzbl.gui.main_window = create_window ();
2467 gtk_container_add (GTK_CONTAINER (uzbl.gui.main_window), uzbl.gui.vbox);
2470 gtk_widget_grab_focus (GTK_WIDGET (uzbl.gui.web_view));
2471 gtk_widget_show_all (uzbl.gui.main_window);
2472 uzbl.xwin = GDK_WINDOW_XID (GTK_WIDGET (uzbl.gui.main_window)->window);
2474 if (uzbl.state.verbose) {
2475 printf("Uzbl start location: %s\n", argv[0]);
2476 printf("window_id %i\n",(int) uzbl.xwin);
2477 printf("pid %i\n", getpid ());
2478 printf("name: %s\n", uzbl.state.instance_name);
2481 uzbl.gui.scbar_v = (GtkScrollbar*) gtk_vscrollbar_new (NULL);
2482 uzbl.gui.bar_v = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_v);
2483 uzbl.gui.scbar_h = (GtkScrollbar*) gtk_hscrollbar_new (NULL);
2484 uzbl.gui.bar_h = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_h);
2485 gtk_widget_set_scroll_adjustments ((GtkWidget*) uzbl.gui.web_view, uzbl.gui.bar_h, uzbl.gui.bar_v);
2489 if (!uzbl.behave.show_status)
2490 gtk_widget_hide(uzbl.gui.mainbar);
2499 if (verbose_override > uzbl.state.verbose)
2500 uzbl.state.verbose = verbose_override;
2503 set_var_value("uri", uri_override);
2504 g_free(uri_override);
2505 } else if (uzbl.state.uri)
2506 cmd_load_uri(uzbl.gui.web_view, NULL);
2511 return EXIT_SUCCESS;
2514 /* vi: set et ts=4: */