changeset 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 8f910263b4bb
children eaaf73de9188
files console/gntblist.c console/gntconv.c console/gntgaim.c console/libgnt/gnt.h console/libgnt/gntbox.c console/libgnt/gntbox.h console/libgnt/gntcolors.c console/libgnt/gntcolors.h console/libgnt/gntentry.c console/libgnt/gntkeys.h console/libgnt/gntmain.c console/libgnt/gnttextview.c console/libgnt/gnttextview.h console/libgnt/gnttree.c console/libgnt/gntwidget.c console/libgnt/test/multiwin.c console/libgnt/test/tv.c
diffstat 17 files changed, 368 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/console/gntblist.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/gntblist.c	Sat Jul 01 00:56:05 2006 +0000
@@ -6,6 +6,7 @@
 
 #include "gntgaim.h"
 #include "gntbox.h"
+#include "gntlabel.h"
 #include "gnttree.h"
 
 #include "gntblist.h"
@@ -238,12 +239,27 @@
 static void
 selection_activate(GntWidget *widget, GGBlist *ggblist)
 {
-	gnt_widget_set_focus(widget, FALSE);
+	GntTree *tree = GNT_TREE(ggblist->tree);
+	GaimBlistNode *node = gnt_tree_get_selection_data(tree);
+
+	if (GAIM_BLIST_NODE_IS_BUDDY(node))
+	{
+		GaimBuddy *buddy = (GaimBuddy *)node;
+		gaim_conversation_new(GAIM_CONV_TYPE_IM,
+				gaim_buddy_get_account(buddy),
+				gaim_buddy_get_name(buddy));
+	}
+	else if (GAIM_BLIST_NODE_IS_CHAT(node))
+	{
+		GaimChat *chat = (GaimChat*)node;
+		serv_join_chat(chat->account->gc, chat->components);
+	}
 }
 
 static void
 draw_tooltip(GGBlist *ggblist)
 {
+	return;
 	GaimBlistNode *node;
 	int x, y, top, width;
 	GString *str;
@@ -251,12 +267,15 @@
 	GaimPluginProtocolInfo *prpl_info;
 	GaimAccount *account;
 	GntTree *tree;
-	GntWidget *widget, *box, *label;
+	GntWidget *widget, *box;
 	char *title = NULL;
 
 	widget = ggblist->tree;
 	tree = GNT_TREE(widget);
 
+	if (!gnt_widget_has_focus(ggblist->tree))
+		return;
+
 	if (ggblist->tooltip)
 	{
 		/* XXX: Once we can properly redraw on expose events, this can be removed at the end
@@ -332,7 +351,7 @@
 	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW);
 	gnt_box_set_title(GNT_BOX(box), title);
 
-	gnt_box_add_widget(GNT_BOX(box), GNT_WIDGET(gnt_label_new(str->str)));
+	gnt_box_add_widget(GNT_BOX(box), gnt_label_new(str->str));
 
 	gnt_widget_set_position(box, x, y);
 	gnt_widget_draw(box);
@@ -365,24 +384,6 @@
 			return TRUE;
 		}
 	}
-	else if (text[0] == '\r' && text[1] == '\0')
-	{
-		GntTree *tree = GNT_TREE(ggblist->tree);
-		GaimBlistNode *node = gnt_tree_get_selection_data(tree);
-
-		if (GAIM_BLIST_NODE_IS_BUDDY(node))
-		{
-			GaimBuddy *buddy = (GaimBuddy *)node;
-			gaim_conversation_new(GAIM_CONV_TYPE_IM,
-					gaim_buddy_get_account(buddy),
-					gaim_buddy_get_name(buddy));
-		}
-		else if (GAIM_BLIST_NODE_IS_CHAT(node))
-		{
-			GaimChat *chat = (GaimChat*)node;
-			serv_join_chat(chat->account->gc, chat->components);
-		}
-	}
 
 	return FALSE;
 }
--- a/console/gntconv.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/gntconv.c	Sat Jul 01 00:56:05 2006 +0000
@@ -1,3 +1,4 @@
+#include <string.h>
 #include <util.h>
 
 #include "gntgaim.h"
@@ -59,6 +60,20 @@
 		gnt_entry_clear(GNT_ENTRY(ggconv->entry));
 		return TRUE;
 	}
+	else if (key[0] == 27)
+	{
+		if (strcmp(key+1, GNT_KEY_DOWN) == 0)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 1);
+		else if (strcmp(key+1, GNT_KEY_UP) == 0)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), -1);
+		else if (strcmp(key+1, GNT_KEY_PGDOWN) == 0)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), ggconv->tv->priv.height - 2);
+		else if (strcmp(key+1, GNT_KEY_PGUP) == 0)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), -(ggconv->tv->priv.height - 2));
+		else
+			return FALSE;
+		return TRUE;
+	}
 
 	return FALSE;
 }
@@ -90,7 +105,7 @@
 	ggc->window = gnt_box_new(FALSE, TRUE);
 	gnt_box_set_title(GNT_BOX(ggc->window), title);
 	gnt_box_set_toplevel(GNT_BOX(ggc->window), TRUE);
-	gnt_widget_set_name(ggc->window, "conversation-window");
+	gnt_widget_set_name(ggc->window, title);
 
 	ggc->tv = gnt_text_view_new();
 	gnt_box_add_widget(GNT_BOX(ggc->window), ggc->tv);
@@ -180,6 +195,7 @@
 {
 	GGConv *ggconv = g_hash_table_lookup(ggconvs, conv);
 	char *strip;
+	GntTextViewFlags fl = 0;
 
 	g_return_if_fail(ggconv != NULL);
 
@@ -199,8 +215,14 @@
 				name, GNT_TEXT_FLAG_BOLD);
 		g_free(name);
 	}
+	else
+		fl = GNT_TEXT_FLAG_DIM;
+
+	if (flags & GAIM_MESSAGE_ERROR)
+		fl |= GNT_TEXT_FLAG_BOLD;
+
 	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
-			strip, 0);
+			strip, fl);
 	gnt_text_view_next_line(GNT_TEXT_VIEW(ggconv->tv));
 	gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 0);
 
--- a/console/gntgaim.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/gntgaim.c	Sat Jul 01 00:56:05 2006 +0000
@@ -16,6 +16,7 @@
 #include "whiteboard.h"
 
 #include "gntgaim.h"
+#include "gntui.h"
 
 /* Anything IO-related is directly copied from gtkgaim's source tree */
 
--- a/console/libgnt/gnt.h	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gnt.h	Sat Jul 01 00:56:05 2006 +0000
@@ -14,3 +14,5 @@
 void gnt_screen_update(GntWidget *widget);
 
 void gnt_screen_take_focus(GntWidget *widget);
+
+gboolean gnt_widget_has_focus(GntWidget *widget);
--- a/console/libgnt/gntbox.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gntbox.c	Sat Jul 01 00:56:05 2006 +0000
@@ -10,6 +10,8 @@
 static GntWidgetClass *parent_class = NULL;
 static guint signals[SIGS] = { 0 };
 
+static GntWidget * find_focusable_widget(GntBox *box);
+
 static void
 gnt_box_draw(GntWidget *widget)
 {
@@ -34,7 +36,11 @@
 			/* XXX: Position of the title might be configurable */
 			pos = (widget->priv.width - pos) / 2;
 		}
-		wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE));
+
+		if (gnt_widget_has_focus(widget))
+			wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE));
+		else
+			wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE_D));
 		mvwprintw(widget->window, 0, pos, title);
 		g_free(title);
 	}
