+#include "config.h"
+
+void
+cleanup(void) {
+ while(clients)
+ destroyclient(clients);
+}
+
+void
+proccookies(SoupMessage *m, Client *c) {
+ GSList *l;
+ SoupCookie *co;
+ long t;
+
+ rereadcookies();
+ for (l = soup_cookies_from_response(m); l; l = l->next){
+ co = (SoupCookie *)l->data;
+ t = co->expires ? soup_date_to_time_t(co->expires) : 0;
+ setcookie(co->name, co->value, co->domain, co->value, t);
+ }
+ g_slist_free(l);
+}
+
+void
+clipboard(Client *c, const Arg *arg) {
+ gboolean paste = *(gboolean *)arg;
+ if(paste)
+ gtk_clipboard_request_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), pasteurl, c);
+ else
+ gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), webkit_web_view_get_uri(c->view), -1);
+}
+
+void
+destroyclient(Client *c) {
+ Client *p;
+
+ gtk_widget_destroy(GTK_WIDGET(webkit_web_view_new()));
+ gtk_widget_destroy(c->scroll);
+ gtk_widget_destroy(c->urlbar);
+ gtk_widget_destroy(c->searchbar);
+ gtk_widget_destroy(c->vbox);
+ gtk_widget_destroy(c->win);
+ for(p = clients; p && p->next != c; p = p->next);
+ if(p)
+ p->next = c->next;
+ else
+ clients = c->next;
+ free(c);
+ if(clients == NULL)
+ gtk_main_quit();
+}
+
+void
+destroywin(GtkWidget* w, Client *c) {
+ destroyclient(c);
+}
+
+void
+die(char *str) {
+ fputs(str, stderr);
+ exit(EXIT_FAILURE);
+}
+
+void
+drawindicator(Client *c) {
+ GtkWidget *w;
+ gint width;
+ GdkGC *gc;
+ gchar *uri;
+ GdkColor fg;
+
+
+ uri = geturi(c);
+ w = c->indicator;
+ width = c->progress * w->allocation.width / 100;
+
+ gc = gdk_gc_new(w->window);
+
+ gdk_color_parse(strstr(uri, "https://") == uri ?
+ progress_trust : progress, &fg);
+ gdk_gc_set_rgb_fg_color(gc, &fg);
+ gdk_draw_rectangle(w->window,
+ w->style->bg_gc[GTK_WIDGET_STATE(w)],
+ TRUE,
+ 0, 0, w->allocation.width, w->allocation.height);
+ gdk_draw_rectangle(w->window,
+ gc,
+ TRUE,
+ 0, 0, width, w->allocation.height);
+ g_object_unref(gc);/*g_free(gc);*/
+}
+
+gboolean
+exposeindicator(GtkWidget *w, GdkEventExpose *e, Client *c) {
+ drawindicator(c);
+ return TRUE;
+}
+
+void
+download(WebKitDownload *o, GParamSpec *pspec, Client *c) {
+ WebKitDownloadStatus status;
+
+ status = webkit_download_get_status(c->download);
+ if(status == WEBKIT_DOWNLOAD_STATUS_STARTED || status == WEBKIT_DOWNLOAD_STATUS_CREATED) {
+ c->progress = (int)(webkit_download_get_progress(c->download)*100);
+ }
+ update(c, NULL);
+}
+
+gboolean
+initdownload(WebKitWebView *view, WebKitDownload *o, Client *c) {
+ const gchar *home, *filename;
+ gchar *uri, *path, *html;
+
+ stop(c, NULL);
+ c->download = o;
+ home = g_get_home_dir();
+ filename = webkit_download_get_suggested_filename(o);
+ path = g_build_filename(home, ".surf", "dl",
+ filename, NULL);
+ uri = g_strconcat("file://", path, NULL);
+ webkit_download_set_destination_uri(c->download, uri);
+ c->progress = 0;
+ g_free(uri);
+ html = g_strdup_printf("Download <b>%s</b>...", filename);
+ webkit_web_view_load_html_string(c->view, html,
+ webkit_download_get_uri(c->download));
+ g_signal_connect(c->download, "notify::progress", G_CALLBACK(download), c);
+ g_signal_connect(c->download, "notify::status", G_CALLBACK(download), c);
+ webkit_download_start(c->download);
+ update(c, filename);
+ g_free(html);
+ return TRUE;
+}
+
+gchar *
+geturi(Client *c) {
+ gchar *uri;
+
+ if(!(uri = (gchar *)webkit_web_view_get_uri(c->view)))
+ uri = g_strdup("about:blank");
+ return uri;
+}
+
+void
+hidesearch(Client *c, const Arg *arg) {
+ gtk_widget_hide(c->searchbar);
+ gtk_widget_grab_focus(GTK_WIDGET(c->view));
+}
+
+void
+hideurl(Client *c, const Arg *arg) {
+ gtk_widget_hide(c->urlbar);
+ gtk_widget_grab_focus(GTK_WIDGET(c->view));
+}
+
+gboolean
+keypress(GtkWidget* w, GdkEventKey *ev, Client *c) {
+ unsigned int i, focus;
+ gboolean processed = FALSE;
+
+ if(ev->type != GDK_KEY_PRESS)
+ return FALSE;
+ if(GTK_WIDGET_HAS_FOCUS(c->searchbar))
+ focus = SEARCHBAR;
+ else if(GTK_WIDGET_HAS_FOCUS(c->urlbar))
+ focus = URLBAR;
+ else
+ focus = BROWSER;
+ for(i = 0; i < LENGTH(keys); i++) {
+ if(focus & keys[i].focus && ev->keyval == keys[i].keyval &&
+ (ev->state == keys[i].mod || ev->state & keys[i].mod)
+ && keys[i].func) {
+ keys[i].func(c, &(keys[i].arg));
+ processed = TRUE;