[evolution-patches] second half of the involved e-text patch (in the addressbook this time)



here's the other part of the big e-text utf8 change.  This fixes the
address e-text-model subclass to use utf8 offsets/positions as well.
It too is rather involved, mostly because the original code did a lot of
scanning through the strings.

Chris
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/addressbook/ChangeLog,v
retrieving revision 1.1400
diff -u -r1.1400 ChangeLog
--- ChangeLog	11 May 2003 21:51:42 -0000	1.1400
+++ ChangeLog	11 May 2003 22:25:30 -0000
@@ -1,5 +1,24 @@
 2003-05-11  Chris Toshok  <toshok ximian com>
 
+	* gui/component/select-names/e-select-names-text-model.c
+	(e_select_names_text_model_set_separator): strlen ->
+	g_utf8_strlen.
+	(e_select_names_text_model_insert): same.
+	(e_select_names_text_model_insert_length): big change, make this
+	work with multibyte utf8.
+	(e_select_names_text_model_delete): same.  this could possibly use
+	a tighter loop + a memmove, but this works.
+
+	* gui/component/select-names/e-select-names-model.c
+	(e_select_names_model_get_textification): make sure our truncation
+	to MAX_LENGTH characters uses utf8 characters, not bytes.
+	(e_select_names_model_name_pos): track e-text-model change.
+	pos/length are now in utf8 character terms, so use g_utf8_strlen
+	instead of strlen.
+	(e_select_names_model_text_pos): same.
+
+2003-05-11  Chris Toshok  <toshok ximian com>
+
 	[ fixes bug #42048 ]
 	* gui/widgets/e-addressbook-view.c (e_contact_print_button):
 	button => response.
Index: gui/component/select-names/e-select-names-model.c
===================================================================
RCS file: /cvs/gnome/evolution/addressbook/gui/component/select-names/e-select-names-model.c,v
retrieving revision 1.35
diff -u -r1.35 e-select-names-model.c
--- gui/component/select-names/e-select-names-model.c	23 Mar 2003 09:18:04 -0000	1.35
+++ gui/component/select-names/e-select-names-model.c	11 May 2003 22:25:30 -0000
@@ -219,10 +219,11 @@
 		}
 		
 		text = g_strjoinv (separator, strv);
