changeset 12465:ae4ae98bca20

[gaim-migrate @ 14775] A patch from Bleeter, with some copyright stuff updated by me. This syncs gtksourceiter.c and gtksourceiter.h with upstream. It doesn't seem to break anything and supposedly has bug fixes. Let's see what happens.... committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Mon, 12 Dec 2005 08:08:07 +0000
parents 2b08a27c2342
children 31e4eb57cc86
files COPYRIGHT src/gtksourceiter.c src/gtksourceiter.h
diffstat 3 files changed, 105 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Mon Dec 12 08:05:03 2005 +0000
+++ b/COPYRIGHT	Mon Dec 12 08:08:07 2005 +0000
@@ -29,6 +29,7 @@
 David Blue
 Jason Boerner
 Graham Booker
+Paolo Borelli
 Craig Boston
 Chris Boyle
 Derrick J Brashear
@@ -91,6 +92,7 @@
 François Gagné
 Evgueni V. Gavrilov
 Ignacy Gawedzki
+Gustavo Giráldez
 Richard Gobeille
 Michael Golden
 Charlie Gordon
@@ -197,6 +199,7 @@
 Sam S.
 Tom Samstag
 Neil Sanchala
+Laurent Sansonetti
 Alceste Scalas
 Carsten Schaar
 Luke Schierer
--- a/src/gtksourceiter.c	Mon Dec 12 08:05:03 2005 +0000
+++ b/src/gtksourceiter.c	Mon Dec 12 08:08:07 2005 +0000
@@ -1,13 +1,15 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 
- * @file gtksourceiter.h GTK+ Source iterator
- * @ingroup gtkui
- *
- *  gaim
+ *  gtksourceiter.c
  *
  *  Gaim is the legal property of its developers, whose names are too numerous
  *  to list here.  Please refer to the COPYRIGHT file distributed with this
  *  source distribution.
  *
+ *  The following copyright notice applies to this file:
+ *
+ *  Copyright (C) 2000 - 2005 Paolo Maggi 
+ *  Copyright (C) 2002, 2003 Jeroen Zwartepoorte
+ *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU Library General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
@@ -36,12 +38,36 @@
 
 #define GTK_TEXT_UNKNOWN_CHAR 0xFFFC
 
