bring readme a bit more up to date
[uzbl-mobile] / uzbl.c
diff --git a/uzbl.c b/uzbl.c
index 29b59ae..ed9c4be 100644 (file)
--- a/uzbl.c
+++ b/uzbl.c
@@ -32,6 +32,7 @@
 
 #define LENGTH(x) (sizeof x / sizeof x[0])
 #define MAX_BINDINGS 256
+#define _POSIX_SOURCE
 
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
@@ -44,6 +45,7 @@
 #include <sys/time.h>
 #include <webkit/webkit.h>
 #include <libsoup/soup.h>
+#include <JavaScriptCore/JavaScript.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -56,7 +58,6 @@
 #include "config.h"
 
 static Uzbl uzbl;
-typedef void (*Command)(WebKitWebView*, GArray *argv);
 
 
 
@@ -72,6 +73,8 @@ GOptionEntry entries[] =
         "Name of the current instance (defaults to Xorg window id)", "NAME" },
     { "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" },
     { NULL,      0, 0, 0, NULL, NULL, NULL }
 };
 
@@ -113,6 +116,7 @@ const struct {
     { "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)},
@@ -187,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 '@<java script>@'
+ */
 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) {
@@ -200,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);
@@ -218,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);
 }
 
@@ -441,36 +542,48 @@ 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);
+
+    if (*end == '%')
+        value += page_size * amount * 0.01;
+    else
+        value += amount;
+
+    max_value = gtk_adjustment_get_upper(bar) - page_size;
 
-    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 (value > max_value)
+        value = max_value; /* don't scroll past the end of the page */
+
+    gtk_adjustment_set_value (bar, value);
 }
 
 static 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));
 }
 
 static 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));
 }
 
 static 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);
 }
 
 static 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);
 }
 
@@ -485,9 +598,19 @@ cmd_set_status() {
 }
 
 static 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));
+}
+
+static 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);
@@ -513,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();
 }
 
@@ -545,6 +668,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, "");
@@ -587,7 +711,7 @@ log_history_cb () {
 
 
 /* VIEW funcs (little webkit wrappers) */
-#define VIEWFUNC(name) static void view_##name(WebKitWebView *page, GArray *argv){(void)argv; webkit_web_view_##name(page);}
+#define VIEWFUNC(name) static 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)
@@ -598,7 +722,7 @@ VIEWFUNC(go_forward)
 #undef VIEWFUNC
 
 /* -- command to callback/function map for things we cannot attach to any signals */
-static struct {char *name; Command command[2];} cmdlist[] =
+static struct {char *key; CommandInfo value;} cmdlist[] =
 {   /* key                   function      no_split      */
     { "back",               {view_go_back, 0}              },
     { "forward",            {view_go_forward, 0}           },
@@ -611,8 +735,9 @@ static 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}                     },
@@ -620,19 +745,19 @@ static 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}                },
-    { "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}                  }
 };
 
 static void
@@ -642,7 +767,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 -- */
@@ -675,28 +800,30 @@ file_exists (const char * filename) {
 }
 
 static 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);
 }
 
 static 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);
 }
 
 static 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);
@@ -711,8 +838,8 @@ act_dump_config() {
 }
 
 static void
-toggle_insert_mode(WebKitWebView *page, GArray *argv) {
-    (void)page;
+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) {
@@ -728,10 +855,16 @@ toggle_insert_mode(WebKitWebView *page, GArray *argv) {
 }
 
 static 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_strrstr (argv_idx(argv, 0), "://") == NULL)
+        if (g_strstr_len (argv_idx(argv, 0), 11, "javascript:") != NULL) {
+            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)
             g_string_prepend (newuri, "http://");
         /* if we do handle cookies, ask our handler for them */
         webkit_web_view_load_uri (web_view, newuri->str);
@@ -739,14 +872,111 @@ load_uri (WebKitWebView *web_view, GArray *argv) {
     }
 }
 
+
+/* Javascript*/
+
+static 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);
+}
+
+static JSStaticFunction js_static_functions[] = {
+    {"run", js_run_command, kJSPropertyAttributeNone},
+};
+
 static 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);
+    }
+}
+
+
+static 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);
+}
+
+static 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);
 }
 
 static 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;
@@ -772,7 +1002,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);
     }
@@ -797,18 +1027,20 @@ search_text (WebKitWebView *page, GArray *argv, const gboolean forward) {
 }
 
 static void
-search_forward_text (WebKitWebView *page, GArray *argv) {
+search_forward_text (WebKitWebView *page, GArray *argv, GString *result) {
+    (void) result;
     search_text(page, argv, TRUE);
 }
 
 static void
-search_reverse_text (WebKitWebView *page, GArray *argv) {
+search_reverse_text (WebKitWebView *page, GArray *argv, GString *result) {
+    (void) result;
     search_text(page, argv, FALSE);
 }
 
 static 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);
 }
 
@@ -833,48 +1065,55 @@ new_window_load_uri (const gchar * uri) {
 }
 
 static 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;    
     while ((a = argv_idx(argv, i++))) {
         parts = g_strsplit (a, " ", 2);
-        parse_command(parts[0], parts[1]);
+        parse_command(parts[0], parts[1], result);
         g_strfreev (parts);
     }
 }
 
 static void
