epiphany r8707 - in branches/gnome-2-26: lib/widgets src



Author: gns
Date: Tue Jan 20 00:35:13 2009
New Revision: 8707
URL: http://svn.gnome.org/viewvc/epiphany?rev=8707&view=rev

Log:
Implement multiple keyword-based AND-search for the location bar

Bug #568101

Modified:
   branches/gnome-2-26/lib/widgets/ephy-location-entry.c
   branches/gnome-2-26/lib/widgets/ephy-location-entry.h
   branches/gnome-2-26/src/ephy-location-action.c

Modified: branches/gnome-2-26/lib/widgets/ephy-location-entry.c
==============================================================================
--- branches/gnome-2-26/lib/widgets/ephy-location-entry.c	(original)
+++ branches/gnome-2-26/lib/widgets/ephy-location-entry.c	Tue Jan 20 00:35:13 2009
@@ -53,7 +53,7 @@
 	GdkColor secure_bg_colour;
 	GdkColor secure_fg_colour;
 
-	GRegex *regex;
+	GSList *search_terms;
 
 	char *before_completion;
 	char *saved_text;
@@ -203,6 +203,17 @@
 	ephy_location_entry_set_secure (entry, priv->secure);
 }
 
+inline static void
+free_search_terms (GSList *search_terms)
+{
+	GSList *iter;
+	
+	for (iter = search_terms; iter != NULL; iter = iter->next)
+		g_regex_unref ((GRegex*)iter->data);
+	
+	g_slist_free (search_terms);
+}
+
 static void
 ephy_location_entry_finalize (GObject *object)
 {
@@ -216,10 +227,10 @@
 		g_object_unref (priv->favicon);
 	}
 	
-	if (priv->regex)
+	if (priv->search_terms)
 	{
-		g_regex_unref (priv->regex);
-		priv->regex = NULL;
+		free_search_terms (priv->search_terms);
+		priv->search_terms = NULL;
 	}
 
 	parent_class->finalize (object);
@@ -348,24 +359,88 @@
 		priv->can_redo = FALSE;
 	}	
 	
-	if (priv->regex)
+	if (priv->search_terms)
 	{
-		g_regex_unref (priv->regex);
-		priv->regex = NULL;
+		free_search_terms (priv->search_terms);
+		priv->search_terms = NULL;
 	}
-	
+
 	text = gtk_entry_get_text (GTK_ENTRY (editable));
 
+	/*
+	 * user is specifying a regular expression, so we will
+	 * have only one search term
+	 */
 	if (g_str_has_prefix (text, "re:"))
+	{
+		GRegex *regex;
 		pattern = g_strdup (text+3);
+		regex = g_regex_new (pattern,
+				     G_REGEX_CASELESS | G_REGEX_OPTIMIZE,
+				     G_REGEX_MATCH_NOTEMPTY, NULL);
+		priv->search_terms = g_slist_append (priv->search_terms, regex);
+		g_free (pattern);
+	}
 	else
-		pattern = g_regex_escape_string (text, -1);
+	{
+		const char *current;
+		const char *ptr;
+		char *tmp;
+		char *term;
+		GRegex *term_regex;
+		GRegex *quote_regex;
+		guint count;
+		gboolean inside_quotes = FALSE;
 
-	priv->regex = g_regex_new (pattern, 
-				G_REGEX_CASELESS | G_REGEX_OPTIMIZE, 
-				G_REGEX_MATCH_NOTEMPTY, NULL);
+		quote_regex = g_regex_new ("\"", G_REGEX_OPTIMIZE,
+					   G_REGEX_MATCH_NOTEMPTY, NULL);
+		
+		/*
+		 * This code loops through the string using pointer arythmetics.
+		 * Although the string we are handling may contain UTF-8 chars
+		 * this works because only ASCII chars affect what is actually
+		 * copied from the string as a search term.
+		 */
+		for (count = 0, current = ptr = text; ptr[0] != '\0'; ptr++, count++)
+		{
+			/*
+			 * If we found a double quote character; we will 
+			 * consume bytes up until the next quote, or
+			 * end of line;
+			 */
+			if (ptr[0] == '"')
+				inside_quotes = !inside_quotes;
+
+			/*
+			 * If we found a space, and we are not looking for a
+			 * closing double quote, or if the next char is the
+			 * end of the string, append what we have already as
+			 * a search term.
+			 */
+			if (((ptr[0] == ' ') && (!inside_quotes)) || ptr[1] == '\0')
+			{
+				/*
+				 * remove quotes, and quote any regex-sensitive
+				 * characters
+				 */
+				tmp = g_regex_escape_string (current, count);
+				term = g_regex_replace (quote_regex, tmp, -1, 0,
+							"", G_REGEX_MATCH_NOTEMPTY, NULL);
+				g_free (tmp);
+
+				term_regex = g_regex_new (g_strstrip (term),
+							  G_REGEX_CASELESS | G_REGEX_OPTIMIZE,
+							  G_REGEX_MATCH_NOTEMPTY, NULL);
+				priv->search_terms = g_slist_append (priv->search_terms, term_regex);
+				g_free (term);
+
+				count = 0;
+				current = ptr + 1;
+			}
+		}
 
-	g_free (pattern);
+		g_regex_unref (quote_regex);
+	}
 
 	update_favicon (entry);
 
