+static void sigchld(int unused);
+static void spawn(Client *c, const Arg *arg);
+static void stop(Client *c, const Arg *arg);
+static void titlechanged(WebKitWebView *view, GParamSpec *ps, Client *c);
+static void titlechangeleave(void *a, void *b, Client *c);
+static void toggle(Client *c, const Arg *arg);
+static void togglecookiepolicy(Client *c, const Arg *arg);
+static void togglegeolocation(Client *c, const Arg *arg);
+static void togglescrollbars(Client *c, const Arg *arg);
+static void togglestyle(Client *c, const Arg *arg);
+static void updatetitle(Client *c);
+static void updatewinid(Client *c);
+static void usage(void);
+static void windowobjectcleared(GtkWidget *w, WebKitWebFrame *frame,
+ JSContextRef js, JSObjectRef win, Client *c);
+static void zoom(Client *c, const Arg *arg);
+
+/* configuration, allows nested code to access above variables */
+#include "config.h"
+
+void
+addaccelgroup(Client *c)
+{
+ int i;
+ GtkAccelGroup *group = gtk_accel_group_new();
+ GClosure *closure;
+
+ for (i = 0; i < LENGTH(keys); i++) {
+ closure = g_cclosure_new(G_CALLBACK(keypress), c, NULL);
+ gtk_accel_group_connect(group, keys[i].keyval, keys[i].mod, 0,
+ closure);
+ }
+ gtk_window_add_accel_group(GTK_WINDOW(c->win), group);
+}
+
+void
+beforerequest(WebKitWebView *w, WebKitWebFrame *f, WebKitWebResource *r,
+ WebKitNetworkRequest *req, WebKitNetworkResponse *resp,
+ Client *c)
+{
+ const gchar *uri = webkit_network_request_get_uri(req);
+ int i, isascii = 1;
+
+ if (g_str_has_suffix(uri, "/favicon.ico"))
+ webkit_network_request_set_uri(req, "about:blank");
+
+ if (!g_str_has_prefix(uri, "http://")
+ && !g_str_has_prefix(uri, "https://")
+ && !g_str_has_prefix(uri, "about:")
+ && !g_str_has_prefix(uri, "file://")
+ && !g_str_has_prefix(uri, "data:")
+ && !g_str_has_prefix(uri, "blob:")
+ && strlen(uri) > 0) {
+ for (i = 0; i < strlen(uri); i++) {
+ if (!g_ascii_isprint(uri[i])) {
+ isascii = 0;
+ break;
+ }
+ }
+ if (isascii)
+ handleplumb(c, w, uri);
+ }
+}
+
+char *
+buildfile(const char *path)
+{
+ char *dname, *bname, *bpath, *fpath;
+ FILE *f;
+
+ dname = g_path_get_dirname(path);
+ bname = g_path_get_basename(path);
+
+ bpath = buildpath(dname);
+ g_free(dname);
+
+ fpath = g_build_filename(bpath, bname, NULL);
+ g_free(bpath);
+ g_free(bname);
+
+ if (!(f = fopen(fpath, "a")))
+ die("Could not open file: %s\n", fpath);
+
+ g_chmod(fpath, 0600); /* always */
+ fclose(f);
+
+ return fpath;
+}
+
+char *
+buildpath(const char *path)
+{
+ struct passwd *pw;
+ char *apath, *name, *p, *fpath;
+
+ if (path[0] == '~') {
+ if (path[1] == '/' || path[1] == '\0') {
+ p = (char *)&path[1];
+ pw = getpwuid(getuid());
+ } else {
+ if ((p = strchr(path, '/')))
+ name = g_strndup(&path[1], --p - path);
+ else
+ name = g_strdup(&path[1]);
+
+ if (!(pw = getpwnam(name))) {
+ die("Can't get user %s home directory: %s.\n",
+ name, path);
+ }
+ g_free(name);
+ }
+ apath = g_build_filename(pw->pw_dir, p, NULL);
+ } else {
+ apath = g_strdup(path);
+ }
+
+ /* creating directory */
+ if (g_mkdir_with_parents(apath, 0700) < 0)
+ die("Could not access directory: %s\n", apath);
+
+ fpath = realpath(apath, NULL);
+ g_free(apath);
+
+ return fpath;
+}
+
+gboolean
+buttonrelease(WebKitWebView *web, GdkEventButton *e, Client *c)
+{
+ WebKitHitTestResultContext context;
+ WebKitHitTestResult *result;
+ Arg arg;
+ unsigned int i;
+
+ result = webkit_web_view_get_hit_test_result(web, e);
+ g_object_get(result, "context", &context, NULL);
+ g_object_get(result, "link-uri", &arg.v, NULL);
+ for (i = 0; i < LENGTH(buttons); i++) {
+ if (context & buttons[i].click
+ && e->button == buttons[i].button
+ && CLEANMASK(e->state) == CLEANMASK(buttons[i].mask)
+ && buttons[i].func) {
+ buttons[i].func(c, buttons[i].click == ClkLink
+ && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
+ return true;
+ }
+ }
+ return false;
+}