-		
-		if (strlen(text) > MAX_LENGTH) {
-			text[MAX_LENGTH] = '\0';
-			text = g_realloc (text, MAX_LENGTH + 1);
+
+		if (g_utf8_strlen(text, -1) > MAX_LENGTH) {
+			char *p = g_utf8_offset_to_pointer (text, MAX_LENGTH);
+			*p = '\0';
+			text = g_realloc (text, p - text + 1);
 		}
 		
 		g_free (strv);
@@ -650,7 +651,7 @@
 	while (iter && i <= index) {
 		rp += len + (i > 0 ? seplen : 0);
 		str = e_destination_get_textrep (E_DESTINATION (iter->data), FALSE);
-		len = str ? strlen (str) : 0;
+		len = str ? g_utf8_strlen (str, -1) : 0;
 		++i;
 		iter = g_list_next (iter);
 	}
@@ -680,7 +681,7 @@
 
 	while (iter != NULL) {
 		str = e_destination_get_textrep (E_DESTINATION (iter->data), FALSE);
-		len = str ? strlen (str) : 0;
+		len = str ? g_utf8_strlen (str, -1) : 0;
 
 		if (sp <= pos && pos <= sp + len + adj) {
 			break;
Index: gui/component/select-names/e-select-names-text-model.c
===================================================================
RCS file: /cvs/gnome/evolution/addressbook/gui/component/select-names/e-select-names-text-model.c,v
retrieving revision 1.35
diff -u -r1.35 e-select-names-text-model.c
--- gui/component/select-names/e-select-names-text-model.c	23 Mar 2003 09:18:04 -0000	1.35
+++ gui/component/select-names/e-select-names-text-model.c	11 May 2003 22:25:30 -0000
@@ -297,7 +297,7 @@
 
 	g_free (model->sep);
 	model->sep = g_strdup (sep);
-	model->seplen = strlen (sep);
+	model->seplen = g_utf8_strlen (sep, -1);
 }
 
 static const gchar *
@@ -325,7 +325,7 @@
 static void
 e_select_names_text_model_insert (ETextModel *model, gint position, const gchar *text)
 {
-	e_select_names_text_model_insert_length (model, position, text, strlen (text));
+	e_select_names_text_model_insert_length (model, position, text, g_utf8_strlen (text, -1));
 }
 
 static void
@@ -333,8 +333,7 @@
 {
 	ESelectNamesTextModel *text_model = E_SELECT_NAMES_TEXT_MODEL (model);
 	ESelectNamesModel *source = text_model->source;
-
-	gint i;
+	const char *t;
 
 	if (out) {
 		gchar *tmp = g_strndup (text, length);
@@ -342,7 +341,7 @@
 		g_free (tmp);
 	}
 
-	pos = CLAMP (pos, 0, strlen (e_select_names_model_get_textification (source, text_model->sep)));
+	pos = CLAMP (pos, 0, g_utf8_strlen (e_select_names_model_get_textification (source, text_model->sep), -1));
 
 	/* We want to control all cursor motions ourselves, rather than taking hints
 	   from the ESelectNamesModel. */
@@ -350,40 +349,49 @@
 
 	/* We handle this one character at a time. */
 
-	for (i = 0; i < length && text[i]; ++i) {
+	for (t = text; length >= 0; t = g_utf8_next_char (t), length--) {
 		gint index, start_pos, text_len;
 		gboolean inside_quote = FALSE;
+		gunichar ut = g_utf8_get_char (t);
+
+		if (ut == 0)
+			break;
 
 		text_model->last_magic_comma_pos = -1;
 
 		if (out) 
-			fprintf (out, "processing [%c]\n", text[i]);
+			fprintf (out, "processing [%d]\n", ut);
 
 		e_select_names_model_text_pos (source, text_model->seplen, pos, &index, &start_pos, &text_len);
 
 		if (out) 
 			fprintf (out, "index=%d start_pos=%d text_len=%d\n", index, start_pos, text_len);
 
-		if (text[i] == *text_model->sep && index >= 0) { /* Is this a quoted or an unquoted separator we are dealing with? */
+		/* Is this a quoted or an unquoted separator we are dealing with? */
+		if (ut == g_utf8_get_char(text_model->sep) && index >= 0) {
 			const EDestination *dest = e_select_names_model_get_destination (source, index);
 			if (dest) {
 				const gchar *str = e_destination_get_textrep (dest, FALSE);
-				gint j;
+				int j;
+				const char *jp;
+
 				if (out)
 					fprintf (out, "str=%s pos=%d\n", str, pos);
-				for (j=0; j<pos-start_pos && str[j]; ++j)
-					if (str[j] == '"') {
+
+				for (jp = str, j = 0; j<pos-start_pos && *jp; jp = g_utf8_next_char (jp), ++j) {
+					if (*jp == '"') {
 						inside_quote = !inside_quote;
 						if (out)
 							fprintf (out, "flip to %d at %d\n", start_pos+j, inside_quote);
 					}
+				}
 			}
 			if (out)
 				fprintf (out, inside_quote ? "inside quote\n" : "not inside quote\n");
 		}
 
 
-		if (text[i] == *text_model->sep && !inside_quote) {
+		if (ut == g_utf8_get_char (text_model->sep) && !inside_quote) {
 
 			/* This is the case of hitting , first thing in an empty entry */
 			if (index == -1) {
@@ -449,9 +457,9 @@
 			EReposInsertShift repos;
 			gint offset = MAX (pos - start_pos, 0);
 			const gchar *str;
-			gchar *new_str = NULL;
+			GString *new_str = g_string_new (NULL);
 			gint this_length = 1;
-			gboolean whitespace = isspace ((gint) text[i]);
+			gboolean whitespace = g_unichar_isspace (ut);
 
 			str = index >= 0 ? e_select_names_model_get_string (source, index) : NULL;
 			if (str && *str) {
@@ -462,27 +470,34 @@
 					} else {
 						/* Adjust for our "magic white space" */
 						/* FIXME: This code does the wrong thing if seplen > 2 */
-						new_str = g_strdup_printf("%c%s%s", text[i], pos < start_pos ? " " : "", str);
+						g_string_append_unichar (new_str, ut);
+						g_string_append (new_str, pos < start_pos ? " " : "");
+						g_string_append (new_str, str);
 						if (pos < start_pos)
 							++this_length;
 					}
 				} else {
-					new_str = g_strdup_printf ("%.*s%c%s", offset, str, text[i], str + offset);
+					const char *u;
+					int n;
+					for (u = str, n = 0; n < offset; u = g_utf8_next_char (u), n++) 
+						g_string_append_unichar (new_str, g_utf8_get_char (u));
+					g_string_append_unichar (new_str, ut);
+					g_string_append (new_str, u);
 				}
 			} else {
 				if (whitespace) {
 					/* swallow leading whitespace */
 					this_length = 0;
 				} else {
-					new_str = g_strdup_printf ("%c", text[i]);
+					g_string_append_unichar (new_str, ut);
 				}
 			}
 
-			if (new_str) {
+			if (new_str->len) {
 
 				EDestination *dest;
 				dest = index >= 0 ? e_destination_copy (e_select_names_model_get_destination (source, index)) : e_destination_new ();
-				e_destination_set_raw (dest, new_str);
+				e_destination_set_raw (dest, new_str->str);
 				e_select_names_model_replace (source, index, dest);
 				
 				/* e_select_names_model_replace (source, index, dest); */
@@ -495,9 +510,8 @@
 
 					pos += this_length;
 				}
-
-				g_free (new_str);
 			}
+			g_string_free (new_str, TRUE);
 		}
 	}
 
@@ -666,12 +680,41 @@
 		offset = pos - start_pos;
 		
 		str = e_select_names_model_get_string (source, index);
-		new_str = str ? g_strdup_printf ("%.*s%s", offset, str, str + offset + length) : NULL;
-		
-		if (new_str) {
+
+		if (str) {
+			const char *p;
+			char *np;
+			int i;
 			EReposDeleteShift repos;
 			EDestination *dest;
 
+			new_str = g_new0 (char, strlen (str) * 6 + 1); /* worse case it can't be any longer than this */
+
+			/* copy the region before the deletion */
+			for (p = str, i = 0, np = new_str; i < offset; i++) {
+				gunichar ch;
+
+				ch = g_utf8_get_char (p);
+				g_unichar_to_utf8 (ch, np);
+
+				np = g_utf8_next_char (np);
+				p = g_utf8_next_char (p);
+			}
+
+			/* skip the deleted segment */
+			for (i = 0; i < length; i++)
+				p = g_utf8_next_char (p);
+
+			/* copy the region after the deletion */
+			for (; *p; p = g_utf8_next_char (p)) {
+				gunichar ch;
+
+				ch = g_utf8_get_char (p);
+				g_unichar_to_utf8 (ch, np);
+
+				np = g_utf8_next_char (np);
+			}
+
 			dest = index >= 0 ? e_destination_copy (e_select_names_model_get_destination (source, index)) : e_destination_new ();
 			e_destination_set_raw (dest, new_str);
 			e_select_names_model_replace (source, index, dest);
@@ -768,7 +811,7 @@
 	
 	if (text_model->text == NULL)
 		text_model->text = e_select_names_model_get_textification (source, text_model->sep);
-	return text_model->text + pos;
+	return g_utf8_offset_to_pointer (text_model->text, pos);
 }
 
 static void


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