changeset 13850:0e1e59770cb0

[gaim-migrate @ 16308] This is my first commit here. So don't yell at me if things get borked. Also, I haven't looked at the auto-thingies yet. So don't puke at the Makefiles. Files in console/libgnt/ are for the 'Gaim/GObjectified Ncurses Toolkit' library. Files in console/ uses libgaim and libgnt. Currently, only the buddylist-ui is 'functional', ie. the buddy-list updates when someone logs on or logs off. It still needs a lot of work. committer: Tailor Script <tailor@pidgin.im>
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Thu, 22 Jun 2006 08:33:54 +0000
parents 8d1c55309e3c
children 41753203a94d 995aea35b05c
files console/Makefile console/gntblist.c console/gntblist.h console/gntgaim.c console/gntgaim.h console/gntui.c console/gntui.h console/libgnt/Makefile console/libgnt/gnt-skel.c console/libgnt/gnt-skel.h console/libgnt/gnt.h console/libgnt/gntbox.c console/libgnt/gntbox.h console/libgnt/gntbutton.c console/libgnt/gntbutton.h console/libgnt/gntcolors.c console/libgnt/gntcolors.h console/libgnt/gntkeys.h console/libgnt/gntlabel.c console/libgnt/gntlabel.h console/libgnt/gntmain.c console/libgnt/gnttree.c console/libgnt/gnttree.h console/libgnt/gntutils.c console/libgnt/gntutils.h console/libgnt/gntwidget.c console/libgnt/gntwidget.h console/libgnt/test.c
diffstat 28 files changed, 2641 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/Makefile	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,27 @@
+CFLAGS=`pkg-config --cflags gaim gobject-2.0` -g -I./libgnt/
+LDFLAGS=`pkg-config --libs gaim gobject-2.0 gthread-2.0 libxml-2.0` -lncursesw -L./libgnt/ -lgnt
+
+GG_SOURCES = \
+	gntblist.c \
+	gntui.c
+
+GG_HEADERS = \
+	gntblist.h \
+	gntui.h
+
+GG_OBJECTS = \
+	gntblist.o \
+	gntui.o
+
+all: gntgaim
+
+gntgaim: gntgaim.o $(GG_OBJECTS)
+	$(CC) -o gntgaim gntgaim.o $(GG_OBJECTS) $(LDFLAGS)
+gntblist.o: gntblist.c $(GG_HEADERS)
+gntgaim.o: gntgaim.c gntgaim.h $(GG_HEADERS)
+gntui.o: gntui.c $(GG_HEADERS)
+
+clean:
+	rm *.o
+	rm gntgaim
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/gntblist.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,121 @@
+#include <gaim/account.h>
+#include <gaim/blist.h>
+#include <signal.h>
+#include <gaim/util.h>
+#include <gaim/server.h>
+
+#include "gntgaim.h"
+#include "gntbox.h"
+#include "gnttree.h"
+
+#define	TAB_SIZE 3
+
+/**
+ * NOTES:
+ *
+ * 1. signal-callbacks should check for module_in_focus() before redrawing anything.
+ * 2. call module_lost_focus() before opening a new window, and module_gained_focus() when
+ * 		the new window is closed. This is to make sure the signal callbacks don't screw up
+ * 		the display.
+ */
+
+static GaimBlistUiOps blist_ui_ops = 
+{
+	NULL,
+	NULL,
+	NULL,
+	NULL,		/* This doesn't do crap */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+typedef struct
+{
+	GntWidget *window;
+	GntWidget *tree;
+} GGBlist;
+
+GGBlist *ggblist;
+
+static gpointer
+gg_blist_get_handle()
+{
+	static int handle;
+
+	return &handle;
+}
+
+static void
+add_group(GaimGroup *group, GGBlist *ggblist)
+{
+	GaimBlistNode *node = (GaimBlistNode *)group;
+	if (node->ui_data)
+		return;
+	gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group,
+			group->name, NULL, NULL);
+	node->ui_data = GINT_TO_POINTER(TRUE);
+}
+
+static void
+buddy_signed_on(GaimBuddy *buddy, GGBlist *ggblist)
+{
+	GaimGroup *group = gaim_buddy_get_group(buddy);
+	char *text;
+
+	add_group(group, ggblist);
+
+	text = g_strdup_printf("%*s%s", TAB_SIZE, "", gaim_buddy_get_alias(buddy));
+	gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy, text, group, NULL);
+	g_free(text);
+}
+
+static void
+buddy_signed_off(GaimBuddy *buddy, GGBlist *ggblist)
+{
+	gnt_tree_remove(GNT_TREE(ggblist->tree), buddy);
+}
+
+GaimBlistUiOps *gg_get_blist_ui_ops()
+{
+	return &blist_ui_ops;
+}
+
+static void
+selection_activate(GntWidget *widget, GGBlist *ggblist)
+{
+	gnt_widget_set_focus(widget, FALSE);
+}
+
+void gg_blist_init()
+{
+	ggblist = g_new0(GGBlist, 1);
+
+	ggblist->window = gnt_box_new(FALSE, FALSE);
+	gnt_box_set_title(GNT_BOX(ggblist->window), _("Buddy List"));
+
+	ggblist->tree = gnt_tree_new();
+	gnt_widget_set_size(ggblist->tree, 25, getmaxy(stdscr));
+
+	gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->tree);
+	gnt_widget_show(ggblist->window);
+	
+	gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-on", gg_blist_get_handle(),
+				GAIM_CALLBACK(buddy_signed_on), ggblist);
+	gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-off", gg_blist_get_handle(),
+				GAIM_CALLBACK(buddy_signed_off), ggblist);
+
+	g_signal_connect(G_OBJECT(ggblist->tree), "activate", G_CALLBACK(selection_activate), ggblist);
+	
+	/*gaim_signal_connect(gaim_conversations_get_handle(), "received-im-msg", gg_blist_get_handle(),*/
+				/*GAIM_CALLBACK(received_im_msg), list);*/
+	/*gaim_signal_connect(gaim_conversations_get_handle(), "sent-im-msg", gg_blist_get_handle(),*/
+				/*GAIM_CALLBACK(sent_im_msg), NULL);*/
+
+	/*gaim_signal_connect(gaim_conversations_get_handle(), "received-chat-msg", gg_blist_get_handle(),*/
+				/*GAIM_CALLBACK(received_chat_msg), list);*/
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/gntblist.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,5 @@
+#include "blist.h"
+
+GaimBlistUiOps * gg_get_blist_ui_ops();
+
+void gg_blist_init();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/gntgaim.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,193 @@
+#include "account.h"
+#include "conversation.h"
+#include "core.h"
+#include "debug.h"
+#include "eventloop.h"
+#include "ft.h"
+#include "log.h"
+#include "notify.h"
+#include "prefs.h"
+#include "prpl.h"
+#include "pounce.h"
+#include "savedstatuses.h"
+#include "sound.h"
+#include "status.h"
+#include "util.h"
+#include "whiteboard.h"
+
+#include "gntgaim.h"
+
+/* Anything IO-related is directly copied from gtkgaim's source tree */
+
+static GaimCoreUiOps core_ops =
+{
+	NULL, /*gaim_gtk_prefs_init,*/
+	NULL, /*debug_init,*/
+	NULL, /*gaim_gtk_ui_init,*/
+	NULL, /*gaim_gtk_quit*/
+};
+
+static GaimCoreUiOps *
+gnt_core_get_ui_ops()
+{
+	return &core_ops;
+}
+
+#define GAIM_GTK_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
+#define GAIM_GTK_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
+
+typedef struct _GaimGtkIOClosure {
+	GaimInputFunction function;
+	guint result;
+	gpointer data;
+
+} GaimGtkIOClosure;
+
+static void gaim_gtk_io_destroy(gpointer data)
+{
+	g_free(data);
+}
+
+static gboolean gaim_gtk_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+	GaimGtkIOClosure *closure = data;
+	GaimInputCondition gaim_cond = 0;
+
+	if (condition & GAIM_GTK_READ_COND)
+		gaim_cond |= GAIM_INPUT_READ;
+	if (condition & GAIM_GTK_WRITE_COND)
+		gaim_cond |= GAIM_INPUT_WRITE;
+
+#if 0
+	gaim_debug(GAIM_DEBUG_MISC, "gtk_eventloop",
+			   "CLOSURE: callback for %d, fd is %d\n",
+			   closure->result, g_io_channel_unix_get_fd(source));
+#endif
+
+#ifdef _WIN32
+	if(! gaim_cond) {
+#if DEBUG
+		gaim_debug(GAIM_DEBUG_MISC, "gtk_eventloop",
+			   "CLOSURE received GIOCondition of 0x%x, which does not"
+			   " match 0x%x (READ) or 0x%x (WRITE)\n",
+			   condition, GAIM_GTK_READ_COND, GAIM_GTK_WRITE_COND);
+#endif /* DEBUG */
+
+		return TRUE;
+	}
+#endif /* _WIN32 */
+
+	closure->function(closure->data, g_io_channel_unix_get_fd(source),
+			  gaim_cond);
+
+	return TRUE;
+}
+
+static guint gnt_input_add(gint fd, GaimInputCondition condition, GaimInputFunction function,
+							   gpointer data)
+{
+	GaimGtkIOClosure *closure = g_new0(GaimGtkIOClosure, 1);
+	GIOChannel *channel;
+	GIOCondition cond = 0;
+
+	closure->function = function;
+	closure->data = data;
+
+	if (condition & GAIM_INPUT_READ)
+		cond |= GAIM_GTK_READ_COND;
+	if (condition & GAIM_INPUT_WRITE)
+		cond |= GAIM_GTK_WRITE_COND;
+
+	channel = g_io_channel_unix_new(fd);
+	closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
+					      gaim_gtk_io_invoke, closure, gaim_gtk_io_destroy);
+
+#if 0
+	gaim_debug(GAIM_DEBUG_MISC, "gtk_eventloop",
+			   "CLOSURE: adding input watcher %d for fd %d\n",
+			   closure->result, fd);
+#endif
+
+	g_io_channel_unref(channel);
+	return closure->result;
+}
+
+static GaimEventLoopUiOps eventloop_ops =
+{
+	g_timeout_add,
+	(guint (*)(guint))g_source_remove,
+	gnt_input_add,
+	(guint (*)(guint))g_source_remove
+};
+
+GaimEventLoopUiOps *
+gnt_eventloop_get_ui_ops(void)
+{
+	return &eventloop_ops;
+}
+
+/* This is mostly copied from gtkgaim's source tree */
+static void
+init_libgaim()
+{
+	char *path;
+
+	gaim_debug_set_enabled(FALSE);
+
+	gaim_core_set_ui_ops(gnt_core_get_ui_ops());
+	gaim_eventloop_set_ui_ops(gnt_eventloop_get_ui_ops());
+
+	gaim_util_set_user_dir("/tmp/tmp/");		/* XXX: */
+
+	path = g_build_filename(gaim_user_dir(), "plugins", NULL);
+	gaim_plugins_add_search_path(path);
+	g_free(path);
+	gaim_plugins_add_search_path("/usr/local/lib/gaim");	/* XXX: */
+
+	if (!gaim_core_init(GAIM_GNT_UI))
+	{
+		fprintf(stderr, "OOPSSS!!\n");
+		abort();
+	}
+
+	/* TODO: Move blist loading into gaim_blist_init() */
+	gaim_set_blist(gaim_blist_new());
+	gaim_blist_load();
+
+	/* TODO: Move prefs loading into gaim_prefs_init() */
+	gaim_prefs_load();
+	gaim_prefs_update_old();
+
+	/* load plugins we had when we quit */
+	gaim_plugins_load_saved("/gaim/gtk/plugins/loaded");
+
+	/* TODO: Move pounces loading into gaim_pounces_init() */
+	gaim_pounces_load();
+
+}
+
+int main(int argc, char **argv)
+{
+	GMainLoop *loop;
+
+	/* Initialize the libgaim stuff */
+	init_libgaim();
+
+	/* Connect to the signals */
+
+	/* Enable the accounts and restore the status */
+	gaim_accounts_restore_current_statuses();
+
+	/* Main loop */
+	g_thread_init(NULL);
+	loop = g_main_loop_new(NULL, TRUE);
+	g_thread_create((GThreadFunc)g_main_loop_run, loop, FALSE, NULL);
+	
+	/* Initialize the UI */
+	init_gnt_ui();
+
+	gaim_core_quit();
+
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/gntgaim.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,5 @@
+#include <glib.h>
+
+#define GAIM_GNT_UI "gnt-gaim"
+
+#define	_(x)	x
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/gntui.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,18 @@
+#include "gntui.h"
+
+void init_gnt_ui()
+{
+	gnt_init();
+
+	wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+	werase(stdscr);
+	/*box(stdscr, ACS_VLINE, ACS_HLINE);*/
+	wrefresh(stdscr);
+
+	/* Initialize the buddy list */
+	gg_blist_init();
+	gaim_blist_set_ui_ops(gg_get_blist_ui_ops());
+
+	gnt_main();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/gntui.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,3 @@
+#include "gnt.h"
+
+void init_gnt_ui();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/Makefile	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,53 @@
+CFLAGS=`pkg-config --cflags gobject-2.0` -g
+LDFLAGS=`pkg-config --libs gobject-2.0` -lncursesw
+
+HEADERS = \
+	gntwidget.h \
+	gntbox.h \
+	gntbutton.h \
+	gntcolors.h \
+	gntlabel.h \
+	gnttree.h \
+	gntutils.h \
+	gnt.h
+
+SOURCES = \
+	gntwidget.c \
+	gntbox.c \
+	gntbutton.c \
+	gntcolors.c \
+	gntlabel.c \
+	gnttree.c \
+	gntutils.c \
+	gntmain.c
+
+OBJECTS = \
+	gntwidget.o \
+	gntbox.o \
+	gntbutton.o \
+	gntcolors.o \
+	gntlabel.o \
+	gnttree.o \
+	gntutils.o \
+	gntmain.o
+
+all: libgnt
+
+test: $(OBJECTS)
+
+gntwidget.o: gntwidget.c $(HEADERS)
+gntbox.o: gntbox.c $(HEADERS)
+gntbutton.o: gntbutton.c $(HEADERS)
+gntcolors.o: gntcolors.c $(HEADERS)
+gntlabel.o: gntlabel.c $(HEADERS)
+gnttree.o: gnttree.c $(HEADERS)
+gntutils.o: gntutils.c $(HEADERS)
+gntmain.o: gntmain.c $(HEADERS)
+
+libgnt: $(OBJECTS)
+	$(CC) --shared -o libgnt.so $(OBJECTS)
+
+clean:
+	rm *.o
+	rm libgnt.so
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gnt-skel.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,93 @@
+#include "gn-skel.h"
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntWidgetClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+
+static void
+gnt_skel_draw(GntWidget *widget)
+{
+	DEBUG;
+}
+
+static void
+gnt_skel_size_request(GntWidget *widget)
+{
+}
+
+static void
+gnt_skel_map(GntWidget *widget)
+{
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+		gnt_widget_size_request(widget);
+	DEBUG;
+}
+
+static gboolean
+gnt_skel_key_pressed(GntWidget *widget, const char *text)
+{
+	return FALSE;
+}
+
+static void
+gnt_skel_class_init(GntWidgetClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->draw = gnt_skel_draw;
+	parent_class->map = gnt_skel_map;
+	parent_class->size_request = gnt_skel_size_request;
+	parent_class->key_pressed = gnt_skel_key_pressed;
+
+	DEBUG;
+}
+
+static void
+gnt_skel_init(GTypeInstance *instance, gpointer class)
+{
+	DEBUG;
+}
+
+/******************************************************************************
+ * GntSkel API
+ *****************************************************************************/
+GType
+gnt_skel_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntSkelClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_skel_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntSkel),
+			0,						/* n_preallocs		*/
+			gnt_skel_init,			/* instance_init	*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntSkel",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_skel_new()
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_SKEL, NULL);
+	GntSkel *skel = GNT_SKEL(widget);
+
+	return widget;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gnt-skel.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,47 @@
+#ifndef GNT_SKEL_H
+#define GNT_SKEL_H
+
+#include "gnwidget.h"
+#include "gn.h"
+#include "gncolors.h"
+#include "gnkeys.h"
+
+#define GNT_TYPE_SKEL				(gnt_skel_get_gtype())
+#define GNT_SKEL(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_SKEL, GntSkel))
+#define GNT_SKEL_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_SKEL, GntSkelClass))
+#define GNT_IS_SKEL(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_SKEL))
+#define GNT_IS_SKEL_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_SKEL))
+#define GNT_SKEL_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_SKEL, GntSkelClass))
+
+#define GNT_SKEL_FLAGS(obj)				(GNT_SKEL(obj)->priv.flags)
+#define GNT_SKEL_SET_FLAGS(obj, flags)		(GNT_SKEL_FLAGS(obj) |= flags)
+#define GNT_SKEL_UNSET_FLAGS(obj, flags)	(GNT_SKEL_FLAGS(obj) &= ~(flags))
+
+typedef struct _GnSkel			GntSkel;
+typedef struct _GnSkelPriv		GntSkelPriv;
+typedef struct _GnSkelClass		GntSkelClass;
+
+struct _GnSkel
+{
+	GntWidget parent;
+};
+
+struct _GnSkelClass
+{
+	GntWidgetClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_skel_get_gtype(void);
+
+GntWidget *gnt_skel_new();
+
+G_END_DECLS
+
+#endif /* GNT_SKEL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gnt.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,17 @@
+#include <glib.h>
+#include "gntwidget.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+
+/* XXX: Find a better place for this */
+#define SCROLL_HEIGHT	4096
+#define SCROLL_WIDTH 512
+
+void gnt_init();
+
+void gnt_main();
+
+void gnt_screen_take_focus(GntWidget *widget);
+
+void gnt_screen_remove_widget(GntWidget *widget);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntbox.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,323 @@
+#include "gntbox.h"
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntWidgetClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+
+static void
+gnt_box_draw(GntWidget *widget)
+{
+	GntBox *box = GNT_BOX(widget);
+	GList *iter;
+
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		gnt_widget_draw(GNT_WIDGET(iter->data));
+	}
+
+	if (box->title)
+	{
+		gchar *title = g_strdup(box->title);
+		int pos = g_utf8_strlen(title, -1);
+
+		if (pos >= widget->priv.width - 2)
+		{
+			g_utf8_strncpy(title, box->title, widget->priv.width - 2);
+			pos = 1;
+		}
+		else
+		{
+			pos = (widget->priv.width - pos - 2) / 2;
+			/*pos = 2;*/
+		}
+		wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE));
+		mvwprintw(widget->window, 0, pos, title);
+		g_free(title);
+	}
+	wrefresh(widget->window);
+	
+	DEBUG;
+}
+
+static void
+reposition_children(GntWidget *widget)
+{
+	GList *iter;
+	GntBox *box = GNT_BOX(widget);
+	int w, h, curx, cury, max;
+	gboolean has_border = FALSE;
+	int x, y;
+
+	x = widget->priv.x;
+	y = widget->priv.y;
+	w = h = 0;
+	max = -1;
+	curx = widget->priv.x;
+	cury = widget->priv.y;
+	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER))
+	{
+		has_border = TRUE;
+		curx += 1;
+		cury += 1;
+		if (!box->vertical)
+			curx++;
+	}
+
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		gnt_widget_set_position(GNT_WIDGET(iter->data), curx, cury);
+		gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h);
+		if (box->vertical)
+		{
+			cury += h + 1;
+			if (max < w)
+				max = w;
+		}
+		else
+		{
+			curx += w + 2;
+			if (max < h)
+				max = h;
+		}
+	}
+
+	if (has_border)
+	{
+		curx += 2;
+		cury += 1;
+		max += 2;
+	}
+
+	if (box->vertical)
+	{
+		widget->priv.width = max;
+		widget->priv.height = cury - widget->priv.y;
+	}
+	else
+	{
+		widget->priv.width = curx - widget->priv.x;
+		widget->priv.height = max;
+	}
+}
+
+static void
+gnt_box_set_position(GntWidget *widget, int x, int y)
+{
+	gnt_widget_size_request(widget);
+	reposition_children(widget);
+}
+
+static void
+gnt_box_size_request(GntWidget *widget)
+{
+	GntBox *box = GNT_BOX(widget);
+	GList *iter;
+	
+	g_list_foreach(box->list, (GFunc)gnt_widget_size_request, NULL);
+
+	if (box->homogeneous)
+	{
+		int max = -1, w, h;
+
+		/* XXX: should probably be changed based on vertical-ness */
+		for (iter = box->list; iter; iter = iter->next)
+		{
+			gnt_widget_get_size(GNT_WIDGET(iter->data), &w, NULL);
+			if (max < w)
+				max = w;
+		}
+
+		for (iter = box->list; iter; iter = iter->next)
+		{
+			gnt_widget_get_size(GNT_WIDGET(iter->data), NULL, &h);
+			gnt_widget_set_size(GNT_WIDGET(iter->data), max, h);
+		}
+	}
+
+	reposition_children(widget);
+}
+
+static void
+gnt_box_map(GntWidget *widget)
+{
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+		gnt_widget_size_request(widget);
+	DEBUG;
+}
+
+static gboolean
+gnt_box_key_pressed(GntWidget *widget, const char *text)
+{
+	GntBox *box = GNT_BOX(widget);
+
+	/*if (box->list == NULL)*/
+		/*return FALSE;*/
+
+	if (box->active == NULL)
+		box->active = box->list;
+
+	if (gnt_widget_key_pressed(box->active->data, text))
+		return TRUE;
+	
+	if (text[0] == 27)
+	{
+		GList *now = NULL;
+		if (strcmp(text+1, GNT_KEY_LEFT) == 0)
+		{
+			now = box->active->prev;
+			if (now == NULL)
+				now = g_list_last(box->list);
+		}
+		else if (strcmp(text+1, GNT_KEY_RIGHT) == 0)
+		{
+			now = box->active->next;
+			if (now == NULL)
+				now = box->list;
+		}
+
+		if (now)
+		{
+			gnt_widget_set_focus(box->active->data, FALSE);
+			box->active = now;
+			gnt_widget_set_focus(box->active->data, TRUE);
+
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+static GntWidget *find_focused_widget(GntBox *box)
+{
+	GList *iter;
+
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		GntWidget *w = iter->data;
+		
+		if (GNT_IS_BOX(w))
+		{
+			if ((w = find_focused_widget(GNT_BOX(w))) != NULL)
+				return w;
+		}
+		else
+		{
+			if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_CAN_TAKE_FOCUS) &&
+					GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_HAS_FOCUS))
+				return w;
+		}
+	}
+	return NULL;
+}
+
+static void
+gnt_box_lost_focus(GntWidget *widget)
+{
+	GntBox *box = GNT_BOX(widget);
+	GntWidget *p = widget;
+
+	while (p->parent)
+		p = p->parent;
+
+	p = find_focused_widget(GNT_BOX(p));
+	if (p)
+		gnt_widget_set_focus(p, FALSE);
+}
+
+static void
+gnt_box_destroy(GntWidget *w)
+{
+	GntBox *box = GNT_BOX(w);
+	GList *iter;
+
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		gnt_widget_destroy(iter->data);
+	}
+
+	g_list_free(box->list);
+}
+
+static void
+gnt_box_class_init(GntWidgetClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->destroy = gnt_box_destroy;
+	parent_class->draw = gnt_box_draw;
+	parent_class->map = gnt_box_map;
+	parent_class->size_request = gnt_box_size_request;
+	parent_class->set_position = gnt_box_set_position;
+	parent_class->key_pressed = gnt_box_key_pressed;
+	parent_class->lost_focus = gnt_box_lost_focus;
+
+	DEBUG;
+}
+
+static void
+gnt_box_init(GTypeInstance *instance, gpointer class)
+{
+	DEBUG;
+}
+
+/******************************************************************************
+ * GntBox API
+ *****************************************************************************/
+GType
+gnt_box_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntBoxClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_box_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntBox),
+			0,						/* n_preallocs		*/
+			gnt_box_init,			/* instance_init	*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntBox",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_box_new(gboolean homo, gboolean vert)
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_BOX, NULL);
+	GntBox *box = GNT_BOX(widget);
+
+	box->homogeneous = homo;
+	box->vertical = vert;
+	gnt_widget_set_take_focus(widget, TRUE);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+
+	return widget;
+}
+
+void gnt_box_add_widget(GntBox *b, GntWidget *widget)
+{
+	b->list = g_list_append(b->list, widget);
+	widget->parent = GNT_WIDGET(b);
+}
+
+void gnt_box_set_title(GntBox *b, const char *title)
+{
+	g_free(b->title);
+	b->title = g_strdup(title);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntbox.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,58 @@
+#ifndef GNT_BOX_H
+#define GNT_BOX_H
+
+#include "gnt.h"
+#include "gntwidget.h"
+
+#define GNT_TYPE_BOX				(gnt_box_get_gtype())
+#define GNT_BOX(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_BOX, GntBox))
+#define GNT_BOX_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_BOX, GntBoxClass))
+#define GNT_IS_BOX(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_BOX))
+#define GNT_IS_BOX_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_BOX))
+#define GNT_BOX_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_BOX, GntBoxClass))
+
+typedef struct _GnBox			GntBox;
+typedef struct _GnBoxClass		GntBoxClass;
+
+struct _GnBox
+{
+	GntWidget parent;
+
+	gboolean vertical;
+	gboolean homogeneous;
+	GList *list;		/* List of widgets */
+
+	GList *active;
+
+	char *title;
+
+    void (*gnt_reserved1)(void);
+    void (*gnt_reserved2)(void);
+    void (*gnt_reserved3)(void);
+    void (*gnt_reserved4)(void);
+};
+
+struct _GnBoxClass
+{
+	GntWidgetClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_box_get_gtype(void);
+
+GntWidget *gnt_box_new(gboolean homo, gboolean vert);
+
+void gnt_box_add_widget(GntBox *box, GntWidget *widget);
+
+void gnt_box_set_title(GntBox *box, const char *title);
+
+G_END_DECLS
+
+#endif /* GNT_BOX_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntbutton.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,116 @@
+#include "gntbutton.h"
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntWidgetClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+
+static void
+gnt_button_draw(GntWidget *widget)
+{
+	GntButton *button = GNT_BUTTON(widget);
+	GntColorType type;
+
+	if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_HAS_FOCUS)
+		type = GNT_COLOR_HIGHLIGHT;
+	else
+		type = GNT_COLOR_NORMAL;
+	wbkgdset(widget->window, '\0' | COLOR_PAIR(type));
+	mvwprintw(widget->window, 1, 1, button->priv->text);
+
+	wrefresh(widget->window);
+
+	DEBUG;
+}
+
+static void
+gnt_button_size_request(GntWidget *widget)
+{
+	GntButton *button = GNT_BUTTON(widget);
+	widget->priv.width = g_utf8_strlen(button->priv->text, -1) + 2;
+	widget->priv.height = 3;
+}
+
+static void
+gnt_button_map(GntWidget *widget)
+{
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+		gnt_widget_size_request(widget);
+	DEBUG;
+}
+
+static gboolean
+gnt_button_key_pressed(GntWidget *widget, const char *key)
+{
+	if (strcmp(key, GNT_KEY_ENTER) == 0)
+	{
+		gnt_widget_activate(widget);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static void
+gnt_button_class_init(GntWidgetClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->draw = gnt_button_draw;
+	parent_class->map = gnt_button_map;
+	parent_class->size_request = gnt_button_size_request;
+	parent_class->key_pressed = gnt_button_key_pressed;
+
+	DEBUG;
+}
+
+static void
+gnt_button_init(GTypeInstance *instance, gpointer class)
+{
+	GntButton *button = GNT_BUTTON(instance);
+	button->priv = g_new0(GntButtonPriv, 1);
+	DEBUG;
+}
+
+/******************************************************************************
+ * GntButton API
+ *****************************************************************************/
+GType
+gnt_button_get_gtype(void) {
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(GntButtonClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_button_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntButton),
+			0,						/* n_preallocs		*/
+			gnt_button_init,			/* instance_init	*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntButton",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_button_new(const char *text)
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_BUTTON, NULL);
+	GntButton *button = GNT_BUTTON(widget);
+
+	button->priv->text = g_strdup(text);
+	gnt_widget_set_take_focus(widget, TRUE);
+
+	return widget;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntbutton.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,55 @@
+#ifndef GNT_BUTTON_H
+#define GNT_BUTTON_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "gnt.h"
+#include "gntwidget.h"
+
+#define GNT_TYPE_BUTTON				(gnt_button_get_gtype())
+#define GNT_BUTTON(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_BUTTON, GntButton))
+#define GNT_BUTTON_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_BUTTON, GntButtonClass))
+#define GNT_IS_BUTTON(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_BUTTON))
+#define GNT_IS_BUTTON_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_BUTTON))
+#define GNT_BUTTON_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_BUTTON, GntButtonClass))
+
+typedef struct _GnButton			GntButton;
+typedef struct _GnButtonPriv		GntButtonPriv;
+typedef struct _GnButtonClass		GntButtonClass;
+
+struct _GnButtonPriv
+{
+	char *text;
+};
+
+struct _GnButton
+{
+	GntWidget parent;
+
+	GntButtonPriv *priv;
+
+    void (*gnt_reserved1)(void);
+    void (*gnt_reserved2)(void);
+    void (*gnt_reserved3)(void);
+    void (*gnt_reserved4)(void);
+};
+
+struct _GnButtonClass
+{
+	GntWidgetClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_button_get_gtype(void);
+
+GntWidget *gnt_button_new(const char *text);
+
+G_END_DECLS
+
+#endif /* GNT_BUTTON_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntcolors.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,21 @@
+#include <ncursesw/ncurses.h>
+#include "gntcolors.h"
+
+void gnt_init_colors()
+{
+	/* XXX: Do some init_color()s */
+	init_color(GNT_COLOR_BLACK, 0, 0, 0);
+	init_color(GNT_COLOR_RED, 1000, 0, 0);
+	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_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_SHADOW, GNT_COLOR_BLACK, GNT_COLOR_DARK_GRAY);
+	init_pair(GNT_COLOR_TITLE, GNT_COLOR_WHITE, GNT_COLOR_DARK_GRAY);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntcolors.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,34 @@
+#ifndef GNT_COLORS_H
+#define GNT_COLORS_H
+
+typedef enum
+{
+	GNT_COLOR_NORMAL = 1,
+	GNT_COLOR_HIGHLIGHT,		/* eg. when a button is selected */
+	GNT_COLOR_DISABLED,		/* eg. when a button is disabled */
+	GNT_COLOR_HIGHLIGHT_D,	/* eg. when a button is selected, but some other window is in focus */
+	GNT_COLOR_TEXT_NORMAL,
+	GNT_COLOR_TEXT_INACTIVE,	/* when the entry is out of focus */
+	GNT_COLOR_MNEMONIC,
+	GNT_COLOR_MNEMONIC_D,
+	GNT_COLOR_SHADOW,
+	GNT_COLOR_TITLE,
+	GNT_COLORS
+} GntColorType;
+
+enum
+{
+	GNT_COLOR_BLACK = 1,
+	GNT_COLOR_RED,
+	GNT_COLOR_GREEN,
+	GNT_COLOR_BLUE,
+	GNT_COLOR_WHITE,
+	GNT_COLOR_GRAY,
+	GNT_COLOR_DARK_GRAY,
+	GNT_TOTAL_COLORS
+};
+
+/* populate some default colors */
+void gnt_init_colors();
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntkeys.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,14 @@
+#ifndef GNT_KEYS_H
+#define GNT_KEYS_H
+
+#define	GNT_KEY_POPUP	"[29~"
+
+/* Arrow keys */
+#define	GNT_KEY_LEFT		"[D"
+#define	GNT_KEY_RIGHT	"[C"
+#define	GNT_KEY_UP		"[A"
+#define	GNT_KEY_DOWN		"[B"
+
+#define	GNT_KEY_ENTER	"\r"
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntlabel.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,120 @@
+#include "gntlabel.h"
+
+#include <string.h>
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntWidgetClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+
+static void
+gnt_label_destroy(GntWidget *widget)
+{
+	GntLabel *label = GNT_LABEL(widget);
+	g_free(label->text);
+}
+
+static void
+gnt_label_draw(GntWidget *widget)
+{
+	GntLabel *label = GNT_LABEL(widget);
+
+	wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+	mvwprintw(widget->window, 0, 0, label->text);
+	wrefresh(widget->window);
+
+	DEBUG;
+}
+
+static void
+gnt_label_size_request(GntWidget *widget)
+{
+	GntLabel *label = GNT_LABEL(widget);
+	char *s = label->text, *last = s;
+	int count = 1;
+	int max = 0;
+
+	/* XXX: ew ... everyone look away */
+	while (*s)
+	{
+		if (*s == '\n' || *s == '\r')
+		{
+			count++;
+			if (max < s - last + 1)
+				max = s - last + 1;
+			last = s + 1;
+		}
+		s++;
+	}
+	if (max < s - last + 1)
+		max = s - last + 1;
+	widget->priv.height = count;
+
+	widget->priv.width = max;
+}
+
+static void
+gnt_label_class_init(GntWidgetClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->destroy = gnt_label_destroy;
+	parent_class->draw = gnt_label_draw;
+	parent_class->map = NULL;
+	parent_class->size_request = gnt_label_size_request;
+
+	DEBUG;
+}
+
+static void
+gnt_label_init(GTypeInstance *instance, gpointer class)
+{
+	DEBUG;
+}
+
+/******************************************************************************
+ * GntLabel API
+ *****************************************************************************/
+GType
+gnt_label_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntLabelClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_label_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntLabel),
+			0,						/* n_preallocs		*/
+			gnt_label_init,			/* instance_init	*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntLabel",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_label_new(const char *text)
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_LABEL, NULL);
+	GntLabel *label = GNT_LABEL(widget);
+
+	label->text = g_strdup(text);
+	gnt_widget_set_take_focus(widget, FALSE);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+
+	return widget;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntlabel.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,48 @@
+#ifndef GNT_LABEL_H
+#define GNT_LABEL_H
+
+#include "gnt.h"
+#include "gntwidget.h"
+
+#define GNT_TYPE_LABEL				(gnt_label_get_gtype())
+#define GNT_LABEL(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_LABEL, GntLabel))
+#define GNT_LABEL_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_LABEL, GntLabelClass))
+#define GNT_IS_LABEL(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_LABEL))
+#define GNT_IS_LABEL_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_LABEL))
+#define GNT_LABEL_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_LABEL, GntLabelClass))
+
+typedef struct _GnLabel			GntLabel;
+typedef struct _GnLabelClass	GntLabelClass;
+
+struct _GnLabel
+{
+	GntWidget parent;
+
+	char *text;
+
+    void (*gnt_reserved1)(void);
+    void (*gnt_reserved2)(void);
+    void (*gnt_reserved3)(void);
+    void (*gnt_reserved4)(void);
+};
+
+struct _GnLabelClass
+{
+	GntWidgetClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_label_get_gtype(void);
+
+GntWidget *gnt_label_new(const char *text);
+
+G_END_DECLS
+
+#endif /* GNT_LABEL_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntmain.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,111 @@
+#include "gnt.h"
+#include "gntkeys.h"
+#include "gntcolors.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <locale.h>
+
+static GList *focus_list;
+static int max_x;
+static int max_y;
+
+void gnt_screen_take_focus(GntWidget *widget)
+{
+	focus_list = g_list_prepend(focus_list, widget);
+}
+
+void gnt_screen_remove_widget(GntWidget *widget)
+{
+	focus_list = g_list_remove(focus_list, widget);
+	if (focus_list)
+		gnt_widget_draw(focus_list->data);
+}
+
+static gboolean
+io_invoke(GIOChannel *source, GIOCondition cond, gpointer null)
+{
+	char buffer[256];
+
+	int rd = read(0, buffer, sizeof(buffer) - 1);
+	if (rd < 0)
+	{
+		endwin();
+		printf("ERROR!\n");
+		exit(1);
+	}
+	else if (rd == 0)
+	{
+		endwin();
+		printf("EOF\n");
+		exit(1);
+	}
+
+	buffer[rd] = 0;
+
+	if (focus_list)
+	{
+		gboolean ret = FALSE;
+		/*g_signal_emit_by_name(focus_list->data, "key_pressed", buffer, &ret);*/
+		ret = gnt_widget_key_pressed(focus_list->data, buffer);
+	}
+
+	if (buffer[0] == 27)
+	{
+		/* Some special key has been pressed */
+		if (strcmp(buffer+1, GNT_KEY_POPUP) == 0)
+		{
+			/*printf("popup\n");*/
+		}
+		else
+		{
+			/*printf("Unknown: %s\n", buffer+1);*/
+		}
+	}
+	else
+	{
+		if (buffer[0] == 'q')
+		{
+			endwin();
+			exit(1);
+		}
+		/*printf("%s\n", buffer);*/
+	}
+	refresh();
+
+	return TRUE;
+}
+
+void gnt_init()
+{
+	GIOChannel *channel = g_io_channel_unix_new(0);
+
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+	g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL );
+
+	int result = g_io_add_watch(channel, 
+					(G_IO_IN | G_IO_HUP | G_IO_ERR),
+					io_invoke, NULL);
+
+	setlocale(LC_ALL, "");
+	initscr();
+	start_color();
+	/*use_default_colors();*/
+	gnt_init_colors();
+
+	max_x = getmaxx(stdscr);
+	max_y = getmaxy(stdscr);
+
+	wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+	noecho();
+	refresh();
+	mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
+	g_type_init();
+}
+
+void gnt_main()
+{
+	GMainLoop *loop = g_main_new(FALSE);
+	g_main_run(loop);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gnttree.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,346 @@
+#include "gnttree.h"
+
+enum
+{
+	SIGS = 1,
+};
+
+/* XXX: Make this one into a GObject?
+ * 		 ... Probably not */
+struct _GnTreeRow
+{
+	void *key;
+	char *text;
+	void *data;		/* XXX: unused */
+
+	GntTreeRow *parent;
+	GntTreeRow *child;
+	GntTreeRow *next;
+};
+
+static GntWidgetClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+
+/* XXX: This is ugly, but what can you do ... */
+static void
+gnt_tree_refresh(GntTree *tree)
+{
+	GntWidget *widget = GNT_WIDGET(tree);
+	int pos;
+
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
+		pos = 0;
+	else
+		pos = 1;
+
+	copywin(tree->scroll, widget->window, tree->top, 0,
+			pos, pos, widget->priv.height - pos - 1, widget->priv.width - pos - 1, FALSE);
+	wrefresh(widget->window);
+}
+
+static void
+redraw_tree(GntTree *tree)
+{
+	int start;
+	GntWidget *widget = GNT_WIDGET(tree);
+	GList *iter;
+
+	wbkgd(tree->scroll, COLOR_PAIR(GNT_COLOR_NORMAL));
+
+	/* XXX: Add the rows */
+	for (start = tree->top, iter = g_list_nth(tree->list, tree->top);
+				iter && start < tree->bottom; start++, iter = iter->next)
+	{
+		char str[2096];	/* XXX: This should be safe for any terminal */
+		GntTreeRow *row = g_hash_table_lookup(tree->hash, iter->data);
+
+		snprintf(str, widget->priv.width - 2, "%s\n", row->text);
+		
+		if (start == tree->current)
+		{
+			wbkgdset(tree->scroll, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT));
+			mvwprintw(tree->scroll, start, 0, str);
+			wbkgdset(tree->scroll, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+		}
+		else
+			mvwprintw(tree->scroll, start, 0, str);
+	}
+
+	while (start < tree->bottom)
+	{
+		wmove(tree->scroll, start, 0);
+		wclrtoeol(tree->scroll);
+		start++;
+	}
+
+	gnt_tree_refresh(tree);
+}
+
+static void
+gnt_tree_draw(GntWidget *widget)
+{
+	GntTree *tree = GNT_TREE(widget);
+
+	/* For the Tree (or anything that scrolls), we will create a 'hidden' window
+	 * of 'large enough' size. We never wrefresh that hidden-window, instead we
+	 * just 'scroll' it, and wrefresh the subwindow */
+
+	if (tree->scroll == NULL)
+	{
+		tree->scroll = newwin(SCROLL_HEIGHT, widget->priv.width, widget->priv.y, widget->priv.x);
+		scrollok(tree->scroll, TRUE);
+		wsetscrreg(tree->scroll, 0, SCROLL_HEIGHT - 1);
+
+		tree->top = 0;
+		tree->bottom = widget->priv.height -
+				(GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER) ? 0 : 2);
+	}
+
+	redraw_tree(tree);
+	
+	DEBUG;
+}
+
+static void
+gnt_tree_size_request(GntWidget *widget)
+{
+	if (widget->priv.height == 0)
+		widget->priv.height = 10;	/* XXX: Why?! */
+	if (widget->priv.width == 0)
+		widget->priv.width = 20;	/* YYY: 'cuz ... */
+}
+
+static void
+gnt_tree_map(GntWidget *widget)
+{
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+		gnt_widget_size_request(widget);
+	DEBUG;
+}
+
+static gboolean
+gnt_tree_key_pressed(GntWidget *widget, const char *text)
+{
+	GntTree *tree = GNT_TREE(widget);
+	if (text[0] == 27)
+	{
+		if (strcmp(text+1, GNT_KEY_DOWN) == 0 && tree->current < g_list_length(tree->list) - 1)
+		{
+			tree->current++;
+			if (tree->current >= tree->bottom)
+				gnt_tree_scroll(tree, 1 + tree->current - tree->bottom);
+			redraw_tree(tree);
+		}
+		else if (strcmp(text+1, GNT_KEY_UP) == 0 && tree->current > 0)
+		{
+			tree->current--;
+			if (tree->current < tree->top)
+				gnt_tree_scroll(tree, tree->current - tree->top);
+			redraw_tree(tree);
+		}
+	}
+	else if (text[0] == '\r')
+	{
+		gnt_widget_activate(widget);
+	}
+
+	return FALSE;
+}
+
+static void
+gnt_tree_destroy(GntWidget *widget)
+{
+	GntTree *tree = GNT_TREE(widget);
+
+	g_hash_table_destroy(tree->hash);
+	g_list_free(tree->list);
+}
+
+static void
+gnt_tree_class_init(GntWidgetClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->destroy = gnt_tree_destroy;
+	parent_class->draw = gnt_tree_draw;
+	parent_class->map = gnt_tree_map;
+	parent_class->size_request = gnt_tree_size_request;
+	parent_class->key_pressed = gnt_tree_key_pressed;
+
+	DEBUG;
+}
+
+static void
+gnt_tree_init(GTypeInstance *instance, gpointer class)
+{
+	DEBUG;
+}
+
+/******************************************************************************
+ * GntTree API
+ *****************************************************************************/
+GType
+gnt_tree_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntTreeClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_tree_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntTree),
+			0,						/* n_preallocs		*/
+			gnt_tree_init,			/* instance_init	*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntTree",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_tree_new()
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_TREE, NULL);
+	GntTree *tree = GNT_TREE(widget);
+
+	tree->hash = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	return widget;
+}
+
+void gnt_tree_set_visible_rows(GntTree *tree, int rows)
+{
+	GntWidget *widget = GNT_WIDGET(tree);
+	widget->priv.height = rows;
+	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
+		widget->priv.height += 2;
+}
+
+int gnt_tree_get_visible_rows(GntTree *tree)
+{
+	GntWidget *widget = GNT_WIDGET(tree);
+	int ret = widget->priv.height;
+	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
+		widget->priv.height -= 2;
+}
+
+void gnt_tree_scroll(GntTree *tree, int count)
+{
+	if (tree->top == 0 && count < 0)
+		return;
+
+	if (count > 0 && tree->bottom + count >= g_list_length(tree->list))
+		count = g_list_length(tree->list) - tree->bottom;
+	else if (count < 0 && tree->top + count < 0)
+		count = -tree->top;
+
+	tree->top += count;
+	tree->bottom += count;
+
+	/*wscrl(tree->scroll, count);*/
+	gnt_tree_refresh(tree);
+}
+
+void gnt_tree_add_row_after(GntTree *tree, void *key, const char *text, void *parent, void *bigbro)
+{
+	GntTreeRow *row = g_new0(GntTreeRow, 1), *pr = NULL;
+
+	row->key = key;
+	row->text = g_strdup(text);
+	row->data = NULL;
+
+	g_hash_table_insert(tree->hash, key, row);
+
+	if (tree->root == NULL)
+	{
+		tree->root = row;
+		tree->list = g_list_prepend(tree->list, key);
+	}
+	else
+	{
+		int position;
+
+		if (bigbro)
+		{
+			pr = g_hash_table_lookup(tree->hash, bigbro);
+			if (pr)
+			{
+				row->next = pr->next;
+				pr->next = row;
+				row->parent = pr->parent;
+
+				position = g_list_index(tree->list, bigbro);
+			}
+		}
+
+		if (pr == NULL && parent)	
+		{
+			pr = g_hash_table_lookup(tree->hash, parent);
+			if (pr)
+			{
+				row->next = pr->child;
+				pr->child = row;
+				row->parent = pr;
+
+				position = g_list_index(tree->list, parent);
+			}
+		}
+
+		if (pr == NULL)
+		{
+			row->next = tree->root;
+			tree->root = row;
+
+			tree->list = g_list_prepend(tree->list, key);
+		}
+		else
+		{
+			tree->list = g_list_insert(tree->list, key, position + 1);
+		}
+	}
+
+	if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_MAPPED))
+		redraw_tree(tree);
+}
+
+gpointer gnt_tree_get_selection_data(GntTree *tree)
+{
+	return g_list_nth(tree->list, tree->current);
+}
+
+int gnt_tree_get_selection_index(GntTree *tree)
+{
+	return tree->current;
+}
+
+void gnt_tree_remove(GntTree *tree, gpointer key)
+{
+	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
+	if (row)
+	{
+		int len, pos;
+
+		g_free(row->text);
+		g_free(row);
+
+		pos = g_list_index(tree->list, key);
+
+		g_hash_table_remove(tree->hash, key);
+		tree->list = g_list_remove(tree->list, key);
+
+		if (pos >= tree->top && pos < tree->bottom)
+		{
+			redraw_tree(tree);
+		}
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gnttree.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,75 @@
+#ifndef GNT_TREE_H
+#define GNT_TREE_H
+
+#include "gntwidget.h"
+#include "gnt.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+
+#define GNT_TYPE_TREE				(gnt_tree_get_gtype())
+#define GNT_TREE(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_TREE, GntTree))
+#define GNT_TREE_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_TREE, GntTreeClass))
+#define GNT_IS_TREE(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_TREE))
+#define GNT_IS_TREE_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_TREE))
+#define GNT_TREE_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_TREE, GntTreeClass))
+
+#define GNT_TREE_FLAGS(obj)				(GNT_TREE(obj)->priv.flags)
+#define GNT_TREE_SET_FLAGS(obj, flags)		(GNT_TREE_FLAGS(obj) |= flags)
+#define GNT_TREE_UNSET_FLAGS(obj, flags)	(GNT_TREE_FLAGS(obj) &= ~(flags))
+
+typedef struct _GnTree			GntTree;
+typedef struct _GnTreePriv		GntTreePriv;
+typedef struct _GnTreeClass		GntTreeClass;
+
+typedef struct _GnTreeRow		GntTreeRow;
+
+struct _GnTree
+{
+	GntWidget parent;
+
+	WINDOW *scroll;
+
+	int current;	/* current selection */
+
+	int top;		/* The index in 'list' of the topmost visible item */
+	int bottom;		/* The index in 'list' of the bottommost visible item */
+	
+	GntTreeRow *root; /* The root of all evil */
+	
+	GList *list;	/* List of GntTreeRow s */
+	GHashTable *hash;	/* XXX: We may need this for quickly referencing the rows */
+};
+
+struct _GnTreeClass
+{
+	GntWidgetClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_tree_get_gtype(void);
+
+GntWidget *gnt_tree_new();
+
+void gnt_tree_set_visible_rows(GntTree *tree, int rows);
+
+int gnt_tree_get_visible_rows(GntTree *tree);
+
+void gnt_tree_scroll(GntTree *tree, int count);
+
+void gnt_tree_add_row_after(GntTree *tree, void *key, const char *text, void *parent, void *bigbro);
+
+gpointer gnt_tree_get_selection_data(GntTree *tree);
+
+int gnt_tree_get_selection_index(GntTree *tree);
+
+void gnt_tree_remove(GntTree *tree, gpointer key);
+
+G_END_DECLS
+
+#endif /* GNT_TREE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntutils.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,100 @@
+#include "gntutils.h"
+
+void gnt_closure_marshal_BOOLEAN__STRING(GClosure *closure,
+										GValue *ret_value,
+										guint n_param_values,
+										const GValue *param_values,
+										gpointer invocation_hint,
+										gpointer marshal_data)
+{
+	typedef gboolean (*func) (gpointer data1, const char *arg1, gpointer data2);
+	register func callback;
+	register GCClosure *cc = (GCClosure*)closure;
+	register gpointer data1, data2;
+	gboolean ret;
+
+	g_return_if_fail(ret_value != NULL);
+	g_return_if_fail(n_param_values == 2);
+
+	if (G_CCLOSURE_SWAP_DATA(closure))
+	{
+		data1 = closure->data;
+		data2 = g_value_peek_pointer(param_values + 0);
+	}
+	else
+	{
+		data1 = g_value_peek_pointer(param_values + 0);
+		data2 = closure->data;
+	}
+
+	callback = (func) (marshal_data ? marshal_data : cc->callback);
+	ret = callback(data1, g_value_get_string(param_values + 1) , data2);
+	g_value_set_boolean(ret_value, ret);
+}
+
+void gnt_closure_marshal_VOID__INT_INT_INT_INT(GClosure *closure,
+										GValue *ret_value,
+										guint n_param_values,
+										const GValue *param_values,
+										gpointer invocation_hint,
+										gpointer marshal_data)
+{
+	typedef void (*func) (gpointer data1, int, int, int, int, gpointer data2);
+	register func callback;
+	register GCClosure *cc = (GCClosure*)closure;
+	register gpointer data1, data2;
+
+	g_return_if_fail(n_param_values == 5);
+
+	if (G_CCLOSURE_SWAP_DATA(closure))
+	{
+		data1 = closure->data;
+		data2 = g_value_peek_pointer(param_values + 0);
+	}
+	else
+	{
+		data1 = g_value_peek_pointer(param_values + 0);
+		data2 = closure->data;
+	}
+
+	callback = (func) (marshal_data ? marshal_data : cc->callback);
+	callback(data1,
+			g_value_get_int(param_values + 1) ,
+			g_value_get_int(param_values + 2) ,
+			g_value_get_int(param_values + 3) ,
+			g_value_get_int(param_values + 4) ,
+			data2);
+}
+
+void gnt_closure_marshal_VOID__INT_INT(GClosure *closure,
+										GValue *ret_value,
+										guint n_param_values,
+										const GValue *param_values,
+										gpointer invocation_hint,
+										gpointer marshal_data)
+{
+	typedef void (*func) (gpointer data1, int, int, gpointer data2);
+	register func callback;
+	register GCClosure *cc = (GCClosure*)closure;
+	register gpointer data1, data2;
+
+	g_return_if_fail(n_param_values == 3);
+
+	if (G_CCLOSURE_SWAP_DATA(closure))
+	{
+		data1 = closure->data;
+		data2 = g_value_peek_pointer(param_values + 0);
+	}
+	else
+	{
+		data1 = g_value_peek_pointer(param_values + 0);
+		data2 = closure->data;
+	}
+
+	callback = (func) (marshal_data ? marshal_data : cc->callback);
+	callback(data1,
+			g_value_get_int(param_values + 1) ,
+			g_value_get_int(param_values + 2) ,
+			data2);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntutils.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,23 @@
+#include "gntwidget.h"
+
+void gnt_closure_marshal_BOOLEAN__STRING(GClosure *closure,
+										GValue *ret_value,
+										guint n_param_values,
+										const GValue *param_values,
+										gpointer invocation_hint,
+										gpointer marshal_data);
+
+void gnt_closure_marshal_VOID__INT_INT_INT_INT(GClosure *closure,
+										GValue *ret_value,
+										guint n_param_values,
+										const GValue *param_values,
+										gpointer invocation_hint,
+										gpointer marshal_data);
+
+void gnt_closure_marshal_VOID__INT_INT(GClosure *closure,
+										GValue *ret_value,
+										guint n_param_values,
+										const GValue *param_values,
+										gpointer invocation_hint,
+										gpointer marshal_data);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntwidget.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,386 @@
+/* Stuff brutally ripped from Gflib */
+
+#include "gntwidget.h"
+#include "gntutils.h"
+#include "gnt.h"
+
+enum
+{
+	SIG_DESTROY,
+	SIG_DRAW,
+	SIG_GIVE_FOCUS,
+	SIG_LOST_FOCUS,
+	SIG_KEY_PRESSED,
+	SIG_MAP,
+	SIG_ACTIVATE,
+	SIG_EXPOSE,
+	SIG_SIZE_REQUEST,
+	SIG_POSITION,
+	SIGS
+};
+
+static GObjectClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+
+static void
+gnt_widget_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	widget->priv.name = NULL;
+	DEBUG;
+}
+
+static void
+gnt_widget_map(GntWidget *widget)
+{
+	/* Get some default size for the widget */
+	DEBUG;
+	g_signal_emit(widget, signals[SIG_MAP], 0);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_MAPPED);
+}
+
+static void
+gnt_widget_dispose(GObject *obj)
+{
+	GntWidget *self = GNT_WIDGET(obj);
+
+	if(!(GNT_WIDGET_FLAGS(self) & GNT_WIDGET_DESTROYING)) {
+		GNT_WIDGET_SET_FLAGS(self, GNT_WIDGET_DESTROYING);
+
+		g_signal_emit(self, signals[SIG_DESTROY], 0);
+
+		GNT_WIDGET_UNSET_FLAGS(self, GNT_WIDGET_DESTROYING);
+	}
+
+	parent_class->dispose(obj);
+	DEBUG;
+}
+
+static void
+gnt_widget_focus_change(GntWidget *widget)
+{
+	if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED)
+		gnt_widget_draw(widget);
+}
+
+static void
+gnt_widget_class_init(GntWidgetClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	parent_class = g_type_class_peek_parent(klass);
+
+	obj_class->dispose = gnt_widget_dispose;
+
+	klass->destroy = gnt_widget_destroy;
+	klass->show = gnt_widget_show;
+	klass->draw = gnt_widget_draw;
+	klass->expose = gnt_widget_expose;
+	klass->map = gnt_widget_map;
+	klass->lost_focus = gnt_widget_focus_change;
+	klass->gained_focus = gnt_widget_focus_change;
+	
+	klass->key_pressed = NULL;
+	klass->activate = NULL;
+	
+	signals[SIG_DESTROY] = 
+		g_signal_new("destroy",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, destroy),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__VOID,
+					 G_TYPE_NONE, 0);
+	signals[SIG_GIVE_FOCUS] = 
+		g_signal_new("gained-focus",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, gained_focus),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__VOID,
+					 G_TYPE_NONE, 0);
+	signals[SIG_LOST_FOCUS] = 
+		g_signal_new("lost-focus",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, lost_focus),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__VOID,
+					 G_TYPE_NONE, 0);
+	signals[SIG_ACTIVATE] = 
+		g_signal_new("activate",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, activate),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__VOID,
+					 G_TYPE_NONE, 0);
+	signals[SIG_MAP] = 
+		g_signal_new("map",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, map),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__VOID,
+					 G_TYPE_NONE, 0);
+	signals[SIG_DRAW] = 
+		g_signal_new("draw",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, draw),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__VOID,
+					 G_TYPE_NONE, 0);
+	signals[SIG_EXPOSE] = 
+		g_signal_new("expose",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, expose),
+					 NULL, NULL,
+					 gnt_closure_marshal_VOID__INT_INT_INT_INT,
+					 G_TYPE_NONE, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
+	signals[SIG_POSITION] = 
+		g_signal_new("position-set",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, set_position),
+					 NULL, NULL,
+					 gnt_closure_marshal_VOID__INT_INT,
+					 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+	signals[SIG_SIZE_REQUEST] = 
+		g_signal_new("size_request",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, size_request),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__VOID,
+					 G_TYPE_NONE, 0);
+	signals[SIG_KEY_PRESSED] = 
+		g_signal_new("key_pressed",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, key_pressed),
+					 NULL, NULL,
+					 gnt_closure_marshal_BOOLEAN__STRING,
+					 G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
+	DEBUG;
+}
+
+/******************************************************************************
+ * GntWidget API
+ *****************************************************************************/
+GType
+gnt_widget_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(GntWidgetClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_widget_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntWidget),
+			0,						/* n_preallocs		*/
+			gnt_widget_init,					/* instance_init	*/
+		};
+
+		type = g_type_register_static(G_TYPE_OBJECT,
+									  "GntWidget",
+									  &info, G_TYPE_FLAG_ABSTRACT);
+	}
+
+	return type;
+}
+
+static void
+gnt_widget_take_focus(GntWidget *widget)
+{
+	gnt_screen_take_focus(widget);
+}
+
+void gnt_widget_set_take_focus(GntWidget *widget, gboolean can)
+{
+	if (can)
+		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
+	else
+		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
+}
+
+/**
+ * gnt_widget_destroy:
+ * @obj: The #GntWidget instance.
+ *
+ * Emits the "destroy" signal notifying all reference holders that they
+ * should release @obj.
+ */
+void
+gnt_widget_destroy(GntWidget *obj)
+{
+	g_return_if_fail(GNT_IS_WIDGET(obj));
+
+	delwin(obj->window);
+	if(!(GNT_WIDGET_FLAGS(obj) & GNT_WIDGET_DESTROYING))
+		g_object_run_dispose(G_OBJECT(obj));
+	gnt_screen_remove_widget(obj);
+	DEBUG;
+}
+
+void
+gnt_widget_show(GntWidget *widget)
+{
+	/* Draw the widget and take focus */
+	gnt_widget_draw(widget);
+	if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_CAN_TAKE_FOCUS)
+	{
+		gnt_widget_take_focus(widget);
+	}
+}
+
+void
+gnt_widget_draw(GntWidget *widget)
+{
+	/* Draw the widget */
+	DEBUG;
+	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED))
+		gnt_widget_map(widget);
+
+	if (widget->window)
+	{
+		delwin(widget->window);
+	}
+	
+	widget->window = newwin(widget->priv.height, widget->priv.width,
+					widget->priv.y, widget->priv.x);
+	wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL));
+	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER))
+	{
+		box(widget->window, 0, 0);
+	}
+	else
+		werase(widget->window);
+
+	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_SHADOW))
+	{
+		/* XXX: Find out the actual windows beneath this window, and 
+		 * draw the shadow on them */
+		/* XXX: Or perhaps do all these from a psedo-WM! */
+		widget->back = newwin(widget->priv.height, widget->priv.width,
+						widget->priv.y + 1, widget->priv.x + 1);
+		wbkgd(widget->back, COLOR_PAIR(GNT_COLOR_SHADOW));
+		werase(widget->back);
+
+		mvwchgat(widget->back, 0, 0, widget->priv.height,
+					A_REVERSE | A_BLINK, 0, 0);
+		touchline(widget->back, 0, widget->priv.height);
+		wrefresh(widget->back);
+	}
+
+	wrefresh(widget->window);
+	g_signal_emit(widget, signals[SIG_DRAW], 0);
+}
+
+gboolean
+gnt_widget_key_pressed(GntWidget *widget, const char *keys)
+{
+	gboolean ret;
+	g_signal_emit(widget, signals[SIG_KEY_PRESSED], 0, keys, &ret);
+	return ret;
+}
+
+void
+gnt_widget_expose(GntWidget *widget, int x, int y, int width, int height)
+{
+	g_signal_emit(widget, signals[SIG_EXPOSE], 0, x, y, width, height);
+}
+
+void
+gnt_widget_hide(GntWidget *widget)
+{
+	int i;
+
+	/* XXX: Currently it simply empties the window. Ideally, it will
+	 * detect what windows are immediately beneath this one, and cause
+	 * those windows to redraw themselves by emitting the approrpiate
+	 * expose signal. */
+
+	werase(widget->window);
+	wrefresh(widget->window);
+}
+
+void
+gnt_widget_set_position(GntWidget *wid, int x, int y)
+{
+	/* XXX: Need to install properties for these and g_object_notify */
+	wid->priv.x = x;
+	wid->priv.y = y;
+	g_signal_emit(wid, signals[SIG_POSITION], 0, x, y);
+}
+
+void
+gnt_widget_get_position(GntWidget *wid, int *x, int *y)
+{
+	if (x)
+		*x = wid->priv.x;
+	if (y)
+		*y = wid->priv.y;
+}
+
+void
+gnt_widget_size_request(GntWidget *widget)
+{
+	g_signal_emit(widget, signals[SIG_SIZE_REQUEST], 0);
+}
+
+void
+gnt_widget_get_size(GntWidget *wid, int *width, int *height)
+{
+	if (width)
+		*width = wid->priv.width;
+	if (height)
+		*height = wid->priv.height;
+}
+
+void
+gnt_widget_set_size(GntWidget *widget, int width, int height)
+{
+	widget->priv.width = width;
+	widget->priv.height = height;
+}
+
+gboolean
+gnt_widget_set_focus(GntWidget *widget, gboolean set)
+{
+	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_CAN_TAKE_FOCUS))
+		return FALSE;
+
+	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);
+	}
+	else if (!set)
+	{
+		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_HAS_FOCUS);
+		g_signal_emit(widget, signals[SIG_LOST_FOCUS], 0);
+	}
+	else
+		return FALSE;
+
+	return TRUE;
+}
+
+void gnt_widget_set_name(GntWidget *widget, const char *name)
+{
+	g_free(widget->priv.name);
+	widget->priv.name = g_strdup(name);
+}
+
+void gnt_widget_activate(GntWidget *widget)
+{
+	g_signal_emit(widget, signals[SIG_ACTIVATE], 0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/gntwidget.h	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,117 @@
+#ifndef GNT_WIDGET_H
+#define GNT_WIDGET_H
+
+#include <stdio.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <ncursesw/curses.h>
+
+#define GNT_TYPE_WIDGET				(gnt_widget_get_gtype())
+#define GNT_WIDGET(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_WIDGET, GntWidget))
+#define GNT_WIDGET_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_WIDGET, GntWidgetClass))
+#define GNT_IS_WIDGET(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_WIDGET))
+#define GNT_IS_OBJECT_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WIDGET))
+#define GNT_WIDGET_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WIDGET, GntWidgetClass))
+
+#define GNT_WIDGET_FLAGS(obj)				(GNT_WIDGET(obj)->priv.flags)
+#define GNT_WIDGET_SET_FLAGS(obj, flags)		(GNT_WIDGET_FLAGS(obj) |= flags)
+#define GNT_WIDGET_UNSET_FLAGS(obj, flags)	(GNT_WIDGET_FLAGS(obj) &= ~(flags))
+#define GNT_WIDGET_IS_FLAG_SET(obj, flags)	(GNT_WIDGET_FLAGS(obj) & (flags))
+#define	DEBUG
+//#define	DEBUG	printf("%s\n", __FUNCTION__)
+
+typedef struct _GnWidget			GntWidget;
+typedef struct _GnWidgetPriv		GntWidgetPriv;
+typedef struct _GnWidgetClass		GntWidgetClass;
+
+#define	N_(X)	X
+
+typedef enum _GnWidgetFlags
+{
+	GNT_WIDGET_DESTROYING	= 1 << 0,
+	GNT_WIDGET_CAN_TAKE_FOCUS= 1 << 1,
+	GNT_WIDGET_MAPPED 		= 1 << 2,
+	/* XXX: Need to set the following two as properties, and setup a callback whenever these
+	 * get chnaged. */
+	GNT_WIDGET_NO_BORDER		= 1 << 3,
+	GNT_WIDGET_NO_SHADOW		= 1 << 4,
+	GNT_WIDGET_HAS_FOCUS		= 1 << 5
+} GntWidgetFlags;
+
+typedef enum _GnParamFlags
+{
+	GNT_PARAM_SERIALIZABLE	= 1 << G_PARAM_USER_SHIFT
+} GntParamFlags;
+
+struct _GnWidgetPriv
+{
+	int x, y;
+	int width, height;
+	GntWidgetFlags flags;
+	char *name;
+};
+
+struct _GnWidget
+{
+	GObject inherit;
+
+	GntWidget *parent;
+
+	GntWidgetPriv priv;
+	WINDOW *window;
+	WINDOW *back;
+
+    void (*gnt_reserved1)(void);
+    void (*gnt_reserved2)(void);
+    void (*gnt_reserved3)(void);
+    void (*gnt_reserved4)(void);
+};
+
+struct _GnWidgetClass
+{
+	GObjectClass parent;
+
+	void (*map)(GntWidget *obj);
+	void (*show)(GntWidget *obj);		/* This will call draw() and take focus (if it can take focus) */
+	void (*destroy)(GntWidget *obj);
+	void (*draw)(GntWidget *obj);		/* This will draw the widget */
+	void (*expose)(GntWidget *widget, int x, int y, int width, int height);
+	void (*gained_focus)(GntWidget *widget);
+	void (*lost_focus)(GntWidget *widget);
+
+	void (*size_request)(GntWidget *widget);
+	void (*set_position)(GntWidget *widget, int x, int y);
+	gboolean (*key_pressed)(GntWidget *widget, const char *key);
+	void (*activate)(GntWidget *widget);
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_widget_get_gtype(void);
+void gnt_widget_destroy(GntWidget *widget);
+void gnt_widget_show(GntWidget *widget);
+void gnt_widget_draw(GntWidget *widget);
+void gnt_widget_expose(GntWidget *widget, int x, int y, int width, int height);
+void gnt_widget_hide(GntWidget *widget);
+
+void gnt_widget_get_position(GntWidget *widget, int *x, int *y);
+void gnt_widget_set_position(GntWidget *widget, int x, int y);
+void gnt_widget_size_request(GntWidget *widget);
+void gnt_widget_get_size(GntWidget *widget, int *width, int *height);
+void gnt_widget_set_size(GntWidget *widget, int width, int height);
+
+gboolean gnt_widget_key_pressed(GntWidget *widget, const char *keys);
+
+gboolean gnt_widget_set_focus(GntWidget *widget, gboolean set);
+void gnt_widget_activate(GntWidget *widget);
+
+void gnt_widget_set_name(GntWidget *widget, const char *name);
+
+G_END_DECLS
+
+#endif /* GNT_WIDGET_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/libgnt/test.c	Thu Jun 22 08:33:54 2006 +0000
@@ -0,0 +1,112 @@
+#include "gntbutton.h"
+#include "gnt.h"
+#include "gntkeys.h"
+#include "gnttree.h"
+
+static gboolean
+key_pressed(GntWidget *widget, const char *text, gpointer null)
+{
+	GntWidget *w = null;
+
+	gnt_widget_set_focus(w, TRUE);
+
+	/* XXX: This is to just test stuff */
+	if (text[0] == 27)
+	{
+		if (strcmp(text+1, GNT_KEY_LEFT) == 0 && w->priv.x)
+			(w->priv.x)--;
+		else if (strcmp(text+1, GNT_KEY_RIGHT) == 0)
+			(w->priv.x)++;
+		else if (strcmp(text+1, GNT_KEY_UP) == 0 && w->priv.y)
+			(w->priv.y)--;
+		else if (strcmp(text+1, GNT_KEY_DOWN) == 0)
+			(w->priv.y)++;
+	}
+
+	gnt_widget_draw(w);
+
+	return FALSE;
+}
+
+static void
+button1(GntWidget *widget, gpointer null)
+{
+	printf("OLAAA");
+	gnt_widget_destroy(null);
+}
+
+static void
+button2(GntWidget *widget, gpointer null)
+{
+	printf("BOOYAA");
+}
+
+static gboolean
+w_scroll(GntWidget *tree)
+{
+	g_return_val_if_fail(GNT_IS_TREE(tree), FALSE);
+	gnt_tree_scroll(GNT_TREE(tree), 1);
+	/*wscrl(tree->window, 1);*/
+	/*box(tree->window, ACS_VLINE, ACS_HLINE);*/
+	/*wrefresh(tree->window);*/
+	/*char *s = 0;*/
+	/**s = 'a';*/
+	return TRUE;
+}
+
+int main()
+{
+	gnt_init();
+
+	GntWidget *widget = gnt_button_new("Button 1");
+	GntWidget *widget2 = gnt_button_new("Button 2 has a longish text with a UTF-8 thing …");
+	GntWidget *label = gnt_label_new("So wassup dudes and dudettes!!\nSo this is, like,\nthe third line!! \\o/");
+	GntWidget *vbox, *hbox, *tree;
+	WINDOW *test;
+
+	box(stdscr, 0, 0);
+	wrefresh(stdscr);
+
+	vbox = gnt_box_new(FALSE, FALSE);
+	hbox = gnt_box_new(FALSE, TRUE);
+
+	gnt_widget_set_name(vbox, "vbox");
+	gnt_widget_set_name(hbox, "hbox");
+	gnt_widget_set_name(widget, "widget");
+	gnt_widget_set_name(widget2, "widget2");
+
+	gnt_box_add_widget(vbox, widget);
+	gnt_box_add_widget(vbox, widget2);
+
+	gnt_box_add_widget(hbox, label);
+	gnt_box_add_widget(hbox, vbox);
+
+	tree = gnt_tree_new();
+	gnt_box_add_widget(hbox, tree);
+
+	gnt_tree_add_row_after(GNT_TREE(tree), "a", "a", NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "c", "c", NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "d", "d", NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "e", "e", "a", NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "b", "b", "d", NULL);
+
+	GNT_WIDGET_UNSET_FLAGS(hbox, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+	gnt_box_set_title(hbox, "111111111111111111111111111111111111111111111111111111111111111This is the title …");
+
+	/*gnt_widget_set_take_focus(vbox, TRUE);*/
+	/*gnt_widget_set_take_focus(hbox, TRUE);*/
+	gnt_widget_set_position(hbox, 10, 10);
+
+	gnt_widget_show(hbox);
+
+	g_signal_connect(hbox, "key_pressed", G_CALLBACK(key_pressed), widget);
+	g_signal_connect(widget, "activate", G_CALLBACK(button1), hbox);
+	g_signal_connect(widget2, "activate", G_CALLBACK(button2), hbox);
+
+	/*g_timeout_add(1000, (GSourceFunc)w_scroll, tree);*/
+
+	gnt_main();
+
+	return 0;
+}
+