merge in sm217s cookie code (which is work in progress)
authorDieter Plaetinck <dieter@plaetinck.be>
Wed, 6 May 2009 19:59:48 +0000 (21:59 +0200)
committerDieter Plaetinck <dieter@plaetinck.be>
Wed, 6 May 2009 19:59:48 +0000 (21:59 +0200)
1  2 
.gitignore
uzbl.c
uzbl.h

diff --combined .gitignore
@@@ -1,4 -1,3 +1,5 @@@
  uzbl
  uzblctrl
 -examples/data
 +*~
 +tags
++examples/data
diff --combined uzbl.c
--- 1/uzbl.c
--- 2/uzbl.c
+++ b/uzbl.c
@@@ -1,4 -1,4 +1,4 @@@
- /* -*- c-basic-offset: 4; */
+ /* -*- c-basic-offset: 4; -*- */
  // Original code taken from the example webkit-gtk+ application. see notice below.
  // Modified code is licensed under the GPL 3.  See LICENSE file.
  
@@@ -40,8 -40,8 +40,8 @@@
  #include <sys/stat.h>
  #include <sys/types.h>
  #include <sys/un.h>
 +#include <sys/utsname.h>
  #include <webkit/webkit.h>
 -#include <pthread.h>
  #include <stdio.h>
  #include <string.h>
  #include <unistd.h>
  #include <libsoup/soup.h>
  #include "uzbl.h"
  
 +
 +/* status bar format
 +   TODO: integrate with the config file
 +*/
 +char *status_format =  "<span background=\"darkgreen\" foreground=\"khaki\"> MODE </span> | Cmd: <span background=\"red\" foreground=\"white\">KEYCMD</span> | <span background=\"darkblue\" foreground=\"white\">  <b>TITLE</b>  </span> | LOAD_PROGRESS% <span font_family=\"monospace\">LOAD_PROGRESSBAR</span> | <span foreground=\"darkgreen\">URI</span> | NAME | <span foreground=\"black\" background=\"khaki\"> Uzbl browser </span>";
 +
  /* housekeeping / internal variables */
 -static GtkWidget*     main_window;
 -static GtkWidget*     mainbar;
 -static GtkWidget*     mainbar_label;
 -static GtkScrollbar*  scbar_v;   // Horizontal and Vertical Scrollbar 
 -static GtkScrollbar*  scbar_h;   // (These are still hidden)
 -static GtkAdjustment* bar_v; // Information about document length
 -static GtkAdjustment* bar_h; // and scrolling position
 -static WebKitWebView* web_view;
 -static gchar*         main_title;
  static gchar          selected_url[500] = "\0";
 -static gint           load_progress;
 -static Window         xwin = 0;
 -static char           fifo_path[64];
 -static char           socket_path[108];
  static char           executable_path[500];
  static GString*       keycmd;
 +static gchar          searchtx[500] = "\0";
  
 -/* state variables (initial values coming from command line arguments but may be changed later) */
 -static gchar*   uri         = NULL;
 -static gchar*   config_file = NULL;
 -static gchar    config_file_path[500];
 -static gboolean verbose     = FALSE;
 +static Uzbl uzbl;
  
  /* settings from config: group behaviour */
  static gchar*   history_handler    = NULL;
  static gchar*   fifo_dir           = NULL;
  static gchar*   socket_dir         = NULL;
  static gchar*   download_handler   = NULL;
++static gchar*   cookie_handler     = NULL;
  static gboolean always_insert_mode = FALSE;
  static gboolean show_status        = FALSE;
  static gboolean insert_mode        = FALSE;
@@@ -80,10 -90,7 +81,10 @@@ static gboolean status_top         = FA
  static gchar*   modkey             = NULL;
  static guint    modmask            = 0;
  static guint    http_debug         = 0;
 -static gchar*   cookie_handler     = NULL;
 +
 +/* System info */
 +static struct utsname unameinfo;
 +
  /* settings from config: group bindings, key -> action */
  static GHashTable* bindings;
  
