X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=uzbl.c;h=7cff70a64eafb90ee7c4889257de7afc66f2ecb1;hb=a7eff065557599d8aa3e605be7d85d9316de2a96;hp=733fef947f045a45b513b920e7e7c4023afcfbde;hpb=d854da32ff575ff21dc6ffc0bc63737a76a7f2a6;p=uzbl-mobile diff --git a/uzbl.c b/uzbl.c index 733fef9..7cff70a 100644 --- a/uzbl.c +++ b/uzbl.c @@ -62,18 +62,18 @@ static Uzbl uzbl; /* commandline arguments (set initial values for the state variables) */ -static const +static const GOptionEntry entries[] = { { "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, "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", 's', 0, G_OPTION_ARG_INT, &uzbl.state.socket_id, "Socket ID", "SOCKET" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; @@ -191,12 +191,41 @@ make_var_to_name_hash() { } /* --- UTILITY FUNCTIONS --- */ + +enum {EXP_ERR, EXP_SIMPLE_VAR, EXP_BRACED_VAR, EXP_EXPR, EXP_JS}; +static 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 + return EXP_SIMPLE_VAR; + +return EXP_ERR; +} + +/* + * recurse == 1: don't expand '@(command)@' + * recurse == 2: don't expand '@@' + */ static 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[2]; + char ret[4096]; + char *vend; + 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,15 +233,51 @@ 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')) ) { - strncpy(ret, s, vend-s); - ret[vend-s] = '\0'; + + switch(etype) { + case EXP_SIMPLE_VAR: + if( (vend = strpbrk(s, end_simple_var)) || + (vend = strchr(s, '\0')) ) { + strncpy(ret, s, vend-s); + ret[vend-s] = '\0'; + } + break; + case EXP_BRACED_VAR: + s++; upto = '}'; + if( (vend = strchr(s, upto)) || + (vend = strchr(s, '\0')) ) { + strncpy(ret, s, vend-s); + ret[vend-s] = '\0'; + } + break; + case EXP_EXPR: + s++; + strcpy(str_end, ")@"); + str_end[2] = '\0'; + if( (vend = strstr(s, str_end)) || + (vend = strchr(s, '\0')) ) { + strncpy(ret, s, vend-s); + ret[vend-s] = '\0'; + } + break; + case EXP_JS: + s++; + strcpy(str_end, ">@"); + str_end[2] = '\0'; + if( (vend = strstr(s, str_end)) || + (vend = strchr(s, '\0')) ) { + strncpy(ret, s, vend-s); + ret[vend-s] = '\0'; + } + break; + } + + 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) g_string_append(buf, (gchar *)*c->ptr); @@ -222,17 +287,49 @@ expand_vars(char *s) { g_free(b); } } - 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) { + 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; } break; + default: g_string_append_c(buf, *s); s++; break; } } + g_string_free(js_ret, TRUE); return g_string_free(buf, FALSE); } @@ -269,9 +366,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); @@ -279,12 +376,12 @@ 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; } @@ -293,7 +390,7 @@ gchar* parseenv (char* string) { extern char** environ; gchar* tmpstr = NULL; int i = 0; - + while (environ[i] != NULL) { gchar** env = g_strsplit (environ[i], "=", 2); @@ -341,7 +438,7 @@ clean_up(void) { g_hash_table_destroy(uzbl.behave.commands); } -/* 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 */ @@ -391,8 +488,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; } static gboolean @@ -445,12 +542,24 @@ download_cb (WebKitWebView *web_view, GObject *download, gpointer user_data) { /* scroll a bar in a given direction */ static void scroll (GtkAdjustment* bar, GArray *argv) { - gdouble amount; gchar *end; + gdouble max_value; + + 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); - 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); + 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); } static void @@ -527,13 +636,13 @@ link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpoin } static 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(); } @@ -694,9 +803,11 @@ static void 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); } @@ -705,7 +816,7 @@ print(WebKitWebView *page, GArray *argv, GString *result) { (void) page; (void) result; gchar* buf; - buf = expand_vars(argv_idx(argv, 0)); + buf = expand(argv_idx(argv, 0), 0); g_string_assign(result, buf); g_free(buf); } @@ -771,7 +882,7 @@ js_run_command (JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, (void) function; (void) thisObject; (void) exception; - + JSStringRef js_result_string; GString *result = g_string_new(""); @@ -809,7 +920,7 @@ js_init() { } -static void +static void eval_js(WebKitWebView * web_view, gchar *script, GString *result) { WebKitWebFrame *frame; JSGlobalContextRef context; @@ -820,20 +931,20 @@ eval_js(WebKitWebView * web_view, gchar *script, GString *result) { 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), + JSObjectMake(context, uzbl.js.classref, NULL), kJSClassAttributeNone, NULL); - - /* evaluate the script and get return value*/ + + /* 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)) { @@ -882,7 +993,7 @@ run_external_js (WebKitWebView * web_view, GArray *argv, GString *result) { i ++; g_free (line); } - + if (uzbl.state.verbose) printf ("External JavaScript file %s loaded\n", argv_idx(argv, 0)); @@ -906,7 +1017,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); @@ -958,7 +1069,7 @@ 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], result); @@ -1241,7 +1352,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); @@ -1259,11 +1370,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, @@ -1298,7 +1409,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*)); @@ -1341,7 +1452,7 @@ spawn(WebKitWebView *web_view, GArray *argv, GString *result) { static void 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); @@ -1354,7 +1465,7 @@ spawn_sh(WebKitWebView *web_view, GArray *argv, GString *result) { g_printerr ("spawn_sh: shell_cmd is not set!\n"); return; } - + guint i; gchar *spacer = g_strdup(""); g_array_insert_val(argv, 1, spacer); @@ -1375,7 +1486,7 @@ spawn_sh_sync(WebKitWebView *web_view, GArray *argv, GString *result) { 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); @@ -1383,7 +1494,7 @@ spawn_sh_sync(WebKitWebView *web_view, GArray *argv, GString *result) { 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); @@ -1451,7 +1562,6 @@ set_icon() { } else { g_printerr ("Icon \"%s\" not found. ignoring.\n", uzbl.gui.icon); } - g_free (uzbl.gui.icon); } static void @@ -1462,7 +1572,7 @@ cmd_load_uri() { g_array_free (a, TRUE); } -static void +static void cmd_always_insert_mode() { uzbl.behave.insert_mode = uzbl.behave.always_insert_mode ? TRUE : FALSE; @@ -1504,7 +1614,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); @@ -1521,7 +1631,7 @@ cmd_zoom_level() { static 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); } @@ -1568,31 +1678,31 @@ cmd_print_bg() { uzbl.behave.print_bg, NULL); } -static void +static void cmd_style_uri() { g_object_set (G_OBJECT(view_settings()), "user-stylesheet-uri", uzbl.behave.style_uri, NULL); } -static void +static void cmd_resizable_txt() { g_object_set (G_OBJECT(view_settings()), "resizable-text-areas", uzbl.behave.resizable_txt, NULL); } -static void +static void cmd_default_encoding() { g_object_set (G_OBJECT(view_settings()), "default-encoding", uzbl.behave.default_encoding, NULL); } -static void +static void cmd_enforce_96dpi() { g_object_set (G_OBJECT(view_settings()), "enforce-96-dpi", uzbl.behave.enforce_96dpi, NULL); } -static void +static void cmd_caret_browsing() { g_object_set (G_OBJECT(view_settings()), "enable-caret-browsing", uzbl.behave.caret_browsing, NULL); @@ -1637,7 +1747,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; @@ -1691,17 +1801,17 @@ set_var_value(gchar *name, gchar *val) { if( (c = g_hash_table_lookup(uzbl.comm.proto_var, name)) ) { /* 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); } @@ -1895,7 +2005,7 @@ control_socket(GIOChannel *chan) { clientsock = accept (g_io_channel_unix_get_fd(chan), (struct sockaddr *) &remote, &t); - + if ((clientchan = g_io_channel_unix_new(clientsock))) { g_io_add_watch(clientchan, G_IO_IN|G_IO_HUP, (GIOFunc) control_client_socket, clientchan); @@ -2009,9 +2119,11 @@ update_title (void) { 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) + //labels and hboxes do not draw their own background. applying this on the vbox 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) { @@ -2112,7 +2224,7 @@ run_keycmd(const gboolean key_ret) { 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); @@ -2147,7 +2259,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); @@ -2265,7 +2377,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; @@ -2273,7 +2385,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; @@ -2283,7 +2395,7 @@ 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); @@ -2293,7 +2405,7 @@ run_handler (const gchar *act, const gchar *args) { 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], NULL); @@ -2365,7 +2477,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)) { @@ -2382,8 +2494,13 @@ settings_init () { for (i = 0; default_config[i].command != NULL; i++) { 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"); } @@ -2425,7 +2542,7 @@ static void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer use } if (uzbl.comm.sync_stdout) uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout); - + g_string_free(s, TRUE); } @@ -2582,7 +2699,7 @@ main (int argc, char* argv[]) { 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; @@ -2669,11 +2786,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);