gtksourceview r2092 - in trunk: . gtksourceview tests



Author: muntyan
Date: Sat Nov 29 22:15:42 2008
New Revision: 2092
URL: http://svn.gnome.org/viewvc/gtksourceview?rev=2092&view=rev

Log:
2008-11-29  Yevgen Muntyan  <muntyan tamu edu>

	* gtksourceview/gtksourceiter.c: (forward_chars_with_skipping):
	call g_utf8_casefold() before normalizing, to match behavior
	of the search code. Bug #496780.
	* tests/test-widget.c: added Find command.



Modified:
   trunk/ChangeLog
   trunk/gtksourceview/gtksourceiter.c
   trunk/tests/test-widget.c

Modified: trunk/gtksourceview/gtksourceiter.c
==============================================================================
--- trunk/gtksourceview/gtksourceiter.c	(original)
+++ trunk/gtksourceview/gtksourceiter.c	Sat Nov 29 22:15:42 2008
@@ -1,7 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *  gtksourceiter.h
  *
- *  Copyright (C) 2000 - 2005 Paolo Maggi 
+ *  Copyright (C) 2000 - 2005 Paolo Maggi
  *  Copyright (C) 2002, 2003 Jeroen Zwartepoorte
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -222,7 +222,7 @@
 
 finally_2:
 	g_free (normalized_s1);
-	g_free (normalized_s2); 
+	g_free (normalized_s2);
 
 	return ret;
 }
@@ -237,7 +237,7 @@
 	while (tags)
 	{
 		gboolean this_invisible, invisible_set;
-		g_object_get (tags->data, "invisible", &this_invisible, 
+		g_object_get (tags->data, "invisible", &this_invisible,
 			      "invisible-set", &invisible_set, NULL);
 		if (invisible_set)
 			invisible = this_invisible;
@@ -281,16 +281,19 @@
 		{
 			/* being UTF8 correct sucks; this accounts for extra
 			   offsets coming from canonical decompositions of
-			   UTF8 characters (e.g. accented characters) which 
+			   UTF8 characters (e.g. accented characters) which
 			   g_utf8_normalize() performs */
 			gchar *normal;
+			gchar *casefold;
 			gchar buffer[6];
 			gint buffer_len;
 
 			buffer_len = g_unichar_to_utf8 (gtk_text_iter_get_char (iter), buffer);
-			normal = g_utf8_normalize (buffer, buffer_len, G_NORMALIZE_NFD);
+			casefold = g_utf8_casefold (buffer, buffer_len);
+			normal = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
 			i -= (g_utf8_strlen (normal, -1) - 1);
 			g_free (normal);
+			g_free (casefold);
 		}
 
 		gtk_text_iter_forward_char (iter);
@@ -564,14 +567,14 @@
  * @match_start: return location for start of match, or %%NULL.
  * @match_end: return location for end of match, or %%NULL.
  * @limit: bound for the search, or %%NULL for the end of the buffer.
- * 
- * Searches forward for @str. Any match is returned by setting 
- * @match_start to the first character of the match and @match_end to the 
+ *
+ * Searches forward for @str. Any match is returned by setting
+ * @match_start to the first character of the match and @match_end to the
  * first character after the match. The search will not continue past
  * @limit. Note that a search is a linear or O(n) operation, so you
  * may wish to use @limit to avoid locking up your UI on large
  * buffers.
- * 
+ *
  * If the #GTK_SOURCE_SEARCH_VISIBLE_ONLY flag is present, the match may
  * have invisible text interspersed in @str. i.e. @str will be a
  * possibly-noncontiguous subsequence of the matched range. similarly,
@@ -584,7 +587,7 @@
  *
  * Same as gtk_text_iter_forward_search(), but supports case insensitive
  * searching.
- * 
+ *
  * Return value: whether a match was found.
  **/
 gboolean
@@ -608,7 +611,7 @@
 	if ((flags & GTK_SOURCE_SEARCH_CASE_INSENSITIVE) == 0)
 		return gtk_text_iter_forward_search (iter, str, flags,
 						     match_start, match_end,
-						     limit); 
+						     limit);
 
 	if (limit && gtk_text_iter_compare (iter, limit) >= 0)
 		return FALSE;
@@ -684,10 +687,10 @@
  * @match_start: return location for start of match, or %%NULL.
  * @match_end: return location for end of match, or %%NULL.
  * @limit: location of last possible @match_start, or %%NULL for start of buffer.
- * 
+ *
  * Same as gtk_text_iter_backward_search(), but supports case insensitive
  * searching.
- * 
+ *
  * Return value: whether a match was found.
  **/
 gboolean
@@ -711,7 +714,7 @@
 	if ((flags & GTK_SOURCE_SEARCH_CASE_INSENSITIVE) == 0)
 		return gtk_text_iter_backward_search (iter, str, flags,
 						      match_start, match_end,
-						      limit); 
+						      limit);
 
 	if (limit && gtk_text_iter_compare (iter, limit) <= 0)
 		return FALSE;

