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>
44 #include <webkit/webkit.h>
52 #include <sys/socket.h>
54 #include <libsoup/soup.h>
61 /* define names and pointers to all config specific variables */
65 } var_name_to_ptr[] = {
66 // Already working commands
67 { "uri", (void *)&uzbl.state.uri },
68 { "status_format", (void *)&uzbl.behave.status_format },
69 { "status_background", (void *)&uzbl.behave.status_background },
70 { "status_message", (void *)&uzbl.gui.sbar.msg },
71 { "show_status", (void *)&uzbl.behave.show_status },
72 { "insert_mode", (void *)&uzbl.behave.insert_mode },
73 { "modkey" , (void *)&uzbl.behave.modkey },
74 { "always_insert" , (void *)&uzbl.behave.always_insert_mode },
75 { "load_finish_handler",(void *)&uzbl.behave.load_finish_handler},
76 { "history_handler", (void *)&uzbl.behave.history_handler },
77 { "download_handler", (void *)&uzbl.behave.download_handler },
78 { "cookie_handler", (void *)&uzbl.behave.cookie_handler },
79 { "fifo_dir", (void *)&uzbl.behave.fifo_dir },
80 { "socket_dir", (void *)&uzbl.behave.socket_dir },
81 { "proxy_url", (void *)&uzbl.net.proxy_url },
82 { "max_conns", (void *)&uzbl.net.max_conns },
83 { "max_conns_host", (void *)&uzbl.net.max_conns_host },
84 { "http_debug", (void *)&uzbl.behave.http_debug },
85 // TODO: write cmd handlers for the following
86 { "useragent", (void *)&uzbl.net.useragent },
88 }, *n2v_p = var_name_to_ptr;
90 /* construct a hash from the var_name_to_ptr array for quick access */
92 make_var_to_name_hash() {
93 uzbl.comm.proto_var = g_hash_table_new(g_str_hash, g_str_equal);
95 g_hash_table_insert(uzbl.comm.proto_var, n2v_p->name, n2v_p->ptr);
100 /* commandline arguments (set initial values for the state variables) */
101 static GOptionEntry entries[] =
103 { "uri", 'u', 0, G_OPTION_ARG_STRING, &uzbl.state.uri, "Uri to load", "URI" },
104 { "name", 'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name, "Name of the current instance", "NAME" },
105 { "config", 'c', 0, G_OPTION_ARG_STRING, &uzbl.state.config_file, "Config file", "FILE" },
106 { NULL, 0, 0, 0, NULL, NULL, NULL }
109 typedef void (*Command)(WebKitWebView*, const char *);
112 static char *XDG_CONFIG_HOME_default[256];
113 static char *XDG_CONFIG_DIRS_default = "/etc/xdg";
116 /* --- UTILITY FUNCTIONS --- */
122 snprintf(tmp, sizeof(tmp), "%i", val);
123 return g_strdup(tmp);
127 str_replace (const char* search, const char* replace, const char* string) {
128 return g_strjoinv (replace, g_strsplit(string, search, -1));
132 setup_signal(int signr, sigfunc *shandler) {
133 struct sigaction nh, oh;
135 nh.sa_handler = shandler;
136 sigemptyset(&nh.sa_mask);
139 if(sigaction(signr, &nh, &oh) < 0)
147 if (uzbl.behave.fifo_dir)
148 unlink (uzbl.comm.fifo_path);
149 if (uzbl.behave.socket_dir)
150 unlink (uzbl.comm.socket_path);
152 g_string_free(uzbl.state.keycmd, TRUE);
153 g_hash_table_destroy(uzbl.bindings);
154 g_hash_table_destroy(uzbl.behave.commands);
158 /* --- SIGNAL HANDLER --- */
161 catch_sigterm(int s) {
166 /* --- CALLBACKS --- */
169 new_window_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *navigation_action, WebKitWebPolicyDecision *policy_decision, gpointer user_data) {
172 (void) navigation_action;
173 (void) policy_decision;
175 const gchar* uri = webkit_network_request_get_uri (request);
176 printf("New window requested -> %s \n", uri);
177 new_window_load_uri(uri);
182 create_web_view_cb (WebKitWebView *web_view, WebKitWebFrame *frame, gpointer user_data) {
186 if (uzbl.state.selected_url[0]!=0) {
187 printf("\nNew web view -> %s\n",uzbl.state.selected_url);
188 new_window_load_uri(uzbl.state.selected_url);
190 printf("New web view -> %s\n","Nothing to open, exiting");
196 download_cb (WebKitWebView *web_view, GObject *download, gpointer user_data) {
199 if (uzbl.behave.download_handler) {
200 const gchar* uri = webkit_download_get_uri ((WebKitDownload*)download);
201 printf("Download -> %s\n",uri);
202 run_command_async(uzbl.behave.download_handler, uri);
207 /* scroll a bar in a given direction */
209 scroll (GtkAdjustment* bar, const char *param) {
213 amount = g_ascii_strtod(param, &end);
216 fprintf(stderr, "found something after double: %s\n", end);
218 gtk_adjustment_set_value (bar, gtk_adjustment_get_value(bar)+amount);
221 static void scroll_vert(WebKitWebView* page, const char *param) {
224 scroll(uzbl.gui.bar_v, param);
227 static void scroll_horz(WebKitWebView* page, const char *param) {
230 scroll(uzbl.gui.bar_h, param);
235 if (!uzbl.behave.show_status) {
236 gtk_widget_hide(uzbl.gui.mainbar);
238 gtk_widget_show(uzbl.gui.mainbar);
244 toggle_status_cb (WebKitWebView* page, const char *param) {
248 if (uzbl.behave.show_status) {
249 gtk_widget_hide(uzbl.gui.mainbar);
251 gtk_widget_show(uzbl.gui.mainbar);
253 uzbl.behave.show_status = !uzbl.behave.show_status;
258 link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpointer data) {
262 //ADD HOVER URL TO WINDOW TITLE
263 uzbl.state.selected_url[0] = '\0';
265 strcpy (uzbl.state.selected_url, link);
271 title_change_cb (WebKitWebView* web_view, WebKitWebFrame* web_frame, const gchar* title, gpointer data) {
275 if (uzbl.gui.main_title)
276 g_free (uzbl.gui.main_title);
277 uzbl.gui.main_title = g_strdup (title);
282 progress_change_cb (WebKitWebView* page, gint progress, gpointer data) {
285 uzbl.gui.sbar.load_progress = progress;
290 load_finish_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
294 if (uzbl.behave.load_finish_handler) {
295 run_command_async(uzbl.behave.load_finish_handler, NULL);
300 load_commit_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
303 free (uzbl.state.uri);
304 GString* newuri = g_string_new (webkit_web_frame_get_uri (frame));
305 uzbl.state.uri = g_string_free (newuri, FALSE);
306 if (uzbl.behave.reset_command_mode && uzbl.behave.insert_mode) {
307 uzbl.behave.insert_mode = uzbl.behave.always_insert_mode;
310 g_string_truncate(uzbl.state.keycmd, 0); // don't need old commands to remain on new page?
314 destroy_cb (GtkWidget* widget, gpointer data) {
322 if (uzbl.behave.history_handler) {
324 struct tm * timeinfo;
327 timeinfo = localtime ( &rawtime );
328 strftime (date, 80, "%Y-%m-%d %H:%M:%S", timeinfo);
329 GString* args = g_string_new ("");
330 g_string_printf (args, "'%s'", date);
331 run_command_async(uzbl.behave.history_handler, args->str);
332 g_string_free (args, TRUE);
337 /* VIEW funcs (little webkit wrappers) */
338 #define VIEWFUNC(name) static void view_##name(WebKitWebView *page, const char *param){(void)param; webkit_web_view_##name(page);}
340 VIEWFUNC(reload_bypass_cache)
341 VIEWFUNC(stop_loading)
348 /* -- command to callback/function map for things we cannot attach to any signals */
351 static struct {char *name; Command command;} cmdlist[] =
353 { "back", view_go_back },
354 { "forward", view_go_forward },
355 { "scroll_vert", scroll_vert },
356 { "scroll_horz", scroll_horz },
357 { "reload", view_reload, },
358 { "reload_ign_cache", view_reload_bypass_cache},
359 { "stop", view_stop_loading, },
360 { "zoom_in", view_zoom_in, }, //Can crash (when max zoom reached?).
361 { "zoom_out", view_zoom_out, },
363 { "script", run_js },
364 { "toggle_status", toggle_status_cb },
366 { "exit", close_uzbl },
367 { "search", search_text },
368 { "insert_mode", set_insert_mode }
375 uzbl.behave.commands = g_hash_table_new(g_str_hash, g_str_equal);
377 for (i = 0; i < LENGTH(cmdlist); i++)
378 g_hash_table_insert(uzbl.behave.commands, cmdlist[i].name, cmdlist[i].command);
381 /* -- CORE FUNCTIONS -- */
384 free_action(gpointer act) {
385 Action *action = (Action*)act;
386 g_free(action->name);
388 g_free(action->param);
393 new_action(const gchar *name, const gchar *param) {
394 Action *action = g_new(Action, 1);
396 action->name = g_strdup(name);
398 action->param = g_strdup(param);
400 action->param = NULL;
406 file_exists (const char * filename) {
407 FILE *file = fopen (filename, "r");
416 set_insert_mode(WebKitWebView *page, const gchar *param) {
420 uzbl.behave.insert_mode = TRUE;
425 load_uri (WebKitWebView * web_view, const gchar *param) {
427 GString* newuri = g_string_new (param);
428 if (g_strrstr (param, "://") == NULL)
429 g_string_prepend (newuri, "http://");
430 /* if we do handle cookies, ask our handler for them */
431 webkit_web_view_load_uri (web_view, newuri->str);
432 g_string_free (newuri, TRUE);
437 run_js (WebKitWebView * web_view, const gchar *param) {
439 webkit_web_view_execute_script (web_view, param);
443 search_text (WebKitWebView *page, const char *param) {
444 if ((param) && (param[0] != '\0')) {
445 strcpy(uzbl.state.searchtx, param);
447 if (uzbl.state.searchtx[0] != '\0') {
448 printf ("Searching: %s\n", uzbl.state.searchtx);
449 webkit_web_view_unmark_text_matches (page);
450 webkit_web_view_mark_text_matches (page, uzbl.state.searchtx, FALSE, 0);
451 webkit_web_view_set_highlight_text_matches (page, TRUE);
452 webkit_web_view_search_text (page, uzbl.state.searchtx, FALSE, TRUE, TRUE);
457 new_window_load_uri (const gchar * uri) {
458 GString* to_execute = g_string_new ("");
459 g_string_append_printf (to_execute, "%s --uri '%s'", uzbl.state.executable_path, uri);
461 for (i = 0; entries[i].long_name != NULL; i++) {
462 if ((entries[i].arg == G_OPTION_ARG_STRING) && (strcmp(entries[i].long_name,"uri")!=0)) {
463 gchar** str = (gchar**)entries[i].arg_data;
465 g_string_append_printf (to_execute, " --%s '%s'", entries[i].long_name, *str);
469 printf("\n%s\n", to_execute->str);
470 g_spawn_command_line_async (to_execute->str, NULL);
471 g_string_free (to_execute, TRUE);
475 close_uzbl (WebKitWebView *page, const char *param) {
481 /* --Statusbar functions-- */
483 build_progressbar_ascii(int percent) {
487 GString *bar = g_string_new("");
489 l = (double)percent*((double)width/100.);
490 l = (int)(l+.5)>=(int)l ? l+.5 : l;
492 g_string_append(bar, "[");
493 for(i=0; i<(int)l; i++)
494 g_string_append(bar, "=");
497 g_string_append(bar, "·");
498 g_string_append(bar, "]");
500 return g_string_free(bar, FALSE);
505 const GScannerConfig scan_config = {
508 ) /* cset_skip_characters */,
513 ) /* cset_identifier_first */,
520 ) /* cset_identifier_nth */,
521 ( "" ) /* cpair_comment_single */,
523 TRUE /* case_sensitive */,
525 FALSE /* skip_comment_multi */,
526 FALSE /* skip_comment_single */,
527 FALSE /* scan_comment_multi */,
528 TRUE /* scan_identifier */,
529 TRUE /* scan_identifier_1char */,
530 FALSE /* scan_identifier_NULL */,
531 TRUE /* scan_symbols */,
532 FALSE /* scan_binary */,
533 FALSE /* scan_octal */,
534 FALSE /* scan_float */,
535 FALSE /* scan_hex */,
536 FALSE /* scan_hex_dollar */,
537 FALSE /* scan_string_sq */,
538 FALSE /* scan_string_dq */,
539 TRUE /* numbers_2_int */,
540 FALSE /* int_2_float */,
541 FALSE /* identifier_2_string */,
542 FALSE /* char_2_token */,
543 FALSE /* symbol_2_token */,
544 TRUE /* scope_0_fallback */,
549 uzbl.scan = g_scanner_new(&scan_config);
550 while(symp->symbol_name) {
551 g_scanner_scope_add_symbol(uzbl.scan, 0,
553 GINT_TO_POINTER(symp->symbol_token));
559 parse_status_template(const char *template) {
560 GTokenType token = G_TOKEN_NONE;
561 GString *ret = g_string_new("");
568 g_scanner_input_text(uzbl.scan, template, strlen(template));
569 while(!g_scanner_eof(uzbl.scan) && token != G_TOKEN_LAST) {
570 token = g_scanner_get_next_token(uzbl.scan);
572 if(token == G_TOKEN_SYMBOL) {
573 sym = (int)g_scanner_cur_value(uzbl.scan).v_symbol;
578 g_markup_printf_escaped("%s", uzbl.state.uri):"");
581 g_string_append(ret, itos(uzbl.gui.sbar.load_progress));
583 case SYM_LOADPRGSBAR:
584 buf = build_progressbar_ascii(uzbl.gui.sbar.load_progress);
585 g_string_append(ret, buf);
591 g_markup_printf_escaped("%s", uzbl.gui.main_title):"");
595 uzbl.state.instance_name?uzbl.state.instance_name:itos(uzbl.xwin));
599 uzbl.state.keycmd->str ?
600 g_markup_printf_escaped("%s", uzbl.state.keycmd->str):"");
604 uzbl.behave.insert_mode?"[I]":"[C]");
608 uzbl.gui.sbar.msg?uzbl.gui.sbar.msg:"");
614 else if(token == G_TOKEN_INT) {
615 g_string_append(ret, itos(g_scanner_cur_value(uzbl.scan).v_int));
617 else if(token == G_TOKEN_IDENTIFIER) {
618 g_string_append(ret, (gchar *)g_scanner_cur_value(uzbl.scan).v_identifier);
620 else if(token == G_TOKEN_CHAR) {
621 g_string_append_c(ret, (gchar)g_scanner_cur_value(uzbl.scan).v_char);
625 return g_string_free(ret, FALSE);
627 /* --End Statusbar functions-- */
630 // make sure to put '' around args, so that if there is whitespace we can still keep arguments together.
632 run_command_async(const char *command, const char *args) {
633 //command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl fifo file> <uzbl socket file> [args]
634 GString* to_execute = g_string_new ("");
636 g_string_printf (to_execute, "%s '%s' '%i' '%i' '%s' '%s'",
637 command, uzbl.state.config_file, (int) getpid() ,
638 (int) uzbl.xwin, uzbl.comm.fifo_path, uzbl.comm.socket_path);
639 g_string_append_printf (to_execute, " '%s' '%s'",
640 uzbl.state.uri, "TODO title here");
642 g_string_append_printf (to_execute, " %s", args);
644 result = g_spawn_command_line_async (to_execute->str, NULL);
645 printf("Called %s. Result: %s\n", to_execute->str, (result ? "TRUE" : "FALSE" ));
646 g_string_free (to_execute, TRUE);
651 run_command_sync(const char *command, const char *args, char **stdout) {
652 //command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl fifo file> <uzbl socket file> [args]
653 GString* to_execute = g_string_new ("");
655 g_string_printf (to_execute, "%s '%s' '%i' '%i' '%s' '%s'", command, uzbl.state.config_file, (int) getpid() , (int) uzbl.xwin, uzbl.comm.fifo_path, uzbl.comm.socket_path);
656 g_string_append_printf (to_execute, " '%s' '%s'", uzbl.state.uri, "TODO title here");
658 g_string_append_printf (to_execute, " %s", args);
660 result = g_spawn_command_line_sync (to_execute->str, stdout, NULL, NULL, NULL);
661 printf("Called %s. Result: %s\n", to_execute->str, (result ? "TRUE" : "FALSE" ));
662 g_string_free (to_execute, TRUE);
667 spawn(WebKitWebView *web_view, const char *param) {
669 run_command_async(param, NULL);
673 parse_command(const char *cmd, const char *param) {
676 if ((c = g_hash_table_lookup(uzbl.behave.commands, cmd)))
677 c(uzbl.gui.web_view, param);
679 fprintf (stderr, "command \"%s\" not understood. ignoring.\n", cmd);
687 uzbl.comm.get_regex = g_regex_new("^[Gg][a-zA-Z]*\\s+([^ \\n]+)$",
688 G_REGEX_OPTIMIZE, 0, &err);
689 uzbl.comm.set_regex = g_regex_new("^[Ss][a-zA-Z]*\\s+([^ ]+)\\s*=\\s*([^\\n].*)$",
690 G_REGEX_OPTIMIZE, 0, &err);
691 uzbl.comm.bind_regex = g_regex_new("^[Bb][a-zA-Z]*\\s+?(.*[^ ])\\s*?=\\s*([a-z][^\\n].+)$",
692 G_REGEX_UNGREEDY|G_REGEX_OPTIMIZE, 0, &err);
693 uzbl.comm.cmd_regex = g_regex_new("^[Cc][a-zA-Z]*\\s+([^ \\n]+)\\s*([^\\n]*)?$",
694 G_REGEX_OPTIMIZE, 0, &err);
698 get_var_value(gchar *name) {
701 if( (p = g_hash_table_lookup(uzbl.comm.proto_var, name)) ) {
702 if(!strcmp(name, "status_format")) {
703 printf("VAR: %s VALUE: %s\n", name, (char *)*p);
705 printf("VAR: %s VALUE: %d\n", name, (int)*p);
715 if(*uzbl.net.proxy_url == ' '
716 || uzbl.net.proxy_url == NULL) {
717 soup_session_remove_feature_by_type(uzbl.net.soup_session,
718 (GType) SOUP_SESSION_PROXY_URI);
721 suri = soup_uri_new(uzbl.net.proxy_url);
722 g_object_set(G_OBJECT(uzbl.net.soup_session),
723 SOUP_SESSION_PROXY_URI,
732 Behaviour *b = &uzbl.behave;
737 //POSSIBLE MODKEY VALUES (COMBINATIONS CAN BE USED)
738 gchar* modkeyup = g_utf8_strup (b->modkey, -1);
739 if (g_strrstr (modkeyup,"SHIFT") != NULL) b->modmask |= GDK_SHIFT_MASK; //the Shift key.
740 if (g_strrstr (modkeyup,"LOCK") != NULL) b->modmask |= GDK_LOCK_MASK; //a Lock key (depending on the modifier mapping of the X server this may either be CapsLock or ShiftLock).
741 if (g_strrstr (modkeyup,"CONTROL") != NULL) b->modmask |= GDK_CONTROL_MASK; //the Control key.
742 if (g_strrstr (modkeyup,"MOD1") != NULL) b->modmask |= GDK_MOD1_MASK; //the fourth modifier key (it depends on the modifier mapping of the X server which key is interpreted as this modifier, but normally it is the Alt key).
743 if (g_strrstr (modkeyup,"MOD2") != NULL) b->modmask |= GDK_MOD2_MASK; //the fifth modifier key (it depends on the modifier mapping of the X server which key is interpreted as this modifier).
744 if (g_strrstr (modkeyup,"MOD3") != NULL) b->modmask |= GDK_MOD3_MASK; //the sixth modifier key (it depends on the modifier mapping of the X server which key is interpreted as this modifier).
745 if (g_strrstr (modkeyup,"MOD4") != NULL) b->modmask |= GDK_MOD4_MASK; //the seventh modifier key (it depends on the modifier mapping of the X server which key is interpreted as this modifier).
746 if (g_strrstr (modkeyup,"MOD5") != NULL) b->modmask |= GDK_MOD5_MASK; //the eighth modifier key (it depends on the modifier mapping of the X server which key is interpreted as this modifier).
747 if (g_strrstr (modkeyup,"BUTTON1") != NULL) b->modmask |= GDK_BUTTON1_MASK; //the first mouse button.
748 if (g_strrstr (modkeyup,"BUTTON2") != NULL) b->modmask |= GDK_BUTTON2_MASK; //the second mouse button.
749 if (g_strrstr (modkeyup,"BUTTON3") != NULL) b->modmask |= GDK_BUTTON3_MASK; //the third mouse button.
750 if (g_strrstr (modkeyup,"BUTTON4") != NULL) b->modmask |= GDK_BUTTON4_MASK; //the fourth mouse button.
751 if (g_strrstr (modkeyup,"BUTTON5") != NULL) b->modmask |= GDK_BUTTON5_MASK; //the fifth mouse button.
752 if (g_strrstr (modkeyup,"SUPER") != NULL) b->modmask |= GDK_SUPER_MASK; //the Super modifier. Since 2.10
753 if (g_strrstr (modkeyup,"HYPER") != NULL) b->modmask |= GDK_HYPER_MASK; //the Hyper modifier. Since 2.10
754 if (g_strrstr (modkeyup,"META") != NULL) b->modmask |= GDK_META_MASK; //the Meta modifier. Since 2.10 */
759 var_is(const char *x, const char *y) {
760 gboolean ret = FALSE;
769 set_var_value(gchar *name, gchar *val) {
773 if( (p = g_hash_table_lookup(uzbl.comm.proto_var, name)) ) {
774 if(var_is("status_message", name)
775 || var_is("status_background", name)
776 || var_is("status_format", name)
777 || var_is("load_finish_handler", name)
778 || var_is("history_handler", name)
779 || var_is("download_handler", name)
780 || var_is("cookie_handler", name)) {
786 else if(var_is("uri", name)) {
789 load_uri(uzbl.gui.web_view, (const gchar*)*p);
791 else if(var_is("proxy_url", name)) {
796 else if(var_is("fifo_dir", name)) {
798 *p = init_fifo(g_strdup(val));
800 else if(var_is("socket_dir", name)) {
802 *p = init_socket(g_strdup(val));
804 else if(var_is("modkey", name)) {
809 /* variables that take int values */
812 *ip = (int)strtoul(val, &endp, 10);
814 if(var_is("show_status", name)) {
817 else if(var_is("always_insert", name)) {
819 uzbl.behave.insert_mode =
820 uzbl.behave.always_insert_mode ? TRUE : FALSE;
823 else if (var_is("max_conns", name)) {
824 g_object_set(G_OBJECT(uzbl.net.soup_session),
825 SOUP_SESSION_MAX_CONNS, uzbl.net.max_conns, NULL);
827 else if (var_is("max_conns_host", name)) {
828 g_object_set(G_OBJECT(uzbl.net.soup_session),
829 SOUP_SESSION_MAX_CONNS_PER_HOST, uzbl.net.max_conns_host, NULL);
831 else if (var_is("http_debug", name)) {
832 //soup_session_remove_feature
833 // (uzbl.net.soup_session, uzbl.net.soup_logger);
834 soup_session_remove_feature
835 (uzbl.net.soup_session, SOUP_SESSION_FEATURE(uzbl.net.soup_logger));
836 /* do we leak if this doesn't get freed? why does it occasionally crash if freed? */
837 /*g_free(uzbl.net.soup_logger);*/
839 uzbl.net.soup_logger = soup_logger_new(uzbl.behave.http_debug, -1);
840 soup_session_add_feature(uzbl.net.soup_session,
841 SOUP_SESSION_FEATURE(uzbl.net.soup_logger));
849 parse_cmd_line(char *ctl_line) {
853 if(ctl_line[0] == 's' || ctl_line[0] == 'S') {
854 tokens = g_regex_split(uzbl.comm.set_regex, ctl_line, 0);
855 if(tokens[0][0] == 0) {
856 set_var_value(tokens[1], tokens[2]);
860 printf("Error in command: %s\n", tokens[0]);
863 else if(ctl_line[0] == 'g' || ctl_line[0] == 'G') {
864 tokens = g_regex_split(uzbl.comm.get_regex, ctl_line, 0);
865 if(tokens[0][0] == 0) {
866 get_var_value(tokens[1]);
870 printf("Error in command: %s\n", tokens[0]);
873 else if(ctl_line[0] == 'b' || ctl_line[0] == 'B') {
874 tokens = g_regex_split(uzbl.comm.bind_regex, ctl_line, 0);
875 if(tokens[0][0] == 0) {
876 add_binding(tokens[1], tokens[2]);
880 printf("Error in command: %s\n", tokens[0]);
883 else if(ctl_line[0] == 'C' || ctl_line[0] == 'c') {
884 tokens = g_regex_split(uzbl.comm.cmd_regex, ctl_line, 0);
885 if(tokens[0][0] == 0) {
886 parse_command(tokens[1], tokens[2]);
890 printf("Error in command: %s\n", tokens[0]);
893 else if( (ctl_line[0] == '#')
894 || (ctl_line[0] == ' ')
895 || (ctl_line[0] == '\n'))
896 ; /* ignore these lines */
898 printf("Command not understood (%s)\n", ctl_line);
904 build_stream_name(int type, const gchar* dir) {
906 State *s = &uzbl.state;
909 xwin_str = itos((int)uzbl.xwin);
911 str = g_strdup_printf
912 ("%s/uzbl_fifo_%s", dir,
913 s->instance_name ? s->instance_name : xwin_str);
914 } else if (type == SOCKET) {
915 str = g_strdup_printf
916 ("%s/uzbl_socket_%s", dir,
917 s->instance_name ? s->instance_name : xwin_str );
924 control_fifo(GIOChannel *gio, GIOCondition condition) {
925 printf("triggered\n");
930 if (condition & G_IO_HUP)
931 g_error ("Fifo: Read end of pipe died!\n");
934 g_error ("Fifo: GIOChannel broke\n");
936 ret = g_io_channel_read_line(gio, &ctl_line, NULL, NULL, &err);
937 if (ret == G_IO_STATUS_ERROR)
938 g_error ("Fifo: Error reading: %s\n", err->message);
940 parse_cmd_line(ctl_line);
947 init_fifo(gchar *dir) { /* return dir or, on error, free dir and return NULL */
948 if (uzbl.comm.fifo_path) { /* get rid of the old fifo if one exists */
949 if (unlink(uzbl.comm.fifo_path) == -1)
950 g_warning ("Fifo: Can't unlink old fifo at %s\n", uzbl.comm.fifo_path);
951 g_free(uzbl.comm.fifo_path);
952 uzbl.comm.fifo_path = NULL;
955 if (!strcmp(dir, " ")) { /* space unsets the variable */
960 GIOChannel *chan = NULL;
961 GError *error = NULL;
962 gchar *path = build_stream_name(FIFO, dir);
964 if (!file_exists(path)) {
965 if (mkfifo (path, 0666) == 0) {
966 // 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.
967 chan = g_io_channel_new_file(path, "r+", &error);
969 if (g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_fifo, NULL)) {
970 printf ("init_fifo: created successfully as %s\n", path);
971 uzbl.comm.fifo_path = path;
973 } else g_warning ("init_fifo: could not add watch on %s\n", path);
974 } else g_warning ("init_fifo: can't open: %s\n", error->message);
975 } else g_warning ("init_fifo: can't create %s: %s\n", path, strerror(errno));
976 } else g_warning ("init_fifo: can't create %s: file exists\n", path);
978 /* if we got this far, there was an error; cleanup */
985 control_stdin(GIOChannel *gio, GIOCondition condition) {
986 gchar *ctl_line = NULL;
987 gsize ctl_line_len = 0;
991 if (condition & G_IO_HUP) {
992 ret = g_io_channel_shutdown (gio, FALSE, &err);
996 ret = g_io_channel_read_line(gio, &ctl_line, &ctl_line_len, NULL, &err);
997 if ( (ret == G_IO_STATUS_ERROR) || (ret == G_IO_STATUS_EOF) )
1000 parse_cmd_line(ctl_line);
1008 GIOChannel *chan = NULL;
1009 GError *error = NULL;
1011 chan = g_io_channel_unix_new(fileno(stdin));
1013 if (!g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_stdin, NULL)) {
1014 g_error ("Stdin: could not add watch\n");
1016 printf ("Stdin: watch added successfully\n");
1019 g_error ("Stdin: Error while opening: %s\n", error->message);
1024 control_socket(GIOChannel *chan) {
1025 struct sockaddr_un remote;
1026 char buffer[512], *ctl_line;
1028 int sock, clientsock, n, done;
1031 sock = g_io_channel_unix_get_fd(chan);
1033 memset (buffer, 0, sizeof (buffer));
1035 t = sizeof (remote);
1036 clientsock = accept (sock, (struct sockaddr *) &remote, &t);
1040 memset (temp, 0, sizeof (temp));
1041 n = recv (clientsock, temp, 128, 0);
1043 buffer[strlen (buffer)] = '\0';
1047 strcat (buffer, temp);
1050 if (strcmp (buffer, "\n") < 0) {
1051 buffer[strlen (buffer) - 1] = '\0';
1053 buffer[strlen (buffer)] = '\0';
1056 ctl_line = g_strdup(buffer);
1057 parse_cmd_line (ctl_line);
1060 TODO: we should be able to do it with this. but glib errors out with "Invalid argument"
1061 GError *error = NULL;
1064 ret = g_io_channel_read_line(chan, &ctl_line, &len, NULL, &error);
1065 if (ret == G_IO_STATUS_ERROR)
1066 g_error ("Error reading: %s\n", error->message);
1068 printf("Got line %s (%u bytes) \n",ctl_line, len);
1070 parse_line(ctl_line);
1078 init_socket(gchar *dir) { /* return dir or, on error, free dir and return NULL */
1079 if (uzbl.comm.socket_path) { /* remove an existing socket should one exist */
1080 if (unlink(uzbl.comm.socket_path) == -1)
1081 g_warning ("init_socket: couldn't unlink socket at %s\n", uzbl.comm.socket_path);
1082 g_free(uzbl.comm.socket_path);
1083 uzbl.comm.socket_path = NULL;
1086 if (!strcmp(dir, " ")) {
1091 GIOChannel *chan = NULL;
1093 struct sockaddr_un local;
1094 gchar *path = build_stream_name(SOCKET, dir);
1096 sock = socket (AF_UNIX, SOCK_STREAM, 0);
1098 local.sun_family = AF_UNIX;
1099 strcpy (local.sun_path, path);
1100 unlink (local.sun_path);
1102 len = strlen (local.sun_path) + sizeof (local.sun_family);
1103 if (bind (sock, (struct sockaddr *) &local, len) != -1) {
1104 printf ("init_socket: opened in %s\n", path);
1107 if( (chan = g_io_channel_unix_new(sock)) ) {
1108 g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_socket, chan);
1109 uzbl.comm.socket_path = path;
1112 } else g_warning ("init_socket: could not open in %s: %s\n", path, strerror(errno));
1114 /* if we got this far, there was an error; cleanup */
1121 update_title (void) {
1122 GString* string_long = g_string_new ("");
1123 GString* string_short = g_string_new ("");
1127 State *s = &uzbl.state;
1128 Behaviour *b = &uzbl.behave;
1130 if(s->instance_name) {
1131 iname_len = strlen(s->instance_name)+4;
1132 iname = malloc(iname_len);
1133 snprintf(iname, iname_len, "<%s> ", s->instance_name);
1135 g_string_prepend(string_long, iname);
1136 g_string_prepend(string_short, iname);
1140 g_string_append_printf(string_long, "%s ", s->keycmd->str);
1141 if (!b->always_insert_mode)
1142 g_string_append (string_long, (b->insert_mode ? "[I] " : "[C] "));
1143 if (uzbl.gui.main_title) {
1144 g_string_append (string_long, uzbl.gui.main_title);
1145 g_string_append (string_short, uzbl.gui.main_title);
1147 g_string_append (string_long, " - Uzbl browser");
1148 g_string_append (string_short, " - Uzbl browser");
1149 if (s->selected_url[0]!=0) {
1150 g_string_append_printf (string_long, " -> (%s)", s->selected_url);
1153 gchar* title_long = g_string_free (string_long, FALSE);
1154 gchar* title_short = g_string_free (string_short, FALSE);
1156 if (b->show_status) {
1157 gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), title_short);
1158 // TODO: we should probably not do this every time we want to update the title..?
1159 statln = parse_status_template(uzbl.behave.status_format);
1160 gtk_label_set_markup(GTK_LABEL(uzbl.gui.mainbar_label), statln);
1161 if (b->status_background) {
1163 gdk_color_parse (b->status_background, &color);
1164 //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)
1165 gtk_widget_modify_bg (uzbl.gui.main_window, GTK_STATE_NORMAL, &color);
1169 gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), title_long);
1172 g_free (title_long);
1173 g_free (title_short);
1177 key_press_cb (WebKitWebView* page, GdkEventKey* event)
1179 //TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1184 if (event->type != GDK_KEY_PRESS || event->keyval == GDK_Page_Up || event->keyval == GDK_Page_Down
1185 || 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)
1188 /* turn off insert mode (if always_insert_mode is not used) */
1189 if (uzbl.behave.insert_mode && (event->keyval == GDK_Escape)) {
1190 uzbl.behave.insert_mode = uzbl.behave.always_insert_mode;
1195 if (uzbl.behave.insert_mode && (((event->state & uzbl.behave.modmask) != uzbl.behave.modmask) || (!uzbl.behave.modmask)))
1198 if (event->keyval == GDK_Escape) {
1199 g_string_truncate(uzbl.state.keycmd, 0);
1204 //Insert without shift - insert from clipboard; Insert with shift - insert from primary
1205 if (event->keyval == GDK_Insert) {
1207 if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) {
1208 str = gtk_clipboard_wait_for_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY));
1210 str = gtk_clipboard_wait_for_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD));
1213 g_string_append_printf (uzbl.state.keycmd, "%s", str);
1220 if ((event->keyval == GDK_BackSpace) && (uzbl.state.keycmd->len > 0)) {
1221 g_string_truncate(uzbl.state.keycmd, uzbl.state.keycmd->len - 1);
1225 gboolean key_ret = FALSE;
1226 if ((event->keyval == GDK_Return) || (event->keyval == GDK_KP_Enter))
1229 if (!key_ret) g_string_append(uzbl.state.keycmd, event->string);
1230 if ((action = g_hash_table_lookup(uzbl.bindings, uzbl.state.keycmd->str))) {
1231 g_string_truncate(uzbl.state.keycmd, 0);
1232 parse_command(action->name, action->param);
1235 GString* short_keys = g_string_new ("");
1236 GString* short_keys_inc = g_string_new ("");
1238 for (i=0; i<(uzbl.state.keycmd->len); i++) {
1239 g_string_append_c(short_keys, uzbl.state.keycmd->str[i]);
1240 g_string_assign(short_keys_inc, short_keys->str);
1241 g_string_append_c(short_keys, '_');
1242 g_string_append_c(short_keys_inc, '*');
1244 gboolean exec_now = FALSE;
1245 if ((action = g_hash_table_lookup(uzbl.bindings, short_keys->str))) {
1246 if (key_ret) exec_now = TRUE; // run normal cmds only if return was pressed
1247 } else if ((action = g_hash_table_lookup(uzbl.bindings, short_keys_inc->str))) {
1248 if (key_ret) { // just quit the incremental command on return
1249 g_string_truncate(uzbl.state.keycmd, 0);
1251 } else exec_now = TRUE; // always exec inc. commands on keys other than return
1255 GString* parampart = g_string_new (uzbl.state.keycmd->str);
1256 GString* actionname = g_string_new ("");
1257 GString* actionparam = g_string_new ("");
1258 g_string_erase (parampart, 0, i+1);
1260 g_string_printf (actionname, action->name, parampart->str);
1262 g_string_printf (actionparam, action->param, parampart->str);
1263 parse_command(actionname->str, actionparam->str);
1264 g_string_free (actionname, TRUE);
1265 g_string_free (actionparam, TRUE);
1266 g_string_free (parampart, TRUE);
1268 g_string_truncate(uzbl.state.keycmd, 0);
1272 g_string_truncate(short_keys, short_keys->len - 1);
1274 g_string_free (short_keys, TRUE);
1275 g_string_free (short_keys_inc, TRUE);
1277 if (key_ret) return (!uzbl.behave.insert_mode);
1285 GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL);
1286 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
1288 g->web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ());
1289 gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (g->web_view));
1291 g_signal_connect (G_OBJECT (g->web_view), "title-changed", G_CALLBACK (title_change_cb), g->web_view);
1292 g_signal_connect (G_OBJECT (g->web_view), "load-progress-changed", G_CALLBACK (progress_change_cb), g->web_view);
1293 g_signal_connect (G_OBJECT (g->web_view), "load-committed", G_CALLBACK (load_commit_cb), g->web_view);
1294 g_signal_connect (G_OBJECT (g->web_view), "load-committed", G_CALLBACK (log_history_cb), g->web_view);
1295 g_signal_connect (G_OBJECT (g->web_view), "load-finished", G_CALLBACK (load_finish_cb), g->web_view);
1296 g_signal_connect (G_OBJECT (g->web_view), "hovering-over-link", G_CALLBACK (link_hover_cb), g->web_view);
1297 g_signal_connect (G_OBJECT (g->web_view), "key-press-event", G_CALLBACK (key_press_cb), g->web_view);
1298 g_signal_connect (G_OBJECT (g->web_view), "new-window-policy-decision-requested", G_CALLBACK (new_window_cb), g->web_view);
1299 g_signal_connect (G_OBJECT (g->web_view), "download-requested", G_CALLBACK (download_cb), g->web_view);
1300 g_signal_connect (G_OBJECT (g->web_view), "create-web-view", G_CALLBACK (create_web_view_cb), g->web_view);
1302 return scrolled_window;
1309 g->mainbar = gtk_hbox_new (FALSE, 0);
1310 g->mainbar_label = gtk_label_new ("");
1311 gtk_label_set_selectable((GtkLabel *)g->mainbar_label, TRUE);
1312 gtk_label_set_ellipsize(GTK_LABEL(g->mainbar_label), PANGO_ELLIPSIZE_END);
1313 gtk_misc_set_alignment (GTK_MISC(g->mainbar_label), 0, 0);
1314 gtk_misc_set_padding (GTK_MISC(g->mainbar_label), 2, 2);
1315 gtk_box_pack_start (GTK_BOX (g->mainbar), g->mainbar_label, TRUE, TRUE, 0);
1320 GtkWidget* create_window () {
1321 GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1322 gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
1323 gtk_widget_set_name (window, "Uzbl browser");
1324 g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy_cb), NULL);
1330 add_binding (const gchar *key, const gchar *act) {
1331 char **parts = g_strsplit(act, " ", 2);
1338 printf ("Binding %-10s : %s\n", key, act);
1339 action = new_action(parts[0], parts[1]);
1341 if(g_hash_table_lookup(uzbl.bindings, key))
1342 g_hash_table_remove(uzbl.bindings, key);
1343 g_hash_table_insert(uzbl.bindings, g_strdup(key), action);
1350 GKeyFile* config = NULL;
1351 gboolean res = FALSE;
1353 State *s = &uzbl.state;
1354 Network *n = &uzbl.net;
1355 Behaviour *b = &uzbl.behave;
1357 if (!s->config_file) {
1358 const char* XDG_CONFIG_HOME = getenv ("XDG_CONFIG_HOME");
1359 if (! XDG_CONFIG_HOME || ! strcmp (XDG_CONFIG_HOME, "")) {
1360 XDG_CONFIG_HOME = (char*)XDG_CONFIG_HOME_default;
1362 printf("XDG_CONFIG_HOME: %s\n", XDG_CONFIG_HOME);
1364 strcpy (s->config_file_path, XDG_CONFIG_HOME);
1365 strcat (s->config_file_path, "/uzbl/config");
1366 if (file_exists (s->config_file_path)) {
1367 printf ("Config file %s found.\n", s->config_file_path);
1368 s->config_file = &s->config_file_path[0];
1370 // Now we check $XDG_CONFIG_DIRS
1371 char *XDG_CONFIG_DIRS = getenv ("XDG_CONFIG_DIRS");
1372 if (! XDG_CONFIG_DIRS || ! strcmp (XDG_CONFIG_DIRS, ""))
1373 XDG_CONFIG_DIRS = XDG_CONFIG_DIRS_default;
1375 printf("XDG_CONFIG_DIRS: %s\n", XDG_CONFIG_DIRS);
1378 strcpy (buffer, XDG_CONFIG_DIRS);
1379 const gchar* dir = (char *) strtok_r (buffer, ":", &saveptr);
1380 while (dir && ! file_exists (s->config_file_path)) {
1381 strcpy (s->config_file_path, dir);
1382 strcat (s->config_file_path, "/uzbl/config_file_pathig");
1383 if (file_exists (s->config_file_path)) {
1384 printf ("Config file %s found.\n", s->config_file_path);
1385 s->config_file = &s->config_file_path[0];
1387 dir = (char * ) strtok_r (NULL, ":", &saveptr);
1392 if (s->config_file) {
1393 config = g_key_file_new ();
1394 res = g_key_file_load_from_file (config, s->config_file, G_KEY_FILE_NONE, NULL);
1396 printf ("Config %s loaded\n", s->config_file);
1398 fprintf (stderr, "Config %s loading failed\n", s->config_file);
1401 printf ("No configuration.\n");
1405 b->status_top = g_key_file_get_boolean (config, "behavior", "status_top", NULL);
1406 b->reset_command_mode = g_key_file_get_boolean (config, "behavior", "reset_command_mode", NULL);
1409 printf ("Reset mode: %s\n" , (b->reset_command_mode ? "TRUE" : "FALSE"));
1411 /* networking options */
1413 n->useragent = g_key_file_get_value (config, "network", "user-agent", NULL);
1417 char* newagent = malloc(1024);
1419 strcpy(newagent, str_replace("%webkit-major%", itos(WEBKIT_MAJOR_VERSION), n->useragent));
1420 strcpy(newagent, str_replace("%webkit-minor%", itos(WEBKIT_MINOR_VERSION), newagent));
1421 strcpy(newagent, str_replace("%webkit-micro%", itos(WEBKIT_MICRO_VERSION), newagent));
1423 if (uname (&s->unameinfo) == -1) {
1424 printf("Error getting uname info. Not replacing system-related user agent variables.\n");
1426 strcpy(newagent, str_replace("%sysname%", s->unameinfo.sysname, newagent));
1427 strcpy(newagent, str_replace("%nodename%", s->unameinfo.nodename, newagent));
1428 strcpy(newagent, str_replace("%kernrel%", s->unameinfo.release, newagent));
1429 strcpy(newagent, str_replace("%kernver%", s->unameinfo.version, newagent));
1430 strcpy(newagent, str_replace("%arch-system%", s->unameinfo.machine, newagent));
1433 strcpy(newagent, str_replace("%domainname%", s->unameinfo.domainname, newagent));
1437 strcpy(newagent, str_replace("%arch-uzbl%", ARCH, newagent));
1438 strcpy(newagent, str_replace("%commit%", COMMIT, newagent));
1440 n->useragent = malloc(1024);
1441 strcpy(n->useragent, newagent);
1442 g_object_set(G_OBJECT(n->soup_session), SOUP_SESSION_USER_AGENT, n->useragent, NULL);
1445 printf("User-agent: %s\n", n->useragent? n->useragent : "default");
1447 g_signal_connect(n->soup_session, "request-queued", G_CALLBACK(handle_cookies), NULL);
1450 static void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data){
1453 if (!uzbl.behave.cookie_handler) return;
1455 gchar * stdout = NULL;
1456 soup_message_add_header_handler(msg, "got-headers", "Set-Cookie", G_CALLBACK(save_cookies), NULL);
1457 GString* args = g_string_new ("");
1458 SoupURI * soup_uri = soup_message_get_uri(msg);
1459 g_string_printf (args, "GET %s %s", soup_uri->host, soup_uri->path);
1460 run_command_sync(uzbl.behave.cookie_handler, args->str, &stdout);
1462 soup_message_headers_replace (msg->request_headers, "Cookie", stdout);
1464 g_string_free(args, TRUE);
1468 save_cookies (SoupMessage *msg, gpointer user_data){
1472 for (ck = soup_cookies_from_response(msg); ck; ck = ck->next){
1473 cookie = soup_cookie_to_set_cookie_header(ck->data);
1474 GString* args = g_string_new ("");
1475 SoupURI * soup_uri = soup_message_get_uri(msg);
1476 g_string_printf (args, "PUT %s %s \"%s\"", soup_uri->host, soup_uri->path, cookie);
1477 run_command_async(uzbl.behave.cookie_handler, args->str);
1478 g_string_free(args, TRUE);
1485 main (int argc, char* argv[]) {
1486 gtk_init (&argc, &argv);
1487 if (!g_thread_supported ())
1488 g_thread_init (NULL);
1490 printf("Uzbl start location: %s\n", argv[0]);
1491 strcpy(uzbl.state.executable_path,argv[0]);
1493 strcat ((char *) XDG_CONFIG_HOME_default, getenv ("HOME"));
1494 strcat ((char *) XDG_CONFIG_HOME_default, "/.config");
1496 GError *error = NULL;
1497 GOptionContext* context = g_option_context_new ("- some stuff here maybe someday");
1498 g_option_context_add_main_entries (context, entries, NULL);
1499 g_option_context_add_group (context, gtk_get_option_group (TRUE));
1500 g_option_context_parse (context, &argc, &argv, &error);
1501 /* initialize hash table */
1502 uzbl.bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_action);
1504 uzbl.net.soup_session = webkit_get_default_session();
1505 uzbl.state.keycmd = g_string_new("");
1511 GtkWidget* vbox = gtk_vbox_new (FALSE, 0);
1512 if (uzbl.behave.status_top)
1513 gtk_box_pack_start (GTK_BOX (vbox), create_mainbar (), FALSE, TRUE, 0);
1514 gtk_box_pack_start (GTK_BOX (vbox), create_browser (), TRUE, TRUE, 0);
1515 if (!uzbl.behave.status_top)
1516 gtk_box_pack_start (GTK_BOX (vbox), create_mainbar (), FALSE, TRUE, 0);
1518 uzbl.gui.main_window = create_window ();
1519 gtk_container_add (GTK_CONTAINER (uzbl.gui.main_window), vbox);
1521 load_uri (uzbl.gui.web_view, uzbl.state.uri);
1523 gtk_widget_grab_focus (GTK_WIDGET (uzbl.gui.web_view));
1524 gtk_widget_show_all (uzbl.gui.main_window);
1525 uzbl.xwin = GDK_WINDOW_XID (GTK_WIDGET (uzbl.gui.main_window)->window);
1526 printf("window_id %i\n",(int) uzbl.xwin);
1527 printf("pid %i\n", getpid ());
1528 printf("name: %s\n", uzbl.state.instance_name);
1530 uzbl.gui.scbar_v = (GtkScrollbar*) gtk_vscrollbar_new (NULL);
1531 uzbl.gui.bar_v = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_v);
1532 uzbl.gui.scbar_h = (GtkScrollbar*) gtk_hscrollbar_new (NULL);
1533 uzbl.gui.bar_h = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_h);
1534 gtk_widget_set_scroll_adjustments ((GtkWidget*) uzbl.gui.web_view, uzbl.gui.bar_h, uzbl.gui.bar_v);
1537 if(setup_signal(SIGTERM, catch_sigterm) == SIG_ERR)
1538 fprintf(stderr, "uzbl: error hooking SIGTERM\n");
1544 if (!uzbl.behave.status_format)
1545 uzbl.behave.status_format = g_strdup(STATUS_DEFAULT);
1546 if (!uzbl.behave.show_status)
1547 gtk_widget_hide(uzbl.gui.mainbar);
1552 make_var_to_name_hash();
1554 /*if (uzbl.behave.fifo_dir)
1556 /*if (uzbl.behave.socket_dir)
1562 return EXIT_SUCCESS;
1565 /* vi: set et ts=4: */