@@ -922,7 +997,7 @@
 	p->user_changed = FALSE;
 	p->block_update = FALSE;
 	p->saved_text = NULL;
-	p->regex = NULL;
+	p->search_terms = NULL;
 	
 	ephy_location_entry_construct_contents (le);
 
@@ -1011,18 +1086,32 @@
 		ctext = title;
 	}
 
-	g_regex_match (priv->regex, ctext, G_REGEX_MATCH_NOTEMPTY, &match);
-
-	while (g_match_info_matches (match))
+	if (priv->search_terms)
 	{
-		g_match_info_fetch_pos (match, 0, &start, &end);
+		GSList *iter;
+		GRegex *regex;
 
-		att = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
-		att->start_index = start;
-		att->end_index = end;
+		for (iter = priv->search_terms; iter != NULL; iter = iter->next)
+		{
+			regex = (GRegex*) iter->data;
+			g_regex_match (regex, ctext, G_REGEX_MATCH_NOTEMPTY, &match);
+
+			while (g_match_info_matches (match))
+			{
+				g_match_info_fetch_pos (match, 0, &start, &end);
+
+				att = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+				att->start_index = start;
+				att->end_index = end;
+
+				pango_attr_list_insert (list, att);
+				g_match_info_next (match, NULL);
+			}
+
+			g_match_info_free (match);
+			match = NULL;
+		}
 
-		pango_attr_list_insert (list, att);
-		g_match_info_next (match, NULL);
 	}
 
 	g_object_set (G_OBJECT (cell),
@@ -1035,7 +1124,6 @@
 	g_value_unset (&text);
 
 	pango_attr_list_unref (list);
-	g_match_info_free (match);
 
 	g_free (title);
 	g_free (url);
@@ -1396,10 +1484,20 @@
 	gtk_widget_set_tooltip_text (priv->lock_ebox, tooltip);
 }
 
-GRegex *
-ephy_location_entry_get_regex (EphyLocationEntry *entry)
+/**
+ * ephy_location_entry_get_search_terms:
+ * @entry: an #EphyLocationEntry widget
+ *
+ * Return the internal #GSList containing the search terms as #GRegex
+ * instances, formed in @entry on user changes.
+ *
+ * Return value: the internal #GSList
+ *
+ **/
+GSList *
+ephy_location_entry_get_search_terms (EphyLocationEntry *entry)
 {
 	EphyLocationEntryPrivate *priv = entry->priv;
 	
-	return priv->regex;
+	return priv->search_terms;
 }

Modified: branches/gnome-2-26/lib/widgets/ephy-location-entry.h
==============================================================================
--- branches/gnome-2-26/lib/widgets/ephy-location-entry.h	(original)
+++ branches/gnome-2-26/lib/widgets/ephy-location-entry.h	Tue Jan 20 00:35:13 2009
@@ -89,7 +89,7 @@
 
 gboolean	ephy_location_entry_get_can_redo	(EphyLocationEntry *entry);
 
-GRegex *	ephy_location_entry_get_regex		(EphyLocationEntry *entry);
+GSList         *ephy_location_entry_get_search_terms	(EphyLocationEntry *entry);
 
 gboolean	ephy_location_entry_reset		(EphyLocationEntry *entry);
 

Modified: branches/gnome-2-26/src/ephy-location-action.c
==============================================================================
--- branches/gnome-2-26/src/ephy-location-action.c	(original)
+++ branches/gnome-2-26/src/ephy-location-action.c	Tue Jan 20 00:35:13 2009
@@ -98,7 +98,7 @@
 
 	gboolean ret = FALSE;
 	GtkTreeModel *model;
-	GRegex *regex;
+	GSList *search_terms;
 
 	model = gtk_entry_completion_get_model (completion);
 
@@ -112,12 +112,26 @@
 	if (!key)
 		return FALSE;
 	
-	regex = ephy_location_entry_get_regex ((EphyLocationEntry *) data);
-	
-	ret = (g_regex_match (regex, item, G_REGEX_MATCH_NOTEMPTY, NULL)
-		|| g_regex_match (regex, url, G_REGEX_MATCH_NOTEMPTY, NULL)
-		|| g_regex_match (regex, keywords, G_REGEX_MATCH_NOTEMPTY, NULL)
-		);
+	search_terms = ephy_location_entry_get_search_terms (data);
+
+	if (search_terms)
+	{
+		GSList *iter;
+		GRegex *current = NULL;
+
+		ret = TRUE;
+		for (iter = search_terms; iter != NULL; iter = iter->next)
+		{
+			current = (GRegex*) iter->data;
+			if ((!g_regex_match (current, item, G_REGEX_MATCH_NOTEMPTY, NULL)) &&
+			    (!g_regex_match (current, url, G_REGEX_MATCH_NOTEMPTY, NULL)) &&
+			    (!g_regex_match (current, keywords, G_REGEX_MATCH_NOTEMPTY, NULL)))
+			{
+				ret = FALSE;
+				break;
+			}
+		}
+	}
 
 	g_free (item);
 	g_free (url);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]