#include <sys/time.h>
#include <webkit/webkit.h>
#include <libsoup/soup.h>
+#include <JavaScriptCore/JavaScript.h>
#include <stdio.h>
#include <string.h>
#include "uzbl.h"
#include "config.h"
-static Uzbl uzbl;
-typedef void (*Command)(WebKitWebView*, GArray *argv);
-
-
+Uzbl uzbl;
/* commandline arguments (set initial values for the state variables) */
-static const
+const
GOptionEntry entries[] =
{
{ "uri", 'u', 0, G_OPTION_ARG_STRING, &uzbl.state.uri,
"Uri to load at startup (equivalent to 'set uri = URI')", "URI" },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &uzbl.state.verbose,
"Whether to print all messages or just errors.", NULL },
- { "name", 'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name,
+ { "name", 'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name,
"Name of the current instance (defaults to Xorg window id)", "NAME" },
- { "config", 'c', 0, G_OPTION_ARG_STRING, &uzbl.state.config_file,
+ { "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" },
+ { "version", 'V', 0, G_OPTION_ARG_NONE, &uzbl.behave.print_version,
+ "Print the version and exit", NULL },
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
{ "history_handler", PTR(uzbl.behave.history_handler, STR, 1, NULL)},
{ "download_handler", PTR(uzbl.behave.download_handler, STR, 1, NULL)},
{ "cookie_handler", PTR(uzbl.behave.cookie_handler, STR, 1, cmd_cookie_handler)},
+ { "new_window", PTR(uzbl.behave.new_window, STR, 1, cmd_new_window)},
{ "fifo_dir", PTR(uzbl.behave.fifo_dir, STR, 1, cmd_fifo_dir)},
{ "socket_dir", PTR(uzbl.behave.socket_dir, STR, 1, cmd_socket_dir)},
{ "http_debug", PTR(uzbl.behave.http_debug, INT, 1, cmd_http_debug)},
/* construct a hash from the var_name_to_ptr array for quick access */
-static void
+void
make_var_to_name_hash() {
uzbl.comm.proto_var = g_hash_table_new(g_str_hash, g_str_equal);
while(n2v_p->name) {
}
/* --- UTILITY FUNCTIONS --- */
-static gchar *
-expand_vars(char *s) {
+enum {EXP_ERR, EXP_SIMPLE_VAR, EXP_BRACED_VAR, EXP_EXPR, EXP_JS};
+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>@'
+ */
+gchar *
+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) {
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);
g_string_append_printf(buf, "%f", *(float *)c->ptr);
}
}
- 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);
}
return g_strdup(tmp);
}
-static gchar*
+gchar*
strfree(gchar *str) { g_free(str); return NULL; } // for freeing & setting to null in one go
-static gchar*
+gchar*
argv_idx(const GArray *a, const guint idx) { return g_array_index(a, gchar*, idx); }
-static char *
+char *
str_replace (const char* search, const char* replace, const char* string) {
gchar **buf;
char *ret;
return ret;
}
-static GArray*
+GArray*
read_file_by_line (gchar *path) {
GIOChannel *chan = NULL;
gchar *readbuf = NULL;
gsize len;
GArray *lines = g_array_new(TRUE, FALSE, sizeof(gchar*));
int i = 0;
-
+
chan = g_io_channel_new_file(path, "r", NULL);
-
+
if (chan) {
while (g_io_channel_read_line(chan, &readbuf, &len, NULL, NULL) == G_IO_STATUS_NORMAL) {
const gchar* val = g_strdup (readbuf);
g_free (readbuf);
i ++;
}
-
+
g_io_channel_unref (chan);
} else {
fprintf(stderr, "File '%s' not be read.\n", path);
}
-
+
return lines;
}
-static
-gchar* parseenv (char* string) {
+gchar*
+parseenv (char* string) {
extern char** environ;
gchar* tmpstr = NULL;
int i = 0;
-
+
while (environ[i] != NULL) {
gchar** env = g_strsplit (environ[i], "=", 2);
return string;
}
-static sigfunc*
+sigfunc*
setup_signal(int signr, sigfunc *shandler) {
struct sigaction nh, oh;
return NULL;
}
-static void
+void
clean_up(void) {
if (uzbl.behave.fifo_dir)
unlink (uzbl.comm.fifo_path);
g_string_free(uzbl.state.keycmd, TRUE);
g_hash_table_destroy(uzbl.bindings);
g_hash_table_destroy(uzbl.behave.commands);
+ g_scanner_destroy(uzbl.scan);
}
-/* used for html_mode_timeout
+/* used for html_mode_timeout
* be sure to extend this function to use
* more timers if needed in other places
*/
-static void
+void
set_timeout(int seconds) {
struct itimerval t;
memset(&t, 0, sizeof t);
/* --- SIGNAL HANDLER --- */
-static void
+void
catch_sigterm(int s) {
(void) s;
clean_up();
}
-static void
+void
catch_sigint(int s) {
(void) s;
clean_up();
exit(EXIT_SUCCESS);
}
-static void
+void
catch_alrm(int s) {
(void) s;
/* --- CALLBACKS --- */
-static gboolean
+gboolean
new_window_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *navigation_action, WebKitWebPolicyDecision *policy_decision, gpointer user_data) {
(void) web_view;
(void) frame;
const gchar* uri = webkit_network_request_get_uri (request);
if (uzbl.state.verbose)
printf("New window requested -> %s \n", uri);
- new_window_load_uri(uri);
- return (FALSE);
+ webkit_web_policy_decision_use(policy_decision);
+ return TRUE;
}
-static gboolean
+gboolean
mime_policy_cb(WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, gchar *mime_type, WebKitWebPolicyDecision *policy_decision, gpointer user_data) {
(void) frame;
(void) request;
return (NULL);
}
-static gboolean
+gboolean
download_cb (WebKitWebView *web_view, GObject *download, gpointer user_data) {
(void) web_view;
(void) user_data;
}
/* scroll a bar in a given direction */
-static void
+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;
- 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);
+ max_value = gtk_adjustment_get_upper(bar) - page_size;
+
+ 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;
+void
+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;
+void
+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;
+void
+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;
+void
+scroll_horz(WebKitWebView* page, GArray *argv, GString *result) {
+ (void) page; (void) result;
scroll(uzbl.gui.bar_h, argv);
}
-static void
+void
cmd_set_status() {
if (!uzbl.behave.show_status) {
gtk_widget_hide(uzbl.gui.mainbar);
update_title();
}
-static void
-toggle_status_cb (WebKitWebView* page, GArray *argv) {
+void
+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));
+}
+
+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);
update_title();
}
-static void
+void
link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpointer data) {
(void) page;
(void) title;
update_title();
}
-static void
-title_change_cb (WebKitWebView* web_view, WebKitWebFrame* web_frame, const gchar* title, gpointer data) {
+void
+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();
}
-static void
+void
progress_change_cb (WebKitWebView* page, gint progress, gpointer data) {
(void) page;
(void) data;
update_title();
}
-static void
+void
load_finish_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
(void) page;
(void) frame;
run_handler(uzbl.behave.load_finish_handler, "");
}
-static void
+void
load_start_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
(void) page;
(void) frame;
run_handler(uzbl.behave.load_start_handler, "");
}
-static void
+void
load_commit_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
(void) page;
(void) data;
run_handler(uzbl.behave.load_commit_handler, uzbl.state.uri);
}
-static void
+void
destroy_cb (GtkWidget* widget, gpointer data) {
(void) widget;
(void) data;
gtk_main_quit ();
}
-static void
+void
log_history_cb () {
if (uzbl.behave.history_handler) {
- time_t rawtime;
- struct tm * timeinfo;
- char date [80];
- time ( &rawtime );
- timeinfo = localtime ( &rawtime );
- strftime (date, 80, "\"%Y-%m-%d %H:%M:%S\"", timeinfo);
+ GTimeVal the_time;
+ gchar *date;
+
+ g_get_current_time(&the_time);
+ /* no need to wrap this string with quotes since it contains no spaces.
+ format is like: 2009-06-26T20:02:05.262864Z */
+ date = g_time_val_to_iso8601(&the_time);
run_handler(uzbl.behave.history_handler, date);
+ g_free(date);
}
}
/* 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) 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)
#undef VIEWFUNC
/* -- command to callback/function map for things we cannot attach to any signals */
-static struct {char *name; Command command[2];} cmdlist[] =
+struct {char *key; CommandInfo value;} cmdlist[] =
{ /* key function no_split */
{ "back", {view_go_back, 0} },
{ "forward", {view_go_forward, 0} },
{ "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} },
{ "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} },
+ { "quit", {close_uzbl, 0} },
+ { "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
+void
commands_hash(void)
{
unsigned int i;
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 -- */
return action;
}
-static bool
+bool
file_exists (const char * filename) {
return (access(filename, F_OK) == 0);
}
-static void
-set_var(WebKitWebView *page, GArray *argv) {
- (void) page;
+void
+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;
+void
+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;
+void
+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);
}
-static void
+void
act_dump_config() {
dump_config();
}
-static void
-toggle_insert_mode(WebKitWebView *page, GArray *argv) {
- (void)page;
+void
+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) {
update_title();
}
-static void
-load_uri (WebKitWebView *web_view, GArray *argv) {
+void
+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_strstr_len (argv_idx(argv, 0), 11, "javascript:") != NULL) {
- run_js(web_view, argv);
+ 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)
}
}
-static void
-run_js (WebKitWebView * web_view, GArray *argv) {
+/* Javascript*/
+
+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);
+}
+
+JSStaticFunction js_static_functions[] = {
+ {"run", js_run_command, kJSPropertyAttributeNone},
+};
+
+void
+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);
+ }
+}
+
+
+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);
+}
+
+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) {
+void
+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;
i ++;
g_free (line);
}
-
+
if (uzbl.state.verbose)
printf ("External JavaScript file %s loaded\n", argv_idx(argv, 0));
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);
}
}
-static void
+void
search_text (WebKitWebView *page, GArray *argv, const gboolean forward) {
if (argv_idx(argv, 0) && (*argv_idx(argv, 0) != '\0')) {
if (g_strcmp0 (uzbl.state.searchtx, argv_idx(argv, 0)) != 0) {
uzbl.state.searchtx = g_strdup(argv_idx(argv, 0));
}
}
-
+
if (uzbl.state.searchtx) {
if (uzbl.state.verbose)
printf ("Searching: %s\n", uzbl.state.searchtx);
}
}
-static void
-search_forward_text (WebKitWebView *page, GArray *argv) {
+void
+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) {
+void
+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;
+void
+dehilight (WebKitWebView *page, GArray *argv, GString *result) {
+ (void) argv; (void) result;
webkit_web_view_set_highlight_text_matches (page, FALSE);
}
-static void
+void
new_window_load_uri (const gchar * uri) {
+ if (uzbl.behave.new_window) {
+ GString *s = g_string_new ("");
+ g_string_printf(s, "'%s'", uri);
+ run_handler(uzbl.behave.new_window, s->str);
+ return;
+ }
GString* to_execute = g_string_new ("");
g_string_append_printf (to_execute, "%s --uri '%s'", uzbl.state.executable_path, uri);
int i;
g_string_free (to_execute, TRUE);
}
-static void
-chain (WebKitWebView *page, GArray *argv) {
- (void)page;
+void
+chain (WebKitWebView *page, GArray *argv, GString *result) {
+ (void) page; (void) result;
gchar *a = NULL;
gchar **parts = NULL;
- guint i = 0;
+ guint i = 0;
while ((a = argv_idx(argv, i++))) {
parts = g_strsplit (a, " ", 2);
- parse_command(parts[0], parts[1]);
+ if (parts[0])
+ parse_command(parts[0], parts[1], result);
g_strfreev (parts);
}
}
-static void
-keycmd (WebKitWebView *page, GArray *argv) {
+void
+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) {
+void
+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) {
+void
+keycmd_bs (WebKitWebView *page, GArray *argv, GString *result) {
+ gchar *prev;
(void)page;
(void)argv;
- g_string_truncate(uzbl.state.keycmd,
- /* Calculate the number of bytes to truncate...
- * This is not simply (len-1) when dealing with UTF-8 string */
- g_utf8_offset_to_pointer(uzbl.state.keycmd->str,
- g_utf8_strlen(uzbl.state.keycmd->str, uzbl.state.keycmd->len) - 1)
- - uzbl.state.keycmd->str);
+ (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) {
+void
+close_uzbl (WebKitWebView *page, GArray *argv, GString *result) {
(void)page;
(void)argv;
+ (void)result;
gtk_main_quit ();
}
/* --Statusbar functions-- */
-static char*
+char*
build_progressbar_ascii(int percent) {
int width=uzbl.gui.sbar.progress_w;
int i;
return g_string_free(bar, FALSE);
}
-static void
+void
setup_scanner() {
const GScannerConfig scan_config = {
(
}
}
-static gchar *
+gchar *
expand_template(const char *template, gboolean escape_markup) {
if(!template) return NULL;
}
else
g_string_append(ret, uzbl.gui.main_title ?
- uzbl.gui.main_title : g_strdup(""));
+ uzbl.gui.main_title : "");
break;
case SYM_SELECTED_URI:
if(escape_markup) {
}
else
g_string_append(ret, uzbl.state.selected_url ?
- uzbl.state.selected_url : g_strdup(""));
+ uzbl.state.selected_url : "");
break;
case SYM_NAME:
buf = itos(uzbl.xwin);
}
else
g_string_append(ret, uzbl.state.keycmd->str ?
- uzbl.state.keycmd->str : g_strdup(""));
+ uzbl.state.keycmd->str : "");
break;
case SYM_MODE:
g_string_append(ret,
}
}
else if(token == G_TOKEN_INT) {
- buf = itos(g_scanner_cur_value(uzbl.scan).v_int);
- g_string_append(ret, buf);
- g_free(buf);
+ g_string_append_printf(ret, "%lu", 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_c(ret, (gchar)g_scanner_cur_value(uzbl.scan).v_char);
}
+ else if(token == G_TOKEN_ERROR) {
+ g_scanner_error(uzbl.scan, "Token error in template ('%s') at line %d, column %d.",
+ template,
+ g_scanner_cur_line(uzbl.scan),
+ g_scanner_cur_position(uzbl.scan));
+ }
}
return g_string_free(ret, FALSE);
}
/* --End Statusbar functions-- */
-static void
+void
sharg_append(GArray *a, const gchar *str) {
const gchar *s = (str ? str : "");
g_array_append_val(a, s);
}
// make sure that the args string you pass can properly be interpreted (eg properly escaped against whitespace, quotes etc)
-static gboolean
+gboolean
run_command (const gchar *command, const guint npre, const gchar **args,
const gboolean sync, char **output_stdout) {
//command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl fifo file> <uzbl socket file> [args]
GError *err = NULL;
-
+
GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*));
gchar *pid = itos(getpid());
gchar *xwin = itos(uzbl.xwin);
for (i = npre; i < g_strv_length((gchar**)args); i++)
sharg_append(a, args[i]);
-
+
gboolean result;
if (sync) {
if (*output_stdout) *output_stdout = strfree(*output_stdout);
-
+
result = g_spawn_sync(NULL, (gchar **)a->data, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, output_stdout, NULL, NULL, &err);
} else result = g_spawn_async(NULL, (gchar **)a->data, NULL, G_SPAWN_SEARCH_PATH,
return result;
}
-static gchar**
+gchar**
split_quoted(const gchar* src, const gboolean unquote) {
/* split on unquoted space, return array of strings;
remove a layer of quotes and backslashes if unquote */
if (!src) return NULL;
-
+
gboolean dq = FALSE;
gboolean sq = FALSE;
GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*));
return ret;
}
-static void
-spawn(WebKitWebView *web_view, GArray *argv) {
- (void)web_view;
+void
+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;
-
+void
+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*))),
TRUE, &uzbl.comm.sync_stdout);
}
-static void
-spawn_sh(WebKitWebView *web_view, GArray *argv) {
- (void)web_view;
+void
+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;
}
-
+
guint i;
gchar *spacer = g_strdup("");
g_array_insert_val(argv, 1, spacer);
g_strfreev (cmd);
}
-static void
-spawn_sh_sync(WebKitWebView *web_view, GArray *argv) {
- (void)web_view;
+void
+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;
}
-
+
guint i;
gchar *spacer = g_strdup("");
g_array_insert_val(argv, 1, spacer);
for (i = 1; i < g_strv_length(cmd); i++)
g_array_prepend_val(argv, cmd[i]);
-
+
if (cmd) run_command(cmd[0], g_strv_length(cmd) + 1, (const gchar **) argv->data,
TRUE, &uzbl.comm.sync_stdout);
g_free (spacer);
g_strfreev (cmd);
}
-static void
-parse_command(const char *cmd, const char *param) {
- Command *c;
+void
+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);
g_printerr ("command \"%s\" not understood. ignoring.\n", cmd);
}
-static void
+void
set_proxy_url() {
SoupURI *suri;
return;
}
-static void
+void
set_icon() {
if(file_exists(uzbl.gui.icon)) {
- gtk_window_set_icon_from_file (GTK_WINDOW (uzbl.gui.main_window), uzbl.gui.icon, NULL);
+ 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);
}
}
-static void
+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);
}
-static void
+void
cmd_always_insert_mode() {
uzbl.behave.insert_mode =
uzbl.behave.always_insert_mode ? TRUE : FALSE;
update_title();
}
-static void
+void
cmd_max_conns() {
g_object_set(G_OBJECT(uzbl.net.soup_session),
SOUP_SESSION_MAX_CONNS, uzbl.net.max_conns, NULL);
}
-static void
+void
cmd_max_conns_host() {
g_object_set(G_OBJECT(uzbl.net.soup_session),
SOUP_SESSION_MAX_CONNS_PER_HOST, uzbl.net.max_conns_host, NULL);
}
-static void
+void
cmd_http_debug() {
soup_session_remove_feature
(uzbl.net.soup_session, SOUP_SESSION_FEATURE(uzbl.net.soup_logger));
SOUP_SESSION_FEATURE(uzbl.net.soup_logger));
}
-static WebKitWebSettings*
+WebKitWebSettings*
view_settings() {
return webkit_web_view_get_settings(uzbl.gui.web_view);
}
-static void
+void
cmd_font_size() {
WebKitWebSettings *ws = view_settings();
if (uzbl.behave.font_size > 0) {
g_object_set (G_OBJECT(ws), "default-font-size", uzbl.behave.font_size, NULL);
}
-
+
if (uzbl.behave.monospace_size > 0) {
g_object_set (G_OBJECT(ws), "default-monospace-font-size",
uzbl.behave.monospace_size, NULL);
}
}
-static void
+void
cmd_zoom_level() {
webkit_web_view_set_zoom_level (uzbl.gui.web_view, uzbl.behave.zoom_level);
}
-static void
+void
cmd_disable_plugins() {
- g_object_set (G_OBJECT(view_settings()), "enable-plugins",
+ g_object_set (G_OBJECT(view_settings()), "enable-plugins",
!uzbl.behave.disable_plugins, NULL);
}
-static void
+void
cmd_disable_scripts() {
g_object_set (G_OBJECT(view_settings()), "enable-scripts",
!uzbl.behave.disable_scripts, NULL);
}
-static void
+void
cmd_minimum_font_size() {
g_object_set (G_OBJECT(view_settings()), "minimum-font-size",
uzbl.behave.minimum_font_size, NULL);
}
-static void
+void
cmd_autoload_img() {
g_object_set (G_OBJECT(view_settings()), "auto-load-images",
uzbl.behave.autoload_img, NULL);
}
-static void
+void
cmd_autoshrink_img() {
g_object_set (G_OBJECT(view_settings()), "auto-shrink-images",
uzbl.behave.autoshrink_img, NULL);
}
-static void
+void
cmd_enable_spellcheck() {
g_object_set (G_OBJECT(view_settings()), "enable-spell-checking",
uzbl.behave.enable_spellcheck, NULL);
}
-static void
+void
cmd_enable_private() {
g_object_set (G_OBJECT(view_settings()), "enable-private-browsing",
uzbl.behave.enable_private, NULL);
}
-static void
+void
cmd_print_bg() {
g_object_set (G_OBJECT(view_settings()), "print-backgrounds",
uzbl.behave.print_bg, NULL);
}
-static void
+void
cmd_style_uri() {
g_object_set (G_OBJECT(view_settings()), "user-stylesheet-uri",
uzbl.behave.style_uri, NULL);
}
-static void
+void
cmd_resizable_txt() {
g_object_set (G_OBJECT(view_settings()), "resizable-text-areas",
uzbl.behave.resizable_txt, NULL);
}
-static void
+void
cmd_default_encoding() {
g_object_set (G_OBJECT(view_settings()), "default-encoding",
uzbl.behave.default_encoding, NULL);
}
-static void
+void
cmd_enforce_96dpi() {
g_object_set (G_OBJECT(view_settings()), "enforce-96-dpi",
uzbl.behave.enforce_96dpi, NULL);
}
-static void
+void
cmd_caret_browsing() {
g_object_set (G_OBJECT(view_settings()), "enable-caret-browsing",
uzbl.behave.caret_browsing, NULL);
}
-static void
+void
cmd_cookie_handler() {
gchar **split = g_strsplit(uzbl.behave.cookie_handler, " ", 2);
/* pitfall: doesn't handle chain actions; must the sync_ action manually */
g_strfreev (split);
}
-static void
+void
+cmd_new_window() {
+ gchar **split = g_strsplit(uzbl.behave.new_window, " ", 2);
+ /* pitfall: doesn't handle chain actions; must the sync_ action manually */
+ if ((g_strcmp0(split[0], "sh") == 0) ||
+ (g_strcmp0(split[0], "spawn") == 0)) {
+ g_free (uzbl.behave.new_window);
+ uzbl.behave.new_window =
+ g_strdup_printf("%s %s", split[0], split[1]);
+ }
+ g_strfreev (split);
+}
+
+void
cmd_fifo_dir() {
uzbl.behave.fifo_dir = init_fifo(uzbl.behave.fifo_dir);
}
-static void
+void
cmd_socket_dir() {
uzbl.behave.socket_dir = init_socket(uzbl.behave.socket_dir);
}
-static void
+void
cmd_inject_html() {
if(uzbl.behave.inject_html) {
webkit_web_view_load_html_string (uzbl.gui.web_view,
}
}
-static void
+void
cmd_modkey() {
int i;
char *buf;
buf = g_utf8_strup(uzbl.behave.modkey, -1);
uzbl.behave.modmask = 0;
- if(uzbl.behave.modkey)
+ if(uzbl.behave.modkey)
g_free(uzbl.behave.modkey);
uzbl.behave.modkey = buf;
}
}
-static void
+void
cmd_useragent() {
if (*uzbl.net.useragent == ' ') {
g_free (uzbl.net.useragent);
}
}
-static void
+void
move_statusbar() {
gtk_widget_ref(uzbl.gui.scrolled_win);
gtk_widget_ref(uzbl.gui.mainbar);
return;
}
-static gboolean
+gboolean
set_var_value(gchar *name, gchar *val) {
uzbl_cmdprop *c = NULL;
char *endp = NULL;
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);
+ buf = expand(val, 0);
*fp = strtod(buf, &endp);
g_free(buf);
}
return TRUE;
}
-static void
+void
render_html() {
Behaviour *b = &uzbl.behave;
}
enum {M_CMD, M_HTML};
-static void
-parse_cmd_line(const char *ctl_line) {
+void
+parse_cmd_line(const char *ctl_line, GString *result) {
Behaviour *b = &uzbl.behave;
size_t len=0;
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);
}
}
-static gchar*
+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) {
return str;
}
-static gboolean
+gboolean
control_fifo(GIOChannel *gio, GIOCondition condition) {
if (uzbl.state.verbose)
printf("triggered\n");
g_error_free (err);
}
- parse_cmd_line(ctl_line);
+ parse_cmd_line(ctl_line, NULL);
g_free(ctl_line);
return TRUE;
}
-static gchar*
+gchar*
init_fifo(gchar *dir) { /* return dir or, on error, free dir and return NULL */
- if (uzbl.comm.fifo_path) { /* get rid of the old fifo if one exists */
- if (unlink(uzbl.comm.fifo_path) == -1)
- g_warning ("Fifo: Can't unlink old fifo at %s\n", uzbl.comm.fifo_path);
- g_free(uzbl.comm.fifo_path);
- uzbl.comm.fifo_path = NULL;
- }
-
- if (*dir == ' ') { /* space unsets the variable */
- g_free (dir);
- return NULL;
- }
-
GIOChannel *chan = NULL;
GError *error = NULL;
gchar *path = build_stream_name(FIFO, dir);
return NULL;
}
-static gboolean
+gboolean
control_stdin(GIOChannel *gio, GIOCondition condition) {
(void) condition;
gchar *ctl_line = NULL;
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;
}
-static void
+void
create_stdin () {
GIOChannel *chan = NULL;
GError *error = NULL;
if (error) g_error_free (error);
}
-static gboolean
+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;
-
- sock = g_io_channel_unix_get_fd(chan);
-
- memset (buffer, 0, sizeof (buffer));
+ unsigned int t = sizeof(remote);
+ int clientsock;
+ GIOChannel *clientchan;
- t = sizeof (remote);
- clientsock = accept (sock, (struct sockaddr *) &remote, &t);
+ clientsock = accept (g_io_channel_unix_get_fd(chan),
+ (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';
+ 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;
+}
+
+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;
}
-static gchar*
+gchar*
init_socket(gchar *dir) { /* return dir or, on error, free dir and return NULL */
if (uzbl.comm.socket_path) { /* remove an existing socket should one exist */
if (unlink(uzbl.comm.socket_path) == -1)
it will probably improve performance if we would "cache" the processed variant, but for now it works well enough...
*/
// this function may be called very early when the templates are not set (yet), hence the checks
-static void
+void
update_title (void) {
Behaviour *b = &uzbl.behave;
gchar *parsed;
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) {
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 vbox/main_window 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 (GTK_WIDGET(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);
}
}
}
-static gboolean
+gboolean
key_press_cb (GtkWidget* window, GdkEventKey* event)
{
//TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
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;
}
}
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))
return TRUE;
}
-static void
+void
run_keycmd(const gboolean key_ret) {
/* run the keycmd immediately if it isn't incremental and doesn't take args */
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;
}
else exec_paramcmd(act, i); /* otherwise execute the incremental */
break;
}
-
+
g_string_truncate(short_keys, short_keys->len - 1);
}
g_string_free (short_keys, TRUE);
g_string_free (short_keys_inc, TRUE);
}
-static void
+void
exec_paramcmd(const Action *act, const guint i) {
GString *parampart = g_string_new (uzbl.state.keycmd->str);
GString *actionname = g_string_new ("");
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);
}
-static GtkWidget*
+GtkWidget*
create_browser () {
GUI *g = &uzbl.gui;
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);
return scrolled_window;
}
-static GtkWidget*
+GtkWidget*
create_mainbar () {
GUI *g = &uzbl.gui;
return g->mainbar;
}
-static
-GtkWidget* create_window () {
+GtkWidget*
+create_window () {
GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
gtk_widget_set_name (window, "Uzbl browser");
return window;
}
-static gchar**
+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;
+}
+
+
+gchar**
inject_handler_args(const gchar *actname, const gchar *origargs, const gchar *newargs) {
/*
If actname is one that calls an external command, this function will inject
come become after the body of the script (in sh) or after the name of
the command to execute (in spawn).
i.e. sh <body> <userargs> becomes sh <body> <ARGS> <userargs> and
- span <command> <userargs> becomes spawn <command> <ARGS> <userargs>.
+ spawn <command> <userargs> becomes spawn <command> <ARGS> <userargs>.
The return value consist of two strings: the action (sh, ...) and its args.
gets duplicated.
*/
GArray *rets = g_array_new(TRUE, FALSE, sizeof(gchar*));
+ /* Arrr! Here be memory leaks */
gchar *actdup = g_strdup(actname);
g_array_append_val(rets, actdup);
return (gchar**)g_array_free(rets, FALSE);
}
-static void
+void
run_handler (const gchar *act, const gchar *args) {
/* Consider this code a temporary hack to make the handlers usable.
In practice, all this splicing, injection, and reconstruction is
if (g_strcmp0(parts[0], "chain") == 0) {
GString *newargs = g_string_new("");
gchar **chainparts = split_quoted(parts[1], FALSE);
-
+
/* for every argument in the chain, inject the handler args
and make sure the new parts are wrapped in quotes */
gchar **cp = chainparts;
gchar *quotless = NULL;
gchar **spliced_quotless = NULL; // sigh -_-;
gchar **inpart = NULL;
-
+
while (*cp) {
if ((**cp == '\'') || (**cp == '\"')) { /* strip old quotes */
quot = **cp;
spliced_quotless = g_strsplit(quotless, " ", 2);
inpart = inject_handler_args(spliced_quotless[0], spliced_quotless[1], args);
g_strfreev(spliced_quotless);
-
+
g_string_append_printf(newargs, " %c%s %s%c", quot, inpart[0], inpart[1], quot);
g_free(quotless);
g_strfreev(inpart);
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]);
}
g_strfreev(parts);
}
-static void
+void
add_binding (const gchar *key, const gchar *act) {
char **parts = g_strsplit(act, " ", 2);
Action *action;
g_strfreev(parts);
}
-static gchar*
+gchar*
get_xdg_var (XDG_Var xdg) {
const gchar* actual_value = getenv (xdg.environmental);
const gchar* home = getenv ("HOME");
return return_value;
}
-static gchar*
+gchar*
find_xdg_file (int xdg_type, char* filename) {
/* xdg_type = 0 => config
xdg_type = 1 => data
temporary_file = g_strconcat (temporary_string, filename, NULL);
}
}
-
+
//g_free (temporary_string); - segfaults.
if (file_exists (temporary_file)) {
return NULL;
}
}
-static void
+void
settings_init () {
State *s = &uzbl.state;
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");
}
gchar* line;
while ((line = g_array_index(lines, gchar*, i))) {
- parse_cmd_line (line);
+ parse_cmd_line (line, NULL);
i ++;
g_free (line);
}
g_signal_connect_after(n->soup_session, "request-started", G_CALLBACK(handle_cookies), NULL);
}
-static void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data){
+void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data){
(void) session;
(void) user_data;
if (!uzbl.behave.cookie_handler)
soup_message_add_header_handler(msg, "got-headers", "Set-Cookie", G_CALLBACK(save_cookies), NULL);
GString *s = g_string_new ("");
SoupURI * soup_uri = soup_message_get_uri(msg);
- g_string_printf(s, "GET '%s' '%s'", soup_uri->host, soup_uri->path);
+ g_string_printf(s, "GET '%s' '%s' '%s'", soup_uri->scheme, soup_uri->host, soup_uri->path);
run_handler(uzbl.behave.cookie_handler, s->str);
if(uzbl.comm.sync_stdout && strcmp (uzbl.comm.sync_stdout, "") != 0) {
}
if (uzbl.comm.sync_stdout)
uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
-
+
g_string_free(s, TRUE);
}
-static void
+void
save_cookies (SoupMessage *msg, gpointer user_data){
(void) user_data;
GSList *ck;
cookie = soup_cookie_to_set_cookie_header(ck->data);
SoupURI * soup_uri = soup_message_get_uri(msg);
GString *s = g_string_new ("");
- g_string_printf(s, "PUT '%s' '%s' '%s'", soup_uri->host, soup_uri->path, cookie);
+ g_string_printf(s, "PUT '%s' '%s' '%s' '%s'", soup_uri->scheme, soup_uri->host, soup_uri->path, cookie);
run_handler(uzbl.behave.cookie_handler, s->str);
g_free (cookie);
g_string_free(s, TRUE);
}
/* --- WEBINSPECTOR --- */
-static void
+void
hide_window_cb(GtkWidget *widget, gpointer data) {
(void) data;
gtk_widget_hide(widget);
}
-static WebKitWebView*
+WebKitWebView*
create_inspector_cb (WebKitWebInspector* web_inspector, WebKitWebView* page, gpointer data){
(void) data;
(void) page;
return WEBKIT_WEB_VIEW(new_web_view);
}
-static gboolean
+gboolean
inspector_show_window_cb (WebKitWebInspector* inspector){
(void) inspector;
gtk_widget_show(uzbl.gui.inspector_window);
}
/* TODO: Add variables and code to make use of these functions */
-static gboolean
+gboolean
inspector_close_window_cb (WebKitWebInspector* inspector){
(void) inspector;
return TRUE;
}
-static gboolean
+gboolean
inspector_attach_window_cb (WebKitWebInspector* inspector){
(void) inspector;
return FALSE;
}
-static gboolean
+gboolean
inspector_detach_window_cb (WebKitWebInspector* inspector){
(void) inspector;
return FALSE;
}
-static gboolean
+gboolean
inspector_uri_changed_cb (WebKitWebInspector* inspector){
(void) inspector;
return FALSE;
}
-static gboolean
+gboolean
inspector_inspector_destroyed_cb (WebKitWebInspector* inspector){
(void) inspector;
return FALSE;
}
-static void
+void
set_up_inspector() {
GUI *g = &uzbl.gui;
WebKitWebSettings *settings = view_settings();
g_signal_connect (G_OBJECT (g->inspector), "notify::inspected-uri", G_CALLBACK (inspector_uri_changed_cb), NULL);
}
-static void
+void
dump_var_hash(gpointer k, gpointer v, gpointer ud) {
(void) ud;
uzbl_cmdprop *c = v;
printf("set %s = %f\n", (char *)k, *(float *)c->ptr);
}
-static void
+void
dump_key_hash(gpointer k, gpointer v, gpointer ud) {
(void) ud;
Action *a = v;
(char *)a->name, a->param?(char *)a->param:"");
}
-static void
+void
dump_config() {
g_hash_table_foreach(uzbl.comm.proto_var, dump_var_hash, NULL);
g_hash_table_foreach(uzbl.bindings, dump_key_hash, NULL);
}
+#ifndef UZBL_LIBRARY
/** -- MAIN -- **/
int
main (int argc, char* argv[]) {
uzbl.state.selected_url = NULL;
uzbl.state.searchtx = NULL;
- GOptionContext* context = g_option_context_new ("- some stuff here maybe someday");
+ GOptionContext* context = g_option_context_new ("[ uri ] - load a uri by default");
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_add_group (context, gtk_get_option_group (TRUE));
g_option_context_parse (context, &argc, &argv, NULL);
g_option_context_free(context);
-
+
+ if (uzbl.behave.print_version) {
+ printf("Commit: %s\n", COMMIT);
+ exit(0);
+ }
+
gchar *uri_override = (uzbl.state.uri ? g_strdup(uzbl.state.uri) : NULL);
+ if (argc > 1 && !uzbl.state.uri)
+ uri_override = g_strdup(argv[1]);
gboolean verbose_override = uzbl.state.verbose;
/* initialize hash table */
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);
}
/* WebInspector */
set_up_inspector();
- create_stdin();
-
if (verbose_override > uzbl.state.verbose)
uzbl.state.verbose = verbose_override;
-
+
if (uri_override) {
set_var_value("uri", uri_override);
g_free(uri_override);
return EXIT_SUCCESS;
}
+#endif
/* vi: set et ts=4: */