@@ -139,23 +145,88 @@
 gnt_box_map(GntWidget *widget)
 {
 	if (widget->priv.width == 0 || widget->priv.height == 0)
+	{
 		gnt_widget_size_request(widget);
+		find_focusable_widget(GNT_BOX(widget));
+	}
 	DEBUG;
 }
 
+static GntWidget *
+find_next_focus(GntBox *box)
+{
+	GntWidget *w = box->active;
+	GList *iter;
+
+	while (w && !(iter = g_list_find(box->list, w)))
+		w = w->parent;
+
+	if (!w)
+		box->active = NULL;
+	else if (iter)
+	{
+		GntWidget *next = NULL;
+		
+		do
+		{
+			next = find_next_focus(iter->data);
+			box->active = next;
+			iter = iter->next;
+		} while (!next && iter);
+	}
+
+	if (box->active == NULL && GNT_WIDGET(box)->parent == NULL)
+	{
+		box->active = find_focusable_widget(box);
+	}
+	
+	if (box->active)
+		GNT_WIDGET_SET_FLAGS(box->active, GNT_WIDGET_HAS_FOCUS);
+
+	return box->active;
+}
+
 /* Ensures that the current widget can take focus */
-static void
-ensure_active(GntBox *box)
+static GntWidget *
+find_focusable_widget(GntBox *box)
 {
 	int investigated = 0;
 	int total;
+	GntWidget *w = NULL;
+	GList *iter;
 
-	if (box->active == NULL)
-		box->active = box->list;
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		w = iter->data;
+		if (GNT_IS_BOX(w))
+		{
+			w = find_focusable_widget(GNT_BOX(w));
+			if (w)
+				break;
+		}
+		else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_CAN_TAKE_FOCUS))
+			break;
+	}
+
+	if (iter)
+		box->active = w;
+	else
+		box->active = NULL;
+
+	if (box->active)
+		GNT_WIDGET_SET_FLAGS(box->active, GNT_WIDGET_HAS_FOCUS);
+
+	return box->active;
+
+#if 0
+	if (box->active == NULL && box->list)
+		box->active = box->list->data;
+	else
+		w = box->active;
 
 	total = g_list_length(box->list);
 
