viking

webkit based web browser for Enlightenment
Log | Files | Refs | LICENSE

commit edc43785525594f39492f66fbec1133055ec4fc8
parent 3f9605ab1fb52c7e45a41006c53313e29add9c38
Author: Kyle Milz <kmilz@ucalgary.ca>
Date:   Tue, 25 Sep 2012 12:55:33 -0600

hack in config system from eve

using the .geneet file from eve (copyright proFusion) use the data
structres it generates to make a persistent config file.

config file includes a history of web pages visited, persistent
settings, and session data (buffers open, etc).

Diffstat:
MMakefile | 2+-
Acallbacks.c | 951+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acallbacks.h | 35+++++++++++++++++++++++++++++++++++
Mcommands.c | 62++++++++++++++++++++++++++++++++++++++++++++++----------------
Mcommands.h | 5+----
Dconfig.h | 155-------------------------------------------------------------------------------
Mkeymap.h | 4++--
Mmain.c | 1598++++++++++++++++++++++++-------------------------------------------------------
Mmain.h | 7+++++++
Mutilities.c | 3++-
Mviking.h | 15+++++++++++++++
Aviking_state.c | 1259+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aviking_state.h | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 files changed, 2962 insertions(+), 1291 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,7 +1,7 @@ TARGET = viking # Objectfiles, needed for $(TARGET) -OBJ = main.o utilities.o commands.o jsmn.o +OBJ = main.o utilities.o commands.o jsmn.o viking_state.o callbacks.o # Manpages MAN1 = evi2.1 MAN5 = evirc.5 diff --git a/callbacks.c b/callbacks.c @@ -0,0 +1,951 @@ + +#include <Elementary.h> +#include <EWebKit.h> + +#include "viking.h" +#include "viking_state.h" +#include "main.h" +#include "utilities.h" +#include "javascript.h" +#include "commands.h" +#include "callbacks.h" + +static Eina_Bool commandhistoryfetch (const Arg *, void *); +static Eina_Bool process_keypress (void *, void*); + +void download_complete_cb(void*, const char*, int); +int download_progress_cb(void*, const char*, long int, long int, long int, long int); + +#define IS_ESCAPE(ev) ((!strcmp(ev->keyname, "Escape")) || \ + (!strcmp(ev->keyname, "[") && evas_key_modifier_is_set(ev->modifiers, "Control"))) + + +void +webview_title_changed_cb(void *data, Evas_Object *obj, void *event_info) +{ + /* + const char *title = ""; + Ewk_Text_With_Direction *dir_text = event_info; + if (event_info) title = dir_text->string; + char buf[20] = ""; + + if (title) + strncpy(buf, title, sizeof(buf) - 1); + elm_object_item_text_set(td->tab, buf); + */ +} + +void +webview_progress_changed_cb(void *data, Evas_Object *obj, void *event_info) +{ + Buffer_Data *td = data; + /* *event_info is a double between 0.0 and 1.0 */ + update_state(td->app); +} + + +void +protocol_register_cb(void *data, Evas_Object *obj, void *event_info) +{ + printf("protocol_register()\n"); +} + +void +load_error_cb(void *data, Evas_Object *obj, void *event_info) +{ + char *contents; + Ewk_Frame_Load_Error *error = event_info; + + if (error->is_cancellation) + return; + + contents = strdup_printf("<html><body>\ + <h1>Error %i</h1>\ + <h2>%s</h2>\ + <h2>%s</h2>\ + </body></html>", + error->code, error->failing_url, error->description); + + ewk_frame_contents_set(error->frame, contents, strlen(contents) - 1, + "text/html", "UTF-8", NULL); + free(contents); +} + +void +webview_inspector_cb(void *data, Evas_Object *obj, void *event_info) +{ + Buffer_Data *td = data; + App_Data *ad = td->app; + + td->web_inspector = ewk_view_single_add(evas_object_evas_get(ad->win)); + ewk_view_theme_set(td->web_inspector, "/usr/share/ewebkit-0/themes/default.edj"); + + evas_object_size_hint_weight_set(td->web_inspector, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(td->web_inspector, EVAS_HINT_FILL, EVAS_HINT_FILL); + + ewk_view_web_inspector_view_set(td->view, td->web_inspector); + + evas_object_show(td->web_inspector); + elm_box_pack_end(ad->web_inspector, td->web_inspector); + + evas_object_size_hint_weight_set(ad->web_inspector, EVAS_HINT_EXPAND, 0.66); + evas_object_show(ad->web_inspector); + + /* + td->web_inspector = elm_web_add(ad->win); + + evas_object_size_hint_weight_set(td->web_inspector, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(td->web_inspector, EVAS_HINT_FILL, EVAS_HINT_FILL); + + ewk_view_web_inspector_view_set(view, elm_web_webkit_view_get(td->web_inspector)); + + evas_object_show(td->web_inspector); + elm_box_pack_end(ad->web_inspector, td->web_inspector); + + evas_object_size_hint_weight_set(ad->web_inspector, EVAS_HINT_EXPAND, 1.0); + evas_object_show(ad->web_inspector); + */ +} + +void +webview_inspector_close_cb(void *data, Evas_Object *obj, void *event_info) +{ + Buffer_Data *td = data; + App_Data *ad = td->app; + + elm_box_clear(ad->web_inspector); + evas_object_size_hint_weight_set(ad->web_inspector, EVAS_HINT_EXPAND, 0.0); + ewk_view_web_inspector_view_set(td->view, NULL); + + td->web_inspector = NULL; +} + +void +webview_uri_changed_cb(void *data, Evas_Object *obj, void *event_info) +{ + Arg a = { .i = Silent, .s = strdup(JS_SETUP_HINTS) }; + Buffer_Data *td = data; + const char *uri = event_info; + + if (td->web != td->app->cur_buf->web) + return; + + // userscript_hooks_start(elm_web_uri_get(td->web)); + + script(&a, td->app); + free(a.s); + + /* + FILE *fp = fopen("/home/kyle/.config/evi/userscript/adblockplus/contentScript1.js", "r"); + if (!fp) + printf("error opening file.\n"); + fseek(fp, 0L, SEEK_END); + int len = ftell(fp); + char *buf = malloc(len); + rewind(fp); + fread(buf, len, 1, fp); + fclose(fp); + + ewk_frame_script_execute(frame, buf); + + free(buf); + */ + + if (td->app->mode == ModeInsert || td->app->mode == ModeHints) { + Arg a = { .i = ModeNormal }; + set(&a, td->app); + } + + td->app->manual_focus = EINA_FALSE; + update_url(uri, td->app); +} + +void +webview_document_finished_cb(void *data, Evas_Object *obj, void *event_info) +{ + Hist_Item *item; + Buffer_Data *bd = data; + App_Data *ad = bd->app; + Evas_Object *frame = event_info; + const Ewk_Text_With_Direction *txt = ewk_frame_title_get(frame); + const char *url = ewk_frame_uri_get(frame); + const char *title = (txt ? txt->string : ""); + + if (!bd->history_enabled) + return; + + if ((item = hist_items_get(ad->history, url))) { + hist_item_visit_count_set(item, hist_item_visit_count_get(item) + 1); + hist_item_last_visit_set(item, ecore_time_unix_get()); + hist_item_title_set(item, title); + } + else { + hist_items_add(ad->history, url, hist_item_new(title, url, 1, ecore_time_unix_get())); + } +} + +static Eina_Bool escape_input_on_load = TRUE; /* TRUE will disable automatic focusing of input fields via Javascript*/ + +void +webview_load_finished_cb(void *data, Evas_Object *obj, void *event_info) +{ + /* WebKitWebSettings *settings = webkit_web_view_get_settings(webview); */ + Buffer_Data *bd = data; + App_Data *ad = bd->app; + Eina_Bool scripts = 1; + Elm_Web_Frame_Load_Error *frame_error = event_info; + + printf("load_finished()\n"); + + if (frame_error) + return; + + /* g_object_get(settings, "enable-scripts", &scripts, NULL); */ + if (escape_input_on_load && scripts && !ad->manual_focus && !elm_object_focus_get(ad->url)) { + Arg a = { .i = Silent, .s = strdup("hints.clearFocus();") }; + script(&a, ad); + free(a.s); + a.i = ModeNormal; + a.s = NULL; + set(&a, ad); + } + + update_state(ad); + + // userscript_hooks_end(elm_web_uri_get(td->web)); + + /* + FILE *fp = fopen("/home/kyle/.config/evi/userscript/adblockplus/contentScript2.js", "r"); + if (!fp) + printf("error opening file.\n"); + fseek(fp, 0L, SEEK_END); + int len = ftell(fp); + char *buf = malloc(len); + rewind(fp); + fread(buf, len, 1, fp); + fclose(fp); + + ewk_frame_script_execute(frame, buf); + + free(buf); + */ + + + // elm_object_focus_set(td->web, EINA_TRUE); +} + +#if 0 +void +webview_open_js_window_cb(WebKitWebView* temp_view, GParamSpec param_spec) { + /* retrieve the URI of the temporary webview */ + Arg a = { .i = TargetNew, .s = (char*)webkit_web_view_get_uri(temp_view) }; + /* clean up */ + webkit_web_view_stop_loading(temp_view); + gtk_widget_destroy(GTK_WIDGET(temp_view)); + /* open the requested window */ + open_arg(&a); +} + +static WebKitWebView * +webview_open_in_new_window_cb(WebKitWebView *webview, WebKitWebFrame *frame, gpointer user_data) { + /* create a temporary webview to execute the script in */ + WebKitWebView *temp_view = WEBKIT_WEB_VIEW(webkit_web_view_new()); + /* wait until the new webview receives its new URI */ + g_object_connect(temp_view, "signal::notify::uri", G_CALLBACK(webview_open_js_window_cb), NULL, NULL); + return temp_view; +} + +Eina_Bool +webview_new_window_cb(WebKitWebView *webview, WebKitWebFrame *frame, WebKitNetworkRequest *request, + WebKitWebNavigationAction *action, WebKitWebPolicyDecision *decision, gpointer user_data) { + Arg a = { .i = TargetNew, .s = (char*)webkit_network_request_get_uri(request) }; + open_arg(&a); + webkit_web_policy_decision_ignore(decision); + return TRUE; +} +#endif + +/* +Eina_Bool +webview_mimetype_cb(WebKitWebView *webview, WebKitWebFrame *frame, WebKitNetworkRequest *request, + char *mime_type, WebKitWebPolicyDecision *decision, gpointer user_data) { + if (webkit_web_view_can_show_mime_type(webview, mime_type) == FALSE) { + webkit_web_policy_decision_download(decision); + return TRUE; + } else { + return FALSE; + } +} + +*/ + +void +download_entry_free_cb(void *data) +{ + free(data); +} + +void +download_complete_cb(void *data, const char *file, int status) +{ + App_Data *ad = data; + Arg a; + a.i = Info; + a.s = strdup_printf("Download %s finished, status %i", file, status); + echo(&a, data); + free(a.s); + + // ad->active_downloads = eina_list_remove(ad->active_downloads, file); + eina_hash_del(ad->downloads, file, NULL); + + update_state(data); +} + +int +download_progress_cb(void *data, const char *file, long int dltotal, long int dlnow, long int ultotal, long int ulnow) +{ + App_Data *ad = data; + + void *stat_old; + struct dl *stat = malloc(sizeof(struct dl)); + + stat->dltotal = dltotal; + stat->dlnow = dlnow; + + stat_old = eina_hash_modify(ad->downloads, file, (const void *)stat); + free(stat_old); + + update_state(data); + + return 0; +} + +void +webview_download_cb(void *data, Evas_Object *obj, void *event_info) +{ + Eina_Bool ret; + Buffer_Data *td = data; + App_Data *ad = td->app; + + Ewk_Download *dl = event_info; + char *suggested_name = strdup(strrchr(dl->url, '/')); + + char *full_path = strdup_printf("/home/kyle/%s", suggested_name); + + ret = ecore_file_download(dl->url, full_path, download_complete_cb, + download_progress_cb, ad, NULL); + + /* if file already exists, ret == NULL */ + if (!ret) { + Arg a; + a.i = Info; + a.s = strdup_printf("%s already exists!", suggested_name); + echo(&a, ad); + free(a.s); + return; + } + + // ad->active_downloads = eina_list_append(ad->active_downloads, strdup(full_path)); + eina_hash_add(ad->downloads, full_path, calloc(1, sizeof(struct dl))); + + // free(full_path); + free(suggested_name); + + update_state(ad); +} + + +void +webview_mousewheel_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Buffer_Data *td = data; + update_state(td->app); +} + +Eina_Bool +process_keypress(void *event_info, void *data) +{ + KeyList *walk; + Key key; + // int keyval; + // GdkModifierType irrelevant; + App_Data *ad = data; + Evas_Event_Key_Down *ev = event_info; + + // Get a mask of modifiers that shouldn't be considered for this event. + // E.g.: It shouldn't matter whether ';' is shifted or not. + // gdk_keymap_translate_keyboard_state(keymap, event->hardware_keycode, + // event->state, event->group, &keyval, NULL, NULL, &irrelevant); + + walk = ad->keylistroot; + while (walk != NULL) { + key = walk->Element; + // if (current->Element.mask == (CLEAN(event->state) & ~irrelevant) + if ((key.mask == 0 || evas_key_modifier_is_set(ev->modifiers, key.mask)) + && (key.modkey == ad->current_modkey + || (!key.modkey && !ad->current_modkey) + || key.modkey == '*' ) // wildcard + && !strcmp(key.key, ev->key) + && key.func) + if (key.func(&key.arg, data)) { + // printf("process_keypress() function for mask = %s modkey = %c key = %s called.\n", key.mask, ad->current_modkey, key.key); + ad->current_modkey = ad->count = 0; + update_state(data); + return TRUE; + } + walk = walk->next; + } + return FALSE; +} + +void +webview_keypress_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Arg a = { .i = ModeNormal, .s = NULL }; + // int keyval; + Evas_Event_Key_Down *ev = event_info; + Buffer_Data *td = data; + App_Data *ad = td->app; + // GdkModifierType irrelevant; + + /* Get a mask of modifiers that shouldn't be considered for this event. + * E.g.: It shouldn't matter whether ';' is shifted or not. */ + // gdk_keymap_translate_keyboard_state(keymap, event->hardware_keycode, + // event->state, event->group, &keyval, NULL, NULL, &irrelevant); + + switch (ad->mode) { + case ModeNormal: + // if ((CLEAN(event->state) & ~irrelevant) == 0) { + if (IS_ESCAPE(ev)) { + a.i = Info; + a.s = strdup(""); + echo(&a, ad); + elm_box_clear(ad->event_box); + evas_object_hide(ad->event_box); + free(a.s); + } else if (ad->current_modkey == 0 && + (( strcmp(ev->key, "1") >= 0 && strcmp(ev->key, "9") <= 0) + || (!strcmp(ev->key, "0") && ad->count))) { + // ad->count = (ad->count ? ad->count * 10 : 0) + (ev->key - "0"); + ad->count = (ad->count ? ad->count * 10 : 0) + atoi(ev->key); + update_state(ad); + return; + } else if (strchr(ad->modkeys, ev->key[0]) && ad->current_modkey != ev->key[0]) { + ad->current_modkey = ev->key[0]; + // ad->current_modkey = strdup(ev->key); + + update_state(ad); + return; + } + // } + /* keybindings */ + if (process_keypress(event_info, ad) == TRUE) return; + + break; + case ModeInsert: + if (IS_ESCAPE(ev)) { + a.i = Silent; + a.s = strdup("hints.clearFocus();"); + script(&a, ad); + free(a.s); + a.i = ModeNormal; + set(&a, ad); + // ewk_view_input_method_state_set(td->web, FALSE); + return; + } + case ModePassThrough: + if (IS_ESCAPE(ev)) { + echo(&a, ad); + set(&a, ad); + return; + } + break; + case ModeSendKey: + echo(&a, ad); + set(&a, ad); + break; + } +} + +void +xss_detected_cb(void *data, Evas_Object *obj, void *event_info) +{ + printf("xss_detected()\n"); +} + +void +icon_received_cb(void *data, Evas_Object *obj, void *event_info) +{ + printf("icon_received_cb()\n"); +} + +void +webview_hoverlink_cb(void *data, Evas_Object *obj, void *event_info) +{ + Buffer_Data *td = data; + const char *uri = elm_web_uri_get(td->web); + /* event_info is a char *link[2] where the first string contains the URL + * and the second the title of the link */ + char **link = event_info; + // char *markup; + + memset(td->app->rememberedURI, 0, 1024); + if (link && link[0]) { + // markup = g_markup_printf_escaped("<span font=\"%s\">Link: %s</span>", statusfont, link[0]); + // markup = strdup_printf("<font=Monospace font_size=10 color=#FF0>%s", link[0]); + // gtk_label_set_markup(GTK_LABEL(td->app->status_url), markup); + // elm_object_text_set(td->app->status_url, markup); + update_url(link[0], td->app); + strcpy(td->app->rememberedURI, link[0]); + // free(markup); + } else + update_url(uri, td->app); +} + +void +webview_hoverlink_out_cb(void *data, Evas_Object *obj, void *event_info) +{ + Buffer_Data *td = data; + update_url(elm_web_uri_get(td->web), td->app); +} + +void +webview_console_cb(void *data, Evas_Object *obj, const char *message, unsigned int line, const char *source) +{ + Arg a; + Buffer_Data *td = data; + + /* Don't change internal mode if the browser doesn't have focus to prevent inconsistent states */ + // if (gtk_window_has_toplevel_focus(window)) { + if (elm_object_focus_get(td->app->win)) { + if (!strcmp(message, "hintmode_off") || !strcmp(message, "insertmode_off")) { + a.i = ModeNormal; + set(&a, td->app); + return; + } else if (!strcmp(message, "insertmode_on")) { + a.i = ModeInsert; + set(&a, td->app); + return; + } + } +} + +void +inputbox_activate_cb(void *data, Evas_Object *obj, void *event_info) +{ + const char *text; + App_Data *ad = data; + uint16_t length = strlen(elm_entry_entry_get(ad->url)); + Arg a; + Eina_Bool forward = FALSE; + + // printf("In inputbox_activate\n"); + + a.i = HideCompletion; + complete(&a, data); + if (length == 0) + return; + text = elm_entry_entry_get(ad->url); + if (length > 1 && text[0] == ':') { + process_line((text + 1), data); + } else if (length > 1 && ((forward = text[0] == '/') || text[0] == '?')) { + // webkit_web_view_unmark_text_matches(webview); + elm_web_text_matches_unmark_all(ad->cur_buf->web); + + // webkit_web_view_mark_text_matches(webview, &text[1], FALSE, 0); + // webkit_web_view_set_highlight_text_matches(webview, TRUE); + elm_web_text_matches_mark(ad->cur_buf->web, &text[1], EINA_FALSE, EINA_TRUE, 0); + + ad->count = 0; + ad->search_direction = forward; + ad->search_handle = strdup(&text[1]); + } else if (text[0] == '.' || text[0] == ',' || text[0] == ';') { + a.i = Silent; + a.s = strdup("hints.fire();"); + script(&a, data); + free(a.s); + update_state(data); + } else + return; + if (!ad->echo_active) + // gtk_entry_set_text(entry, ""); + elm_entry_entry_set(ad->url, ""); + // gtk_widget_grab_focus(GTK_WIDGET(webview)); + + /* process_line above may have deleted the tab, check if its still around */ + if (ad->cur_buf->web) + elm_object_focus_set(ad->cur_buf->web, EINA_TRUE); +} + +static Eina_Bool +commandhistoryfetch(const Arg *arg, void *data) +{ + App_Data *ad = data; + char *command; + const int length = eina_list_count(ad->commandhistory); + + if (length > 0) { + if (arg->i == DirectionPrev) { + ad->commandpointer = (length + ad->commandpointer - 1) % length; + } else { + ad->commandpointer = (length + ad->commandpointer + 1) % length; + } + + command = eina_list_nth(ad->commandhistory, ad->commandpointer); + // gtk_entry_set_text(GTK_ENTRY(inputbox), g_strconcat(":", command, NULL)); + // gtk_editable_set_position(GTK_EDITABLE(inputbox), -1); + command = strdup_printf(":%s", command); + elm_entry_entry_set(ad->url, command); + free(command); + elm_entry_cursor_line_end_set(ad->url); + return TRUE; + } + + return FALSE; +} + +void +inputbox_keypress_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Arg a; + int numval; + Evas_Event_Key_Down *ev = event_info; + App_Data *ad = data; + + if (ad->mode == ModeHints) { + // if (event->keyval == GDK_ISO_Left_Tab) { + if (!strcmp(ev->keyname, "Tab") && evas_key_modifier_is_set(ev->modifiers, "Shift")) { + a.i = Silent; + a.s = strdup("hints.focusPreviousHint();"); + script(&a, data); + free(a.s); + update_state(data); + return; + } + // if (event->keyval == GDK_Tab) { + if (!strcmp(ev->keyname, "Tab")) { + a.i = Silent; + a.s = strdup("hints.focusNextHint();"); + script(&a, data); + free(a.s); + update_state(data); + return; + } + // if (event->keyval == GDK_Return) { + if (!strcmp(ev->keyname, "Return")) { + a.i = Silent; + a.s = strdup_printf("hints.fire();"); + script(&a, data); + free(a.s); + update_state(data); + return; + } + } + if (!strcmp(ev->keyname, "[") || !strcmp(ev->keyname, "Escape")) { + a.i = HideCompletion; + complete(&a, data); + a.i = ModeNormal; + ad->commandpointer = 0; + set(&a, data); + return; + } + else if (!strcmp(ev->keyname, "Tab") && evas_key_modifier_is_set(ev->modifiers, "Shift")) { + a.i = DirectionPrev; + complete(&a, data); + return; + } + else if (!strcmp(ev->keyname, "Tab")) { + a.i = DirectionNext; + complete(&a, data); + return; + } + else if (!strcmp(ev->keyname, "Up")) { + a.i = DirectionPrev; + commandhistoryfetch(&a, data); + return; + } + else if (!strcmp(ev->keyname, "Down")) { + a.i = DirectionNext; + commandhistoryfetch(&a, data); + return; + } + + /* + switch (event->keyval) { + case GDK_bracketleft: + case GDK_Escape: + if (!IS_ESCAPE(event)) break; + a.i = HideCompletion; + complete(&a, data); + a.i = ModeNormal; + commandpointer = 0; + return set(&a, ad); + break; + case GDK_Tab: + a.i = DirectionNext; + return complete(&a, data); + break; + case GDK_Up: + a.i = DirectionPrev; + return commandhistoryfetch(&a); + break; + case GDK_Down: + a.i = DirectionNext; + return commandhistoryfetch(&a); + break; + case GDK_ISO_Left_Tab: + a.i = DirectionPrev; + return complete(&a, data); + break; + } + */ + + if (ad->mode == ModeHints) { +#if 0 + if ((CLEAN(event->state) & GDK_SHIFT_MASK) && + (CLEAN(event->state) & GDK_CONTROL_MASK) && + (event->keyval == GDK_BackSpace)) { + count /= 10; + a.i = Silent; + a.s = g_strdup_printf("hints.updateHints(%d);", count); + script(&a, data); + g_free(a.s); + update_state(); + return TRUE; + } +#endif + + // numval = g_unichar_digit_value((gunichar) gdk_keyval_to_unicode(event->keyval)); + numval = atoi(ev->key); + if ((numval >= 1 && numval <= 9) || (numval == 0 && ad->count)) { + /* allow a zero as non-first number */ + ad->count = (ad->count ? ad->count * 10 : 0) + numval; + a.i = Silent; + a.s = strdup_printf("hints.updateHints(%d);", ad->count); + script(&a, data); + free(a.s); + update_state(data); + return; + } + } +} + +void +inputmethod_changed_cb(void *data, Evas_Object *obj, void *event_info) +{ + const char *value; + Eina_Bool *enabled = event_info; + Buffer_Data *td = data; + App_Data *ad = td->app; + Evas_Object *frame = ewk_view_frame_main_get(td->view); + + if (ad->mode == ModeNormal && enabled) { + Arg a = { .i = ModeInsert }; + set(&a, ad); + ad->manual_focus = TRUE; + } else if (ad->mode == ModeInsert && !enabled) { + Arg a = { .i = ModeNormal }; + set(&a, ad); + } else { + // char *value = NULL, *message = NULL; + // jsapi_evaluate_script("window.getSelection().focusNode", &value, &message, ad); + value = ewk_frame_script_execute(frame, "window.getSelection().focusNode"); + if (value && !strcmp(value, "[object HTMLFormElement]")) { + Arg a = { .i = ModeInsert, .s = NULL }; + set(&a, ad); + ad->manual_focus = TRUE; + } + // free(value); + eina_stringshare_del(value); + // free(message); + } +} + +/* +static void +// notify_event_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) { +notify_event_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + int i; + // WebKitHitTestResult *result; + // WebKitHitTestResultContext context; + Ewk_Hit_Test *result; + Ewk_Hit_Test_Result_Context context; + + Evas_Event_Mouse_Up *ev = event_info; + Buffer_Data *td = data; + App_Data *ad = td->app; + + Evas_Object *view = elm_web_webkit_view_get(td->web); + Evas_Object *frame = ewk_view_frame_main_get(view); + + // if (mode == ModeNormal && event->type == GDK_BUTTON_RELEASE) { + if (ad->mode == ModeNormal) { + // handle mouse click events + for (i = 0; i < LENGTH(mouse); i++) { + // if (mouse[i].mask == CLEAN(event->button.state) + if ( (mouse[i].mask == 0 || evas_key_modifier_is_set(ev->modifiers, mouse[i].mask)) + // && (mouse[i].modkey == current_modkey + && ((ad->current_modkey && !strcmp(mouse[i].modkey, ad->current_modkey)) + || (!mouse[i].modkey && !ad->current_modkey) + // || mouse[i].modkey == GDK_VoidSymbol) // wildcard + || !strcmp(mouse[i].modkey, "*")) // wildcard + // && mouse[i].button == event->button.button + && (mouse[i].button & ev->button) + && mouse[i].func) { + if (mouse[i].func(&mouse[i].arg, ad)) { + // current_modkey = count = 0; + ad->current_modkey = NULL; + ad->count = 0; + update_state(ad); + return TRUE; + } + } + } + // result = webkit_web_view_get_hit_test_result(WEBKIT_WEB_VIEW(widget), (GdkEventButton*)event); + result = ewk_frame_hit_test_new(frame, ev->canvas.x, ev->canvas.y); + context = result->context; + + // g_object_get(result, "context", &context, NULL); + // if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE) { + if (context & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE) { + Arg a = { .i = ModeInsert }; + set(&a, ad); + ad->manual_focus = TRUE; + } + // } else if (mode == ModeInsert && event->type == GDK_BUTTON_RELEASE) { + } else if (ad->mode == ModeInsert) { + //result = webkit_web_view_get_hit_test_result(WEBKIT_WEB_VIEW(widget), (GdkEventButton*)event); + result = ewk_frame_hit_test_new(frame, ev->output.x, ev->output.y); + + // g_object_get(result, "context", &context, NULL); + // if (!(context & WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE)) { + if (!(context & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE)) { + Arg a = { .i = ModeNormal }; + set(&a, ad); + } + } else { + char *value = NULL, *message = NULL; + jsapi_evaluate_script("window.getSelection().focusNode", &value, &message, ad); + if (value && !strcmp(value, "[object HTMLFormElement]")) { + Arg a = { .i = ModeInsert, .s = NULL }; + set(&a, ad); + ad->manual_focus = TRUE; + } + free(value); + free(message); + } + ewk_frame_hit_test_free(result); + return FALSE; +} +*/ + +void +inputbox_keyrelease_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Arg a; + App_Data *ad = data; + // guint16 length = gtk_entry_get_text_length(entry); + uint16_t length = strlen(elm_entry_entry_get(ad->url)); + + if (!length) { + a.i = HideCompletion; + complete(&a, data); + a.i = ModeNormal; + set(&a, data); + } +} + +/* used for incremental search */ +void +inputbox_changed_cb(void *data, Evas_Object *obj, void *event_info) +{ + Arg a; + App_Data *ad = data; + const char *text = elm_entry_entry_get(ad->url); + uint16_t length = strlen(text); + Eina_Bool forward = FALSE; + + /* Update incremental search if the user changes the search text. + * + * Note: gtk_widget_is_focus() is a poor way to check if the change comes + * from the user. But if the entry is focused and the text is set + * through gtk_entry_set_text() in some asyncrounous operation, + * I would consider that a bug. + */ + + // if (gtk_widget_is_focus(GTK_WIDGET(entry)) && length > 1 && ((forward = text[0] == '/') || text[0] == '?')) { + if (elm_object_focus_get(ad->url) && length > 1 && ((forward = text[0] == '/') || text[0] == '?')) { + // webkit_web_view_unmark_text_matches(webview); + elm_web_text_matches_unmark_all(ad->cur_buf->web); + + // webkit_web_view_search_text(webview, &text[1], searchoptions & CaseSensitive, forward, searchoptions & Wrapping); + elm_web_text_search(ad->cur_buf->web, &text[1], EINA_TRUE, forward, EINA_FALSE); + return; + // } else if (gtk_widget_is_focus(GTK_WIDGET(entry)) && length >= 1 && + } else if (elm_object_focus_get(ad->url) && length >= 1 && + (text[0] == '.' || text[0] == ',' || text[0] == ';')) { + a.i = Silent; + switch (text[0]) { + case '.': + // a.s = strconcat("hints.createHints('", text + 1, "', 'f');", NULL); + a.s = strdup_printf("hints.createHints('%s', 'f');", text + 1); + break; + + case ',': + // a.s = strconcat("hints.createHints('", text + 1, "', 'F');", NULL); + a.s = strdup_printf("hints.createHints('%s', 'F');", text + 1); + break; + + case ';': + a.s = NULL; + switch (text[1]) { + case 's': + // a.s = strconcat("hints.createHints('", text + 2, "', 's');", NULL); + a.s = strdup_printf("hints.createHints('%s', 's');", text + 2); + break; + case 'y': + // a.s = strconcat("hints.createHints('", text + 2, "', 'y');", NULL); + a.s = strdup_printf("hints.createHints('%s', 'y');", text + 2); + break; + case 'o': + // a.s = strconcat("hints.createHints('", text + 2, "', 'f');", NULL); + a.s = strdup_printf("hints.createHints('%s', 'f');", text + 2); + break; + case 't': case 'w': + // a.s = strconcat("hints.createHints('", text + 2, "', 'F');", NULL); + a.s = strdup_printf("hints.createHints('%s', 'F');", text + 2); + break; + case 'O': case 'T': case 'W': + // a.s = strconcat("hints.createHints('", text + 2, "', 'O');", NULL); + a.s = strdup_printf("hints.createHints('%s', 'O');", text + 2); + break; + case 'i': + // a.s = strconcat("hints.createHints('", text + 2, "', 'i');", NULL); + a.s = strdup_printf("hints.createHints('%s', 'i');", text + 2); + break; + case 'I': + // a.s = strconcat("hints.createHints('", text + 2, "', 'I');", NULL); + a.s = strdup_printf("hints.createHints('%s', 'I');", text + 2); + break; + } + break; + } + ad->count = 0; + if (a.s) { + script(&a, data); + free(a.s); + } + + return; + } else if (length == 0 && ad->followTarget[0]) { + ad->mode = ModeNormal; + a.i = Silent; + a.s = strdup("hints.clearHints();"); + script(&a, data); + free(a.s); + ad->count = 0; + update_state(data); + } +} + diff --git a/callbacks.h b/callbacks.h @@ -0,0 +1,35 @@ + + +void inputbox_activate_cb (void *, Evas_Object *, void *); +void inputbox_changed_cb (void *, Evas_Object *, void *); +void inputbox_keypress_cb (void *, Evas *, Evas_Object *, void *); +void inputbox_keyrelease_cb (void *, Evas *, Evas_Object *, void *); + +void webview_console_cb(void *, Evas_Object *, const char *, unsigned int, const char *); +void webview_hoverlink_cb (void *, Evas_Object *, void*); +void webview_hoverlink_out_cb (void *, Evas_Object *, void*); +void webview_uri_changed_cb (void *, Evas_Object *, void*); +void webview_load_finished_cb (void *, Evas_Object *, void*); +void webview_document_finished_cb(void *, Evas_Object *, void*); +void webview_progress_changed_cb(void *, Evas_Object *, void *); +void webview_title_changed_cb (void *, Evas_Object *, void *); +void webview_download_cb (void *, Evas_Object *, void *); +void inputmethod_changed_cb (void *, Evas_Object *, void *); +void icon_received_cb (void *, Evas_Object *, void *); +void xss_detected_cb (void *, Evas_Object *, void *); +void webview_inspector_cb (void *, Evas_Object *, void *); +void webview_inspector_close_cb (void *, Evas_Object *, void *); +void protocol_register_cb (void *, Evas_Object *, void *); +void load_error_cb (void *, Evas_Object *, void *); +void webview_keypress_cb (void *, Evas *, Evas_Object *, void *); +void webview_mousewheel_cb (void *, Evas *, Evas_Object *, void *); + +void download_entry_free_cb(void *); + +/* +static Eina_Bool webview_mimetype_cb(WebKitWebView *webview, WebKitWebFrame *frame, WebKitNetworkRequest *request, char *mime_type, WebKitWebPolicyDecision *decision, gpointer user_data); +static void webview_open_js_window_cb(WebKitWebView* temp_view, GParamSpec param_spec); +static Eina_Bool webview_new_window_cb(WebKitWebView *webview, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *action, WebKitWebPolicyDecision *decision, gpointer user_data); +static WebKitWebView* webview_open_in_new_window_cb(WebKitWebView *webview, WebKitWebFrame *frame, gpointer user_data); +*/ + diff --git a/commands.c b/commands.c @@ -4,13 +4,13 @@ #include <libsoup/soup.h> #include "viking.h" +#include "viking_state.h" #include "commands.h" #include "utilities.h" #include "main.h" -extern unsigned int scrollstep; -extern unsigned int pagingkeep; -extern char defaultsearch[MAX_SETTING_SIZE]; +static unsigned int scrollstep = 40; /* cursor difference in pixel */ +static unsigned int pagingkeep = 40; /* pixels kept when paging */ void fill_suggline(char * suggline, const char * command, const char *fill_with); @@ -466,6 +466,8 @@ number(const Arg *arg, void *data) return TRUE; } +static char defaultsearch[MAX_SETTING_SIZE] = "d"; + Eina_Bool open_arg(const Arg *arg, void *data) { @@ -1382,29 +1384,34 @@ list(const Arg *arg, void *data) elm_box_pack_end(ad->event_box, row); evas_object_show(row); - icon = ewk_settings_icon_database_icon_object_get(elm_web_uri_get(td->web), e); - // evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(icon, 0.0, EVAS_HINT_FILL); - evas_object_size_hint_max_set(icon, 16, 16); - evas_object_size_hint_min_set(icon, 16, 16); - elm_box_pack_end(row, icon); - evas_object_show(icon); - label = elm_label_add(ad->win); // evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL); elm_box_pack_end(row, label); evas_object_show(label); - count_str = strdup_printf("<font=Monospace font_size=12>%i. ", td->buf_number); - elm_object_text_set(label, count_str); - free(count_str); + char status_buf[512] = ""; + strcat(status_buf, "<font=Monospace font_size=12 backing=on backing_color=#FFF>"); + + char *flags_str = status_flags(td); + strcat(status_buf, flags_str); + free(flags_str); + + elm_object_text_set(label, status_buf); + + icon = ewk_settings_icon_database_icon_object_get(elm_web_uri_get(td->web), e); + // evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(icon, 0.0, EVAS_HINT_FILL); + evas_object_size_hint_max_set(icon, 14, 14); + evas_object_size_hint_min_set(icon, 14, 14); + elm_box_pack_end(row, icon); + evas_object_show(icon); label = elm_label_add(ad->win); evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL); elm_box_pack_end(row, label); evas_object_show(label); - url = strdup_printf("<font=Monospace font_size=12>%s", elm_web_uri_get(td->web)); + url = strdup_printf("<font=Monospace font_size=12 backing=on backing_color=#FFF>%s", elm_web_uri_get(td->web)); elm_object_text_set(label, url); free(url); @@ -1413,7 +1420,7 @@ list(const Arg *arg, void *data) evas_object_size_hint_align_set(label, 1.0, EVAS_HINT_FILL); elm_box_pack_end(row, label); evas_object_show(label); - count_str = strdup_printf("<font=Monospace font_size=12>%s", elm_web_title_get(td->web)); + count_str = strdup_printf("<font=Monospace font_size=12 backing=on backing_color=#FFF>%s", elm_web_title_get(td->web)); elm_object_text_set(label, count_str); free(count_str); } @@ -1421,6 +1428,29 @@ list(const Arg *arg, void *data) evas_object_show(ad->event_box); + /* + elm_layout_sizing_eval(ad->event_box); + + int x, y, w, h; + evas_object_geometry_get(ad->event_box, &x, &y, &w, &h); + printf("list() event_box is (x, y, w, h) = (%i, %i, %i, %i)\n", x, y, w, h); + evas_object_move(ad->event_box_bg, x, y); + evas_object_resize(ad->event_box_bg, w, 100); + evas_object_show(ad->event_box_bg); + */ + + + /* + bg = evas_object_rectangle_add(evas_object_evas_get(ad->win)); + // bg = elm_bg_add(ad->event_box); + evas_object_color_set(bg, 255, 255, 255, 255); + evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(bg, EVAS_HINT_FILL, EVAS_HINT_FILL); + // elm_box_pack_end(ad->event_box, bg); + evas_object_show(bg); + ecore_evas_object_associate(ecore_evas_ecore_evas_get(evas_object_evas_get(ad->win)), bg, ECORE_EVAS_OBJECT_ASSOCIATE_BASE); + */ + return EINA_TRUE; } diff --git a/commands.h b/commands.h @@ -1,7 +1,4 @@ -// #include "config.h" -// #include "utilities.h" - Eina_Bool complete(const Arg *, void *); Eina_Bool script(const Arg *, void *); Eina_Bool open_arg(const Arg *, void *); @@ -36,7 +33,7 @@ Eina_Bool toggle_history(const Arg *, void *); Eina_Bool process_set_line(char *line); -extern char startpage[MAX_SETTING_SIZE]; +// extern char startpage[MAX_SETTING_SIZE]; /* command mapping */ static Command commands[COMMANDSIZE] = { diff --git a/config.h b/config.h @@ -1,155 +0,0 @@ -/* - (c) 2009 by Leon Winter - (c) 2009-2012 by Hannes Schueller - (c) 2009-2010 by Matto Fransen - (c) 2010-2011 by Hans-Peter Deifel - (c) 2010-2011 by Thomas Adam - (c) 2011 by Albert Kim - see LICENSE file -*/ - -/* Vimprobable version number */ -#define VERSION "1" -#define INTERNAL_VERSION "Evi/"VERSION - -/* general settings */ -char startpage[MAX_SETTING_SIZE] = "http://www.getaddrinfo.net/"; -// static char useragent[MAX_SETTING_SIZE] = "Vimprobable2/" VERSION; -// static char acceptlanguage[MAX_SETTING_SIZE] = ""; -static const Eina_Bool enablePlugins = TRUE; /* TRUE keeps plugins enabled */ -static const Eina_Bool enableJava = TRUE; /* FALSE disables Java applets */ -static const Eina_Bool enablePagecache = FALSE; /* TRUE turns on the page cache. */ -static Eina_Bool escape_input_on_load = TRUE; /* TRUE will disable automatic focusing of input fields via Javascript*/ - -/* appearance */ -// static char statusbgcolor[MAX_SETTING_SIZE] = "#000"; /* background color for status bar */ -// static char statuscolor[MAX_SETTING_SIZE] = "#FFF"; /* color for status bar */ -// static char sslbgcolor[MAX_SETTING_SIZE] = "#b0ff00"; /* background color for status bar with SSL url */ -// static char sslinvalidbgcolor[MAX_SETTING_SIZE]= "#ff0000"; /* background color for status bar with unverified SSL url */ -// static char sslcolor[MAX_SETTING_SIZE] = "#0F0"; /* color for status bar with SSL url */ - - /* normal, warning, error */ -static const char *urlboxfont[] = { "monospace normal 8", "monospace normal 8", "monospace bold 8"}; -static const char *urlboxcolor[] = { NULL, "#ff0000", "#ffffff" }; -static const char *urlboxbgcolor[] = { NULL, NULL, "#ff0000" }; - - /* normal, error */ -// static const char *completionfont[] = { "monospace normal 8", "monospace bold 8" }; - /* topborder color */ -static const unsigned char completioncolor[][3] = { {0, 0, 0}, {255, 0, 255}, {0, 0, 0} }; -/* current row background */ -static const unsigned char completionbgcolor[][3] = { {255, 255, 255}, {255, 255, 255}, {255, 240, 0} }; -/* pango markup for prefix highliting: opening, closing */ -#define COMPLETION_TAG_OPEN "<b>" -#define COMPLETION_TAG_CLOSE "</b>" - -static const char statusfont[] = "monospace bold 8"; /* font for status bar */ -static const int progressbartick = 20; -static const char progressborderleft = '['; -static const char progressbartickchar = '='; -static const char progressbarcurrent = '>'; -static const char progressbarspacer = ' '; -static const char progressborderright = ']'; - -/* external handlers: - * the handle (first string) contain what the handled links have to start with - * the handlers (second string) contain the external applications which should be called for this sort of link - * %s can be used as a placeholder for the link argument after the handler - * e.g.: "mailto:user@example.org - * "handle" is "mailto:" - * "%s" will translate to "user@example.org" - */ -static URIHandler uri_handlers[] = { - { "mailto:", "x-terminal-emulator -e mutt %s" }, - { "ftp://", "x-terminal-emulator -e wget ftp://%s" }, -}; - -/* cookies */ -#define ENABLE_COOKIE_SUPPORT -#define COOKIES_STORAGE_FILENAME "%s/evi/cookies", config_base -#define COOKIES_STORAGE_READONLY FALSE /* if TRUE new cookies will be lost if you quit */ - -/* downloads directory */ -#define DOWNLOADS_PATH "%s", getenv("HOME") - -/* font size */ -#define DEFAULT_FONT_SIZE 12 - -/* user styles */ -#define USER_STYLESHEET "%s/evi/style.css", config_base - -/* ssl */ -static Eina_Bool strict_ssl = TRUE; /* FALSE will accept any SSL certificate at face value */ -static char ca_bundle[MAX_SETTING_SIZE] = "/etc/ssl/certs/ca-certificates.crt"; - -/* proxy */ -static const Eina_Bool use_proxy = TRUE; /* TRUE if you're going to use a proxy (whose address - is specified in http_proxy environment variable), false otherwise */ -/* scrolling */ -unsigned int scrollstep = 40; /* cursor difference in pixel */ -unsigned int pagingkeep = 40; /* pixels kept when paging */ -#define DISABLE_SCROLLBAR - -/* searching */ -#define ENABLE_MATCH_HIGHLITING -static const int searchoptions = CaseInsensitive | Wrapping; -Eina_Bool complete_case_sensitive = TRUE; - -/* search engines */ -static Searchengine searchengines[] = { - { "d", "https://duckduckgo.com/?q=%s&t=Vimprobable" }, - { "i", "http://ixquick.com/do/metasearch.pl?query=%s" }, - { "w", "https://secure.wikimedia.org/wikipedia/en/w/index.php?title=Special%%3ASearch&search=%s&go=Go" }, - { "wd", "https://secure.wikimedia.org/wikipedia/de/w/index.php?title=Special%%3ASearch&search=%s&go=Go" }, - { "dd", "https://duckduckgo.com/html/?q=%s&t=Vimprobable" }, -}; - -char defaultsearch[MAX_SETTING_SIZE] = "d"; - -#if 0 -/* settings (arguments of :set command) */ -static Setting browsersettings[] = { -/* public name, internal variwebkit setting integer ? bool? colour? reload page? */ - { "useragent", useragent, "user-agent", FALSE, FALSE, FALSE, FALSE }, - { "scripts", NULL, "enable-scripts", FALSE, TRUE, FALSE, FALSE }, - { "plugins", NULL, "enable-plugins", FALSE, TRUE, FALSE, FALSE }, - { "pagecache", NULL, "enable-page-cache", FALSE, TRUE, FALSE, FALSE }, - { "java", NULL, "enable-java-applet", FALSE, TRUE, FALSE, FALSE }, - { "images", NULL, "auto-load-images", FALSE, TRUE, FALSE, FALSE }, - { "shrinkimages", NULL, "auto-shrink-images", FALSE, TRUE, FALSE, FALSE }, - { "cursivefont", NULL, "cursive-font-family", FALSE, FALSE, FALSE, FALSE }, - { "defaultencoding", NULL, "default-encoding", FALSE, FALSE, FALSE, FALSE }, - { "defaultfont", NULL, "default-font-family", FALSE, FALSE, FALSE, FALSE }, - { "fontsize", NULL, "default-font-size", TRUE, FALSE, FALSE, FALSE }, - { "monofontsize", NULL, "default-monospace-font-size", TRUE, FALSE, FALSE, FALSE }, - { "caret", NULL, "enable-caret-browsing", FALSE, TRUE, FALSE, FALSE }, - { "fantasyfont", NULL, "fantasy-font-family", FALSE, FALSE, FALSE, FALSE }, - { "minimumfontsize", NULL, "minimum-font-size", TRUE, FALSE, FALSE, FALSE }, - { "monofont", NULL, "monospace-font-family", FALSE, FALSE, FALSE, FALSE }, - { "backgrounds", NULL, "print-backgrounds", FALSE, TRUE, FALSE, FALSE }, - { "sansfont", NULL, "sans-serif-font-family", FALSE, FALSE, FALSE, FALSE }, - { "seriffont", NULL, "serif-font-family", FALSE, FALSE, FALSE, FALSE }, - { "stylesheet", NULL, "user-stylesheet-uri", FALSE, FALSE, FALSE, FALSE }, - { "resizetextareas", NULL, "resizable-text-areas", FALSE, TRUE, FALSE, FALSE }, - { "webinspector", NULL, "enable-developer-extras", FALSE, TRUE, FALSE, FALSE }, - - { "homepage", startpage, "", FALSE, FALSE, FALSE, FALSE }, - { "statusbgcolor", statusbgcolor,"", FALSE, FALSE, TRUE, TRUE }, - { "statuscolor", statuscolor, "", FALSE, FALSE, TRUE, TRUE }, - { "sslbgcolor", sslbgcolor, "", FALSE, FALSE, TRUE, TRUE }, - { "sslcolor", sslcolor, "", FALSE, FALSE, TRUE, TRUE }, - { "acceptlanguage", acceptlanguage, "", FALSE, FALSE, FALSE, FALSE }, - { "defaultsearch", defaultsearch, "", FALSE, FALSE, FALSE, FALSE }, - { "qmark", NULL, "", FALSE, FALSE, FALSE, FALSE }, - { "proxy", NULL, "", FALSE, TRUE, FALSE, FALSE }, - { "windowsize", NULL, "", FALSE, FALSE, FALSE, FALSE }, - { "scrollbars", NULL, "", FALSE, TRUE, FALSE, FALSE }, - { "statusbar", NULL, "", FALSE, TRUE, FALSE, FALSE }, - { "inputbox", NULL, "", FALSE, TRUE, FALSE, FALSE }, - { "completioncase", NULL, "", FALSE, TRUE, FALSE, FALSE }, - { "escapeinput", NULL, "", FALSE, TRUE, FALSE, FALSE }, - { "strictssl", NULL, "", FALSE, TRUE, FALSE, FALSE }, - { "cabundle", ca_bundle, "", FALSE, FALSE, FALSE, FALSE }, -}; -#endif - diff --git a/keymap.h b/keymap.h @@ -83,8 +83,8 @@ static Key keys[] = { { 0, 'g', "u", descend, {NthSubdir} }, { 0, 'g', "U", descend, {Rootdir} }, - { 0, 'g', "h", open_arg, {TargetCurrent, startpage} }, - { 0, 'g', "H", open_arg, {TargetNew, startpage} }, + { 0, 'g', "h", open_arg, {TargetCurrent, DEFAULT_URL} }, + { 0, 'g', "H", open_arg, {TargetNew, DEFAULT_URL} }, { "Control", 0, "p", proxy, {0} }, { 0, 0, "p", paste, {TargetCurrent | ClipboardPrimary | ClipboardGTK} }, diff --git a/main.c b/main.c @@ -16,10 +16,11 @@ #include "javascript.h" #include "viking.h" +#include "viking_state.h" #include "main.h" #include "commands.h" #include "utilities.h" -#include "config.h" +#include "callbacks.h" #include "keymap.h" #include <stdio.h> /* asprintf() */ @@ -29,53 +30,12 @@ EAPI_MAIN int elm_main(int argc, char *argv[]); -#define IS_ESCAPE(ev) ((!strcmp(ev->keyname, "Escape")) || \ - (!strcmp(ev->keyname, "[") && evas_key_modifier_is_set(ev->modifiers, "Control"))) - - -/* callbacks here */ -static void inputbox_activate_cb (void *, Evas_Object *, void *); -static void inputbox_changed_cb (void *, Evas_Object *, void *); -static Eina_Bool commandhistoryfetch (const Arg *, void *); -static void inputbox_keypress_cb (void *, Evas *, Evas_Object *, void *); -static void inputbox_keyrelease_cb (void *, Evas *, Evas_Object *, void *); - -static void webview_console_cb(void *, Evas_Object *, const char *, unsigned int, const char *); -static void webview_hoverlink_cb (void *, Evas_Object *, void*); -static void webview_hoverlink_out_cb (void *, Evas_Object *, void*); -static void webview_uri_changed_cb (void *, Evas_Object *, void*); -static void webview_load_finished_cb (void *, Evas_Object *, void*); -static void webview_document_finished_cb(void *, Evas_Object *, void*); -static void history(void *); -static void webview_progress_changed_cb(void *, Evas_Object *, void *); -static void webview_title_changed_cb (void *, Evas_Object *, void *); -static void webview_download_cb (void *, Evas_Object *, void *); -static void inputmethod_changed_cb (void *, Evas_Object *, void *); -static void icon_received_cb (void *, Evas_Object *, void *); -static void xss_detected_cb (void *, Evas_Object *, void *); -static void webview_inspector_cb (void *, Evas_Object *, void *); -static Eina_Bool process_keypress (void *, void*); -static void webview_keypress_cb (void *, Evas *, Evas_Object *, void *); -static void webview_mousewheel_cb (void *, Evas *, Evas_Object *, void *); -Evas_Object *webview_create_window_cb(void*, Evas_Object*, Eina_Bool, const Elm_Web_Window_Features*); - -/* -static WebKitWebView* inspector_inspect_web_view_cb(gpointer inspector, WebKitWebView* web_view); -static Eina_Bool webview_mimetype_cb(WebKitWebView *webview, WebKitWebFrame *frame, WebKitNetworkRequest *request, char *mime_type, WebKitWebPolicyDecision *decision, gpointer user_data); -static void webview_open_js_window_cb(WebKitWebView* temp_view, GParamSpec param_spec); -static Eina_Bool webview_new_window_cb(WebKitWebView *webview, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *action, WebKitWebPolicyDecision *decision, gpointer user_data); -static WebKitWebView* webview_open_in_new_window_cb(WebKitWebView *webview, WebKitWebFrame *frame, gpointer user_data); -*/ +Evas_Object *webview_create_window_cb(void*, Evas_Object*, Eina_Bool, const Elm_Web_Window_Features*); /* functions */ static void ascii_bar(int total, int state, char *string); -// static char *jsapi_ref_to_string(JSContextRef context, JSValueRef ref); -// static void jsapi_evaluate_script(const gchar *script, gchar **value, gchar **message, void *data); -static void set_widget_font_and_color(Evas_Object *widget, const char *font_str, const char *bg_color_str, const char *fg_color_str); -void download_complete_cb(void*, const char*, int); -int download_progress_cb(void*, const char*, long int, long int, long int, long int); - +char *uri_sanitize(const char *); Eina_Bool enable_proxy(Buffer_Data *bd) @@ -109,6 +69,14 @@ enable_proxy(Buffer_Data *bd) } } +static const char statusfont[] = "monospace bold 8"; /* font for status bar */ +static const int progressbartick = 20; +static const char progressborderleft = '['; +static const char progressbartickchar = '='; +static const char progressbarcurrent = '>'; +static const char progressbarspacer = ' '; +static const char progressborderright = ']'; + static void ascii_bar(int total, int state, char *string) { @@ -227,48 +195,72 @@ update_state(void *data) // recalculate_status_bar(data); } -static void +char* +/* must free() the return value */ +status_flags(void *data) +{ + char *end; + Buffer_Data *bd = data; + char *flags = calloc(32, 1); + + strcat(flags, "["); + strcat(flags, bd->proxy_enabled ? "P" : " "); + strcat(flags, bd->inspector_enabled ? "I" : " "); + strcat(flags, bd->history_enabled ? "H" : " "); + end = strdup_printf("] %i ", bd->buf_number); + strcat(flags, end); + free(end); + + return flags; +} + +void update_url(const char *uri, void *data) { - char *markup; + char *tmp; char before[] = " ["; char after[] = "]"; + char url_buf[1024] = ""; + App_Data *ad = data; + Buffer_Data *bd = ad->cur_buf; if (uri == NULL) return; - App_Data *ad = data; - Eina_Bool back = elm_web_back_possible_get(ad->cur_buf->web); - Eina_Bool fwd = elm_web_forward_possible_get(ad->cur_buf->web); + Eina_Bool back = elm_web_back_possible_get(bd->web); + Eina_Bool fwd = elm_web_forward_possible_get(bd->web); - Evas_Object *frame = ewk_view_frame_main_get(ad->cur_buf->view); + Evas_Object *frame = ewk_view_frame_main_get(bd->view); char *url_color = "#FFF"; if (!strncmp(uri, "https://", 8)) { Ewk_Certificate_Status cert_status = ewk_frame_certificate_status_get(frame); if (cert_status & EWK_CERTIFICATE_STATUS_TRUSTED) - url_color = "#0F0"; + url_color = "#6F6"; else if (cert_status & EWK_CERTIFICATE_STATUS_UNTRUSTED) - url_color = "#F00"; + url_color = "#F66"; } if (!back && !fwd) before[0] = after[0] = '\0'; - markup = strdup_printf("<font=Monospace font_size=12 color=%s backing=on backing_color=#000>%s%s%s%s%s", + strcat(url_buf, "<font=Monospace font_size=12 color=#FFF>"); + tmp = status_flags(bd); + strcat(url_buf, tmp); + free(tmp); + tmp = strdup_printf("<color=%s>%s<color=#FFF>%s%s%s%s", url_color, uri, before, back ? "+" : "", fwd ? "-" : "", after); - + strcat(url_buf, tmp); + free(tmp); int state_width, window_width; evas_object_geometry_get(ad->status_state, NULL, NULL, &state_width, NULL); evas_object_geometry_get(ad->win, NULL, NULL, &window_width, NULL); elm_label_wrap_width_set(ad->status_url, window_width - state_width); - elm_object_text_set(ad->status_url, markup); + elm_object_text_set(ad->status_url, url_buf); // elm_label_line_wrap_set(ad->status_url, ELM_WRAP_CHAR); // elm_label_ellipsis_set(ad->status_url, EINA_TRUE); - - free(markup); } Eina_Bool @@ -283,7 +275,7 @@ echo(const Arg *arg, void *data) // printf("echo(%s)\n", arg->s); // if (!gtk_widget_is_focus(GTK_WIDGET(inputbox))) { if (!elm_object_focus_get(ad->url)) { - set_widget_font_and_color(ad->url, urlboxfont[index], urlboxbgcolor[index], urlboxcolor[index]); + // set_widget_font_and_color(ad->url, urlboxfont[index], urlboxbgcolor[index], urlboxcolor[index]); // gtk_entry_set_text(GTK_ENTRY(inputbox), !arg->s ? "" : arg->s); elm_entry_entry_set(ad->url, !arg->s ? "" : arg->s); } @@ -291,520 +283,10 @@ echo(const Arg *arg, void *data) return TRUE; } -void -webview_title_changed_cb(void *data, Evas_Object *obj, void *event_info) -{ - /* - const char *title = ""; - Ewk_Text_With_Direction *dir_text = event_info; - if (event_info) title = dir_text->string; - char buf[20] = ""; - - if (title) - strncpy(buf, title, sizeof(buf) - 1); - elm_object_item_text_set(td->tab, buf); - */ -} - -void -webview_progress_changed_cb(void *data, Evas_Object *obj, void *event_info) -{ - Buffer_Data *td = data; - /* *event_info is a double between 0.0 and 1.0 */ - update_state(td->app); -} - - -static void -protocol_register_cb(void *data, Evas_Object *obj, void *event_info) -{ - printf("protocol_register()\n"); -} - -static void -webview_inspector_cb(void *data, Evas_Object *obj, void *event_info) -{ - Buffer_Data *td = data; - App_Data *ad = td->app; - - td->web_inspector = ewk_view_single_add(evas_object_evas_get(ad->win)); - ewk_view_theme_set(td->web_inspector, "/usr/share/ewebkit-0/themes/default.edj"); - - evas_object_size_hint_weight_set(td->web_inspector, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(td->web_inspector, EVAS_HINT_FILL, EVAS_HINT_FILL); - - ewk_view_web_inspector_view_set(td->view, td->web_inspector); - - evas_object_show(td->web_inspector); - elm_box_pack_end(ad->web_inspector, td->web_inspector); - - evas_object_size_hint_weight_set(ad->web_inspector, EVAS_HINT_EXPAND, 0.66); - evas_object_show(ad->web_inspector); - - /* - td->web_inspector = elm_web_add(ad->win); - - evas_object_size_hint_weight_set(td->web_inspector, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(td->web_inspector, EVAS_HINT_FILL, EVAS_HINT_FILL); - - ewk_view_web_inspector_view_set(view, elm_web_webkit_view_get(td->web_inspector)); - - evas_object_show(td->web_inspector); - elm_box_pack_end(ad->web_inspector, td->web_inspector); - - evas_object_size_hint_weight_set(ad->web_inspector, EVAS_HINT_EXPAND, 1.0); - evas_object_show(ad->web_inspector); - */ -} - -static void -webview_inspector_close_cb(void *data, Evas_Object *obj, void *event_info) -{ - Buffer_Data *td = data; - App_Data *ad = td->app; - - elm_box_clear(ad->web_inspector); - evas_object_size_hint_weight_set(ad->web_inspector, EVAS_HINT_EXPAND, 0.0); - ewk_view_web_inspector_view_set(td->view, NULL); - - td->web_inspector = NULL; -} - -void -webview_uri_changed_cb(void *data, Evas_Object *obj, void *event_info) -{ - Arg a = { .i = Silent, .s = strdup(JS_SETUP_HINTS) }; - Buffer_Data *td = data; - const char *uri = event_info; - - if (td->web != td->app->cur_buf->web) - return; - - // userscript_hooks_start(elm_web_uri_get(td->web)); - - script(&a, td->app); - free(a.s); - - /* - FILE *fp = fopen("/home/kyle/.config/evi/userscript/adblockplus/contentScript1.js", "r"); - if (!fp) - printf("error opening file.\n"); - fseek(fp, 0L, SEEK_END); - int len = ftell(fp); - char *buf = malloc(len); - rewind(fp); - fread(buf, len, 1, fp); - fclose(fp); - - ewk_frame_script_execute(frame, buf); - - free(buf); - */ - - if (td->app->mode == ModeInsert || td->app->mode == ModeHints) { - Arg a = { .i = ModeNormal }; - set(&a, td->app); - } - - td->app->manual_focus = EINA_FALSE; - update_url(uri, td->app); -} - -void -history(void *data) -{ - FILE *f; - char *filename; - // const char *uri = webkit_web_view_get_uri(webview); - // const char *title = webkit_web_view_get_title(webview); - App_Data *ad = data; - const char *uri = elm_web_uri_get(ad->cur_buf->web); - const char *title = elm_web_title_get(ad->cur_buf->web); - char *entry, buffer[512], *new; - int n, i = 0; - Eina_Bool finished = EINA_FALSE; - if (uri != NULL) { - if (title != NULL) { - entry = malloc((strlen(uri) + strlen(title) + 2) * sizeof(char)); - memset(entry, 0, strlen(uri) + strlen(title) + 2); - } else { - entry = malloc((strlen(uri) + 1) * sizeof(char)); - memset(entry, 0, strlen(uri) + 1); - } - if (entry != NULL) { - strncpy(entry, uri, strlen(uri)); - if (title != NULL) { - strncat(entry, " ", 1); - strncat(entry, title, strlen(title)); - } - n = strlen(entry); - filename = strdup_printf(HISTORY_STORAGE_FILENAME); - f = fopen(filename, "r"); - if (f != NULL) { - new = (char *)malloc(HISTORY_MAX_ENTRIES * 512 * sizeof(char) + 1); - if (new != NULL) { - memset(new, 0, HISTORY_MAX_ENTRIES * 512 * sizeof(char) + 1); - /* newest entries go on top */ - strncpy(new, entry, strlen(entry)); - strncat(new, "\n", 1); - /* retain at most HISTORY_MAX_ENTIRES - 1 old entries */ - while (finished != TRUE) { - if ((char *)NULL == fgets(buffer, 512, f)) { - /* check if end of file was reached / error occured */ - if (!feof(f)) { - break; - } - /* end of file reached */ - finished = TRUE; - continue; - } - /* compare line (-1 because of newline character) */ - if (n != strlen(buffer) - 1 || strncmp(entry, buffer, n) != 0) { - /* if the URI is already in history; we put it on top and skip it here */ - strncat(new, buffer, 512); - i++; - } - if ((i + 1) >= HISTORY_MAX_ENTRIES) { - break; - } - } - fclose(f); - } - f = fopen(filename, "w"); - free(filename); - if (f != NULL) { - fprintf(f, "%s", new); - fclose(f); - } - if (new != NULL) { - free(new); - new = NULL; - } - } - } - if (entry != NULL) { - free(entry); - entry = NULL; - } - } -} - -void -webview_document_finished_cb(void *data, Evas_Object *obj, void *event_info) -{ - // Evas_Object *frame = event_info; - printf("loca_document_finished()\n"); -} - -void -webview_load_finished_cb(void *data, Evas_Object *obj, void *event_info) -{ - /* WebKitWebSettings *settings = webkit_web_view_get_settings(webview); */ - Buffer_Data *td = data; - App_Data *ad = td->app; - Eina_Bool scripts = 1; - Elm_Web_Frame_Load_Error *frame_error = event_info; - - printf("load_finished()\n"); - -// Evas_Object *view = elm_web_webkit_view_get(td->web); -// Evas_Object *frame = ewk_view_frame_main_get(view); - - if (frame_error) - fprintf(stderr, "Error http code %i on domain %s\n%s\n", frame_error->code, frame_error->failing_url, frame_error->description); - - /* g_object_get(settings, "enable-scripts", &scripts, NULL); */ - if (escape_input_on_load && scripts && !ad->manual_focus && !elm_object_focus_get(ad->url)) { - Arg a = { .i = Silent, .s = strdup("hints.clearFocus();") }; - script(&a, ad); - free(a.s); - a.i = ModeNormal; - a.s = NULL; - set(&a, ad); - } - if (HISTORY_MAX_ENTRIES > 0) - history(ad); - update_state(ad); - - // userscript_hooks_end(elm_web_uri_get(td->web)); - /* - FILE *fp = fopen("/home/kyle/.config/evi/userscript/adblockplus/contentScript2.js", "r"); - if (!fp) - printf("error opening file.\n"); - fseek(fp, 0L, SEEK_END); - int len = ftell(fp); - char *buf = malloc(len); - rewind(fp); - fread(buf, len, 1, fp); - fclose(fp); - - ewk_frame_script_execute(frame, buf); - - free(buf); - */ - - - // elm_object_focus_set(td->web, EINA_TRUE); -} - -#if 0 -void -webview_open_js_window_cb(WebKitWebView* temp_view, GParamSpec param_spec) { - /* retrieve the URI of the temporary webview */ - Arg a = { .i = TargetNew, .s = (char*)webkit_web_view_get_uri(temp_view) }; - /* clean up */ - webkit_web_view_stop_loading(temp_view); - gtk_widget_destroy(GTK_WIDGET(temp_view)); - /* open the requested window */ - open_arg(&a); -} - -static WebKitWebView * -webview_open_in_new_window_cb(WebKitWebView *webview, WebKitWebFrame *frame, gpointer user_data) { - /* create a temporary webview to execute the script in */ - WebKitWebView *temp_view = WEBKIT_WEB_VIEW(webkit_web_view_new()); - /* wait until the new webview receives its new URI */ - g_object_connect(temp_view, "signal::notify::uri", G_CALLBACK(webview_open_js_window_cb), NULL, NULL); - return temp_view; -} - -Eina_Bool -webview_new_window_cb(WebKitWebView *webview, WebKitWebFrame *frame, WebKitNetworkRequest *request, - WebKitWebNavigationAction *action, WebKitWebPolicyDecision *decision, gpointer user_data) { - Arg a = { .i = TargetNew, .s = (char*)webkit_network_request_get_uri(request) }; - open_arg(&a); - webkit_web_policy_decision_ignore(decision); - return TRUE; -} -#endif - -/* -Eina_Bool -webview_mimetype_cb(WebKitWebView *webview, WebKitWebFrame *frame, WebKitNetworkRequest *request, - char *mime_type, WebKitWebPolicyDecision *decision, gpointer user_data) { - if (webkit_web_view_can_show_mime_type(webview, mime_type) == FALSE) { - webkit_web_policy_decision_download(decision); - return TRUE; - } else { - return FALSE; - } -} - -static WebKitWebView* -inspector_inspect_web_view_cb(gpointer inspector, WebKitWebView* web_view) { - gchar* inspector_title; - GtkWidget* inspector_window; - GtkWidget* inspector_view; - - // just enough code to show the inspector - no signal handling etc. - inspector_title = strdup_printf("Inspect page - %s - Vimprobable2", webkit_web_view_get_uri(web_view)); - if (embed) { - inspector_window = gtk_plug_new(embed); - } else { - inspector_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_wmclass(window, "vimprobable2", "Vimprobable2"); - } - gtk_window_set_title(GTK_WINDOW(inspector_window), inspector_title); - free(inspector_title); - inspector_view = webkit_web_view_new(); - gtk_container_add(GTK_CONTAINER(inspector_window), inspector_view); - gtk_widget_show_all(inspector_window); - return WEBKIT_WEB_VIEW(inspector_view); -} -*/ - -static void -download_entry_free_cb(void *data) -{ - free(data); -} - -void -download_complete_cb(void *data, const char *file, int status) -{ - App_Data *ad = data; - Arg a; - a.i = Info; - a.s = strdup_printf("Download %s finished, status %i", file, status); - echo(&a, data); - free(a.s); - - // ad->active_downloads = eina_list_remove(ad->active_downloads, file); - eina_hash_del(ad->downloads, file, NULL); - - update_state(data); -} - -int -download_progress_cb(void *data, const char *file, long int dltotal, long int dlnow, long int ultotal, long int ulnow) -{ - App_Data *ad = data; - - void *stat_old; - struct dl *stat = malloc(sizeof(struct dl)); - - stat->dltotal = dltotal; - stat->dlnow = dlnow; - - stat_old = eina_hash_modify(ad->downloads, file, (const void *)stat); - free(stat_old); - - update_state(data); - - return 0; -} - -static void -webview_download_cb(void *data, Evas_Object *obj, void *event_info) -{ - Eina_Bool ret; - Buffer_Data *td = data; - App_Data *ad = td->app; - - Ewk_Download *dl = event_info; - char *suggested_name = strdup(strrchr(dl->url, '/')); - - char *full_path = strdup_printf("/home/kyle/%s", suggested_name); - - ret = ecore_file_download(dl->url, full_path, download_complete_cb, - download_progress_cb, ad, NULL); - - /* if file already exists, ret == NULL */ - if (!ret) { - Arg a; - a.i = Info; - a.s = strdup_printf("%s already exists!", suggested_name); - echo(&a, ad); - free(a.s); - return; - } - - // ad->active_downloads = eina_list_append(ad->active_downloads, strdup(full_path)); - eina_hash_add(ad->downloads, full_path, calloc(1, sizeof(struct dl))); - - // free(full_path); - free(suggested_name); - - update_state(ad); -} - -static void -webview_mousewheel_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) -{ - Buffer_Data *td = data; - update_state(td->app); -} - -static Eina_Bool -process_keypress(void *event_info, void *data) -{ - KeyList *walk; - Key key; - // int keyval; - // GdkModifierType irrelevant; - App_Data *ad = data; - Evas_Event_Key_Down *ev = event_info; - - // Get a mask of modifiers that shouldn't be considered for this event. - // E.g.: It shouldn't matter whether ';' is shifted or not. - // gdk_keymap_translate_keyboard_state(keymap, event->hardware_keycode, - // event->state, event->group, &keyval, NULL, NULL, &irrelevant); - - walk = ad->keylistroot; - while (walk != NULL) { - key = walk->Element; - // if (current->Element.mask == (CLEAN(event->state) & ~irrelevant) - if ((key.mask == 0 || evas_key_modifier_is_set(ev->modifiers, key.mask)) - && (key.modkey == ad->current_modkey - || (!key.modkey && !ad->current_modkey) - || key.modkey == '*' ) // wildcard - && !strcmp(key.key, ev->key) - && key.func) - if (key.func(&key.arg, data)) { - // printf("process_keypress() function for mask = %s modkey = %c key = %s called.\n", key.mask, ad->current_modkey, key.key); - ad->current_modkey = ad->count = 0; - update_state(data); - return TRUE; - } - walk = walk->next; - } - return FALSE; -} - -static void -webview_keypress_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) -{ - Arg a = { .i = ModeNormal, .s = NULL }; - // int keyval; - Evas_Event_Key_Down *ev = event_info; - Buffer_Data *td = data; - App_Data *ad = td->app; - // GdkModifierType irrelevant; - - /* Get a mask of modifiers that shouldn't be considered for this event. - * E.g.: It shouldn't matter whether ';' is shifted or not. */ - // gdk_keymap_translate_keyboard_state(keymap, event->hardware_keycode, - // event->state, event->group, &keyval, NULL, NULL, &irrelevant); - - switch (ad->mode) { - case ModeNormal: - // if ((CLEAN(event->state) & ~irrelevant) == 0) { - if (IS_ESCAPE(ev)) { - a.i = Info; - a.s = strdup(""); - echo(&a, ad); - elm_box_clear(ad->event_box); - evas_object_hide(ad->event_box); - free(a.s); - } else if (ad->current_modkey == 0 && - (( strcmp(ev->key, "1") >= 0 && strcmp(ev->key, "9") <= 0) - || (!strcmp(ev->key, "0") && ad->count))) { - // ad->count = (ad->count ? ad->count * 10 : 0) + (ev->key - "0"); - ad->count = (ad->count ? ad->count * 10 : 0) + atoi(ev->key); - update_state(ad); - return; - } else if (strchr(ad->modkeys, ev->key[0]) && ad->current_modkey != ev->key[0]) { - ad->current_modkey = ev->key[0]; - // ad->current_modkey = strdup(ev->key); - - update_state(ad); - return; - } - // } - /* keybindings */ - if (process_keypress(event_info, ad) == TRUE) return; - - break; - case ModeInsert: - if (IS_ESCAPE(ev)) { - a.i = Silent; - a.s = strdup("hints.clearFocus();"); - script(&a, ad); - free(a.s); - a.i = ModeNormal; - set(&a, ad); - // ewk_view_input_method_state_set(td->web, FALSE); - return; - } - case ModePassThrough: - if (IS_ESCAPE(ev)) { - echo(&a, ad); - set(&a, ad); - return; - } - break; - case ModeSendKey: - echo(&a, ad); - set(&a, ad); - break; - } -} - void set_widget_font_and_color(Evas_Object *widget, const char *font_str, const char *bg_color_str, const char *fg_color_str) { - /* GdkColor fg_color; GdkColor bg_color; PangoFontDescription *font; @@ -820,492 +302,12 @@ set_widget_font_and_color(Evas_Object *widget, const char *font_str, const char gtk_widget_modify_text(widget, GTK_STATE_NORMAL, fg_color_str ? &fg_color : NULL); gtk_widget_modify_base(widget, GTK_STATE_NORMAL, bg_color_str ? &bg_color : NULL); - */ return; } - -void -xss_detected_cb(void *data, Evas_Object *obj, void *event_info) -{ - printf("xss_detected()\n"); -} - -void -icon_received_cb(void *data, Evas_Object *obj, void *event_info) -{ - printf("icon_received_cb()\n"); -} - -void -webview_hoverlink_cb(void *data, Evas_Object *obj, void *event_info) -{ - Buffer_Data *td = data; - const char *uri = elm_web_uri_get(td->web); - /* event_info is a char *link[2] where the first string contains the URL - * and the second the title of the link */ - char **link = event_info; - // char *markup; - - memset(td->app->rememberedURI, 0, 1024); - if (link && link[0]) { - // markup = g_markup_printf_escaped("<span font=\"%s\">Link: %s</span>", statusfont, link[0]); - // markup = strdup_printf("<font=Monospace font_size=10 color=#FF0>%s", link[0]); - // gtk_label_set_markup(GTK_LABEL(td->app->status_url), markup); - // elm_object_text_set(td->app->status_url, markup); - update_url(link[0], td->app); - strcpy(td->app->rememberedURI, link[0]); - // free(markup); - } else - update_url(uri, td->app); -} - -static void -webview_hoverlink_out_cb(void *data, Evas_Object *obj, void *event_info) -{ - Buffer_Data *td = data; - update_url(elm_web_uri_get(td->web), td->app); -} - -static void -webview_console_cb(void *data, Evas_Object *obj, const char *message, unsigned int line, const char *source) -{ - Arg a; - Buffer_Data *td = data; - - /* Don't change internal mode if the browser doesn't have focus to prevent inconsistent states */ - // if (gtk_window_has_toplevel_focus(window)) { - if (elm_object_focus_get(td->app->win)) { - if (!strcmp(message, "hintmode_off") || !strcmp(message, "insertmode_off")) { - a.i = ModeNormal; - set(&a, td->app); - return; - } else if (!strcmp(message, "insertmode_on")) { - a.i = ModeInsert; - set(&a, td->app); - return; - } - } -} - -void -inputbox_activate_cb(void *data, Evas_Object *obj, void *event_info) -{ - const char *text; - App_Data *ad = data; - uint16_t length = strlen(elm_entry_entry_get(ad->url)); - Arg a; - Eina_Bool forward = FALSE; - - // printf("In inputbox_activate\n"); - - a.i = HideCompletion; - complete(&a, data); - if (length == 0) - return; - text = elm_entry_entry_get(ad->url); - if (length > 1 && text[0] == ':') { - process_line((text + 1), data); - } else if (length > 1 && ((forward = text[0] == '/') || text[0] == '?')) { - // webkit_web_view_unmark_text_matches(webview); - elm_web_text_matches_unmark_all(ad->cur_buf->web); - - // webkit_web_view_mark_text_matches(webview, &text[1], FALSE, 0); - // webkit_web_view_set_highlight_text_matches(webview, TRUE); - elm_web_text_matches_mark(ad->cur_buf->web, &text[1], EINA_FALSE, EINA_TRUE, 0); - - ad->count = 0; - ad->search_direction = forward; - ad->search_handle = strdup(&text[1]); - } else if (text[0] == '.' || text[0] == ',' || text[0] == ';') { - a.i = Silent; - a.s = strdup("hints.fire();"); - script(&a, data); - free(a.s); - update_state(data); - } else - return; - if (!ad->echo_active) - // gtk_entry_set_text(entry, ""); - elm_entry_entry_set(ad->url, ""); - // gtk_widget_grab_focus(GTK_WIDGET(webview)); - - /* process_line above may have deleted the tab, check if its still around */ - if (ad->cur_buf->web) - elm_object_focus_set(ad->cur_buf->web, EINA_TRUE); -} - -static Eina_Bool -commandhistoryfetch(const Arg *arg, void *data) -{ - App_Data *ad = data; - char *command; - const int length = eina_list_count(ad->commandhistory); - - if (length > 0) { - if (arg->i == DirectionPrev) { - ad->commandpointer = (length + ad->commandpointer - 1) % length; - } else { - ad->commandpointer = (length + ad->commandpointer + 1) % length; - } - - command = eina_list_nth(ad->commandhistory, ad->commandpointer); - // gtk_entry_set_text(GTK_ENTRY(inputbox), g_strconcat(":", command, NULL)); - // gtk_editable_set_position(GTK_EDITABLE(inputbox), -1); - command = strdup_printf(":%s", command); - elm_entry_entry_set(ad->url, command); - free(command); - elm_entry_cursor_line_end_set(ad->url); - return TRUE; - } - - return FALSE; -} - -static void -inputbox_keypress_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) -{ - Arg a; - int numval; - Evas_Event_Key_Down *ev = event_info; - App_Data *ad = data; - - if (ad->mode == ModeHints) { - // if (event->keyval == GDK_ISO_Left_Tab) { - if (!strcmp(ev->keyname, "Tab") && evas_key_modifier_is_set(ev->modifiers, "Shift")) { - a.i = Silent; - a.s = strdup("hints.focusPreviousHint();"); - script(&a, data); - free(a.s); - update_state(data); - return; - } - // if (event->keyval == GDK_Tab) { - if (!strcmp(ev->keyname, "Tab")) { - a.i = Silent; - a.s = strdup("hints.focusNextHint();"); - script(&a, data); - free(a.s); - update_state(data); - return; - } - // if (event->keyval == GDK_Return) { - if (!strcmp(ev->keyname, "Return")) { - a.i = Silent; - a.s = strdup_printf("hints.fire();"); - script(&a, data); - free(a.s); - update_state(data); - return; - } - } - if (!strcmp(ev->keyname, "[") || !strcmp(ev->keyname, "Escape")) { - a.i = HideCompletion; - complete(&a, data); - a.i = ModeNormal; - ad->commandpointer = 0; - set(&a, data); - return; - } - else if (!strcmp(ev->keyname, "Tab") && evas_key_modifier_is_set(ev->modifiers, "Shift")) { - a.i = DirectionPrev; - complete(&a, data); - return; - } - else if (!strcmp(ev->keyname, "Tab")) { - a.i = DirectionNext; - complete(&a, data); - return; - } - else if (!strcmp(ev->keyname, "Up")) { - a.i = DirectionPrev; - commandhistoryfetch(&a, data); - return; - } - else if (!strcmp(ev->keyname, "Down")) { - a.i = DirectionNext; - commandhistoryfetch(&a, data); - return; - } - - /* - switch (event->keyval) { - case GDK_bracketleft: - case GDK_Escape: - if (!IS_ESCAPE(event)) break; - a.i = HideCompletion; - complete(&a, data); - a.i = ModeNormal; - commandpointer = 0; - return set(&a, ad); - break; - case GDK_Tab: - a.i = DirectionNext; - return complete(&a, data); - break; - case GDK_Up: - a.i = DirectionPrev; - return commandhistoryfetch(&a); - break; - case GDK_Down: - a.i = DirectionNext; - return commandhistoryfetch(&a); - break; - case GDK_ISO_Left_Tab: - a.i = DirectionPrev; - return complete(&a, data); - break; - } - */ - - if (ad->mode == ModeHints) { -#if 0 - if ((CLEAN(event->state) & GDK_SHIFT_MASK) && - (CLEAN(event->state) & GDK_CONTROL_MASK) && - (event->keyval == GDK_BackSpace)) { - count /= 10; - a.i = Silent; - a.s = g_strdup_printf("hints.updateHints(%d);", count); - script(&a, data); - g_free(a.s); - update_state(); - return TRUE; - } -#endif - - // numval = g_unichar_digit_value((gunichar) gdk_keyval_to_unicode(event->keyval)); - numval = atoi(ev->key); - if ((numval >= 1 && numval <= 9) || (numval == 0 && ad->count)) { - /* allow a zero as non-first number */ - ad->count = (ad->count ? ad->count * 10 : 0) + numval; - a.i = Silent; - a.s = strdup_printf("hints.updateHints(%d);", ad->count); - script(&a, data); - free(a.s); - update_state(data); - return; - } - } -} - -static void -inputmethod_changed_cb(void *data, Evas_Object *obj, void *event_info) -{ - const char *value; - Eina_Bool *enabled = event_info; - Buffer_Data *td = data; - App_Data *ad = td->app; - Evas_Object *frame = ewk_view_frame_main_get(td->view); - - if (ad->mode == ModeNormal && enabled) { - Arg a = { .i = ModeInsert }; - set(&a, ad); - ad->manual_focus = TRUE; - } else if (ad->mode == ModeInsert && !enabled) { - Arg a = { .i = ModeNormal }; - set(&a, ad); - } else { - // char *value = NULL, *message = NULL; - // jsapi_evaluate_script("window.getSelection().focusNode", &value, &message, ad); - value = ewk_frame_script_execute(frame, "window.getSelection().focusNode"); - if (value && !strcmp(value, "[object HTMLFormElement]")) { - Arg a = { .i = ModeInsert, .s = NULL }; - set(&a, ad); - ad->manual_focus = TRUE; - } - // free(value); - eina_stringshare_del(value); - // free(message); - } -} - -/* -static void -// notify_event_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) { -notify_event_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) -{ - int i; - // WebKitHitTestResult *result; - // WebKitHitTestResultContext context; - Ewk_Hit_Test *result; - Ewk_Hit_Test_Result_Context context; - - Evas_Event_Mouse_Up *ev = event_info; - Buffer_Data *td = data; - App_Data *ad = td->app; - - Evas_Object *view = elm_web_webkit_view_get(td->web); - Evas_Object *frame = ewk_view_frame_main_get(view); - - // if (mode == ModeNormal && event->type == GDK_BUTTON_RELEASE) { - if (ad->mode == ModeNormal) { - // handle mouse click events - for (i = 0; i < LENGTH(mouse); i++) { - // if (mouse[i].mask == CLEAN(event->button.state) - if ( (mouse[i].mask == 0 || evas_key_modifier_is_set(ev->modifiers, mouse[i].mask)) - // && (mouse[i].modkey == current_modkey - && ((ad->current_modkey && !strcmp(mouse[i].modkey, ad->current_modkey)) - || (!mouse[i].modkey && !ad->current_modkey) - // || mouse[i].modkey == GDK_VoidSymbol) // wildcard - || !strcmp(mouse[i].modkey, "*")) // wildcard - // && mouse[i].button == event->button.button - && (mouse[i].button & ev->button) - && mouse[i].func) { - if (mouse[i].func(&mouse[i].arg, ad)) { - // current_modkey = count = 0; - ad->current_modkey = NULL; - ad->count = 0; - update_state(ad); - return TRUE; - } - } - } - // result = webkit_web_view_get_hit_test_result(WEBKIT_WEB_VIEW(widget), (GdkEventButton*)event); - result = ewk_frame_hit_test_new(frame, ev->canvas.x, ev->canvas.y); - context = result->context; - - // g_object_get(result, "context", &context, NULL); - // if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE) { - if (context & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE) { - Arg a = { .i = ModeInsert }; - set(&a, ad); - ad->manual_focus = TRUE; - } - // } else if (mode == ModeInsert && event->type == GDK_BUTTON_RELEASE) { - } else if (ad->mode == ModeInsert) { - //result = webkit_web_view_get_hit_test_result(WEBKIT_WEB_VIEW(widget), (GdkEventButton*)event); - result = ewk_frame_hit_test_new(frame, ev->output.x, ev->output.y); - - // g_object_get(result, "context", &context, NULL); - // if (!(context & WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE)) { - if (!(context & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE)) { - Arg a = { .i = ModeNormal }; - set(&a, ad); - } - } else { - char *value = NULL, *message = NULL; - jsapi_evaluate_script("window.getSelection().focusNode", &value, &message, ad); - if (value && !strcmp(value, "[object HTMLFormElement]")) { - Arg a = { .i = ModeInsert, .s = NULL }; - set(&a, ad); - ad->manual_focus = TRUE; - } - free(value); - free(message); - } - ewk_frame_hit_test_free(result); - return FALSE; -} */ -static void -inputbox_keyrelease_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) -{ - Arg a; - App_Data *ad = data; - // guint16 length = gtk_entry_get_text_length(entry); - uint16_t length = strlen(elm_entry_entry_get(ad->url)); - - if (!length) { - a.i = HideCompletion; - complete(&a, data); - a.i = ModeNormal; - set(&a, data); - } -} -/* used for incremental search */ -static void -inputbox_changed_cb(void *data, Evas_Object *obj, void *event_info) -{ - Arg a; - App_Data *ad = data; - const char *text = elm_entry_entry_get(ad->url); - uint16_t length = strlen(text); - Eina_Bool forward = FALSE; - - /* Update incremental search if the user changes the search text. - * - * Note: gtk_widget_is_focus() is a poor way to check if the change comes - * from the user. But if the entry is focused and the text is set - * through gtk_entry_set_text() in some asyncrounous operation, - * I would consider that a bug. - */ - - // if (gtk_widget_is_focus(GTK_WIDGET(entry)) && length > 1 && ((forward = text[0] == '/') || text[0] == '?')) { - if (elm_object_focus_get(ad->url) && length > 1 && ((forward = text[0] == '/') || text[0] == '?')) { - // webkit_web_view_unmark_text_matches(webview); - elm_web_text_matches_unmark_all(ad->cur_buf->web); - - // webkit_web_view_search_text(webview, &text[1], searchoptions & CaseSensitive, forward, searchoptions & Wrapping); - elm_web_text_search(ad->cur_buf->web, &text[1], EINA_TRUE, forward, EINA_FALSE); - return; - // } else if (gtk_widget_is_focus(GTK_WIDGET(entry)) && length >= 1 && - } else if (elm_object_focus_get(ad->url) && length >= 1 && - (text[0] == '.' || text[0] == ',' || text[0] == ';')) { - a.i = Silent; - switch (text[0]) { - case '.': - // a.s = strconcat("hints.createHints('", text + 1, "', 'f');", NULL); - a.s = strdup_printf("hints.createHints('%s', 'f');", text + 1); - break; - - case ',': - // a.s = strconcat("hints.createHints('", text + 1, "', 'F');", NULL); - a.s = strdup_printf("hints.createHints('%s', 'F');", text + 1); - break; - - case ';': - a.s = NULL; - switch (text[1]) { - case 's': - // a.s = strconcat("hints.createHints('", text + 2, "', 's');", NULL); - a.s = strdup_printf("hints.createHints('%s', 's');", text + 2); - break; - case 'y': - // a.s = strconcat("hints.createHints('", text + 2, "', 'y');", NULL); - a.s = strdup_printf("hints.createHints('%s', 'y');", text + 2); - break; - case 'o': - // a.s = strconcat("hints.createHints('", text + 2, "', 'f');", NULL); - a.s = strdup_printf("hints.createHints('%s', 'f');", text + 2); - break; - case 't': case 'w': - // a.s = strconcat("hints.createHints('", text + 2, "', 'F');", NULL); - a.s = strdup_printf("hints.createHints('%s', 'F');", text + 2); - break; - case 'O': case 'T': case 'W': - // a.s = strconcat("hints.createHints('", text + 2, "', 'O');", NULL); - a.s = strdup_printf("hints.createHints('%s', 'O');", text + 2); - break; - case 'i': - // a.s = strconcat("hints.createHints('", text + 2, "', 'i');", NULL); - a.s = strdup_printf("hints.createHints('%s', 'i');", text + 2); - break; - case 'I': - // a.s = strconcat("hints.createHints('", text + 2, "', 'I');", NULL); - a.s = strdup_printf("hints.createHints('%s', 'I');", text + 2); - break; - } - break; - } - ad->count = 0; - if (a.s) { - script(&a, data); - free(a.s); - } - - return; - } else if (length == 0 && ad->followTarget[0]) { - ad->mode = ModeNormal; - a.i = Silent; - a.s = strdup("hints.clearHints();"); - script(&a, data); - free(a.s); - ad->count = 0; - update_state(data); - } -} Evas_Object * webview_create_window_cb(void *data, Evas_Object *obj, Eina_Bool js, const Elm_Web_Window_Features *wf) @@ -1345,8 +347,6 @@ buffer_current_set(Buffer_Data *new_buf) if (ad->cur_buf) { ewk_view_visibility_state_set(ad->cur_buf->view, EWK_PAGE_VISIBILITY_STATE_VISIBLE, 0); if (ad->cur_buf->inspector_enabled) { - printf("re-enabling inspector ..\n"); - ewk_view_setting_enable_developer_extras_set(ad->cur_buf->view, EINA_TRUE); ewk_view_web_inspector_show(ad->cur_buf->view); } @@ -1391,6 +391,7 @@ buffer_add(App_Data *ad) td->buf_number = ad->buf_total; td->inspector_enabled = EINA_FALSE; td->proxy_enabled = EINA_FALSE; + td->history_enabled = EINA_TRUE; td->view = elm_web_webkit_view_get(td->web); ad->buffer_list = eina_list_append(ad->buffer_list, td); @@ -1420,6 +421,7 @@ buffer_add(App_Data *ad) evas_object_smart_callback_add(td->web, "inputmethod,changed", inputmethod_changed_cb, td); /* these signals are not offered by elm_web */ + evas_object_smart_callback_add(td->view, "load,error", load_error_cb, td); evas_object_smart_callback_add(td->view, "inspector,view,create", webview_inspector_cb, td); evas_object_smart_callback_add(td->view, "inspector,view,close", webview_inspector_close_cb, td); evas_object_smart_callback_add(td->view, "protocolhandler,isregistered", protocol_register_cb, td); @@ -1434,58 +436,19 @@ buffer_add(App_Data *ad) return td; } - -EAPI_MAIN int -elm_main(int argc, char *argv[]) +static void +setup_gui(App_Data *ad) { Evas_Object *win, *bg, *box, *status_bar, *url, *naviframe, *status_url; Evas_Object *status_state, *event_box, *web_inspector; - Evas *e; - Evas_Modifier_Mask mask; - App_Data *ad; - unsigned int i; - - if (!elm_need_web()) - return -1; - - ad = calloc(1, sizeof(App_Data)); - if (!ad) return -1; elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); win = elm_win_add(NULL, "viking", ELM_WIN_BASIC); elm_win_autodel_set(win, EINA_TRUE); - // elm_win_shaped_set(win, EINA_TRUE); // elm_win_screen_constrain_set(win, EINA_TRUE); - - ad->modkeys = calloc(LENGTH(keys) + 1, sizeof(char)); - ad->modkeys[0] = '\0'; - e = evas_object_evas_get(win); - - for (i = 0; i < LENGTH(keys); i++) { - if (keys[i].modkey && !strchr(ad->modkeys, keys[i].modkey)) { - // strcat(ad->modkeys, keys[i].modkey); - ad->modkeys[strlen(ad->modkeys)] = keys[i].modkey; - ad->modkeys[strlen(ad->modkeys) + 1] = '\0'; - } - - mask = evas_key_modifier_mask_get(e, keys[i].mask); - if (keys[i].key && !evas_object_key_grab(win, keys[i].key, mask, 0, EINA_FALSE)) - fprintf(stderr, "Could not grab trigger for mask = %s, key = %s\n", keys[i].mask , keys[i].key); - } - - fprintf(stderr, "Modkey array looks like %s\n", ad->modkeys); - evas_object_smart_callback_add(win, "delete,request", _win_del_request_cb, ad); - // ewk_network_tls_ca_certificates_path_set(ca_bundle); - ewk_settings_icon_database_path_set("./"); - ewk_settings_application_cache_path_set("./"); - ewk_settings_shadow_dom_enable_set(EINA_TRUE); - - ewk_cookies_file_set("cookies.txt"); - ewk_cookies_policy_set(EWK_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY); - /* program bacground */ bg = elm_bg_add(win); evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); @@ -1533,12 +496,12 @@ elm_main(int argc, char *argv[]) evas_object_size_hint_align_set(web_inspector, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(box, web_inspector); evas_object_hide(web_inspector); - + /* invisible event box, populated on tab completions and :ls */ event_box = elm_box_add(win); evas_object_size_hint_align_set(event_box, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(box, event_box); - evas_object_hide(event_box); +// evas_object_hide(event_box); /* main entry widget */ url = elm_entry_add(win); @@ -1563,44 +526,455 @@ elm_main(int argc, char *argv[]) ad->status_state = status_state; ad->event_box = event_box; ad->web_inspector = web_inspector; - ad->soup_session = ewk_network_default_soup_session_get(); +} + +static void +setup_modkeys(App_Data *ad) +{ + Evas *e; + Evas_Modifier_Mask mask; + unsigned int i; + + ad->modkeys = calloc(LENGTH(keys) + 1, sizeof(char)); + ad->modkeys[0] = '\0'; + e = evas_object_evas_get(ad->win); + + for (i = 0; i < LENGTH(keys); i++) { + if (keys[i].modkey && !strchr(ad->modkeys, keys[i].modkey)) { + // strcat(ad->modkeys, keys[i].modkey); + ad->modkeys[strlen(ad->modkeys)] = keys[i].modkey; + ad->modkeys[strlen(ad->modkeys) + 1] = '\0'; + } + + mask = evas_key_modifier_mask_get(e, keys[i].mask); + if (keys[i].key && !evas_object_key_grab(ad->win, keys[i].key, mask, 0, EINA_FALSE)) + fprintf(stderr, "Could not grab trigger for mask = %s, key = %s\n", keys[i].mask , keys[i].key); + } + fprintf(stderr, "Modkey array looks like %s\n", ad->modkeys); +} + +static char ca_bundle[MAX_SETTING_SIZE] = "/etc/ssl/certs/ca-certificates.crt"; +static Eina_Bool strict_ssl = TRUE; /* FALSE will accept any SSL certificate at face value */ +static void +setup_network(App_Data *ad) +{ + + ad->soup_session = ewk_network_default_soup_session_get(); g_object_set(G_OBJECT(ad->soup_session), "ssl-ca-file", ca_bundle, NULL); g_object_set(G_OBJECT(ad->soup_session), "ssl-strict", strict_ssl, NULL); + // ewk_network_tls_ca_certificates_path_set(ca_bundle); +} - ad->buf_total = 0; +static Eina_Bool +_cb_session_save(void *data) +{ + /* + Browser_Window *win; + Eina_List *chrome_iter, *win_iter; + Evas_Object *chrome; + Eina_Bool changed = EINA_FALSE; + Session_Item *si; + + if (!config_restore_state_get(config)) goto end; + + EINA_LIST_FOREACH(app.windows, win_iter, win) + { + EINA_LIST_FOREACH(win->chromes, chrome_iter, chrome) + { + Evas_Object *view = evas_object_data_get(chrome, "view"); + Evas_Object *frame = ewk_view_frame_main_get(view); + const Eina_Bool focused = chrome == win->current_chrome; + const char *url, *wk_url; + int sx, sy; + + si = evas_object_data_get(chrome, "session"); + if (!si) + { + WRN("chrome %p doesn't have a Session_Item, ignoring", chrome); + continue; + } - Buffer_Data *td = buffer_add(ad); - buffer_current_set(td); - elm_web_uri_set(td->web, startpage); + url = session_item_url_get(si); + wk_url = ewk_view_uri_get(view); + if ((url && wk_url && strcmp(url, wk_url)) || (wk_url && !url)) + { + session_item_url_set(si, wk_url); + changed = EINA_TRUE; + } + + ewk_frame_scroll_pos_get(frame, &sx, &sy); + if (session_item_scroll_x_get(si) != sx || + session_item_scroll_y_get(si) != sy) + { + session_item_scroll_x_set(si, sx); + session_item_scroll_y_set(si, sy); + changed = EINA_TRUE; + } + + if (session_item_focused_get(si) != focused) + { + session_item_focused_set(si, focused); + changed = EINA_TRUE; + } + } + } + + if (changed) + session_save(session, NULL); +end: + return ECORE_CALLBACK_RENEW; + */ + + return EINA_FALSE; +} + + + +static const Ecore_Getopt options = { + PACKAGE_NAME, + "%prog [options] [url]", + PACKAGE_VERSION " Revision: ", // VREV, + "(C) 2010 ProFUSION embedded systems", + "LGPL-3", + "WebKit-EFL demo browser for mobile systems with touchscreen.", + EINA_TRUE, + { + // ECORE_GETOPT_STORE_DEF_BOOL('F', "fullscreen", "start in fullscreen.", 1), + ECORE_GETOPT_STORE_DEF_BOOL('P', "disable-plugins", + "disable plugins (flash, etc).", 1), + // ECORE_GETOPT_STORE_DEF_BOOL('M', "disable-mouse", + // "disable mouse (hide it).", 1), + // ECORE_GETOPT_STORE_DEF_BOOL('T', "disable-touch-interface", + // "disable touch interface handling of mouse events", 1), + ECORE_GETOPT_STORE_STR('U', "user-agent", + "user agent string to use. Special cases=iphone,safari,chrome,firefox,android,ie,ie9,ie8,ie7."), + ECORE_GETOPT_STORE_DEF_STR('B', "backing-store", + "backing store to use. single or tiled.", "single"), + // ECORE_GETOPT_STORE_DEF_UINT('R', "rotate", "Screen Rotation in degrees", 0), + ECORE_GETOPT_VERSION('V', "version"), + ECORE_GETOPT_COPYRIGHT('C', "copyright"), + ECORE_GETOPT_LICENSE('L', "license"), + ECORE_GETOPT_HELP('h', "help"), + ECORE_GETOPT_SENTINEL + } +}; + +char * +uri_sanitize(const char *uri) { + char *fixed_uri; + char *schema; + char *tmp; + + if (!uri || !*uri) return NULL; + + tmp = strstr(uri, "://"); + if (!tmp || (tmp == uri) || (tmp > (uri + 15))) + { + char *new_uri = NULL; + if (ecore_file_exists(uri)) + { + schema = "file"; + new_uri = ecore_file_realpath(uri); + } + else + schema = "http"; + + if (asprintf(&fixed_uri, "%s://%s", schema, new_uri ? new_uri : uri) > 0) + { + free(new_uri); + return fixed_uri; + } + free(new_uri); + } + else + { + char search_uri[4096]; + strcat(search_uri, "http://google.com/search?q="); + return strdup(strcat(search_uri, uri)); + } + + return NULL; +} + +static void +setup_config(App_Data *ad, int argc, char **argv) +{ + char *home, *basename; + char path[PATH_MAX]; + Config *config; + Hist *hist; + Session *session; + size_t dirlen; + int args; + Ecore_Timer *session_save_timer = NULL; + char *user_agent_option = NULL; + const char *user_agent_str; + Eina_Bool disable_plugins = 0xff; + char *backing_store_option = NULL; + Backing_Store backing_store_enum; + Eina_Bool quit_option = EINA_FALSE; + char *uri; + Eina_Bool disable_mouse_cursor = 0xff; + Eina_Bool disable_touch_interface = 0xff; + + Ecore_Getopt_Value values[] = { + ECORE_GETOPT_VALUE_BOOL(disable_plugins), + ECORE_GETOPT_VALUE_BOOL(disable_mouse_cursor), + ECORE_GETOPT_VALUE_BOOL(disable_touch_interface), + ECORE_GETOPT_VALUE_STR(user_agent_option), + ECORE_GETOPT_VALUE_STR(backing_store_option), + // ECORE_GETOPT_VALUE_UINT(ad->rotate), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_NONE + }; + + args = ecore_getopt_parse(&options, values, argc, argv); + if (args < 0) + ERR("Could not parse command line options."); + + if (!user_agent_option || (user_agent_option && (strcasecmp(user_agent_option, "eve") == 0))) + user_agent_str = "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " PACKAGE_NAME "/" PACKAGE_VERSION; + else + { + /* http://www.useragentstring.com/ */ + if (strcasecmp(user_agent_option, "iphone") == 0) + user_agent_str = "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3"; + else if (strcasecmp(user_agent_option, "safari") == 0) + user_agent_str = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8"; + + else if (strcasecmp(user_agent_option, "chrome") == 0) + user_agent_str = "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7"; + else if (strcasecmp(user_agent_option, "firefox") == 0) + user_agent_str = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.2) Gecko/20121223 Firefox/3.8"; + else if (strcasecmp(user_agent_option, "android") == 0) + user_agent_str = "Mozilla/5.0 (Linux; U; Android 2.1; en-US;) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17"; + + else if (strcasecmp(user_agent_option, "ie") == 0) /* last */ + user_agent_str = "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)"; + else if (strcasecmp(user_agent_option, "ie9") == 0) + user_agent_str = "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)"; + else if (strcasecmp(user_agent_option, "ie8") == 0) + user_agent_str = "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 1.1.4322)"; + else if (strcasecmp(user_agent_option, "ie7") == 0) + user_agent_str = "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)"; + else + user_agent_str = user_agent_option; + } + + if (backing_store_option && !strcasecmp(backing_store_option, "tiled")) + backing_store_enum = BACKING_STORE_TILED; + else + backing_store_enum = BACKING_STORE_SINGLE; + + viking_state_init(); + + home = getenv("HOME"); + if (!home || !home[0]) { + CRITICAL("Could not get $HOME"); + home = "/"; + } - evas_object_resize(win, 480, 640); - evas_object_show(win); + dirlen = snprintf(path, sizeof(path), "%s/.config/viking", home); + + if (dirlen >= sizeof(path)) + ERR("Path is too long: %s/.config/eve", home); + + if (!ecore_file_mkpath(path)) + ERR("Could not create %s", path); + + if (!ewk_settings_icon_database_path_set(path)) + ERR("Could not set icon database path to %s", path); + + basename = path + dirlen; + basename[0] = '/'; + basename++; + dirlen++; + + eina_strlcpy(basename, "cookies.txt", sizeof(path) - dirlen); + ewk_cookies_file_set(path); + ewk_cookies_policy_set(EWK_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY); + + + eina_strlcpy(basename, "config.eet", sizeof(path) - dirlen); + config = config_load(path); + if (!config) { + + Eina_Bool enable_mouse_cursor, enable_touch_interface, enable_plugins; + +#define BOOL_OPT(opt) \ + enable_##opt = ((disable_##opt == 0xff) ? EINA_TRUE : !disable_##opt) + BOOL_OPT(mouse_cursor); + BOOL_OPT(touch_interface); + BOOL_OPT(plugins); +#undef BOOL_OPT + + config = config_new(EINA_TRUE /* allow_popup */, + EINA_TRUE /* enable_auto_load_images */, + EINA_TRUE /* enable_auto_shrink_images */, + EINA_TRUE /* enable_javascript */, + enable_mouse_cursor, + enable_plugins, + EINA_FALSE /* enable_private_mode */, + enable_touch_interface, + DEFAULT_URL /* home_page */, + NULL /* proxy */, + EINA_FALSE /* restore_state */, + user_agent_str, + EINA_FALSE /* frame_flattening */, + EINA_FALSE /* text_only_zoom */, + 12 /* minimum_font_size */, + ewk_cookies_policy_get(), + backing_store_enum); + if (!config_save(config, path)) + ERR("Could not save new configuration at %s", path); + } + else + config_backing_store_set(config, backing_store_enum); + + hist = hist_load(path); + if (!hist) { + hist = hist_new(); + if (!hist_save(hist, path)) + ERR("Could not save new history file at %s", path); + } + + session = session_load(path); + if (!session) { + session = session_new(NULL); + if (!session_save(session, path)) + ERR("Could not save new session file at %s", path); + } + + session_save_timer = ecore_timer_loop_add(15, _cb_session_save, NULL); + if (!session_save_timer) + ERR("Could not register session save timer"); + +#define BOOL_OPT(opt) \ + if (disable_##opt != 0xff) { \ + Eina_Bool old = config_enable_##opt##_get(config); \ + Eina_Bool cur = !disable_##opt; \ + if (old != cur) { \ + INF("Changed preferences to "#opt"=%hhu", cur); \ + config_enable_##opt##_set(config, cur); \ + } \ + } + // BOOL_OPT(mouse_cursor); + // BOOL_OPT(touch_interface); + BOOL_OPT(plugins); +#undef BOOL_OPT + + if (user_agent_option) { + const char *old = config_user_agent_get(config); + const char *cur = user_agent_str; + if (strcmp(old, cur) != 0) { + INF("Changed preferences to user_agent=\"%s\"", cur); + config_user_agent_set(config, cur); + } + } + + if (args < argc) { + uri = uri_sanitize(argv[args]); + printf("setup_config() cmd line uri = %s\n", uri); + free(uri); + } + + ad->config = config; + ad->history = hist; + ad->session = session; + ad->session_save_timer = session_save_timer; +} + +static Eina_Bool +session_restore(void) +{ + return EINA_FALSE; +} + +static URIHandler uri_handlers[] = { + { "mailto:", "x-terminal-emulator -e mutt %s" }, + { "ftp://", "x-terminal-emulator -e wget ftp://%s" }, +}; + +/* search engines */ +static Searchengine searchengines[] = { + { "d", "https://duckduckgo.com/?q=%s&t=Vimprobable" }, + { "i", "http://ixquick.com/do/metasearch.pl?query=%s" }, + { "w", "https://secure.wikimedia.org/wikipedia/en/w/index.php?title=Special%%3ASearch&search=%s&go=Go" }, + { "wd", "https://secure.wikimedia.org/wikipedia/de/w/index.php?title=Special%%3ASearch&search=%s&go=Go" }, + { "dd", "https://duckduckgo.com/html/?q=%s&t=Vimprobable" }, +}; + +static char defaultsearch[MAX_SETTING_SIZE] = "d"; + + +EAPI_MAIN int +elm_main(int argc, char *argv[]) +{ + App_Data *ad; + Buffer_Data *bd; + +#if ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); +#endif + + /* calloc zeros the memory!! */ + ad = calloc(1, sizeof(App_Data)); + if (!ad) return -1; + + ad->log_domain = eina_log_domain_register("viking", NULL); + if (ad->log_domain < 0) + EINA_LOG_CRIT("could not create log domain 'viking'."); + + if (!elm_need_web()) + return -1; + + setup_config(ad, argc, argv); + setup_gui(ad); + setup_modkeys(ad); + setup_network(ad); + + /* session was restored successfully */ + if (config_restore_state_get(ad->config) + && session_windows_count(ad->session) > 0 + && session_restore()); + + bd = buffer_add(ad); + buffer_current_set(bd); + elm_web_uri_set(bd->web, config_home_page_get(ad->config)); + + evas_object_resize(ad->win, 480, 640); + evas_object_show(ad->win); make_searchengines_list(searchengines, LENGTH(searchengines)); make_uri_handlers_list(uri_handlers, LENGTH(uri_handlers)); + /* initialize fields that are non-zero */ ad->keylistroot = make_keyslist(); - - memset(ad->rememberedURI, 0, 1024); - memset(ad->followTarget, 0, 8); - ad->error_msg = NULL; ad->config_base = "./"; - ad->manual_focus = FALSE; ad->zoomstep = 0.1f; - ad->current_modkey = 0; - - ad->commandhistory = NULL; - ad->commandpointer = 0; - ad->mode = ModeNormal; - ad->count = 0; ad->echo_active = EINA_TRUE; - ad->downloads = eina_hash_string_superfast_new(download_entry_free_cb); + /* main loop */ elm_run(); + + config_save(ad->config, NULL); + config_free(ad->config); + hist_save(ad->history, NULL); + hist_free(ad->history); + _cb_session_save(ad->session); + session_free(ad->session); + if (ad->session_save_timer) ecore_timer_del(ad->session_save_timer); + elm_shutdown(); free(ad->modkeys); diff --git a/main.h b/main.h @@ -52,6 +52,12 @@ typedef struct SoupSession *soup_session; Buffer_Data *cur_buf; + Hist *history; + Config *config; + Session *session; + Ecore_Timer *session_save_timer; + int log_domain; + Eina_Bool exiting : 1; } App_Data; @@ -80,6 +86,7 @@ Eina_Bool echo(const Arg *arg, void *); void buffer_current_set(Buffer_Data *td); Buffer_Data *buffer_add(App_Data *ad); Eina_Bool enable_proxy(Buffer_Data *bd); +char* status_flags(void *data); #endif diff --git a/utilities.c b/utilities.c @@ -18,6 +18,7 @@ #include <unistd.h> /* realloc */ #include "viking.h" +#include "viking_state.h" #include "main.h" #include "utilities.h" #include "commands.h" @@ -26,7 +27,7 @@ #include "jsmn.h" /* these all need to go */ -extern Eina_Bool complete_case_sensitive; +static Eina_Bool complete_case_sensitive = TRUE; extern char *config_base; static Eina_List *dynamic_searchengines = NULL, *dynamic_uri_handlers = NULL; diff --git a/viking.h b/viking.h @@ -194,4 +194,19 @@ enum ConfigFileError { /* completion list size */ #define MAX_LIST_SIZE 40 +#define DEFAULT_URL "http://getaddrinfo.net" +#define PACKAGE_NAME "viking" +#define PACKAGE_VERSION "1" + +#define CRITICAL(...) EINA_LOG_DOM_CRIT(ad->log_domain, __VA_ARGS__) +#define ERR(...) EINA_LOG_DOM_ERR(ad->log_domain, __VA_ARGS__) +#define WRN(...) EINA_LOG_DOM_WARN(ad->log_domain, __VA_ARGS__) +#define INF(...) EINA_LOG_DOM_INFO(ad->log_domain, __VA_ARGS__) +#define DBG(...) EINA_LOG_DOM_DBG(ad->log_domain, __VA_ARGS__) + +typedef enum +{ + BACKING_STORE_SINGLE, + BACKING_STORE_TILED +} Backing_Store; diff --git a/viking_state.c b/viking_state.c @@ -0,0 +1,1259 @@ +/* This file has been automatically generated by geneet.py */ +/* DO NOT MODIFY */ + +#include <limits.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "viking_state.h" + +struct _Config { + unsigned char allow_popup; + unsigned char enable_auto_load_images; + unsigned char enable_auto_shrink_images; + unsigned char enable_javascript; + unsigned char enable_mouse_cursor; + unsigned char enable_plugins; + unsigned char enable_private_mode; + unsigned char enable_touch_interface; + const char * home_page; + const char * proxy; + unsigned char restore_state; + const char * user_agent; + unsigned char frame_flattening; + int text_zoom; + int minimum_font_size; + int cookie_policy; + int backing_store; + const char *__eet_filename; +}; + +struct _Hist_Item { + const char * title; + const char * url; + unsigned int visit_count; + double last_visit; +}; + +struct _Hist { + Eina_Hash * items; + const char *__eet_filename; +}; + +struct _Fav_Item { + const char * url; + const char * title; + unsigned int visit_count; +}; + +struct _Fav { + Eina_Hash * items; + const char *__eet_filename; +}; + +struct _Session_Item { + const char * url; + unsigned char focused; + int scroll_x; + int scroll_y; +}; + +struct _Session_Window { + Eina_List * tabs; + unsigned char focused; +}; + +struct _Session { + Eina_List * windows; + const char *__eet_filename; +}; + +static const char CONFIG_ENTRY[] = "config"; +static const char HIST_ITEM_ENTRY[] = "hist_item"; +static const char HIST_ENTRY[] = "hist"; +static const char FAV_ITEM_ENTRY[] = "fav_item"; +static const char FAV_ENTRY[] = "fav"; +static const char SESSION_ITEM_ENTRY[] = "session_item"; +static const char SESSION_WINDOW_ENTRY[] = "session_window"; +static const char SESSION_ENTRY[] = "session"; + +static Eet_Data_Descriptor *_config_descriptor = NULL; +static Eet_Data_Descriptor *_hist_item_descriptor = NULL; +static Eet_Data_Descriptor *_hist_descriptor = NULL; +static Eet_Data_Descriptor *_fav_item_descriptor = NULL; +static Eet_Data_Descriptor *_fav_descriptor = NULL; +static Eet_Data_Descriptor *_session_item_descriptor = NULL; +static Eet_Data_Descriptor *_session_window_descriptor = NULL; +static Eet_Data_Descriptor *_session_descriptor = NULL; + +static inline void +_config_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + if (_config_descriptor) return; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Config); + _config_descriptor = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "allow_popup", allow_popup, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "enable_auto_load_images", enable_auto_load_images, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "enable_auto_shrink_images", enable_auto_shrink_images, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "enable_javascript", enable_javascript, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "enable_mouse_cursor", enable_mouse_cursor, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "enable_plugins", enable_plugins, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "enable_private_mode", enable_private_mode, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "enable_touch_interface", enable_touch_interface, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "home_page", home_page, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "proxy", proxy, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "restore_state", restore_state, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "user_agent", user_agent, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "frame_flattening", frame_flattening, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "text_zoom", text_zoom, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "minimum_font_size", minimum_font_size, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "cookie_policy", cookie_policy, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(_config_descriptor, Config, "backing_store", backing_store, EET_T_INT); +} + +static inline void +_config_shutdown(void) +{ + if (!_config_descriptor) return; + eet_data_descriptor_free(_config_descriptor); + _config_descriptor = NULL; +} + +Config * +config_new(unsigned char allow_popup, unsigned char enable_auto_load_images, unsigned char enable_auto_shrink_images, unsigned char enable_javascript, unsigned char enable_mouse_cursor, unsigned char enable_plugins, unsigned char enable_private_mode, unsigned char enable_touch_interface, const char * home_page, const char * proxy, unsigned char restore_state, const char * user_agent, unsigned char frame_flattening, int text_zoom, int minimum_font_size, int cookie_policy, int backing_store) +{ + Config *config = calloc(1, sizeof(Config)); + + if (!config) + { + fprintf(stderr, "ERROR: could not calloc Config\n"); + return NULL; + } + + config->allow_popup = allow_popup; + config->enable_auto_load_images = enable_auto_load_images; + config->enable_auto_shrink_images = enable_auto_shrink_images; + config->enable_javascript = enable_javascript; + config->enable_mouse_cursor = enable_mouse_cursor; + config->enable_plugins = enable_plugins; + config->enable_private_mode = enable_private_mode; + config->enable_touch_interface = enable_touch_interface; + config->home_page = eina_stringshare_add(home_page ? home_page : "http://www.google.com"); + config->proxy = eina_stringshare_add(proxy); + config->restore_state = restore_state; + config->user_agent = eina_stringshare_add(user_agent ? user_agent : "eve"); + config->frame_flattening = frame_flattening; + config->text_zoom = text_zoom; + config->minimum_font_size = minimum_font_size; + config->cookie_policy = cookie_policy; + config->backing_store = backing_store; + + return config; +} + +void +config_free(Config *config) +{ + eina_stringshare_del(config->home_page); + eina_stringshare_del(config->proxy); + eina_stringshare_del(config->user_agent); + free(config); +} + +inline unsigned char +config_allow_popup_get(const Config *config) +{ + return config->allow_popup; +} + +inline void +config_allow_popup_set(Config *config, unsigned char allow_popup) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->allow_popup = allow_popup; +} + +inline unsigned char +config_enable_auto_load_images_get(const Config *config) +{ + return config->enable_auto_load_images; +} + +inline void +config_enable_auto_load_images_set(Config *config, unsigned char enable_auto_load_images) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->enable_auto_load_images = enable_auto_load_images; +} + +inline unsigned char +config_enable_auto_shrink_images_get(const Config *config) +{ + return config->enable_auto_shrink_images; +} + +inline void +config_enable_auto_shrink_images_set(Config *config, unsigned char enable_auto_shrink_images) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->enable_auto_shrink_images = enable_auto_shrink_images; +} + +inline unsigned char +config_enable_javascript_get(const Config *config) +{ + return config->enable_javascript; +} + +inline void +config_enable_javascript_set(Config *config, unsigned char enable_javascript) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->enable_javascript = enable_javascript; +} + +inline unsigned char +config_enable_mouse_cursor_get(const Config *config) +{ + return config->enable_mouse_cursor; +} + +inline void +config_enable_mouse_cursor_set(Config *config, unsigned char enable_mouse_cursor) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->enable_mouse_cursor = enable_mouse_cursor; +} + +inline unsigned char +config_enable_plugins_get(const Config *config) +{ + return config->enable_plugins; +} + +inline void +config_enable_plugins_set(Config *config, unsigned char enable_plugins) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->enable_plugins = enable_plugins; +} + +inline unsigned char +config_enable_private_mode_get(const Config *config) +{ + return config->enable_private_mode; +} + +inline void +config_enable_private_mode_set(Config *config, unsigned char enable_private_mode) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->enable_private_mode = enable_private_mode; +} + +inline unsigned char +config_enable_touch_interface_get(const Config *config) +{ + return config->enable_touch_interface; +} + +inline void +config_enable_touch_interface_set(Config *config, unsigned char enable_touch_interface) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->enable_touch_interface = enable_touch_interface; +} + +inline const char * +config_home_page_get(const Config *config) +{ + return config->home_page; +} + +inline void +config_home_page_set(Config *config, const char *home_page) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + eina_stringshare_replace(&(config->home_page), home_page); +} + +inline const char * +config_proxy_get(const Config *config) +{ + return config->proxy; +} + +inline void +config_proxy_set(Config *config, const char *proxy) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + eina_stringshare_replace(&(config->proxy), proxy); +} + +inline unsigned char +config_restore_state_get(const Config *config) +{ + return config->restore_state; +} + +inline void +config_restore_state_set(Config *config, unsigned char restore_state) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->restore_state = restore_state; +} + +inline const char * +config_user_agent_get(const Config *config) +{ + return config->user_agent; +} + +inline void +config_user_agent_set(Config *config, const char *user_agent) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + eina_stringshare_replace(&(config->user_agent), user_agent); +} + +inline unsigned char +config_frame_flattening_get(const Config *config) +{ + return config->frame_flattening; +} + +inline void +config_frame_flattening_set(Config *config, unsigned char frame_flattening) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->frame_flattening = frame_flattening; +} + +inline int +config_text_zoom_get(const Config *config) +{ + return config->text_zoom; +} + +inline void +config_text_zoom_set(Config *config, int text_zoom) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->text_zoom = text_zoom; +} + +inline int +config_minimum_font_size_get(const Config *config) +{ + return config->minimum_font_size; +} + +inline void +config_minimum_font_size_set(Config *config, int minimum_font_size) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->minimum_font_size = minimum_font_size; +} + +inline int +config_cookie_policy_get(const Config *config) +{ + return config->cookie_policy; +} + +inline void +config_cookie_policy_set(Config *config, int cookie_policy) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->cookie_policy = cookie_policy; +} + +inline int +config_backing_store_get(const Config *config) +{ + return config->backing_store; +} + +inline void +config_backing_store_set(Config *config, int backing_store) +{ + EINA_SAFETY_ON_NULL_RETURN(config); + config->backing_store = backing_store; +} + +Config * +config_load(const char *filename) +{ + Config *config = NULL; + Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for read\n", filename); + return NULL; + } + + config = eet_data_read(ef, _config_descriptor, CONFIG_ENTRY); + if (!config) goto end; + config->__eet_filename = eina_stringshare_add(filename); + +end: + eet_close(ef); + return config; +} + +Eina_Bool +config_save(Config *config, const char *filename) +{ + Eet_File *ef; + Eina_Bool ret; + + if (filename) eina_stringshare_replace(&(config->__eet_filename), filename); + else if (config->__eet_filename) filename = config->__eet_filename; + else return EINA_FALSE; + + ef = eet_open(filename, EET_FILE_MODE_READ_WRITE); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for write\n", filename); + return EINA_FALSE; + } + + ret = !!eet_data_write(ef, _config_descriptor, CONFIG_ENTRY, config, EINA_TRUE); + eet_close(ef); + + return ret; +} + +static inline void +_hist_item_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + if (_hist_item_descriptor) return; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Hist_Item); + _hist_item_descriptor = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_BASIC(_hist_item_descriptor, Hist_Item, "title", title, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_hist_item_descriptor, Hist_Item, "url", url, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_hist_item_descriptor, Hist_Item, "visit_count", visit_count, EET_T_UINT); + EET_DATA_DESCRIPTOR_ADD_BASIC(_hist_item_descriptor, Hist_Item, "last_visit", last_visit, EET_T_DOUBLE); +} + +static inline void +_hist_item_shutdown(void) +{ + if (!_hist_item_descriptor) return; + eet_data_descriptor_free(_hist_item_descriptor); + _hist_item_descriptor = NULL; +} + +Hist_Item * +hist_item_new(const char * title, const char * url, unsigned int visit_count, double last_visit) +{ + Hist_Item *hist_item = calloc(1, sizeof(Hist_Item)); + + if (!hist_item) + { + fprintf(stderr, "ERROR: could not calloc Hist_Item\n"); + return NULL; + } + + hist_item->title = eina_stringshare_add(title ? title : "Untitled"); + hist_item->url = eina_stringshare_add(url ? url : "about:blank"); + hist_item->visit_count = visit_count; + hist_item->last_visit = last_visit; + + return hist_item; +} + +void +hist_item_free(Hist_Item *hist_item) +{ + eina_stringshare_del(hist_item->title); + eina_stringshare_del(hist_item->url); + free(hist_item); +} + +inline const char * +hist_item_title_get(const Hist_Item *hist_item) +{ + return hist_item->title; +} + +inline void +hist_item_title_set(Hist_Item *hist_item, const char *title) +{ + EINA_SAFETY_ON_NULL_RETURN(hist_item); + eina_stringshare_replace(&(hist_item->title), title); +} + +inline const char * +hist_item_url_get(const Hist_Item *hist_item) +{ + return hist_item->url; +} + +inline void +hist_item_url_set(Hist_Item *hist_item, const char *url) +{ + EINA_SAFETY_ON_NULL_RETURN(hist_item); + eina_stringshare_replace(&(hist_item->url), url); +} + +inline unsigned int +hist_item_visit_count_get(const Hist_Item *hist_item) +{ + return hist_item->visit_count; +} + +inline void +hist_item_visit_count_set(Hist_Item *hist_item, unsigned int visit_count) +{ + EINA_SAFETY_ON_NULL_RETURN(hist_item); + hist_item->visit_count = visit_count; +} + +inline double +hist_item_last_visit_get(const Hist_Item *hist_item) +{ + return hist_item->last_visit; +} + +inline void +hist_item_last_visit_set(Hist_Item *hist_item, double last_visit) +{ + EINA_SAFETY_ON_NULL_RETURN(hist_item); + hist_item->last_visit = last_visit; +} + + +static inline void +_hist_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + if (_hist_descriptor) return; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Hist); + _hist_descriptor = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_HASH(_hist_descriptor, Hist, "items", items, _hist_item_descriptor); +} + +static inline void +_hist_shutdown(void) +{ + if (!_hist_descriptor) return; + eet_data_descriptor_free(_hist_descriptor); + _hist_descriptor = NULL; +} + +Hist * +hist_new() +{ + Hist *hist = calloc(1, sizeof(Hist)); + + if (!hist) + { + fprintf(stderr, "ERROR: could not calloc Hist\n"); + return NULL; + } + + hist->items = eina_hash_stringshared_new(EINA_FREE_CB(hist_item_free)); + + return hist; +} + +void +hist_free(Hist *hist) +{ + if (hist->items) eina_hash_free(hist->items); + free(hist); +} + +void +hist_items_add(Hist *hist, const char * url, Hist_Item *hist_item) +{ + EINA_SAFETY_ON_NULL_RETURN(hist); + eina_hash_add(hist->items, url, hist_item); +} + +void +hist_items_del(Hist *hist, const char * url) +{ + EINA_SAFETY_ON_NULL_RETURN(hist); + eina_hash_del(hist->items, url, NULL); +} + +inline Hist_Item * +hist_items_get(const Hist *hist, const char * url) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(hist, NULL); + return eina_hash_find(hist->items, url); +} + +inline Eina_Hash * +hist_items_hash_get(const Hist *hist) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(hist, NULL); + return hist->items; +} + +void +hist_items_modify(Hist *hist, const char * key, void *value) +{ + EINA_SAFETY_ON_NULL_RETURN(hist); + eina_hash_modify(hist->items, key, value); +} + +Hist * +hist_load(const char *filename) +{ + Hist *hist = NULL; + Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for read\n", filename); + return NULL; + } + + hist = eet_data_read(ef, _hist_descriptor, HIST_ENTRY); + if (!hist) goto end; + hist->__eet_filename = eina_stringshare_add(filename); + + if (!hist->items) hist->items = eina_hash_stringshared_new(EINA_FREE_CB(hist_item_free)); + +end: + eet_close(ef); + return hist; +} + +Eina_Bool +hist_save(Hist *hist, const char *filename) +{ + Eet_File *ef; + Eina_Bool ret; + + if (filename) eina_stringshare_replace(&(hist->__eet_filename), filename); + else if (hist->__eet_filename) filename = hist->__eet_filename; + else return EINA_FALSE; + + ef = eet_open(filename, EET_FILE_MODE_READ_WRITE); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for write\n", filename); + return EINA_FALSE; + } + + ret = !!eet_data_write(ef, _hist_descriptor, HIST_ENTRY, hist, EINA_TRUE); + eet_close(ef); + + return ret; +} + +static inline void +_fav_item_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + if (_fav_item_descriptor) return; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Fav_Item); + _fav_item_descriptor = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_BASIC(_fav_item_descriptor, Fav_Item, "url", url, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_fav_item_descriptor, Fav_Item, "title", title, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_fav_item_descriptor, Fav_Item, "visit_count", visit_count, EET_T_UINT); +} + +static inline void +_fav_item_shutdown(void) +{ + if (!_fav_item_descriptor) return; + eet_data_descriptor_free(_fav_item_descriptor); + _fav_item_descriptor = NULL; +} + +Fav_Item * +fav_item_new(const char * url, const char * title, unsigned int visit_count) +{ + Fav_Item *fav_item = calloc(1, sizeof(Fav_Item)); + + if (!fav_item) + { + fprintf(stderr, "ERROR: could not calloc Fav_Item\n"); + return NULL; + } + + fav_item->url = eina_stringshare_add(url); + fav_item->title = eina_stringshare_add(title); + fav_item->visit_count = visit_count; + + return fav_item; +} + +void +fav_item_free(Fav_Item *fav_item) +{ + eina_stringshare_del(fav_item->url); + eina_stringshare_del(fav_item->title); + free(fav_item); +} + +inline const char * +fav_item_url_get(const Fav_Item *fav_item) +{ + return fav_item->url; +} + +inline void +fav_item_url_set(Fav_Item *fav_item, const char *url) +{ + EINA_SAFETY_ON_NULL_RETURN(fav_item); + eina_stringshare_replace(&(fav_item->url), url); +} + +inline const char * +fav_item_title_get(const Fav_Item *fav_item) +{ + return fav_item->title; +} + +inline void +fav_item_title_set(Fav_Item *fav_item, const char *title) +{ + EINA_SAFETY_ON_NULL_RETURN(fav_item); + eina_stringshare_replace(&(fav_item->title), title); +} + +inline unsigned int +fav_item_visit_count_get(const Fav_Item *fav_item) +{ + return fav_item->visit_count; +} + +inline void +fav_item_visit_count_set(Fav_Item *fav_item, unsigned int visit_count) +{ + EINA_SAFETY_ON_NULL_RETURN(fav_item); + fav_item->visit_count = visit_count; +} + + +static inline void +_fav_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + if (_fav_descriptor) return; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Fav); + _fav_descriptor = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_HASH(_fav_descriptor, Fav, "items", items, _fav_item_descriptor); +} + +static inline void +_fav_shutdown(void) +{ + if (!_fav_descriptor) return; + eet_data_descriptor_free(_fav_descriptor); + _fav_descriptor = NULL; +} + +Fav * +fav_new() +{ + Fav *fav = calloc(1, sizeof(Fav)); + + if (!fav) + { + fprintf(stderr, "ERROR: could not calloc Fav\n"); + return NULL; + } + + fav->items = eina_hash_stringshared_new(EINA_FREE_CB(fav_item_free)); + + return fav; +} + +void +fav_free(Fav *fav) +{ + if (fav->items) eina_hash_free(fav->items); + free(fav); +} + +void +fav_items_add(Fav *fav, const char * url, Fav_Item *fav_item) +{ + EINA_SAFETY_ON_NULL_RETURN(fav); + eina_hash_add(fav->items, url, fav_item); +} + +void +fav_items_del(Fav *fav, const char * url) +{ + EINA_SAFETY_ON_NULL_RETURN(fav); + eina_hash_del(fav->items, url, NULL); +} + +inline Fav_Item * +fav_items_get(const Fav *fav, const char * url) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(fav, NULL); + return eina_hash_find(fav->items, url); +} + +inline Eina_Hash * +fav_items_hash_get(const Fav *fav) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(fav, NULL); + return fav->items; +} + +void +fav_items_modify(Fav *fav, const char * key, void *value) +{ + EINA_SAFETY_ON_NULL_RETURN(fav); + eina_hash_modify(fav->items, key, value); +} + +Fav * +fav_load(const char *filename) +{ + Fav *fav = NULL; + Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for read\n", filename); + return NULL; + } + + fav = eet_data_read(ef, _fav_descriptor, FAV_ENTRY); + if (!fav) goto end; + fav->__eet_filename = eina_stringshare_add(filename); + + if (!fav->items) fav->items = eina_hash_stringshared_new(EINA_FREE_CB(fav_item_free)); + +end: + eet_close(ef); + return fav; +} + +Eina_Bool +fav_save(Fav *fav, const char *filename) +{ + Eet_File *ef; + Eina_Bool ret; + + if (filename) eina_stringshare_replace(&(fav->__eet_filename), filename); + else if (fav->__eet_filename) filename = fav->__eet_filename; + else return EINA_FALSE; + + ef = eet_open(filename, EET_FILE_MODE_READ_WRITE); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for write\n", filename); + return EINA_FALSE; + } + + ret = !!eet_data_write(ef, _fav_descriptor, FAV_ENTRY, fav, EINA_TRUE); + eet_close(ef); + + return ret; +} + +static inline void +_session_item_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + if (_session_item_descriptor) return; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Session_Item); + _session_item_descriptor = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_BASIC(_session_item_descriptor, Session_Item, "url", url, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_session_item_descriptor, Session_Item, "focused", focused, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(_session_item_descriptor, Session_Item, "scroll_x", scroll_x, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(_session_item_descriptor, Session_Item, "scroll_y", scroll_y, EET_T_INT); +} + +static inline void +_session_item_shutdown(void) +{ + if (!_session_item_descriptor) return; + eet_data_descriptor_free(_session_item_descriptor); + _session_item_descriptor = NULL; +} + +Session_Item * +session_item_new(const char * url, unsigned char focused, int scroll_x, int scroll_y) +{ + Session_Item *session_item = calloc(1, sizeof(Session_Item)); + + if (!session_item) + { + fprintf(stderr, "ERROR: could not calloc Session_Item\n"); + return NULL; + } + + session_item->url = eina_stringshare_add(url); + session_item->focused = focused; + session_item->scroll_x = scroll_x; + session_item->scroll_y = scroll_y; + + return session_item; +} + +void +session_item_free(Session_Item *session_item) +{ + eina_stringshare_del(session_item->url); + free(session_item); +} + +inline const char * +session_item_url_get(const Session_Item *session_item) +{ + return session_item->url; +} + +inline void +session_item_url_set(Session_Item *session_item, const char *url) +{ + EINA_SAFETY_ON_NULL_RETURN(session_item); + eina_stringshare_replace(&(session_item->url), url); +} + +inline unsigned char +session_item_focused_get(const Session_Item *session_item) +{ + return session_item->focused; +} + +inline void +session_item_focused_set(Session_Item *session_item, unsigned char focused) +{ + EINA_SAFETY_ON_NULL_RETURN(session_item); + session_item->focused = focused; +} + +inline int +session_item_scroll_x_get(const Session_Item *session_item) +{ + return session_item->scroll_x; +} + +inline void +session_item_scroll_x_set(Session_Item *session_item, int scroll_x) +{ + EINA_SAFETY_ON_NULL_RETURN(session_item); + session_item->scroll_x = scroll_x; +} + +inline int +session_item_scroll_y_get(const Session_Item *session_item) +{ + return session_item->scroll_y; +} + +inline void +session_item_scroll_y_set(Session_Item *session_item, int scroll_y) +{ + EINA_SAFETY_ON_NULL_RETURN(session_item); + session_item->scroll_y = scroll_y; +} + + +static inline void +_session_window_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + if (_session_window_descriptor) return; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Session_Window); + _session_window_descriptor = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_LIST(_session_window_descriptor, Session_Window, "tabs", tabs, _session_item_descriptor); + EET_DATA_DESCRIPTOR_ADD_BASIC(_session_window_descriptor, Session_Window, "focused", focused, EET_T_UCHAR); +} + +static inline void +_session_window_shutdown(void) +{ + if (!_session_window_descriptor) return; + eet_data_descriptor_free(_session_window_descriptor); + _session_window_descriptor = NULL; +} + +Session_Window * +session_window_new(Eina_List * tabs, unsigned char focused) +{ + Session_Window *session_window = calloc(1, sizeof(Session_Window)); + + if (!session_window) + { + fprintf(stderr, "ERROR: could not calloc Session_Window\n"); + return NULL; + } + + session_window->tabs = tabs; + session_window->focused = focused; + + return session_window; +} + +void +session_window_free(Session_Window *session_window) +{ + if (session_window->tabs) + { + Session_Item *tabs_elem; + EINA_LIST_FREE(session_window->tabs, tabs_elem) + session_item_free(tabs_elem); + } + free(session_window); +} + +inline void +session_window_tabs_add(Session_Window *session_window, Session_Item *session_item) +{ + EINA_SAFETY_ON_NULL_RETURN(session_window); + session_window->tabs = eina_list_append(session_window->tabs, session_item); +} + +inline void +session_window_tabs_del(Session_Window *session_window, Session_Item *session_item) +{ + EINA_SAFETY_ON_NULL_RETURN(session_window); + session_window->tabs = eina_list_remove(session_window->tabs, session_item); +} + +inline Session_Item * +session_window_tabs_get(const Session_Window *session_window, unsigned int nth) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(session_window, NULL); + return eina_list_nth(session_window->tabs, nth); +} + +inline unsigned int +session_window_tabs_count(const Session_Window *session_window) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(session_window, 0); + return eina_list_count(session_window->tabs); +} + +void +session_window_tabs_list_clear(Session_Window *session_window) +{ + EINA_SAFETY_ON_NULL_RETURN(session_window); + Session_Item *data; + EINA_LIST_FREE(session_window->tabs, data) session_item_free(data); +} + +inline Eina_List * +session_window_tabs_list_get(const Session_Window *session_window) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(session_window, NULL); + return session_window->tabs; +} + +inline void +session_window_tabs_list_set(Session_Window *session_window, Eina_List *list) +{ + EINA_SAFETY_ON_NULL_RETURN(session_window); + session_window->tabs = list; +} + +inline unsigned char +session_window_focused_get(const Session_Window *session_window) +{ + return session_window->focused; +} + +inline void +session_window_focused_set(Session_Window *session_window, unsigned char focused) +{ + EINA_SAFETY_ON_NULL_RETURN(session_window); + session_window->focused = focused; +} + + +static inline void +_session_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + if (_session_descriptor) return; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Session); + _session_descriptor = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_LIST(_session_descriptor, Session, "windows", windows, _session_window_descriptor); +} + +static inline void +_session_shutdown(void) +{ + if (!_session_descriptor) return; + eet_data_descriptor_free(_session_descriptor); + _session_descriptor = NULL; +} + +Session * +session_new(Eina_List * windows) +{ + Session *session = calloc(1, sizeof(Session)); + + if (!session) + { + fprintf(stderr, "ERROR: could not calloc Session\n"); + return NULL; + } + + session->windows = windows; + + return session; +} + +void +session_free(Session *session) +{ + if (session->windows) + { + Session_Window *windows_elem; + EINA_LIST_FREE(session->windows, windows_elem) + session_window_free(windows_elem); + } + free(session); +} + +inline void +session_windows_add(Session *session, Session_Window *session_window) +{ + EINA_SAFETY_ON_NULL_RETURN(session); + session->windows = eina_list_append(session->windows, session_window); +} + +inline void +session_windows_del(Session *session, Session_Window *session_window) +{ + EINA_SAFETY_ON_NULL_RETURN(session); + session->windows = eina_list_remove(session->windows, session_window); +} + +inline Session_Window * +session_windows_get(const Session *session, unsigned int nth) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(session, NULL); + return eina_list_nth(session->windows, nth); +} + +inline unsigned int +session_windows_count(const Session *session) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(session, 0); + return eina_list_count(session->windows); +} + +void +session_windows_list_clear(Session *session) +{ + EINA_SAFETY_ON_NULL_RETURN(session); + Session_Window *data; + EINA_LIST_FREE(session->windows, data) session_window_free(data); +} + +inline Eina_List * +session_windows_list_get(const Session *session) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(session, NULL); + return session->windows; +} + +inline void +session_windows_list_set(Session *session, Eina_List *list) +{ + EINA_SAFETY_ON_NULL_RETURN(session); + session->windows = list; +} + +Session * +session_load(const char *filename) +{ + Session *session = NULL; + Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for read\n", filename); + return NULL; + } + + session = eet_data_read(ef, _session_descriptor, SESSION_ENTRY); + if (!session) goto end; + session->__eet_filename = eina_stringshare_add(filename); + +end: + eet_close(ef); + return session; +} + +Eina_Bool +session_save(Session *session, const char *filename) +{ + Eet_File *ef; + Eina_Bool ret; + + if (filename) eina_stringshare_replace(&(session->__eet_filename), filename); + else if (session->__eet_filename) filename = session->__eet_filename; + else return EINA_FALSE; + + ef = eet_open(filename, EET_FILE_MODE_READ_WRITE); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for write\n", filename); + return EINA_FALSE; + } + + ret = !!eet_data_write(ef, _session_descriptor, SESSION_ENTRY, session, EINA_TRUE); + eet_close(ef); + + return ret; +} + +void +viking_state_init(void) +{ + _config_init(); + _hist_item_init(); + _hist_init(); + _fav_item_init(); + _fav_init(); + _session_item_init(); + _session_window_init(); + _session_init(); +} + +void +viking_state_shutdown(void) +{ + _config_shutdown(); + _hist_item_shutdown(); + _hist_shutdown(); + _fav_item_shutdown(); + _fav_shutdown(); + _session_item_shutdown(); + _session_window_shutdown(); + _session_shutdown(); +} + diff --git a/viking_state.h b/viking_state.h @@ -0,0 +1,157 @@ +/* This file has been automatically generated by geneet.py */ +/* DO NOT MODIFY */ + +#ifndef __VIKING_STATE_H__ +#define __VIKING_STATE_H__ + +#include <Eina.h> +#include <Eet.h> + +typedef struct _Config Config; +typedef struct _Hist_Item Hist_Item; +typedef struct _Hist Hist; +typedef struct _Fav_Item Fav_Item; +typedef struct _Fav Fav; +typedef struct _Session_Item Session_Item; +typedef struct _Session_Window Session_Window; +typedef struct _Session Session; + +/* Config */ +Config *config_new(unsigned char allow_popup, unsigned char enable_auto_load_images, unsigned char enable_auto_shrink_images, unsigned char enable_javascript, unsigned char enable_mouse_cursor, unsigned char enable_plugins, unsigned char enable_private_mode, unsigned char enable_touch_interface, const char * home_page, const char * proxy, unsigned char restore_state, const char * user_agent, unsigned char frame_flattening, int text_zoom, int minimum_font_size, int cookie_policy, int backing_store); +void config_free(Config *config); + +void config_allow_popup_set(Config *config, unsigned char allow_popup); +unsigned char config_allow_popup_get(const Config *config); +void config_enable_auto_load_images_set(Config *config, unsigned char enable_auto_load_images); +unsigned char config_enable_auto_load_images_get(const Config *config); +void config_enable_auto_shrink_images_set(Config *config, unsigned char enable_auto_shrink_images); +unsigned char config_enable_auto_shrink_images_get(const Config *config); +void config_enable_javascript_set(Config *config, unsigned char enable_javascript); +unsigned char config_enable_javascript_get(const Config *config); +void config_enable_mouse_cursor_set(Config *config, unsigned char enable_mouse_cursor); +unsigned char config_enable_mouse_cursor_get(const Config *config); +void config_enable_plugins_set(Config *config, unsigned char enable_plugins); +unsigned char config_enable_plugins_get(const Config *config); +void config_enable_private_mode_set(Config *config, unsigned char enable_private_mode); +unsigned char config_enable_private_mode_get(const Config *config); +void config_enable_touch_interface_set(Config *config, unsigned char enable_touch_interface); +unsigned char config_enable_touch_interface_get(const Config *config); +void config_home_page_set(Config *config, const char * home_page); +const char * config_home_page_get(const Config *config); +void config_proxy_set(Config *config, const char * proxy); +const char * config_proxy_get(const Config *config); +void config_restore_state_set(Config *config, unsigned char restore_state); +unsigned char config_restore_state_get(const Config *config); +void config_user_agent_set(Config *config, const char * user_agent); +const char * config_user_agent_get(const Config *config); +void config_frame_flattening_set(Config *config, unsigned char frame_flattening); +unsigned char config_frame_flattening_get(const Config *config); +void config_text_zoom_set(Config *config, int text_zoom); +int config_text_zoom_get(const Config *config); +void config_minimum_font_size_set(Config *config, int minimum_font_size); +int config_minimum_font_size_get(const Config *config); +void config_cookie_policy_set(Config *config, int cookie_policy); +int config_cookie_policy_get(const Config *config); +void config_backing_store_set(Config *config, int backing_store); +int config_backing_store_get(const Config *config); + +Config *config_load(const char *filename); +Eina_Bool config_save(Config *config, const char *filename); + +/* Hist_Item */ +Hist_Item *hist_item_new(const char * title, const char * url, unsigned int visit_count, double last_visit); +void hist_item_free(Hist_Item *hist_item); + +void hist_item_title_set(Hist_Item *hist_item, const char * title); +const char * hist_item_title_get(const Hist_Item *hist_item); +void hist_item_url_set(Hist_Item *hist_item, const char * url); +const char * hist_item_url_get(const Hist_Item *hist_item); +void hist_item_visit_count_set(Hist_Item *hist_item, unsigned int visit_count); +unsigned int hist_item_visit_count_get(const Hist_Item *hist_item); +void hist_item_last_visit_set(Hist_Item *hist_item, double last_visit); +double hist_item_last_visit_get(const Hist_Item *hist_item); + +/* Hist */ +Hist *hist_new(void); +void hist_free(Hist *hist); + +void hist_items_add(Hist *hist, const char * url, Hist_Item *hist_item); +void hist_items_del(Hist *hist, const char * url); +Hist_Item *hist_items_get(const Hist *hist, const char * key); +Eina_Hash *hist_items_hash_get(const Hist *hist); +void hist_items_modify(Hist *hist, const char * key, void *value); + +Hist *hist_load(const char *filename); +Eina_Bool hist_save(Hist *hist, const char *filename); + +/* Fav_Item */ +Fav_Item *fav_item_new(const char * url, const char * title, unsigned int visit_count); +void fav_item_free(Fav_Item *fav_item); + +void fav_item_url_set(Fav_Item *fav_item, const char * url); +const char * fav_item_url_get(const Fav_Item *fav_item); +void fav_item_title_set(Fav_Item *fav_item, const char * title); +const char * fav_item_title_get(const Fav_Item *fav_item); +void fav_item_visit_count_set(Fav_Item *fav_item, unsigned int visit_count); +unsigned int fav_item_visit_count_get(const Fav_Item *fav_item); + +/* Fav */ +Fav *fav_new(void); +void fav_free(Fav *fav); + +void fav_items_add(Fav *fav, const char * url, Fav_Item *fav_item); +void fav_items_del(Fav *fav, const char * url); +Fav_Item *fav_items_get(const Fav *fav, const char * key); +Eina_Hash *fav_items_hash_get(const Fav *fav); +void fav_items_modify(Fav *fav, const char * key, void *value); + +Fav *fav_load(const char *filename); +Eina_Bool fav_save(Fav *fav, const char *filename); + +/* Session_Item */ +Session_Item *session_item_new(const char * url, unsigned char focused, int scroll_x, int scroll_y); +void session_item_free(Session_Item *session_item); + +void session_item_url_set(Session_Item *session_item, const char * url); +const char * session_item_url_get(const Session_Item *session_item); +void session_item_focused_set(Session_Item *session_item, unsigned char focused); +unsigned char session_item_focused_get(const Session_Item *session_item); +void session_item_scroll_x_set(Session_Item *session_item, int scroll_x); +int session_item_scroll_x_get(const Session_Item *session_item); +void session_item_scroll_y_set(Session_Item *session_item, int scroll_y); +int session_item_scroll_y_get(const Session_Item *session_item); + +/* Session_Window */ +Session_Window *session_window_new(Eina_List * tabs, unsigned char focused); +void session_window_free(Session_Window *session_window); + +void session_window_tabs_add(Session_Window *session_window, Session_Item *session_item); +void session_window_tabs_del(Session_Window *session_window, Session_Item *session_item); +Session_Item *session_window_tabs_get(const Session_Window *session_window, unsigned int nth); +unsigned int session_window_tabs_count(const Session_Window *session_window); +Eina_List *session_window_tabs_list_get(const Session_Window *session_window); +void session_window_tabs_list_clear(Session_Window *session_window); +void session_window_tabs_list_set(Session_Window *session_window, Eina_List *list); +void session_window_focused_set(Session_Window *session_window, unsigned char focused); +unsigned char session_window_focused_get(const Session_Window *session_window); + +/* Session */ +Session *session_new(Eina_List * windows); +void session_free(Session *session); + +void session_windows_add(Session *session, Session_Window *session_window); +void session_windows_del(Session *session, Session_Window *session_window); +Session_Window *session_windows_get(const Session *session, unsigned int nth); +unsigned int session_windows_count(const Session *session); +Eina_List *session_windows_list_get(const Session *session); +void session_windows_list_clear(Session *session); +void session_windows_list_set(Session *session, Eina_List *list); + +Session *session_load(const char *filename); +Eina_Bool session_save(Session *session, const char *filename); + +/* Global initializer / shutdown functions */ +void viking_state_init(void); +void viking_state_shutdown(void); + +#endif /* __VIKING_STATE_H__ */