@@@ -93,9 -100,9 +94,9 @@@ static GHashTable* commands
  /* commandline arguments (set initial values for the state variables) */
  static GOptionEntry entries[] =
  {
 -    { "uri",     'u', 0, G_OPTION_ARG_STRING, &uri,         "Uri to load", NULL },
 -    { "verbose", 'v', 0, G_OPTION_ARG_NONE,   &verbose,     "Be verbose",  NULL },
 -    { "config",  'c', 0, G_OPTION_ARG_STRING, &config_file, "Config file", NULL },
 +    { "uri",     'u', 0, G_OPTION_ARG_STRING, &uzbl.state.uri,           "Uri to load", "URI" },
 +    { "name",    'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name, "Name of the current instance", "NAME" },
 +    { "config",  'c', 0, G_OPTION_ARG_STRING, &uzbl.state.config_file,   "Config file", "FILE" },
      { NULL,      0, 0, 0, NULL, NULL, NULL }
  };
  
@@@ -105,21 -112,15 +106,21 @@@ typedef void (*Command)(WebKitWebView*
  static char *XDG_CONFIG_HOME_default[256];
  static char *XDG_CONFIG_DIRS_default = "/etc/xdg";
  
 -/* libsoup stuff - proxy and friends; networking aptions actually */
 -static SoupSession *soup_session;
 -static SoupLogger *soup_logger;
 -static char *proxy_url = NULL;
 -static char *useragent = NULL;
 -static gint max_conns;
 -static gint max_conns_host;
 -static SoupCookieJar *ck;
 -static char* current_req = NULL;
 +
 +/* --- UTILITY FUNCTIONS --- */
 +
 +char *
 +itos(int val) {
 +    char tmp[20];
 +
 +    snprintf(tmp, sizeof(tmp), "%i", val);
 +    return g_strdup(tmp);
 +}
 +
 +static char *
 +str_replace (const char* search, const char* replace, const char* string) {
 +    return g_strjoinv (replace, g_strsplit(string, search, -1));
 +}
  
  /* --- CALLBACKS --- */
  
@@@ -157,7 -158,7 +158,7 @@@ download_cb (WebKitWebView *web_view, G
      if (download_handler) {
          const gchar* uri = webkit_download_get_uri ((WebKitDownload*)download);
          printf("Download -> %s\n",uri);
-         run_command(download_handler, uri);
+         run_command_async(download_handler, uri);
      }
      return (FALSE);
  }
@@@ -179,13 -180,13 +180,13 @@@ scroll (GtkAdjustment* bar, const char 
  static void scroll_vert(WebKitWebView* page, const char *param) {
      (void) page;
  
 -    scroll(bar_v, param);
 +    scroll(uzbl.gui.bar_v, param);
  }
  
  static void scroll_horz(WebKitWebView* page, const char *param) {
      (void) page;
  
 -    scroll(bar_h, param);
 +    scroll(uzbl.gui.bar_h, param);
  }
  
  static void
@@@ -194,9 -195,9 +195,9 @@@ toggle_status_cb (WebKitWebView* page, 
      (void)param;
  
      if (show_status) {
 -        gtk_widget_hide(mainbar);
 +        gtk_widget_hide(uzbl.gui.mainbar);
      } else {
 -        gtk_widget_show(mainbar);
 +        gtk_widget_show(uzbl.gui.mainbar);
      }
      show_status = !show_status;
      update_title();
@@@ -220,9 -221,9 +221,9 @@@ title_change_cb (WebKitWebView* web_vie
      (void) web_view;
      (void) web_frame;
      (void) data;
 -    if (main_title)
 -        g_free (main_title);
 -    main_title = g_strdup (title);
 +    if (uzbl.gui.main_title)
 +        g_free (uzbl.gui.main_title);
 +    uzbl.gui.main_title = g_strdup (title);
      update_title();
  }
  
@@@ -230,7 -231,7 +231,7 @@@ static voi
  progress_change_cb (WebKitWebView* page, gint progress, gpointer data) {
      (void) page;
      (void) data;
 -    load_progress = progress;
 +    uzbl.gui.sbar.load_progress = progress;
      update_title();
  }
  
@@@ -238,9 -239,9 +239,9 @@@ static voi
  load_commit_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
      (void) page;
      (void) data;
 -    free (uri);
 +    free (uzbl.state.uri);
      GString* newuri = g_string_new (webkit_web_frame_get_uri (frame));
 -    uri = g_string_free (newuri, FALSE);
 +    uzbl.state.uri = g_string_free (newuri, FALSE);
  }
  
  static void
@@@ -261,16 -262,15 +262,16 @@@ log_history_cb () 
         strftime (date, 80, "%Y-%m-%d %H:%M:%S", timeinfo);
         GString* args = g_string_new ("");
         g_string_printf (args, "'%s'", date);
-        run_command(history_handler, args->str);
+        run_command_async(history_handler, args->str);
         g_string_free (args, TRUE);
     }
  }
  
 -/* VIEW funcs (little webkit wrappers) */
  
 +/* VIEW funcs (little webkit wrappers) */
  #define VIEWFUNC(name) static void view_##name(WebKitWebView *page, const char *param){(void)param; webkit_web_view_##name(page);}
  VIEWFUNC(reload)
 +VIEWFUNC(reload_bypass_cache)
  VIEWFUNC(stop_loading)
  VIEWFUNC(zoom_in)
  VIEWFUNC(zoom_out)
@@@ -283,22 -283,20 +284,22 @@@ VIEWFUNC(go_forward
  
  static struct {char *name; Command command;} cmdlist[] =
  {
 -    { "back",          view_go_back       },
 -    { "forward",       view_go_forward    },
 -    { "scroll_vert",   scroll_vert        },
 -    { "scroll_horz",   scroll_horz        },
 -    { "reload",        view_reload,       }, //Buggy
 -    { "refresh",       view_reload,       }, /* for convenience, will change */
 -    { "stop",          view_stop_loading, },
 -    { "zoom_in",       view_zoom_in,      }, //Can crash (when max zoom reached?).
 -    { "zoom_out",      view_zoom_out,     },
 -    { "uri",           load_uri           },
 -    { "toggle_status", toggle_status_cb   },
 -    { "spawn",         spawn              },
 -    { "exit",          close_uzbl         },
 -    { "insert_mode",   set_insert_mode    }
 +    { "back",             view_go_back            },
 +    { "forward",          view_go_forward         },
 +    { "scroll_vert",      scroll_vert             },
 +    { "scroll_horz",      scroll_horz             },
 +    { "reload",           view_reload,            }, 
 +    { "reload_ign_cache", view_reload_bypass_cache},
 +    { "stop",             view_stop_loading,      },
 +    { "zoom_in",          view_zoom_in,           }, //Can crash (when max zoom reached?).
 +    { "zoom_out",         view_zoom_out,          },
 +    { "uri",              load_uri                },
 +    { "script",           run_js                  },
 +    { "toggle_status",    toggle_status_cb        },
 +    { "spawn",            spawn                   },
 +    { "exit",             close_uzbl              },
 +    { "search",           search_text             },
 +    { "insert_mode",      set_insert_mode         }
  };
  
  static void
@@@ -359,33 -357,14 +360,34 @@@ load_uri (WebKitWebView * web_view, con
      if (param) {
          GString* newuri = g_string_new (param);
          if (g_strrstr (param, "://") == NULL)
-             g_string_prepend (newuri, "http://"); 
+             g_string_prepend (newuri, "http://");
+               /* if we do handle cookies, ask our handler for them */
          webkit_web_view_load_uri (web_view, newuri->str);
          g_string_free (newuri, TRUE);
      }
  }
  
  static void
 +run_js (WebKitWebView * web_view, const gchar *param) {
 +    if (param)
 +        webkit_web_view_execute_script (web_view, param);
 +}
 +
 +static void
 +search_text (WebKitWebView *page, const char *param) {
 +    if ((param) && (param[0] != '\0')) {
 +        strcpy(searchtx, param);
 +    }
 +    if (searchtx[0] != '\0') {
 +        printf ("Searching: %s\n", searchtx);
 +        webkit_web_view_unmark_text_matches (page);
 +        webkit_web_view_mark_text_matches (page, searchtx, FALSE, 0);
 +        webkit_web_view_set_highlight_text_matches (page, TRUE);
 +        webkit_web_view_search_text (page, searchtx, FALSE, TRUE, TRUE);
 +    }
 +}
 +
 +static void
  new_window_load_uri (const gchar * uri) {
      GString* to_execute = g_string_new ("");
      g_string_append_printf (to_execute, "%s --uri '%s'", executable_path, uri);
@@@ -410,158 -389,14 +412,158 @@@ close_uzbl (WebKitWebView *page, const 
      gtk_main_quit ();
  }
  
 +/* --Statusbar functions-- */
 +static char*
 +build_progressbar_ascii(int percent) {
 +   int width=10;
 +   int i;
 +   double l;
 +   GString *bar = g_string_new("");
 +
 +   l = (double)percent*((double)width/100.);
 +   l = (int)(l+.5)>=(int)l ? l+.5 : l;
 +
 +   g_string_append(bar, "[");
 +   for(i=0; i<(int)l; i++)
 +       g_string_append(bar, "=");
 +          
 +   for(; i<width; i++)
 +       g_string_append(bar, "ยท");
 +   g_string_append(bar, "]");
 +
 +   return g_string_free(bar, FALSE);
 +}
 +
 +static 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 */,
 +             ( "#\n" )    /* 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++;
 +     }
 +}
 +
 +static gchar *
 +parse_status_template(const char *template) {
 +     GTokenType token = G_TOKEN_NONE;
 +     GString *ret = g_string_new("");
 +     gchar *buf=NULL;
 +     int sym;
 +
 +     if(!template)
 +         return NULL;
 +
 +     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 = (int)g_scanner_cur_value(uzbl.scan).v_symbol;
 +             switch(sym) {
 +                 case SYM_URI:
 +                     g_string_append(ret, uzbl.state.uri);
 +                     break;
 +                 case SYM_LOADPRGS:
 +                     g_string_append(ret, itos(uzbl.gui.sbar.load_progress));
 +                     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:
 +                     g_string_append(ret,
 +                         uzbl.gui.main_title?uzbl.gui.main_title:"");
 +                     break;
 +                 case SYM_NAME:
 +                     g_string_append(ret, 
 +                         uzbl.state.instance_name?uzbl.state.instance_name:"" );
 +                     break;
 +                 case SYM_KEYCMD:
 +                     g_string_append(ret, 
 +                         keycmd->str?keycmd->str:"" );
 +                     break;
 +                 case SYM_MODE:
 +                     g_string_append(ret, 
 +                         insert_mode?"[I]":"[C]" );
 +                     break;
 +                 default:
 +                     break;
 +             }
 +         }
 +         else if(token == G_TOKEN_INT) {
 +             g_string_append(ret, itos(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_printf(ret, "%c", g_scanner_cur_value(uzbl.scan).v_char);
 +         }
 +     }
 +
 +     return g_string_free(ret, FALSE);
 +}
 +/* --End Statusbar functions-- */
 +
 +
  // make sure to put '' around args, so that if there is whitespace we can still keep arguments together.
  static gboolean
- run_command(const char *command, const char *args) {
+ run_command_async(const char *command, const char *args) {
     //command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl fifo file> <uzbl socket file> [args]
      GString* to_execute = g_string_new ("");
      gboolean result;
 -    g_string_printf (to_execute, "%s '%s' '%i' '%i' '%s' '%s'", command, config_file, (int) getpid() , (int) xwin, fifo_path, socket_path);
 -    g_string_append_printf (to_execute, " '%s' '%s'", uri, "TODO title here");
 +    g_string_printf (to_execute, "%s '%s' '%i' '%i' '%s' '%s'", 
 +                    command, uzbl.state.config_file, (int) getpid() ,
 +                    (int) uzbl.xwin, uzbl.comm.fifo_path, uzbl.comm.socket_path);
 +    g_string_append_printf (to_execute, " '%s' '%s'", 
 +                    uzbl.state.uri, "TODO title here");
      if(args) {
          g_string_append_printf (to_execute, " %s", args);
      }
      return result;
  }
  
+ static gboolean
+ run_command_sync(const char *command, const char *args, char **stdout) {
+       //command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl fifo file> <uzbl socket file> [args]
+     GString* to_execute = g_string_new ("");
+     gboolean result;
 -    g_string_printf (to_execute, "%s '%s' '%i' '%i' '%s' '%s'", command, config_file, (int) getpid() , (int) xwin, fifo_path, socket_path);
 -    g_string_append_printf (to_execute, " '%s' '%s'", uri, "TODO title here");
++    g_string_printf (to_execute, "%s '%s' '%i' '%i' '%s' '%s'", command, uzbl.state.config_file, (int) getpid() , (int) uzbl.xwin, uzbl.comm.fifo_path, uzbl.comm.socket_path);
++    g_string_append_printf (to_execute, " '%s' '%s'", uzbl.state.uri, "TODO title here");
+     if(args) {
+         g_string_append_printf (to_execute, " %s", args);
+     }
+     result = g_spawn_command_line_sync (to_execute->str, stdout, NULL, NULL, NULL);
+     printf("Called %s.  Result: %s\n", to_execute->str, (result ? "TRUE" : "FALSE" ));
+     g_string_free (to_execute, TRUE);
+     return result;
+ }
  static void
  spawn(WebKitWebView *web_view, const char *param) {
      (void)web_view;
-     run_command(param, NULL);
+     run_command_async(param, NULL);
  }
  
  static void
@@@ -582,7 -433,7 +600,7 @@@ parse_command(const char *cmd, const ch
      Command c;
  
      if ((c = g_hash_table_lookup(commands, cmd)))
 -        c(web_view, param);
 +        c(uzbl.gui.web_view, param);
      else
          fprintf (stderr, "command \"%s\" not understood. ignoring.\n", cmd);
  }
@@@ -603,199 -454,132 +621,199 @@@ parse_line(char *line) 
      g_strfreev(parts);
  }
  
 +enum { FIFO, SOCKET};
 +void
 +build_stream_name(int type) {
 +    char *xwin_str;
 +    State *s = &uzbl.state;
 +
 +    xwin_str = itos((int)uzbl.xwin);
 +    switch(type) {
 +        case FIFO:
 +            if (fifo_dir) {
 +                sprintf (uzbl.comm.fifo_path, "%s/uzbl_fifo_%s", 
 +                                fifo_dir, s->instance_name ? s->instance_name : xwin_str);
 +            } else {
 +                sprintf (uzbl.comm.fifo_path, "/tmp/uzbl_fifo_%s",
 +                                s->instance_name ? s->instance_name : xwin_str);
 +            }
 +            break;
 +
 +        case SOCKET:
 +            if (socket_dir) {
 +                sprintf (uzbl.comm.socket_path, "%s/uzbl_socket_%s",
 +                                socket_dir, s->instance_name ? s->instance_name : xwin_str);
 +            } else {
 +                sprintf (uzbl.comm.socket_path, "/tmp/uzbl_socket_%s",
 +                                s->instance_name ? s->instance_name : xwin_str);
 +            }
 +            break;
 +        default:
 +            break;
 +    }
 +    g_free(xwin_str);
 +}
 +
  static void
 -control_fifo(GIOChannel *fd) {
 +control_fifo(GIOChannel *gio, GIOCondition condition) {
 +    printf("triggered\n");
      gchar *ctl_line;
 -    gsize term_pos;
 +    GIOStatus ret;
 +    GError *err = NULL;
  
 -    if(!fd)
 -       return;
 +    if (condition & G_IO_HUP)
 +        g_error ("Fifo: Read end of pipe died!\n");
  
 -    g_io_channel_read_line(fd, &ctl_line, NULL, &term_pos, NULL);
 -    ctl_line[term_pos] ='\0';
 +    if(!gio)
 +       g_error ("Fifo: GIOChannel broke\n");
  
 -    parse_line(ctl_line);
 +    ret = g_io_channel_read_line(gio, &ctl_line, NULL, NULL, &err);
 +    if (ret == G_IO_STATUS_ERROR)
 +        g_error ("Fifo: Error reading: %s\n", err->message);
  
 +    parse_line(ctl_line);
      g_free(ctl_line);
 -
 +    printf("...done\n");
      return;
  }
  
  static void
  create_fifo() {
      GIOChannel *chan = NULL;
 +    GError *error = NULL;
  
 -    if (fifo_dir) {
 -        sprintf (fifo_path, "%s/uzbl_fifo_%d", fifo_dir, (int) xwin);
 -    } else {
 -        sprintf (fifo_path, "/tmp/uzbl_fifo_%d", (int) xwin);
 +    build_stream_name(FIFO);
 +    if (file_exists(uzbl.comm.fifo_path)) {
 +        g_error ("Fifo: Error when creating %s: File exists\n", uzbl.comm.fifo_path);
 +        return;
      }
 -    printf ("Control fifo opened in %s\n", fifo_path);
 -    if (mkfifo (fifo_path, 0666) == -1) {
 -        printf ("Possible error creating fifo\n");
 +    if (mkfifo (uzbl.comm.fifo_path, 0666) == -1) {
 +        g_error ("Fifo: Error when creating %s: %s\n", uzbl.comm.fifo_path, strerror(errno));
 +    } else {
 +        // 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.
 +        chan = g_io_channel_new_file((gchar *) uzbl.comm.fifo_path, "r+", &error);
 +        if (chan) {
 +            if (!g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_fifo, NULL)) {
 +                g_error ("Fifo: could not add watch on %s\n", uzbl.comm.fifo_path);
 +            } else { 
 +                printf ("Fifo: created successfully as %s\n", uzbl.comm.fifo_path);
 +            }
 +        } else {
 +            g_error ("Fifo: Error while opening: %s\n", error->message);
 +        }
      }
 -
 -    if( (chan = g_io_channel_new_file((gchar *) fifo_path, "r+", NULL)) )
 -        g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_fifo, chan);
      return;
  }
  
  static void
 -*control_socket() {
 -    if (socket_dir) {
 -        sprintf (socket_path, "%s/uzbl_socket_%d", socket_dir, (int) xwin);
 +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);
 +
 +    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 {
 -        sprintf (socket_path, "/tmp/uzbl_socket_%d", (int) xwin);
 +        buffer[strlen (buffer)] = '\0';
      }
 - 
 -    int sock, clientsock, len;
 -    unsigned int t;
 -    struct sockaddr_un local, remote;
 +    close (clientsock);
 +    ctl_line = g_strdup(buffer);
 +    parse_line (ctl_line);
 +
 +/*
 +   TODO: we should be able to do it with this.  but glib errors out with "Invalid argument"
 +    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);
 +
 +    printf("Got line %s (%u bytes) \n",ctl_line, len);
 +    if(ctl_line) {
 +       parse_line(ctl_line);
 +*/
 +
 +    g_free(ctl_line);
 +    return;
 +} 
  
 +static void
 +create_socket() {
 +    GIOChannel *chan = NULL;
 +    int sock, len;
 +    struct sockaddr_un local;
 +
 +    build_stream_name(SOCKET);
      sock = socket (AF_UNIX, SOCK_STREAM, 0);
  
      local.sun_family = AF_UNIX;
 -    strcpy (local.sun_path, socket_path);
 +    strcpy (local.sun_path, uzbl.comm.socket_path);
      unlink (local.sun_path);
  
      len = strlen (local.sun_path) + sizeof (local.sun_family);
      bind (sock, (struct sockaddr *) &local, len);
  
      if (errno == -1) {
 -        printf ("A problem occurred when opening a socket in %s\n", socket_path);
 +        printf ("Socket: Could not open in %s: %s\n", uzbl.comm.socket_path, strerror(errno));
      } else {
 -        printf ("Control socket opened in %s\n", socket_path);
 -    }
 -
 -    listen (sock, 5);
 - 
 -    char buffer[512];
 -    char temp[128];
 -    int done, n;
 -    for(;;) {
 -        memset (buffer, 0, sizeof (buffer));
 -
 -        t          = sizeof (remote);
 -        clientsock = accept (sock, (struct sockaddr *) &remote, &t);
 -        printf ("Connected to client\n");
 -
 -        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);
 +        printf ("Socket: Opened in %s\n", uzbl.comm.socket_path);
 +        listen (sock, 5);
  
 -        if (strcmp (buffer, "\n") < 0) {
 -            buffer[strlen (buffer) - 1] = '\0';
 -        } else {
 -          buffer[strlen (buffer)] = '\0';
 -        }
 -
 -        parse_line (buffer);
 -        close (clientsock);
 +        if( (chan = g_io_channel_unix_new(sock)) )
 +            g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_socket, chan);
      }
 -
 -    return NULL;
 -} 
 - 
 -static void
 -setup_threading () {
 -    pthread_t control_thread;
 -    pthread_create(&control_thread, NULL, control_socket, NULL);
 -    pthread_detach(control_thread);
  }
  
  static void
  update_title (void) {
      GString* string_long = g_string_new ("");
      GString* string_short = g_string_new ("");
 +    char* iname = NULL;
 +    gchar *statln;
 +    int iname_len;
 +    State *s = &uzbl.state;
 +
 +    if(s->instance_name) {
 +            iname_len = strlen(s->instance_name)+4;
 +            iname = malloc(iname_len);
 +            snprintf(iname, iname_len, "<%s> ", s->instance_name);
 +            
 +            g_string_prepend(string_long, iname);
 +            g_string_prepend(string_short, iname);
 +            free(iname);
 +    }
  
      g_string_append_printf(string_long, "%s ", keycmd->str);
      if (!always_insert_mode)
          g_string_append (string_long, (insert_mode ? "[I] " : "[C] "));
 -    if (main_title) {
 -        g_string_append (string_long, main_title);
 -        g_string_append (string_short, main_title);
 +    if (uzbl.gui.main_title) {
 +        g_string_append (string_long, uzbl.gui.main_title);
 +        g_string_append (string_short, uzbl.gui.main_title);
      }
      g_string_append (string_long, " - Uzbl browser");
      g_string_append (string_short, " - Uzbl browser");
 -    if (load_progress < 100)
 -        g_string_append_printf (string_long, " (%d%%)", load_progress);
 -
      if (selected_url[0]!=0) {
          g_string_append_printf (string_long, " -> (%s)", selected_url);
      }
      gchar* title_short = g_string_free (string_short, FALSE);
  
      if (show_status) {
 -        gtk_window_set_title (GTK_WINDOW(main_window), title_short);
 -    gtk_label_set_text(GTK_LABEL(mainbar_label), title_long);
 +        gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), title_short);
 +        statln = parse_status_template(status_format);
 +        gtk_label_set_markup(GTK_LABEL(uzbl.gui.mainbar_label), statln);
 +        g_free(statln);
      } else {
 -        gtk_window_set_title (GTK_WINDOW(main_window), title_long);
 +        gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), title_long);
      }
  
      g_free (title_long);
      g_free (title_short);
  }
 - 
 +
  static gboolean
  key_press_cb (WebKitWebView* page, GdkEventKey* event)
  {
          return TRUE;
      }
  
 -    if (insert_mode && event->state != modmask)
 +    if (insert_mode && ((event->state & modmask) != modmask))
          return FALSE;
  
 -
      if (event->keyval == GDK_Escape) {
          g_string_truncate(keycmd, 0);
 -
          update_title();
 +        return TRUE;
 +    }
  
 +    //Insert without shift - insert from clipboard; Insert with shift - insert from primary
 +    if (event->keyval == GDK_Insert) {
 +        gchar * str;
 +        if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) {
 +            str = gtk_clipboard_wait_for_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY));
 +        } else {
 +            str = gtk_clipboard_wait_for_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)); 
 +        }
 +        if (str) {
 +            g_string_append_printf (keycmd, "%s",  str);
 +            update_title ();
 +            free (str);
 +        }
          return TRUE;
      }
  
 -    g_string_append(keycmd, event->string);
 +    if ((event->keyval == GDK_BackSpace) && (keycmd->len > 0)) {
 +        g_string_truncate(keycmd, keycmd->len - 1);
 +        update_title();
 +        return TRUE;
 +    }
  
 +    if ((event->keyval == GDK_Return) || (event->keyval == GDK_KP_Enter)) {
 +        GString* short_keys = g_string_new ("");
 +        unsigned int i;
 +        for (i=0; i<(keycmd->len); i++) {
 +            g_string_append_c(short_keys, keycmd->str[i]);
 +            g_string_append_c(short_keys, '_');
 +            
 +            //printf("\nTesting string: @%s@\n", short_keys->str);
 +            if ((action = g_hash_table_lookup(bindings, short_keys->str))) {
 +                GString* parampart = g_string_new (keycmd->str);
 +                g_string_erase (parampart, 0, i+1);
 +                //printf("\nParameter: @%s@\n", parampart->str);
 +                GString* actionname = g_string_new ("");
 +                if (action->name)
 +                    g_string_printf (actionname, action->name, parampart->str);
 +                GString* actionparam = g_string_new ("");
 +                if (action->param)
 +                    g_string_printf (actionparam, action->param, parampart->str);
 +                parse_command(actionname->str, actionparam->str);
 +                g_string_free (actionname, TRUE);
 +                g_string_free (actionparam, TRUE);
 +                g_string_free (parampart, TRUE);
 +                g_string_truncate(keycmd, 0);
 +                update_title();
 +            }          
 +
 +            g_string_truncate(short_keys, short_keys->len - 1);
 +        }
 +        g_string_free (short_keys, TRUE);
 +        return (!insert_mode);
 +    }
 +
 +    g_string_append(keycmd, event->string);
      if ((action = g_hash_table_lookup(bindings, keycmd->str))) {
          g_string_truncate(keycmd, 0);
 -
          parse_command(action->name, action->param);
      }
  
  
  static GtkWidget*
  create_browser () {
 +    GUI *g = &uzbl.gui;
 +
      GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_NEVER); //todo: some sort of display of position/total length. like what emacs does
  
 -    web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ());
 -    gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (web_view));
 +    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 (web_view), "title-changed", G_CALLBACK (title_change_cb), web_view);
 -    g_signal_connect (G_OBJECT (web_view), "load-progress-changed", G_CALLBACK (progress_change_cb), web_view);
 -    g_signal_connect (G_OBJECT (web_view), "load-committed", G_CALLBACK (load_commit_cb), web_view);
 -    g_signal_connect (G_OBJECT (web_view), "load-committed", G_CALLBACK (log_history_cb), web_view);
 -    g_signal_connect (G_OBJECT (web_view), "hovering-over-link", G_CALLBACK (link_hover_cb), web_view);
 -    g_signal_connect (G_OBJECT (web_view), "key-press-event", G_CALLBACK (key_press_cb), web_view);
 -    g_signal_connect (G_OBJECT (web_view), "new-window-policy-decision-requested", G_CALLBACK (new_window_cb), web_view); 
 -    g_signal_connect (G_OBJECT (web_view), "download-requested", G_CALLBACK (download_cb), web_view); 
 -    g_signal_connect (G_OBJECT (web_view), "create-web-view", G_CALLBACK (create_web_view_cb), 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), "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-committed", G_CALLBACK (log_history_cb), g->web_view);
 +    g_signal_connect (G_OBJECT (g->web_view), "hovering-over-link", G_CALLBACK (link_hover_cb), g->web_view);
 +    g_signal_connect (G_OBJECT (g->web_view), "key-press-event", G_CALLBACK (key_press_cb), g->web_view);
 +    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);  
  
      return scrolled_window;
  }
  
  static GtkWidget*
  create_mainbar () {
 -    mainbar = gtk_hbox_new (FALSE, 0);
 -    mainbar_label = gtk_label_new ("");  
 -    gtk_misc_set_alignment (GTK_MISC(mainbar_label), 0, 0);
 -    gtk_misc_set_padding (GTK_MISC(mainbar_label), 2, 2);
 -    gtk_box_pack_start (GTK_BOX (mainbar), mainbar_label, TRUE, TRUE, 0);
 -    return mainbar;
 +    GUI *g = &uzbl.gui;
 +
 +    g->mainbar = gtk_hbox_new (FALSE, 0);
 +    g->mainbar_label = gtk_label_new ("");  
 +    gtk_label_set_ellipsize(GTK_LABEL(g->mainbar_label), PANGO_ELLIPSIZE_END);
 +    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);
 +    return g->mainbar;
  }
  
  static