-	while (box->active && !GNT_WIDGET_IS_FLAG_SET(box->active->data, GNT_WIDGET_CAN_TAKE_FOCUS))
+	while (box->active && !GNT_WIDGET_IS_FLAG_SET(box->active, GNT_WIDGET_CAN_TAKE_FOCUS))
 	{
 		box->active = box->active->next;
 		investigated++;
@@ -171,6 +242,12 @@
 			investigated++;
 		}
 	}
+
+	if (box->active)
+		gnt_widget_set_focus(box->active->data, TRUE);
+	if (w && w != box->active->data)
+		gnt_widget_set_focus(w, FALSE);
+#endif
 }
 
 static gboolean
@@ -178,15 +255,15 @@
 {
 	GntBox *box = GNT_BOX(widget);
 
-	ensure_active(box);
-	if (box->active == NULL)
+	if (box->active == NULL && !find_focusable_widget(box))
 		return FALSE;
 
-	if (gnt_widget_key_pressed(box->active->data, text))
+	if (gnt_widget_key_pressed(box->active, text))
 		return TRUE;
 	
 	if (text[0] == 27)
 	{
+#if 0
 		GList *now = NULL;
 		if (strcmp(text+1, GNT_KEY_LEFT) == 0)
 		{
@@ -209,6 +286,7 @@
 
 			return TRUE;
 		}
+#endif
 	}
 
 	return FALSE;
@@ -237,8 +315,9 @@
 	return NULL;
 }
 
+#if 0
 static void
-gnt_box_lost_focus(GntWidget *widget)
+gnt_box_set_focus(GntWidget *widget, gboolean set)
 {
 	GntWidget *p = widget;
 
@@ -247,10 +326,32 @@
 
 	p = find_focused_widget(GNT_BOX(p));
 	if (p)
-		gnt_widget_set_focus(p, FALSE);
+		gnt_widget_set_focus(p, set);
+	gnt_widget_draw(widget);
+}
+
+static void
+gnt_box_lost_focus(GntWidget *widget)
+{
+	gnt_box_set_focus(widget, FALSE);
 }
 
 static void
+gnt_box_gained_focus(GntWidget *widget)
+{
+	GntWidget *p;
+
+	while (widget->parent)
+		widget = widget->parent;
+	
+	p = find_focused_widget(GNT_BOX(widget));
+	GNT_BOX(widget)->active = g_list_find(GNT_BOX(widget)->list, p);
+	if (p)
+		gnt_widget_draw(p);
+}
+#endif
+
+static void
 gnt_box_destroy(GntWidget *w)
 {
 	GntBox *box = GNT_BOX(w);
@@ -286,7 +387,11 @@
 	parent_class->size_request = gnt_box_size_request;
 	parent_class->set_position = gnt_box_set_position;
 	parent_class->key_pressed = gnt_box_key_pressed;
+#if 0
+	/* We are going to need this when there are multiple focusble widgets in a box */
 	parent_class->lost_focus = gnt_box_lost_focus;
+	parent_class->gained_focus = gnt_box_gained_focus;
+#endif
 
 	DEBUG;
 }
