changeset 14311:fda9dc44807d

[gaim-migrate @ 17001] Wide-characters should no longer eat characters at the end of the line in textview. committer: Tailor Script <tailor@pidgin.im>
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Wed, 23 Aug 2006 13:46:51 +0000
parents a766441af5ea
children ef05f400817f
files console/libgnt/gntentry.c console/libgnt/gnttextview.c console/libgnt/gntutils.c console/libgnt/gntutils.h
diffstat 4 files changed, 79 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/console/libgnt/gntentry.c	Wed Aug 23 12:29:08 2006 +0000
+++ b/console/libgnt/gntentry.c	Wed Aug 23 13:46:51 2006 +0000
@@ -1,11 +1,10 @@
 #include <ctype.h>
-#include <stdlib.h>
 #include <string.h>
-#include <wchar.h>
 
 #include "gntbox.h"
 #include "gntentry.h"
 #include "gnttree.h"
+#include "gntutils.h"
 
 enum
 {
@@ -15,25 +14,6 @@
 static GntWidgetClass *parent_class = NULL;
 static guint signals[SIGS] = { 0 };
 
-static int
-get_onscreen_width(const char *start, const char *end)
-{
-	wchar_t wch;
-	int size;
-	int width = 0;
-
-	while (start < end) {
-		if ((size = mbtowc(&wch, start, end - start)) > 0) {
-			start += size;
-			width += wcwidth(wch);
-		} else {
-			++width;
-			++start;
-		}
-	}
-	return width;
-}
-
 static void
 destroy_suggest(GntEntry *entry)
 {
@@ -72,7 +52,7 @@
 		char *s = get_beginning_of_word(entry);
 		suggest = g_strndup(s, entry->cursor - s);
 		if (entry->scroll < s)
-			offset = get_onscreen_width(entry->scroll, s);
+			offset = gnt_util_onscreen_width(entry->scroll, s);
 	}
 	else
 		suggest = g_strdup(entry->start);
@@ -141,12 +121,12 @@
 	else
 		mvwprintw(widget->window, 0, 0, "%s", entry->scroll);
 
-	stop = get_onscreen_width(entry->scroll, entry->end);
+	stop = gnt_util_onscreen_width(entry->scroll, entry->end);
 	if (stop < widget->priv.width)
 		whline(widget->window, ENTRY_CHAR, widget->priv.width - stop);
 
 	if (focus)
-		mvwchgat(widget->window, 0, get_onscreen_width(entry->scroll, entry->cursor),
+		mvwchgat(widget->window, 0, gnt_util_onscreen_width(entry->scroll, entry->cursor),
 				1, A_REVERSE, COLOR_PAIR(GNT_COLOR_TEXT_NORMAL), NULL);
 
 	DEBUG;
@@ -194,7 +174,7 @@
 	if (entry->cursor >= entry->end)
 		return;
 	entry->cursor = g_utf8_find_next_char(entry->cursor, NULL);
-	while (get_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width)
+	while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width)
 		entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
 	entry_redraw(GNT_WIDGET(entry));
 }
@@ -249,7 +229,7 @@
 {
 	entry->cursor = entry->end;
 	/* This should be better than this */
-	while (get_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width)
+	while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width)
 		entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
 	entry_redraw(GNT_WIDGET(entry));
 }
@@ -410,7 +390,7 @@
 					str++;
 				}
 
-				while (get_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width)
+				while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width)
 					entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
 
 				if (entry->ddown)
--- a/console/libgnt/gnttextview.c	Wed Aug 23 12:29:08 2006 +0000
+++ b/console/libgnt/gnttextview.c	Wed Aug 23 13:46:51 2006 +0000
@@ -1,4 +1,5 @@
 #include "gnttextview.h"
