X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=uzbl.c;h=2bc212c5bc61c669e7a5e1f1c3115aa6ef51fc1c;hb=b2780461a6f660102830b1001c34ca3a7f564b7b;hp=2641b4ccb18e6c525efa2e5108e340bdc0b00185;hpb=00baad15a16c5ac1bfefdc9314848b7bc561393c;p=uzbl-mobile diff --git a/uzbl.c b/uzbl.c index 2641b4c..2bc212c 100644 --- a/uzbl.c +++ b/uzbl.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -57,22 +58,25 @@ #include "config.h" Uzbl uzbl; -typedef void (*Command)(WebKitWebView*, GArray *argv); - - /* commandline arguments (set initial values for the state variables) */ -const +const GOptionEntry entries[] = { - { "uri", 'u', 0, G_OPTION_ARG_STRING, &uzbl.state.uri, + { "uri", 'u', 0, G_OPTION_ARG_STRING, &uzbl.state.uri, "Uri to load at startup (equivalent to 'set uri = URI')", "URI" }, - { "verbose", 'v', 0, G_OPTION_ARG_NONE, &uzbl.state.verbose, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &uzbl.state.verbose, "Whether to print all messages or just errors.", NULL }, - { "name", 'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name, + { "name", 'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name, "Name of the current instance (defaults to Xorg window id)", "NAME" }, - { "config", 'c', 0, G_OPTION_ARG_STRING, &uzbl.state.config_file, + { "config", 'c', 0, G_OPTION_ARG_STRING, &uzbl.state.config_file, "Config file (this is pretty much equivalent to uzbl < FILE )", "FILE" }, + { "socket", 's', 0, G_OPTION_ARG_INT, &uzbl.state.socket_id, + "Socket ID", "SOCKET" }, + { "geometry", 'g', 0, G_OPTION_ARG_STRING, &uzbl.gui.geometry, + "Set window geometry (format: WIDTHxHEIGHT+-X+-Y)", "GEOMETRY" }, + { "version", 'V', 0, G_OPTION_ARG_NONE, &uzbl.behave.print_version, + "Print the version and exit", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; @@ -83,79 +87,98 @@ typedef const struct { void **ptr; int type; int dump; + int writeable; void (*func)(void); } uzbl_cmdprop; enum {TYPE_INT, TYPE_STR, TYPE_FLOAT}; -/* an abbreviation to help keep the table's width humane */ -#define PTR(var, t, d, fun) { .ptr = (void*)&(var), .type = TYPE_##t, .dump = d, .func = fun } +/* abbreviations to help keep the table's width humane */ +#define PTR_V(var, t, d, fun) { .ptr = (void*)&(var), .type = TYPE_##t, .dump = d, .writeable = 1, .func = fun } +#define PTR_C(var, t, fun) { .ptr = (void*)&(var), .type = TYPE_##t, .dump = 0, .writeable = 0, .func = fun } const struct { char *name; uzbl_cmdprop cp; } var_name_to_ptr[] = { -/* variable name pointer to variable in code type dump callback function */ -/* --------------------------------------------------------------------------------------- */ - { "uri", PTR(uzbl.state.uri, STR, 1, cmd_load_uri)}, - { "verbose", PTR(uzbl.state.verbose, INT, 1, NULL)}, - { "mode", PTR(uzbl.behave.mode, INT, 0, NULL)}, - { "inject_html", PTR(uzbl.behave.inject_html, STR, 0, cmd_inject_html)}, - { "base_url", PTR(uzbl.behave.base_url, STR, 1, NULL)}, - { "html_endmarker", PTR(uzbl.behave.html_endmarker, STR, 1, NULL)}, - { "html_mode_timeout", PTR(uzbl.behave.html_timeout, INT, 1, NULL)}, - { "status_message", PTR(uzbl.gui.sbar.msg, STR, 1, update_title)}, - { "show_status", PTR(uzbl.behave.show_status, INT, 1, cmd_set_status)}, - { "status_top", PTR(uzbl.behave.status_top, INT, 1, move_statusbar)}, - { "status_format", PTR(uzbl.behave.status_format, STR, 1, update_title)}, - { "status_pbar_done", PTR(uzbl.gui.sbar.progress_s, STR, 1, update_title)}, - { "status_pbar_pending", PTR(uzbl.gui.sbar.progress_u, STR, 1, update_title)}, - { "status_pbar_width", PTR(uzbl.gui.sbar.progress_w, INT, 1, update_title)}, - { "status_background", PTR(uzbl.behave.status_background, STR, 1, update_title)}, - { "insert_indicator", PTR(uzbl.behave.insert_indicator, STR, 1, update_title)}, - { "command_indicator", PTR(uzbl.behave.cmd_indicator, STR, 1, update_title)}, - { "title_format_long", PTR(uzbl.behave.title_format_long, STR, 1, update_title)}, - { "title_format_short", PTR(uzbl.behave.title_format_short, STR, 1, update_title)}, - { "icon", PTR(uzbl.gui.icon, STR, 1, set_icon)}, - { "insert_mode", PTR(uzbl.behave.insert_mode, INT, 1, NULL)}, - { "always_insert_mode", PTR(uzbl.behave.always_insert_mode, INT, 1, cmd_always_insert_mode)}, - { "reset_command_mode", PTR(uzbl.behave.reset_command_mode, INT, 1, NULL)}, - { "modkey", PTR(uzbl.behave.modkey, STR, 1, cmd_modkey)}, - { "load_finish_handler", PTR(uzbl.behave.load_finish_handler, STR, 1, NULL)}, - { "load_start_handler", PTR(uzbl.behave.load_start_handler, STR, 1, NULL)}, - { "load_commit_handler", PTR(uzbl.behave.load_commit_handler, STR, 1, NULL)}, - { "history_handler", PTR(uzbl.behave.history_handler, STR, 1, NULL)}, - { "download_handler", PTR(uzbl.behave.download_handler, STR, 1, NULL)}, - { "cookie_handler", PTR(uzbl.behave.cookie_handler, STR, 1, cmd_cookie_handler)}, - { "fifo_dir", PTR(uzbl.behave.fifo_dir, STR, 1, cmd_fifo_dir)}, - { "socket_dir", PTR(uzbl.behave.socket_dir, STR, 1, cmd_socket_dir)}, - { "http_debug", PTR(uzbl.behave.http_debug, INT, 1, cmd_http_debug)}, - { "shell_cmd", PTR(uzbl.behave.shell_cmd, STR, 1, NULL)}, - { "proxy_url", PTR(uzbl.net.proxy_url, STR, 1, set_proxy_url)}, - { "max_conns", PTR(uzbl.net.max_conns, INT, 1, cmd_max_conns)}, - { "max_conns_host", PTR(uzbl.net.max_conns_host, INT, 1, cmd_max_conns_host)}, - { "useragent", PTR(uzbl.net.useragent, STR, 1, cmd_useragent)}, +/* variable name pointer to variable in code type dump callback function */ +/* ---------------------------------------------------------------------------------------------- */ + { "uri", PTR_V(uzbl.state.uri, STR, 1, cmd_load_uri)}, + { "verbose", PTR_V(uzbl.state.verbose, INT, 1, NULL)}, + { "mode", PTR_V(uzbl.behave.mode, INT, 0, NULL)}, + { "inject_html", PTR_V(uzbl.behave.inject_html, STR, 0, cmd_inject_html)}, + { "base_url", PTR_V(uzbl.behave.base_url, STR, 1, NULL)}, + { "html_endmarker", PTR_V(uzbl.behave.html_endmarker, STR, 1, NULL)}, + { "html_mode_timeout", PTR_V(uzbl.behave.html_timeout, INT, 1, NULL)}, + { "keycmd", PTR_V(uzbl.state.keycmd, STR, 1, set_keycmd)}, + { "status_message", PTR_V(uzbl.gui.sbar.msg, STR, 1, update_title)}, + { "show_status", PTR_V(uzbl.behave.show_status, INT, 1, cmd_set_status)}, + { "status_top", PTR_V(uzbl.behave.status_top, INT, 1, move_statusbar)}, + { "status_format", PTR_V(uzbl.behave.status_format, STR, 1, update_title)}, + { "status_pbar_done", PTR_V(uzbl.gui.sbar.progress_s, STR, 1, update_title)}, + { "status_pbar_pending", PTR_V(uzbl.gui.sbar.progress_u, STR, 1, update_title)}, + { "status_pbar_width", PTR_V(uzbl.gui.sbar.progress_w, INT, 1, update_title)}, + { "status_background", PTR_V(uzbl.behave.status_background, STR, 1, update_title)}, + { "insert_indicator", PTR_V(uzbl.behave.insert_indicator, STR, 1, update_indicator)}, + { "command_indicator", PTR_V(uzbl.behave.cmd_indicator, STR, 1, update_indicator)}, + { "title_format_long", PTR_V(uzbl.behave.title_format_long, STR, 1, update_title)}, + { "title_format_short", PTR_V(uzbl.behave.title_format_short, STR, 1, update_title)}, + { "icon", PTR_V(uzbl.gui.icon, STR, 1, set_icon)}, + { "insert_mode", PTR_V(uzbl.behave.insert_mode, INT, 1, set_mode_indicator)}, + { "always_insert_mode", PTR_V(uzbl.behave.always_insert_mode, INT, 1, cmd_always_insert_mode)}, + { "reset_command_mode", PTR_V(uzbl.behave.reset_command_mode, INT, 1, NULL)}, + { "modkey", PTR_V(uzbl.behave.modkey, STR, 1, cmd_modkey)}, + { "load_finish_handler", PTR_V(uzbl.behave.load_finish_handler, STR, 1, NULL)}, + { "load_start_handler", PTR_V(uzbl.behave.load_start_handler, STR, 1, NULL)}, + { "load_commit_handler", PTR_V(uzbl.behave.load_commit_handler, STR, 1, NULL)}, + { "history_handler", PTR_V(uzbl.behave.history_handler, STR, 1, NULL)}, + { "download_handler", PTR_V(uzbl.behave.download_handler, STR, 1, NULL)}, + { "cookie_handler", PTR_V(uzbl.behave.cookie_handler, STR, 1, cmd_cookie_handler)}, + { "new_window", PTR_V(uzbl.behave.new_window, STR, 1, cmd_new_window)}, + { "fifo_dir", PTR_V(uzbl.behave.fifo_dir, STR, 1, cmd_fifo_dir)}, + { "socket_dir", PTR_V(uzbl.behave.socket_dir, STR, 1, cmd_socket_dir)}, + { "http_debug", PTR_V(uzbl.behave.http_debug, INT, 1, cmd_http_debug)}, + { "shell_cmd", PTR_V(uzbl.behave.shell_cmd, STR, 1, NULL)}, + { "proxy_url", PTR_V(uzbl.net.proxy_url, STR, 1, set_proxy_url)}, + { "max_conns", PTR_V(uzbl.net.max_conns, INT, 1, cmd_max_conns)}, + { "max_conns_host", PTR_V(uzbl.net.max_conns_host, INT, 1, cmd_max_conns_host)}, + { "useragent", PTR_V(uzbl.net.useragent, STR, 1, cmd_useragent)}, + /* exported WebKitWebSettings properties */ - { "zoom_level", PTR(uzbl.behave.zoom_level, FLOAT,1, cmd_zoom_level)}, - { "font_size", PTR(uzbl.behave.font_size, INT, 1, cmd_font_size)}, - { "monospace_size", PTR(uzbl.behave.monospace_size, INT, 1, cmd_font_size)}, - { "minimum_font_size", PTR(uzbl.behave.minimum_font_size, INT, 1, cmd_minimum_font_size)}, - { "disable_plugins", PTR(uzbl.behave.disable_plugins, INT, 1, cmd_disable_plugins)}, - { "disable_scripts", PTR(uzbl.behave.disable_scripts, INT, 1, cmd_disable_scripts)}, - { "autoload_images", PTR(uzbl.behave.autoload_img, INT, 1, cmd_autoload_img)}, - { "autoshrink_images", PTR(uzbl.behave.autoshrink_img, INT, 1, cmd_autoshrink_img)}, - { "enable_spellcheck", PTR(uzbl.behave.enable_spellcheck, INT, 1, cmd_enable_spellcheck)}, - { "enable_private", PTR(uzbl.behave.enable_private, INT, 1, cmd_enable_private)}, - { "print_backgrounds", PTR(uzbl.behave.print_bg, INT, 1, cmd_print_bg)}, - { "stylesheet_uri", PTR(uzbl.behave.style_uri, STR, 1, cmd_style_uri)}, - { "resizable_text_areas",PTR(uzbl.behave.resizable_txt, INT, 1, cmd_resizable_txt)}, - { "default_encoding", PTR(uzbl.behave.default_encoding, STR, 1, cmd_default_encoding)}, - { "enforce_96_dpi", PTR(uzbl.behave.enforce_96dpi, INT, 1, cmd_enforce_96dpi)}, - { "caret_browsing", PTR(uzbl.behave.caret_browsing, INT, 1, cmd_caret_browsing)}, - - { NULL, {.ptr = NULL, .type = TYPE_INT, .dump = 0, .func = NULL}} + { "zoom_level", PTR_V(uzbl.behave.zoom_level, FLOAT,1, cmd_zoom_level)}, + { "font_size", PTR_V(uzbl.behave.font_size, INT, 1, cmd_font_size)}, + { "monospace_size", PTR_V(uzbl.behave.monospace_size, INT, 1, cmd_font_size)}, + { "minimum_font_size", PTR_V(uzbl.behave.minimum_font_size, INT, 1, cmd_minimum_font_size)}, + { "disable_plugins", PTR_V(uzbl.behave.disable_plugins, INT, 1, cmd_disable_plugins)}, + { "disable_scripts", PTR_V(uzbl.behave.disable_scripts, INT, 1, cmd_disable_scripts)}, + { "autoload_images", PTR_V(uzbl.behave.autoload_img, INT, 1, cmd_autoload_img)}, + { "autoshrink_images", PTR_V(uzbl.behave.autoshrink_img, INT, 1, cmd_autoshrink_img)}, + { "enable_spellcheck", PTR_V(uzbl.behave.enable_spellcheck, INT, 1, cmd_enable_spellcheck)}, + { "enable_private", PTR_V(uzbl.behave.enable_private, INT, 1, cmd_enable_private)}, + { "print_backgrounds", PTR_V(uzbl.behave.print_bg, INT, 1, cmd_print_bg)}, + { "stylesheet_uri", PTR_V(uzbl.behave.style_uri, STR, 1, cmd_style_uri)}, + { "resizable_text_areas",PTR_V(uzbl.behave.resizable_txt, INT, 1, cmd_resizable_txt)}, + { "default_encoding", PTR_V(uzbl.behave.default_encoding, STR, 1, cmd_default_encoding)}, + { "enforce_96_dpi", PTR_V(uzbl.behave.enforce_96dpi, INT, 1, cmd_enforce_96dpi)}, + { "caret_browsing", PTR_V(uzbl.behave.caret_browsing, INT, 1, cmd_caret_browsing)}, + + /* constants (not dumpable or writeable) */ + { "WEBKIT_MAJOR", PTR_C(uzbl.info.webkit_major, INT, NULL)}, + { "WEBKIT_MINOR", PTR_C(uzbl.info.webkit_minor, INT, NULL)}, + { "WEBKIT_MICRO", PTR_C(uzbl.info.webkit_micro, INT, NULL)}, + { "ARCH_UZBL", PTR_C(uzbl.info.arch, STR, NULL)}, + { "COMMIT", PTR_C(uzbl.info.commit, STR, NULL)}, + { "LOAD_PROGRESS", PTR_C(uzbl.gui.sbar.load_progress, INT, NULL)}, + { "LOAD_PROGRESSBAR", PTR_C(uzbl.gui.sbar.progress_bar, STR, NULL)}, + { "TITLE", PTR_C(uzbl.gui.main_title, STR, NULL)}, + { "SELECTED_URI", PTR_C(uzbl.state.selected_url, STR, NULL)}, + { "MODE", PTR_C(uzbl.gui.sbar.mode_indicator, STR, NULL)}, + { "NAME", PTR_C(uzbl.state.instance_name, STR, NULL)}, + + { NULL, {.ptr = NULL, .type = TYPE_INT, .dump = 0, .writeable = 0, .func = NULL}} }, *n2v_p = var_name_to_ptr; + const struct { char *key; guint mask; @@ -191,12 +214,42 @@ make_var_to_name_hash() { } /* --- UTILITY FUNCTIONS --- */ +enum {EXP_ERR, EXP_SIMPLE_VAR, EXP_BRACED_VAR, EXP_EXPR, EXP_JS, EXP_ESCAPE}; +guint +get_exp_type(gchar *s) { + /* variables */ + if(*(s+1) == '(') + return EXP_EXPR; + else if(*(s+1) == '{') + return EXP_BRACED_VAR; + else if(*(s+1) == '<') + return EXP_JS; + else if(*(s+1) == '[') + return EXP_ESCAPE; + else + return EXP_SIMPLE_VAR; + +return EXP_ERR; +} + +/* + * recurse == 1: don't expand '@(command)@' + * recurse == 2: don't expand '@@' + */ gchar * -expand_vars(char *s) { +expand(char *s, guint recurse) { uzbl_cmdprop *c; + guint etype; char upto = ' '; - char ret[256], *vend; + char *end_simple_var = "^°!\"§$%&/()=?'`'+~*'#-.:,;@<>| \\{}[]¹²³¼½"; + char str_end[3]; + char ret[4096]; + char *vend = NULL; + GError *err = NULL; + gchar *cmd_stdout = NULL; + gchar *mycmd = NULL; GString *buf = g_string_new(""); + GString *js_ret = g_string_new(""); while(*s) { switch(*s) { @@ -204,36 +257,120 @@ expand_vars(char *s) { g_string_append_c(buf, *++s); s++; break; + case '@': - if(*(s+1) == '{') { - upto = '}'; s++; - } + etype = get_exp_type(s); s++; - if( (vend = strchr(s, upto)) || - (vend = strchr(s, '\0')) ) { + + switch(etype) { + case EXP_SIMPLE_VAR: + vend = strpbrk(s, end_simple_var); + if(!vend) vend = strchr(s, '\0'); + break; + case EXP_BRACED_VAR: + s++; upto = '}'; + vend = strchr(s, upto); + if(!vend) vend = strchr(s, '\0'); + break; + case EXP_EXPR: + s++; + strcpy(str_end, ")@"); + str_end[2] = '\0'; + vend = strstr(s, str_end); + if(!vend) vend = strchr(s, '\0'); + break; + case EXP_JS: + s++; + strcpy(str_end, ">@"); + str_end[2] = '\0'; + vend = strstr(s, str_end); + if(!vend) vend = strchr(s, '\0'); + break; + case EXP_ESCAPE: + s++; + strcpy(str_end, "]@"); + str_end[2] = '\0'; + vend = strstr(s, str_end); + if(!vend) vend = strchr(s, '\0'); + break; + } + + if(vend) { strncpy(ret, s, vend-s); ret[vend-s] = '\0'; + } + + if(etype == EXP_SIMPLE_VAR || + etype == EXP_BRACED_VAR) { if( (c = g_hash_table_lookup(uzbl.comm.proto_var, ret)) ) { - if(c->type == TYPE_STR) + if(c->type == TYPE_STR && *c->ptr != NULL) { g_string_append(buf, (gchar *)*c->ptr); - else if(c->type == TYPE_INT) { + } else if(c->type == TYPE_INT) { g_string_append_printf(buf, "%d", (int)*c->ptr); } else if(c->type == TYPE_FLOAT) { g_string_append_printf(buf, "%f", *(float *)c->ptr); } } - if(upto == ' ') s = vend; - else s = vend+1; - upto = ' '; + + if(etype == EXP_SIMPLE_VAR) + s = vend; + else + s = vend+1; + } + else if(recurse != 1 && + etype == EXP_EXPR) { + mycmd = expand(ret, 1); + g_spawn_command_line_sync(mycmd, &cmd_stdout, NULL, NULL, &err); + g_free(mycmd); + + if (err) { + g_printerr("error on running command: %s\n", err->message); + g_error_free (err); + } + else if (*cmd_stdout) { + int len = strlen(cmd_stdout); + + if(cmd_stdout[len-1] == '\n') + cmd_stdout[--len] = 0; /* strip trailing newline */ + + g_string_append(buf, cmd_stdout); + g_free(cmd_stdout); + } + s = vend+2; + } + else if(recurse != 2 && + etype == EXP_JS) { + mycmd = expand(ret, 2); + eval_js(uzbl.gui.web_view, mycmd, js_ret); + g_free(mycmd); + + if(js_ret->str) { + g_string_append(buf, js_ret->str); + g_string_free(js_ret, TRUE); + js_ret = g_string_new(""); + } + s = vend+2; + } + else if(etype == EXP_ESCAPE) { + mycmd = expand(ret, 0); + char *escaped = g_markup_escape_text(mycmd, strlen(mycmd)); + + g_string_append(buf, escaped); + + g_free(escaped); + g_free(mycmd); + s = vend+2; } break; + default: g_string_append_c(buf, *s); s++; break; } } + g_string_free(js_ret, TRUE); return g_string_free(buf, FALSE); } @@ -270,9 +407,9 @@ read_file_by_line (gchar *path) { gsize len; GArray *lines = g_array_new(TRUE, FALSE, sizeof(gchar*)); int i = 0; - + chan = g_io_channel_new_file(path, "r", NULL); - + if (chan) { while (g_io_channel_read_line(chan, &readbuf, &len, NULL, NULL) == G_IO_STATUS_NORMAL) { const gchar* val = g_strdup (readbuf); @@ -280,21 +417,21 @@ read_file_by_line (gchar *path) { g_free (readbuf); i ++; } - + g_io_channel_unref (chan); } else { fprintf(stderr, "File '%s' not be read.\n", path); } - + return lines; } -static -gchar* parseenv (char* string) { +gchar* +parseenv (char* string) { extern char** environ; gchar* tmpstr = NULL; int i = 0; - + while (environ[i] != NULL) { gchar** env = g_strsplit (environ[i], "=", 2); @@ -337,13 +474,12 @@ clean_up(void) { unlink (uzbl.comm.socket_path); g_free(uzbl.state.executable_path); - g_string_free(uzbl.state.keycmd, TRUE); + g_free(uzbl.state.keycmd); g_hash_table_destroy(uzbl.bindings); g_hash_table_destroy(uzbl.behave.commands); - g_scanner_destroy(uzbl.scan); } -/* used for html_mode_timeout +/* used for html_mode_timeout * be sure to extend this function to use * more timers if needed in other places */ @@ -393,8 +529,8 @@ new_window_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequ const gchar* uri = webkit_network_request_get_uri (request); if (uzbl.state.verbose) printf("New window requested -> %s \n", uri); - new_window_load_uri(uri); - return (FALSE); + webkit_web_policy_decision_use(policy_decision); + return TRUE; } gboolean @@ -447,40 +583,66 @@ download_cb (WebKitWebView *web_view, GObject *download, gpointer user_data) { /* scroll a bar in a given direction */ void scroll (GtkAdjustment* bar, GArray *argv) { - gdouble amount; gchar *end; + gdouble max_value; - amount = g_ascii_strtod(g_array_index(argv, gchar*, 0), &end); - if (*end == '%') amount = gtk_adjustment_get_page_size(bar) * amount * 0.01; - gtk_adjustment_set_value (bar, gtk_adjustment_get_value(bar)+amount); + gdouble page_size = gtk_adjustment_get_page_size(bar); + gdouble value = gtk_adjustment_get_value(bar); + gdouble amount = g_ascii_strtod(g_array_index(argv, gchar*, 0), &end); + + if (*end == '%') + value += page_size * amount * 0.01; + else + value += amount; + + max_value = gtk_adjustment_get_upper(bar) - page_size; + + if (value > max_value) + value = max_value; /* don't scroll past the end of the page */ + + gtk_adjustment_set_value (bar, value); } void -scroll_begin(WebKitWebView* page, GArray *argv) { - (void) page; (void) argv; +scroll_begin(WebKitWebView* page, GArray *argv, GString *result) { + (void) page; (void) argv; (void) result; gtk_adjustment_set_value (uzbl.gui.bar_v, gtk_adjustment_get_lower(uzbl.gui.bar_v)); } void -scroll_end(WebKitWebView* page, GArray *argv) { - (void) page; (void) argv; +scroll_end(WebKitWebView* page, GArray *argv, GString *result) { + (void) page; (void) argv; (void) result; gtk_adjustment_set_value (uzbl.gui.bar_v, gtk_adjustment_get_upper(uzbl.gui.bar_v) - gtk_adjustment_get_page_size(uzbl.gui.bar_v)); } void -scroll_vert(WebKitWebView* page, GArray *argv) { - (void) page; +scroll_vert(WebKitWebView* page, GArray *argv, GString *result) { + (void) page; (void) result; scroll(uzbl.gui.bar_v, argv); } void -scroll_horz(WebKitWebView* page, GArray *argv) { - (void) page; +scroll_horz(WebKitWebView* page, GArray *argv, GString *result) { + (void) page; (void) result; scroll(uzbl.gui.bar_h, argv); } void +cmd_set_geometry() { + if(!gtk_window_parse_geometry(GTK_WINDOW(uzbl.gui.main_window), uzbl.gui.geometry)) { + if(uzbl.state.verbose) + printf("Error in geometry string: %s\n", uzbl.gui.geometry); + } + /* update geometry var with the actual geometry + this is necessary as some WMs don't seem to honour + the above setting and we don't want to end up with + wrong geometry information + */ + retreive_geometry(); +} + +void cmd_set_status() { if (!uzbl.behave.show_status) { gtk_widget_hide(uzbl.gui.mainbar); @@ -491,9 +653,19 @@ cmd_set_status() { } void -toggle_status_cb (WebKitWebView* page, GArray *argv) { +toggle_zoom_type (WebKitWebView* page, GArray *argv, GString *result) { (void)page; (void)argv; + (void)result; + + webkit_web_view_set_full_content_zoom (page, !webkit_web_view_get_full_content_zoom (page)); +} + +void +toggle_status_cb (WebKitWebView* page, GArray *argv, GString *result) { + (void)page; + (void)argv; + (void)result; if (uzbl.behave.show_status) { gtk_widget_hide(uzbl.gui.mainbar); @@ -519,13 +691,13 @@ link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpoin } void -title_change_cb (WebKitWebView* web_view, WebKitWebFrame* web_frame, const gchar* title, gpointer data) { +title_change_cb (WebKitWebView* web_view, GParamSpec param_spec) { (void) web_view; - (void) web_frame; - (void) data; + (void) param_spec; + const gchar *title = webkit_web_view_get_title(web_view); if (uzbl.gui.main_title) g_free (uzbl.gui.main_title); - uzbl.gui.main_title = g_strdup (title); + uzbl.gui.main_title = title ? g_strdup (title) : g_strdup ("(no title)"); update_title(); } @@ -534,6 +706,10 @@ progress_change_cb (WebKitWebView* page, gint progress, gpointer data) { (void) page; (void) data; uzbl.gui.sbar.load_progress = progress; + + g_free(uzbl.gui.sbar.progress_bar); + uzbl.gui.sbar.progress_bar = build_progressbar_ascii(uzbl.gui.sbar.load_progress); + update_title(); } @@ -546,13 +722,18 @@ load_finish_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) { run_handler(uzbl.behave.load_finish_handler, ""); } +void clear_keycmd() { + g_free(uzbl.state.keycmd); + uzbl.state.keycmd = g_strdup(""); +} + void load_start_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) { (void) page; (void) frame; (void) data; uzbl.gui.sbar.load_progress = 0; - g_string_truncate(uzbl.state.keycmd, 0); // don't need old commands to remain on new page? + clear_keycmd(); // don't need old commands to remain on new page? if (uzbl.behave.load_start_handler) run_handler(uzbl.behave.load_start_handler, ""); } @@ -565,7 +746,7 @@ load_commit_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) { GString* newuri = g_string_new (webkit_web_frame_get_uri (frame)); uzbl.state.uri = g_string_free (newuri, FALSE); if (uzbl.behave.reset_command_mode && uzbl.behave.insert_mode) { - uzbl.behave.insert_mode = uzbl.behave.always_insert_mode; + set_insert_mode(uzbl.behave.always_insert_mode); update_title(); } if (uzbl.behave.load_commit_handler) @@ -594,7 +775,7 @@ log_history_cb () { /* VIEW funcs (little webkit wrappers) */ -#define VIEWFUNC(name) void view_##name(WebKitWebView *page, GArray *argv){(void)argv; webkit_web_view_##name(page);} +#define VIEWFUNC(name) void view_##name(WebKitWebView *page, GArray *argv, GString *result){(void)argv; (void)result; webkit_web_view_##name(page);} VIEWFUNC(reload) VIEWFUNC(reload_bypass_cache) VIEWFUNC(stop_loading) @@ -605,7 +786,7 @@ VIEWFUNC(go_forward) #undef VIEWFUNC /* -- command to callback/function map for things we cannot attach to any signals */ -struct {char *name; Command command[2];} cmdlist[] = +struct {char *key; CommandInfo value;} cmdlist[] = { /* key function no_split */ { "back", {view_go_back, 0} }, { "forward", {view_go_forward, 0} }, @@ -618,8 +799,9 @@ struct {char *name; Command command[2];} cmdlist[] = { "stop", {view_stop_loading, 0}, }, { "zoom_in", {view_zoom_in, 0}, }, //Can crash (when max zoom reached?). { "zoom_out", {view_zoom_out, 0}, }, - { "uri", {load_uri, NOSPLIT} }, - { "js", {run_js, NOSPLIT} }, + { "toggle_zoom_type", {toggle_zoom_type, 0}, }, + { "uri", {load_uri, TRUE} }, + { "js", {run_js, TRUE} }, { "script", {run_external_js, 0} }, { "toggle_status", {toggle_status_cb, 0} }, { "spawn", {spawn, 0} }, @@ -627,20 +809,19 @@ struct {char *name; Command command[2];} cmdlist[] = { "sh", {spawn_sh, 0} }, { "sync_sh", {spawn_sh_sync, 0} }, // needed for cookie handler { "exit", {close_uzbl, 0} }, - { "quit", {close_uzbl, 0} }, - { "search", {search_forward_text, NOSPLIT} }, - { "search_reverse", {search_reverse_text, NOSPLIT} }, + { "search", {search_forward_text, TRUE} }, + { "search_reverse", {search_reverse_text, TRUE} }, { "dehilight", {dehilight, 0} }, { "toggle_insert_mode", {toggle_insert_mode, 0} }, - { "set", {set_var, NOSPLIT} }, - //{ "get", {get_var, NOSPLIT} }, - { "bind", {act_bind, NOSPLIT} }, + { "set", {set_var, TRUE} }, + //{ "get", {get_var, TRUE} }, + { "bind", {act_bind, TRUE} }, { "dump_config", {act_dump_config, 0} }, - { "keycmd", {keycmd, NOSPLIT} }, - { "keycmd_nl", {keycmd_nl, NOSPLIT} }, + { "keycmd", {keycmd, TRUE} }, + { "keycmd_nl", {keycmd_nl, TRUE} }, { "keycmd_bs", {keycmd_bs, 0} }, { "chain", {chain, 0} }, - { "print", {print, NOSPLIT} } + { "print", {print, TRUE} } }; void @@ -650,7 +831,7 @@ commands_hash(void) uzbl.behave.commands = g_hash_table_new(g_str_hash, g_str_equal); for (i = 0; i < LENGTH(cmdlist); i++) - g_hash_table_insert(uzbl.behave.commands, cmdlist[i].name, cmdlist[i].command); + g_hash_table_insert(uzbl.behave.commands, cmdlist[i].key, &cmdlist[i].value); } /* -- CORE FUNCTIONS -- */ @@ -683,28 +864,30 @@ file_exists (const char * filename) { } void -set_var(WebKitWebView *page, GArray *argv) { - (void) page; +set_var(WebKitWebView *page, GArray *argv, GString *result) { + (void) page; (void) result; gchar **split = g_strsplit(argv_idx(argv, 0), "=", 2); - gchar *value = parseenv(g_strdup(split[1] ? g_strchug(split[1]) : " ")); - set_var_value(g_strstrip(split[0]), value); - g_free(value); + if (split[0] != NULL) { + gchar *value = parseenv(g_strdup(split[1] ? g_strchug(split[1]) : " ")); + set_var_value(g_strstrip(split[0]), value); + g_free(value); + } g_strfreev(split); } void -print(WebKitWebView *page, GArray *argv) { - (void) page; +print(WebKitWebView *page, GArray *argv, GString *result) { + (void) page; (void) result; gchar* buf; - buf = expand_vars(argv_idx(argv, 0)); - puts(buf); + buf = expand(argv_idx(argv, 0), 0); + g_string_assign(result, buf); g_free(buf); } void -act_bind(WebKitWebView *page, GArray *argv) { - (void) page; +act_bind(WebKitWebView *page, GArray *argv, GString *result) { + (void) page; (void) result; gchar **split = g_strsplit(argv_idx(argv, 0), " = ", 2); gchar *value = parseenv(g_strdup(split[1] ? g_strchug(split[1]) : " ")); add_binding(g_strstrip(split[0]), value); @@ -719,28 +902,54 @@ act_dump_config() { } void -toggle_insert_mode(WebKitWebView *page, GArray *argv) { - (void)page; +set_keycmd() { + run_keycmd(FALSE); + update_title(); +} + +void +set_mode_indicator() { + uzbl.gui.sbar.mode_indicator = (uzbl.behave.insert_mode ? + uzbl.behave.insert_indicator : uzbl.behave.cmd_indicator); +} + +void +update_indicator() { + set_mode_indicator(); + update_title(); +} + +void +set_insert_mode(gboolean mode) { + uzbl.behave.insert_mode = mode; + set_mode_indicator(); +} + +void +toggle_insert_mode(WebKitWebView *page, GArray *argv, GString *result) { + (void) page; (void) result; if (argv_idx(argv, 0)) { if (strcmp (argv_idx(argv, 0), "0") == 0) { - uzbl.behave.insert_mode = FALSE; + set_insert_mode(FALSE); } else { - uzbl.behave.insert_mode = TRUE; + set_insert_mode(TRUE); } } else { - uzbl.behave.insert_mode = ! uzbl.behave.insert_mode; + set_insert_mode( !uzbl.behave.insert_mode ); } update_title(); } void -load_uri (WebKitWebView *web_view, GArray *argv) { +load_uri (WebKitWebView *web_view, GArray *argv, GString *result) { + (void) result; + if (argv_idx(argv, 0)) { GString* newuri = g_string_new (argv_idx(argv, 0)); if (g_strstr_len (argv_idx(argv, 0), 11, "javascript:") != NULL) { - run_js(web_view, argv); + run_js(web_view, argv, NULL); return; } if (g_strrstr (argv_idx(argv, 0), "://") == NULL && g_strstr_len (argv_idx(argv, 0), 5, "data:") == NULL) @@ -751,14 +960,109 @@ load_uri (WebKitWebView *web_view, GArray *argv) { } } +/* Javascript*/ + +JSValueRef +js_run_command (JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, + size_t argumentCount, const JSValueRef arguments[], + JSValueRef* exception) { + (void) function; + (void) thisObject; + (void) exception; + + JSStringRef js_result_string; + GString *result = g_string_new(""); + + if (argumentCount >= 1) { + JSStringRef arg = JSValueToStringCopy(ctx, arguments[0], NULL); + size_t arg_size = JSStringGetMaximumUTF8CStringSize(arg); + char ctl_line[arg_size]; + JSStringGetUTF8CString(arg, ctl_line, arg_size); + + parse_cmd_line(ctl_line, result); + + JSStringRelease(arg); + } + js_result_string = JSStringCreateWithUTF8CString(result->str); + + g_string_free(result, TRUE); + + return JSValueMakeString(ctx, js_result_string); +} + +JSStaticFunction js_static_functions[] = { + {"run", js_run_command, kJSPropertyAttributeNone}, +}; + void -run_js (WebKitWebView * web_view, GArray *argv) { +js_init() { + /* This function creates the class and its definition, only once */ + if (!uzbl.js.initialized) { + /* it would be pretty cool to make this dynamic */ + uzbl.js.classdef = kJSClassDefinitionEmpty; + uzbl.js.classdef.staticFunctions = js_static_functions; + + uzbl.js.classref = JSClassCreate(&uzbl.js.classdef); + } +} + + +void +eval_js(WebKitWebView * web_view, gchar *script, GString *result) { + WebKitWebFrame *frame; + JSGlobalContextRef context; + JSObjectRef globalobject; + JSStringRef var_name; + + JSStringRef js_script; + JSValueRef js_result; + JSStringRef js_result_string; + size_t js_result_size; + + js_init(); + + frame = webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(web_view)); + context = webkit_web_frame_get_global_context(frame); + globalobject = JSContextGetGlobalObject(context); + + /* uzbl javascript namespace */ + var_name = JSStringCreateWithUTF8CString("Uzbl"); + JSObjectSetProperty(context, globalobject, var_name, + JSObjectMake(context, uzbl.js.classref, NULL), + kJSClassAttributeNone, NULL); + + /* evaluate the script and get return value*/ + js_script = JSStringCreateWithUTF8CString(script); + js_result = JSEvaluateScript(context, js_script, globalobject, NULL, 0, NULL); + if (js_result && !JSValueIsUndefined(context, js_result)) { + js_result_string = JSValueToStringCopy(context, js_result, NULL); + js_result_size = JSStringGetMaximumUTF8CStringSize(js_result_string); + + if (js_result_size) { + char js_result_utf8[js_result_size]; + JSStringGetUTF8CString(js_result_string, js_result_utf8, js_result_size); + g_string_assign(result, js_result_utf8); + } + + JSStringRelease(js_result_string); + } + + /* cleanup */ + JSObjectDeleteProperty(context, globalobject, var_name, NULL); + + JSStringRelease(var_name); + JSStringRelease(js_script); +} + +void +run_js (WebKitWebView * web_view, GArray *argv, GString *result) { if (argv_idx(argv, 0)) - webkit_web_view_execute_script (web_view, argv_idx(argv, 0)); + eval_js(web_view, argv_idx(argv, 0), result); } void -run_external_js (WebKitWebView * web_view, GArray *argv) { +run_external_js (WebKitWebView * web_view, GArray *argv, GString *result) { + (void) result; if (argv_idx(argv, 0)) { GArray* lines = read_file_by_line (argv_idx (argv, 0)); gchar* js = NULL; @@ -775,7 +1079,7 @@ run_external_js (WebKitWebView * web_view, GArray *argv) { i ++; g_free (line); } - + if (uzbl.state.verbose) printf ("External JavaScript file %s loaded\n", argv_idx(argv, 0)); @@ -784,7 +1088,7 @@ run_external_js (WebKitWebView * web_view, GArray *argv) { g_free (js); js = newjs; } - webkit_web_view_execute_script (web_view, js); + eval_js (web_view, js, result); g_free (js); g_array_free (lines, TRUE); } @@ -799,7 +1103,7 @@ search_text (WebKitWebView *page, GArray *argv, const gboolean forward) { uzbl.state.searchtx = g_strdup(argv_idx(argv, 0)); } } - + if (uzbl.state.searchtx) { if (uzbl.state.verbose) printf ("Searching: %s\n", uzbl.state.searchtx); @@ -809,24 +1113,32 @@ search_text (WebKitWebView *page, GArray *argv, const gboolean forward) { } void -search_forward_text (WebKitWebView *page, GArray *argv) { +search_forward_text (WebKitWebView *page, GArray *argv, GString *result) { + (void) result; search_text(page, argv, TRUE); } void -search_reverse_text (WebKitWebView *page, GArray *argv) { +search_reverse_text (WebKitWebView *page, GArray *argv, GString *result) { + (void) result; search_text(page, argv, FALSE); } void -dehilight (WebKitWebView *page, GArray *argv) { - (void) argv; +dehilight (WebKitWebView *page, GArray *argv, GString *result) { + (void) argv; (void) result; webkit_web_view_set_highlight_text_matches (page, FALSE); } void new_window_load_uri (const gchar * uri) { + if (uzbl.behave.new_window) { + GString *s = g_string_new (""); + g_string_printf(s, "'%s'", uri); + run_handler(uzbl.behave.new_window, s->str); + return; + } GString* to_execute = g_string_new (""); g_string_append_printf (to_execute, "%s --uri '%s'", uzbl.state.executable_path, uri); int i; @@ -845,53 +1157,57 @@ new_window_load_uri (const gchar * uri) { } void -chain (WebKitWebView *page, GArray *argv) { - (void)page; +chain (WebKitWebView *page, GArray *argv, GString *result) { + (void) page; (void) result; gchar *a = NULL; gchar **parts = NULL; - guint i = 0; + guint i = 0; while ((a = argv_idx(argv, i++))) { parts = g_strsplit (a, " ", 2); - parse_command(parts[0], parts[1]); + if (parts[0]) + parse_command(parts[0], parts[1], result); g_strfreev (parts); } } void -keycmd (WebKitWebView *page, GArray *argv) { +keycmd (WebKitWebView *page, GArray *argv, GString *result) { (void)page; (void)argv; - g_string_assign(uzbl.state.keycmd, argv_idx(argv, 0)); + (void)result; + uzbl.state.keycmd = g_strdup(argv_idx(argv, 0)); run_keycmd(FALSE); update_title(); } void -keycmd_nl (WebKitWebView *page, GArray *argv) { +keycmd_nl (WebKitWebView *page, GArray *argv, GString *result) { (void)page; (void)argv; - g_string_assign(uzbl.state.keycmd, argv_idx(argv, 0)); + (void)result; + uzbl.state.keycmd = g_strdup(argv_idx(argv, 0)); run_keycmd(TRUE); update_title(); } void -keycmd_bs (WebKitWebView *page, GArray *argv) { +keycmd_bs (WebKitWebView *page, GArray *argv, GString *result) { + gchar *prev; (void)page; (void)argv; - g_string_truncate(uzbl.state.keycmd, - /* Calculate the number of bytes to truncate... - * This is not simply (len-1) when dealing with UTF-8 string */ - g_utf8_offset_to_pointer(uzbl.state.keycmd->str, - g_utf8_strlen(uzbl.state.keycmd->str, uzbl.state.keycmd->len) - 1) - - uzbl.state.keycmd->str); + (void)result; + int len = strlen(uzbl.state.keycmd); + prev = g_utf8_find_prev_char(uzbl.state.keycmd, uzbl.state.keycmd + len); + if (prev) + uzbl.state.keycmd[prev - uzbl.state.keycmd] = '\0'; update_title(); } void -close_uzbl (WebKitWebView *page, GArray *argv) { +close_uzbl (WebKitWebView *page, GArray *argv, GString *result) { (void)page; (void)argv; + (void)result; gtk_main_quit (); } @@ -914,212 +1230,6 @@ build_progressbar_ascii(int percent) { return g_string_free(bar, FALSE); } - -void -setup_scanner() { - const GScannerConfig scan_config = { - ( - "\t\r\n" - ) /* cset_skip_characters */, - ( - G_CSET_a_2_z - "_#" - G_CSET_A_2_Z - ) /* cset_identifier_first */, - ( - G_CSET_a_2_z - "_0123456789" - G_CSET_A_2_Z - G_CSET_LATINS - G_CSET_LATINC - ) /* cset_identifier_nth */, - ( "" ) /* cpair_comment_single */, - - TRUE /* case_sensitive */, - - FALSE /* skip_comment_multi */, - FALSE /* skip_comment_single */, - FALSE /* scan_comment_multi */, - TRUE /* scan_identifier */, - TRUE /* scan_identifier_1char */, - FALSE /* scan_identifier_NULL */, - TRUE /* scan_symbols */, - FALSE /* scan_binary */, - FALSE /* scan_octal */, - FALSE /* scan_float */, - FALSE /* scan_hex */, - FALSE /* scan_hex_dollar */, - FALSE /* scan_string_sq */, - FALSE /* scan_string_dq */, - TRUE /* numbers_2_int */, - FALSE /* int_2_float */, - FALSE /* identifier_2_string */, - FALSE /* char_2_token */, - FALSE /* symbol_2_token */, - TRUE /* scope_0_fallback */, - FALSE, - TRUE - }; - - uzbl.scan = g_scanner_new(&scan_config); - while(symp->symbol_name) { - g_scanner_scope_add_symbol(uzbl.scan, 0, - symp->symbol_name, - GINT_TO_POINTER(symp->symbol_token)); - symp++; - } -} - -gchar * -expand_template(const char *template, gboolean escape_markup) { - if(!template) return NULL; - - GTokenType token = G_TOKEN_NONE; - GString *ret = g_string_new(""); - char *buf=NULL; - int sym; - - g_scanner_input_text(uzbl.scan, template, strlen(template)); - while(!g_scanner_eof(uzbl.scan) && token != G_TOKEN_LAST) { - token = g_scanner_get_next_token(uzbl.scan); - - if(token == G_TOKEN_SYMBOL) { - sym = GPOINTER_TO_INT(g_scanner_cur_value(uzbl.scan).v_symbol); - switch(sym) { - case SYM_URI: - if(escape_markup) { - buf = uzbl.state.uri ? - g_markup_printf_escaped("%s", uzbl.state.uri) : g_strdup(""); - g_string_append(ret, buf); - g_free(buf); - } - else - g_string_append(ret, uzbl.state.uri ? - uzbl.state.uri : g_strdup("")); - break; - case SYM_LOADPRGS: - buf = itos(uzbl.gui.sbar.load_progress); - g_string_append(ret, buf); - g_free(buf); - break; - case SYM_LOADPRGSBAR: - buf = build_progressbar_ascii(uzbl.gui.sbar.load_progress); - g_string_append(ret, buf); - g_free(buf); - break; - case SYM_TITLE: - if(escape_markup) { - buf = uzbl.gui.main_title ? - g_markup_printf_escaped("%s", uzbl.gui.main_title) : g_strdup(""); - g_string_append(ret, buf); - g_free(buf); - } - else - g_string_append(ret, uzbl.gui.main_title ? - uzbl.gui.main_title : g_strdup("")); - break; - case SYM_SELECTED_URI: - if(escape_markup) { - buf = uzbl.state.selected_url ? - g_markup_printf_escaped("%s", uzbl.state.selected_url) : g_strdup(""); - g_string_append(ret, buf); - g_free(buf); - } - else - g_string_append(ret, uzbl.state.selected_url ? - uzbl.state.selected_url : g_strdup("")); - break; - case SYM_NAME: - buf = itos(uzbl.xwin); - g_string_append(ret, - uzbl.state.instance_name ? uzbl.state.instance_name : buf); - g_free(buf); - break; - case SYM_KEYCMD: - if(escape_markup) { - buf = uzbl.state.keycmd->str ? - g_markup_printf_escaped("%s", uzbl.state.keycmd->str) : g_strdup(""); - g_string_append(ret, buf); - g_free(buf); - } - else - g_string_append(ret, uzbl.state.keycmd->str ? - uzbl.state.keycmd->str : g_strdup("")); - break; - case SYM_MODE: - g_string_append(ret, - uzbl.behave.insert_mode ? - uzbl.behave.insert_indicator : uzbl.behave.cmd_indicator); - break; - case SYM_MSG: - g_string_append(ret, - uzbl.gui.sbar.msg ? uzbl.gui.sbar.msg : ""); - break; - /* useragent syms */ - case SYM_WK_MAJ: - buf = itos(WEBKIT_MAJOR_VERSION); - g_string_append(ret, buf); - g_free(buf); - break; - case SYM_WK_MIN: - buf = itos(WEBKIT_MINOR_VERSION); - g_string_append(ret, buf); - g_free(buf); - break; - case SYM_WK_MIC: - buf = itos(WEBKIT_MICRO_VERSION); - g_string_append(ret, buf); - g_free(buf); - break; - case SYM_SYSNAME: - g_string_append(ret, uzbl.state.unameinfo.sysname); - break; - case SYM_NODENAME: - g_string_append(ret, uzbl.state.unameinfo.nodename); - break; - case SYM_KERNREL: - g_string_append(ret, uzbl.state.unameinfo.release); - break; - case SYM_KERNVER: - g_string_append(ret, uzbl.state.unameinfo.version); - break; - case SYM_ARCHSYS: - g_string_append(ret, uzbl.state.unameinfo.machine); - break; - case SYM_ARCHUZBL: - g_string_append(ret, ARCH); - break; -#ifdef _GNU_SOURCE - case SYM_DOMAINNAME: - g_string_append(ret, uzbl.state.unameinfo.domainname); - break; -#endif - case SYM_COMMIT: - g_string_append(ret, COMMIT); - break; - default: - break; - } - } - else if(token == G_TOKEN_INT) { - g_string_append_printf(ret, "%lu", g_scanner_cur_value(uzbl.scan).v_int); - } - else if(token == G_TOKEN_IDENTIFIER) { - g_string_append(ret, (gchar *)g_scanner_cur_value(uzbl.scan).v_identifier); - } - else if(token == G_TOKEN_CHAR) { - g_string_append_c(ret, (gchar)g_scanner_cur_value(uzbl.scan).v_char); - } - else if(token == G_TOKEN_ERROR) { - g_scanner_error(uzbl.scan, "Token error in template ('%s') at line %d, column %d.", - template, - g_scanner_cur_line(uzbl.scan), - g_scanner_cur_position(uzbl.scan)); - } - } - - return g_string_free(ret, FALSE); -} /* --End Statusbar functions-- */ void @@ -1134,7 +1244,7 @@ run_command (const gchar *command, const guint npre, const gchar **args, const gboolean sync, char **output_stdout) { //command [args] GError *err = NULL; - + GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*)); gchar *pid = itos(getpid()); gchar *xwin = itos(uzbl.xwin); @@ -1152,11 +1262,11 @@ run_command (const gchar *command, const guint npre, const gchar **args, for (i = npre; i < g_strv_length((gchar**)args); i++) sharg_append(a, args[i]); - + gboolean result; if (sync) { if (*output_stdout) *output_stdout = strfree(*output_stdout); - + result = g_spawn_sync(NULL, (gchar **)a->data, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, output_stdout, NULL, NULL, &err); } else result = g_spawn_async(NULL, (gchar **)a->data, NULL, G_SPAWN_SEARCH_PATH, @@ -1191,7 +1301,7 @@ split_quoted(const gchar* src, const gboolean unquote) { /* split on unquoted space, return array of strings; remove a layer of quotes and backslashes if unquote */ if (!src) return NULL; - + gboolean dq = FALSE; gboolean sq = FALSE; GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*)); @@ -1224,30 +1334,30 @@ split_quoted(const gchar* src, const gboolean unquote) { } void -spawn(WebKitWebView *web_view, GArray *argv) { - (void)web_view; +spawn(WebKitWebView *web_view, GArray *argv, GString *result) { + (void)web_view; (void)result; //TODO: allow more control over argument order so that users can have some arguments before the default ones from run_command, and some after if (argv_idx(argv, 0)) run_command(argv_idx(argv, 0), 0, ((const gchar **) (argv->data + sizeof(gchar*))), FALSE, NULL); } void -spawn_sync(WebKitWebView *web_view, GArray *argv) { - (void)web_view; - +spawn_sync(WebKitWebView *web_view, GArray *argv, GString *result) { + (void)web_view; (void)result; + if (argv_idx(argv, 0)) run_command(argv_idx(argv, 0), 0, ((const gchar **) (argv->data + sizeof(gchar*))), TRUE, &uzbl.comm.sync_stdout); } void -spawn_sh(WebKitWebView *web_view, GArray *argv) { - (void)web_view; +spawn_sh(WebKitWebView *web_view, GArray *argv, GString *result) { + (void)web_view; (void)result; if (!uzbl.behave.shell_cmd) { g_printerr ("spawn_sh: shell_cmd is not set!\n"); return; } - + guint i; gchar *spacer = g_strdup(""); g_array_insert_val(argv, 1, spacer); @@ -1262,13 +1372,13 @@ spawn_sh(WebKitWebView *web_view, GArray *argv) { } void -spawn_sh_sync(WebKitWebView *web_view, GArray *argv) { - (void)web_view; +spawn_sh_sync(WebKitWebView *web_view, GArray *argv, GString *result) { + (void)web_view; (void)result; if (!uzbl.behave.shell_cmd) { g_printerr ("spawn_sh_sync: shell_cmd is not set!\n"); return; } - + guint i; gchar *spacer = g_strdup(""); g_array_insert_val(argv, 1, spacer); @@ -1276,7 +1386,7 @@ spawn_sh_sync(WebKitWebView *web_view, GArray *argv) { for (i = 1; i < g_strv_length(cmd); i++) g_array_prepend_val(argv, cmd[i]); - + if (cmd) run_command(cmd[0], g_strv_length(cmd) + 1, (const gchar **) argv->data, TRUE, &uzbl.comm.sync_stdout); g_free (spacer); @@ -1284,22 +1394,32 @@ spawn_sh_sync(WebKitWebView *web_view, GArray *argv) { } void -parse_command(const char *cmd, const char *param) { - Command *c; +parse_command(const char *cmd, const char *param, GString *result) { + CommandInfo *c; if ((c = g_hash_table_lookup(uzbl.behave.commands, cmd))) { - guint i; gchar **par = split_quoted(param, TRUE); GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*)); - if (c[1] == NOSPLIT) { /* don't split */ + if (c->no_split) { /* don't split */ sharg_append(a, param); } else if (par) { for (i = 0; i < g_strv_length(par); i++) sharg_append(a, par[i]); } - c[0](uzbl.gui.web_view, a); + + if (result == NULL) { + GString *result_print = g_string_new(""); + + c->function(uzbl.gui.web_view, a, result_print); + if (result_print->len) + printf("%*s\n", result_print->len, result_print->str); + + g_string_free(result_print, TRUE); + } else { + c->function(uzbl.gui.web_view, a, result); + } g_strfreev (par); g_array_free (a, TRUE); @@ -1329,7 +1449,8 @@ set_proxy_url() { void set_icon() { if(file_exists(uzbl.gui.icon)) { - gtk_window_set_icon_from_file (GTK_WINDOW (uzbl.gui.main_window), uzbl.gui.icon, NULL); + if (uzbl.gui.main_window) + gtk_window_set_icon_from_file (GTK_WINDOW (uzbl.gui.main_window), uzbl.gui.icon, NULL); } else { g_printerr ("Icon \"%s\" not found. ignoring.\n", uzbl.gui.icon); } @@ -1339,14 +1460,13 @@ void cmd_load_uri() { GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*)); g_array_append_val (a, uzbl.state.uri); - load_uri(uzbl.gui.web_view, a); + load_uri(uzbl.gui.web_view, a, NULL); g_array_free (a, TRUE); } -void +void cmd_always_insert_mode() { - uzbl.behave.insert_mode = - uzbl.behave.always_insert_mode ? TRUE : FALSE; + set_insert_mode(uzbl.behave.always_insert_mode); update_title(); } @@ -1385,7 +1505,7 @@ cmd_font_size() { if (uzbl.behave.font_size > 0) { g_object_set (G_OBJECT(ws), "default-font-size", uzbl.behave.font_size, NULL); } - + if (uzbl.behave.monospace_size > 0) { g_object_set (G_OBJECT(ws), "default-monospace-font-size", uzbl.behave.monospace_size, NULL); @@ -1402,7 +1522,7 @@ cmd_zoom_level() { void cmd_disable_plugins() { - g_object_set (G_OBJECT(view_settings()), "enable-plugins", + g_object_set (G_OBJECT(view_settings()), "enable-plugins", !uzbl.behave.disable_plugins, NULL); } @@ -1449,31 +1569,31 @@ cmd_print_bg() { uzbl.behave.print_bg, NULL); } -void +void cmd_style_uri() { g_object_set (G_OBJECT(view_settings()), "user-stylesheet-uri", uzbl.behave.style_uri, NULL); } -void +void cmd_resizable_txt() { g_object_set (G_OBJECT(view_settings()), "resizable-text-areas", uzbl.behave.resizable_txt, NULL); } -void +void cmd_default_encoding() { g_object_set (G_OBJECT(view_settings()), "default-encoding", uzbl.behave.default_encoding, NULL); } -void +void cmd_enforce_96dpi() { g_object_set (G_OBJECT(view_settings()), "enforce-96-dpi", uzbl.behave.enforce_96dpi, NULL); } -void +void cmd_caret_browsing() { g_object_set (G_OBJECT(view_settings()), "enable-caret-browsing", uzbl.behave.caret_browsing, NULL); @@ -1493,6 +1613,19 @@ cmd_cookie_handler() { } void +cmd_new_window() { + gchar **split = g_strsplit(uzbl.behave.new_window, " ", 2); + /* pitfall: doesn't handle chain actions; must the sync_ action manually */ + if ((g_strcmp0(split[0], "sh") == 0) || + (g_strcmp0(split[0], "spawn") == 0)) { + g_free (uzbl.behave.new_window); + uzbl.behave.new_window = + g_strdup_printf("%s %s", split[0], split[1]); + } + g_strfreev (split); +} + +void cmd_fifo_dir() { uzbl.behave.fifo_dir = init_fifo(uzbl.behave.fifo_dir); } @@ -1518,7 +1651,7 @@ cmd_modkey() { buf = g_utf8_strup(uzbl.behave.modkey, -1); uzbl.behave.modmask = 0; - if(uzbl.behave.modkey) + if(uzbl.behave.modkey) g_free(uzbl.behave.modkey); uzbl.behave.modkey = buf; @@ -1534,11 +1667,8 @@ cmd_useragent() { g_free (uzbl.net.useragent); uzbl.net.useragent = NULL; } else { - gchar *ua = expand_template(uzbl.net.useragent, FALSE); - if (ua) - g_object_set(G_OBJECT(uzbl.net.soup_session), SOUP_SESSION_USER_AGENT, ua, NULL); - g_free(uzbl.net.useragent); - uzbl.net.useragent = ua; + g_object_set(G_OBJECT(uzbl.net.soup_session), SOUP_SESSION_USER_AGENT, + uzbl.net.useragent, NULL); } } @@ -1570,19 +1700,21 @@ set_var_value(gchar *name, gchar *val) { char *buf = NULL; if( (c = g_hash_table_lookup(uzbl.comm.proto_var, name)) ) { + if(!c->writeable) return FALSE; + /* check for the variable type */ if (c->type == TYPE_STR) { - buf = expand_vars(val); + buf = expand(val, 0); g_free(*c->ptr); *c->ptr = buf; } else if(c->type == TYPE_INT) { int *ip = (int *)c->ptr; - buf = expand_vars(val); + buf = expand(val, 0); *ip = (int)strtoul(buf, &endp, 10); g_free(buf); } else if (c->type == TYPE_FLOAT) { float *fp = (float *)c->ptr; - buf = expand_vars(val); + buf = expand(val, 0); *fp = strtod(buf, &endp); g_free(buf); } @@ -1607,7 +1739,7 @@ render_html() { enum {M_CMD, M_HTML}; void -parse_cmd_line(const char *ctl_line) { +parse_cmd_line(const char *ctl_line, GString *result) { Behaviour *b = &uzbl.behave; size_t len=0; @@ -1640,7 +1772,7 @@ parse_cmd_line(const char *ctl_line) { else ctlstrip = g_strdup(ctl_line); tokens = g_strsplit(ctlstrip, " ", 2); - parse_command(tokens[0], tokens[1]); + parse_command(tokens[0], tokens[1], result); g_free(ctlstrip); g_strfreev(tokens); } @@ -1648,21 +1780,16 @@ parse_cmd_line(const char *ctl_line) { gchar* build_stream_name(int type, const gchar* dir) { - char *xwin_str; State *s = &uzbl.state; - gchar *str; + gchar *str = NULL; - xwin_str = itos((int)uzbl.xwin); if (type == FIFO) { str = g_strdup_printf - ("%s/uzbl_fifo_%s", dir, - s->instance_name ? s->instance_name : xwin_str); + ("%s/uzbl_fifo_%s", dir, s->instance_name); } else if (type == SOCKET) { str = g_strdup_printf - ("%s/uzbl_socket_%s", dir, - s->instance_name ? s->instance_name : xwin_str ); + ("%s/uzbl_socket_%s", dir, s->instance_name); } - g_free(xwin_str); return str; } @@ -1686,7 +1813,7 @@ control_fifo(GIOChannel *gio, GIOCondition condition) { g_error_free (err); } - parse_cmd_line(ctl_line); + parse_cmd_line(ctl_line, NULL); g_free(ctl_line); return TRUE; @@ -1694,6 +1821,13 @@ control_fifo(GIOChannel *gio, GIOCondition condition) { gchar* init_fifo(gchar *dir) { /* return dir or, on error, free dir and return NULL */ + if (uzbl.comm.fifo_path) { /* get rid of the old fifo if one exists */ + if (unlink(uzbl.comm.fifo_path) == -1) + g_warning ("Fifo: Can't unlink old fifo at %s\n", uzbl.comm.fifo_path); + g_free(uzbl.comm.fifo_path); + uzbl.comm.fifo_path = NULL; + } + GIOChannel *chan = NULL; GError *error = NULL; gchar *path = build_stream_name(FIFO, dir); @@ -1730,7 +1864,7 @@ control_stdin(GIOChannel *gio, GIOCondition condition) { if ( (ret == G_IO_STATUS_ERROR) || (ret == G_IO_STATUS_EOF) ) return FALSE; - parse_cmd_line(ctl_line); + parse_cmd_line(ctl_line, NULL); g_free(ctl_line); return TRUE; @@ -1758,53 +1892,53 @@ create_stdin () { gboolean control_socket(GIOChannel *chan) { struct sockaddr_un remote; - char buffer[512], *ctl_line; - char temp[128]; - int sock, clientsock, n, done; - unsigned int t; - - sock = g_io_channel_unix_get_fd(chan); + unsigned int t = sizeof(remote); + int clientsock; + GIOChannel *clientchan; - memset (buffer, 0, sizeof (buffer)); - - t = sizeof (remote); - clientsock = accept (sock, (struct sockaddr *) &remote, &t); - - done = 0; - do { - memset (temp, 0, sizeof (temp)); - n = recv (clientsock, temp, 128, 0); - if (n == 0) { - buffer[strlen (buffer)] = '\0'; - done = 1; - } - if (!done) - strcat (buffer, temp); - } while (!done); + clientsock = accept (g_io_channel_unix_get_fd(chan), + (struct sockaddr *) &remote, &t); - if (strcmp (buffer, "\n") < 0) { - buffer[strlen (buffer) - 1] = '\0'; - } else { - buffer[strlen (buffer)] = '\0'; + if ((clientchan = g_io_channel_unix_new(clientsock))) { + g_io_add_watch(clientchan, G_IO_IN|G_IO_HUP, + (GIOFunc) control_client_socket, clientchan); } - close (clientsock); - ctl_line = g_strdup(buffer); - parse_cmd_line (ctl_line); -/* - TODO: we should be able to do it with this. but glib errors out with "Invalid argument" + return TRUE; +} + +gboolean +control_client_socket(GIOChannel *clientchan) { + char *ctl_line; + GString *result = g_string_new(""); GError *error = NULL; - gsize len; GIOStatus ret; - ret = g_io_channel_read_line(chan, &ctl_line, &len, NULL, &error); - if (ret == G_IO_STATUS_ERROR) - g_error ("Error reading: %s\n", error->message); + gsize len; - printf("Got line %s (%u bytes) \n",ctl_line, len); - if(ctl_line) { - parse_line(ctl_line); -*/ + ret = g_io_channel_read_line(clientchan, &ctl_line, &len, NULL, &error); + if (ret == G_IO_STATUS_ERROR) { + g_warning ("Error reading: %s\n", error->message); + g_io_channel_shutdown(clientchan, TRUE, &error); + return FALSE; + } else if (ret == G_IO_STATUS_EOF) { + /* shutdown and remove channel watch from main loop */ + g_io_channel_shutdown(clientchan, TRUE, &error); + return FALSE; + } + if (ctl_line) { + parse_cmd_line (ctl_line, result); + g_string_append_c(result, '\n'); + ret = g_io_channel_write_chars (clientchan, result->str, result->len, + &len, &error); + if (ret == G_IO_STATUS_ERROR) { + g_warning ("Error writing: %s", error->message); + } + g_io_channel_flush(clientchan, &error); + } + + if (error) g_error_free (error); + g_string_free(result, TRUE); g_free(ctl_line); return TRUE; } @@ -1865,55 +1999,80 @@ update_title (void) { if (b->show_status) { if (b->title_format_short) { - parsed = expand_template(b->title_format_short, FALSE); - gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed); + parsed = expand(b->title_format_short, 0); + if (uzbl.gui.main_window) + gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed); g_free(parsed); } if (b->status_format) { - parsed = expand_template(b->status_format, TRUE); + parsed = expand(b->status_format, 0); gtk_label_set_markup(GTK_LABEL(uzbl.gui.mainbar_label), parsed); g_free(parsed); } if (b->status_background) { GdkColor color; gdk_color_parse (b->status_background, &color); - //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) - gtk_widget_modify_bg (uzbl.gui.main_window, GTK_STATE_NORMAL, &color); + //labels and hboxes do not draw their own background. applying this on the vbox/main_window is ok as the statusbar is the only affected widget. (if not, we could also use GtkEventBox) + if (uzbl.gui.main_window) + gtk_widget_modify_bg (uzbl.gui.main_window, GTK_STATE_NORMAL, &color); + else if (uzbl.gui.plug) + gtk_widget_modify_bg (GTK_WIDGET(uzbl.gui.plug), GTK_STATE_NORMAL, &color); } } else { if (b->title_format_long) { - parsed = expand_template(b->title_format_long, FALSE); - gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed); + parsed = expand(b->title_format_long, 0); + if (uzbl.gui.main_window) + gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed); g_free(parsed); } } } gboolean +configure_event_cb(GtkWidget* window, GdkEventConfigure* event) { + (void) window; + (void) event; + + retreive_geometry(); + return FALSE; +} + +gboolean key_press_cb (GtkWidget* window, GdkEventKey* event) { //TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further. (void) window; - if (event->type != GDK_KEY_PRESS || event->keyval == GDK_Page_Up || event->keyval == GDK_Page_Down - || 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) + if (event->type != GDK_KEY_PRESS || + event->keyval == GDK_Page_Up || + event->keyval == GDK_Page_Down || + 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) return FALSE; /* turn off insert mode (if always_insert_mode is not used) */ if (uzbl.behave.insert_mode && (event->keyval == GDK_Escape)) { - uzbl.behave.insert_mode = uzbl.behave.always_insert_mode; + set_insert_mode(uzbl.behave.always_insert_mode); update_title(); return TRUE; } - if (uzbl.behave.insert_mode && (((event->state & uzbl.behave.modmask) != uzbl.behave.modmask) || (!uzbl.behave.modmask))) + if (uzbl.behave.insert_mode && + ( ((event->state & uzbl.behave.modmask) != uzbl.behave.modmask) || + (!uzbl.behave.modmask) + ) + ) return FALSE; if (event->keyval == GDK_Escape) { - g_string_truncate(uzbl.state.keycmd, 0); + clear_keycmd(); update_title(); - dehilight(uzbl.gui.web_view, NULL); + dehilight(uzbl.gui.web_view, NULL, NULL); return TRUE; } @@ -1926,7 +2085,9 @@ key_press_cb (GtkWidget* window, GdkEventKey* event) str = gtk_clipboard_wait_for_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)); } if (str) { - g_string_append (uzbl.state.keycmd, str); + GString* keycmd = g_string_new(uzbl.state.keycmd); + g_string_append (keycmd, str); + uzbl.state.keycmd = g_string_free(keycmd, FALSE); update_title (); g_free (str); } @@ -1934,12 +2095,16 @@ key_press_cb (GtkWidget* window, GdkEventKey* event) } if (event->keyval == GDK_BackSpace) - keycmd_bs(NULL, NULL); + keycmd_bs(NULL, NULL, NULL); gboolean key_ret = FALSE; if ((event->keyval == GDK_Return) || (event->keyval == GDK_KP_Enter)) key_ret = TRUE; - if (!key_ret) g_string_append(uzbl.state.keycmd, event->string); + if (!key_ret) { + GString* keycmd = g_string_new(uzbl.state.keycmd); + g_string_append(keycmd, event->string); + uzbl.state.keycmd = g_string_free(keycmd, FALSE); + } run_keycmd(key_ret); update_title(); @@ -1951,9 +2116,9 @@ void run_keycmd(const gboolean key_ret) { /* run the keycmd immediately if it isn't incremental and doesn't take args */ Action *act; - if ((act = g_hash_table_lookup(uzbl.bindings, uzbl.state.keycmd->str))) { - g_string_truncate(uzbl.state.keycmd, 0); - parse_command(act->name, act->param); + if ((act = g_hash_table_lookup(uzbl.bindings, uzbl.state.keycmd))) { + clear_keycmd(); + parse_command(act->name, act->param, NULL); return; } @@ -1961,8 +2126,9 @@ run_keycmd(const gboolean key_ret) { GString* short_keys = g_string_new (""); GString* short_keys_inc = g_string_new (""); guint i; - for (i=0; i<(uzbl.state.keycmd->len); i++) { - g_string_append_c(short_keys, uzbl.state.keycmd->str[i]); + guint len = strlen(uzbl.state.keycmd); + for (i=0; istr); g_string_append_c(short_keys, '_'); g_string_append_c(short_keys_inc, '*'); @@ -1970,15 +2136,15 @@ run_keycmd(const gboolean key_ret) { if (key_ret && (act = g_hash_table_lookup(uzbl.bindings, short_keys->str))) { /* run normal cmds only if return was pressed */ exec_paramcmd(act, i); - g_string_truncate(uzbl.state.keycmd, 0); + clear_keycmd(); break; } else if ((act = g_hash_table_lookup(uzbl.bindings, short_keys_inc->str))) { if (key_ret) /* just quit the incremental command on return */ - g_string_truncate(uzbl.state.keycmd, 0); + clear_keycmd(); else exec_paramcmd(act, i); /* otherwise execute the incremental */ break; } - + g_string_truncate(short_keys, short_keys->len - 1); } g_string_free (short_keys, TRUE); @@ -1987,7 +2153,7 @@ run_keycmd(const gboolean key_ret) { void exec_paramcmd(const Action *act, const guint i) { - GString *parampart = g_string_new (uzbl.state.keycmd->str); + GString *parampart = g_string_new (uzbl.state.keycmd); GString *actionname = g_string_new (""); GString *actionparam = g_string_new (""); g_string_erase (parampart, 0, i+1); @@ -1995,7 +2161,7 @@ exec_paramcmd(const Action *act, const guint i) { g_string_printf (actionname, act->name, parampart->str); if (act->param) g_string_printf (actionparam, act->param, parampart->str); - parse_command(actionname->str, actionparam->str); + parse_command(actionname->str, actionparam->str, NULL); g_string_free(actionname, TRUE); g_string_free(actionparam, TRUE); g_string_free(parampart, TRUE); @@ -2013,7 +2179,7 @@ create_browser () { g->web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ()); gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (g->web_view)); - g_signal_connect (G_OBJECT (g->web_view), "title-changed", G_CALLBACK (title_change_cb), g->web_view); + g_signal_connect (G_OBJECT (g->web_view), "notify::title", G_CALLBACK (title_change_cb), NULL); g_signal_connect (G_OBJECT (g->web_view), "load-progress-changed", G_CALLBACK (progress_change_cb), g->web_view); g_signal_connect (G_OBJECT (g->web_view), "load-committed", G_CALLBACK (load_commit_cb), g->web_view); g_signal_connect (G_OBJECT (g->web_view), "load-started", G_CALLBACK (load_start_cb), g->web_view); @@ -2047,17 +2213,28 @@ create_mainbar () { return g->mainbar; } -static -GtkWidget* create_window () { +GtkWidget* +create_window () { GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size (GTK_WINDOW (window), 800, 600); gtk_widget_set_name (window, "Uzbl browser"); g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy_cb), NULL); g_signal_connect (G_OBJECT (window), "key-press-event", G_CALLBACK (key_press_cb), NULL); + g_signal_connect (G_OBJECT (window), "configure-event", G_CALLBACK (configure_event_cb), NULL); return window; } +GtkPlug* +create_plug () { + GtkPlug* plug = GTK_PLUG (gtk_plug_new (uzbl.state.socket_id)); + g_signal_connect (G_OBJECT (plug), "destroy", G_CALLBACK (destroy_cb), NULL); + g_signal_connect (G_OBJECT (plug), "key-press-event", G_CALLBACK (key_press_cb), NULL); + + return plug; +} + + gchar** inject_handler_args(const gchar *actname, const gchar *origargs, const gchar *newargs) { /* @@ -2066,7 +2243,7 @@ inject_handler_args(const gchar *actname, const gchar *origargs, const gchar *ne come become after the body of the script (in sh) or after the name of the command to execute (in spawn). i.e. sh becomes sh and - span becomes spawn . + spawn becomes spawn . The return value consist of two strings: the action (sh, ...) and its args. @@ -2074,6 +2251,7 @@ inject_handler_args(const gchar *actname, const gchar *origargs, const gchar *ne gets duplicated. */ GArray *rets = g_array_new(TRUE, FALSE, sizeof(gchar*)); + /* Arrr! Here be memory leaks */ gchar *actdup = g_strdup(actname); g_array_append_val(rets, actdup); @@ -2121,7 +2299,7 @@ run_handler (const gchar *act, const gchar *args) { if (g_strcmp0(parts[0], "chain") == 0) { GString *newargs = g_string_new(""); gchar **chainparts = split_quoted(parts[1], FALSE); - + /* for every argument in the chain, inject the handler args and make sure the new parts are wrapped in quotes */ gchar **cp = chainparts; @@ -2129,7 +2307,7 @@ run_handler (const gchar *act, const gchar *args) { gchar *quotless = NULL; gchar **spliced_quotless = NULL; // sigh -_-; gchar **inpart = NULL; - + while (*cp) { if ((**cp == '\'') || (**cp == '\"')) { /* strip old quotes */ quot = **cp; @@ -2139,20 +2317,20 @@ run_handler (const gchar *act, const gchar *args) { spliced_quotless = g_strsplit(quotless, " ", 2); inpart = inject_handler_args(spliced_quotless[0], spliced_quotless[1], args); g_strfreev(spliced_quotless); - + g_string_append_printf(newargs, " %c%s %s%c", quot, inpart[0], inpart[1], quot); g_free(quotless); g_strfreev(inpart); cp++; } - parse_command(parts[0], &(newargs->str[1])); + parse_command(parts[0], &(newargs->str[1]), NULL); g_string_free(newargs, TRUE); g_strfreev(chainparts); - + } else { gchar **inparts = inject_handler_args(parts[0], parts[1], args); - parse_command(inparts[0], inparts[1]); + parse_command(inparts[0], inparts[1], NULL); g_free(inparts[0]); g_free(inparts[1]); } @@ -2221,7 +2399,7 @@ find_xdg_file (int xdg_type, char* filename) { temporary_file = g_strconcat (temporary_string, filename, NULL); } } - + //g_free (temporary_string); - segfaults. if (file_exists (temporary_file)) { @@ -2236,10 +2414,15 @@ settings_init () { Network *n = &uzbl.net; int i; for (i = 0; default_config[i].command != NULL; i++) { - parse_cmd_line(default_config[i].command); + parse_cmd_line(default_config[i].command, NULL); + } + + if (g_strcmp0(s->config_file, "-") == 0) { + s->config_file = NULL; + create_stdin(); } - if (!s->config_file) { + else if (!s->config_file) { s->config_file = find_xdg_file (0, "/uzbl/config"); } @@ -2249,7 +2432,7 @@ settings_init () { gchar* line; while ((line = g_array_index(lines, gchar*, i))) { - parse_cmd_line (line); + parse_cmd_line (line, NULL); i ++; g_free (line); } @@ -2271,7 +2454,7 @@ void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data) soup_message_add_header_handler(msg, "got-headers", "Set-Cookie", G_CALLBACK(save_cookies), NULL); GString *s = g_string_new (""); SoupURI * soup_uri = soup_message_get_uri(msg); - g_string_printf(s, "GET '%s' '%s'", soup_uri->host, soup_uri->path); + g_string_printf(s, "GET '%s' '%s' '%s'", soup_uri->scheme, soup_uri->host, soup_uri->path); run_handler(uzbl.behave.cookie_handler, s->str); if(uzbl.comm.sync_stdout && strcmp (uzbl.comm.sync_stdout, "") != 0) { @@ -2281,7 +2464,7 @@ void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data) } if (uzbl.comm.sync_stdout) uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout); - + g_string_free(s, TRUE); } @@ -2294,7 +2477,7 @@ save_cookies (SoupMessage *msg, gpointer user_data){ cookie = soup_cookie_to_set_cookie_header(ck->data); SoupURI * soup_uri = soup_message_get_uri(msg); GString *s = g_string_new (""); - g_string_printf(s, "PUT '%s' '%s' '%s'", soup_uri->host, soup_uri->path, cookie); + g_string_printf(s, "PUT '%s' '%s' '%s' '%s'", soup_uri->scheme, soup_uri->host, soup_uri->path, cookie); run_handler(uzbl.behave.cookie_handler, s->str); g_free (cookie); g_string_free(s, TRUE); @@ -2425,9 +2608,25 @@ dump_config() { g_hash_table_foreach(uzbl.bindings, dump_key_hash, NULL); } -/** -- MAIN -- **/ -int -main (int argc, char* argv[]) { +void +retreive_geometry() { + int w, h, x, y; + GString *buf = g_string_new(""); + + gtk_window_get_size(GTK_WINDOW(uzbl.gui.main_window), &w, &h); + gtk_window_get_position(GTK_WINDOW(uzbl.gui.main_window), &x, &y); + + g_string_printf(buf, "%dx%d+%d+%d", w, h, x, y); + + if(uzbl.gui.geometry) + g_free(uzbl.gui.geometry); + uzbl.gui.geometry = g_string_free(buf, FALSE); +} + +/* set up gtk, gobject, variable defaults and other things that tests and other + * external applications need to do anyhow */ +void +initialize(int argc, char *argv[]) { gtk_init (&argc, &argv); if (!g_thread_supported ()) g_thread_init (NULL); @@ -2435,20 +2634,22 @@ main (int argc, char* argv[]) { uzbl.state.selected_url = NULL; uzbl.state.searchtx = NULL; - GOptionContext* context = g_option_context_new ("- some stuff here maybe someday"); + GOptionContext* context = g_option_context_new ("[ uri ] - load a uri by default"); g_option_context_add_main_entries (context, entries, NULL); g_option_context_add_group (context, gtk_get_option_group (TRUE)); g_option_context_parse (context, &argc, &argv, NULL); g_option_context_free(context); - - gchar *uri_override = (uzbl.state.uri ? g_strdup(uzbl.state.uri) : NULL); - gboolean verbose_override = uzbl.state.verbose; + + if (uzbl.behave.print_version) { + printf("Commit: %s\n", COMMIT); + exit(0); + } /* initialize hash table */ uzbl.bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_action); uzbl.net.soup_session = webkit_get_default_session(); - uzbl.state.keycmd = g_string_new(""); + uzbl.state.keycmd = g_strdup(""); if(setup_signal(SIGTERM, catch_sigterm) == SIG_ERR) fprintf(stderr, "uzbl: error hooking SIGTERM\n"); @@ -2457,11 +2658,7 @@ main (int argc, char* argv[]) { if(setup_signal(SIGALRM, catch_alrm) == SIG_ERR) fprintf(stderr, "uzbl: error hooking SIGALARM\n"); - - if(uname(&uzbl.state.unameinfo) == -1) - g_printerr("Can't retrieve unameinfo. Your useragent might appear wrong.\n"); - - uzbl.gui.sbar.progress_s = g_strdup("="); + uzbl.gui.sbar.progress_s = g_strdup("="); //TODO: move these to config.h uzbl.gui.sbar.progress_u = g_strdup("·"); uzbl.gui.sbar.progress_w = 10; @@ -2475,30 +2672,54 @@ main (int argc, char* argv[]) { uzbl.behave.insert_indicator = g_strdup("I"); uzbl.behave.cmd_indicator = g_strdup("C"); - setup_scanner(); + uzbl.info.webkit_major = WEBKIT_MAJOR_VERSION; + uzbl.info.webkit_minor = WEBKIT_MINOR_VERSION; + uzbl.info.webkit_micro = WEBKIT_MICRO_VERSION; + uzbl.info.arch = ARCH; + uzbl.info.commit = COMMIT; + commands_hash (); make_var_to_name_hash(); + uzbl.gui.scrolled_win = create_browser(); +} + +#ifndef UZBL_LIBRARY +/** -- MAIN -- **/ +int +main (int argc, char* argv[]) { + initialize(argc, argv); + uzbl.gui.vbox = gtk_vbox_new (FALSE, 0); - uzbl.gui.scrolled_win = create_browser(); create_mainbar(); /* initial packing */ gtk_box_pack_start (GTK_BOX (uzbl.gui.vbox), uzbl.gui.scrolled_win, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (uzbl.gui.vbox), uzbl.gui.mainbar, FALSE, TRUE, 0); - uzbl.gui.main_window = create_window (); - gtk_container_add (GTK_CONTAINER (uzbl.gui.main_window), uzbl.gui.vbox); + if (uzbl.state.socket_id) { + uzbl.gui.plug = create_plug (); + gtk_container_add (GTK_CONTAINER (uzbl.gui.plug), uzbl.gui.vbox); + gtk_widget_show_all (GTK_WIDGET (uzbl.gui.plug)); + } else { + uzbl.gui.main_window = create_window (); + gtk_container_add (GTK_CONTAINER (uzbl.gui.main_window), uzbl.gui.vbox); + gtk_widget_show_all (uzbl.gui.main_window); + uzbl.xwin = GDK_WINDOW_XID (GTK_WIDGET (uzbl.gui.main_window)->window); + } + if(!uzbl.state.instance_name) + uzbl.state.instance_name = itos((int)uzbl.xwin); gtk_widget_grab_focus (GTK_WIDGET (uzbl.gui.web_view)); - gtk_widget_show_all (uzbl.gui.main_window); - uzbl.xwin = GDK_WINDOW_XID (GTK_WIDGET (uzbl.gui.main_window)->window); if (uzbl.state.verbose) { printf("Uzbl start location: %s\n", argv[0]); - printf("window_id %i\n",(int) uzbl.xwin); + if (uzbl.state.socket_id) + printf("plug_id %i\n", gtk_plug_get_id(uzbl.gui.plug)); + else + printf("window_id %i\n",(int) uzbl.xwin); printf("pid %i\n", getpid ()); printf("name: %s\n", uzbl.state.instance_name); } @@ -2509,7 +2730,18 @@ main (int argc, char* argv[]) { uzbl.gui.bar_h = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_h); gtk_widget_set_scroll_adjustments ((GtkWidget*) uzbl.gui.web_view, uzbl.gui.bar_h, uzbl.gui.bar_v); + if(uzbl.gui.geometry) + cmd_set_geometry(); + else + retreive_geometry(); + + gchar *uri_override = (uzbl.state.uri ? g_strdup(uzbl.state.uri) : NULL); + if (argc > 1 && !uzbl.state.uri) + uri_override = g_strdup(argv[1]); + gboolean verbose_override = uzbl.state.verbose; + settings_init (); + set_insert_mode(FALSE); if (!uzbl.behave.show_status) gtk_widget_hide(uzbl.gui.mainbar); @@ -2519,11 +2751,9 @@ main (int argc, char* argv[]) { /* WebInspector */ set_up_inspector(); - create_stdin(); - if (verbose_override > uzbl.state.verbose) uzbl.state.verbose = verbose_override; - + if (uri_override) { set_var_value("uri", uri_override); g_free(uri_override); @@ -2535,5 +2765,6 @@ main (int argc, char* argv[]) { return EXIT_SUCCESS; } +#endif /* vi: set et ts=4: */