-keycmd (WebKitWebView *page, GArray *argv) {
+keycmd (WebKitWebView *page, GArray *argv, GString *result) {
     (void)page;
     (void)argv;
+    (void)result;
     g_string_assign(uzbl.state.keycmd, argv_idx(argv, 0));
     run_keycmd(FALSE);
     update_title();
 }
 
 static void
-keycmd_nl (WebKitWebView *page, GArray *argv) {
+keycmd_nl (WebKitWebView *page, GArray *argv, GString *result) {
     (void)page;
     (void)argv;
+    (void)result;
     g_string_assign(uzbl.state.keycmd, argv_idx(argv, 0));
     run_keycmd(TRUE);
     update_title();
 }
 
 static 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, uzbl.state.keycmd->len - 1);
+    (void)result;
+    prev = g_utf8_find_prev_char(uzbl.state.keycmd->str, uzbl.state.keycmd->str + uzbl.state.keycmd->len);
+    if (prev)
+      g_string_truncate(uzbl.state.keycmd, prev - uzbl.state.keycmd->str);
     update_title();
 }
 
 static void
-close_uzbl (WebKitWebView *page, GArray *argv) {
+close_uzbl (WebKitWebView *page, GArray *argv, GString *result) {
     (void)page;
     (void)argv;
+    (void)result;
     gtk_main_quit ();
 }
 
@@ -1110,7 +1349,7 @@ sharg_append(GArray *a, const gchar *str) {
 // make sure that the args string you pass can properly be interpreted (eg properly escaped against whitespace, quotes etc)
 static gboolean
 run_command (const gchar *command, const guint npre, const gchar **args,
-             const gboolean sync, char **stdout) {
+             const gboolean sync, char **output_stdout) {
    //command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl fifo file> <uzbl socket file> [args]
     GError *err = NULL;
     
@@ -1134,10 +1373,10 @@ run_command (const gchar *command, const guint npre, const gchar **args,
     
     gboolean result;
     if (sync) {
-        if (*stdout) *stdout = strfree(*stdout);
+        if (*output_stdout) *output_stdout = strfree(*output_stdout);
         
         result = g_spawn_sync(NULL, (gchar **)a->data, NULL, G_SPAWN_SEARCH_PATH,
-                              NULL, NULL, stdout, NULL, NULL, &err);
+                              NULL, NULL, output_stdout, NULL, NULL, &err);
     } else result = g_spawn_async(NULL, (gchar **)a->data, NULL, G_SPAWN_SEARCH_PATH,
                                   NULL, NULL, NULL, &err);
 
@@ -1151,8 +1390,8 @@ 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(output_stdout) {
+            printf("Stdout: %s\n", *output_stdout);
         }
     }
     if (err) {
@@ -1203,16 +1442,16 @@ split_quoted(const gchar* src, const gboolean unquote) {
 }
 
 static 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);
 }
 
 static 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*))),
@@ -1220,8 +1459,8 @@ spawn_sync(WebKitWebView *web_view, GArray *argv) {
 }
 
 static 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;
@@ -1241,8 +1480,8 @@ spawn_sh(WebKitWebView *web_view, GArray *argv) {
 }
 
 static 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;
@@ -1263,22 +1502,32 @@ spawn_sh_sync(WebKitWebView *web_view, GArray *argv) {
 }
 
 static 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);
 
@@ -1306,10 +1555,21 @@ set_proxy_url() {
 }
 
 static void
+set_icon() {
+    if(file_exists(uzbl.gui.icon)) {
+        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);
+    }
+    g_free (uzbl.gui.icon);
+}
+
+static 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);
 }
 
@@ -1542,18 +1802,18 @@ 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);
-            *fp = strtof(buf, &endp);
+            buf = expand(val, 0);
+            *fp = strtod(buf, &endp);
             g_free(buf);
         }
 
@@ -1577,7 +1837,7 @@ render_html() {
 
 enum {M_CMD, M_HTML};
 static 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;
 
@@ -1610,7 +1870,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);
     }