+#include "gntutils.h"
 
 enum
 {
@@ -14,7 +15,7 @@
 typedef struct
 {
 	GList *segments;         /* A list of GntTextSegments */
-	int length;              /* The current length of the line so far */
+	int length;              /* The current length of the line so far (ie. onscreen width) */
 } GntTextLine;
 
 static GntWidgetClass *parent_class = NULL;
@@ -236,18 +237,23 @@
 
 		while (iter && *iter)
 		{
-			GntTextSegment *seg = g_new0(GntTextSegment, 1);
-			int len = g_utf8_offset_to_pointer(iter, widget->priv.width - line->length - 1) - iter;
-			seg->flags = fl;
-			seg->text = g_new0(char, len + 1);
-			g_utf8_strncpy(seg->text, iter, widget->priv.width - line->length - 1);
-			line->segments = g_list_append(line->segments, seg);
+			int len;
 
-			prev = g_utf8_strlen(seg->text, -1);
-			line->length += prev;
-			iter = g_utf8_offset_to_pointer(iter, prev);
-			if (line->length >= widget->priv.width - 1 && *iter)
-			{
+			len = gnt_util_onscreen_width_to_pointer(iter, widget->priv.width - line->length - 1, &prev) - iter;
+			if (len) {
+				GntTextSegment *seg = g_new0(GntTextSegment, 1);
+				seg->flags = fl;
+				seg->text = g_new0(char, len + 1);
+				g_utf8_strncpy(seg->text, iter, g_utf8_pointer_to_offset(iter, iter + len));
+				line->segments = g_list_append(line->segments, seg);
+
+				line->length += prev;
+				iter += len;
+				if (line->length >= widget->priv.width - 1 && *iter) {
+					line = g_new0(GntTextLine, 1);
+					view->list = g_list_prepend(g_list_first(view->list), line);
+				}
+			} else {
 				line = g_new0(GntTextLine, 1);
 				view->list = g_list_prepend(g_list_first(view->list), line);
 			}
--- a/console/libgnt/gntutils.c	Wed Aug 23 12:29:08 2006 +0000
+++ b/console/libgnt/gntutils.c	Wed Aug 23 13:46:51 2006 +0000
@@ -1,5 +1,9 @@
 #include "gntutils.h"
 
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
 void gnt_util_get_text_bound(const char *text, int *width, int *height)
 {
 	const char *s = text, *last;
@@ -34,3 +38,49 @@
 		*width = max + (count > 1);
 }
 
+int gnt_util_onscreen_width(const char *start, const char *end)
+{
+	wchar_t wch;
+	int size;
+	int width = 0;
+
+	while (start < end) {
+		if ((size = mbtowc(&wch, start, end - start)) > 0) {
+			start += size;
+			width += wcwidth(wch);
+		} else {
+			++width;
+			++start;
+		}
+	}
+	return width;
+}
+
+char *gnt_util_onscreen_width_to_pointer(const char *string, int len, int *w)
+{
+	wchar_t wch;
+	int size;
+	int width = 0;
+	char *str = (char*)string;
+	int slen = strlen(string);  /* Yeah, no. of bytes */
+
+	while (width < len && *str) {
+		if ((size = mbtowc(&wch, str, slen)) > 0) {
+			if (width + wcwidth(wch) > len)
+				break;
+			str += size;
+			width += wcwidth(wch);
+			slen -= size;
+		} else {
+			++str;
+			++width;
+			--slen;
+		}
+	}
+
+	if (w)
+		*w = width;
+
+	return str;
+}
+
--- a/console/libgnt/gntutils.h	Wed Aug 23 12:29:08 2006 +0000
+++ b/console/libgnt/gntutils.h	Wed Aug 23 13:46:51 2006 +0000
@@ -4,3 +4,7 @@
 #include "gntwidget.h"
 
 void gnt_util_get_text_bound(const char *text, int *width, int *height);
+
+int gnt_util_onscreen_width(const char *start, const char *end);
+
+char *gnt_util_onscreen_width_to_pointer(const char *str, int len, int *w);