--- a/console/libgnt/gntbox.h	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gntbox.h	Sat Jul 01 00:56:05 2006 +0000
@@ -22,7 +22,7 @@
 	gboolean homogeneous;
 	GList *list;		/* List of widgets */
 
-	GList *active;
+	GntWidget *active;
 	int pad;			/* Number of spaces to use between widgets */
 
 	char *title;
--- a/console/libgnt/gntcolors.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gntcolors.c	Sat Jul 01 00:56:05 2006 +0000
@@ -11,16 +11,18 @@
 		init_color(GNT_COLOR_GREEN, 0, 1000, 0);
 		init_color(GNT_COLOR_BLUE, 0, 0, 1000);
 		init_color(GNT_COLOR_WHITE, 1000, 1000, 1000);
-		init_color(GNT_COLOR_GRAY, 799, 799, 799);
+		init_color(GNT_COLOR_GRAY, 699, 699, 699);
 		init_color(GNT_COLOR_DARK_GRAY, 256, 256, 256);
 
 		/* Now some init_pair()s */
 		init_pair(GNT_COLOR_NORMAL, GNT_COLOR_BLACK, GNT_COLOR_WHITE);
-		init_pair(GNT_COLOR_HIGHLIGHT, GNT_COLOR_BLUE, GNT_COLOR_GRAY);
+		init_pair(GNT_COLOR_HIGHLIGHT, GNT_COLOR_WHITE, GNT_COLOR_BLUE);
 		init_pair(GNT_COLOR_SHADOW, GNT_COLOR_BLACK, GNT_COLOR_DARK_GRAY);
 		init_pair(GNT_COLOR_TITLE, GNT_COLOR_WHITE, GNT_COLOR_DARK_GRAY);
-		init_pair(GNT_COLOR_TEXT_NORMAL, GNT_COLOR_BLACK, GNT_COLOR_GRAY);
+		init_pair(GNT_COLOR_TITLE_D, GNT_COLOR_BLACK, GNT_COLOR_GRAY);
+		init_pair(GNT_COLOR_TEXT_NORMAL, GNT_COLOR_WHITE, GNT_COLOR_BLUE);
 		init_pair(GNT_COLOR_HIGHLIGHT_D, GNT_COLOR_BLACK, GNT_COLOR_GRAY);
+		init_pair(GNT_COLOR_DISABLED, GNT_COLOR_GRAY, GNT_COLOR_WHITE);
 	}
 	else
 	{
@@ -30,6 +32,7 @@
 		init_pair(GNT_COLOR_TITLE, COLOR_WHITE, COLOR_BLACK);
 		init_pair(GNT_COLOR_TEXT_NORMAL, COLOR_BLACK, COLOR_WHITE);
 		init_pair(GNT_COLOR_HIGHLIGHT_D, COLOR_CYAN, COLOR_BLACK);
+		init_pair(GNT_COLOR_DISABLED, COLOR_YELLOW, COLOR_WHITE);
 	}
 }
 
--- a/console/libgnt/gntcolors.h	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gntcolors.h	Sat Jul 01 00:56:05 2006 +0000
@@ -13,6 +13,7 @@
 	GNT_COLOR_MNEMONIC_D,
 	GNT_COLOR_SHADOW,
 	GNT_COLOR_TITLE,
+	GNT_COLOR_TITLE_D,
 	GNT_COLORS
 } GntColorType;
 
--- a/console/libgnt/gntentry.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gntentry.c	Sat Jul 01 00:56:05 2006 +0000
@@ -17,7 +17,10 @@
 	GntEntry *entry = GNT_ENTRY(widget);
 	int stop;
 