@@ -1618,9 +1878,9 @@ parse_cmd_line(const char *ctl_line) {
 
 static gchar*
 build_stream_name(int type, const gchar* dir) {
-    char *xwin_str;
+    char *xwin_str = NULL;
     State *s = &uzbl.state;
-    gchar *str;
+    gchar *str = NULL;
 
     xwin_str = itos((int)uzbl.xwin);
     if (type == FIFO) {
@@ -1656,7 +1916,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;
@@ -1680,12 +1940,6 @@ init_fifo(gchar *dir) { /* return dir or, on error, free dir and return NULL */
     GError *error = NULL;
     gchar *path = build_stream_name(FIFO, dir);
 
-    // This extra check is an alternative to recursively calling init_fifo() or using goto 
-    if (file_exists(path)) {
-        if (unlink(path))
-            g_warning ("init_fifo: can't delete %s: %s", path, strerror(errno));
-    }
-
     if (!file_exists(path)) {
         if (mkfifo (path, 0666) == 0) {
             // we don't really need to write to the file, but if we open the file as 'r' we will block here, waiting for a writer to open the file.
@@ -1718,7 +1972,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;
@@ -1746,53 +2000,53 @@ create_stdin () {
 static 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;
+    unsigned int t = sizeof(remote);
+    int clientsock;
+    GIOChannel *clientchan;
 
-    sock = g_io_channel_unix_get_fd(chan);
-
-    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);
-
-    if (strcmp (buffer, "\n") < 0) {
-        buffer[strlen (buffer) - 1] = '\0';
-    } else {
-        buffer[strlen (buffer)] = '\0';
+    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);
     }
-    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;
+}
+
+static 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;
 }
@@ -1854,7 +2108,8 @@ 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);
+            if (uzbl.gui.main_window)
+                gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed);
             g_free(parsed);
         }
         if (b->status_format) {
@@ -1865,13 +2120,17 @@ 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)
-            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 window/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 ((GtkWidget * ) 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);
+            if (uzbl.gui.main_window)
+                gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed);
             g_free(parsed);
         }
     }
@@ -1901,7 +2160,7 @@ key_press_cb (GtkWidget* window, GdkEventKey* event)
     if (event->keyval == GDK_Escape) {
         g_string_truncate(uzbl.state.keycmd, 0);
         update_title();
-        dehilight(uzbl.gui.web_view, NULL);
+        dehilight(uzbl.gui.web_view, NULL, NULL);
         return TRUE;
     }
 
@@ -1922,7 +2181,7 @@ 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))
@@ -1941,7 +2200,7 @@ run_keycmd(const gboolean key_ret) {
     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);
+        parse_command(act->name, act->param, NULL);
         return;
     }
 
@@ -1983,7 +2242,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);
@@ -2001,7 +2260,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);
@@ -2031,24 +2290,31 @@ create_mainbar () {
     gtk_misc_set_alignment (GTK_MISC(g->mainbar_label), 0, 0);
     gtk_misc_set_padding (GTK_MISC(g->mainbar_label), 2, 2);
     gtk_box_pack_start (GTK_BOX (g->mainbar), g->mainbar_label, TRUE, TRUE, 0);
+    g_signal_connect (G_OBJECT (g->mainbar), "key-press-event", G_CALLBACK (key_press_cb), NULL);
     return g->mainbar;
 }
 
 static
 GtkWidget* create_window () {
     GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-    gchar* uzbl_icon = g_strdup(find_xdg_file(1, "/uzbl/uzbl.png"));
     gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
     gtk_widget_set_name (window, "Uzbl browser");
-    gtk_window_set_icon_from_file (GTK_WINDOW (window), uzbl_icon, NULL);
     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_free (uzbl_icon);
-
     return window;
 }
 
+static
+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;
+}
+
+
 static gchar**
 inject_handler_args(const gchar *actname, const gchar *origargs, const gchar *newargs) {
     /*
@@ -2137,13 +2403,13 @@ run_handler (const gchar *act, const gchar *args) {
             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]);
     }
@@ -2227,10 +2493,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");
     }
 
@@ -2240,7 +2511,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);
         }
@@ -2250,7 +2521,7 @@ 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){
@@ -2351,7 +2622,7 @@ inspector_attach_window_cb (WebKitWebInspector* inspector){
 }
 
 static gboolean
-inspector_dettach_window_cb (WebKitWebInspector* inspector){
+inspector_detach_window_cb (WebKitWebInspector* inspector){
     (void) inspector;
     return FALSE;
 }
@@ -2379,8 +2650,8 @@ set_up_inspector() {
     g_signal_connect (G_OBJECT (g->inspector), "show-window", G_CALLBACK (inspector_show_window_cb), NULL);
     g_signal_connect (G_OBJECT (g->inspector), "close-window", G_CALLBACK (inspector_close_window_cb), NULL);
     g_signal_connect (G_OBJECT (g->inspector), "attach-window", G_CALLBACK (inspector_attach_window_cb), NULL);
-    g_signal_connect (G_OBJECT (g->inspector), "dettach-window", G_CALLBACK (inspector_dettach_window_cb), NULL);
-    g_signal_connect (G_OBJECT (g->inspector), "destroy", G_CALLBACK (inspector_inspector_destroyed_cb), NULL);
+    g_signal_connect (G_OBJECT (g->inspector), "detach-window", G_CALLBACK (inspector_detach_window_cb), NULL);
+    g_signal_connect (G_OBJECT (g->inspector), "finished", G_CALLBACK (inspector_inspector_destroyed_cb), NULL);
 
     g_signal_connect (G_OBJECT (g->inspector), "notify::inspected-uri", G_CALLBACK (inspector_uri_changed_cb), NULL);
 }
@@ -2477,17 +2748,25 @@ main (int argc, char* argv[]) {
     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);
+    }
 
     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);
     }
@@ -2508,8 +2787,6 @@ main (int argc, char* argv[]) {
     /* WebInspector */
     set_up_inspector();
 
-    create_stdin();
-
     if (verbose_override > uzbl.state.verbose)
         uzbl.state.verbose = verbose_override;