diff console/libgnt/gnttextview.c @ 13896:a621329e8c85

[gaim-migrate @ 16381] Changes in GntTextView. Things go somewhat 'smooth' when run inside valgrind. Otherwise, it's kind of flaky. I don't mind a single bit if someone gave me a hint :) committer: Tailor Script <tailor@pidgin.im>
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Sat, 01 Jul 2006 00:56:05 +0000
parents 9d66969a2e32
children 9309d27d780c
line wrap: on
line diff
--- a/console/libgnt/gnttextview.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gnttextview.c	Sat Jul 01 00:56:05 2006 +0000
@@ -5,6 +5,18 @@
 	SIGS = 1,
 };
 
+typedef struct
+{
+	GntTextViewFlags flags;
+	char *text;
+} GntTextSegment;
+
+typedef struct
+{
+	GList *segments;         /* A list of GntTextSegments */
+	int length;              /* The current length of the line so far */
+} GntTextLine;
+
 static GntWidgetClass *parent_class = NULL;
 static guint signals[SIGS] = { 0 };
 
@@ -12,9 +24,27 @@
 gnt_text_view_draw(GntWidget *widget)
 {
 	GntTextView *view = GNT_TEXT_VIEW(widget);
+	int i = 0;
+	GList *lines;
 
-	copywin(view->scroll, widget->window, view->pos, 0, 0, 0,
-					widget->priv.height - 1, widget->priv.width - 1, FALSE);
+	werase(widget->window);
+
+	for (i = 0, lines = view->list; i < widget->priv.height && lines; i++, lines = lines->next)
+	{
+		GList *iter;
+		GntTextLine *line = lines->data;
+
+		wmove(widget->window, widget->priv.height - 1 - i, 0);
+
+		for (iter = line->segments; iter; iter = iter->next)
+		{
+			GntTextSegment *seg = iter->data;
+			wattrset(widget->window, seg->flags);
+			wprintw(widget->window, "%s", seg->text);
+			if (!iter->next)
+				whline(widget->window, ' ' | seg->flags, widget->priv.width - line->length - 1);
+		}
+	}
 	
 	DEBUG;
 }
@@ -43,8 +73,28 @@
 }
 
 static void
+free_text_segment(gpointer data, gpointer null)
+{
+	GntTextSegment *seg = data;
+	g_free(seg->text);
+	g_free(seg);
+}
+
+static void
+free_text_line(gpointer data, gpointer null)
+{
+	GntTextLine *line = data;
+	g_list_foreach(line->segments, free_text_segment, NULL);
+	g_list_free(line->segments);
+	g_free(line);
+}
+
+static void
 gnt_text_view_destroy(GntWidget *widget)
 {
+	GntTextView *view = GNT_TEXT_VIEW(widget);
+	g_list_foreach(view->list, free_text_line, NULL);
+	g_list_free(view->list);
 }
 
 static void
@@ -100,14 +150,12 @@
 {
 	GntWidget *widget = g_object_new(GNT_TYPE_TEXTVIEW, NULL);
 	GntTextView *view = GNT_TEXT_VIEW(widget);
+	GntTextLine *line = g_new0(GntTextLine, 1);
 
-	view->scroll = newwin(255, widget->priv.width, widget->priv.y, widget->priv.x);
-	scrollok(view->scroll, TRUE);
-	wsetscrreg(view->scroll, 0, 254);
-	wbkgd(view->scroll, COLOR_PAIR(GNT_COLOR_NORMAL));
-	werase(view->scroll);
 	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
 
+	view->list = g_list_append(view->list, line);
+
 	return widget;
 }
 
@@ -117,6 +165,7 @@
 	int fl = 0;
 	char **split;
 	int i;
+	GList *list = view->list;
 
 	if (text == NULL || *text == '\0')
 		return;
@@ -128,48 +177,80 @@
 	if (flags & GNT_TEXT_FLAG_BLINK)
 		fl |= A_BLINK;
 
-	wattrset(view->scroll, fl | COLOR_PAIR(GNT_COLOR_NORMAL));
+	if (flags & GNT_TEXT_FLAG_DIM)
+		fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_DISABLED));
+	else if (flags & GNT_TEXT_FLAG_HIGHLIGHT)
+		fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_HIGHLIGHT));
+	else
+		fl |= COLOR_PAIR(GNT_COLOR_NORMAL);
+
+	view->list = g_list_first(view->list);
 
 	split = g_strsplit(text, "\n", 0);
-	for (i = 0; split[i + 1]; i++)
+	for (i = 0; split[i]; i++)
 	{
-		/* XXX: Do something if the strlen of split[i] is big
-		 * enough to cause the text to wrap. */
-		wprintw(view->scroll, "%s\n", split[i]);
-		view->lines++;
+		GntTextLine *line = view->list->data;
+		int len = g_utf8_strlen(split[i], -1);
+		char *iter = split[i];
+		int prev = 0;
+
+		while (iter && *iter)
+		{
+			GntTextSegment *seg = g_new0(GntTextSegment, 1);
+			seg->flags = fl;
+			seg->text = g_new0(char, len);		/* XXX: MUST be improved */
+			g_utf8_strncpy(seg->text, iter, widget->priv.width - line->length - 1);
+			line->segments = g_list_append(line->segments, seg);
+
+			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)
+			{
+				line = g_new0(GntTextLine, 1);
+				view->list = g_list_prepend(g_list_first(view->list), line);
+			}
+			/*len -= prev;*/
+		}
 	}
-	wprintw(view->scroll, "%s", split[i]);
+
 	g_strfreev(split);
+	view->list = list;
 
 	gnt_widget_draw(widget);
 }
 
 void gnt_text_view_scroll(GntTextView *view, int scroll)
 {
-	GntWidget *widget = GNT_WIDGET(view);
-	int height;
-
 	if (scroll == 0)
 	{
-		view->pos = view->lines - widget->priv.height + 1;
+		view->list = g_list_first(view->list);
 	}
-	else
+	else if (scroll > 0)
 	{
-		view->pos += scroll;
+		GList *list = g_list_nth_prev(view->list, scroll);
+		if (list == NULL)
+			list = g_list_first(view->list);
+		view->list = list;
 	}
-
-	if (view->pos + (height = widget->priv.height) > view->lines)
-		view->pos = view->lines - height + 1;
-
-	if (view->pos < 0)
-		view->pos = 0;
-
+	else if (scroll < 0)
+	{
+		GList *list = g_list_nth(view->list, -scroll);
+		if (list == NULL)
+			list = g_list_last(view->list);
+		view->list = list;
+	}
+		
 	gnt_widget_draw(GNT_WIDGET(view));
 }
 
 void gnt_text_view_next_line(GntTextView *view)
 {
-	wclrtoeol(view->scroll);
-	gnt_text_view_append_text_with_flags(view, "\n", 0);
+	GntTextLine *line = g_new0(GntTextLine, 1);
+	GList *list = view->list;
+	
+	view->list = g_list_prepend(g_list_first(view->list), line);
+	view->list = list;
+	gnt_widget_draw(GNT_WIDGET(view));
 }