-	wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TEXT_NORMAL));
+	if (gnt_widget_has_focus(widget))
+		wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TEXT_NORMAL));
+	else
+		wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
 	mvwprintw(widget->window, 0, 0, entry->scroll);
 
 	stop = entry->end - entry->scroll;
--- a/console/libgnt/gntkeys.h	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gntkeys.h	Sat Jul 01 00:56:05 2006 +0000
@@ -9,6 +9,9 @@
 #define GNT_KEY_UP     "[A"
 #define GNT_KEY_DOWN   "[B"
 
+#define GNT_KEY_PGUP   "[5~"
+#define GNT_KEY_PGDOWN "[6~"
+
 #define GNT_KEY_ENTER  "\r"
 
 #define GNT_KEY_BACKSPACE "\177"
--- a/console/libgnt/gntmain.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gntmain.c	Sat Jul 01 00:56:05 2006 +0000
@@ -13,20 +13,57 @@
 static int max_x;
 static int max_y;
 
+typedef struct
+{
+	GntWidget *me;
+	GList *below;		/* List of widgets below me */
+	GList *above;		/* List of widgets above me */
+} GntNode;
+
 static GHashTable *nodes;
 
 static void free_node(gpointer data);
 
 void gnt_screen_take_focus(GntWidget *widget)
 {
+	GntWidget *w = NULL;
+	if (focus_list)
+		w = focus_list->data;
 	focus_list = g_list_prepend(focus_list, widget);
+	gnt_widget_set_focus(widget, TRUE);
+	if (w)
+		gnt_widget_set_focus(w, FALSE);
 }
 
 void gnt_screen_remove_widget(GntWidget *widget)
 {
 	focus_list = g_list_remove(focus_list, widget);
 	if (focus_list)
+	{
+		gnt_widget_set_focus(focus_list->data, TRUE);
 		gnt_widget_draw(focus_list->data);
+	}
+}
+
+static void
+bring_on_top(GntWidget *widget)
+{
+	GntNode *node = g_hash_table_lookup(nodes, widget);
+	GList *iter;
+
+	if (!node)
+		return;
+
+	for (iter = node->above; iter;)
+	{
+		GntNode *n = iter->data;
+		iter = iter->next;
+		n->below = g_list_remove(n->below, node);
+		n->above = g_list_prepend(n->above, node);
+
+		node->above = g_list_remove(node->above, n);
+		node->below = g_list_prepend(node->below, n);
+	}
 }
 
 static gboolean
@@ -79,15 +116,23 @@
 		else if (strcmp(buffer + 1, "n") == 0)
 		{
 			/* Alt + n to go to the next window */
+			GntWidget *w = NULL;
+			if (focus_list)
+				w = focus_list->data;
+
 			if (focus_list && focus_list->next)
 				focus_list = focus_list->next;
 			else
 				focus_list = g_list_first(focus_list);
 			if (focus_list)
 			{
-				/* XXX: Need a way to bring it on top */
+				gnt_widget_set_focus(focus_list->data, TRUE);
+				bring_on_top(focus_list->data);
 				gnt_widget_draw(focus_list->data);
 			}
+
+			if (w && w != focus_list->data)
+				gnt_widget_set_focus(w, FALSE);
 		}
 	}
 	refresh();
@@ -134,13 +179,6 @@
  * Stuff for 'window management' *
  *********************************/
 
-typedef struct
-{
-	GntWidget *me;
-	GList *below;		/* List of widgets below me */
-	GList *above;		/* List of widgets above me */
-} GntNode;
-
 static void
 free_node(gpointer data)
 {
@@ -284,3 +322,26 @@
 	delwin(win);
 }
 
+gboolean gnt_widget_has_focus(GntWidget *widget)
+{
+	GntWidget *w;
+	if (!widget)
+		return FALSE;
+
+	w = widget;
+
+	while (widget->parent)
+	{
+		fprintf(stderr, "%p %p\n", widget, widget->parent);
+		widget = widget->parent;
+	}
+	fprintf(stderr, "%p %p\n", widget, widget->parent);
+
+	if (focus_list && focus_list->data == widget &&
+			(!GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_CAN_TAKE_FOCUS) ||
+			GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_HAS_FOCUS)))
+		return TRUE;
+
+	return FALSE;
+}
+
--- 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));
 }
 