Modified: trunk/tests/test-widget.c
==============================================================================
--- trunk/tests/test-widget.c	(original)
+++ trunk/tests/test-widget.c	Sat Nov 29 22:15:42 2008
@@ -36,6 +36,7 @@
 #include <gtksourceview/gtksourcelanguagemanager.h>
 #include <gtksourceview/gtksourcestyleschememanager.h>
 #include <gtksourceview/gtksourceprintcompositor.h>
+#include <gtksourceview/gtksourceiter.h>
 #ifdef TEST_XML_MEM
 #include <libxml/xmlreader.h>
 #endif
@@ -59,7 +60,9 @@
 						  gpointer         user_data);
 static void       print_file_cb                  (GtkAction       *action,
 						  gpointer         user_data);
-static void       debug_thing_3_cb		 (GtkAction       *action,
+static void       find_cb			 (GtkAction       *action,
+						  gpointer         user_data);
+static void       replace_cb			 (GtkAction       *action,
 						  gpointer         user_data);
 
 static void       new_view_cb                    (GtkAction       *action,
@@ -112,8 +115,10 @@
 	{ "TabWidth", NULL, "_Tab Width" },
 	{ "IndentWidth", NULL, "I_ndent Width" },
 	{ "SmartHomeEnd", NULL, "_Smart Home/End" },
-	{ "DebugThing3", GTK_STOCK_FIND_AND_REPLACE, "Search and _Replace", "<control>R",
-	  "Search and Replace", G_CALLBACK (debug_thing_3_cb) },
+	{ "Find", GTK_STOCK_FIND, "_Find", "<control>F",
+	  "Find", G_CALLBACK (find_cb) },
+	{ "Replace", GTK_STOCK_FIND_AND_REPLACE, "Search and _Replace", "<control>R",
+	  "Search and Replace", G_CALLBACK (replace_cb) },
 };
 
 static GtkToggleActionEntry toggle_entries[] = {
@@ -228,7 +233,8 @@
 "    <menu action=\"FileMenu\">"
 "      <menuitem action=\"Open\"/>"
 "      <menuitem action=\"Print\"/>"
-"      <menuitem action=\"DebugThing3\"/>"
+"      <menuitem action=\"Find\"/>"
+"      <menuitem action=\"Replace\"/>"
 "      <separator/>"
 "      <menuitem action=\"Quit\"/>"
 "    </menu>"
@@ -616,21 +622,28 @@
 
 /* Buffer action callbacks ------------------------------------------------------------ */
 
+static struct {
+	char *what;
+	char *replacement;
+	GtkSourceSearchFlags flags;
+} search_data = {
+	NULL,
+	NULL,
+	GTK_SOURCE_SEARCH_CASE_INSENSITIVE
+};
+
 static gboolean
-replace_dialog (GtkWidget *widget,
-		char     **what_p,
-		char     **replacement_p)
+search_dialog (GtkWidget            *widget,
+	       gboolean              replace,
+	       char                **what_p,
+	       char                **replacement_p,
+	       GtkSourceSearchFlags *flags_p)
 {
 	GtkWidget *dialog;
 	GtkEntry *entry1, *entry2;
-	static char *what, *replacement;
-
-	if (!what)
-		what = g_strdup ("gtk");
-	if (!replacement)
-		replacement = g_strdup ("boo");
+	GtkToggleButton *case_sensitive;
 
-	dialog = gtk_dialog_new_with_buttons ("Replace",
+	dialog = gtk_dialog_new_with_buttons (replace ? "Replace" : "Find",
 					      GTK_WINDOW (gtk_widget_get_toplevel (widget)),
 					      GTK_DIALOG_MODAL,
 					      GTK_STOCK_CANCEL,
@@ -642,19 +655,27 @@
 
 	entry1 = g_object_new (GTK_TYPE_ENTRY,
 			       "visible", TRUE,
-			       "text", what ? what : "",
+			       "text", search_data.what ? search_data.what : "",
 			       "activates-default", TRUE,
 			       NULL);
 	gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog)->vbox),
 				     GTK_WIDGET (entry1));
 	entry2 = g_object_new (GTK_TYPE_ENTRY,
-			       "visible", TRUE,
-			       "text", replacement ? replacement : "",
+			       "visible", replace,
+			       "text", search_data.replacement ? search_data.replacement : "",
 			       "activates-default", TRUE,
 			       NULL);
 	gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog)->vbox),
 				     GTK_WIDGET (entry2));
 
