use stdlib atof() instead of gnu99 strtof() + more sense making example binds for...
[uzbl-mobile] / uzbl.c
diff --git a/uzbl.c b/uzbl.c
index a6b699a..1564192 100644 (file)
--- a/uzbl.c
+++ b/uzbl.c
 #include <sys/utsname.h>
 #include <sys/time.h>
 #include <webkit/webkit.h>
+#include <libsoup/soup.h>
+
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
-#include <string.h>
 #include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <libsoup/soup.h>
 #include <signal.h>
 #include "uzbl.h"
 #include "config.h"
@@ -85,7 +83,7 @@ typedef const struct {
     void (*func)(void);
 } uzbl_cmdprop;
 
-enum {TYPE_INT, TYPE_STR};
+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 }
@@ -97,6 +95,7 @@ const struct {
 /*    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)},
@@ -132,7 +131,8 @@ const struct {
     { "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)},
-    /* exported WebKitWebSettings properties*/
+    /* 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)},
@@ -189,48 +189,44 @@ make_var_to_name_hash() {
 /* --- UTILITY FUNCTIONS --- */
 static gchar *
 expand_vars(char *s) {
-    char ret[256],  /* 256 chars per var name should be safe */
-         *vend;
     uzbl_cmdprop *c;
     char upto = ' ';
+    char ret[256],  *vend;
     GString *buf = g_string_new("");
 
     while(*s) {
-        /* found quotation char */
-        if(*s == '\\') {
-            g_string_append_c(buf, *++s);
-            s++;
-        }
-        /* found variable */
-        else if(*s == '@') {
-            if(*(s+1) == '{') {
-                upto = '}'; s++;
-            }
-            s++;
-            if( (vend = strchr(s, upto)) ||
-                (vend = strchr(s, '\0')) ) {
-                strncpy(ret, s, vend-s);
-                ret[vend-s] = '\0';
-                if( (c = g_hash_table_lookup(uzbl.comm.proto_var, ret)) ) {
-                    if(c->type == TYPE_STR)
-                        g_string_append(buf, (gchar *)*c->ptr);
-                    else if(c->type == TYPE_INT) {
-                        char *b = itos((int)*c->ptr);
-                        g_string_append(buf, b);
-                        g_free(b);
+        switch(*s) {
+            case '\\':
+                g_string_append_c(buf, *++s);
+                s++;
+                break;
+            case '@':
+                if(*(s+1) == '{') {
+                    upto = '}'; s++;
+                }
+                s++;
+                if( (vend = strchr(s, upto)) ||
+                        (vend = strchr(s, '\0')) ) {
+                    strncpy(ret, s, vend-s);
+                    ret[vend-s] = '\0';
+                    if( (c = g_hash_table_lookup(uzbl.comm.proto_var, ret)) ) {
+                        if(c->type == TYPE_STR)
+                            g_string_append(buf, (gchar *)*c->ptr);
+                        else if(c->type == TYPE_INT) {
+                            char *b = itos((int)*c->ptr);
+                            g_string_append(buf, b);
+                            g_free(b);
+                        }
                     }
+                    if(upto == ' ') s = vend;
+                    else s = vend+1;
+                    upto = ' ';
                 }
-                if(upto == ' ')
-                    s = vend;
-                else
-                    s = vend+1;
-                upto = ' ';
-            }
-        }
-        /* every other char */
-        else {
-            g_string_append_c(buf, *s);
-            s++;
+                break;
+            default:
+                g_string_append_c(buf, *s);
+                s++;
+                break;
         }
     }
     return g_string_free(buf, FALSE);
@@ -395,6 +391,23 @@ new_window_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequ
     return (FALSE);
 }
 
+static gboolean
+mime_policy_cb(WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, gchar *mime_type,  WebKitWebPolicyDecision *policy_decision, gpointer user_data) {
+    (void) frame;
+    (void) request;
+    (void) user_data;
+
+    /* If we can display it, let's display it... */
+    if (webkit_web_view_can_show_mime_type (web_view, mime_type)) {
+        webkit_web_policy_decision_use (policy_decision);
+        return TRUE;
+    }
+
+    /* ...everything we can't displayed is downloaded */
+    webkit_web_policy_decision_download (policy_decision);
+    return TRUE;
+}
+
 WebKitWebView*
 create_web_view_cb (WebKitWebView  *web_view, WebKitWebFrame *frame, gpointer user_data) {
     (void) web_view;
@@ -532,6 +545,7 @@ 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?
     if (uzbl.behave.load_start_handler)
         run_handler(uzbl.behave.load_start_handler, "");
@@ -585,7 +599,6 @@ VIEWFUNC(go_forward)
 #undef VIEWFUNC
 
 /* -- command to callback/function map for things we cannot attach to any signals */
-// TODO: reload
 static struct {char *name; Command command[2];} cmdlist[] =
 {   /* key                   function      no_split      */
     { "back",               {view_go_back, 0}              },
@@ -613,13 +626,14 @@ static struct {char *name; Command command[2];} cmdlist[] =
     { "dehilight",          {dehilight, 0}                 },
     { "toggle_insert_mode", {toggle_insert_mode, 0}        },
     { "set",                {set_var, NOSPLIT}             },
-    { "get",                {get_var, NOSPLIT}             },
+    //{ "get",                {get_var, NOSPLIT}             },
     { "bind",               {act_bind, NOSPLIT}            },
     { "dump_config",        {act_dump_config, 0}           },
     { "keycmd",             {keycmd, NOSPLIT}              },
     { "keycmd_nl",          {keycmd_nl, NOSPLIT}           },
     { "keycmd_bs",          {keycmd_bs, 0}                 },
-    { "chain",              {chain, 0}                     }
+    { "chain",              {chain, 0}                     },
+    { "print",              {print, NOSPLIT}               }
 };
 
 static void
@@ -672,9 +686,13 @@ set_var(WebKitWebView *page, GArray *argv) {
 }
 
 static void
-get_var(WebKitWebView *page, GArray *argv) {
+print(WebKitWebView *page, GArray *argv) {
     (void) page;
-    get_var_value(argv_idx(argv, 0));
+    gchar* buf;
+
+    buf = expand_vars(argv_idx(argv, 0));
+    puts(buf);
+    g_free(buf);
 }
 
 static void
@@ -714,7 +732,11 @@ static void
 load_uri (WebKitWebView *web_view, GArray *argv) {
     if (argv_idx(argv, 0)) {
         GString* newuri = g_string_new (argv_idx(argv, 0));
-        if (g_strrstr (argv_idx(argv, 0), "://") == NULL)
+        if (g_strstr_len (argv_idx(argv, 0), 11, "javascript:") != NULL) {
+            run_js(web_view, argv);
+            return;
+        }
+        if (g_strrstr (argv_idx(argv, 0), "://") == NULL && g_strstr_len (argv_idx(argv, 0), 5, "data:") == NULL)
             g_string_prepend (newuri, "http://");
         /* if we do handle cookies, ask our handler for them */
         webkit_web_view_load_uri (web_view, newuri->str);
@@ -950,7 +972,7 @@ expand_template(const char *template, gboolean escape_markup) {
          token = g_scanner_get_next_token(uzbl.scan);
 
          if(token == G_TOKEN_SYMBOL) {
-             sym = (int)g_scanner_cur_value(uzbl.scan).v_symbol;
+             sym = GPOINTER_TO_INT(g_scanner_cur_value(uzbl.scan).v_symbol);
              switch(sym) {
                  case SYM_URI:
                      if(escape_markup) {
@@ -1134,6 +1156,9 @@ run_command (const gchar *command, const guint npre, const gchar **args,
         g_string_append_printf(s, " -- result: %s", (result ? "true" : "false"));
         printf("%s\n", s->str);
         g_string_free(s, TRUE);
+        if(stdout) {
+            printf("Stdout: %s\n", *stdout);
+        }
     }
     if (err) {
         g_printerr("error on run_command: %s\n", err->message);
@@ -1266,19 +1291,6 @@ parse_command(const char *cmd, const char *param) {
         g_printerr ("command \"%s\" not understood. ignoring.\n", cmd);
 }
 
-static gboolean
-get_var_value(const gchar *name) {
-    uzbl_cmdprop *c;
-
-    if( (c = g_hash_table_lookup(uzbl.comm.proto_var, name)) ) {
-        if(c->type == TYPE_STR)
-            printf("VAR: %s VALUE: (%s)\n", name, (char *)*c->ptr);
-        else if(c->type == TYPE_INT)
-            printf("VAR: %s VALUE: %d\n", name, (int)*c->ptr);
-    }
-    return TRUE;
-}
-
 static void
 set_proxy_url() {
     SoupURI *suri;
@@ -1359,6 +1371,11 @@ cmd_font_size() {
 }
 
 static void
+cmd_zoom_level() {
+    webkit_web_view_set_zoom_level (uzbl.gui.web_view, uzbl.behave.zoom_level);
+}
+
+static void
 cmd_disable_plugins() {
     g_object_set (G_OBJECT(view_settings()), "enable-plugins", 
             !uzbl.behave.disable_plugins, NULL);
@@ -1538,6 +1555,11 @@ set_var_value(gchar *name, gchar *val) {
             buf = expand_vars(val);
             *ip = (int)strtoul(buf, &endp, 10);
             g_free(buf);
+        } else if (c->type == TYPE_FLOAT) {
+            float *fp = (float *)c->ptr;
+            buf = expand_vars(val);
+            *fp = atof(buf);
+            g_free(buf);
         }
 
         /* invoke a command specific function */
@@ -1586,9 +1608,10 @@ parse_cmd_line(const char *ctl_line) {
     else { /* parse a command */
         gchar *ctlstrip;
         gchar **tokens = NULL;
+        len = strlen(ctl_line);
 
-        if (ctl_line[strlen(ctl_line) - 1] == '\n') /* strip trailing newline */
-            ctlstrip = g_strndup(ctl_line, strlen(ctl_line) - 1);
+        if (ctl_line[len - 1] == '\n') /* strip trailing newline */
+            ctlstrip = g_strndup(ctl_line, len - 1);
         else ctlstrip = g_strdup(ctl_line);
 
         tokens = g_strsplit(ctlstrip, " ", 2);
@@ -1987,6 +2010,7 @@ create_browser () {
     g_signal_connect (G_OBJECT (g->web_view), "new-window-policy-decision-requested", G_CALLBACK (new_window_cb), g->web_view);
     g_signal_connect (G_OBJECT (g->web_view), "download-requested", G_CALLBACK (download_cb), g->web_view);
     g_signal_connect (G_OBJECT (g->web_view), "create-web-view", G_CALLBACK (create_web_view_cb), g->web_view);
+    g_signal_connect (G_OBJECT (g->web_view), "mime-type-policy-decision-requested", G_CALLBACK (mime_policy_cb), g->web_view);
 
     return scrolled_window;
 }
@@ -2134,6 +2158,8 @@ add_binding (const gchar *key, const gchar *act) {
         printf ("Binding %-10s : %s\n", key, act);
     action = new_action(parts[0], parts[1]);
 
+    if (g_hash_table_remove (uzbl.bindings, key))
+        g_warning ("Overwriting existing binding for \"%s\"", key);
     g_hash_table_replace(uzbl.bindings, g_strdup(key), action);
     g_strfreev(parts);
 }
@@ -2217,13 +2243,14 @@ settings_init () {
             printf ("No configuration file loaded.\n");
     }
 
-    g_signal_connect(n->soup_session, "request-queued", G_CALLBACK(handle_cookies), NULL);
+    g_signal_connect_after(n->soup_session, "request-started", G_CALLBACK(handle_cookies), NULL);
 }
 
 static void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data){
     (void) session;
     (void) user_data;
-    if (!uzbl.behave.cookie_handler) return;
+    if (!uzbl.behave.cookie_handler)
+         return;
 
     soup_message_add_header_handler(msg, "got-headers", "Set-Cookie", G_CALLBACK(save_cookies), NULL);
     GString *s = g_string_new ("");
@@ -2231,10 +2258,13 @@ static void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer use
     g_string_printf(s, "GET '%s' '%s'", soup_uri->host, soup_uri->path);
     run_handler(uzbl.behave.cookie_handler, s->str);
 
-    if(uzbl.comm.sync_stdout)
-        soup_message_headers_replace (msg->request_headers, "Cookie", uzbl.comm.sync_stdout);
-    //printf("stdout: %s\n", uzbl.comm.sync_stdout);   // debugging
-    if (uzbl.comm.sync_stdout) uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
+    if(uzbl.comm.sync_stdout && strcmp (uzbl.comm.sync_stdout, "") != 0) {
+        char *p = strchr(uzbl.comm.sync_stdout, '\n' );
+        if ( p != NULL ) *p = '\0';
+        soup_message_headers_replace (msg->request_headers, "Cookie", (const char *) uzbl.comm.sync_stdout);
+    }
+    if (uzbl.comm.sync_stdout)
+        uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
         
     g_string_free(s, TRUE);
 }
@@ -2394,6 +2424,7 @@ main (int argc, char* argv[]) {
     g_option_context_free(context);
     
     gchar *uri_override = (uzbl.state.uri ? g_strdup(uzbl.state.uri) : NULL);
+    gboolean verbose_override = uzbl.state.verbose;
 
     /* initialize hash table */
     uzbl.bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_action);
@@ -2472,6 +2503,9 @@ main (int argc, char* argv[]) {
 
     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);