-static gchar *
+/* this function acts like g_utf8_offset_to_pointer() except that if it finds a
+ * decomposable character it consumes the decomposition length from the given
+ * offset.  So it's useful when the offset was calculated for the normalized
+ * version of str, but we need a pointer to str itself. */
+static const gchar *
+pointer_from_offset_skipping_decomp (const gchar *str, gint offset)
+{
+	gchar *casefold, *normal;
+	const gchar *p, *q;
+
+	p = str;
+	while (offset > 0)
+	{
+		q = g_utf8_next_char (p);
+		casefold = g_utf8_casefold (p, q - p);
+		normal = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
+		offset -= g_utf8_strlen (normal, -1);
+		g_free (casefold);
+		g_free (normal);
+		p = q;
+	}
+	return p;
+}
+
+static const gchar *
 g_utf8_strcasestr (const gchar *haystack, const gchar *needle)
 {
 	gsize needle_len;
 	gsize haystack_len;
-	gchar *ret = NULL;
+	const gchar *ret = NULL;
 	gchar *p;
 	gchar *casefold;
 	gchar *caseless_haystack;
@@ -51,7 +77,7 @@
 	g_return_val_if_fail (needle != NULL, NULL);
 
 	casefold = g_utf8_casefold (haystack, -1);
-	caseless_haystack = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
+	caseless_haystack = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
 	g_free (casefold);
 
 	needle_len = g_utf8_strlen (needle, -1);
@@ -77,7 +103,7 @@
 	{
 		if ((strncmp (p, needle, needle_len) == 0))
 		{
-			ret = g_utf8_offset_to_pointer (haystack, i);
+			ret = pointer_from_offset_skipping_decomp (haystack, i);
 			goto finally_1;
 		}
 
@@ -91,12 +117,12 @@
 	return ret;
 }
 
-static gchar *
+static const gchar *
 g_utf8_strrcasestr (const gchar *haystack, const gchar *needle)
 {
 	gsize needle_len;
 	gsize haystack_len;
-	gchar *ret = NULL;
+	const gchar *ret = NULL;
 	gchar *p;
 	gchar *casefold;
 	gchar *caseless_haystack;
@@ -106,7 +132,7 @@
 	g_return_val_if_fail (needle != NULL, NULL);
 
 	casefold = g_utf8_casefold (haystack, -1);
-	caseless_haystack = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
+	caseless_haystack = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
 	g_free (casefold);
 
 	needle_len = g_utf8_strlen (needle, -1);
@@ -124,16 +150,15 @@
 		goto finally_1;
 	}
 
-	haystack_len = strlen (caseless_haystack);
+	i = haystack_len - needle_len;
+	p = g_utf8_offset_to_pointer (caseless_haystack, i);
 	needle_len = strlen (needle);
-	p = (gchar *)caseless_haystack + haystack_len - needle_len;
-	i = haystack_len - needle_len;
 
 	while (p >= caseless_haystack)
 	{
-		if (strncasecmp (p, needle, needle_len) == 0)
+		if (strncmp (p, needle, needle_len) == 0)
 		{
-			ret = g_utf8_offset_to_pointer (haystack, i);
+			ret = pointer_from_offset_skipping_decomp (haystack, i);
 			goto finally_1;
 		}
 
@@ -164,11 +189,11 @@
 	g_return_val_if_fail (n2 > 0, FALSE);
 
 	casefold = g_utf8_casefold (s1, n1);
-	normalized_s1 = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
+	normalized_s1 = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
 	g_free (casefold);
 
 	casefold = g_utf8_casefold (s2, n2);
-	normalized_s2 = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
+	normalized_s2 = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
 	g_free (casefold);
 
 	len_s1 = strlen (normalized_s1);
@@ -190,7 +215,8 @@
 forward_chars_with_skipping (GtkTextIter *iter,
 			     gint         count,
 			     gboolean     skip_invisible,
-			     gboolean     skip_nontext)
+			     gboolean     skip_nontext,
+			     gboolean     skip_decomp)
 {
 	gint i;
 
@@ -202,15 +228,37 @@
 	{
 		gboolean ignored = FALSE;
 
+		/* minimal workaround to avoid the infinite loop of bug #168247.
+		 * It doesn't fix the problemjust the symptom...
+		 */
+		if (gtk_text_iter_is_end (iter))
+			return;
+
 		if (skip_nontext && gtk_text_iter_get_char (iter) == GTK_TEXT_UNKNOWN_CHAR)
 			ignored = TRUE;
 
 #if 0
 		if (!ignored && skip_invisible &&
-		    _gtk_text_btree_char_is_invisible (iter))
+		    /* _gtk_text_btree_char_is_invisible (iter)*/ FALSE)
 			ignored = TRUE;
 #endif
 
+		if (!ignored && skip_decomp)
+		{
+			/* being UTF8 correct sucks; this accounts for extra
+			   offsets coming from canonical decompositions of
+			   UTF8 characters (e.g. accented characters) which 
+			   g_utf8_normalize() performs */
+			gchar *normal;
+			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);
+			i -= (g_utf8_strlen (normal, -1) - 1);
+			g_free (normal);
+		}
+
 		gtk_text_iter_forward_char (iter);
 
 		if (!ignored)
@@ -292,18 +340,14 @@
 	/* If match start needs to be returned, set it to the
 	 * start of the search string.
 	 */
+	forward_chars_with_skipping (&next, offset, visible_only, !slice, FALSE);
 	if (match_start)
 	{
 		*match_start = next;
-
-		forward_chars_with_skipping (match_start, offset,
-					     visible_only, !slice);
 	}
 
 	/* Go to end of search string */
-	offset += g_utf8_strlen (*lines, -1);
-
-	forward_chars_with_skipping (&next, offset, visible_only, !slice);
+	forward_chars_with_skipping (&next, g_utf8_strlen (*lines, -1), visible_only, !slice, TRUE);
 
 	g_free (line_text);
 
@@ -389,19 +433,18 @@
 	/* Get offset to start of search string */
 	offset = g_utf8_strlen (line_text, found - line_text);
 
+	forward_chars_with_skipping (&next, offset, visible_only, !slice, FALSE);
+
 	/* If match start needs to be returned, set it to the
 	 * start of the search string.
 	 */
 	if (match_start)
 	{
 		*match_start = next;
-		gtk_text_iter_set_visible_line_offset (match_start, offset);
 	}
 
 	/* Go to end of search string */
-	offset += g_utf8_strlen (*lines, -1);
-
-	forward_chars_with_skipping (&next, offset, visible_only, !slice);
+	forward_chars_with_skipping (&next, g_utf8_strlen (*lines, -1), visible_only, !slice, TRUE);
 
 	g_free (line_text);
 
@@ -448,7 +491,7 @@
 			new_string[len] = 0;
 			casefold = g_utf8_casefold (new_string, -1);
 			g_free (new_string);
-			new_string = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
+			new_string = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
 			g_free (casefold);
 			string_list = g_slist_prepend (string_list, new_string);
 			n++;
@@ -461,7 +504,7 @@
 	{
 		n++;
 		casefold = g_utf8_casefold (string, -1);
-		new_string = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
+		new_string = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
 		g_free (casefold);
 		string_list = g_slist_prepend (string_list, new_string);
 	}
@@ -481,6 +524,12 @@
 
 /**
  * gtk_source_iter_forward_search:
+ * @iter: start of search.
+ * @str: a search string.
+ * @flags: flags affecting how the search is done.
+ * @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 
@@ -502,14 +551,8 @@
  * Same as gtk_text_iter_forward_search(), but supports case insensitive
  * searching.
  * 
- * @param iter start of search
- * @param str a search string
- * @param flags flags affecting how the search is done
- * @param match_start return location for start of match, or %NULL
- * @param match_end return location for end of match, or %NULL
- * @param limit bound for the search, or %NULL for the end of the buffer
- * @return returns whether a match was found
- */
+ * Return value: whether a match was found.
+ **/
 gboolean
 gtk_source_iter_forward_search (const GtkTextIter   *iter,
 				const gchar         *str,
@@ -580,8 +623,8 @@
 		if (lines_match (&search, (const gchar**)lines,
 				 visible_only, slice, &match, &end))
 		{
-			if (limit == NULL || (limit &&
-					      gtk_text_iter_compare (&end, limit) < 0))
+			if (limit == NULL ||
+			    (limit && gtk_text_iter_compare (&end, limit) <= 0))
 			{
 				retval = TRUE;
 
@@ -601,18 +644,18 @@
 
 /**
  * gtk_source_iter_backward_search:
+ * @iter: a #GtkTextIter where the search begins.
+ * @str: search string.
+ * @flags: bitmask of flags affecting the search.
+ * @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.
  * 
- * @param iter a #GtkTextIter where the search begins
- * @param str search string
- * @param flags bitmask of flags affecting the search
- * @param match_start return location for start of match, or %NULL
- * @param match_end return location for end of match, or %NULL
- * @param limit location of last possible @match_start, or %NULL for start of buffer
- * @return returns whether a match was found
- */
+ * Return value: whether a match was found.
+ **/
 gboolean
 gtk_source_iter_backward_search (const GtkTextIter   *iter,
 				 const gchar         *str,
--- a/src/gtksourceiter.h	Mon Dec 12 08:05:03 2005 +0000
+++ b/src/gtksourceiter.h	Mon Dec 12 08:08:07 2005 +0000
@@ -5,6 +5,11 @@
  *  to list here.  Please refer to the COPYRIGHT file distributed with this
  *  source distribution.
  *
+ *  The following copyright notice applies to this file:
+ *
+ *  Copyright (C) 2000 - 2005 Paolo Maggi 
+ *  Copyright (C) 2002, 2003 Jeroen Zwartepoorte
+ *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU Library General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
@@ -19,6 +24,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
+
 #ifndef _GAIM_GTKSOURCEITER_H_
 #define _GAIM_GTKSOURCEITER_H_
 
@@ -28,9 +34,9 @@
 
 typedef enum
 {
-	GTK_SOURCE_SEARCH_VISIBLE_ONLY,
-	GTK_SOURCE_SEARCH_TEXT_ONLY,
-	GTK_SOURCE_SEARCH_CASE_INSENSITIVE
+	GTK_SOURCE_SEARCH_VISIBLE_ONLY		 = 1 << 0,
+	GTK_SOURCE_SEARCH_TEXT_ONLY		 = 1 << 1,
+	GTK_SOURCE_SEARCH_CASE_INSENSITIVE	 = 1 << 2
 	/* Possible future plans: SEARCH_REGEXP */
 } GtkSourceSearchFlags;