@@@ -963,8 -691,6 +981,8 @@@ add_binding (const gchar *key, const gc
      if (!parts)
          return;
  
 +    //Debug:
 +    printf ("Binding %-10s : %s\n", key, act);
      action = new_action(parts[0], parts[1]);
      g_hash_table_insert(bindings, g_strdup(key), action);
  
@@@ -977,21 -703,19 +995,21 @@@ settings_init () 
      gboolean res  = FALSE;
      char *saveptr;
      gchar** keys = NULL;
 +    State *s = &uzbl.state;
 +    Network *n = &uzbl.net;
  
 -    if (!config_file) {
 +    if (!s->config_file) {
          const char* XDG_CONFIG_HOME = getenv ("XDG_CONFIG_HOME");
          if (! XDG_CONFIG_HOME || ! strcmp (XDG_CONFIG_HOME, "")) {
            XDG_CONFIG_HOME = (char*)XDG_CONFIG_HOME_default;
          }
          printf("XDG_CONFIG_HOME: %s\n", XDG_CONFIG_HOME);
      
 -        strcpy (config_file_path, XDG_CONFIG_HOME);
 -        strcat (config_file_path, "/uzbl/config");
 -        if (file_exists (config_file_path)) {
 -          printf ("Config file %s found.\n", config_file_path);
 -          config_file = &config_file_path[0];
 +        strcpy (s->config_file_path, XDG_CONFIG_HOME);
 +        strcat (s->config_file_path, "/uzbl/config");
 +        if (file_exists (s->config_file_path)) {
 +          printf ("Config file %s found.\n", s->config_file_path);
 +          s->config_file = &s->config_file_path[0];
          } else {
              // Now we check $XDG_CONFIG_DIRS
              char *XDG_CONFIG_DIRS = getenv ("XDG_CONFIG_DIRS");
              char buffer[512];
              strcpy (buffer, XDG_CONFIG_DIRS);
              const gchar* dir = (char *) strtok_r (buffer, ":", &saveptr);
 -            while (dir && ! file_exists (config_file_path)) {
 -                strcpy (config_file_path, dir);
 -                strcat (config_file_path, "/uzbl/config_file_pathig");
 -                if (file_exists (config_file_path)) {
 -                    printf ("Config file %s found.\n", config_file_path);
 -                    config_file = &config_file_path[0];
 +            while (dir && ! file_exists (s->config_file_path)) {
 +                strcpy (s->config_file_path, dir);
 +                strcat (s->config_file_path, "/uzbl/config_file_pathig");
 +                if (file_exists (s->config_file_path)) {
 +                    printf ("Config file %s found.\n", s->config_file_path);
 +                    s->config_file = &s->config_file_path[0];
                  }
                  dir = (char * ) strtok_r (NULL, ":", &saveptr);
              }
          }
      }
  
 -    if (config_file) {
 +    if (s->config_file) {
          config = g_key_file_new ();
 -        res = g_key_file_load_from_file (config, config_file, G_KEY_FILE_NONE, NULL);
 -          if(res) {
 -            printf ("Config %s loaded\n", config_file);
 +        res = g_key_file_load_from_file (config, s->config_file, G_KEY_FILE_NONE, NULL);
 +          if (res) {
 +            printf ("Config %s loaded\n", s->config_file);
            } else {
 -            fprintf (stderr, "Config %s loading failed\n", config_file);
 +            fprintf (stderr, "Config %s loading failed\n", s->config_file);
          }
      } else {
          printf ("No configuration.\n");
      if (res) {
          history_handler    = g_key_file_get_value   (config, "behavior", "history_handler",    NULL);
          download_handler   = g_key_file_get_value   (config, "behavior", "download_handler",   NULL);
++      cookie_handler     = g_key_file_get_string  (config, "behavior", "cookie_handler",     NULL);
          always_insert_mode = g_key_file_get_boolean (config, "behavior", "always_insert_mode", NULL);
          show_status        = g_key_file_get_boolean (config, "behavior", "show_status",        NULL);
          modkey             = g_key_file_get_value   (config, "behavior", "modkey",             NULL);
              socket_dir     = g_key_file_get_value   (config, "behavior", "socket_dir",         NULL);
          keys               = g_key_file_get_keys    (config, "bindings", NULL,                 NULL);
      }
 -    
 +
      printf ("History handler: %s\n",    (history_handler    ? history_handler  : "disabled"));
      printf ("Download manager: %s\n",   (download_handler   ? download_handler : "disabled"));
 -    printf ("Fifo directory: %s\n",     (fifo_dir           ? fifo_dir         : "/tmp"));
 -    printf ("Socket directory: %s\n",   (socket_dir         ? socket_dir       : "/tmp"));
++    printf ("Cookie handler: %s\n",     (cookie_handler     ? cookie_handler   : "disabled"));
 +    printf ("Fifo directory: %s\n",     (fifo_dir           ? fifo_dir         : "disabled"));
 +    printf ("Socket directory: %s\n",   (socket_dir         ? socket_dir       : "disabled"));
      printf ("Always insert mode: %s\n", (always_insert_mode ? "TRUE"           : "FALSE"));
      printf ("Show status: %s\n",        (show_status        ? "TRUE"           : "FALSE"));
      printf ("Status top: %s\n",         (status_top         ? "TRUE"           : "FALSE"));
      }
  
      /* networking options */
 -    proxy_url      = g_key_file_get_value   (config, "network", "proxy_server",       NULL);
 -    http_debug     = g_key_file_get_integer (config, "network", "http_debug",         NULL);
 -    useragent      = g_key_file_get_value   (config, "network", "user-agent",         NULL);
 -    max_conns      = g_key_file_get_integer (config, "network", "max_conns",          NULL);
 -    max_conns_host = g_key_file_get_integer (config, "network", "max_conns_per_host", NULL);
 +    if (res) {
 +        n->proxy_url      = g_key_file_get_value   (config, "network", "proxy_server",       NULL);
 +        http_debug     = g_key_file_get_integer (config, "network", "http_debug",         NULL);
 +        n->useragent      = g_key_file_get_value   (config, "network", "user-agent",         NULL);
 +        n->max_conns      = g_key_file_get_integer (config, "network", "max_conns",          NULL);
 +        n->max_conns_host = g_key_file_get_integer (config, "network", "max_conns_per_host", NULL);
 +    }
  
 -    if(proxy_url){
 -        g_object_set(G_OBJECT(soup_session), SOUP_SESSION_PROXY_URI, soup_uri_new(proxy_url), NULL);
 +    if(n->proxy_url){
 +        g_object_set(G_OBJECT(n->soup_session), SOUP_SESSION_PROXY_URI, soup_uri_new(n->proxy_url), NULL);
      }
        
      if(!(http_debug <= 3)){
          http_debug = 0;
          fprintf(stderr, "Wrong http_debug level, ignoring.\n");
      } else if (http_debug > 0) {
 -        soup_logger = soup_logger_new(http_debug, -1);
 -        soup_session_add_feature(soup_session, SOUP_SESSION_FEATURE(soup_logger));
 +        n->soup_logger = soup_logger_new(http_debug, -1);
 +        soup_session_add_feature(n->soup_session, SOUP_SESSION_FEATURE(n->soup_logger));
      }
        
 -    if(useragent){
 -        g_object_set(G_OBJECT(soup_session), SOUP_SESSION_USER_AGENT, useragent, NULL);
 +    if(n->useragent){
 +        char* newagent  = malloc(1024);
 +
 +        strcpy(newagent, str_replace("%webkit-major%", itos(WEBKIT_MAJOR_VERSION), n->useragent));
 +        strcpy(newagent, str_replace("%webkit-minor%", itos(WEBKIT_MINOR_VERSION), newagent));
 +        strcpy(newagent, str_replace("%webkit-micro%", itos(WEBKIT_MICRO_VERSION), newagent));
 +
 +        if (uname (&unameinfo) == -1) {
 +            printf("Error getting uname info. Not replacing system-related user agent variables.\n");
 +        } else {
 +            strcpy(newagent, str_replace("%sysname%",     unameinfo.sysname, newagent));
 +            strcpy(newagent, str_replace("%nodename%",    unameinfo.nodename, newagent));
 +            strcpy(newagent, str_replace("%kernrel%",     unameinfo.release, newagent));
 +            strcpy(newagent, str_replace("%kernver%",     unameinfo.version, newagent));
 +            strcpy(newagent, str_replace("%arch-system%", unameinfo.machine, newagent));
 +
 +            #ifdef _GNU_SOURCE
 +                strcpy(newagent, str_replace("%domainname%", unameinfo.domainname, newagent));
 +            #endif
 +        }
 +
 +        strcpy(newagent, str_replace("%arch-uzbl%",    ARCH,                       newagent));
 +        strcpy(newagent, str_replace("%commit%",       COMMIT,                     newagent));
 +
 +        n->useragent = malloc(1024);
 +        strcpy(n->useragent, newagent);
 +        g_object_set(G_OBJECT(n->soup_session), SOUP_SESSION_USER_AGENT, n->useragent, NULL);
      }
  
 -    if(max_conns >= 1){
 -        g_object_set(G_OBJECT(soup_session), SOUP_SESSION_MAX_CONNS, max_conns, NULL);
 +    if(n->max_conns >= 1){
 +        g_object_set(G_OBJECT(n->soup_session), SOUP_SESSION_MAX_CONNS, n->max_conns, NULL);
      }
  
 -    if(max_conns_host >= 1){
 -        g_object_set(G_OBJECT(soup_session), SOUP_SESSION_MAX_CONNS_PER_HOST, max_conns_host, NULL);
 +    if(n->max_conns_host >= 1){
 +        g_object_set(G_OBJECT(n->soup_session), SOUP_SESSION_MAX_CONNS_PER_HOST, n->max_conns_host, NULL);
      }
  
 -    printf("Proxy configured: %s\n", proxy_url ? proxy_url : "none");
 +    printf("Proxy configured: %s\n", n->proxy_url ? n->proxy_url : "none");
      printf("HTTP logging level: %d\n", http_debug);
 -    printf("User-agent: %s\n", useragent? useragent : "default");
 -    printf("Maximum connections: %d\n", max_conns ? max_conns : 0);
 -    printf("Maximum connections per host: %d\n", max_conns_host ? max_conns_host: 0);
 +    printf("User-agent: %s\n", n->useragent? n->useragent : "default");
 +    printf("Maximum connections: %d\n", n->max_conns ? n->max_conns : 0);
 +    printf("Maximum connections per host: %d\n", n->max_conns_host ? n->max_conns_host: 0);
 +              
 -      /* om nom nom nom */
 -      cookie_handler = g_key_file_get_string(config, "behavior", "cookie_handler", NULL);
+       if(cookie_handler){
+               /* ck = soup_cookie_jar_new(); */
+               /* soup_session_add_feature(soup_session, SOUP_SESSION_FEATURE(ck)); */
+               /* g_signal_connect(ck, "changed", G_CALLBACK(cookie_recieved_action), NULL); */
 -              g_signal_connect(soup_session, "request-queued", G_CALLBACK(handle_cookies), NULL);
 -              printf("Cookie handler: %s\n", cookie_handler);
++              g_signal_connect(n->soup_session, "request-queued", G_CALLBACK(handle_cookies), NULL);
+       }
+       
+ }
 -static 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);
++static void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data){
++    (void) session;
++    (void) user_data;
++    soup_message_add_header_handler(msg, "got-headers", "Set-Cookie", G_CALLBACK(save_cookies), NULL);
+       
+       /* ask handler for cookies, if there are any, use
+          soup_message_headers_replace (msg->request_headers,
+          "Cookie", cookies);
+          to add them
+       */
+ }
+ static void
 -save_cookies (SoupMessage *msg,
 -                        gpointer     user_data){
 -      GSList *ck;
 -      char *req, *cookie;
 -      for (ck = soup_cookies_from_response(msg); ck; ck = ck->next){
 -              cookie = soup_cookie_to_set_cookie_header(ck->data);
 -              req = malloc(strlen(cookie) + 10);
 -              sprintf(req, "PUT \"%s\"", cookie);
 -              run_command_async(cookie_handler, req);
 -              free(req);
 -              free(cookie);
 -      }
 -      g_slist_free(ck);
++save_cookies (SoupMessage *msg, gpointer user_data){
++    (void) user_data;
++    GSList *ck;
++    char *req, *cookie;
++    for (ck = soup_cookies_from_response(msg); ck; ck = ck->next){
++        cookie = soup_cookie_to_set_cookie_header(ck->data);
++        req = malloc(strlen(cookie) + 10);
++        sprintf(req, "PUT \"%s\"", cookie);
++        run_command_async(cookie_handler, req);
++        free(req);
++        free(cookie);
++    }
++    g_slist_free(ck);
  }
  
  int
@@@ -1171,12 -907,12 +1228,12 @@@ main (int argc, char* argv[]) 
      /* initialize hash table */
      bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_action);
        
 -      soup_session = webkit_get_default_session();
 +      uzbl.net.soup_session = webkit_get_default_session();
      keycmd = g_string_new("");
  
      settings_init ();
      commands_hash ();
+       
      if (always_insert_mode)
          insert_mode = TRUE;
  
      if (!status_top)
          gtk_box_pack_start (GTK_BOX (vbox), create_mainbar (), FALSE, TRUE, 0);
  
 -    main_window = create_window ();
 -    gtk_container_add (GTK_CONTAINER (main_window), vbox);
 +    uzbl.gui.main_window = create_window ();
 +    gtk_container_add (GTK_CONTAINER (uzbl.gui.main_window), vbox);
  
 -    load_uri (web_view, uri);
 +    load_uri (uzbl.gui.web_view, uzbl.state.uri);
  
 -    gtk_widget_grab_focus (GTK_WIDGET (web_view));
 -    gtk_widget_show_all (main_window);
 -    xwin = GDK_WINDOW_XID (GTK_WIDGET (main_window)->window);
 -    printf("window_id %i\n",(int) 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);
 +    printf("window_id %i\n",(int) uzbl.xwin);
      printf("pid %i\n", getpid ());
 +    printf("name: %s\n", uzbl.state.instance_name);
 +
 +    uzbl.gui.scbar_v = (GtkScrollbar*) gtk_vscrollbar_new (NULL);
 +    uzbl.gui.bar_v = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_v);
 +    uzbl.gui.scbar_h = (GtkScrollbar*) gtk_hscrollbar_new (NULL);
 +    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);
  
 -    scbar_v = (GtkScrollbar*) gtk_vscrollbar_new (NULL);
 -    bar_v = gtk_range_get_adjustment((GtkRange*) scbar_v);
 -    scbar_h = (GtkScrollbar*) gtk_hscrollbar_new (NULL);
 -    bar_h = gtk_range_get_adjustment((GtkRange*) scbar_h);
 -    gtk_widget_set_scroll_adjustments ((GtkWidget*) web_view, bar_h, bar_v);
  
      if (!show_status)
 -        gtk_widget_hide(mainbar);
 +        gtk_widget_hide(uzbl.gui.mainbar);
 +    setup_scanner();
  
 -    setup_threading ();
 -    create_fifo ();
 +    if (fifo_dir)
 +        create_fifo ();
 +    if (socket_dir)
 +        create_socket();
  
      gtk_main ();
  
      g_string_free(keycmd, TRUE);
  
 -    unlink (socket_path);
 -    unlink (fifo_path);
 +    if (fifo_dir)
 +        unlink (uzbl.comm.fifo_path);
 +    if (socket_dir)
 +        unlink (uzbl.comm.socket_path);
  
      g_hash_table_destroy(bindings);
      g_hash_table_destroy(commands);
diff --combined uzbl.h
--- 1/uzbl.h
--- 2/uzbl.h
+++ b/uzbl.h
@@@ -1,89 -1,9 +1,89 @@@
 +/* statusbar symbols */
 +enum { SYM_TITLE, SYM_URI, SYM_NAME, 
 +       SYM_LOADPRGS, SYM_LOADPRGSBAR,
 +       SYM_KEYCMD, SYM_MODE};
 +const struct {
 +    gchar *symbol_name;
 +    guint symbol_token;
 +} symbols[] = {
 +    {"NAME",                 SYM_NAME},
 +    {"URI",                  SYM_URI},
 +    {"TITLE",                SYM_TITLE},
 +    {"KEYCMD",               SYM_KEYCMD},
 +    {"MODE",                 SYM_MODE},
 +    {"LOAD_PROGRESS",        SYM_LOADPRGS},
 +    {"LOAD_PROGRESSBAR",     SYM_LOADPRGSBAR},
 +    {NULL,                   0}
 +}, *symp = symbols;
 +
 +/* status bar elements */
 +typedef struct {
 +    gint           load_progress;
 +} StatusBar;
 +
 +/* gui elements */
 +typedef struct {
 +    GtkWidget*     main_window;
 +    GtkWidget*     mainbar;
 +    GtkWidget*     mainbar_label;
 +    GtkScrollbar*  scbar_v;   // Horizontal and Vertical Scrollbar
 +    GtkScrollbar*  scbar_h;   // (These are still hidden)
 +    GtkAdjustment* bar_v; // Information about document length
 +    GtkAdjustment* bar_h; // and scrolling position
 +    WebKitWebView* web_view;
 +    gchar*         main_title;
 +
 +    StatusBar sbar;
 +} GUI;
 +
 +/* external communication*/
 +typedef struct {
 +    char           fifo_path[64];
 +    char           socket_path[108];
 +} Communication;
 +
 +/* internal state */
 +typedef struct {
 +    gchar    *uri;
 +    gchar    *config_file;
 +    gchar    *instance_name;
 +    gchar    config_file_path[500];
 +} State;
 +
 +typedef struct {
 +    SoupSession *soup_session;
 +    SoupLogger *soup_logger;
 +    char *proxy_url;
 +    char *useragent;
 +    gint max_conns;
 +    gint max_conns_host;
 +} Network;
 +
 +
 +/* main uzbl data structure */
 +typedef struct {
 +    GUI     gui;
 +    Communication comm;
 +    State   state;
 +    Network net;
 +    Window  xwin;
 +    GScanner *scan;
 +} Uzbl;
 +
  typedef struct {
      char* name;
      char* param;
  } Action;
  
  
 +
 +/* Functions */
 +static void
 +setup_scanner();
 +
 +char *
 +itos(int val);
 +
  static gboolean
  new_window_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *navigation_action, WebKitWebPolicyDecision *policy_decision, gpointer user_data);
  
@@@ -139,7 -59,10 +139,10 @@@ static voi
  close_uzbl (WebKitWebView *page, const char *param);
  
  static gboolean
- run_command(const char *command, const char *args);
+ run_command_async(const char *command, const char *args);
+ static gboolean
+ run_command_sync(const char *command, const char *args, char **stdout);
  
  static void
  spawn(WebKitWebView *web_view, const char *param);
@@@ -150,21 -73,17 +153,21 @@@ parse_command(const char *cmd, const ch
  static void
  parse_line(char *line);
  
 +void
 +build_stream_name(int type);
 +
  static void
 -control_fifo(GIOChannel *fd);
 +control_fifo(GIOChannel *gio, GIOCondition condition);
  
  static void
  create_fifo();
  
  static void
 -*control_socket();
 - 
 +create_socket();
 +
  static void
 -setup_threading ();
 +control_socket(GIOChannel *chan);
 + 
  
  static void
  update_title (void);
@@@ -187,13 -106,22 +190,19 @@@ add_binding (const gchar *key, const gc
  static void
  settings_init ();
  
 -/* static void */
 -/* cookie_recieved_action (SoupCookieJar *jar, */
 -                                 /* SoupCookie    *old_cookie, */
 -                                 /* SoupCookie    *new_cookie, */
 -                                 /* gpointer       user_data); */
 -/* static void */
 -/* catch_cookies (SoupSession *session, */
 -/*                       SoupMessage *msg, */
 -/*                       gpointer     user_data); */
 -/*                            /\* SoupSocket  *socket, *\/ */
 -/*                            /\* gpointer     user_data); *\/ */
 +static void
 +search_text (WebKitWebView *page, const char *param);
 +
 +static void
 +run_js (WebKitWebView * web_view, const gchar *param);
 +
 +static char *
 +str_replace (const char* search, const char* replace, const char* string);
  
+ static void handle_cookies (SoupSession *session,
+                                                       SoupMessage *msg,
+                                                       gpointer     user_data);
+ static void
+ save_cookies (SoupMessage *msg,
+                         gpointer     user_data);
  /* vi: set et ts=4: */