--- a/console/libgnt/gnttextview.h	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gnttextview.h	Sat Jul 01 00:56:05 2006 +0000
@@ -25,9 +25,7 @@
 {
 	GntWidget parent;
 
-	WINDOW *scroll;     /* XXX: For now, let's do with this. */
-	int pos;            /* Scroll position. */
-	int lines;          /* No. of lines of text. */
+	GList *list;        /* List of GntTextLine */
 };
 
 typedef enum
@@ -35,6 +33,8 @@
 	GNT_TEXT_FLAG_BOLD        = 1 << 0,
 	GNT_TEXT_FLAG_UNDERLINE   = 1 << 1,
 	GNT_TEXT_FLAG_BLINK       = 1 << 2,
+	GNT_TEXT_FLAG_DIM         = 1 << 3,
+	GNT_TEXT_FLAG_HIGHLIGHT   = 1 << 4,
 } GntTextViewFlags;
 
 struct _GnTextViewClass
--- a/console/libgnt/gnttree.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gnttree.c	Sat Jul 01 00:56:05 2006 +0000
@@ -203,7 +203,7 @@
 		
 		if (row == tree->current)
 		{
-			if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_HAS_FOCUS))
+			if (gnt_widget_has_focus(widget))
 				wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT));
 			else
 				wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); /* XXX: This, somehow, doesn't work */
@@ -230,9 +230,6 @@
 {
 	GntTree *tree = GNT_TREE(widget);
 
-	scrollok(widget->window, TRUE);
-	wsetscrreg(widget->window, 0, widget->priv.height - 1);
-
 	redraw_tree(tree);
 	
 	DEBUG;
--- a/console/libgnt/gntwidget.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/gntwidget.c	Sat Jul 01 00:56:05 2006 +0000
@@ -369,7 +369,6 @@
 
 	if (set && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_HAS_FOCUS))
 	{
-		g_signal_emit(widget->parent, signals[SIG_LOST_FOCUS], 0);
 		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_HAS_FOCUS);
 		g_signal_emit(widget, signals[SIG_GIVE_FOCUS], 0);
 	}
--- a/console/libgnt/test/multiwin.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/test/multiwin.c	Sat Jul 01 00:56:05 2006 +0000
@@ -37,6 +37,7 @@
 	gnt_box_set_title(GNT_BOX(box2), "On top");
 
 	gnt_box_add_widget(GNT_BOX(box2), GNT_WIDGET(gnt_label_new("asdasd")));
+	gnt_box_add_widget(GNT_BOX(box2), gnt_entry_new(NULL));
 
 	gnt_widget_show(hbox);
 	gnt_widget_set_position(box2, 5, 5);
--- a/console/libgnt/test/tv.c	Fri Jun 30 16:23:56 2006 +0000
+++ b/console/libgnt/test/tv.c	Sat Jul 01 00:56:05 2006 +0000
@@ -11,10 +11,10 @@
 {
 	if (key[0] == '\r' && key[1] == 0)
 	{
-		gnt_text_view_next_line(GNT_TEXT_VIEW(view));
 		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view),
 				gnt_entry_get_text(GNT_ENTRY(w)),
-				GNT_TEXT_FLAG_BOLD);
+				GNT_TEXT_FLAG_HIGHLIGHT);
+		gnt_text_view_next_line(GNT_TEXT_VIEW(view));
 		gnt_entry_clear(GNT_ENTRY(w));
 		gnt_text_view_scroll(GNT_TEXT_VIEW(view), 0);
 
@@ -54,8 +54,8 @@
 	view = gnt_text_view_new();
 	gnt_widget_set_name(view, "view");
 
-	gnt_widget_set_size(view, getmaxx(stdscr) - 3, 15);
-	gnt_widget_set_size(entry, getmaxx(stdscr) - 3, 1);
+	gnt_widget_set_size(view, 20, 15);
+	gnt_widget_set_size(entry, 20, 1);
 
 	gnt_box_add_widget(GNT_BOX(hbox), view);
 	gnt_box_add_widget(GNT_BOX(hbox), entry);