From 39ddaa46ca4dbba300503829b9df88d8d1160171 Mon Sep 17 00:00:00 2001 From: Daniel Carl Date: Sun, 16 Dec 2012 00:10:06 +0100 Subject: [PATCH] Allow to filter and update hints. --- src/hints.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/main.c | 1 + 2 files changed, 121 insertions(+), 3 deletions(-) diff --git a/src/hints.c b/src/hints.c index e1475ae..8b8d784 100644 --- a/src/hints.c +++ b/src/hints.c @@ -17,6 +17,8 @@ * along with this program. If not, see http://www.gnu.org/licenses/. */ +#include +#include #include "hints.h" #include "dom.h" @@ -57,10 +59,16 @@ static void hints_focus(const gulong num); static Hint* hints_get_hint_by_number(const gulong num); static GList* hints_get_hint_list_by_number(const gulong num); static gchar* hints_get_xpath(const gchar* input); +static void hints_observe_input(gboolean observe); +static gboolean hints_changed_callback(GtkEditable *entry, gpointer data); +static gboolean hints_keypress_callback(WebKitWebView* webview, GdkEventKey* event); +static gboolean hints_num_has_prefix(gulong num, gulong prefix); +/* variables */ static GList* hints = NULL; static gulong currentFocusNum = 0; static gulong hintCount = 0; +static gulong hintNum = 0; static HintMode currentMode = HINTS_MODE_LINK; static Element* hintContainer = NULL; @@ -75,11 +83,13 @@ void hints_clear(void) /* reset the previous color of the hinted elements */ dom_element_style_set_property(hint->elem, "color", hint->elemColor); dom_element_style_set_property(hint->elem, "background-color", hint->elemBackgroundColor); + g_free(hint); } g_list_free(hints); hints = NULL; hintCount = 0; + hintNum = 0; } /* remove the hint container */ if (hintContainer) { @@ -87,6 +97,8 @@ void hints_clear(void) webkit_dom_node_remove_child(parent, WEBKIT_DOM_NODE(hintContainer), NULL); hintContainer = NULL; } + + hints_observe_input(FALSE); } void hints_create(const gchar* input, HintMode mode) @@ -95,14 +107,21 @@ void hints_create(const gchar* input, HintMode mode) Window* win; gulong top_width, top_height, offsetX, offsetY; - hints_clear(); + /* set the current mode only if this was given */ + if (mode) { + currentMode = mode; + } - currentMode = mode; + hints_clear(); doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(vp.gui.webview)); if (!doc) { return; } + + /* add event hanlder for inputbox */ + hints_observe_input(TRUE); + win = webkit_dom_document_get_default_view(doc); top_width = webkit_dom_dom_window_get_inner_width(win); top_height = webkit_dom_dom_window_get_inner_height(win); @@ -123,12 +142,43 @@ void hints_create(const gchar* input, HintMode mode) void hints_update(const gulong num) { + Hint* hint = NULL; + GList* next = NULL; + GList* link = hints; + if (num == 0) { + /* recreate the hints */ + hints_create(NULL, 0); + return; + } + + while (link != NULL) { + hint = (Hint*)link->data; + if (!hints_num_has_prefix(hint->num, num)) { + /* reset the previous color of the hinted elements */ + dom_element_style_set_property(hint->elem, "color", hint->elemColor); + dom_element_style_set_property(hint->elem, "background-color", hint->elemBackgroundColor); + webkit_dom_node_remove_child(WEBKIT_DOM_NODE(hintContainer), WEBKIT_DOM_NODE(hint->hint), NULL); + g_free(hint); + + /* store next element before remove current */ + next = g_list_next(link); + hints = g_list_remove_link(hints, link); + link = next; + } else { + link = g_list_next(link); + } + } + if (g_list_length(hints) == 1) { + hints_fire(num); + } else { + hints_focus(num); + } } void hints_fire(const gulong num) { - PRINT_DEBUG("fire hint %li", num); + PRINT_DEBUG("fire hint %lu", num); } void hints_clear_focus(void) @@ -321,3 +371,70 @@ static gchar* hints_get_xpath(const gchar* input) return xpath; } + +static void hints_observe_input(gboolean observe) +{ + static gulong changeHandler = 0; + static gulong keypressHandler = 0; + + if (observe) { + changeHandler = g_signal_connect( + G_OBJECT(vp.gui.inputbox), "changed", G_CALLBACK(hints_changed_callback), NULL + ); + keypressHandler = g_signal_connect( + G_OBJECT(vp.gui.inputbox), "key-press-event", G_CALLBACK(hints_keypress_callback), NULL + ); + } else if (changeHandler && keypressHandler) { + g_signal_handler_disconnect(G_OBJECT(vp.gui.inputbox), changeHandler); + g_signal_handler_disconnect(G_OBJECT(vp.gui.inputbox), keypressHandler); + changeHandler = 0; + keypressHandler = 0; + } +} + +static gboolean hints_changed_callback(GtkEditable *entry, gpointer data) +{ + const gchar* text = GET_TEXT(); + + if (text[0] == '.' || text[0] == ',') { + hints_create(text + 1, currentMode); + } + + return TRUE; +} + +static gboolean hints_keypress_callback(WebKitWebView* webview, GdkEventKey* event) +{ + gint numval; + guint keyval = event->keyval; + guint state = CLEAN_STATE_WITH_SHIFT(event); + + if (keyval == GDK_BackSpace && (state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK)) { + hintNum /= 10; + hints_update(hintNum); + + return TRUE; + } + numval = g_unichar_digit_value((gunichar)gdk_keyval_to_unicode(keyval)); + if ((numval >= 1 && numval <= 9) || (numval == 0 && hintNum)) { + /* allow a zero as non-first number */ + hintNum = (hintNum ? hintNum * 10 : 0) + numval; + hints_update(hintNum); + + return TRUE; + } + + return FALSE; +} + +static gboolean hints_num_has_prefix(gulong num, gulong prefix) +{ + if (prefix == num) { + return TRUE; + } + if (num >= 10) { + return hints_num_has_prefix(prefix, num / 10); + } + + return FALSE; +} diff --git a/src/main.c b/src/main.c index 055c8cd..83ccbae 100644 --- a/src/main.c +++ b/src/main.c @@ -302,6 +302,7 @@ gboolean vp_set_mode(Mode mode, gboolean clean) break; case VP_MODE_COMMAND: + case VP_MODE_HINTING: gtk_widget_grab_focus(GTK_WIDGET(vp.gui.inputbox)); break; -- 2.20.1