+	case_sensitive = g_object_new (GTK_TYPE_CHECK_BUTTON,
+				       "visible", TRUE,
+				       "label", "Case sensitive",
+				       "active", !(search_data.flags & GTK_SOURCE_SEARCH_CASE_INSENSITIVE),
+				       NULL);
+	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+			    GTK_WIDGET (case_sensitive), FALSE, FALSE, 0);
+
 	while (TRUE)
 	{
 		if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
@@ -667,48 +688,85 @@
 			break;
 	}
 
-	g_free (what);
-	*what_p = what = g_strdup (gtk_entry_get_text (entry1));
-	g_free (replacement);
-	*replacement_p = replacement = g_strdup (gtk_entry_get_text (entry2));
+	g_free (search_data.what);
+	*what_p = search_data.what = g_strdup (gtk_entry_get_text (entry1));
+	g_free (search_data.replacement);
+	*replacement_p = search_data.replacement = g_strdup (gtk_entry_get_text (entry2));
+	*flags_p = search_data.flags = gtk_toggle_button_get_active (case_sensitive) ?
+					0 : GTK_SOURCE_SEARCH_CASE_INSENSITIVE;
 
 	gtk_widget_destroy (dialog);
 	return TRUE;
 }
 
 static void
-debug_thing_3_cb (GtkAction *action,
-		  gpointer   user_data)
+do_search_replace (GtkTextView *view,
+		   gboolean     replace)
 {
-	GtkTextView *view = user_data;
 	GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
 	GtkTextIter iter;
 	char *what, *replacement;
+	GtkSourceSearchFlags flags;
 
-	if (!replace_dialog (GTK_WIDGET (view), &what, &replacement))
+	if (!search_dialog (GTK_WIDGET (view), replace, &what, &replacement, &flags))
 		return;
 
-	gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
+	if (replace)
+	{
+		gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
 
-	while (TRUE)
+		while (TRUE)
+		{
+			GtkTextIter match_start, match_end;
+
+			if (!gtk_source_iter_forward_search (&iter, what, flags,
+							     &match_start,
+							     &match_end,
+							     NULL))
+			{
+				break;
+			}
+
+			gtk_text_buffer_delete (buffer, &match_start, &match_end);
+			gtk_text_buffer_insert (buffer, &match_start, replacement, -1);
+			iter = match_start;
+		}
+	}
+	else
 	{
 		GtkTextIter match_start, match_end;
 
-		if (!gtk_text_iter_forward_search (&iter, what, 0,
-						   &match_start,
-						   &match_end,
-						   NULL))
+		gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
+
+		if (gtk_source_iter_forward_search (&iter, what, flags, &match_start, &match_end, NULL))
 		{
-			break;
+			gtk_text_buffer_select_range (buffer, &match_start, &match_end);
+		}
+		else
+		{
+			GtkTextIter insert = iter;
+			gtk_text_buffer_get_start_iter (buffer, &iter);
+			if (gtk_source_iter_forward_search (&iter, what, flags, &match_start, &match_end, &insert))
+				gtk_text_buffer_select_range (buffer, &match_start, &match_end);
 		}
-
-		gtk_text_buffer_delete (buffer, &match_start, &match_end);
-		gtk_text_buffer_insert (buffer, &match_start, replacement, -1);
-		iter = match_start;
 	}
 }
 
 static void
+find_cb (GtkAction *action,
+	 gpointer   user_data)
+{
+	do_search_replace (user_data, FALSE);
+}
+
+static void
+replace_cb (GtkAction *action,
+	    gpointer   user_data)
+{
+	do_search_replace (user_data, TRUE);
+}
+
+static void
 open_file_cb (GtkAction *action, gpointer user_data)
 {
 	GtkWidget *chooser;



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