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 { "proxy_url", (void *)&uzbl
.net
.proxy_url
},
74 // TODO: write cmd handlers for the following
75 { "useragent", (void *)&uzbl
.net
.useragent
},
76 { "max_conns", (void *)&uzbl
.net
.max_conns
},
77 { "max_conns_host", (void *)&uzbl
.net
.max_conns_host
},
78 { "http_debug", (void *)&uzbl
.behave
.http_debug
},
80 }, *n2v_p
= var_name_to_ptr
;
82 /* construct a hash from the var_name_to_ptr array for quick access */
84 make_var_to_name_hash() {
85 uzbl
.comm
.proto_var
= g_hash_table_new(g_str_hash
, g_str_equal
);
87 g_hash_table_insert(uzbl
.comm
.proto_var
, n2v_p
->name
, n2v_p
->ptr
);
92 /* commandline arguments (set initial values for the state variables) */
93 static GOptionEntry entries
[] =
95 { "uri", 'u', 0, G_OPTION_ARG_STRING
, &uzbl
.state
.uri
, "Uri to load", "URI" },
96 { "name", 'n', 0, G_OPTION_ARG_STRING
, &uzbl
.state
.instance_name
, "Name of the current instance", "NAME" },
97 { "config", 'c', 0, G_OPTION_ARG_STRING
, &uzbl
.state
.config_file
, "Config file", "FILE" },
98 { NULL
, 0, 0, 0, NULL
, NULL
, NULL
}
101 typedef void (*Command
)(WebKitWebView
*, const char *);
104 static char *XDG_CONFIG_HOME_default
[256];
105 static char *XDG_CONFIG_DIRS_default
= "/etc/xdg";
108 /* --- UTILITY FUNCTIONS --- */
114 snprintf(tmp
, sizeof(tmp
), "%i", val
);
115 return g_strdup(tmp
);
119 str_replace (const char* search
, const char* replace
, const char* string
) {
120 return g_strjoinv (replace
, g_strsplit(string
, search
, -1));
124 setup_signal(int signr
, sigfunc
*shandler
) {
125 struct sigaction nh
, oh
;
127 nh
.sa_handler
= shandler
;
128 sigemptyset(&nh
.sa_mask
);
131 if(sigaction(signr
, &nh
, &oh
) < 0)
139 if (uzbl
.behave
.fifo_dir
)
140 unlink (uzbl
.comm
.fifo_path
);
141 if (uzbl
.behave
.socket_dir
)
142 unlink (uzbl
.comm
.socket_path
);
144 g_string_free(uzbl
.state
.keycmd
, TRUE
);
145 g_hash_table_destroy(uzbl
.bindings
);
146 g_hash_table_destroy(uzbl
.behave
.commands
);
150 /* --- SIGNAL HANDLER --- */
153 catch_sigterm(int s
) {
158 /* --- CALLBACKS --- */
161 new_window_cb (WebKitWebView
*web_view
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
, WebKitWebNavigationAction
*navigation_action
, WebKitWebPolicyDecision
*policy_decision
, gpointer user_data
) {
164 (void) navigation_action
;
165 (void) policy_decision
;
167 const gchar
* uri
= webkit_network_request_get_uri (request
);
168 printf("New window requested -> %s \n", uri
);
169 new_window_load_uri(uri
);
174 create_web_view_cb (WebKitWebView
*web_view
, WebKitWebFrame
*frame
, gpointer user_data
) {
178 if (uzbl
.state
.selected_url
[0]!=0) {
179 printf("\nNew web view -> %s\n",uzbl
.state
.selected_url
);
180 new_window_load_uri(uzbl
.state
.selected_url
);
182 printf("New web view -> %s\n","Nothing to open, exiting");
188 download_cb (WebKitWebView
*web_view
, GObject
*download
, gpointer user_data
) {
191 if (uzbl
.behave
.download_handler
) {
192 const gchar
* uri
= webkit_download_get_uri ((WebKitDownload
*)download
);
193 printf("Download -> %s\n",uri
);
194 run_command_async(uzbl
.behave
.download_handler
, uri
);
199 /* scroll a bar in a given direction */
201 scroll (GtkAdjustment
* bar
, const char *param
) {
205 amount
= g_ascii_strtod(param
, &end
);
208 fprintf(stderr
, "found something after double: %s\n", end
);
210 gtk_adjustment_set_value (bar
, gtk_adjustment_get_value(bar
)+amount
);
213 static void scroll_vert(WebKitWebView
* page
, const char *param
) {
216 scroll(uzbl
.gui
.bar_v
, param
);
219 static void scroll_horz(WebKitWebView
* page
, const char *param
) {
222 scroll(uzbl
.gui
.bar_h
, param
);
227 if (!uzbl
.behave
.show_status
) {
228 gtk_widget_hide(uzbl
.gui
.mainbar
);
230 gtk_widget_show(uzbl
.gui
.mainbar
);
236 toggle_status_cb (WebKitWebView
* page
, const char *param
) {
240 if (uzbl
.behave
.show_status
) {
241 gtk_widget_hide(uzbl
.gui
.mainbar
);
243 gtk_widget_show(uzbl
.gui
.mainbar
);
245 uzbl
.behave
.show_status
= !uzbl
.behave
.show_status
;
250 link_hover_cb (WebKitWebView
* page
, const gchar
* title
, const gchar
* link
, gpointer data
) {
254 //ADD HOVER URL TO WINDOW TITLE
255 uzbl
.state
.selected_url
[0] = '\0';
257 strcpy (uzbl
.state
.selected_url
, link
);
263 title_change_cb (WebKitWebView
* web_view
, WebKitWebFrame
* web_frame
, const gchar
* title
, gpointer data
) {
267 if (uzbl
.gui
.main_title
)
268 g_free (uzbl
.gui
.main_title
);
269 uzbl
.gui
.main_title
= g_strdup (title
);
274 progress_change_cb (WebKitWebView
* page
, gint progress
, gpointer data
) {
277 uzbl
.gui
.sbar
.load_progress
= progress
;
282 load_commit_cb (WebKitWebView
* page
, WebKitWebFrame
* frame
, gpointer data
) {
285 free (uzbl
.state
.uri
);
286 GString
* newuri
= g_string_new (webkit_web_frame_get_uri (frame
));
287 uzbl
.state
.uri
= g_string_free (newuri
, FALSE
);
291 destroy_cb (GtkWidget
* widget
, gpointer data
) {
299 if (uzbl
.behave
.history_handler
) {
301 struct tm
* timeinfo
;
304 timeinfo
= localtime ( &rawtime
);
305 strftime (date
, 80, "%Y-%m-%d %H:%M:%S", timeinfo
);
306 GString
* args
= g_string_new ("");
307 g_string_printf (args
, "'%s'", date
);
308 run_command_async(uzbl
.behave
.history_handler
, args
->str
);
309 g_string_free (args
, TRUE
);
314 /* VIEW funcs (little webkit wrappers) */
315 #define VIEWFUNC(name) static void view_##name(WebKitWebView *page, const char *param){(void)param; webkit_web_view_##name(page);}
317 VIEWFUNC(reload_bypass_cache
)
318 VIEWFUNC(stop_loading
)
325 /* -- command to callback/function map for things we cannot attach to any signals */
328 static struct {char *name
; Command command
;} cmdlist
[] =
330 { "back", view_go_back
},
331 { "forward", view_go_forward
},
332 { "scroll_vert", scroll_vert
},
333 { "scroll_horz", scroll_horz
},
334 { "reload", view_reload
, },
335 { "reload_ign_cache", view_reload_bypass_cache
},
336 { "stop", view_stop_loading
, },
337 { "zoom_in", view_zoom_in
, }, //Can crash (when max zoom reached?).
338 { "zoom_out", view_zoom_out
, },
340 { "script", run_js
},
341 { "toggle_status", toggle_status_cb
},
343 { "exit", close_uzbl
},
344 { "search", search_text
},
345 { "insert_mode", set_insert_mode
}
352 uzbl
.behave
.commands
= g_hash_table_new(g_str_hash
, g_str_equal
);
354 for (i
= 0; i
< LENGTH(cmdlist
); i
++)
355 g_hash_table_insert(uzbl
.behave
.commands
, cmdlist
[i
].name
, cmdlist
[i
].command
);
358 /* -- CORE FUNCTIONS -- */
361 free_action(gpointer act
) {
362 Action
*action
= (Action
*)act
;
363 g_free(action
->name
);
365 g_free(action
->param
);
370 new_action(const gchar
*name
, const gchar
*param
) {
371 Action
*action
= g_new(Action
, 1);
373 action
->name
= g_strdup(name
);
375 action
->param
= g_strdup(param
);
377 action
->param
= NULL
;
383 file_exists (const char * filename
) {
384 FILE *file
= fopen (filename
, "r");
393 set_insert_mode(WebKitWebView
*page
, const gchar
*param
) {
397 uzbl
.behave
.insert_mode
= TRUE
;
402 load_uri (WebKitWebView
* web_view
, const gchar
*param
) {
404 GString
* newuri
= g_string_new (param
);
405 if (g_strrstr (param
, "://") == NULL
)
406 g_string_prepend (newuri
, "http://");
407 /* if we do handle cookies, ask our handler for them */
408 webkit_web_view_load_uri (web_view
, newuri
->str
);
409 g_string_free (newuri
, TRUE
);
414 run_js (WebKitWebView
* web_view
, const gchar
*param
) {
416 webkit_web_view_execute_script (web_view
, param
);
420 search_text (WebKitWebView
*page
, const char *param
) {
421 if ((param
) && (param
[0] != '\0')) {
422 strcpy(uzbl
.state
.searchtx
, param
);
424 if (uzbl
.state
.searchtx
[0] != '\0') {
425 printf ("Searching: %s\n", uzbl
.state
.searchtx
);
426 webkit_web_view_unmark_text_matches (page
);
427 webkit_web_view_mark_text_matches (page
, uzbl
.state
.searchtx
, FALSE
, 0);
428 webkit_web_view_set_highlight_text_matches (page
, TRUE
);
429 webkit_web_view_search_text (page
, uzbl
.state
.searchtx
, FALSE
, TRUE
, TRUE
);
434 new_window_load_uri (const gchar
* uri
) {
435 GString
* to_execute
= g_string_new ("");
436 g_string_append_printf (to_execute
, "%s --uri '%s'", uzbl
.state
.executable_path
, uri
);
438 for (i
= 0; entries
[i
].long_name
!= NULL
; i
++) {
439 if ((entries
[i
].arg
== G_OPTION_ARG_STRING
) && (strcmp(entries
[i
].long_name
,"uri")!=0)) {
440 gchar
** str
= (gchar
**)entries
[i
].arg_data
;
442 g_string_append_printf (to_execute
, " --%s '%s'", entries
[i
].long_name
, *str
);
446 printf("\n%s\n", to_execute
->str
);
447 g_spawn_command_line_async (to_execute
->str
, NULL
);
448 g_string_free (to_execute
, TRUE
);
452 close_uzbl (WebKitWebView
*page
, const char *param
) {
458 /* --Statusbar functions-- */
460 build_progressbar_ascii(int percent
) {
464 GString
*bar
= g_string_new("");
466 l
= (double)percent
*((double)width
/100.);
467 l
= (int)(l
+.5)>=(int)l
? l
+.5 : l
;
469 g_string_append(bar
, "[");
470 for(i
=0; i
<(int)l
; i
++)
471 g_string_append(bar
, "=");
474 g_string_append(bar
, "·");
475 g_string_append(bar
, "]");
477 return g_string_free(bar
, FALSE
);
482 const GScannerConfig scan_config
= {
485 ) /* cset_skip_characters */,
490 ) /* cset_identifier_first */,
497 ) /* cset_identifier_nth */,
498 ( "" ) /* cpair_comment_single */,
500 TRUE
/* case_sensitive */,
502 FALSE
/* skip_comment_multi */,
503 FALSE
/* skip_comment_single */,
504 FALSE
/* scan_comment_multi */,
505 TRUE
/* scan_identifier */,
506 TRUE
/* scan_identifier_1char */,
507 FALSE
/* scan_identifier_NULL */,
508 TRUE
/* scan_symbols */,
509 FALSE
/* scan_binary */,
510 FALSE
/* scan_octal */,
511 FALSE
/* scan_float */,
512 FALSE
/* scan_hex */,
513 FALSE
/* scan_hex_dollar */,
514 FALSE
/* scan_string_sq */,
515 FALSE
/* scan_string_dq */,
516 TRUE
/* numbers_2_int */,
517 FALSE
/* int_2_float */,
518 FALSE
/* identifier_2_string */,
519 FALSE
/* char_2_token */,
520 FALSE
/* symbol_2_token */,
521 TRUE
/* scope_0_fallback */,
526 uzbl
.scan
= g_scanner_new(&scan_config
);
527 while(symp
->symbol_name
) {
528 g_scanner_scope_add_symbol(uzbl
.scan
, 0,
530 GINT_TO_POINTER(symp
->symbol_token
));
536 parse_status_template(const char *template) {
537 GTokenType token
= G_TOKEN_NONE
;
538 GString
*ret
= g_string_new("");
545 g_scanner_input_text(uzbl
.scan
, template, strlen(template));
546 while(!g_scanner_eof(uzbl
.scan
) && token
!= G_TOKEN_LAST
) {
547 token
= g_scanner_get_next_token(uzbl
.scan
);
549 if(token
== G_TOKEN_SYMBOL
) {
550 sym
= (int)g_scanner_cur_value(uzbl
.scan
).v_symbol
;
555 g_markup_printf_escaped("%s", uzbl
.state
.uri
):"");
558 g_string_append(ret
, itos(uzbl
.gui
.sbar
.load_progress
));
560 case SYM_LOADPRGSBAR
:
561 buf
= build_progressbar_ascii(uzbl
.gui
.sbar
.load_progress
);
562 g_string_append(ret
, buf
);
568 g_markup_printf_escaped("%s", uzbl
.gui
.main_title
):"");
572 uzbl
.state
.instance_name
?uzbl
.state
.instance_name
:itos(uzbl
.xwin
));
576 uzbl
.state
.keycmd
->str
?
577 g_markup_printf_escaped("%s", uzbl
.state
.keycmd
->str
):"");
581 uzbl
.behave
.insert_mode
?"[I]":"[C]");
585 uzbl
.gui
.sbar
.msg
?uzbl
.gui
.sbar
.msg
:"");
591 else if(token
== G_TOKEN_INT
) {
592 g_string_append(ret
, itos(g_scanner_cur_value(uzbl
.scan
).v_int
));
594 else if(token
== G_TOKEN_IDENTIFIER
) {
595 g_string_append(ret
, (gchar
*)g_scanner_cur_value(uzbl
.scan
).v_identifier
);
597 else if(token
== G_TOKEN_CHAR
) {
598 g_string_append_c(ret
, (gchar
)g_scanner_cur_value(uzbl
.scan
).v_char
);
602 return g_string_free(ret
, FALSE
);
604 /* --End Statusbar functions-- */
607 // make sure to put '' around args, so that if there is whitespace we can still keep arguments together.
609 run_command_async(const char *command
, const char *args
) {
610 //command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl fifo file> <uzbl socket file> [args]
611 GString
* to_execute
= g_string_new ("");
613 g_string_printf (to_execute
, "%s '%s' '%i' '%i' '%s' '%s'",
614 command
, uzbl
.state
.config_file
, (int) getpid() ,
615 (int) uzbl
.xwin
, uzbl
.comm
.fifo_path
, uzbl
.comm
.socket_path
);
616 g_string_append_printf (to_execute
, " '%s' '%s'",
617 uzbl
.state
.uri
, "TODO title here");
619 g_string_append_printf (to_execute
, " %s", args
);
621 result
= g_spawn_command_line_async (to_execute
->str
, NULL
);
622 printf("Called %s. Result: %s\n", to_execute
->str
, (result
? "TRUE" : "FALSE" ));
623 g_string_free (to_execute
, TRUE
);
628 run_command_sync(const char *command
, const char *args
, char **stdout
) {
629 //command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl fifo file> <uzbl socket file> [args]
630 GString
* to_execute
= g_string_new ("");
632 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
);
633 g_string_append_printf (to_execute
, " '%s' '%s'", uzbl
.state
.uri
, "TODO title here");
635 g_string_append_printf (to_execute
, " %s", args
);
637 result
= g_spawn_command_line_sync (to_execute
->str
, stdout
, NULL
, NULL
, NULL
);
638 printf("Called %s. Result: %s\n", to_execute
->str
, (result
? "TRUE" : "FALSE" ));
639 g_string_free (to_execute
, TRUE
);
644 spawn(WebKitWebView
*web_view
, const char *param
) {
646 run_command_async(param
, NULL
);
650 parse_command(const char *cmd
, const char *param
) {
653 if ((c
= g_hash_table_lookup(uzbl
.behave
.commands
, cmd
)))
654 c(uzbl
.gui
.web_view
, param
);
656 fprintf (stderr
, "command \"%s\" not understood. ignoring.\n", cmd
);
664 uzbl
.comm
.get_regex
= g_regex_new("^[Gg][a-zA-Z]*\\s+([^ \\n]+)$",
665 G_REGEX_OPTIMIZE
, 0, &err
);
666 uzbl
.comm
.set_regex
= g_regex_new("^[Ss][a-zA-Z]*\\s+([^ ]+)\\s*=\\s*([^\\n].*)$",
667 G_REGEX_OPTIMIZE
, 0, &err
);
668 uzbl
.comm
.bind_regex
= g_regex_new("^[Bb][a-zA-Z]*\\s+?(.*[^ ])\\s*?=\\s*([a-z][^\\n].+)$",
669 G_REGEX_UNGREEDY
|G_REGEX_OPTIMIZE
, 0, &err
);
673 get_var_value(gchar
*name
) {
676 if( (p
= g_hash_table_lookup(uzbl
.comm
.proto_var
, name
)) ) {
677 if(!strcmp(name
, "status_format")) {
678 printf("VAR: %s VALUE: %s\n", name
, (char *)*p
);
680 printf("VAR: %s VALUE: %d\n", name
, (int)*p
);
690 if(*uzbl
.net
.proxy_url
== ' '
691 || uzbl
.net
.proxy_url
== NULL
) {
692 soup_session_remove_feature_by_type(uzbl
.net
.soup_session
,
693 (GType
) SOUP_SESSION_PROXY_URI
);
696 suri
= soup_uri_new(uzbl
.net
.proxy_url
);
697 g_object_set(G_OBJECT(uzbl
.net
.soup_session
),
698 SOUP_SESSION_PROXY_URI
,
706 var_is(const char *x
, const char *y
) {
707 gboolean ret
= FALSE
;
716 set_var_value(gchar
*name
, gchar
*val
) {
720 if( (p
= g_hash_table_lookup(uzbl
.comm
.proto_var
, name
)) ) {
721 if(var_is("status_message", name
)
722 || var_is("status_background", name
)
723 || var_is("status_format", name
)) {
729 else if(var_is("uri", name
)) {
733 load_uri(uzbl
.gui
.web_view
, (const gchar
*)*p
);
735 else if(var_is("proxy_url", name
)) {
741 /* variables that take int values */
743 *p
= (int)strtoul(val
, &endp
, 10);
745 if(var_is("show_status", name
)) {
755 parse_cmd_line(char *ctl_line
) {
759 if(ctl_line
[0] == 's' || ctl_line
[0] == 'S') {
760 tokens
= g_regex_split(uzbl
.comm
.set_regex
, ctl_line
, 0);
761 if(tokens
[0][0] == 0) {
762 set_var_value(tokens
[1], tokens
[2]);
766 printf("Error in command: %s\n", tokens
[0]);
769 else if(ctl_line
[0] == 'g' || ctl_line
[0] == 'G') {
770 tokens
= g_regex_split(uzbl
.comm
.get_regex
, ctl_line
, 0);
771 if(tokens
[0][0] == 0) {
772 get_var_value(tokens
[1]);
776 printf("Error in command: %s\n", tokens
[0]);
779 else if(ctl_line
[0] == 'b' || ctl_line
[0] == 'B') {
780 tokens
= g_regex_split(uzbl
.comm
.bind_regex
, ctl_line
, 0);
781 if(tokens
[0][0] == 0) {
782 add_binding(tokens
[1], tokens
[2]);
786 printf("Error in command: %s\n", tokens
[0]);
789 else if( (ctl_line
[0] == '#')
790 || (ctl_line
[0] == ' ')
791 || (ctl_line
[0] == '\n'))
792 ; /* ignore these lines */
794 printf("Command not understood (%s)\n", ctl_line
);
801 build_stream_name(int type
) {
803 State
*s
= &uzbl
.state
;
804 Behaviour
*b
= &uzbl
.behave
;
806 xwin_str
= itos((int)uzbl
.xwin
);
810 sprintf (uzbl
.comm
.fifo_path
, "%s/uzbl_fifo_%s",
812 s
->instance_name
? s
->instance_name
: xwin_str
);
814 sprintf (uzbl
.comm
.fifo_path
, "/tmp/uzbl_fifo_%s",
815 s
->instance_name
? s
->instance_name
: xwin_str
);
821 sprintf (uzbl
.comm
.socket_path
, "%s/uzbl_socket_%s",
823 s
->instance_name
? s
->instance_name
: xwin_str
);
825 sprintf (uzbl
.comm
.socket_path
, "/tmp/uzbl_socket_%s",
826 s
->instance_name
? s
->instance_name
: xwin_str
);
836 control_fifo(GIOChannel
*gio
, GIOCondition condition
) {
837 printf("triggered\n");
842 if (condition
& G_IO_HUP
)
843 g_error ("Fifo: Read end of pipe died!\n");
846 g_error ("Fifo: GIOChannel broke\n");
848 ret
= g_io_channel_read_line(gio
, &ctl_line
, NULL
, NULL
, &err
);
849 if (ret
== G_IO_STATUS_ERROR
)
850 g_error ("Fifo: Error reading: %s\n", err
->message
);
852 parse_cmd_line(ctl_line
);
860 GIOChannel
*chan
= NULL
;
861 GError
*error
= NULL
;
863 build_stream_name(FIFO
);
864 if (file_exists(uzbl
.comm
.fifo_path
)) {
865 g_error ("Fifo: Error when creating %s: File exists\n", uzbl
.comm
.fifo_path
);
868 if (mkfifo (uzbl
.comm
.fifo_path
, 0666) == -1) {
869 g_error ("Fifo: Error when creating %s: %s\n", uzbl
.comm
.fifo_path
, strerror(errno
));
871 // 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.
872 chan
= g_io_channel_new_file((gchar
*) uzbl
.comm
.fifo_path
, "r+", &error
);
874 if (!g_io_add_watch(chan
, G_IO_IN
|G_IO_HUP
, (GIOFunc
) control_fifo
, NULL
)) {
875 g_error ("Fifo: could not add watch on %s\n", uzbl
.comm
.fifo_path
);
877 printf ("Fifo: created successfully as %s\n", uzbl
.comm
.fifo_path
);
880 g_error ("Fifo: Error while opening: %s\n", error
->message
);
888 control_stdin(GIOChannel
*gio
, GIOCondition condition
) {
889 gchar
*ctl_line
= NULL
;
890 gsize ctl_line_len
= 0;
894 if (condition
& G_IO_HUP
) {
895 ret
= g_io_channel_shutdown (gio
, FALSE
, &err
);
899 ret
= g_io_channel_read_line(gio
, &ctl_line
, &ctl_line_len
, NULL
, &err
);
900 if ( (ret
== G_IO_STATUS_ERROR
) || (ret
== G_IO_STATUS_EOF
) )
903 parse_cmd_line(ctl_line
);
911 GIOChannel
*chan
= NULL
;
912 GError
*error
= NULL
;
914 chan
= g_io_channel_unix_new(fileno(stdin
));
916 if (!g_io_add_watch(chan
, G_IO_IN
|G_IO_HUP
, (GIOFunc
) control_stdin
, NULL
)) {
917 g_error ("Stdin: could not add watch\n");
919 printf ("Stdin: watch added successfully\n");
922 g_error ("Stdin: Error while opening: %s\n", error
->message
);
927 control_socket(GIOChannel
*chan
) {
928 struct sockaddr_un remote
;
929 char buffer
[512], *ctl_line
;
931 int sock
, clientsock
, n
, done
;
934 sock
= g_io_channel_unix_get_fd(chan
);
936 memset (buffer
, 0, sizeof (buffer
));
939 clientsock
= accept (sock
, (struct sockaddr
*) &remote
, &t
);
943 memset (temp
, 0, sizeof (temp
));
944 n
= recv (clientsock
, temp
, 128, 0);
946 buffer
[strlen (buffer
)] = '\0';
950 strcat (buffer
, temp
);
953 if (strcmp (buffer
, "\n") < 0) {
954 buffer
[strlen (buffer
) - 1] = '\0';
956 buffer
[strlen (buffer
)] = '\0';
959 ctl_line
= g_strdup(buffer
);
960 parse_cmd_line (ctl_line
);
963 TODO: we should be able to do it with this. but glib errors out with "Invalid argument"
964 GError *error = NULL;
967 ret = g_io_channel_read_line(chan, &ctl_line, &len, NULL, &error);
968 if (ret == G_IO_STATUS_ERROR)
969 g_error ("Error reading: %s\n", error->message);
971 printf("Got line %s (%u bytes) \n",ctl_line, len);
973 parse_line(ctl_line);
982 GIOChannel
*chan
= NULL
;
984 struct sockaddr_un local
;
986 build_stream_name(SOCKET
);
987 sock
= socket (AF_UNIX
, SOCK_STREAM
, 0);
989 local
.sun_family
= AF_UNIX
;
990 strcpy (local
.sun_path
, uzbl
.comm
.socket_path
);
991 unlink (local
.sun_path
);
993 len
= strlen (local
.sun_path
) + sizeof (local
.sun_family
);
994 bind (sock
, (struct sockaddr
*) &local
, len
);
997 printf ("Socket: Could not open in %s: %s\n", uzbl
.comm
.socket_path
, strerror(errno
));
999 printf ("Socket: Opened in %s\n", uzbl
.comm
.socket_path
);
1002 if( (chan
= g_io_channel_unix_new(sock
)) )
1003 g_io_add_watch(chan
, G_IO_IN
|G_IO_HUP
, (GIOFunc
) control_socket
, chan
);
1008 update_title (void) {
1009 GString
* string_long
= g_string_new ("");
1010 GString
* string_short
= g_string_new ("");
1014 State
*s
= &uzbl
.state
;
1015 Behaviour
*b
= &uzbl
.behave
;
1017 if(s
->instance_name
) {
1018 iname_len
= strlen(s
->instance_name
)+4;
1019 iname
= malloc(iname_len
);
1020 snprintf(iname
, iname_len
, "<%s> ", s
->instance_name
);
1022 g_string_prepend(string_long
, iname
);
1023 g_string_prepend(string_short
, iname
);
1027 g_string_append_printf(string_long
, "%s ", s
->keycmd
->str
);
1028 if (!b
->always_insert_mode
)
1029 g_string_append (string_long
, (b
->insert_mode
? "[I] " : "[C] "));
1030 if (uzbl
.gui
.main_title
) {
1031 g_string_append (string_long
, uzbl
.gui
.main_title
);
1032 g_string_append (string_short
, uzbl
.gui
.main_title
);
1034 g_string_append (string_long
, " - Uzbl browser");
1035 g_string_append (string_short
, " - Uzbl browser");
1036 if (s
->selected_url
[0]!=0) {
1037 g_string_append_printf (string_long
, " -> (%s)", s
->selected_url
);
1040 gchar
* title_long
= g_string_free (string_long
, FALSE
);
1041 gchar
* title_short
= g_string_free (string_short
, FALSE
);
1043 if (b
->show_status
) {
1044 gtk_window_set_title (GTK_WINDOW(uzbl
.gui
.main_window
), title_short
);
1045 // TODO: we should probably not do this every time we want to update the title..?
1046 statln
= parse_status_template(uzbl
.behave
.status_format
);
1047 gtk_label_set_markup(GTK_LABEL(uzbl
.gui
.mainbar_label
), statln
);
1048 if (b
->status_background
) {
1050 gdk_color_parse (b
->status_background
, &color
);
1051 //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)
1052 gtk_widget_modify_bg (uzbl
.gui
.main_window
, GTK_STATE_NORMAL
, &color
);
1056 gtk_window_set_title (GTK_WINDOW(uzbl
.gui
.main_window
), title_long
);
1059 g_free (title_long
);
1060 g_free (title_short
);
1064 key_press_cb (WebKitWebView
* page
, GdkEventKey
* event
)
1066 //TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1071 if (event
->type
!= GDK_KEY_PRESS
|| event
->keyval
== GDK_Page_Up
|| event
->keyval
== GDK_Page_Down
1072 || event
->keyval
== GDK_Up
|| event
->keyval
== GDK_Down
|| event
->keyval
== GDK_Left
|| event
->keyval
== GDK_Right
)
1075 /* turn off insert mode (if always_insert_mode is not used) */
1076 if (uzbl
.behave
.insert_mode
&& (event
->keyval
== GDK_Escape
)) {
1077 uzbl
.behave
.insert_mode
= uzbl
.behave
.always_insert_mode
;
1082 if (uzbl
.behave
.insert_mode
&& ((event
->state
& uzbl
.behave
.modmask
) != uzbl
.behave
.modmask
))
1085 if (event
->keyval
== GDK_Escape
) {
1086 g_string_truncate(uzbl
.state
.keycmd
, 0);
1091 //Insert without shift - insert from clipboard; Insert with shift - insert from primary
1092 if (event
->keyval
== GDK_Insert
) {
1094 if ((event
->state
& GDK_SHIFT_MASK
) == GDK_SHIFT_MASK
) {
1095 str
= gtk_clipboard_wait_for_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY
));
1097 str
= gtk_clipboard_wait_for_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD
));
1100 g_string_append_printf (uzbl
.state
.keycmd
, "%s", str
);
1107 if ((event
->keyval
== GDK_BackSpace
) && (uzbl
.state
.keycmd
->len
> 0)) {
1108 g_string_truncate(uzbl
.state
.keycmd
, uzbl
.state
.keycmd
->len
- 1);
1113 if ((event
->keyval
== GDK_Return
) || (event
->keyval
== GDK_KP_Enter
)) {
1114 GString
* short_keys
= g_string_new ("");
1116 for (i
=0; i
<(uzbl
.state
.keycmd
->len
); i
++) {
1117 g_string_append_c(short_keys
, uzbl
.state
.keycmd
->str
[i
]);
1118 g_string_append_c(short_keys
, '_');
1120 //printf("\nTesting string: @%s@\n", short_keys->str);
1121 if ((action
= g_hash_table_lookup(uzbl
.bindings
, short_keys
->str
))) {
1122 GString
* parampart
= g_string_new (uzbl
.state
.keycmd
->str
);
1123 g_string_erase (parampart
, 0, i
+1);
1124 //printf("\nParameter: @%s@\n", parampart->str);
1125 GString
* actionname
= g_string_new ("");
1127 g_string_printf (actionname
, action
->name
, parampart
->str
);
1128 GString
* actionparam
= g_string_new ("");
1130 g_string_printf (actionparam
, action
->param
, parampart
->str
);
1131 parse_command(actionname
->str
, actionparam
->str
);
1132 g_string_free (actionname
, TRUE
);
1133 g_string_free (actionparam
, TRUE
);
1134 g_string_free (parampart
, TRUE
);
1135 g_string_truncate(uzbl
.state
.keycmd
, 0);
1139 g_string_truncate(short_keys
, short_keys
->len
- 1);
1141 g_string_free (short_keys
, TRUE
);
1142 return (!uzbl
.behave
.insert_mode
);
1145 g_string_append(uzbl
.state
.keycmd
, event
->string
);
1146 if ((action
= g_hash_table_lookup(uzbl
.bindings
, uzbl
.state
.keycmd
->str
))) {
1147 g_string_truncate(uzbl
.state
.keycmd
, 0);
1148 parse_command(action
->name
, action
->param
);
1160 GtkWidget
* scrolled_window
= gtk_scrolled_window_new (NULL
, NULL
);
1161 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
1163 g
->web_view
= WEBKIT_WEB_VIEW (webkit_web_view_new ());
1164 gtk_container_add (GTK_CONTAINER (scrolled_window
), GTK_WIDGET (g
->web_view
));
1166 g_signal_connect (G_OBJECT (g
->web_view
), "title-changed", G_CALLBACK (title_change_cb
), g
->web_view
);
1167 g_signal_connect (G_OBJECT (g
->web_view
), "load-progress-changed", G_CALLBACK (progress_change_cb
), g
->web_view
);
1168 g_signal_connect (G_OBJECT (g
->web_view
), "load-committed", G_CALLBACK (load_commit_cb
), g
->web_view
);
1169 g_signal_connect (G_OBJECT (g
->web_view
), "load-committed", G_CALLBACK (log_history_cb
), g
->web_view
);
1170 g_signal_connect (G_OBJECT (g
->web_view
), "hovering-over-link", G_CALLBACK (link_hover_cb
), g
->web_view
);
1171 g_signal_connect (G_OBJECT (g
->web_view
), "key-press-event", G_CALLBACK (key_press_cb
), g
->web_view
);
1172 g_signal_connect (G_OBJECT (g
->web_view
), "new-window-policy-decision-requested", G_CALLBACK (new_window_cb
), g
->web_view
);
1173 g_signal_connect (G_OBJECT (g
->web_view
), "download-requested", G_CALLBACK (download_cb
), g
->web_view
);
1174 g_signal_connect (G_OBJECT (g
->web_view
), "create-web-view", G_CALLBACK (create_web_view_cb
), g
->web_view
);
1176 return scrolled_window
;
1183 g
->mainbar
= gtk_hbox_new (FALSE
, 0);
1184 g
->mainbar_label
= gtk_label_new ("");
1185 gtk_label_set_selectable((GtkLabel
*)g
->mainbar_label
, TRUE
);
1186 gtk_label_set_ellipsize(GTK_LABEL(g
->mainbar_label
), PANGO_ELLIPSIZE_END
);
1187 gtk_misc_set_alignment (GTK_MISC(g
->mainbar_label
), 0, 0);
1188 gtk_misc_set_padding (GTK_MISC(g
->mainbar_label
), 2, 2);
1189 gtk_box_pack_start (GTK_BOX (g
->mainbar
), g
->mainbar_label
, TRUE
, TRUE
, 0);
1194 GtkWidget
* create_window () {
1195 GtkWidget
* window
= gtk_window_new (GTK_WINDOW_TOPLEVEL
);
1196 gtk_window_set_default_size (GTK_WINDOW (window
), 800, 600);
1197 gtk_widget_set_name (window
, "Uzbl browser");
1198 g_signal_connect (G_OBJECT (window
), "destroy", G_CALLBACK (destroy_cb
), NULL
);
1204 add_binding (const gchar
*key
, const gchar
*act
) {
1205 char **parts
= g_strsplit(act
, " ", 2);
1212 printf ("Binding %-10s : %s\n", key
, act
);
1213 action
= new_action(parts
[0], parts
[1]);
1215 if(g_hash_table_lookup(uzbl
.bindings
, key
))
1216 g_hash_table_remove(uzbl
.bindings
, key
);
1217 g_hash_table_insert(uzbl
.bindings
, g_strdup(key
), action
);
1224 GKeyFile
* config
= NULL
;
1225 gboolean res
= FALSE
;
1227 gchar
** keys
= NULL
;
1228 State
*s
= &uzbl
.state
;
1229 Network
*n
= &uzbl
.net
;
1230 Behaviour
*b
= &uzbl
.behave
;
1232 if (!s
->config_file
) {
1233 const char* XDG_CONFIG_HOME
= getenv ("XDG_CONFIG_HOME");
1234 if (! XDG_CONFIG_HOME
|| ! strcmp (XDG_CONFIG_HOME
, "")) {
1235 XDG_CONFIG_HOME
= (char*)XDG_CONFIG_HOME_default
;
1237 printf("XDG_CONFIG_HOME: %s\n", XDG_CONFIG_HOME
);
1239 strcpy (s
->config_file_path
, XDG_CONFIG_HOME
);
1240 strcat (s
->config_file_path
, "/uzbl/config");
1241 if (file_exists (s
->config_file_path
)) {
1242 printf ("Config file %s found.\n", s
->config_file_path
);
1243 s
->config_file
= &s
->config_file_path
[0];
1245 // Now we check $XDG_CONFIG_DIRS
1246 char *XDG_CONFIG_DIRS
= getenv ("XDG_CONFIG_DIRS");
1247 if (! XDG_CONFIG_DIRS
|| ! strcmp (XDG_CONFIG_DIRS
, ""))
1248 XDG_CONFIG_DIRS
= XDG_CONFIG_DIRS_default
;
1250 printf("XDG_CONFIG_DIRS: %s\n", XDG_CONFIG_DIRS
);
1253 strcpy (buffer
, XDG_CONFIG_DIRS
);
1254 const gchar
* dir
= (char *) strtok_r (buffer
, ":", &saveptr
);
1255 while (dir
&& ! file_exists (s
->config_file_path
)) {
1256 strcpy (s
->config_file_path
, dir
);
1257 strcat (s
->config_file_path
, "/uzbl/config_file_pathig");
1258 if (file_exists (s
->config_file_path
)) {
1259 printf ("Config file %s found.\n", s
->config_file_path
);
1260 s
->config_file
= &s
->config_file_path
[0];
1262 dir
= (char * ) strtok_r (NULL
, ":", &saveptr
);
1267 if (s
->config_file
) {
1268 config
= g_key_file_new ();
1269 res
= g_key_file_load_from_file (config
, s
->config_file
, G_KEY_FILE_NONE
, NULL
);
1271 printf ("Config %s loaded\n", s
->config_file
);
1273 fprintf (stderr
, "Config %s loading failed\n", s
->config_file
);
1276 printf ("No configuration.\n");
1280 b
->history_handler
= g_key_file_get_value (config
, "behavior", "history_handler", NULL
);
1281 b
->download_handler
= g_key_file_get_value (config
, "behavior", "download_handler", NULL
);
1282 b
->cookie_handler
= g_key_file_get_string (config
, "behavior", "cookie_handler", NULL
);
1283 b
->always_insert_mode
= g_key_file_get_boolean (config
, "behavior", "always_insert_mode", NULL
);
1284 b
->show_status
= g_key_file_get_boolean (config
, "behavior", "show_status", NULL
);
1285 b
->modkey
= g_key_file_get_value (config
, "behavior", "modkey", NULL
);
1286 b
->status_top
= g_key_file_get_boolean (config
, "behavior", "status_top", NULL
);
1287 b
->status_format
= g_key_file_get_string (config
, "behavior", "status_format", NULL
);
1288 b
->status_background
= g_key_file_get_string (config
, "behavior", "status_background", NULL
);
1290 b
->fifo_dir
= g_key_file_get_value (config
, "behavior", "fifo_dir", NULL
);
1291 if (! b
->socket_dir
)
1292 b
->socket_dir
= g_key_file_get_value (config
, "behavior", "socket_dir", NULL
);
1293 keys
= g_key_file_get_keys (config
, "bindings", NULL
, NULL
);
1296 printf ("History handler: %s\n", (b
->history_handler
? b
->history_handler
: "disabled"));
1297 printf ("Download manager: %s\n", (b
->download_handler
? b
->download_handler
: "disabled"));
1298 printf ("Cookie handler: %s\n", (b
->cookie_handler
? b
->cookie_handler
: "disabled"));
1299 printf ("Fifo directory: %s\n", (b
->fifo_dir
? b
->fifo_dir
: "disabled"));
1300 printf ("Socket directory: %s\n", (b
->socket_dir
? b
->socket_dir
: "disabled"));
1301 printf ("Always insert mode: %s\n", (b
->always_insert_mode
? "TRUE" : "FALSE"));
1302 printf ("Show status: %s\n", (b
->show_status
? "TRUE" : "FALSE"));
1303 printf ("Status top: %s\n", (b
->status_top
? "TRUE" : "FALSE"));
1304 printf ("Modkey: %s\n", (b
->modkey
? b
->modkey
: "disabled"));
1305 printf ("Status format: %s\n", (b
->status_format
? b
->status_format
: "none"));
1310 //POSSIBLE MODKEY VALUES (COMBINATIONS CAN BE USED)
1311 gchar
* modkeyup
= g_utf8_strup (b
->modkey
, -1);
1312 if (g_strrstr (modkeyup
,"SHIFT") != NULL
) b
->modmask
|= GDK_SHIFT_MASK
; //the Shift key.
1313 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).
1314 if (g_strrstr (modkeyup
,"CONTROL") != NULL
) b
->modmask
|= GDK_CONTROL_MASK
; //the Control key.
1315 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).
1316 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).
1317 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).
1318 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).
1319 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).
1320 if (g_strrstr (modkeyup
,"BUTTON1") != NULL
) b
->modmask
|= GDK_BUTTON1_MASK
; //the first mouse button.
1321 if (g_strrstr (modkeyup
,"BUTTON2") != NULL
) b
->modmask
|= GDK_BUTTON2_MASK
; //the second mouse button.
1322 if (g_strrstr (modkeyup
,"BUTTON3") != NULL
) b
->modmask
|= GDK_BUTTON3_MASK
; //the third mouse button.
1323 if (g_strrstr (modkeyup
,"BUTTON4") != NULL
) b
->modmask
|= GDK_BUTTON4_MASK
; //the fourth mouse button.
1324 if (g_strrstr (modkeyup
,"BUTTON5") != NULL
) b
->modmask
|= GDK_BUTTON5_MASK
; //the fifth mouse button.
1325 if (g_strrstr (modkeyup
,"SUPER") != NULL
) b
->modmask
|= GDK_SUPER_MASK
; //the Super modifier. Since 2.10
1326 if (g_strrstr (modkeyup
,"HYPER") != NULL
) b
->modmask
|= GDK_HYPER_MASK
; //the Hyper modifier. Since 2.10
1327 if (g_strrstr (modkeyup
,"META") != NULL
) b
->modmask
|= GDK_META_MASK
; //the Meta modifier. Since 2.10 */
1332 for (i
= 0; keys
[i
]; i
++) {
1333 gchar
*value
= g_key_file_get_string (config
, "bindings", keys
[i
], NULL
);
1335 add_binding(g_strstrip(keys
[i
]), value
);
1342 /* networking options */
1344 b
->http_debug
= g_key_file_get_integer (config
, "network", "http_debug", NULL
);
1345 n
->useragent
= g_key_file_get_value (config
, "network", "user-agent", NULL
);
1346 n
->max_conns
= g_key_file_get_integer (config
, "network", "max_conns", NULL
);
1347 n
->max_conns_host
= g_key_file_get_integer (config
, "network", "max_conns_per_host", NULL
);
1351 if(!(b
->http_debug
<= 3)){
1353 fprintf(stderr
, "Wrong http_debug level, ignoring.\n");
1354 } else if (b
->http_debug
> 0) {
1355 n
->soup_logger
= soup_logger_new(b
->http_debug
, -1);
1356 soup_session_add_feature(n
->soup_session
, SOUP_SESSION_FEATURE(n
->soup_logger
));
1360 char* newagent
= malloc(1024);
1362 strcpy(newagent
, str_replace("%webkit-major%", itos(WEBKIT_MAJOR_VERSION
), n
->useragent
));
1363 strcpy(newagent
, str_replace("%webkit-minor%", itos(WEBKIT_MINOR_VERSION
), newagent
));
1364 strcpy(newagent
, str_replace("%webkit-micro%", itos(WEBKIT_MICRO_VERSION
), newagent
));
1366 if (uname (&s
->unameinfo
) == -1) {
1367 printf("Error getting uname info. Not replacing system-related user agent variables.\n");
1369 strcpy(newagent
, str_replace("%sysname%", s
->unameinfo
.sysname
, newagent
));
1370 strcpy(newagent
, str_replace("%nodename%", s
->unameinfo
.nodename
, newagent
));
1371 strcpy(newagent
, str_replace("%kernrel%", s
->unameinfo
.release
, newagent
));
1372 strcpy(newagent
, str_replace("%kernver%", s
->unameinfo
.version
, newagent
));
1373 strcpy(newagent
, str_replace("%arch-system%", s
->unameinfo
.machine
, newagent
));
1376 strcpy(newagent
, str_replace("%domainname%", s
->unameinfo
.domainname
, newagent
));
1380 strcpy(newagent
, str_replace("%arch-uzbl%", ARCH
, newagent
));
1381 strcpy(newagent
, str_replace("%commit%", COMMIT
, newagent
));
1383 n
->useragent
= malloc(1024);
1384 strcpy(n
->useragent
, newagent
);
1385 g_object_set(G_OBJECT(n
->soup_session
), SOUP_SESSION_USER_AGENT
, n
->useragent
, NULL
);
1388 if(n
->max_conns
>= 1){
1389 g_object_set(G_OBJECT(n
->soup_session
), SOUP_SESSION_MAX_CONNS
, n
->max_conns
, NULL
);
1392 if(n
->max_conns_host
>= 1){
1393 g_object_set(G_OBJECT(n
->soup_session
), SOUP_SESSION_MAX_CONNS_PER_HOST
, n
->max_conns_host
, NULL
);
1396 printf("Proxy configured: %s\n", n
->proxy_url
? n
->proxy_url
: "none");
1397 printf("HTTP logging level: %d\n", b
->http_debug
);
1398 printf("User-agent: %s\n", n
->useragent
? n
->useragent
: "default");
1399 printf("Maximum connections: %d\n", n
->max_conns
? n
->max_conns
: 0);
1400 printf("Maximum connections per host: %d\n", n
->max_conns_host
? n
->max_conns_host
: 0);
1404 if(b
->cookie_handler
){
1405 /* ck = soup_cookie_jar_new(); */
1406 /* soup_session_add_feature(soup_session, SOUP_SESSION_FEATURE(ck)); */
1407 /* g_signal_connect(ck, "changed", G_CALLBACK(cookie_recieved_action), NULL); */
1408 g_signal_connect(n
->soup_session
, "request-queued", G_CALLBACK(handle_cookies
), NULL
);
1413 static void handle_cookies (SoupSession
*session
, SoupMessage
*msg
, gpointer user_data
){
1416 gchar
* stdout
= NULL
;
1417 soup_message_add_header_handler(msg
, "got-headers", "Set-Cookie", G_CALLBACK(save_cookies
), NULL
);
1418 GString
* args
= g_string_new ("");
1419 SoupURI
* soup_uri
= soup_message_get_uri(msg
);
1420 g_string_printf (args
, "GET %s %s", soup_uri
->host
, soup_uri
->path
);
1421 run_command_sync(uzbl
.behave
.cookie_handler
, args
->str
, &stdout
);
1423 soup_message_headers_replace (msg
->request_headers
, "Cookie", stdout
);
1425 g_string_free(args
, TRUE
);
1429 save_cookies (SoupMessage
*msg
, gpointer user_data
){
1433 for (ck
= soup_cookies_from_response(msg
); ck
; ck
= ck
->next
){
1434 cookie
= soup_cookie_to_set_cookie_header(ck
->data
);
1435 GString
* args
= g_string_new ("");
1436 SoupURI
* soup_uri
= soup_message_get_uri(msg
);
1437 g_string_printf (args
, "PUT %s %s \"%s\"", soup_uri
->host
, soup_uri
->path
, cookie
);
1438 run_command_async(uzbl
.behave
.cookie_handler
, args
->str
);
1439 g_string_free(args
, TRUE
);
1446 main (int argc
, char* argv
[]) {
1447 gtk_init (&argc
, &argv
);
1448 if (!g_thread_supported ())
1449 g_thread_init (NULL
);
1451 printf("Uzbl start location: %s\n", argv
[0]);
1452 strcpy(uzbl
.state
.executable_path
,argv
[0]);
1454 strcat ((char *) XDG_CONFIG_HOME_default
, getenv ("HOME"));
1455 strcat ((char *) XDG_CONFIG_HOME_default
, "/.config");
1457 GError
*error
= NULL
;
1458 GOptionContext
* context
= g_option_context_new ("- some stuff here maybe someday");
1459 g_option_context_add_main_entries (context
, entries
, NULL
);
1460 g_option_context_add_group (context
, gtk_get_option_group (TRUE
));
1461 g_option_context_parse (context
, &argc
, &argv
, &error
);
1462 /* initialize hash table */
1463 uzbl
.bindings
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
, free_action
);
1465 uzbl
.net
.soup_session
= webkit_get_default_session();
1466 uzbl
.state
.keycmd
= g_string_new("");
1471 if (uzbl
.behave
.always_insert_mode
)
1472 uzbl
.behave
.insert_mode
= TRUE
;
1474 GtkWidget
* vbox
= gtk_vbox_new (FALSE
, 0);
1475 if (uzbl
.behave
.status_top
)
1476 gtk_box_pack_start (GTK_BOX (vbox
), create_mainbar (), FALSE
, TRUE
, 0);
1477 gtk_box_pack_start (GTK_BOX (vbox
), create_browser (), TRUE
, TRUE
, 0);
1478 if (!uzbl
.behave
.status_top
)
1479 gtk_box_pack_start (GTK_BOX (vbox
), create_mainbar (), FALSE
, TRUE
, 0);
1481 uzbl
.gui
.main_window
= create_window ();
1482 gtk_container_add (GTK_CONTAINER (uzbl
.gui
.main_window
), vbox
);
1484 load_uri (uzbl
.gui
.web_view
, uzbl
.state
.uri
);
1486 gtk_widget_grab_focus (GTK_WIDGET (uzbl
.gui
.web_view
));
1487 gtk_widget_show_all (uzbl
.gui
.main_window
);
1488 uzbl
.xwin
= GDK_WINDOW_XID (GTK_WIDGET (uzbl
.gui
.main_window
)->window
);
1489 printf("window_id %i\n",(int) uzbl
.xwin
);
1490 printf("pid %i\n", getpid ());
1491 printf("name: %s\n", uzbl
.state
.instance_name
);
1493 uzbl
.gui
.scbar_v
= (GtkScrollbar
*) gtk_vscrollbar_new (NULL
);
1494 uzbl
.gui
.bar_v
= gtk_range_get_adjustment((GtkRange
*) uzbl
.gui
.scbar_v
);
1495 uzbl
.gui
.scbar_h
= (GtkScrollbar
*) gtk_hscrollbar_new (NULL
);
1496 uzbl
.gui
.bar_h
= gtk_range_get_adjustment((GtkRange
*) uzbl
.gui
.scbar_h
);
1497 gtk_widget_set_scroll_adjustments ((GtkWidget
*) uzbl
.gui
.web_view
, uzbl
.gui
.bar_h
, uzbl
.gui
.bar_v
);
1500 if(setup_signal(SIGTERM
, catch_sigterm
) == SIG_ERR
)
1501 fprintf(stderr
, "uzbl: error hooking SIGTERM\n");
1507 if (!uzbl
.behave
.status_format
)
1508 uzbl
.behave
.status_format
= g_strdup(STATUS_DEFAULT
);
1509 if (!uzbl
.behave
.show_status
)
1510 gtk_widget_hide(uzbl
.gui
.mainbar
);
1515 make_var_to_name_hash();
1517 if (uzbl
.behave
.fifo_dir
)
1519 if (uzbl
.behave
.socket_dir
)
1525 return EXIT_SUCCESS
;
1528 /* vi: set et ts=4: */