diff options
author | Marco Pesenti Gritti <mpeseng@src.gnome.org> | 2002-12-31 03:29:24 +0800 |
---|---|---|
committer | Marco Pesenti Gritti <mpeseng@src.gnome.org> | 2002-12-31 03:29:24 +0800 |
commit | 6876ede98282c7db318089bfefb292aa59e55d48 (patch) | |
tree | 76b23252d04da232d0ebf22e53bfe3e022686af9 /src/bookmarks/ephy-keywords-entry.c | |
download | gsoc2013-epiphany-6876ede98282c7db318089bfefb292aa59e55d48.tar gsoc2013-epiphany-6876ede98282c7db318089bfefb292aa59e55d48.tar.gz gsoc2013-epiphany-6876ede98282c7db318089bfefb292aa59e55d48.tar.bz2 gsoc2013-epiphany-6876ede98282c7db318089bfefb292aa59e55d48.tar.lz gsoc2013-epiphany-6876ede98282c7db318089bfefb292aa59e55d48.tar.xz gsoc2013-epiphany-6876ede98282c7db318089bfefb292aa59e55d48.tar.zst gsoc2013-epiphany-6876ede98282c7db318089bfefb292aa59e55d48.zip |
Initial revision
Diffstat (limited to 'src/bookmarks/ephy-keywords-entry.c')
-rw-r--r-- | src/bookmarks/ephy-keywords-entry.c | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/src/bookmarks/ephy-keywords-entry.c b/src/bookmarks/ephy-keywords-entry.c new file mode 100644 index 000000000..94d6c93a9 --- /dev/null +++ b/src/bookmarks/ephy-keywords-entry.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2002 Marco Pesenti Gritti + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "ephy-keywords-entry.h" +#include "ephy-marshal.h" +#include "ephy-gobject-misc.h" + +#include <gdk/gdkkeysyms.h> + +//#define DEBUG_MSG(x) g_print x +#define DEBUG_MSG(x) + +#define NOT_IMPLEMENTED g_warning ("not implemented: " G_STRLOC); + +/** + * Private data + */ +struct _EphyKeywordsEntryPrivate +{ + EphyBookmarks *bookmarks; +}; + +/** + * Private functions, only availble from this file + */ +static void ephy_keywords_entry_class_init (EphyKeywordsEntryClass *klass); +static void ephy_keywords_entry_init (EphyKeywordsEntry *w); +static void ephy_keywords_entry_finalize_impl (GObject *o); +static gint ephy_keywords_entry_key_press (GtkWidget *widget, + GdkEventKey *event); + +enum +{ + KEYWORDS_CHANGED, + LAST_SIGNAL +}; + +static GObjectClass *parent_class = NULL; + +static guint keywords_entry_signals[LAST_SIGNAL] = { 0 }; + +MAKE_GET_TYPE (ephy_keywords_entry, "EphyKeywordsEntry", EphyKeywordsEntry, + ephy_keywords_entry_class_init, + ephy_keywords_entry_init, GTK_TYPE_ENTRY); + +static void +ephy_keywords_entry_class_init (EphyKeywordsEntryClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + GtkWidgetClass *widget_class; + + parent_class = g_type_class_peek_parent (class); + widget_class = (GtkWidgetClass*) class; + + gobject_class->finalize = ephy_keywords_entry_finalize_impl; + + widget_class->key_press_event = ephy_keywords_entry_key_press; + + keywords_entry_signals[KEYWORDS_CHANGED] = + g_signal_new ("keywords_changed", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EphyKeywordsEntryClass, keywords_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); +} + +static void +try_to_expand_keyword (GtkEditable *editable) +{ + char *entry_text; + char *user_text; + const char *expand_text; + char *insert_text; + int user_text_length; + int expand_text_length; + int keyword_offset = 0; + int tmp; + EphyKeywordsEntry *entry = EPHY_KEYWORDS_ENTRY (editable); + EphyNode *node; + + entry_text = gtk_editable_get_chars (editable, 0, -1); + g_return_if_fail (entry_text != NULL); + + DEBUG_MSG (("Entry text \"%s\"\n", entry_text)); + + user_text = g_utf8_strrchr (entry_text, -1, ' '); + + if (user_text) + { + user_text = g_utf8_find_next_char (user_text, NULL); + keyword_offset = g_utf8_pointer_to_offset + (entry_text, user_text); + } + else + { + user_text = entry_text; + } + + DEBUG_MSG (("User text \"%s\"\n", user_text)); + + node = ephy_bookmarks_find_keyword (entry->priv->bookmarks, + user_text, TRUE); + if (node) + { + expand_text = ephy_node_get_property_string + (node, EPHY_NODE_KEYWORD_PROP_NAME); + + DEBUG_MSG (("Expand text %s\n", expand_text)); + + expand_text_length = g_utf8_strlen (expand_text, -1); + user_text_length = g_utf8_strlen (user_text, -1); + + insert_text = g_utf8_offset_to_pointer (expand_text, user_text_length); + gtk_editable_insert_text (editable, + insert_text, + g_utf8_strlen (insert_text, -1), + &tmp); + gtk_editable_select_region (editable, user_text_length + keyword_offset, -1); + } + else + { + DEBUG_MSG (("No expansion.\n")); + } + + g_free (entry_text); +} + +/* Until we have a more elegant solution, this is how we figure out if + * the GtkEntry inserted characters, assuming that the return value is + * TRUE indicating that the GtkEntry consumed the key event for some + * reason. This is a clone of code from GtkEntry. + */ +static gboolean +entry_would_have_inserted_characters (const GdkEventKey *event) +{ + switch (event->keyval) { + case GDK_BackSpace: + case GDK_Clear: + case GDK_Insert: + case GDK_Delete: + case GDK_Home: + case GDK_End: + case GDK_Left: + case GDK_Right: + case GDK_Return: + return FALSE; + default: + if (event->keyval >= 0x20 && event->keyval <= 0xFF) { + if ((event->state & GDK_CONTROL_MASK) != 0) { + return FALSE; + } + if ((event->state & GDK_MOD1_MASK) != 0) { + return FALSE; + } + } + return event->length > 0; + } +} + +static int +get_editable_number_of_chars (GtkEditable *editable) +{ + char *text; + int length; + + text = gtk_editable_get_chars (editable, 0, -1); + length = g_utf8_strlen (text, -1); + g_free (text); + return length; +} + +static void +set_position_and_selection_to_end (GtkEditable *editable) +{ + int end; + + end = get_editable_number_of_chars (editable); + gtk_editable_select_region (editable, end, end); + gtk_editable_set_position (editable, end); +} + +static gboolean +position_and_selection_are_at_end (GtkEditable *editable) +{ + int end; + int start_sel, end_sel; + + end = get_editable_number_of_chars (editable); + if (gtk_editable_get_selection_bounds (editable, &start_sel, &end_sel)) + { + if (start_sel != end || end_sel != end) + { + return FALSE; + } + } + return gtk_editable_get_position (editable) == end; +} + +static gint +ephy_keywords_entry_key_press (GtkWidget *widget, + GdkEventKey *event) +{ + GtkEditable *editable; + GdkEventKey *keyevent; + EphyKeywordsEntry *entry; + gboolean result; + + entry = EPHY_KEYWORDS_ENTRY (widget); + editable = GTK_EDITABLE (entry); + keyevent = (GdkEventKey *)event; + + /* After typing the right arrow key we move the selection to + * the end, if we have a valid selection - since this is most + * likely an auto-completion. We ignore shift / control since + * they can validly be used to extend the selection. + */ + if ((keyevent->keyval == GDK_Right || keyevent->keyval == GDK_End) && + !(keyevent->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) && + gtk_editable_get_selection_bounds (editable, NULL, NULL)) + { + set_position_and_selection_to_end (editable); + } + + result = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); + + /* Only do expanding when we are typing at the end of the + * text. + */ + if (entry_would_have_inserted_characters (event) + && position_and_selection_are_at_end (editable)) + { + try_to_expand_keyword (editable); + } + + g_signal_emit (G_OBJECT (entry), keywords_entry_signals[KEYWORDS_CHANGED], 0); + + return result; +} + +static void +ephy_keywords_entry_init (EphyKeywordsEntry *w) +{ + w->priv = g_new0 (EphyKeywordsEntryPrivate, 1); + w->priv->bookmarks = NULL; +} + +static void +ephy_keywords_entry_finalize_impl (GObject *o) +{ + EphyKeywordsEntry *w = EPHY_KEYWORDS_ENTRY (o); + EphyKeywordsEntryPrivate *p = w->priv; + + g_free (p); + G_OBJECT_CLASS (parent_class)->finalize (o); +} + +GtkWidget * +ephy_keywords_entry_new (void) +{ + return GTK_WIDGET (g_object_new (EPHY_TYPE_LOCATION_ENTRY, NULL)); +} + +void +ephy_keywords_entry_set_bookmarks (EphyKeywordsEntry *w, + EphyBookmarks *bookmarks) +{ + w->priv->bookmarks = bookmarks; +} |