changeset 15818:0e3a8505ebbe

renamed gaim-text to finch
author Sean Egan <seanegan@gmail.com>
date Sun, 18 Mar 2007 19:38:15 +0000
parents 317e7613e581
children bf7d258a26e6 c02a897a67c7
files Makefile.am configure.ac console/Makefile.am console/getopt.c console/getopt.h console/getopt1.c console/gntaccount.c console/gntaccount.h console/gntblist.c console/gntblist.h console/gntconn.c console/gntconn.h console/gntconv.c console/gntconv.h console/gntdebug.c console/gntdebug.h console/gntft.c console/gntft.h console/gntgaim.c console/gntgaim.h console/gntidle.c console/gntidle.h console/gntnotify.c console/gntnotify.h console/gntplugin.c console/gntplugin.h console/gntpounce.c console/gntpounce.h console/gntprefs.c console/gntprefs.h console/gntrequest.c console/gntrequest.h console/gntstatus.c console/gntstatus.h console/gntui.c console/gntui.h console/libgnt/AUTHORS console/libgnt/COPYING console/libgnt/ChangeLog console/libgnt/INSTALL console/libgnt/Makefile.am console/libgnt/NEWS console/libgnt/README console/libgnt/autogen.sh console/libgnt/configure.ac console/libgnt/genmarshal console/libgnt/gnt-skel.c console/libgnt/gnt-skel.h console/libgnt/gnt.h console/libgnt/gnt.pc.in console/libgnt/gntbindable.c console/libgnt/gntbindable.h console/libgnt/gntbox.c console/libgnt/gntbox.h console/libgnt/gntbutton.c console/libgnt/gntbutton.h console/libgnt/gntcheckbox.c console/libgnt/gntcheckbox.h console/libgnt/gntclipboard.c console/libgnt/gntclipboard.h console/libgnt/gntcolors.c console/libgnt/gntcolors.h console/libgnt/gntcombobox.c console/libgnt/gntcombobox.h console/libgnt/gntentry.c console/libgnt/gntentry.h console/libgnt/gntkeys.c console/libgnt/gntkeys.h console/libgnt/gntlabel.c console/libgnt/gntlabel.h console/libgnt/gntline.c console/libgnt/gntline.h console/libgnt/gntmain.c console/libgnt/gntmenu.c console/libgnt/gntmenu.h console/libgnt/gntmenuitem.c console/libgnt/gntmenuitem.h console/libgnt/gntmenuitemcheck.c console/libgnt/gntmenuitemcheck.h console/libgnt/gntrc.sample console/libgnt/gntstyle.c console/libgnt/gntstyle.h console/libgnt/gnttextview.c console/libgnt/gnttextview.h 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/gntwindow.c console/libgnt/gntwindow.h console/libgnt/gntwm.c console/libgnt/gntwm.h console/libgnt/test.c console/libgnt/test/Makefile console/libgnt/test/combo.c console/libgnt/test/focus.c console/libgnt/test/key.c console/libgnt/test/keys.c console/libgnt/test/menu.c console/libgnt/test/multiwin.c console/libgnt/test/tv.c console/libgnt/test/wm.c console/libgnt/wms/Makefile.am console/libgnt/wms/s.c console/plugins/Makefile.am console/plugins/gntclipboard.c console/plugins/gntgf.c console/plugins/gnthistory.c console/plugins/lastlog.c finch/Makefile.am finch/getopt.c finch/getopt.h finch/getopt1.c finch/gntaccount.c finch/gntaccount.h finch/gntblist.c finch/gntblist.h finch/gntconn.c finch/gntconn.h finch/gntconv.c finch/gntconv.h finch/gntdebug.c finch/gntdebug.h finch/gntft.c finch/gntft.h finch/gntgaim.c finch/gntgaim.h finch/gntidle.c finch/gntidle.h finch/gntnotify.c finch/gntnotify.h finch/gntplugin.c finch/gntplugin.h finch/gntpounce.c finch/gntpounce.h finch/gntprefs.c finch/gntprefs.h finch/gntrequest.c finch/gntrequest.h finch/gntstatus.c finch/gntstatus.h finch/gntui.c finch/gntui.h finch/libgnt/AUTHORS finch/libgnt/COPYING finch/libgnt/ChangeLog finch/libgnt/INSTALL finch/libgnt/Makefile.am finch/libgnt/NEWS finch/libgnt/README finch/libgnt/autogen.sh finch/libgnt/configure.ac finch/libgnt/genmarshal finch/libgnt/gnt-skel.c finch/libgnt/gnt-skel.h finch/libgnt/gnt.h finch/libgnt/gnt.pc.in finch/libgnt/gntbindable.c finch/libgnt/gntbindable.h finch/libgnt/gntbox.c finch/libgnt/gntbox.h finch/libgnt/gntbutton.c finch/libgnt/gntbutton.h finch/libgnt/gntcheckbox.c finch/libgnt/gntcheckbox.h finch/libgnt/gntclipboard.c finch/libgnt/gntclipboard.h finch/libgnt/gntcolors.c finch/libgnt/gntcolors.h finch/libgnt/gntcombobox.c finch/libgnt/gntcombobox.h finch/libgnt/gntentry.c finch/libgnt/gntentry.h finch/libgnt/gntkeys.c finch/libgnt/gntkeys.h finch/libgnt/gntlabel.c finch/libgnt/gntlabel.h finch/libgnt/gntline.c finch/libgnt/gntline.h finch/libgnt/gntmain.c finch/libgnt/gntmenu.c finch/libgnt/gntmenu.h finch/libgnt/gntmenuitem.c finch/libgnt/gntmenuitem.h finch/libgnt/gntmenuitemcheck.c finch/libgnt/gntmenuitemcheck.h finch/libgnt/gntrc.sample finch/libgnt/gntstyle.c finch/libgnt/gntstyle.h finch/libgnt/gnttextview.c finch/libgnt/gnttextview.h finch/libgnt/gnttree.c finch/libgnt/gnttree.h finch/libgnt/gntutils.c finch/libgnt/gntutils.h finch/libgnt/gntwidget.c finch/libgnt/gntwidget.h finch/libgnt/gntwindow.c finch/libgnt/gntwindow.h finch/libgnt/gntwm.c finch/libgnt/gntwm.h finch/libgnt/test.c finch/libgnt/test/Makefile finch/libgnt/test/combo.c finch/libgnt/test/focus.c finch/libgnt/test/key.c finch/libgnt/test/keys.c finch/libgnt/test/menu.c finch/libgnt/test/multiwin.c finch/libgnt/test/tv.c finch/libgnt/test/wm.c finch/libgnt/wms/Makefile.am finch/libgnt/wms/s.c finch/plugins/Makefile.am finch/plugins/gntclipboard.c finch/plugins/gntgf.c finch/plugins/gnthistory.c finch/plugins/lastlog.c po/ta.po
diffstat 213 files changed, 24646 insertions(+), 24646 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Sun Mar 18 18:17:14 2007 +0000
+++ b/Makefile.am	Sun Mar 18 19:38:15 2007 +0000
@@ -48,7 +48,7 @@
 endif
 
 if ENABLE_GNT
-GNT_DIR=console
+GNT_DIR=finch
 endif
 
 SUBDIRS = libpurple doc $(GNT_DIR) $(GTK_DIR) m4macros po
--- a/configure.ac	Sun Mar 18 18:17:14 2007 +0000
+++ b/configure.ac	Sun Mar 18 19:38:15 2007 +0000
@@ -1983,11 +1983,11 @@
 		   libpurple/protocols/yahoo/Makefile
 		   libpurple/protocols/zephyr/Makefile
 		   libpurple/tests/Makefile
-		   console/Makefile
-		   console/libgnt/Makefile
-		   console/libgnt/gnt.pc
-		   console/libgnt/wms/Makefile
-		   console/plugins/Makefile
+		   finch/Makefile
+		   finch/libgnt/Makefile
+		   finch/libgnt/gnt.pc
+		   finch/libgnt/wms/Makefile
+		   finch/plugins/Makefile
 		   po/Makefile.in
 		   gaim.pc
 		   gaim-uninstalled.pc
--- a/console/Makefile.am	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-if ENABLE_GNT
-
-EXTRA_DIST = \
-		getopt.c \
-		getopt.h \
-		getopt1.c
-
-SUBDIRS = libgnt plugins
-
-bin_PROGRAMS = gaim-text
-
-gaim_text_SOURCES = \
-	gntaccount.c \
-	gntblist.c \
-	gntconn.c \
-	gntconv.c \
-	gntdebug.c \
-	gntft.c \
-	gntgaim.c \
-	gntidle.c \
-	gntnotify.c \
-	gntplugin.c \
-	gntpounce.c \
-	gntprefs.c \
-	gntrequest.c \
-	gntstatus.c \
-	gntui.c
-
-gaim_text_headers = \
-	gntaccount.h \
-	gntblist.h \
-	gntconn.h \
-	gntconv.h \
-	gntdebug.h \
-	gntft.h \
-	gntgaim.h \
-	gntidle.h \
-	gntnotify.h \
-	gntplugin.h \
-	gntpounce.h \
-	gntprefs.h \
-	gntrequest.h \
-	gntstatus.h \
-	gntui.h
-
-gaim_textincludedir=$(includedir)/gaim/gnt
-gaim_textinclude_HEADERS = \
-	$(gaim_text_headers)
-
-gaim_text_DEPENDENCIES = @LIBOBJS@
-gaim_text_LDFLAGS = -export-dynamic
-gaim_text_LDADD = \
-	@LIBOBJS@ \
-	$(DBUS_LIBS) \
-	$(INTLLIBS) \
-	$(GLIB_LIBS) \
-	$(LIBXML_LIBS) \
-	$(GNT_LIBS) \
-	./libgnt/libgnt.la \
-	$(top_builddir)/libpurple/libpurple.la
-
-AM_CPPFLAGS = \
-	-DSTANDALONE \
-	-DBR_PTHREADS=0 \
-	-DDATADIR=\"$(datadir)\" \
-	-DLIBDIR=\"$(libdir)/gaim/\" \
-	-DLOCALEDIR=\"$(datadir)/locale\" \
-	-DSYSCONFDIR=\"$(sysconfdir)\" \
-	-I$(top_srcdir)/libpurple/ \
-	-I$(top_srcdir) \
-	-I$(srcdir)/libgnt/ \
-	$(DEBUG_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(DBUS_CFLAGS) \
-	$(LIBXML_CFLAGS) \
-	$(GNT_CFLAGS)
-endif
--- a/console/getopt.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,737 +0,0 @@
-/* Getopt for GNU.
-   NOTE: getopt is now part of the C library, so if you don't know what
-   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
-   before changing it!
-
-   Gaim is the legal property of its developers, whose names are too numerous
-   to list here.  Please refer to the COPYRIGHT file distributed with this
-   source distribution.
-
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any
-   later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-/* NOTE!!!  AIX requires this to be the first thing in the file.
-   Do not put ANYTHING before it!  */
-#if !defined (__GNUC__) && defined (_AIX)
- #pragma alloca
-#endif
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* Alver says we need this for IRIX. */
-#if HAVE_STRING_H
-#include "string.h"
-#endif
-
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#else /* not __GNUC__ */
-#if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__))))
-#include <alloca.h>
-#else
-#ifndef _AIX
-char *alloca ();
-#endif
-#endif /* alloca.h */
-#endif /* not __GNUC__ */
-
-#if !__STDC__ && !defined(const) && IN_GCC
-#define const
-#endif
-
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.  */
-#ifndef _NO_PROTO
-#define _NO_PROTO
-#endif
-
-#include <stdio.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself.  This code is part of the GNU C
-   Library, but also included in many other GNU distributions.  Compiling
-   and linking in this code is a waste when using the GNU C library
-   (especially if it is a shared library).  Rather than having every GNU
-   program understand `configure --with-gnu-libc' and omit the object files,
-   it is simpler to just do this in the source for each such file.  */
-
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
-
-
-/* This needs to come after some library #include
-   to get __GNU_LIBRARY__ defined.  */
-#ifdef	__GNU_LIBRARY__
-#undef	alloca
-/* Don't include stdlib.h for non-GNU C libraries because some of them
-   contain conflicting prototypes for getopt.  */
-#include <stdlib.h>
-#else	/* Not GNU C library.  */
-#define	__alloca	alloca
-#endif	/* GNU C library.  */
-
-/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
-   long-named option.  Because this is not POSIX.2 compliant, it is
-   being phased out.  */
-/* #define GETOPT_COMPAT */
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
-   but it behaves differently for the user, since it allows the user
-   to intersperse the options with the other arguments.
-
-   As `getopt' works, it permutes the elements of ARGV so that,
-   when it is done, all the options precede everything else.  Thus
-   all application programs are extended to handle flexible argument order.
-
-   Setting the environment variable POSIXLY_CORRECT disables permutation.
-   Then the behavior is completely standard.
-
-   GNU application programs can use a third alternative mode in which
-   they can distinguish the relative order of options and other arguments.  */
-
-#include "getopt.h"
-
-/* For communication from `getopt' to the caller.
-   When `getopt' finds an option that takes an argument,
-   the argument value is returned here.
-   Also, when `ordering' is RETURN_IN_ORDER,
-   each non-option ARGV-element is returned here.  */
-
-char *optarg = 0;
-
-/* Index in ARGV of the next element to be scanned.
-   This is used for communication to and from the caller
-   and for communication between successive calls to `getopt'.
-
-   On entry to `getopt', zero means this is the first call; initialize.
-
-   When `getopt' returns EOF, this is the index of the first of the
-   non-option elements that the caller should itself scan.
-
-   Otherwise, `optind' communicates from one call to the next
-   how much of ARGV has been scanned so far.  */
-
-/* XXX 1003.2 says this must be 1 before any call.  */
-int optind = 0;
-
-/* The next char to be scanned in the option-element
-   in which the last option character we returned was found.
-   This allows us to pick up the scan where we left off.
-
-   If this is zero, or a null string, it means resume the scan
-   by advancing to the next ARGV-element.  */
-
-static char *nextchar;
-
-/* Callers store zero here to inhibit the error message
-   for unrecognized options.  */
-
-int opterr = 1;
-
-/* Set to an option character which was unrecognized.
-   This must be initialized on some systems to avoid linking in the
-   system's own getopt implementation.  */
-
-int optopt = '?';
-
-/* Describe how to deal with options that follow non-option ARGV-elements.
-
-   If the caller did not specify anything,
-   the default is REQUIRE_ORDER if the environment variable
-   POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
-   REQUIRE_ORDER means don't recognize them as options;
-   stop option processing when the first non-option is seen.
-   This is what Unix does.
-   This mode of operation is selected by either setting the environment
-   variable POSIXLY_CORRECT, or using `+' as the first character
-   of the list of option characters.
-
-   PERMUTE is the default.  We permute the contents of ARGV as we scan,
-   so that eventually all the non-options are at the end.  This allows options
-   to be given in any order, even with programs that were not written to
-   expect this.
-
-   RETURN_IN_ORDER is an option available to programs that were written
-   to expect options and other ARGV-elements in any order and that care about
-   the ordering of the two.  We describe each non-option ARGV-element
-   as if it were the argument of an option with character code 1.
-   Using `-' as the first character of the list of option characters
-   selects this mode of operation.
-
-   The special argument `--' forces an end of option-scanning regardless
-   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
-   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
-
-static enum
-{
-  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-} ordering;
-
-#ifdef	__GNU_LIBRARY__
-/* We want to avoid inclusion of string.h with non-GNU libraries
-   because there are many ways it can cause trouble.
-   On some systems, it contains special magic macros that don't work
-   in GCC.  */
-#include <string.h>
-#define	my_index	strchr
-#define	my_bcopy(src, dst, n)	memcpy ((dst), (src), (n))
-#else
-
-/* Avoid depending on library functions or files
-   whose names are inconsistent.  */
-
-char *getenv ();
-
-static char *
-my_index (str, chr)
-     const char *str;
-     int chr;
-{
-  while (*str)
-    {
-      if (*str == chr)
-	return (char *) str;
-      str++;
-    }
-  return 0;
-}
-
-static void
-my_bcopy (from, to, size)
-     const char *from;
-     char *to;
-     int size;
-{
-  int i;
-  for (i = 0; i < size; i++)
-    to[i] = from[i];
-}
-#endif				/* GNU C library.  */
-
-/* Handle permutation of arguments.  */
-
-/* Describe the part of ARGV that contains non-options that have
-   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
-   `last_nonopt' is the index after the last of them.  */
-
-static int first_nonopt;
-static int last_nonopt;
-
-/* Exchange two adjacent subsequences of ARGV.
-   One subsequence is elements [first_nonopt,last_nonopt)
-   which contains all the non-options that have been skipped so far.
-   The other is elements [last_nonopt,optind), which contains all
-   the options processed since those non-options were skipped.
-
-   `first_nonopt' and `last_nonopt' are relocated so that they describe
-   the new indices of the non-options in ARGV after they are moved.  */
-
-static void
-exchange (argv)
-     char **argv;
-{
-  int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
-  char **temp = (char **) __alloca (nonopts_size);
-
-  /* Interchange the two blocks of data in ARGV.  */
-
-  my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size);
-  my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt],
-	    (optind - last_nonopt) * sizeof (char *));
-  my_bcopy ((char *) temp,
-	    (char *) &argv[first_nonopt + optind - last_nonopt],
-	    nonopts_size);
-
-  /* Update records for the slots the non-options now occupy.  */
-
-  first_nonopt += (optind - last_nonopt);
-  last_nonopt = optind;
-}
-
-/* Scan elements of ARGV (whose length is ARGC) for option characters
-   given in OPTSTRING.
-
-   If an element of ARGV starts with '-', and is not exactly "-" or "--",
-   then it is an option element.  The characters of this element
-   (aside from the initial '-') are option characters.  If `getopt'
-   is called repeatedly, it returns successively each of the option characters
-   from each of the option elements.
-
-   If `getopt' finds another option character, it returns that character,
-   updating `optind' and `nextchar' so that the next call to `getopt' can
-   resume the scan with the following option character or ARGV-element.
-
-   If there are no more option characters, `getopt' returns `EOF'.
-   Then `optind' is the index in ARGV of the first ARGV-element
-   that is not an option.  (The ARGV-elements have been permuted
-   so that those that are not options now come last.)
-
-   OPTSTRING is a string containing the legitimate option characters.
-   If an option character is seen that is not listed in OPTSTRING,
-   return '?' after printing an error message.  If you set `opterr' to
-   zero, the error message is suppressed but we still return '?'.
-
-   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
-   so the following text in the same ARGV-element, or the text of the following
-   ARGV-element, is returned in `optarg'.  Two colons mean an option that
-   wants an optional arg; if there is text in the current ARGV-element,
-   it is returned in `optarg', otherwise `optarg' is set to zero.
-
-   If OPTSTRING starts with `-' or `+', it requests different methods of
-   handling the non-option ARGV-elements.
-   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
-   Long-named options begin with `--' instead of `-'.
-   Their names may be abbreviated as long as the abbreviation is unique
-   or is an exact match for some defined option.  If they have an
-   argument, it follows the option name in the same ARGV-element, separated
-   from the option name by a `=', or else the in next ARGV-element.
-   When `getopt' finds a long-named option, it returns 0 if that option's
-   `flag' field is nonzero, the value of the option's `val' field
-   if the `flag' field is zero.
-
-   The elements of ARGV aren't really const, because we permute them.
-   But we pretend they're const in the prototype to be compatible
-   with other systems.
-
-   LONGOPTS is a vector of `struct option' terminated by an
-   element containing a name which is zero.
-
-   LONGIND returns the index in LONGOPT of the long-named option found.
-   It is only valid when a long-named option has been found by the most
-   recent call.
-
-   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
-   long-named options.  */
-
-int
-_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
-     int argc;
-     char *const *argv;
-     const char *optstring;
-     const struct option *longopts;
-     int *longind;
-     int long_only;
-{
-  int option_index;
-
-  optarg = 0;
-
-  /* Initialize the internal data when the first call is made.
-     Start processing options with ARGV-element 1 (since ARGV-element 0
-     is the program name); the sequence of previously skipped
-     non-option ARGV-elements is empty.  */
-
-  if (optind == 0)
-    {
-      first_nonopt = last_nonopt = optind = 1;
-
-      nextchar = NULL;
-
-      /* Determine how to handle the ordering of options and nonoptions.  */
-
-      if (optstring[0] == '-')
-	{
-	  ordering = RETURN_IN_ORDER;
-	  ++optstring;
-	}
-      else if (optstring[0] == '+')
-	{
-	  ordering = REQUIRE_ORDER;
-	  ++optstring;
-	}
-      else if (getenv ("POSIXLY_CORRECT") != NULL)
-	ordering = REQUIRE_ORDER;
-      else
-	ordering = PERMUTE;
-    }
-
-  if (nextchar == NULL || *nextchar == '\0')
-    {
-      if (ordering == PERMUTE)
-	{
-	  /* If we have just processed some options following some non-options,
-	     exchange them so that the options come first.  */
-
-	  if (first_nonopt != last_nonopt && last_nonopt != optind)
-	    exchange ((char **) argv);
-	  else if (last_nonopt != optind)
-	    first_nonopt = optind;
-
-	  /* Now skip any additional non-options
-	     and extend the range of non-options previously skipped.  */
-
-	  while (optind < argc
-		 && (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
-		 && (longopts == NULL
-		     || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif				/* GETOPT_COMPAT */
-		 )
-	    optind++;
-	  last_nonopt = optind;
-	}
-
-      /* Special ARGV-element `--' means premature end of options.
-	 Skip it like a null option,
-	 then exchange with previous non-options as if it were an option,
-	 then skip everything else like a non-option.  */
-
-      if (optind != argc && !strcmp (argv[optind], "--"))
-	{
-	  optind++;
-
-	  if (first_nonopt != last_nonopt && last_nonopt != optind)
-	    exchange ((char **) argv);
-	  else if (first_nonopt == last_nonopt)
-	    first_nonopt = optind;
-	  last_nonopt = argc;
-
-	  optind = argc;
-	}
-
-      /* If we have done all the ARGV-elements, stop the scan
-	 and back over any non-options that we skipped and permuted.  */
-
-      if (optind == argc)
-	{
-	  /* Set the next-arg-index to point at the non-options
-	     that we previously skipped, so the caller will digest them.  */
-	  if (first_nonopt != last_nonopt)
-	    optind = first_nonopt;
-	  return EOF;
-	}
-
-      /* If we have come to a non-option and did not permute it,
-	 either stop the scan or describe it to the caller and pass it by.  */
-
-      if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
-	  && (longopts == NULL
-	      || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif				/* GETOPT_COMPAT */
-	  )
-	{
-	  if (ordering == REQUIRE_ORDER)
-	    return EOF;
-	  optarg = argv[optind++];
-	  return 1;
-	}
-
-      /* We have found another option-ARGV-element.
-	 Start decoding its characters.  */
-
-      nextchar = (argv[optind] + 1
-		  + (longopts != NULL && argv[optind][1] == '-'));
-    }
-
-  if (longopts != NULL
-      && ((argv[optind][0] == '-'
-	   && (argv[optind][1] == '-' || long_only))
-#ifdef GETOPT_COMPAT
-	  || argv[optind][0] == '+'
-#endif				/* GETOPT_COMPAT */
-	  ))
-    {
-      const struct option *p;
-      char *s = nextchar;
-      int exact = 0;
-      int ambig = 0;
-      const struct option *pfound = NULL;
-      int indfound;
-
-      while (*s && *s != '=')
-	s++;
-
-      /* Test all options for either exact match or abbreviated matches.  */
-      for (p = longopts, option_index = 0; p->name;
-	   p++, option_index++)
-	if (!strncmp (p->name, nextchar, s - nextchar))
-	  {
-	    if (s - nextchar == strlen (p->name))
-	      {
-		/* Exact match found.  */
-		pfound = p;
-		indfound = option_index;
-		exact = 1;
-		break;
-	      }
-	    else if (pfound == NULL)
-	      {
-		/* First nonexact match found.  */
-		pfound = p;
-		indfound = option_index;
-	      }
-	    else
-	      /* Second nonexact match found.  */
-	      ambig = 1;
-	  }
-
-      if (ambig && !exact)
-	{
-	  if (opterr)
-	    fprintf (stderr, "%s: option `%s' is ambiguous\n",
-		     argv[0], argv[optind]);
-	  nextchar += strlen (nextchar);
-	  optind++;
-	  return '?';
-	}
-
-      if (pfound != NULL)
-	{
-	  option_index = indfound;
-	  optind++;
-	  if (*s)
-	    {
-	      /* Don't test has_arg with >, because some C compilers don't
-		 allow it to be used on enums.  */
-	      if (pfound->has_arg)
-		optarg = s + 1;
-	      else
-		{
-		  if (opterr)
-		    {
-		      if (argv[optind - 1][1] == '-')
-			/* --option */
-			fprintf (stderr,
-				 "%s: option `--%s' doesn't allow an argument\n",
-				 argv[0], pfound->name);
-		      else
-			/* +option or -option */
-			fprintf (stderr,
-			     "%s: option `%c%s' doesn't allow an argument\n",
-			     argv[0], argv[optind - 1][0], pfound->name);
-		    }
-		  nextchar += strlen (nextchar);
-		  return '?';
-		}
-	    }
-	  else if (pfound->has_arg == 1)
-	    {
-	      if (optind < argc)
-		optarg = argv[optind++];
-	      else
-		{
-		  if (opterr)
-		    fprintf (stderr, "%s: option `%s' requires an argument\n",
-			     argv[0], argv[optind - 1]);
-		  nextchar += strlen (nextchar);
-		  return optstring[0] == ':' ? ':' : '?';
-		}
-	    }
-	  nextchar += strlen (nextchar);
-	  if (longind != NULL)
-	    *longind = option_index;
-	  if (pfound->flag)
-	    {
-	      *(pfound->flag) = pfound->val;
-	      return 0;
-	    }
-	  return pfound->val;
-	}
-      /* Can't find it as a long option.  If this is not getopt_long_only,
-	 or the option starts with '--' or is not a valid short
-	 option, then it's an error.
-	 Otherwise interpret it as a short option.  */
-      if (!long_only || argv[optind][1] == '-'
-#ifdef GETOPT_COMPAT
-	  || argv[optind][0] == '+'
-#endif				/* GETOPT_COMPAT */
-	  || my_index (optstring, *nextchar) == NULL)
-	{
-	  if (opterr)
-	    {
-	      if (argv[optind][1] == '-')
-		/* --option */
-		fprintf (stderr, "%s: unrecognized option `--%s'\n",
-			 argv[0], nextchar);
-	      else
-		/* +option or -option */
-		fprintf (stderr, "%s: unrecognized option `%c%s'\n",
-			 argv[0], argv[optind][0], nextchar);
-	    }
-	  nextchar = (char *) "";
-	  optind++;
-	  return '?';
-	}
-    }
-
-  /* Look at and handle the next option-character.  */
-
-  {
-    char c = *nextchar++;
-    char *temp = my_index (optstring, c);
-
-    /* Increment `optind' when we start to process its last character.  */
-    if (*nextchar == '\0')
-      ++optind;
-
-    if (temp == NULL || c == ':')
-      {
-	if (opterr)
-	  {
-#if 0
-	    if (c < 040 || c >= 0177)
-	      fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
-		       argv[0], c);
-	    else
-	      fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
-#else
-	    /* 1003.2 specifies the format of this message.  */
-	    fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
-#endif
-	  }
-	optopt = c;
-	return '?';
-      }
-    if (temp[1] == ':')
-      {
-	if (temp[2] == ':')
-	  {
-	    /* This is an option that accepts an argument optionally.  */
-	    if (*nextchar != '\0')
-	      {
-		optarg = nextchar;
-		optind++;
-	      }
-	    else
-	      optarg = 0;
-	    nextchar = NULL;
-	  }
-	else
-	  {
-	    /* This is an option that requires an argument.  */
-	    if (*nextchar != '\0')
-	      {
-		optarg = nextchar;
-		/* If we end this ARGV-element by taking the rest as an arg,
-		   we must advance to the next element now.  */
-		optind++;
-	      }
-	    else if (optind == argc)
-	      {
-		if (opterr)
-		  {
-#if 0
-		    fprintf (stderr, "%s: option `-%c' requires an argument\n",
-			     argv[0], c);
-#else
-		    /* 1003.2 specifies the format of this message.  */
-		    fprintf (stderr, "%s: option requires an argument -- %c\n",
-			     argv[0], c);
-#endif
-		  }
-		optopt = c;
-		if (optstring[0] == ':')
-		  c = ':';
-		else
-		  c = '?';
-	      }
-	    else
-	      /* We already incremented `optind' once;
-		 increment it again when taking next ARGV-elt as argument.  */
-	      optarg = argv[optind++];
-	    nextchar = NULL;
-	  }
-      }
-    return c;
-  }
-}
-
-int
-getopt (argc, argv, optstring)
-     int argc;
-     char *const *argv;
-     const char *optstring;
-{
-  return _getopt_internal (argc, argv, optstring,
-			   (const struct option *) 0,
-			   (int *) 0,
-			   0);
-}
-
-#endif	/* _LIBC or not __GNU_LIBRARY__.  */
-
-#ifdef TEST
-
-/* Compile with -DTEST to make an executable for use in testing
-   the above definition of `getopt'.  */
-
-int
-main (argc, argv)
-     int argc;
-     char **argv;
-{
-  int c;
-  int digit_optind = 0;
-
-  while (1)
-    {
-      int this_option_optind = optind ? optind : 1;
-
-      c = getopt (argc, argv, "abc:d:0123456789");
-      if (c == EOF)
-	break;
-
-      switch (c)
-	{
-	case '0':
-	case '1':
-	case '2':
-	case '3':
-	case '4':
-	case '5':
-	case '6':
-	case '7':
-	case '8':
-	case '9':
-	  if (digit_optind != 0 && digit_optind != this_option_optind)
-	    printf ("digits occur in two different argv-elements.\n");
-	  digit_optind = this_option_optind;
-	  printf ("option %c\n", c);
-	  break;
-
-	case 'a':
-	  printf ("option a\n");
-	  break;
-
-	case 'b':
-	  printf ("option b\n");
-	  break;
-
-	case 'c':
-	  printf ("option c with value `%s'\n", optarg);
-	  break;
-
-	case '?':
-	  break;
-
-	default:
-	  printf ("?? getopt returned character code 0%o ??\n", c);
-	}
-    }
-
-  if (optind < argc)
-    {
-      printf ("non-option ARGV-elements: ");
-      while (optind < argc)
-	printf ("%s ", argv[optind++]);
-      printf ("\n");
-    }
-
-  exit (0);
-}
-
-#endif /* TEST */
--- a/console/getopt.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/* Declarations for getopt.
-
-   NOTE: getopt is now part of the C library, so if you don't know what
-   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
-   before changing it!
-
-   Gaim is the legal property of its developers, whose names are too numerous
-   to list here.  Please refer to the COPYRIGHT file distributed with this
-   source distribution.
-
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any
-   later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-#ifndef _GETOPT_H
-#define _GETOPT_H 1
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/* For communication from `getopt' to the caller.
-   When `getopt' finds an option that takes an argument,
-   the argument value is returned here.
-   Also, when `ordering' is RETURN_IN_ORDER,
-   each non-option ARGV-element is returned here.  */
-
-extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
-   This is used for communication to and from the caller
-   and for communication between successive calls to `getopt'.
-
-   On entry to `getopt', zero means this is the first call; initialize.
-
-   When `getopt' returns EOF, this is the index of the first of the
-   non-option elements that the caller should itself scan.
-
-   Otherwise, `optind' communicates from one call to the next
-   how much of ARGV has been scanned so far.  */
-
-extern int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
-   for unrecognized options.  */
-
-extern int opterr;
-
-/* Set to an option character which was unrecognized.  */
-
-extern int optopt;
-
-/* Describe the long-named options requested by the application.
-   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
-   of `struct option' terminated by an element containing a name which is
-   zero.
-
-   The field `has_arg' is:
-   no_argument		(or 0) if the option does not take an argument,
-   required_argument	(or 1) if the option requires an argument,
-   optional_argument 	(or 2) if the option takes an optional argument.
-
-   If the field `flag' is not NULL, it points to a variable that is set
-   to the value given in the field `val' when the option is found, but
-   left unchanged if the option is not found.
-
-   To have a long-named option do something other than set an `int' to
-   a compiled-in constant, such as set a value from `optarg', set the
-   option's `flag' field to zero and its `val' field to a nonzero
-   value (the equivalent single-letter option character, if there is
-   one).  For long options that have a zero `flag' field, `getopt'
-   returns the contents of the `val' field.  */
-
-struct option
-{
-#if	__STDC__
-  const char *name;
-#else
-  char *name;
-#endif
-  /* has_arg can't be an enum because some compilers complain about
-     type mismatches in all the code that assumes it is an int.  */
-  int has_arg;
-  int *flag;
-  int val;
-};
-
-/* Names for the values of the `has_arg' field of `struct option'.  */
-
-#define	no_argument		0
-#define required_argument	1
-#define optional_argument	2
-
-#if __STDC__
-#if defined(__GNU_LIBRARY__)
-/* Many other libraries have conflicting prototypes for getopt, with
-   differences in the consts, in stdlib.h.  To avoid compilation
-   errors, only prototype getopt for the GNU C library.  */
-extern int getopt (int argc, char *const *argv, const char *shortopts);
-#else /* not __GNU_LIBRARY__ */
-extern int getopt ();
-#endif /* not __GNU_LIBRARY__ */
-extern int getopt_long (int argc, char *const *argv, const char *shortopts,
-		        const struct option *longopts, int *longind);
-extern int getopt_long_only (int argc, char *const *argv,
-			     const char *shortopts,
-		             const struct option *longopts, int *longind);
-
-/* Internal only.  Users should not call this directly.  */
-extern int _getopt_internal (int argc, char *const *argv,
-			     const char *shortopts,
-		             const struct option *longopts, int *longind,
-			     int long_only);
-#else /* not __STDC__ */
-extern int getopt ();
-extern int getopt_long ();
-extern int getopt_long_only ();
-
-extern int _getopt_internal ();
-#endif /* not __STDC__ */
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif /* _GETOPT_H */
--- a/console/getopt1.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/* getopt_long and getopt_long_only entry points for GNU getopt.
-   Gaim is the legal property of its developers, whose names are too numerous
-   to list here.  Please refer to the COPYRIGHT file distributed with this
-   source distribution.
-
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any
-   later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "getopt.h"
-
-#if !__STDC__ && !defined(const) && IN_GCC
-#define const
-#endif
-
-#include <stdio.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself.  This code is part of the GNU C
-   Library, but also included in many other GNU distributions.  Compiling
-   and linking in this code is a waste when using the GNU C library
-   (especially if it is a shared library).  Rather than having every GNU
-   program understand `configure --with-gnu-libc' and omit the object files,
-   it is simpler to just do this in the source for each such file.  */
-
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
-
-
-/* This needs to come after some library #include
-   to get __GNU_LIBRARY__ defined.  */
-#ifdef __GNU_LIBRARY__
-#include <stdlib.h>
-#else
-char *getenv ();
-#endif
-
-#ifndef	NULL
-#define NULL 0
-#endif
-
-int
-getopt_long (argc, argv, options, long_options, opt_index)
-     int argc;
-     char *const *argv;
-     const char *options;
-     const struct option *long_options;
-     int *opt_index;
-{
-  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
-}
-
-/* Like getopt_long, but '-' as well as '--' can indicate a long option.
-   If an option that starts with '-' (not '--') doesn't match a long option,
-   but does match a short option, it is parsed as a short option
-   instead.  */
-
-int
-getopt_long_only (argc, argv, options, long_options, opt_index)
-     int argc;
-     char *const *argv;
-     const char *options;
-     const struct option *long_options;
-     int *opt_index;
-{
-  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
-}
-
-
-#endif	/* _LIBC or not __GNU_LIBRARY__.  */
-
-#ifdef TEST
-
-#include <stdio.h>
-
-int
-main (argc, argv)
-     int argc;
-     char **argv;
-{
-  int c;
-  int digit_optind = 0;
-
-  while (1)
-    {
-      int this_option_optind = optind ? optind : 1;
-      int option_index = 0;
-      static struct option long_options[] =
-      {
-	{"add", 1, 0, 0},
-	{"append", 0, 0, 0},
-	{"delete", 1, 0, 0},
-	{"verbose", 0, 0, 0},
-	{"create", 0, 0, 0},
-	{"file", 1, 0, 0},
-	{0, 0, 0, 0}
-      };
-
-      c = getopt_long (argc, argv, "abc:d:0123456789",
-		       long_options, &option_index);
-      if (c == EOF)
-	break;
-
-      switch (c)
-	{
-	case 0:
-	  printf ("option %s", long_options[option_index].name);
-	  if (optarg)
-	    printf (" with arg %s", optarg);
-	  printf ("\n");
-	  break;
-
-	case '0':
-	case '1':
-	case '2':
-	case '3':
-	case '4':
-	case '5':
-	case '6':
-	case '7':
-	case '8':
-	case '9':
-	  if (digit_optind != 0 && digit_optind != this_option_optind)
-	    printf ("digits occur in two different argv-elements.\n");
-	  digit_optind = this_option_optind;
-	  printf ("option %c\n", c);
-	  break;
-
-	case 'a':
-	  printf ("option a\n");
-	  break;
-
-	case 'b':
-	  printf ("option b\n");
-	  break;
-
-	case 'c':
-	  printf ("option c with value `%s'\n", optarg);
-	  break;
-
-	case 'd':
-	  printf ("option d with value `%s'\n", optarg);
-	  break;
-
-	case '?':
-	  break;
-
-	default:
-	  printf ("?? getopt returned character code 0%o ??\n", c);
-	}
-    }
-
-  if (optind < argc)
-    {
-      printf ("non-option ARGV-elements: ");
-      while (optind < argc)
-	printf ("%s ", argv[optind++]);
-      printf ("\n");
-    }
-
-  exit (0);
-}
-
-#endif /* TEST */
--- a/console/gntaccount.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,936 +0,0 @@
-/**
- * @file gntaccount.c GNT Account API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntbutton.h>
-#include <gntcheckbox.h>
-#include <gntcombobox.h>
-#include <gntentry.h>
-#include <gntlabel.h>
-#include <gntline.h>
-#include <gnttree.h>
-
-#include <account.h>
-#include <accountopt.h>
-#include <connection.h>
-#include <notify.h>
-#include <plugin.h>
-#include <request.h>
-
-#include "gntaccount.h"
-#include "gntgaim.h"
-
-#include <string.h>
-
-typedef struct
-{
-	GntWidget *window;
-	GntWidget *tree;
-} GGAccountList;
-
-static GGAccountList accounts;
-
-typedef struct
-{
-	GaimAccount *account;          /* NULL for a new account */
-
-	GntWidget *window;
-
-	GntWidget *protocol;
-	GntWidget *screenname;
-	GntWidget *password;
-	GntWidget *alias;
-	
-	GntWidget *splits;
-	GList *split_entries;
-
-	GList *prpl_entries;
-	GntWidget *prpls;
-
-	GntWidget *newmail;
-	GntWidget *remember;
-} AccountEditDialog;
-
-/* This is necessary to close an edit-dialog when an account is deleted */
-static GList *accountdialogs;
-
-static void
-account_add(GaimAccount *account)
-{
-	gnt_tree_add_choice(GNT_TREE(accounts.tree), account,
-			gnt_tree_create_row(GNT_TREE(accounts.tree),
-				gaim_account_get_username(account),
-				gaim_account_get_protocol_name(account)),
-			NULL, NULL);
-	gnt_tree_set_choice(GNT_TREE(accounts.tree), account,
-			gaim_account_get_enabled(account, GAIM_GNT_UI));
-}
-
-static void
-edit_dialog_destroy(AccountEditDialog *dialog)
-{
-	accountdialogs = g_list_remove(accountdialogs, dialog);
-	g_list_free(dialog->prpl_entries);
-	g_list_free(dialog->split_entries);
-	g_free(dialog);
-}
-
-static void
-save_account_cb(AccountEditDialog *dialog)
-{
-	GaimAccount *account;
-	GaimPlugin *plugin;
-	GaimPluginProtocolInfo *prplinfo;
-	const char *value;
-	GString *username;
-
-	/* XXX: Do some error checking first. */
-
-	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
-	prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
-
-	/* Screenname && user-splits */
-	value = gnt_entry_get_text(GNT_ENTRY(dialog->screenname));
-
-	if (value == NULL || *value == '\0')
-	{
-		gaim_notify_error(NULL, _("Error"), _("Account was not added"),
-				_("Screenname of an account must be non-empty."));
-		return;
-	}
-	
-	username = g_string_new(value);
-
-	if (prplinfo != NULL)
-	{
-		GList *iter, *entries;
-		for (iter = prplinfo->user_splits, entries = dialog->split_entries;
-				iter && entries; iter = iter->next, entries = entries->next)
-		{
-			GaimAccountUserSplit *split = iter->data;
-			GntWidget *entry = entries->data;
-
-			value = gnt_entry_get_text(GNT_ENTRY(entry));
-			if (value == NULL || *value == '\0')
-				value = gaim_account_user_split_get_default_value(split);
-			g_string_append_printf(username, "%c%s",
-					gaim_account_user_split_get_separator(split),
-					value);
-		}
-	}
-
-	if (dialog->account == NULL)
-	{
-		account = gaim_account_new(username->str, gaim_plugin_get_id(plugin));
-		gaim_accounts_add(account);
-	}
-	else
-	{
-		account = dialog->account;
-
-		/* Protocol */
-		gaim_account_set_protocol_id(account, gaim_plugin_get_id(plugin));
-		gaim_account_set_username(account, username->str);
-	}
-	g_string_free(username, TRUE);
-
-	/* Alias */
-	value = gnt_entry_get_text(GNT_ENTRY(dialog->alias));
-	if (value && *value)
-		gaim_account_set_alias(account, value);
-
-	/* Remember password and password */
-	gaim_account_set_remember_password(account,
-			gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->remember)));
-	value = gnt_entry_get_text(GNT_ENTRY(dialog->password));
-	if (value && *value && gaim_account_get_remember_password(account))
-		gaim_account_set_password(account, value);
-	else
-		gaim_account_set_password(account, NULL);
-
-	/* Mail notification */
-	gaim_account_set_check_mail(account,
-			gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->newmail)));
-
-	/* Protocol options */
-	if (prplinfo)
-	{
-		GList *iter, *entries;
-		
-		for (iter = prplinfo->protocol_options, entries = dialog->prpl_entries;
-				iter && entries; iter = iter->next, entries = entries->next)
-		{
-			GaimAccountOption *option = iter->data;
-			GntWidget *entry = entries->data;
-			GaimPrefType type = gaim_account_option_get_type(option);
-			const char *setting = gaim_account_option_get_setting(option);
-
-			if (type == GAIM_PREF_STRING)
-			{
-				const char *value = gnt_entry_get_text(GNT_ENTRY(entry));
-				gaim_account_set_string(account, setting, value);
-			}
-			else if (type == GAIM_PREF_INT)
-			{
-				const char *str = gnt_entry_get_text(GNT_ENTRY(entry));
-				int value = 0;
-				if (str)
-					value = atoi(str);
-				gaim_account_set_int(account, setting, value);
-			}
-			else if (type == GAIM_PREF_BOOLEAN)
-			{
-				gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(entry));
-				gaim_account_set_bool(account, setting, value);
-			}
-			else if (type == GAIM_PREF_STRING_LIST)
-			{
-				/* TODO: */
-			}
-			else
-			{
-				g_assert_not_reached();
-			}
-		}
-	}
-
-	/* XXX: Proxy options */
-
-	gnt_widget_destroy(dialog->window);
-}
-
-static void
-update_user_splits(AccountEditDialog *dialog)
-{
-	GntWidget *hbox;
-	GaimPlugin *plugin;
-	GaimPluginProtocolInfo *prplinfo;
-	GList *iter, *entries;
-	char *username = NULL;
-
-	if (dialog->splits)
-	{
-		gnt_box_remove_all(GNT_BOX(dialog->splits));
-		g_list_free(dialog->split_entries);
-	}
-	else
-	{
-		dialog->splits = gnt_vbox_new(FALSE);
-		gnt_box_set_pad(GNT_BOX(dialog->splits), 0);
-		gnt_box_set_fill(GNT_BOX(dialog->splits), TRUE);
-	}
-
-	dialog->split_entries = NULL;
-
-	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
-	if (!plugin)
-		return;
-	prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
-	
-	username = dialog->account ? g_strdup(gaim_account_get_username(dialog->account)) : NULL;
-
-	for (iter = prplinfo->user_splits; iter; iter = iter->next)
-	{
-		GaimAccountUserSplit *split = iter->data;
-		GntWidget *entry;
-		char *buf;
-
-		hbox = gnt_hbox_new(TRUE);
-		gnt_box_add_widget(GNT_BOX(dialog->splits), hbox);
-
-		buf = g_strdup_printf("%s:", gaim_account_user_split_get_text(split));
-		gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(buf));
-
-		entry = gnt_entry_new(NULL);
-		gnt_box_add_widget(GNT_BOX(hbox), entry);
-
-		dialog->split_entries = g_list_append(dialog->split_entries, entry);
-		g_free(buf);
-	}
-
-	for (iter = g_list_last(prplinfo->user_splits), entries = g_list_last(dialog->split_entries);
-			iter && entries; iter = iter->prev, entries = entries->prev)
-	{
-		GntWidget *entry = entries->data;
-		GaimAccountUserSplit *split = iter->data;
-		const char *value = NULL;
-		char *s;
-
-		if (dialog->account)
-		{
-			s = strrchr(username, gaim_account_user_split_get_separator(split));
-			if (s != NULL)
-			{
-				*s = '\0';
-				s++;
-				value = s;
-			}
-		}
-		if (value == NULL)
-			value = gaim_account_user_split_get_default_value(split);
-
-		if (value != NULL)
-			gnt_entry_set_text(GNT_ENTRY(entry), value);
-	}
-
-	if (username != NULL)
-		gnt_entry_set_text(GNT_ENTRY(dialog->screenname), username);
-
-	g_free(username);
-}
-
-static void
-add_protocol_options(AccountEditDialog *dialog)
-{
-	GaimPlugin *plugin;
-	GaimPluginProtocolInfo *prplinfo;
-	GList *iter;
-	GntWidget *vbox, *box;
-	GaimAccount *account;
-
-	if (dialog->prpls)
-		gnt_box_remove_all(GNT_BOX(dialog->prpls));
-	else
-	{
-		dialog->prpls = vbox = gnt_vbox_new(FALSE);
-		gnt_box_set_pad(GNT_BOX(vbox), 0);
-		gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_LEFT);
-		gnt_box_set_fill(GNT_BOX(vbox), TRUE);
-	}
-
-	if (dialog->prpl_entries)
-	{
-		g_list_free(dialog->prpl_entries);
-		dialog->prpl_entries = NULL;
-	}
-
-	vbox = dialog->prpls;
-
-	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
-	if (!plugin)
-		return;
-
-	prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
-
-	account = dialog->account;
-
-	for (iter = prplinfo->protocol_options; iter; iter = iter->next)
-	{
-		GaimAccountOption *option = iter->data;
-		GaimPrefType type = gaim_account_option_get_type(option);
-
-		box = gnt_hbox_new(TRUE);
-		gnt_box_set_pad(GNT_BOX(box), 0);
-		gnt_box_add_widget(GNT_BOX(vbox), box);
-
-		if (type == GAIM_PREF_BOOLEAN)
-		{
-			GntWidget *widget = gnt_check_box_new(gaim_account_option_get_text(option));
-			gnt_box_add_widget(GNT_BOX(box), widget);
-			dialog->prpl_entries = g_list_append(dialog->prpl_entries, widget);
-
-			if (account)
-				gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
-						gaim_account_get_bool(account,
-							gaim_account_option_get_setting(option),
-							gaim_account_option_get_default_bool(option)));
-			else
-				gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
-						gaim_account_option_get_default_bool(option));
-		}
-		else
-		{
-			gnt_box_add_widget(GNT_BOX(box),
-					gnt_label_new(gaim_account_option_get_text(option)));
-
-			if (type == GAIM_PREF_STRING_LIST)
-			{
-				/* TODO: Use a combobox */
-				/*       Don't forget to append the widget to prpl_entries */
-			}
-			else
-			{
-				GntWidget *entry = gnt_entry_new(NULL);
-				gnt_box_add_widget(GNT_BOX(box), entry);
-				dialog->prpl_entries = g_list_append(dialog->prpl_entries, entry);
-
-				if (type == GAIM_PREF_STRING)
-				{
-					const char *dv = gaim_account_option_get_default_string(option);
-
-					if (account)
-						gnt_entry_set_text(GNT_ENTRY(entry),
-								gaim_account_get_string(account,
-									gaim_account_option_get_setting(option), dv));
-					else
-						gnt_entry_set_text(GNT_ENTRY(entry), dv);
-				}
-				else if (type == GAIM_PREF_INT)
-				{
-					char str[32];
-					int value = gaim_account_option_get_default_int(option);
-					if (account)
-						value = gaim_account_get_int(account,
-								gaim_account_option_get_setting(option), value);
-					snprintf(str, sizeof(str), "%d", value);
-					gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
-					gnt_entry_set_text(GNT_ENTRY(entry), str);
-				}
-				else
-				{
-					g_assert_not_reached();
-				}
-			}
-		}
-	}
-}
-
-static void
-update_user_options(AccountEditDialog *dialog)
-{
-	GaimPlugin *plugin;
-	GaimPluginProtocolInfo *prplinfo;
-
-	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
-	if (!plugin)
-		return;
-
-	prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
-
-	if (dialog->newmail == NULL)
-		dialog->newmail = gnt_check_box_new(_("New mail notifications"));
-	if (dialog->account)
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->newmail),
-				gaim_account_get_check_mail(dialog->account));
-	if (!prplinfo || !(prplinfo->options & OPT_PROTO_MAIL_CHECK))
-		gnt_widget_set_visible(dialog->newmail, FALSE);
-	else
-		gnt_widget_set_visible(dialog->newmail, TRUE);
-
-	if (dialog->remember == NULL)
-		dialog->remember = gnt_check_box_new(_("Remember password"));
-	if (dialog->account)
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->remember),
-				gaim_account_get_remember_password(dialog->account));
-}
-
-static void
-prpl_changed_cb(GntWidget *combo, GaimPlugin *old, GaimPlugin *new, AccountEditDialog *dialog)
-{
-	update_user_splits(dialog);
-	add_protocol_options(dialog);
-	update_user_options(dialog);  /* This may not be necessary here */
-	gnt_box_readjust(GNT_BOX(dialog->window));
-	gnt_widget_draw(dialog->window);
-}
-
-static void
-edit_account(GaimAccount *account)
-{
-	GntWidget *window, *hbox;
-	GntWidget *combo, *button, *entry;
-	GList *list, *iter;
-	AccountEditDialog *dialog;
-
-	if (account)
-	{
-		GList *iter;
-		for (iter = accountdialogs; iter; iter = iter->next)
-		{
-			AccountEditDialog *dlg = iter->data;
-			if (dlg->account == account)
-				return;
-		}
-	}
-
-	dialog = g_new0(AccountEditDialog, 1);
-	accountdialogs = g_list_prepend(accountdialogs, dialog);
-
-	dialog->window = window = gnt_vbox_new(FALSE);
-	dialog->account = account;
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-	gnt_box_set_title(GNT_BOX(window), account ? _("Modify Account") : _("New Account"));
-	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
-	gnt_box_set_pad(GNT_BOX(window), 0);
-	gnt_widget_set_name(window, "edit-account");
-	gnt_box_set_fill(GNT_BOX(window), TRUE);
-
-	hbox = gnt_hbox_new(TRUE);
-	gnt_box_set_pad(GNT_BOX(hbox), 0);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-
-	dialog->protocol = combo = gnt_combo_box_new();
-	list = gaim_plugins_get_protocols();
-	for (iter = list; iter; iter = iter->next)
-	{
-		gnt_combo_box_add_data(GNT_COMBO_BOX(combo), iter->data,
-				((GaimPlugin*)iter->data)->info->name);
-	}
-
-	if (account)
-		gnt_combo_box_set_selected(GNT_COMBO_BOX(combo),
-				gaim_plugins_find_with_id(gaim_account_get_protocol_id(account)));
-	else
-		gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), list->data);
-
-	g_signal_connect(G_OBJECT(combo), "selection-changed", G_CALLBACK(prpl_changed_cb), dialog);
-
-	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Protocol:")));
-	gnt_box_add_widget(GNT_BOX(hbox), combo);
-
-	hbox = gnt_hbox_new(TRUE);
-	gnt_box_set_pad(GNT_BOX(hbox), 0);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-
-	dialog->screenname = entry = gnt_entry_new(NULL);
-	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Screen name:")));
-	gnt_box_add_widget(GNT_BOX(hbox), entry);
-
-	/* User splits */
-	update_user_splits(dialog);
-	gnt_box_add_widget(GNT_BOX(window), dialog->splits);
-
-	hbox = gnt_hbox_new(TRUE);
-	gnt_box_set_pad(GNT_BOX(hbox), 0);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-
-	dialog->password = entry = gnt_entry_new(NULL);
-	gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
-	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Password:")));
-	gnt_box_add_widget(GNT_BOX(hbox), entry);
-	if (account)
-		gnt_entry_set_text(GNT_ENTRY(entry), gaim_account_get_password(account));
-
-	hbox = gnt_hbox_new(TRUE);
-	gnt_box_set_pad(GNT_BOX(hbox), 0);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-
-	dialog->alias = entry = gnt_entry_new(NULL);
-	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Alias:")));
-	gnt_box_add_widget(GNT_BOX(hbox), entry);
-	if (account)
-		gnt_entry_set_text(GNT_ENTRY(entry), gaim_account_get_alias(account));
-
-	/* User options */
-	update_user_options(dialog);
-	gnt_box_add_widget(GNT_BOX(window), dialog->remember);
-	gnt_box_add_widget(GNT_BOX(window), dialog->newmail);
-
-	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
-
-	/* The advanced box */
-	add_protocol_options(dialog);
-	gnt_box_add_widget(GNT_BOX(window), dialog->prpls);
-
-	/* TODO: Add proxy options */
-
-	/* The button box */
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
-
-	button = gnt_button_new(_("Cancel"));
-	gnt_box_add_widget(GNT_BOX(hbox), button);
-	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window);
-	
-	button = gnt_button_new(_("Save"));
-	gnt_box_add_widget(GNT_BOX(hbox), button);
-	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(save_account_cb), dialog);
-
-	g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(edit_dialog_destroy), dialog);
-
-	gnt_widget_show(window);
-	gnt_box_readjust(GNT_BOX(window));
-	gnt_widget_draw(window);
-}
-
-static void
-add_account_cb(GntWidget *widget, gpointer null)
-{
-	edit_account(NULL);
-}
-
-static void
-modify_account_cb(GntWidget *widget, GntTree *tree)
-{
-	GaimAccount *account = gnt_tree_get_selection_data(tree);
-	if (!account)
-		return;
-	edit_account(account);
-}
-
-static void
-really_delete_account(GaimAccount *account)
-{
-	GList *iter;
-	for (iter = accountdialogs; iter; iter = iter->next)
-	{
-		AccountEditDialog *dlg = iter->data;
-		if (dlg->account == account)
-		{
-			gnt_widget_destroy(dlg->window);
-			break;
-		}
-	}
-	gaim_request_close_with_handle(account); /* Close any other opened delete window */
-	gaim_accounts_delete(account);
-}
-
-static void
-delete_account_cb(GntWidget *widget, GntTree *tree)
-{
-	GaimAccount *account;
-	char *prompt;
-
-	account  = gnt_tree_get_selection_data(tree);
-	if (!account)
-		return;
-
-	prompt = g_strdup_printf(_("Are you sure you want to delete %s?"),
-			gaim_account_get_username(account));
-
-	gaim_request_action(account, _("Delete Account"), prompt, NULL, 0, account, 2,
-			_("Delete"), really_delete_account, _("Cancel"), NULL);
-	g_free(prompt);
-}
-
-static void
-account_toggled(GntWidget *widget, void *key, gpointer null)
-{
-	GaimAccount *account = key;
-
-	gaim_account_set_enabled(account, GAIM_GNT_UI, gnt_tree_get_choice(GNT_TREE(widget), key));
-}
-
-static void
-reset_accounts_win(GntWidget *widget, gpointer null)
-{
-	accounts.window = NULL;
-	accounts.tree = NULL;
-}
-
-void gg_accounts_show_all()
-{
-	GList *iter;
-	GntWidget *box, *button;
-
-	if (accounts.window)
-		return;
-
-	accounts.window = gnt_vbox_new(FALSE);
-	gnt_box_set_toplevel(GNT_BOX(accounts.window), TRUE);
-	gnt_box_set_title(GNT_BOX(accounts.window), _("Accounts"));
-	gnt_box_set_pad(GNT_BOX(accounts.window), 0);
-	gnt_box_set_alignment(GNT_BOX(accounts.window), GNT_ALIGN_MID);
-	gnt_widget_set_name(accounts.window, "accounts");
-
-	gnt_box_add_widget(GNT_BOX(accounts.window),
-			gnt_label_new(_("You can enable/disable accounts from the following list.")));
-
-	gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE));
-
-	accounts.tree = gnt_tree_new_with_columns(2);
-	GNT_WIDGET_SET_FLAGS(accounts.tree, GNT_WIDGET_NO_BORDER);
-
-	for (iter = gaim_accounts_get_all(); iter; iter = iter->next)
-	{
-		GaimAccount *account = iter->data;
-		account_add(account);
-	}
-
-	g_signal_connect(G_OBJECT(accounts.tree), "toggled", G_CALLBACK(account_toggled), NULL);
-	
-	gnt_tree_set_col_width(GNT_TREE(accounts.tree), 0, 40);
-	gnt_tree_set_col_width(GNT_TREE(accounts.tree), 1, 10);
-	gnt_box_add_widget(GNT_BOX(accounts.window), accounts.tree);
-
-	gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE));
-
-	box = gnt_hbox_new(FALSE);
-
-	button = gnt_button_new(_("Add"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(add_account_cb), NULL);
-
-	button = gnt_button_new(_("Modify"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(modify_account_cb), accounts.tree);
-
-	button = gnt_button_new(_("Delete"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(delete_account_cb), accounts.tree);
-	
-	gnt_box_add_widget(GNT_BOX(accounts.window), box);
-
-	g_signal_connect(G_OBJECT(accounts.window), "destroy", G_CALLBACK(reset_accounts_win), NULL);
-	
-	gnt_widget_show(accounts.window);
-}
-
-static gpointer
-gg_accounts_get_handle()
-{
-	static int handle;
-
-	return &handle;
-}
-
-static void
-account_added_callback(GaimAccount *account)
-{
-	if (accounts.window == NULL)
-		return;
-	account_add(account);
-	gnt_widget_draw(accounts.tree);
-}
-
-static void
-account_removed_callback(GaimAccount *account)
-{
-	if (accounts.window == NULL)
-		return;
-
-	gnt_tree_remove(GNT_TREE(accounts.tree), account);
-}
-
-void gg_accounts_init()
-{
-	GList *iter;
-
-	gaim_signal_connect(gaim_accounts_get_handle(), "account-added",
-			gg_accounts_get_handle(), GAIM_CALLBACK(account_added_callback),
-			NULL);
-	gaim_signal_connect(gaim_accounts_get_handle(), "account-removed",
-			gg_accounts_get_handle(), GAIM_CALLBACK(account_removed_callback),
-			NULL);
-	
-	for (iter = gaim_accounts_get_all(); iter; iter = iter->next) {
-		if (gaim_account_get_enabled(iter->data, GAIM_GNT_UI))
-			break;
-	}
-	if (!iter)
-		gg_accounts_show_all();
-}
-
-void gg_accounts_uninit()
-{
-	if (accounts.window)
-		gnt_widget_destroy(accounts.window);
-}
-
-/* The following uiops stuff are copied from gtkaccount.c */
-typedef struct
-{
-	GaimAccount *account;
-	char *username;
-	char *alias;
-} AddUserData;
-
-static char *
-make_info(GaimAccount *account, GaimConnection *gc, const char *remote_user,
-          const char *id, const char *alias, const char *msg)
-{
-	if (msg != NULL && *msg == '\0')
-		msg = NULL;
-
-	return g_strdup_printf(_("%s%s%s%s has made %s his or her buddy%s%s"),
-	                       remote_user,
-	                       (alias != NULL ? " ("  : ""),
-	                       (alias != NULL ? alias : ""),
-	                       (alias != NULL ? ")"   : ""),
-	                       (id != NULL
-	                        ? id
-	                        : (gaim_connection_get_display_name(gc) != NULL
-	                           ? gaim_connection_get_display_name(gc)
-	                           : gaim_account_get_username(account))),
-	                       (msg != NULL ? ": " : "."),
-	                       (msg != NULL ? msg  : ""));
-}
-
-static void
-notify_added(GaimAccount *account, const char *remote_user,
-			const char *id, const char *alias,
-			const char *msg)
-{
-	char *buffer;
-	GaimConnection *gc;
-
-	gc = gaim_account_get_connection(account);
-
-	buffer = make_info(account, gc, remote_user, id, alias, msg);
-
-	gaim_notify_info(NULL, NULL, buffer, NULL);
-
-	g_free(buffer);
-}
-
-static void
-free_add_user_data(AddUserData *data)
-{
-	g_free(data->username);
-
-	if (data->alias != NULL)
-		g_free(data->alias);
-
-	g_free(data);
-}
-
-static void
-add_user_cb(AddUserData *data)
-{
-	GaimConnection *gc = gaim_account_get_connection(data->account);
-
-	if (g_list_find(gaim_connections_get_all(), gc))
-	{
-		gaim_blist_request_add_buddy(data->account, data->username,
-									 NULL, data->alias);
-	}
-
-	free_add_user_data(data);
-}
-
-static void
-request_add(GaimAccount *account, const char *remote_user,
-		  const char *id, const char *alias,
-		  const char *msg)
-{
-	char *buffer;
-	GaimConnection *gc;
-	AddUserData *data;
-
-	gc = gaim_account_get_connection(account);
-
-	data = g_new0(AddUserData, 1);
-	data->account  = account;
-	data->username = g_strdup(remote_user);
-	data->alias    = (alias != NULL ? g_strdup(alias) : NULL);
-
-	buffer = make_info(account, gc, remote_user, id, alias, msg);
-	gaim_request_action(NULL, NULL, _("Add buddy to your list?"),
-	                    buffer, GAIM_DEFAULT_ACTION_NONE, data, 2,
-	                    _("Add"),    G_CALLBACK(add_user_cb),
-	                    _("Cancel"), G_CALLBACK(free_add_user_data));
-	g_free(buffer);
-}
-
-/* Copied from gtkaccount.c */
-typedef struct {
-	GaimAccountRequestAuthorizationCb auth_cb;
-	GaimAccountRequestAuthorizationCb deny_cb;
-	void *data;
-	char *username;
-	char *alias;
-	GaimAccount *account;
-} auth_and_add;
-
-static void
-authorize_and_add_cb(auth_and_add *aa)
-{
-	aa->auth_cb(aa->data);
-	gaim_blist_request_add_buddy(aa->account, aa->username,
-	 	                    NULL, aa->alias);
-
-	g_free(aa->username);
-	g_free(aa->alias);
-	g_free(aa);
-}
-
-static void
-deny_no_add_cb(auth_and_add *aa)
-{
-	aa->deny_cb(aa->data);
-
-	g_free(aa->username);
-	g_free(aa->alias);
-	g_free(aa);
-}
-
-static void *
-gg_request_authorize(GaimAccount *account, const char *remote_user,
-					const char *id, const char *alias, const char *message, gboolean on_list,
-					GCallback auth_cb, GCallback deny_cb, void *user_data)
-{
-	char *buffer;
-	GaimConnection *gc;
-	void *uihandle;
-
-	gc = gaim_account_get_connection(account);
-	if (message != NULL && *message == '\0')
-		message = NULL;
-
-	buffer = g_strdup_printf(_("%s%s%s%s wants to add %s to his or her buddy list%s%s"),
-				remote_user,
-	 	                (alias != NULL ? " ("  : ""),
-		                (alias != NULL ? alias : ""),
-		                (alias != NULL ? ")"   : ""),
-		                (id != NULL
-		                ? id
-		                : (gaim_connection_get_display_name(gc) != NULL
-		                ? gaim_connection_get_display_name(gc)
-		                : gaim_account_get_username(account))),
-		                (message != NULL ? ": " : "."),
-		                (message != NULL ? message  : ""));
-	if (!on_list) {
-		auth_and_add *aa = g_new(auth_and_add, 1);
-		aa->auth_cb = (GaimAccountRequestAuthorizationCb)auth_cb;
-		aa->deny_cb = (GaimAccountRequestAuthorizationCb)deny_cb;
-		aa->data = user_data;
-		aa->username = g_strdup(remote_user);
-		aa->alias = g_strdup(alias);
-		aa->account = account;
-		uihandle = gaim_request_action(NULL, _("Authorize buddy?"), buffer, NULL,
-			GAIM_DEFAULT_ACTION_NONE, aa, 2,
-			_("Authorize"), authorize_and_add_cb,
-			_("Deny"), deny_no_add_cb);
-	} else {
-		uihandle = gaim_request_action(NULL, _("Authorize buddy?"), buffer, NULL,
-			GAIM_DEFAULT_ACTION_NONE, user_data, 2,
-			_("Authorize"), auth_cb,
-			_("Deny"), deny_cb);
-	}
-	g_free(buffer);
-	return uihandle;
-}
-
-static void
-gg_request_close(void *uihandle)
-{
-	gaim_request_close(GAIM_REQUEST_ACTION, uihandle);
-}
-
-static GaimAccountUiOps ui_ops =
-{
-	.notify_added = notify_added,
-	.status_changed = NULL,
-	.request_add  = request_add,
-	.request_authorize = gg_request_authorize,
-	.close_account_request = gg_request_close
-};
-
-GaimAccountUiOps *gg_accounts_get_ui_ops()
-{
-	return &ui_ops;
-}
-
--- a/console/gntaccount.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/**
- * @file gntaccount.h GNT Account API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_ACCOUNT_H
-#define _GNT_ACCOUNT_H
-
-#include "account.h"
-
-/**********************************************************************
- * @name GNT Account API
- **********************************************************************/
-/*@{*/
-
-/**
- * Get the ui-functions.
- *
- * @return The GaimAccountUiOps structure populated with the appropriate functions.
- */
-GaimAccountUiOps *gg_accounts_get_ui_ops(void);
-
-/**
- * Perform necessary initializations.
- */
-void gg_accounts_init(void);
-
-/**
- * Perform necessary uninitializations.
- */
-void gg_accounts_uninit(void);
-
-/**
- * Show the account-manager dialog.
- */
-void gg_accounts_show_all(void);
-
-/*@}*/
-
-#endif
--- a/console/gntblist.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2233 +0,0 @@
-/**
- * @file gntblist.c GNT BuddyList API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <account.h>
-#include <blist.h>
-#include <notify.h>
-#include <request.h>
-#include <savedstatuses.h>
-#include <server.h>
-#include <signal.h>
-#include <status.h>
-#include <util.h>
-#include "debug.h"
-
-#include "gntgaim.h"
-#include "gntbox.h"
-#include "gntcombobox.h"
-#include "gntentry.h"
-#include "gntft.h"
-#include "gntlabel.h"
-#include "gntline.h"
-#include "gntmenu.h"
-#include "gntmenuitem.h"
-#include "gntmenuitemcheck.h"
-#include "gntpounce.h"
-#include "gnttree.h"
-#include "gntutils.h"
-#include "gntwindow.h"
-
-#include "gntblist.h"
-#include "gntconv.h"
-#include "gntstatus.h"
-#include <string.h>
-
-#define PREF_ROOT "/gaim/gnt/blist"
-#define TYPING_TIMEOUT 4000
-
-typedef struct
-{
-	GntWidget *window;
-	GntWidget *tree;
-
-	GntWidget *tooltip;
-	GaimBlistNode *tnode;		/* Who is the tooltip being displayed for? */
-	GList *tagged;          /* A list of tagged blistnodes */
-
-	GntWidget *context;
-	GaimBlistNode *cnode;
-
-	/* XXX: I am KISSing */
-	GntWidget *status;          /* Dropdown with the statuses  */
-	GntWidget *statustext;      /* Status message */
-	int typing;
-
-	GntWidget *menu;
-	/* These are the menuitems that get regenerated */
-	GntMenuItem *accounts;
-	GntMenuItem *plugins;
-} GGBlist;
-
-typedef enum
-{
-	STATUS_PRIMITIVE = 0,
-	STATUS_SAVED_POPULAR,
-	STATUS_SAVED_ALL,
-	STATUS_SAVED_NEW
-} StatusType;
-
-typedef struct
-{
-	StatusType type;
-	union
-	{
-		GaimStatusPrimitive prim;
-		GaimSavedStatus *saved;
-	} u;
-} StatusBoxItem;
-
-GGBlist *ggblist;
-
-static void add_buddy(GaimBuddy *buddy, GGBlist *ggblist);
-static void add_contact(GaimContact *contact, GGBlist *ggblist);
-static void add_group(GaimGroup *group, GGBlist *ggblist);
-static void add_chat(GaimChat *chat, GGBlist *ggblist);
-static void add_node(GaimBlistNode *node, GGBlist *ggblist);
-static void draw_tooltip(GGBlist *ggblist);
-static gboolean remove_typing_cb(gpointer null);
-static void remove_peripherals(GGBlist *ggblist);
-static const char * get_display_name(GaimBlistNode *node);
-static void savedstatus_changed(GaimSavedStatus *now, GaimSavedStatus *old);
-static void blist_show(GaimBuddyList *list);
-static void update_buddy_display(GaimBuddy *buddy, GGBlist *ggblist);
-static void account_signed_on_cb(void);
-
-/* Sort functions */
-static int blist_node_compare_text(GaimBlistNode *n1, GaimBlistNode *n2);
-static int blist_node_compare_status(GaimBlistNode *n1, GaimBlistNode *n2);
-static int blist_node_compare_log(GaimBlistNode *n1, GaimBlistNode *n2);
-
-static gboolean
-is_contact_online(GaimContact *contact)
-{
-	GaimBlistNode *node;
-	for (node = ((GaimBlistNode*)contact)->child; node; node = node->next) {
-		if (GAIM_BUDDY_IS_ONLINE((GaimBuddy*)node))
-			return TRUE;
-	}
-	return FALSE;
-}
-
-static gboolean
-is_group_online(GaimGroup *group)
-{
-	GaimBlistNode *node;
-	for (node = ((GaimBlistNode*)group)->child; node; node = node->next) {
-		if (GAIM_BLIST_NODE_IS_CHAT(node))
-			return TRUE;
-		else if (is_contact_online((GaimContact*)node))
-			return TRUE;
-	}
-	return FALSE;
-}
-
-static void
-new_node(GaimBlistNode *node)
-{
-}
-
-static void add_node(GaimBlistNode *node, GGBlist *ggblist)
-{
-	if (GAIM_BLIST_NODE_IS_BUDDY(node))
-		add_buddy((GaimBuddy*)node, ggblist);
-	else if (GAIM_BLIST_NODE_IS_CONTACT(node))
-		add_contact((GaimContact*)node, ggblist);
-	else if (GAIM_BLIST_NODE_IS_GROUP(node))
-		add_group((GaimGroup*)node, ggblist);
-	else if (GAIM_BLIST_NODE_IS_CHAT(node))
-		add_chat((GaimChat *)node, ggblist);
-	draw_tooltip(ggblist);
-}
-
-static void
-remove_tooltip(GGBlist *ggblist)
-{
-	gnt_widget_destroy(ggblist->tooltip);
-	ggblist->tooltip = NULL;
-	ggblist->tnode = NULL;
-}
-
-static void
-node_remove(GaimBuddyList *list, GaimBlistNode *node)
-{
-	GGBlist *ggblist = list->ui_data;
-
-	if (ggblist == NULL || node->ui_data == NULL)
-		return;
-
-	gnt_tree_remove(GNT_TREE(ggblist->tree), node);
-	node->ui_data = NULL;
-	if (ggblist->tagged)
-		ggblist->tagged = g_list_remove(ggblist->tagged, node);
-
-	if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
-		GaimContact *contact = (GaimContact*)node->parent;
-		if ((!gaim_prefs_get_bool(PREF_ROOT "/showoffline") && !is_contact_online(contact)) ||
-				contact->currentsize < 1)
-			node_remove(list, (GaimBlistNode*)contact);
-	} else if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
-		GaimGroup *group = (GaimGroup*)node->parent;
-		if ((!gaim_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group)) ||
-				group->currentsize < 1)
-			node_remove(list, node->parent);
-		for (node = node->child; node; node = node->next)
-			node->ui_data = NULL;
-	}
-
-	draw_tooltip(ggblist);
-}
-
-static void
-node_update(GaimBuddyList *list, GaimBlistNode *node)
-{
-	/* It really looks like this should never happen ... but it does.
-           This will at least emit a warning to the log when it
-           happens, so maybe someone will figure it out. */
-	g_return_if_fail(node != NULL);
-
-	if (list->ui_data == NULL)
-		return;   /* XXX: this is probably the place to auto-join chats */
-
-	if (node->ui_data != NULL) {
-		gnt_tree_change_text(GNT_TREE(ggblist->tree), node,
-				0, get_display_name(node));
-		gnt_tree_sort_row(GNT_TREE(ggblist->tree), node);
-	}
-
-	if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
-		GaimBuddy *buddy = (GaimBuddy*)node;
-		if (gaim_account_is_connected(buddy->account) &&
-				(GAIM_BUDDY_IS_ONLINE(buddy) || gaim_prefs_get_bool(PREF_ROOT "/showoffline")))
-			add_node((GaimBlistNode*)buddy, list->ui_data);
-		else
-			node_remove(gaim_get_blist(), node);
-
-		node_update(list, node->parent);
-	} else if (GAIM_BLIST_NODE_IS_CHAT(node)) {
-		add_chat((GaimChat *)node, list->ui_data);
-	} else if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
-		GaimContact *contact = (GaimContact*)node;
-		if ((!gaim_prefs_get_bool(PREF_ROOT "/showoffline") && !is_contact_online(contact)) ||
-				contact->currentsize < 1)
-			node_remove(gaim_get_blist(), node);
-		else
-			add_node(node, list->ui_data);
-	} else if (GAIM_BLIST_NODE_IS_GROUP(node)) {
-		GaimGroup *group = (GaimGroup*)node;
-		if ((!gaim_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group)) ||
-				group->currentsize < 1)
-			node_remove(list, node);
-	}
-}
-
-static void
-new_list(GaimBuddyList *list)
-{
-	if (ggblist)
-		return;
-
-	ggblist = g_new0(GGBlist, 1);
-	list->ui_data = ggblist;
-}
-
-static void
-add_buddy_cb(void *data, GaimRequestFields *allfields)
-{
-	const char *username = gaim_request_fields_get_string(allfields, "screenname");
-	const char *alias = gaim_request_fields_get_string(allfields, "alias");
-	const char *group = gaim_request_fields_get_string(allfields, "group");
-	GaimAccount *account = gaim_request_fields_get_account(allfields, "account");
-	const char *error = NULL;
-	GaimGroup *grp;
-	GaimBuddy *buddy;
-
-	if (!username)
-		error = _("You must provide a screename for the buddy.");
-	else if (!group)
-		error = _("You must provide a group.");
-	else if (!account)
-		error = _("You must select an account.");
-
-	if (error)
-	{
-		gaim_notify_error(NULL, _("Error"), _("Error adding buddy"), error);
-		return;
-	}
-
-	grp = gaim_find_group(group);
-	if (!grp)
-	{
-		grp = gaim_group_new(group);
-		gaim_blist_add_group(grp, NULL);
-	}
-
-	buddy = gaim_buddy_new(account, username, alias);
-	gaim_blist_add_buddy(buddy, NULL, grp, NULL);
-	gaim_account_add_buddy(account, buddy);
-}
-
-static void
-gg_request_add_buddy(GaimAccount *account, const char *username, const char *grp, const char *alias)
-{
-	GaimRequestFields *fields = gaim_request_fields_new();
-	GaimRequestFieldGroup *group = gaim_request_field_group_new(NULL);
-	GaimRequestField *field;
-
-	gaim_request_fields_add_group(fields, group);
-
-	field = gaim_request_field_string_new("screenname", _("Screen Name"), username, FALSE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_string_new("alias", _("Alias"), alias, FALSE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_string_new("group", _("Group"), grp, FALSE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_account_new("account", _("Account"), NULL);
-	gaim_request_field_account_set_show_all(field, FALSE);
-	if (account)
-		gaim_request_field_account_set_value(field, account);
-	gaim_request_field_group_add_field(group, field);
-
-	gaim_request_fields(NULL, _("Add Buddy"), NULL, _("Please enter buddy information."),
-			fields, _("Add"), G_CALLBACK(add_buddy_cb), _("Cancel"), NULL, NULL);
-}
-
-static void
-add_chat_cb(void *data, GaimRequestFields *allfields)
-{
-	GaimAccount *account;
-	const char *alias, *name, *group;
-	GaimChat *chat;
-	GaimGroup *grp;
-	GHashTable *hash = NULL;
-	GaimConnection *gc;
-
-	account = gaim_request_fields_get_account(allfields, "account");
-	name = gaim_request_fields_get_string(allfields, "name");
-	alias = gaim_request_fields_get_string(allfields, "alias");
-	group = gaim_request_fields_get_string(allfields, "group");
-
-	if (!gaim_account_is_connected(account) || !name || !*name)
-		return;
-	
-	if (!group || !*group)
-		group = _("Chats");
-
-	gc = gaim_account_get_connection(account);
-
-	if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL)
-		hash = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, name);
-	
-	chat = gaim_chat_new(account, name, hash);
-
-	if (chat != NULL) {
-		if ((grp = gaim_find_group(group)) == NULL) {
-			grp = gaim_group_new(group);
-			gaim_blist_add_group(grp, NULL);
-		}
-		gaim_blist_add_chat(chat, grp, NULL);
-		gaim_blist_alias_chat(chat, alias);
-	}
-}
-
-static void
-gg_request_add_chat(GaimAccount *account, GaimGroup *grp, const char *alias, const char *name)
-{
-	GaimRequestFields *fields = gaim_request_fields_new();
-	GaimRequestFieldGroup *group = gaim_request_field_group_new(NULL);
-	GaimRequestField *field;
-
-	gaim_request_fields_add_group(fields, group);
-
-	field = gaim_request_field_account_new("account", _("Account"), NULL);
-	gaim_request_field_account_set_show_all(field, FALSE);
-	if (account)
-		gaim_request_field_account_set_value(field, account);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_string_new("name", _("Name"), name, FALSE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_string_new("alias", _("Alias"), alias, FALSE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_string_new("group", _("Group"), grp ? grp->name : NULL, FALSE);
-	gaim_request_field_group_add_field(group, field);
-
-	gaim_request_fields(NULL, _("Add Chat"), NULL,
-			_("You can edit more information from the context menu later."),
-			fields, _("Add"), G_CALLBACK(add_chat_cb), _("Cancel"), NULL, NULL);
-}
-
-static void
-add_group_cb(gpointer null, const char *group)
-{
-	GaimGroup *grp;
-
-	if (!group || !*group)
-	{
-		gaim_notify_error(NULL, _("Error"), _("Error adding group"),
-				_("You must give a name for the group to add."));
-		return;
-	}
-
-	grp = gaim_find_group(group);
-	if (!grp)
-	{
-		grp = gaim_group_new(group);
-		gaim_blist_add_group(grp, NULL);
-	}
-	else
-	{
-		gaim_notify_error(NULL, _("Error"), _("Error adding group"),
-				_("A group with the name already exists."));
-	}
-}
-
-static void
-gg_request_add_group()
-{
-	gaim_request_input(NULL, _("Add Group"), NULL, _("Enter the name of the group"),
-			NULL, FALSE, FALSE, NULL,
-			_("Add"), G_CALLBACK(add_group_cb), _("Cancel"), NULL, NULL);
-}
-
-static GaimBlistUiOps blist_ui_ops =
-{
-	new_list,
-	new_node,
-	blist_show,
-	node_update,
-	node_remove,
-	NULL,
-	NULL,
-	.request_add_buddy = gg_request_add_buddy,
-	.request_add_chat = gg_request_add_chat,
-	.request_add_group = gg_request_add_group
-};
-
-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;
-	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group,
-			gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)), NULL, NULL);
-}
-
-static const char *
-get_display_name(GaimBlistNode *node)
-{
-	static char text[2096];
-	char status[8] = " ";
-	const char *name = NULL;
-
-	if (GAIM_BLIST_NODE_IS_CONTACT(node))
-		node = (GaimBlistNode*)gaim_contact_get_priority_buddy((GaimContact*)node);  /* XXX: this can return NULL?! */
-	
-	if (node == NULL)
-		return NULL;
-
-	if (GAIM_BLIST_NODE_IS_BUDDY(node))
-	{
-		GaimBuddy *buddy = (GaimBuddy *)node;
-		GaimStatusPrimitive prim;
-		GaimPresence *presence;
-		GaimStatus *now;
-		gboolean ascii = gnt_ascii_only();
-		
-		presence = gaim_buddy_get_presence(buddy);
-		now = gaim_presence_get_active_status(presence);
-
-		prim = gaim_status_type_get_primitive(gaim_status_get_type(now));
-
-		switch(prim)
-		{
-			case GAIM_STATUS_OFFLINE:
-				strncpy(status, ascii ? "x" : "⊗", sizeof(status) - 1);
-				break;
-			case GAIM_STATUS_AVAILABLE:
-				strncpy(status, ascii ? "o" : "◯", sizeof(status) - 1);
-				break;
-			default:
-				strncpy(status, ascii ? "." : "⊖", sizeof(status) - 1);
-				break;
-		}
-		name = gaim_buddy_get_alias(buddy);
-	}
-	else if (GAIM_BLIST_NODE_IS_CHAT(node))
-	{
-		GaimChat *chat = (GaimChat*)node;
-		name = gaim_chat_get_name(chat);
-
-		strncpy(status, "~", sizeof(status) - 1);
-	}
-	else if (GAIM_BLIST_NODE_IS_GROUP(node))
-		return ((GaimGroup*)node)->name;
-
-	snprintf(text, sizeof(text) - 1, "%s %s", status, name);
-
-	return text;
-}
-
-static void
-add_chat(GaimChat *chat, GGBlist *ggblist)
-{
-	GaimGroup *group;
-	GaimBlistNode *node = (GaimBlistNode *)chat;
-	if (node->ui_data)
-		return;
-	if (!gaim_account_is_connected(chat->account))
-		return;
-
-	group = gaim_chat_get_group(chat);
-	add_node((GaimBlistNode*)group, ggblist);
-
-	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), chat,
-				gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)),
-				group, NULL);
-}
-
-static void
-add_contact(GaimContact *contact, GGBlist *ggblist)
-{
-	GaimGroup *group;
-	GaimBlistNode *node = (GaimBlistNode*)contact;
-	const char *name;
-
-	if (node->ui_data)
-		return;
-	
-	name = get_display_name(node);
-	if (name == NULL)
-		return;
-	
-	group = (GaimGroup*)node->parent;
-	add_node((GaimBlistNode*)group, ggblist);
-
-	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), contact,
-				gnt_tree_create_row(GNT_TREE(ggblist->tree), name),
-				group, NULL);
-
-	gnt_tree_set_expanded(GNT_TREE(ggblist->tree), contact, FALSE);
-}
-
-static void
-add_buddy(GaimBuddy *buddy, GGBlist *ggblist)
-{
-	GaimContact *contact;
-	GaimBlistNode *node = (GaimBlistNode *)buddy;
-	if (node->ui_data)
-		return;
-
-	contact = (GaimContact*)node->parent;
-	if (!contact)   /* When a new buddy is added and show-offline is set */
-		return;
-	add_node((GaimBlistNode*)contact, ggblist);
-
-	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy,
-				gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)),
-				contact, NULL);
-	if (gaim_presence_is_idle(gaim_buddy_get_presence(buddy))) {
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, GNT_TEXT_FLAG_DIM);
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, GNT_TEXT_FLAG_DIM);
-	} else {
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, 0);
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, 0);
-	}
-}
-
-#if 0
-static void
-buddy_signed_on(GaimBuddy *buddy, GGBlist *ggblist)
-{
-	add_node((GaimBlistNode*)buddy, ggblist);
-}
-
-static void
-buddy_signed_off(GaimBuddy *buddy, GGBlist *ggblist)
-{
-	node_remove(gaim_get_blist(), (GaimBlistNode*)buddy);
-}
-#endif
-
-GaimBlistUiOps *gg_blist_get_ui_ops()
-{
-	return &blist_ui_ops;
-}
-
-static void
-selection_activate(GntWidget *widget, GGBlist *ggblist)
-{
-	GntTree *tree = GNT_TREE(ggblist->tree);
-	GaimBlistNode *node = gnt_tree_get_selection_data(tree);
-
-	if (!node)
-		return;
-	
-	if (GAIM_BLIST_NODE_IS_CONTACT(node))
-		node = (GaimBlistNode*)gaim_contact_get_priority_buddy((GaimContact*)node);
-
-	if (GAIM_BLIST_NODE_IS_BUDDY(node))
-	{
-		GaimBuddy *buddy = (GaimBuddy *)node;
-		GaimConversation *conv =  gaim_conversation_new(GAIM_CONV_TYPE_IM,
-					gaim_buddy_get_account(buddy),
-					gaim_buddy_get_name(buddy));
-		gg_conversation_set_active(conv);
-	}
-	else if (GAIM_BLIST_NODE_IS_CHAT(node))
-	{
-		GaimChat *chat = (GaimChat*)node;
-		serv_join_chat(chat->account->gc, chat->components);
-	}
-}
-
-static void
-context_menu_callback(GntMenuItem *item, gpointer data)
-{
-	GaimMenuAction *action = data;
-	GaimBlistNode *node = ggblist->cnode;
-	if (action) {
-		void (*callback)(GaimBlistNode *, gpointer);
-		callback = (void (*)(GaimBlistNode *, gpointer))action->callback;
-		if (callback)
-			callback(action->data, node);
-		else
-			return;
-	}
-}
-
-static void
-gnt_append_menu_action(GntMenu *menu, GaimMenuAction *action, gpointer parent)
-{
-	GList *list;
-	GntMenuItem *item;
-
-	if (action == NULL)
-		return;
-
-	item = gnt_menuitem_new(action->label);
-	if (action->callback)
-		gnt_menuitem_set_callback(GNT_MENUITEM(item), context_menu_callback, action);
-	gnt_menu_add_item(menu, GNT_MENUITEM(item));
-
-	if (action->children) {
-		GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
-		gnt_menuitem_set_submenu(item, GNT_MENU(sub));
-		for (list = action->children; list; list = list->next)
-			gnt_append_menu_action(GNT_MENU(sub), list->data, action);
-	}
-}
-
-static void
-append_proto_menu(GntMenu *menu, GaimConnection *gc, GaimBlistNode *node)
-{
-	GList *list;
-	GaimPluginProtocolInfo *prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
-
-	if(!prpl_info || !prpl_info->blist_node_menu)
-		return;
-
-	for(list = prpl_info->blist_node_menu(node); list;
-			list = g_list_delete_link(list, list))
-	{
-		GaimMenuAction *act = (GaimMenuAction *) list->data;
-		act->data = node;
-		gnt_append_menu_action(menu, act, NULL);
-	}
-}
-
-static void
-add_custom_action(GntMenu *menu, const char *label, GaimCallback callback,
-		gpointer data)
-{
-	GaimMenuAction *action = gaim_menu_action_new(label, callback, data, NULL);
-	gnt_append_menu_action(menu, action, NULL);
-	g_signal_connect_swapped(G_OBJECT(menu), "destroy",
-			G_CALLBACK(gaim_menu_action_free), action);
-}
-
-static void
-chat_components_edit_ok(GaimChat *chat, GaimRequestFields *allfields)
-{
-	GList *groups, *fields;
-
-	for (groups = gaim_request_fields_get_groups(allfields); groups; groups = groups->next) {
-		fields = gaim_request_field_group_get_fields(groups->data);
-		for (; fields; fields = fields->next) {
-			GaimRequestField *field = fields->data;
-			const char *id;
-			char *val;
-
-			id = gaim_request_field_get_id(field);
-			if (gaim_request_field_get_type(field) == GAIM_REQUEST_FIELD_INTEGER)
-				val = g_strdup_printf("%d", gaim_request_field_int_get_value(field));
-			else
-				val = g_strdup(gaim_request_field_string_get_value(field));
-
-			g_hash_table_replace(chat->components, g_strdup(id), val);  /* val should not be free'd */
-		}
-	}
-}
-
-static void
-chat_components_edit(GaimChat *chat, GaimBlistNode *selected)
-{
-	GaimRequestFields *fields = gaim_request_fields_new();
-	GaimRequestFieldGroup *group = gaim_request_field_group_new(NULL);
-	GaimRequestField *field;
-	GList *parts, *iter;
-	struct proto_chat_entry *pce;
-
-	gaim_request_fields_add_group(fields, group);
-
-	parts = GAIM_PLUGIN_PROTOCOL_INFO(chat->account->gc->prpl)->chat_info(chat->account->gc);
-
-	for (iter = parts; iter; iter = iter->next) {
-		pce = iter->data;
-		if (pce->is_int) {
-			int val;
-			const char *str = g_hash_table_lookup(chat->components, pce->identifier);
-			if (!str || sscanf(str, "%d", &val) != 1)
-				val = pce->min;
-			field = gaim_request_field_int_new(pce->identifier, pce->label, val);
-		} else {
-			field = gaim_request_field_string_new(pce->identifier, pce->label,
-					g_hash_table_lookup(chat->components, pce->identifier), FALSE);
-		}
-
-		gaim_request_field_group_add_field(group, field);
-		g_free(pce);
-	}
-
-	g_list_free(parts);
-
-	gaim_request_fields(NULL, _("Edit Chat"), NULL, _("Please Update the necessary fields."),
-			fields, _("Edit"), G_CALLBACK(chat_components_edit_ok), _("Cancel"), NULL, chat);
-}
-
-static void
-autojoin_toggled(GntMenuItem *item, gpointer data)
-{
-	GaimMenuAction *action = data;
-	gaim_blist_node_set_bool(action->data, "gnt-autojoin",
-				gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item)));
-}
-
-static void
-create_chat_menu(GntMenu *menu, GaimChat *chat)
-{
-	GaimMenuAction *action = gaim_menu_action_new(_("Auto-join"), NULL, chat, NULL);
-	GntMenuItem *check = gnt_menuitem_check_new(action->label);
-	gnt_menuitem_check_set_checked(GNT_MENUITEM_CHECK(check),
-				gaim_blist_node_get_bool((GaimBlistNode*)chat, "gnt-autojoin"));
-	gnt_menu_add_item(menu, check);
-	gnt_menuitem_set_callback(check, autojoin_toggled, action);
-	g_signal_connect_swapped(G_OBJECT(menu), "destroy",
-			G_CALLBACK(gaim_menu_action_free), action);
-
-	add_custom_action(menu, _("Edit Settings"), (GaimCallback)chat_components_edit, chat);
-}
-
-static void
-gg_add_buddy(GaimGroup *grp, GaimBlistNode *selected)
-{
-	gaim_blist_request_add_buddy(NULL, NULL, grp ? grp->name : NULL, NULL);
-}
-
-static void
-gg_add_group(GaimGroup *grp, GaimBlistNode *selected)
-{
-	gaim_blist_request_add_group();
-}
-
-static void
-gg_add_chat(GaimGroup *grp, GaimBlistNode *selected)
-{
-	gaim_blist_request_add_chat(NULL, grp, NULL, NULL);
-}
-
-static void
-create_group_menu(GntMenu *menu, GaimGroup *group)
-{
-	add_custom_action(menu, _("Add Buddy"),
-			GAIM_CALLBACK(gg_add_buddy), group);
-	add_custom_action(menu, _("Add Chat"),
-			GAIM_CALLBACK(gg_add_chat), group);
-	add_custom_action(menu, _("Add Group"),
-			GAIM_CALLBACK(gg_add_group), group);
-}
-
-static void
-gg_blist_get_buddy_info_cb(GaimBuddy *buddy, GaimBlistNode *selected)
-{
-	serv_get_info(buddy->account->gc, gaim_buddy_get_name(buddy));
-}
-
-static void
-gg_blist_menu_send_file_cb(GaimBuddy *buddy, GaimBlistNode *selected)
-{
-	serv_send_file(buddy->account->gc, buddy->name, NULL);
-}
-
-static void
-gg_blist_pounce_node_cb(GaimBlistNode *node, GaimBlistNode *selected)
-{
-	GaimBuddy *b;
-	if (GAIM_BLIST_NODE_IS_CONTACT(node))
-		b = gaim_contact_get_priority_buddy((GaimContact *)node);
-	else
-		b = (GaimBuddy *)node;
-	gg_pounce_editor_show(b->account, b->name, NULL);
-}
-
-
-static void
-create_buddy_menu(GntMenu *menu, GaimBuddy *buddy)
-{
-	GaimPluginProtocolInfo *prpl_info;
-
-	prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(buddy->account->gc->prpl);
-	if (prpl_info && prpl_info->get_info)
-	{
-		add_custom_action(menu, _("Get Info"),
-				GAIM_CALLBACK(gg_blist_get_buddy_info_cb), buddy);
-	}
-
-	add_custom_action(menu, _("Add Buddy Pounce"),
-			GAIM_CALLBACK(gg_blist_pounce_node_cb), buddy);
-
-	if (prpl_info && prpl_info->send_file)
-	{
-		if (!prpl_info->can_receive_file ||
-			prpl_info->can_receive_file(buddy->account->gc, buddy->name))
-			add_custom_action(menu, _("Send File"),
-					GAIM_CALLBACK(gg_blist_menu_send_file_cb), buddy);
-	}
-#if 0
-	add_custom_action(tree, _("View Log"),
-			GAIM_CALLBACK(gg_blist_view_log_cb)), buddy);
-#endif
-
-	/* Protocol actions */
-	append_proto_menu(menu,
-			gaim_account_get_connection(gaim_buddy_get_account(buddy)),
-			(GaimBlistNode*)buddy);
-}
-
-static void
-append_extended_menu(GntMenu *menu, GaimBlistNode *node)
-{
-	GList *iter;
-
-	for (iter = gaim_blist_node_get_extended_menu(node);
-			iter; iter = g_list_delete_link(iter, iter))
-	{
-		gnt_append_menu_action(menu, iter->data, NULL);
-	}
-}
-
-/* Xerox'd from gtkdialogs.c:gaim_gtkdialogs_remove_contact_cb */
-static void
-remove_contact(GaimContact *contact)
-{
-	GaimBlistNode *bnode, *cnode;
-	GaimGroup *group;
-
-	cnode = (GaimBlistNode *)contact;
-	group = (GaimGroup*)cnode->parent;
-	for (bnode = cnode->child; bnode; bnode = bnode->next) {
-		GaimBuddy *buddy = (GaimBuddy*)bnode;
-		if (gaim_account_is_connected(buddy->account))
-			gaim_account_remove_buddy(buddy->account, buddy, group);
-	}
-	gaim_blist_remove_contact(contact);
-}
-
-static void
-rename_blist_node(GaimBlistNode *node, const char *newname)
-{
-	const char *name = newname;
-	if (name && !*name)
-		name = NULL;
-
-	if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
-		GaimContact *contact = (GaimContact*)node;
-		GaimBuddy *buddy = gaim_contact_get_priority_buddy(contact);
-		gaim_blist_alias_contact(contact, name);
-		gaim_blist_alias_buddy(buddy, name);
-		serv_alias_buddy(buddy);
-	} else if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
-		gaim_blist_alias_buddy((GaimBuddy*)node, name);
-		serv_alias_buddy((GaimBuddy*)node);
-	} else if (GAIM_BLIST_NODE_IS_CHAT(node))
-		gaim_blist_alias_chat((GaimChat*)node, name);
-	else if (GAIM_BLIST_NODE_IS_GROUP(node) && (name != NULL))
-		gaim_blist_rename_group((GaimGroup*)node, name);
-	else
-		g_return_if_reached();
-}
-
-static void
-gg_blist_rename_node_cb(GaimBlistNode *node, GaimBlistNode *selected)
-{
-	const char *name = NULL;
-	char *prompt;
-
-	if (GAIM_BLIST_NODE_IS_CONTACT(node))
-		name = gaim_contact_get_alias((GaimContact*)node);
-	else if (GAIM_BLIST_NODE_IS_BUDDY(node))
-		name = gaim_buddy_get_contact_alias((GaimBuddy*)node);
-	else if (GAIM_BLIST_NODE_IS_CHAT(node))
-		name = gaim_chat_get_name((GaimChat*)node);
-	else if (GAIM_BLIST_NODE_IS_GROUP(node))
-		name = ((GaimGroup*)node)->name;
-	else
-		g_return_if_reached();
-
-	prompt = g_strdup_printf(_("Please enter the new name for %s"), name);
-
-	gaim_request_input(node, _("Rename"), prompt, _("Enter empty string to reset the name."),
-			name, FALSE, FALSE, NULL, _("Rename"), G_CALLBACK(rename_blist_node),
-			_("Cancel"), NULL, node);
-
-	g_free(prompt);
-}
-
-/* Xeroxed from gtkdialogs.c:gaim_gtkdialogs_remove_group_cb*/
-static void
-remove_group(GaimGroup *group)
-{
-	GaimBlistNode *cnode, *bnode;
-
-	cnode = ((GaimBlistNode*)group)->child;
-
-	while (cnode) {
-		if (GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
-			bnode = cnode->child;
-			cnode = cnode->next;
-			while (bnode) {
-				GaimBuddy *buddy;
-				if (GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
-					buddy = (GaimBuddy*)bnode;
-					bnode = bnode->next;
-					if (gaim_account_is_connected(buddy->account)) {
-						gaim_account_remove_buddy(buddy->account, buddy, group);
-						gaim_blist_remove_buddy(buddy);
-					}
-				} else {
-					bnode = bnode->next;
-				}
-			}
-		} else if (GAIM_BLIST_NODE_IS_CHAT(cnode)) {
-			GaimChat *chat = (GaimChat *)cnode;
-			cnode = cnode->next;
-			if (gaim_account_is_connected(chat->account))
-				gaim_blist_remove_chat(chat);
-		} else {
-			cnode = cnode->next;
-		}
-	}
-
-	gaim_blist_remove_group(group);
-}
-
-static void
-gg_blist_remove_node(GaimBlistNode *node)
-{
-	if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
-		remove_contact((GaimContact*)node);
-	} else if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
-		GaimBuddy *buddy = (GaimBuddy*)node;
-		GaimGroup *group = gaim_buddy_get_group(buddy);
-		gaim_account_remove_buddy(gaim_buddy_get_account(buddy), buddy, group);
-		gaim_blist_remove_buddy(buddy);
-	} else if (GAIM_BLIST_NODE_IS_CHAT(node)) {
-		gaim_blist_remove_chat((GaimChat*)node);
-	} else if (GAIM_BLIST_NODE_IS_GROUP(node)) {
-		remove_group((GaimGroup*)node);
-	}
-}
-
-static void
-gg_blist_remove_node_cb(GaimBlistNode *node, GaimBlistNode *selected)
-{
-	char *primary;
-	const char *name, *sec = NULL;
-
-	/* XXX: could be a contact */
-	if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
-		GaimContact *c = (GaimContact*)node;
-		name = gaim_contact_get_alias(c);
-		if (c->totalsize > 1)
-			sec = _("Removing this contact will also remove all the buddies in the contact");
-	} else if (GAIM_BLIST_NODE_IS_BUDDY(node))
-		name = gaim_buddy_get_name((GaimBuddy*)node);
-	else if (GAIM_BLIST_NODE_IS_CHAT(node))
-		name = gaim_chat_get_name((GaimChat*)node);
-	else if (GAIM_BLIST_NODE_IS_GROUP(node))
-	{
-		name = ((GaimGroup*)node)->name;
-		sec = _("Removing this group will also remove all the buddies in the group");
-	}
-	else
-		return;
-
-	primary = g_strdup_printf(_("Are you sure you want to remove %s?"), name);
-
-	/* XXX: anything to do with the returned ui-handle? */
-	gaim_request_action(node, _("Confirm Remove"),
-			primary, sec,
-			1, node, 2,
-			_("Remove"), gg_blist_remove_node,
-			_("Cancel"), NULL);
-	g_free(primary);
-}
-
-static void
-gg_blist_toggle_tag_buddy(GaimBlistNode *node)
-{
-	GList *iter;
-	if (node == NULL)
-		return;
-	if (GAIM_BLIST_NODE_IS_CHAT(node) || GAIM_BLIST_NODE_IS_GROUP(node))
-		return;
-	if (ggblist->tagged && (iter = g_list_find(ggblist->tagged, node)) != NULL) {
-		ggblist->tagged = g_list_delete_link(ggblist->tagged, iter);
-	} else {
-		ggblist->tagged = g_list_prepend(ggblist->tagged, node);
-	}
-	if (GAIM_BLIST_NODE_IS_CONTACT(node))
-		node = (GaimBlistNode*)gaim_contact_get_priority_buddy((GaimContact*)node);
-	update_buddy_display((GaimBuddy*)node, ggblist);
-}
-
-static void
-gg_blist_place_tagged(GaimBlistNode *target)
-{
-	GaimGroup *tg = NULL;
-	GaimContact *tc = NULL;
-
-	if (target == NULL)
-		return;
-
-	/* This target resolution probably needs more clarification; for
-	 * example, if I tag a buddy in a contact, then place on
-	 * another buddy in the same contact, I probably intend to
-	 * place the tagged buddy immediately after (before?) the
-	 * target buddy -- this will simply move the tagged buddy
-	 * within the same contact without reference to position. */
-	if (GAIM_BLIST_NODE_IS_GROUP(target))
-		tg = (GaimGroup*)target;
-	else if (GAIM_BLIST_NODE_IS_CONTACT(target))
-		tc = (GaimContact*)target;
-	else /* Buddy or Chat */
-		tc = (GaimContact*)target->parent;
-
-	if (ggblist->tagged) {
-		GList *list = ggblist->tagged;
-		ggblist->tagged = NULL;
-
-		while (list) {
-			GaimBlistNode *node = list->data;
-			list = g_list_delete_link(list, list);
-			if (tg) {
-				if (GAIM_BLIST_NODE_IS_CONTACT(node))
-					gaim_blist_add_contact((GaimContact*)node, tg, NULL);
-				else
-					gaim_blist_add_buddy((GaimBuddy*)node, NULL, tg, NULL);
-			} else {
-				if (GAIM_BLIST_NODE_IS_BUDDY(node))
-					gaim_blist_add_buddy((GaimBuddy*)node, tc,
-						gaim_buddy_get_group(gaim_contact_get_priority_buddy(tc)), NULL);
-				else if (GAIM_BLIST_NODE_IS_CONTACT(node))
-					gaim_blist_merge_contact((GaimContact*)node, target);
-			}
-		}
-	}
-}
-
-static void
-context_menu_destroyed(GntWidget *widget, GGBlist *ggblist)
-{
-	ggblist->context = NULL;
-}
-
-static void
-draw_context_menu(GGBlist *ggblist)
-{
-	GaimBlistNode *node = NULL;
-	GntWidget *context = NULL;
-	GntTree *tree = NULL;
-	int x, y, top, width;
-	char *title = NULL;
-
-	tree = GNT_TREE(ggblist->tree);
-
-	node = gnt_tree_get_selection_data(tree);
-
-	if (ggblist->tooltip)
-		remove_tooltip(ggblist);
-
-	ggblist->cnode = node;
-
-	ggblist->context = context = gnt_menu_new(GNT_MENU_POPUP);
-	g_signal_connect(G_OBJECT(context), "destroy", G_CALLBACK(context_menu_destroyed), ggblist);
-
-	if (!node) {
-		create_group_menu(GNT_MENU(context), NULL);
-		title = g_strdup(_("Buddy List"));
-	} else if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
-		create_buddy_menu(GNT_MENU(context),
-			gaim_contact_get_priority_buddy((GaimContact*)node));
-		title = g_strdup(gaim_contact_get_alias((GaimContact*)node));
-	} else if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
-		GaimBuddy *buddy = (GaimBuddy *)node;
-		create_buddy_menu(GNT_MENU(context), buddy);
-		title = g_strdup(gaim_buddy_get_name(buddy));
-	} else if (GAIM_BLIST_NODE_IS_CHAT(node)) {
-		GaimChat *chat = (GaimChat*)node;
-		create_chat_menu(GNT_MENU(context), chat);
-		title = g_strdup(gaim_chat_get_name(chat));
-	} else if (GAIM_BLIST_NODE_IS_GROUP(node)) {
-		GaimGroup *group = (GaimGroup *)node;
-		create_group_menu(GNT_MENU(context), group);
-		title = g_strdup(group->name);
-	}
-
-	append_extended_menu(GNT_MENU(context), node);
-
-	/* These are common for everything */
-	if (node) {
-		add_custom_action(GNT_MENU(context), _("Rename"),
-				GAIM_CALLBACK(gg_blist_rename_node_cb), node);
-		add_custom_action(GNT_MENU(context), _("Remove"),
-				GAIM_CALLBACK(gg_blist_remove_node_cb), node);
-
-		if (ggblist->tagged && (GAIM_BLIST_NODE_IS_CONTACT(node)
-				|| GAIM_BLIST_NODE_IS_GROUP(node))) {
-			add_custom_action(GNT_MENU(context), _("Place tagged"),
-					GAIM_CALLBACK(gg_blist_place_tagged), node);
-		}
-
-		if (GAIM_BLIST_NODE_IS_BUDDY(node) || GAIM_BLIST_NODE_IS_CONTACT(node)) {
-			add_custom_action(GNT_MENU(context), _("Toggle Tag"),
-					GAIM_CALLBACK(gg_blist_toggle_tag_buddy), node);
-		}
-	}
-
-	/* Set the position for the popup */
-	gnt_widget_get_position(GNT_WIDGET(tree), &x, &y);
-	gnt_widget_get_size(GNT_WIDGET(tree), &width, NULL);
-	top = gnt_tree_get_selection_visible_line(tree);
-
-	x += width;
-	y += top - 1;
-
-	gnt_widget_set_position(context, x, y);
-	gnt_screen_menu_show(GNT_MENU(context));
-	g_free(title);
-}
-
-static void
-tooltip_for_buddy(GaimBuddy *buddy, GString *str)
-{
-	GaimPlugin *prpl;
-	GaimPluginProtocolInfo *prpl_info;
-	GaimAccount *account;
-	GaimNotifyUserInfo *user_info;
-	const char *alias = gaim_buddy_get_alias(buddy);
-	char *tmp, *strip;
-
-	user_info = gaim_notify_user_info_new();
-
-	account = gaim_buddy_get_account(buddy);
-
-	if (g_utf8_collate(gaim_buddy_get_name(buddy), alias))
-		gaim_notify_user_info_add_pair(user_info, _("Nickname"), alias);
-
-	tmp = g_strdup_printf("%s (%s)",
-			gaim_account_get_username(account),
-			gaim_account_get_protocol_name(account));
-	gaim_notify_user_info_add_pair(user_info, _("Account"), tmp);
-	g_free(tmp);
-	
-	prpl = gaim_find_prpl(gaim_account_get_protocol_id(account));
-	prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
-	if (prpl_info && prpl_info->tooltip_text) {
-		prpl_info->tooltip_text(buddy, user_info, TRUE);
-	}
-
-	if (gaim_prefs_get_bool("/gaim/gnt/blist/idletime")) {
-		GaimPresence *pre = gaim_buddy_get_presence(buddy);
-		if (gaim_presence_is_idle(pre)) {
-			time_t idle = gaim_presence_get_idle_time(pre);
-			if (idle > 0) {
-				char *st = gaim_str_seconds_to_string(time(NULL) - idle);
-				gaim_notify_user_info_add_pair(user_info, _("Idle"), st);
-				g_free(st);
-			}
-		}
-	}
-	
-	tmp = gaim_notify_user_info_get_text_with_newline(user_info, "<BR>");
-	gaim_notify_user_info_destroy(user_info);
-
-	strip = gaim_markup_strip_html(tmp);
-	g_string_append(str, strip);
-	g_free(strip);
-	g_free(tmp);
-}
-
-static GString*
-make_sure_text_fits(GString *string)
-{
-	int maxw = getmaxx(stdscr) - 3;
-	char *str = gnt_util_onscreen_fit_string(string->str, maxw);
-	string = g_string_assign(string, str);
-	g_free(str);
-	return string;
-}
-
-static gboolean
-draw_tooltip_real(GGBlist *ggblist)
-{
-	GaimBlistNode *node;
-	int x, y, top, width, w, h;
-	GString *str;
-	GntTree *tree;
-	GntWidget *widget, *box, *tv;
-	char *title = NULL;
-	int lastseen = 0;
-
-	widget = ggblist->tree;
-	tree = GNT_TREE(widget);
-
-	if (!gnt_widget_has_focus(ggblist->tree) || 
-			(ggblist->context && !GNT_WIDGET_IS_FLAG_SET(ggblist->context, GNT_WIDGET_INVISIBLE)))
-		return FALSE;
-
-	if (ggblist->tooltip)
-	{
-		/* XXX: Once we can properly redraw on expose events, this can be removed at the end
-		 * to avoid the blinking*/
-		remove_tooltip(ggblist);
-	}
-
-	node = gnt_tree_get_selection_data(tree);
-	if (!node)
-		return FALSE;
-
-	str = g_string_new("");
-
-	if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
-		GaimBuddy *pr = gaim_contact_get_priority_buddy((GaimContact*)node);
-		gboolean offline = !GAIM_BUDDY_IS_ONLINE(pr);
-		gboolean showoffline = gaim_prefs_get_bool(PREF_ROOT "/showoffline");
-		const char *name = gaim_buddy_get_name(pr);
-
-		title = g_strdup(name);
-		tooltip_for_buddy(pr, str);
-		for (node = node->child; node; node = node->next) {
-			GaimBuddy *buddy = (GaimBuddy*)node;
-			if (offline) {
-				int value = gaim_blist_node_get_int(node, "last_seen");
-				if (value > lastseen)
-					lastseen = value;
-			}
-			if (node == (GaimBlistNode*)pr)
-				continue;
-			if (!gaim_account_is_connected(buddy->account))
-				continue;
-			if (!showoffline && !GAIM_BUDDY_IS_ONLINE(buddy))
-				continue;
-			str = g_string_append(str, "\n----------\n");
-			tooltip_for_buddy(buddy, str);
-		}
-	} else if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
-		GaimBuddy *buddy = (GaimBuddy *)node;
-		tooltip_for_buddy(buddy, str);
-		title = g_strdup(gaim_buddy_get_name(buddy));
-		if (!GAIM_BUDDY_IS_ONLINE((GaimBuddy*)node))
-			lastseen = gaim_blist_node_get_int(node, "last_seen");
-	} else if (GAIM_BLIST_NODE_IS_GROUP(node)) {
-		GaimGroup *group = (GaimGroup *)node;
-
-		g_string_append_printf(str, _("Online: %d\nTotal: %d"),
-						gaim_blist_get_group_online_count(group),
-						gaim_blist_get_group_size(group, FALSE));
-
-		title = g_strdup(group->name);
-	} else if (GAIM_BLIST_NODE_IS_CHAT(node)) {
-		GaimChat *chat = (GaimChat *)node;
-		GaimAccount *account = chat->account;
-
-		g_string_append_printf(str, _("Account: %s (%s)"),
-				gaim_account_get_username(account),
-				gaim_account_get_protocol_name(account));
-
-		title = g_strdup(gaim_chat_get_name(chat));
-	} else {
-		g_string_free(str, TRUE);
-		return FALSE;
-	}
-
-	if (lastseen > 0) {
-		char *tmp = gaim_str_seconds_to_string(time(NULL) - lastseen);
-		g_string_append_printf(str, _("\nLast Seen: %s ago"), tmp);
-		g_free(tmp);
-	}
-
-	gnt_widget_get_position(widget, &x, &y);
-	gnt_widget_get_size(widget, &width, NULL);
-	top = gnt_tree_get_selection_visible_line(tree);
-
-	x += width;
-	y += top - 1;
-
-	box = gnt_box_new(FALSE, FALSE);
-	gnt_box_set_toplevel(GNT_BOX(box), TRUE);
-	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW);
-	gnt_box_set_title(GNT_BOX(box), title);
-
-	str = make_sure_text_fits(str);
-	gnt_util_get_text_bound(str->str, &w, &h);
-	h = MAX(2, h);
-	tv = gnt_text_view_new();
-	gnt_widget_set_size(tv, w + 1, h);
-	gnt_box_add_widget(GNT_BOX(box), tv);
-
-	gnt_widget_set_position(box, x, y);
-	GNT_WIDGET_UNSET_FLAGS(box, GNT_WIDGET_CAN_TAKE_FOCUS);
-	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_TRANSIENT);
-	gnt_widget_draw(box);
-
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(tv), str->str, GNT_TEXT_FLAG_NORMAL);
-	gnt_text_view_scroll(GNT_TEXT_VIEW(tv), 0);
-
-	g_free(title);
-	g_string_free(str, TRUE);
-	ggblist->tooltip = box;
-	ggblist->tnode = node;
-
-	gnt_widget_set_name(ggblist->tooltip, "tooltip");
-	return FALSE;
-}
-
-static void
-draw_tooltip(GGBlist *ggblist)
-{
-	/* When an account has signed off, it removes one buddy at a time.
-	 * Drawing the tooltip after removing each buddy is expensive. On
-	 * top of that, if the selected buddy belongs to the disconnected
-	 * account, then retreiving the tooltip for that causes crash. So
-	 * let's make sure we wait for all the buddies to be removed first.*/
-	int id = g_timeout_add(0, (GSourceFunc)draw_tooltip_real, ggblist);
-	g_object_set_data_full(G_OBJECT(ggblist->window), "draw_tooltip_calback",
-				GINT_TO_POINTER(id), (GDestroyNotify)g_source_remove);
-}
-
-static void
-selection_changed(GntWidget *widget, gpointer old, gpointer current, GGBlist *ggblist)
-{
-	draw_tooltip(ggblist);
-}
-
-static gboolean
-context_menu(GntWidget *widget, GGBlist *ggblist)
-{
-	draw_context_menu(ggblist);
-	return TRUE;
-}
-
-static gboolean
-key_pressed(GntWidget *widget, const char *text, GGBlist *ggblist)
-{
-	if (text[0] == 27 && text[1] == 0) {
-		/* Escape was pressed */
-		remove_peripherals(ggblist);
-	} else if (strcmp(text, GNT_KEY_CTRL_O) == 0) {
-		gaim_prefs_set_bool(PREF_ROOT "/showoffline",
-				!gaim_prefs_get_bool(PREF_ROOT "/showoffline"));
-	} else if (GNT_TREE(ggblist->tree)->search == NULL) {
-		if (strcmp(text, "t") == 0) {
-			gg_blist_toggle_tag_buddy(gnt_tree_get_selection_data(GNT_TREE(ggblist->tree)));
-			gnt_bindable_perform_action_named(GNT_BINDABLE(ggblist->tree), "move-down");
-		} else if (strcmp(text, "a") == 0) {
-			gg_blist_place_tagged(gnt_tree_get_selection_data(GNT_TREE(ggblist->tree)));
-		} else
-			return FALSE;
-	} else
-		return FALSE;
-
-	return TRUE;
-}
-
-static void
-update_buddy_display(GaimBuddy *buddy, GGBlist *ggblist)
-{
-	GaimContact *contact;
-	GntTextFormatFlags bflag = 0, cflag = 0;
-	
-	contact = gaim_buddy_get_contact(buddy);
-
-	gnt_tree_change_text(GNT_TREE(ggblist->tree), buddy, 0, get_display_name((GaimBlistNode*)buddy));
-	gnt_tree_change_text(GNT_TREE(ggblist->tree), contact, 0, get_display_name((GaimBlistNode*)contact));
-
-	if (ggblist->tagged && g_list_find(ggblist->tagged, buddy))
-		bflag |= GNT_TEXT_FLAG_BOLD;
-	if (ggblist->tagged && g_list_find(ggblist->tagged, contact))
-		cflag |= GNT_TEXT_FLAG_BOLD;
-
-	if (ggblist->tnode == (GaimBlistNode*)buddy)
-		draw_tooltip(ggblist);
-
-	if (gaim_presence_is_idle(gaim_buddy_get_presence(buddy))) {
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, bflag | GNT_TEXT_FLAG_DIM);
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, cflag | GNT_TEXT_FLAG_DIM);
-	} else {
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, bflag);
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, cflag);
-	}
-}
-
-static void
-buddy_status_changed(GaimBuddy *buddy, GaimStatus *old, GaimStatus *now, GGBlist *ggblist)
-{
-	update_buddy_display(buddy, ggblist);
-}
-
-static void
-buddy_idle_changed(GaimBuddy *buddy, int old, int new, GGBlist *ggblist)
-{
-	update_buddy_display(buddy, ggblist);
-}
-
-static void
-remove_peripherals(GGBlist *ggblist)
-{
-	if (ggblist->tooltip)
-		remove_tooltip(ggblist);
-	else if (ggblist->context)
-		gnt_widget_destroy(ggblist->context);
-}
-
-static void
-size_changed_cb(GntWidget *w, int wi, int h)
-{
-	int width, height;
-	gnt_widget_get_size(w, &width, &height);
-	gaim_prefs_set_int(PREF_ROOT "/size/width", width);
-	gaim_prefs_set_int(PREF_ROOT "/size/height", height);
-}
-
-static void
-save_position_cb(GntWidget *w, int x, int y)
-{
-	gaim_prefs_set_int(PREF_ROOT "/position/x", x);
-	gaim_prefs_set_int(PREF_ROOT "/position/y", y);
-}
-
-static void
-reset_blist_window(GntWidget *window, gpointer null)
-{
-	GaimBlistNode *node;
-	gaim_signals_disconnect_by_handle(gg_blist_get_handle());
-	gaim_get_blist()->ui_data = NULL;
-
-	node = gaim_blist_get_root();
-	while (node) {
-		node->ui_data = NULL;
-		node = gaim_blist_node_next(node, TRUE);
-	}
-
-	if (ggblist->typing)
-		g_source_remove(ggblist->typing);
-	remove_peripherals(ggblist);
-	if (ggblist->tagged)
-		g_list_free(ggblist->tagged);
-	g_free(ggblist);
-	ggblist = NULL;
-}
-
-static void
-populate_buddylist()
-{
-	GaimBlistNode *node;
-	GaimBuddyList *list;
-
-	if (strcmp(gaim_prefs_get_string(PREF_ROOT "/sort_type"), "text") == 0) {
-		gnt_tree_set_compare_func(GNT_TREE(ggblist->tree),
-			(GCompareFunc)blist_node_compare_text);
-	} else if (strcmp(gaim_prefs_get_string(PREF_ROOT "/sort_type"), "status") == 0) {
-		gnt_tree_set_compare_func(GNT_TREE(ggblist->tree),
-			(GCompareFunc)blist_node_compare_status);
-	} else if (strcmp(gaim_prefs_get_string(PREF_ROOT "/sort_type"), "log") == 0) {
-		gnt_tree_set_compare_func(GNT_TREE(ggblist->tree),
-			(GCompareFunc)blist_node_compare_log);
-	}
-	
-	list = gaim_get_blist();
-	node = gaim_blist_get_root();
-	while (node)
-	{
-		node_update(list, node);
-		node = gaim_blist_node_next(node, FALSE);
-	}
-}
-
-static void
-destroy_status_list(GList *list)
-{
-	g_list_foreach(list, (GFunc)g_free, NULL);
-	g_list_free(list);
-}
-
-static void
-populate_status_dropdown()
-{
-	int i;
-	GList *iter;
-	GList *items = NULL;
-	StatusBoxItem *item = NULL;
-
-	/* First the primitives */
-	GaimStatusPrimitive prims[] = {GAIM_STATUS_AVAILABLE, GAIM_STATUS_AWAY,
-			GAIM_STATUS_INVISIBLE, GAIM_STATUS_OFFLINE, GAIM_STATUS_UNSET};
-
-	gnt_combo_box_remove_all(GNT_COMBO_BOX(ggblist->status));
-
-	for (i = 0; prims[i] != GAIM_STATUS_UNSET; i++)
-	{
-		item = g_new0(StatusBoxItem, 1);
-		item->type = STATUS_PRIMITIVE;
-		item->u.prim = prims[i];
-		items = g_list_prepend(items, item);
-		gnt_combo_box_add_data(GNT_COMBO_BOX(ggblist->status), item,
-				gaim_primitive_get_name_from_type(prims[i]));
-	}
-
-	/* Now the popular statuses */
-	for (iter = gaim_savedstatuses_get_popular(6); iter; iter = iter->next)
-	{
-		item = g_new0(StatusBoxItem, 1);
-		item->type = STATUS_SAVED_POPULAR;
-		item->u.saved = iter->data;
-		items = g_list_prepend(items, item);
-		gnt_combo_box_add_data(GNT_COMBO_BOX(ggblist->status), item,
-				gaim_savedstatus_get_title(iter->data));
-	}
-
-	/* New savedstatus */
-	item = g_new0(StatusBoxItem, 1);
-	item->type = STATUS_SAVED_NEW;
-	items = g_list_prepend(items, item);
-	gnt_combo_box_add_data(GNT_COMBO_BOX(ggblist->status), item,
-			_("New..."));
-
-	/* More savedstatuses */
-	item = g_new0(StatusBoxItem, 1);
-	item->type = STATUS_SAVED_ALL;
-	items = g_list_prepend(items, item);
-	gnt_combo_box_add_data(GNT_COMBO_BOX(ggblist->status), item,
-			_("Saved..."));
-
-	/* The keys for the combobox are created here, and never used
-	 * anywhere else. So make sure the keys are freed when the widget
-	 * is destroyed. */
-	g_object_set_data_full(G_OBJECT(ggblist->status), "list of statuses",
-			items, (GDestroyNotify)destroy_status_list);
-}
-
-static void
-redraw_blist(const char *name, GaimPrefType type, gconstpointer val, gpointer data)
-{
-	GaimBlistNode *node, *sel;
-	if (ggblist == NULL || ggblist->window == NULL)
-		return;
-
-	sel = gnt_tree_get_selection_data(GNT_TREE(ggblist->tree));
-	gnt_tree_remove_all(GNT_TREE(ggblist->tree));
-	node = gaim_blist_get_root();
-	for (; node; node = gaim_blist_node_next(node, TRUE))
-		node->ui_data = NULL;
-	populate_buddylist();
-	gnt_tree_set_selected(GNT_TREE(ggblist->tree), sel);
-	draw_tooltip(ggblist);
-}
-
-void gg_blist_init()
-{
-	gaim_prefs_add_none(PREF_ROOT);
-	gaim_prefs_add_none(PREF_ROOT "/size");
-	gaim_prefs_add_int(PREF_ROOT "/size/width", 20);
-	gaim_prefs_add_int(PREF_ROOT "/size/height", 17);
-	gaim_prefs_add_none(PREF_ROOT "/position");
-	gaim_prefs_add_int(PREF_ROOT "/position/x", 0);
-	gaim_prefs_add_int(PREF_ROOT "/position/y", 0);
-	gaim_prefs_add_bool(PREF_ROOT "/idletime", TRUE);
-	gaim_prefs_add_bool(PREF_ROOT "/showoffline", FALSE);
-	gaim_prefs_add_string(PREF_ROOT "/sort_type", "text");
-
-	gaim_prefs_connect_callback(gg_blist_get_handle(),
-			PREF_ROOT "/showoffline", redraw_blist, NULL);
-	gaim_prefs_connect_callback(gg_blist_get_handle(),
-			PREF_ROOT "/sort_type", redraw_blist, NULL);
-
-	gaim_signal_connect(gaim_connections_get_handle(), "signed-on", gaim_blist_get_handle(),
-			G_CALLBACK(account_signed_on_cb), NULL);
-	return;
-}
-
-static gboolean
-remove_typing_cb(gpointer null)
-{
-	GaimSavedStatus *current;
-	const char *message, *newmessage;
-	GaimStatusPrimitive prim, newprim;
-	StatusBoxItem *item;
-
-	current = gaim_savedstatus_get_current();
-	message = gaim_savedstatus_get_message(current);
-	prim = gaim_savedstatus_get_type(current);
-
-	newmessage = gnt_entry_get_text(GNT_ENTRY(ggblist->statustext));
-	item = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(ggblist->status));
-	g_return_val_if_fail(item->type == STATUS_PRIMITIVE, FALSE);
-	newprim = item->u.prim;
-
-	if (newprim != prim || ((message && !newmessage) ||
-				(!message && newmessage) ||
-				(message && newmessage && g_utf8_collate(message, newmessage) != 0)))
-	{
-		GaimSavedStatus *status = gaim_savedstatus_find_transient_by_type_and_message(newprim, newmessage);
-									/* Holy Crap! That's a LAWNG function name */
-		if (status == NULL)
-		{
-			status = gaim_savedstatus_new(NULL, newprim);
-			gaim_savedstatus_set_message(status, newmessage);
-		}
-
-		gaim_savedstatus_activate(status);
-	}
-
-	gnt_box_give_focus_to_child(GNT_BOX(ggblist->window), ggblist->tree);
-	if (ggblist->typing)
-		g_source_remove(ggblist->typing);
-	ggblist->typing = 0;
-	return FALSE;
-}
-
-static void
-status_selection_changed(GntComboBox *box, StatusBoxItem *old, StatusBoxItem *now, gpointer null)
-{
-	gnt_entry_set_text(GNT_ENTRY(ggblist->statustext), NULL);
-	if (now->type == STATUS_SAVED_POPULAR)
-	{
-		/* Set the status immediately */
-		gaim_savedstatus_activate(now->u.saved);
-	}
-	else if (now->type == STATUS_PRIMITIVE)
-	{
-		/* Move the focus to the entry box */
-		/* XXX: Make sure the selected status can have a message */
-		gnt_box_move_focus(GNT_BOX(ggblist->window), 1);
-		ggblist->typing = g_timeout_add(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, NULL);
-	}
-	else if (now->type == STATUS_SAVED_ALL)
-	{
-		/* Restore the selection to reflect current status. */
-		savedstatus_changed(gaim_savedstatus_get_current(), NULL);
-		gnt_box_give_focus_to_child(GNT_BOX(ggblist->window), ggblist->tree);
-		gg_savedstatus_show_all();
-	}
-	else if (now->type == STATUS_SAVED_NEW)
-	{
-		savedstatus_changed(gaim_savedstatus_get_current(), NULL);
-		gnt_box_give_focus_to_child(GNT_BOX(ggblist->window), ggblist->tree);
-		gg_savedstatus_edit(NULL);
-	}
-	else
-		g_return_if_reached();
-}
-
-static gboolean
-status_text_changed(GntEntry *entry, const char *text, gpointer null)
-{
-	if ((text[0] == 27 || (text[0] == '\t' && text[1] == '\0')) && ggblist->typing == 0)
-		return FALSE;
-
-	if (ggblist->typing)
-		g_source_remove(ggblist->typing);
-	ggblist->typing = 0;
-
-	if (text[0] == '\r' && text[1] == 0)
-	{
-		/* Set the status only after you press 'Enter' */
-		remove_typing_cb(NULL);
-		return TRUE;
-	}
-
-	ggblist->typing = g_timeout_add(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, NULL);
-	return FALSE;
-}
-
-static void
-savedstatus_changed(GaimSavedStatus *now, GaimSavedStatus *old)
-{
-	GList *list;
-	GaimStatusPrimitive prim;
-	const char *message;
-	gboolean found = FALSE, saved = TRUE;
-
-	if (!ggblist)
-		return;
-
-	/* Block the signals we don't want to emit */
-	g_signal_handlers_block_matched(ggblist->status, G_SIGNAL_MATCH_FUNC,
-			0, 0, NULL, status_selection_changed, NULL);
-	g_signal_handlers_block_matched(ggblist->statustext, G_SIGNAL_MATCH_FUNC,
-			0, 0, NULL, status_text_changed, NULL);
-
-	prim = gaim_savedstatus_get_type(now);
-	message = gaim_savedstatus_get_message(now);
-
-	/* Rebuild the status dropdown */
-	populate_status_dropdown();
-
-	while (!found) {
-		list = g_object_get_data(G_OBJECT(ggblist->status), "list of statuses");
-		for (; list; list = list->next)
-		{
-			StatusBoxItem *item = list->data;
-			if ((saved && item->type != STATUS_PRIMITIVE && item->u.saved == now) ||
-					(!saved && item->type == STATUS_PRIMITIVE && item->u.prim == prim))
-			{
-				char *mess = gaim_unescape_html(message);
-				gnt_combo_box_set_selected(GNT_COMBO_BOX(ggblist->status), item);
-				gnt_entry_set_text(GNT_ENTRY(ggblist->statustext), mess);
-				gnt_widget_draw(ggblist->status);
-				g_free(mess);
-				found = TRUE;
-				break;
-			}
-		}
-		if (!saved)
-			break;
-		saved = FALSE;
-	}
-
-	g_signal_handlers_unblock_matched(ggblist->status, G_SIGNAL_MATCH_FUNC,
-			0, 0, NULL, status_selection_changed, NULL);
-	g_signal_handlers_unblock_matched(ggblist->statustext, G_SIGNAL_MATCH_FUNC,
-			0, 0, NULL, status_text_changed, NULL);
-}
-
-static int
-blist_node_compare_text(GaimBlistNode *n1, GaimBlistNode *n2)
-{
-	const char *s1, *s2;
-	char *us1, *us2;
-	int ret;
-	
-	g_return_val_if_fail(n1->type == n2->type, -1);
-	
-	switch (n1->type)
-	{
-		case GAIM_BLIST_GROUP_NODE:
-			s1 = ((GaimGroup*)n1)->name;
-			s2 = ((GaimGroup*)n2)->name;
-			break;
-		case GAIM_BLIST_CHAT_NODE:
-			s1 = gaim_chat_get_name((GaimChat*)n1);
-			s2 = gaim_chat_get_name((GaimChat*)n2);
-			break;
-		case GAIM_BLIST_BUDDY_NODE:
-			return gaim_presence_compare(gaim_buddy_get_presence((GaimBuddy*)n1),
-					gaim_buddy_get_presence((GaimBuddy*)n2));
-			break;
-		case GAIM_BLIST_CONTACT_NODE:
-			s1 = gaim_contact_get_alias((GaimContact*)n1);
-			s2 = gaim_contact_get_alias((GaimContact*)n2);
-			break;
-		default:
-			return -1;
-	}
-
-	us1 = g_utf8_strup(s1, -1);
-	us2 = g_utf8_strup(s2, -1);
-	ret = g_utf8_collate(us1, us2);
-	g_free(us1);
-	g_free(us2);
-
-	return ret;
-}
-
-static int
-blist_node_compare_status(GaimBlistNode *n1, GaimBlistNode *n2)
-{
-	int ret;
-
-	g_return_val_if_fail(n1->type == n2->type, -1);
-
-	switch (n1->type) {
-		case GAIM_BLIST_CONTACT_NODE:
-			n1 = (GaimBlistNode*)gaim_contact_get_priority_buddy((GaimContact*)n1);
-			n2 = (GaimBlistNode*)gaim_contact_get_priority_buddy((GaimContact*)n2);
-			/* now compare the presence of the priority buddies */
-		case GAIM_BLIST_BUDDY_NODE:
-			ret = gaim_presence_compare(gaim_buddy_get_presence((GaimBuddy*)n1),
-					gaim_buddy_get_presence((GaimBuddy*)n2));
-			if (ret != 0)
-				return ret;
-			break;
-		default:
-			break;
-	}
-
-	/* Sort alphabetically if presence is not comparable */
-	ret = blist_node_compare_text(n1, n2);
-
-	return ret;
-}
-
-static int
-get_contact_log_size(GaimBlistNode *c)
-{
-	int log = 0;
-	GaimBlistNode *node;
-
-	for (node = c->child; node; node = node->next) {
-		GaimBuddy *b = (GaimBuddy*)node;
-		log += gaim_log_get_total_size(GAIM_LOG_IM, b->name, b->account);
-	}
-
-	return log;
-}
-
-static int
-blist_node_compare_log(GaimBlistNode *n1, GaimBlistNode *n2)
-{
-	int ret;
-	GaimBuddy *b1, *b2;
-
-	g_return_val_if_fail(n1->type == n2->type, -1);
-
-	switch (n1->type) {
-		case GAIM_BLIST_BUDDY_NODE:
-			b1 = (GaimBuddy*)n1;
-			b2 = (GaimBuddy*)n2;
-			ret = gaim_log_get_total_size(GAIM_LOG_IM, b2->name, b2->account) - 
-					gaim_log_get_total_size(GAIM_LOG_IM, b1->name, b1->account);
-			if (ret != 0)
-				return ret;
-			break;
-		case GAIM_BLIST_CONTACT_NODE:
-			ret = get_contact_log_size(n2) - get_contact_log_size(n1);
-			if (ret != 0)
-				return ret;
-			break;
-		default:
-			break;
-	}
-	ret = blist_node_compare_text(n1, n2);
-	return ret;
-}
-
-static gboolean
-blist_clicked(GntTree *tree, GntMouseEvent event, int x, int y, gpointer ggblist)
-{
-	if (event == GNT_RIGHT_MOUSE_DOWN) {
-		draw_context_menu(ggblist);
-	}
-	return FALSE;
-}
-
-static void
-plugin_action(GntMenuItem *item, gpointer data)
-{
-	GaimPluginAction *action = data;
-	if (action && action->callback)
-		action->callback(action);
-}
-
-static void
-build_plugin_actions(GntMenuItem *item, GaimPlugin *plugin, gpointer context)
-{
-	GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
-	GList *actions;
-	GntMenuItem *menuitem;
-
-	gnt_menuitem_set_submenu(item, GNT_MENU(sub));
-	for (actions = GAIM_PLUGIN_ACTIONS(plugin, context); actions;
-			actions = g_list_delete_link(actions, actions)) {
-		if (actions->data) {
-			GaimPluginAction *action = actions->data;
-			action->plugin = plugin;
-			action->context = context;
-			menuitem = gnt_menuitem_new(action->label);
-			gnt_menu_add_item(GNT_MENU(sub), menuitem);
-
-			gnt_menuitem_set_callback(menuitem, plugin_action, action);
-			g_object_set_data_full(G_OBJECT(menuitem), "plugin_action",
-								   action, (GDestroyNotify)gaim_plugin_action_free);
-		}
-	}
-}
-
-static void
-reconstruct_plugins_menu()
-{
-	GntWidget *sub;
-	GntMenuItem *plg;
-	GList *iter;
-
-	if (!ggblist)
-		return;
-
-	if (ggblist->plugins == NULL)
-		ggblist->plugins = gnt_menuitem_new(_("Plugins"));
-
-	plg = ggblist->plugins;
-	sub = gnt_menu_new(GNT_MENU_POPUP);
-	gnt_menuitem_set_submenu(plg, GNT_MENU(sub));
-
-	for (iter = gaim_plugins_get_loaded(); iter; iter = iter->next) {
-		GaimPlugin *plugin = iter->data;
-		GntMenuItem *item;
-		if (GAIM_IS_PROTOCOL_PLUGIN(plugin))
-			continue;
-
-		if (!GAIM_PLUGIN_HAS_ACTIONS(plugin))
-			continue;
-
-		item = gnt_menuitem_new(_(plugin->info->name));
-		gnt_menu_add_item(GNT_MENU(sub), item);
-		build_plugin_actions(item, plugin, NULL);
-	}
-}
-
-static void
-reconstruct_accounts_menu()
-{
-	GntWidget *sub;
-	GntMenuItem *acc, *item;
-	GList *iter;
-
-	if (!ggblist)
-		return;
-
-	if (ggblist->accounts == NULL)
-		ggblist->accounts = gnt_menuitem_new(_("Accounts"));
-
-	acc = ggblist->accounts;
-	sub = gnt_menu_new(GNT_MENU_POPUP);
-	gnt_menuitem_set_submenu(acc, GNT_MENU(sub));
-
-	for (iter = gaim_accounts_get_all_active(); iter;
-			iter = g_list_delete_link(iter, iter)) {
-		GaimAccount *account = iter->data;
-		GaimConnection *gc = gaim_account_get_connection(account);
-		GaimPlugin *prpl;
-		
-		if (!gc || !GAIM_CONNECTION_IS_CONNECTED(gc))
-			continue;
-		prpl = gc->prpl;
-
-		if (GAIM_PLUGIN_HAS_ACTIONS(prpl)) {
-			item = gnt_menuitem_new(gaim_account_get_username(account));
-			gnt_menu_add_item(GNT_MENU(sub), item);
-			build_plugin_actions(item, prpl, gc);
-		}
-	}
-}
-
-static void
-account_signed_on_cb()
-{
-	GaimBlistNode *node;
-
-	for (node = gaim_blist_get_root(); node;
-			node = gaim_blist_node_next(node, FALSE)) {
-		if (GAIM_BLIST_NODE_IS_CHAT(node)) {
-			GaimChat *chat = (GaimChat*)node;
-			if (gaim_blist_node_get_bool(node, "gnt-autojoin"))
-				serv_join_chat(gaim_account_get_connection(chat->account), chat->components);
-		}
-	}
-}
-
-static void show_offline_cb(GntMenuItem *item, gpointer n)
-{
-	gaim_prefs_set_bool(PREF_ROOT "/showoffline",
-		!gaim_prefs_get_bool(PREF_ROOT "/showoffline"));
-}
-
-static void sort_blist_change_cb(GntMenuItem *item, gpointer n)
-{
-	gaim_prefs_set_string(PREF_ROOT "/sort_type", n);
-}
-
-/* XXX: send_im_select* -- Xerox */
-static void
-send_im_select_cb(gpointer data, GaimRequestFields *fields)
-{
-	GaimAccount *account;
-	const char *username;
-
-	account  = gaim_request_fields_get_account(fields, "account");
-	username = gaim_request_fields_get_string(fields,  "screenname");
-
-	gaim_conversation_new(GAIM_CONV_TYPE_IM, account, username);
-}
-
-static void
-send_im_select(GntMenuItem *item, gpointer n)
-{
-	GaimRequestFields *fields;
-	GaimRequestFieldGroup *group;
-	GaimRequestField *field;
-
-	fields = gaim_request_fields_new();
-
-	group = gaim_request_field_group_new(NULL);
-	gaim_request_fields_add_group(fields, group);
-
-	field = gaim_request_field_string_new("screenname", _("_Name"), NULL, FALSE);
-	gaim_request_field_set_type_hint(field, "screenname");
-	gaim_request_field_set_required(field, TRUE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_account_new("account", _("_Account"), NULL);
-	gaim_request_field_set_type_hint(field, "account");
-	gaim_request_field_set_visible(field,
-		(gaim_connections_get_all() != NULL &&
-		 gaim_connections_get_all()->next != NULL));
-	gaim_request_field_set_required(field, TRUE);
-	gaim_request_field_group_add_field(group, field);
-
-	gaim_request_fields(gaim_get_blist(), _("New Instant Message"),
-						NULL,
-						_("Please enter the screen name or alias of the person "
-						  "you would like to IM."),
-						fields,
-						_("OK"), G_CALLBACK(send_im_select_cb),
-						_("Cancel"), NULL,
-						NULL);
-}
-
-static void
-create_menu()
-{
-	GntWidget *menu, *sub;
-	GntMenuItem *item;
-	GntWindow *window;
-
-	if (!ggblist)
-		return;
-
-	window = GNT_WINDOW(ggblist->window);
-	ggblist->menu = menu = gnt_menu_new(GNT_MENU_TOPLEVEL);
-	gnt_window_set_menu(window, GNT_MENU(menu));
-
-	item = gnt_menuitem_new(_("Options"));
-	gnt_menu_add_item(GNT_MENU(menu), item);
-
-	sub = gnt_menu_new(GNT_MENU_POPUP);
-	gnt_menuitem_set_submenu(item, GNT_MENU(sub));
-
-	item = gnt_menuitem_new(_("Send IM..."));
-	gnt_menu_add_item(GNT_MENU(sub), item);
-	gnt_menuitem_set_callback(GNT_MENUITEM(item), send_im_select, NULL);
-
-	item = gnt_menuitem_check_new(_("Toggle offline buddies"));
-	gnt_menuitem_check_set_checked(GNT_MENUITEM_CHECK(item),
-				gaim_prefs_get_bool(PREF_ROOT "/showoffline"));
-	gnt_menu_add_item(GNT_MENU(sub), item);
-	gnt_menuitem_set_callback(GNT_MENUITEM(item), show_offline_cb, NULL);
-
-	item = gnt_menuitem_new(_("Sort by status"));
-	gnt_menu_add_item(GNT_MENU(sub), item);
-	gnt_menuitem_set_callback(GNT_MENUITEM(item), sort_blist_change_cb, "status");
-
-	item = gnt_menuitem_new(_("Sort alphabetically"));
-	gnt_menu_add_item(GNT_MENU(sub), item);
-	gnt_menuitem_set_callback(GNT_MENUITEM(item), sort_blist_change_cb, "text");
-
-	item = gnt_menuitem_new(_("Sort by log size"));
-	gnt_menu_add_item(GNT_MENU(sub), item);
-	gnt_menuitem_set_callback(GNT_MENUITEM(item), sort_blist_change_cb, "log");
-
-	reconstruct_accounts_menu();
-	gnt_menu_add_item(GNT_MENU(menu), ggblist->accounts);
-
-	reconstruct_plugins_menu();
-	gnt_menu_add_item(GNT_MENU(menu), ggblist->plugins);
-}
-
-void gg_blist_show()
-{
-	blist_show(gaim_get_blist());
-}
-
-static void
-blist_show(GaimBuddyList *list)
-{
-	if (ggblist == NULL)
-		new_list(list);
-	else if (ggblist->window)
-		return;
-
-	ggblist->window = gnt_vwindow_new(FALSE);
-	gnt_widget_set_name(ggblist->window, "buddylist");
-	gnt_box_set_toplevel(GNT_BOX(ggblist->window), TRUE);
-	gnt_box_set_title(GNT_BOX(ggblist->window), _("Buddy List"));
-	gnt_box_set_pad(GNT_BOX(ggblist->window), 0);
-
-	ggblist->tree = gnt_tree_new();
-
-	GNT_WIDGET_SET_FLAGS(ggblist->tree, GNT_WIDGET_NO_BORDER);
-	gnt_widget_set_size(ggblist->tree, gaim_prefs_get_int(PREF_ROOT "/size/width"),
-			gaim_prefs_get_int(PREF_ROOT "/size/height"));
-	gnt_widget_set_position(ggblist->window, gaim_prefs_get_int(PREF_ROOT "/position/x"),
-			gaim_prefs_get_int(PREF_ROOT "/position/y"));
-
-	gnt_tree_set_col_width(GNT_TREE(ggblist->tree), 0,
-			gaim_prefs_get_int(PREF_ROOT "/size/width") - 1);
-
-	gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->tree);
-
-	ggblist->status = gnt_combo_box_new();
-	gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->status);
-	ggblist->statustext = gnt_entry_new(NULL);
-	gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->statustext);
-
-	gnt_widget_show(ggblist->window);
-
-	gaim_signal_connect(gaim_connections_get_handle(), "signed-on", gg_blist_get_handle(),
-				GAIM_CALLBACK(reconstruct_accounts_menu), NULL);
-	gaim_signal_connect(gaim_connections_get_handle(), "signed-off", gg_blist_get_handle(),
-				GAIM_CALLBACK(reconstruct_accounts_menu), NULL);
-	gaim_signal_connect(gaim_blist_get_handle(), "buddy-status-changed", gg_blist_get_handle(),
-				GAIM_CALLBACK(buddy_status_changed), ggblist);
-	gaim_signal_connect(gaim_blist_get_handle(), "buddy-idle-changed", gg_blist_get_handle(),
-				GAIM_CALLBACK(buddy_idle_changed), ggblist);
-
-	gaim_signal_connect(gaim_plugins_get_handle(), "plugin-load", gg_blist_get_handle(),
-				GAIM_CALLBACK(reconstruct_plugins_menu), NULL);
-	gaim_signal_connect(gaim_plugins_get_handle(), "plugin-unload", gg_blist_get_handle(),
-				GAIM_CALLBACK(reconstruct_plugins_menu), NULL);
-
-#if 0
-	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);
-
-	/* These I plan to use to indicate unread-messages etc. */
-	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);
-#endif
-
-	g_signal_connect(G_OBJECT(ggblist->tree), "selection_changed", G_CALLBACK(selection_changed), ggblist);
-	g_signal_connect(G_OBJECT(ggblist->tree), "key_pressed", G_CALLBACK(key_pressed), ggblist);
-	g_signal_connect(G_OBJECT(ggblist->tree), "context-menu", G_CALLBACK(context_menu), ggblist);
-	g_signal_connect_after(G_OBJECT(ggblist->tree), "clicked", G_CALLBACK(blist_clicked), ggblist);
-	g_signal_connect(G_OBJECT(ggblist->tree), "activate", G_CALLBACK(selection_activate), ggblist);
-	g_signal_connect_data(G_OBJECT(ggblist->tree), "gained-focus", G_CALLBACK(draw_tooltip),
-				ggblist, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
-	g_signal_connect_data(G_OBJECT(ggblist->tree), "lost-focus", G_CALLBACK(remove_peripherals),
-				ggblist, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
-	g_signal_connect(G_OBJECT(ggblist->tree), "size_changed", G_CALLBACK(size_changed_cb), NULL);
-	g_signal_connect(G_OBJECT(ggblist->window), "position_set", G_CALLBACK(save_position_cb), NULL);
-	g_signal_connect(G_OBJECT(ggblist->window), "destroy", G_CALLBACK(reset_blist_window), NULL);
-
-	/* Status signals */
-	gaim_signal_connect(gaim_savedstatuses_get_handle(), "savedstatus-changed", gg_blist_get_handle(),
-				GAIM_CALLBACK(savedstatus_changed), NULL);
-	g_signal_connect(G_OBJECT(ggblist->status), "selection_changed",
-				G_CALLBACK(status_selection_changed), NULL);
-	g_signal_connect(G_OBJECT(ggblist->statustext), "key_pressed",
-				G_CALLBACK(status_text_changed), NULL);
-
-	create_menu();
-
-	populate_buddylist();
-
-	savedstatus_changed(gaim_savedstatus_get_current(), NULL);
-}
-
-void gg_blist_uninit()
-{
-	if (ggblist == NULL)
-		return;
-
-	gnt_widget_destroy(ggblist->window);
-	g_free(ggblist);
-	ggblist = NULL;
-}
-
-gboolean gg_blist_get_position(int *x, int *y)
-{
-	if (!ggblist || !ggblist->window)
-		return FALSE;
-	gnt_widget_get_position(ggblist->window, x, y);
-	return TRUE;
-}
-
-void gg_blist_set_position(int x, int y)
-{
-	gnt_widget_set_position(ggblist->window, x, y);
-}
-
-gboolean gg_blist_get_size(int *width, int *height)
-{
-	if (!ggblist || !ggblist->window)
-		return FALSE;
-	gnt_widget_get_size(ggblist->window, width, height);
-	return TRUE;
-}
-
-void gg_blist_set_size(int width, int height)
-{
-	gnt_widget_set_size(ggblist->window, width, height);
-}
-
--- a/console/gntblist.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/**
- * @file gntblist.h GNT BuddyList API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_BLIST_H
-#define _GNT_BLIST_H
-
-#include "blist.h"
-
-/**********************************************************************
- * @name GNT BuddyList API
- **********************************************************************/
-/*@{*/
-
-/**
- * Get the ui-functions.
- *
- * @return The GaimBlistUiOps structure populated with the appropriate functions.
- */
-GaimBlistUiOps * gg_blist_get_ui_ops(void);
-
-/**
- * Perform necessary initializations.
- */
-void gg_blist_init(void);
-
-/**
- * Perform necessary uninitializations.
- */
-void gg_blist_uninit(void);
-
-/**
- * Show the buddy list.
- */
-void gg_blist_show(void);
-
-/**
- * Get the position of the buddy list.
- *
- * @param x The x-coordinate is set here if not @ NULL.
- * @param y The y-coordinate is set here if not @c NULL.
- *
- * @return Returns @c TRUE if the values were set, @c FALSE otherwise.
- */
-gboolean gg_blist_get_position(int *x, int *y);
-
-/**
- * Set the position of the buddy list.
- *
- * @param x The x-coordinate of the buddy list.
- * @param y The y-coordinate of the buddy list.
- */
-void gg_blist_set_position(int x, int y);
-
-/**
- * Get the size of the buddy list.
- *
- * @param width  The width is set here if not @ NULL.
- * @param height The height is set here if not @c NULL.
- *
- * @return Returns @c TRUE if the values were set, @c FALSE otherwise.
- */
-gboolean gg_blist_get_size(int *width, int *height);
-
-/**
- * Set the size of the buddy list.
- *
- * @param width  The width of the buddy list.
- * @param height The height of the buddy list.
- */
-void gg_blist_set_size(int width, int height);
-
-/*@}*/
-
-#endif
--- a/console/gntconn.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/**
- * @file gntconn.c GNT Connection API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include "account.h"
-#include "core.h"
-#include "request.h"
-
-#include "gntconn.h"
-#include "gntgaim.h"
-
-static void
-gg_connection_report_disconnect(GaimConnection *gc, const char *text)
-{
-	char *act, *primary, *secondary;
-	GaimAccount *account = gaim_connection_get_account(gc);
-
-	act = g_strdup_printf(_("%s (%s)"), gaim_account_get_username(account),
-			gaim_account_get_protocol_name(account));
-
-	primary = g_strdup_printf(_("%s disconnected."), act);
-	secondary = g_strdup_printf(_("%s was disconnected due to the following error:\n%s"),
-			act, text);
-
-	gaim_request_action(account, _("Connection Error"), primary, secondary, 1,
-						account, 2,
-						_("OK"), NULL,
-						_("Connect"),
-						GAIM_CALLBACK(gaim_account_connect));
-
-	g_free(act);
-	g_free(primary);
-	g_free(secondary);
-}
-
-static GaimConnectionUiOps ops = 
-{
-	.connect_progress = NULL,
-	.connected = NULL,
-	.disconnected = NULL,
-	.notice = NULL,
-	.report_disconnect = gg_connection_report_disconnect
-};
-
-GaimConnectionUiOps *gg_connections_get_ui_ops()
-{
-	return &ops;
-}
-
-void gg_connections_init()
-{}
-
-void gg_connections_uninit()
-{}
-
--- a/console/gntconn.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/**
- * @file gntconn.h GNT Connection API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_CONN_H
-#define _GNT_CONN_H
-
-#include "connection.h"
-
-/**********************************************************************
- * @name GNT Connection API
- **********************************************************************/
-/*@{*/
-
-/**
- * Get the ui-functions.
- *
- * @return The GaimConnectionUiOps structure populated with the appropriate functions.
- */
-GaimConnectionUiOps *gg_connections_get_ui_ops(void);
-
-/**
- * Perform necessary initializations.
- */
-void gg_connections_init(void);
-
-/**
- * Perform necessary uninitializations.
- */
-void gg_connections_uninit(void);
-
-/*@}*/
-
-#endif
--- a/console/gntconv.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,760 +0,0 @@
-/**
- * @file gntconv.c GNT Conversation API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <string.h>
-
-#include <cmds.h>
-#include <idle.h>
-#include <prefs.h>
-#include <util.h>
-
-#include "gntgaim.h"
-#include "gntaccount.h"
-#include "gntblist.h"
-#include "gntconv.h"
-#include "gntdebug.h"
-#include "gntplugin.h"
-#include "gntprefs.h"
-#include "gntstatus.h"
-
-#include "gnt.h"
-#include "gntbox.h"
-#include "gntentry.h"
-#include "gnttextview.h"
-
-#define PREF_ROOT	"/gaim/gnt/conversations"
-
-#include "config.h"
-
-static void
-send_typing_notification(GntWidget *w, GGConv *ggconv)
-{
-	const char *text = gnt_entry_get_text(GNT_ENTRY(ggconv->entry));
-	gboolean empty = (!text || !*text);
-	if (gaim_prefs_get_bool("/gaim/gnt/conversations/notify_typing")) {
-		GaimConversation *conv = ggconv->active_conv;
-		GaimConvIm *im = GAIM_CONV_IM(conv);
-		if (!empty) {
-			gboolean send = (gaim_conv_im_get_send_typed_timeout(im) == 0);
-
-			gaim_conv_im_stop_send_typed_timeout(im);
-			gaim_conv_im_start_send_typed_timeout(im);
-			if (send || (gaim_conv_im_get_type_again(im) != 0 &&
-						  time(NULL) > gaim_conv_im_get_type_again(im))) {
-				unsigned int timeout;
-				timeout = serv_send_typing(gaim_conversation_get_gc(conv),
-										   gaim_conversation_get_name(conv),
-										   GAIM_TYPING);
-				gaim_conv_im_set_type_again(im, timeout);
-			}
-		} else {
-			gaim_conv_im_stop_send_typed_timeout(im);
-
-			serv_send_typing(gaim_conversation_get_gc(conv),
-							 gaim_conversation_get_name(conv),
-							 GAIM_NOT_TYPING);
-		}
-	}
-}
-
-static gboolean
-entry_key_pressed(GntWidget *w, const char *key, GGConv *ggconv)
-{
-	if (key[0] == '\r' && key[1] == 0)
-	{
-		const char *text = gnt_entry_get_text(GNT_ENTRY(ggconv->entry));
-		if (*text == '/')
-		{
-			GaimConversation *conv = ggconv->active_conv;
-			GaimCmdStatus status;
-			const char *cmdline = text + 1;
-			char *error = NULL, *escape;
-
-			escape = g_markup_escape_text(cmdline, -1);
-			status = gaim_cmd_do_command(conv, cmdline, escape, &error);
-			g_free(escape);
-
-			switch (status)
-			{
-				case GAIM_CMD_STATUS_OK:
-					break;
-				case GAIM_CMD_STATUS_NOT_FOUND:
-					gaim_conversation_write(conv, "", _("No such command."),
-							GAIM_MESSAGE_NO_LOG, time(NULL));
-					break;
-				case GAIM_CMD_STATUS_WRONG_ARGS:
-					gaim_conversation_write(conv, "", _("Syntax Error:  You typed the wrong number of arguments "
-										"to that command."),
-							GAIM_MESSAGE_NO_LOG, time(NULL));
-					break;
-				case GAIM_CMD_STATUS_FAILED:
-					gaim_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."),
-							GAIM_MESSAGE_NO_LOG, time(NULL));
-					break;
-				case GAIM_CMD_STATUS_WRONG_TYPE:
-					if(gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM)
-						gaim_conversation_write(conv, "", _("That command only works in chats, not IMs."),
-								GAIM_MESSAGE_NO_LOG, time(NULL));
-					else
-						gaim_conversation_write(conv, "", _("That command only works in IMs, not chats."),
-								GAIM_MESSAGE_NO_LOG, time(NULL));
-					break;
-				case GAIM_CMD_STATUS_WRONG_PRPL:
-					gaim_conversation_write(conv, "", _("That command doesn't work on this protocol."),
-							GAIM_MESSAGE_NO_LOG, time(NULL));
-					break;
-			}
-			g_free(error);
-#if 0
-			gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
-					_("Commands are not supported yet. Message was NOT sent."),
-					GNT_TEXT_FLAG_DIM | GNT_TEXT_FLAG_UNDERLINE);
-			gnt_text_view_next_line(GNT_TEXT_VIEW(ggconv->tv));
-			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 0);
-#endif
-		}
-		else
-		{
-			char *escape = g_markup_escape_text(text, -1);
-			char *apos = gaim_strreplace(escape, "&apos;", "'");
-			g_free(escape);
-			escape = apos;
-			switch (gaim_conversation_get_type(ggconv->active_conv))
-			{
-				case GAIM_CONV_TYPE_IM:
-					gaim_conv_im_send_with_flags(GAIM_CONV_IM(ggconv->active_conv), escape, GAIM_MESSAGE_SEND);
-					break;
-				case GAIM_CONV_TYPE_CHAT:
-					gaim_conv_chat_send(GAIM_CONV_CHAT(ggconv->active_conv), escape);
-					break;
-				default:
-					g_free(escape);
-					g_return_val_if_reached(FALSE);
-			}
-			g_free(escape);
-			gaim_idle_touch();
-		}
-		gnt_entry_add_to_history(GNT_ENTRY(ggconv->entry), text);
-		gnt_entry_clear(GNT_ENTRY(ggconv->entry));
-		return TRUE;
-	}
-	else if (key[0] == 27)
-	{
-		if (strcmp(key, GNT_KEY_DOWN) == 0)
-			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 1);
-		else if (strcmp(key, GNT_KEY_UP) == 0)
-			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), -1);
-		else if (strcmp(key, GNT_KEY_PGDOWN) == 0)
-			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), ggconv->tv->priv.height - 2);
-		else if (strcmp(key, GNT_KEY_PGUP) == 0)
-			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), -(ggconv->tv->priv.height - 2));
-		else
-			return FALSE;
-		return TRUE;
-	}
-	else
-	{
-	}
-
-	return FALSE;
-}
-
-static void
-closing_window(GntWidget *window, GGConv *ggconv)
-{
-	GList *list = ggconv->list;
-	ggconv->window = NULL;
-	while (list) {
-		GaimConversation *conv = list->data;
-		list = list->next;
-		gaim_conversation_destroy(conv);
-	}
-}
-
-static void
-size_changed_cb(GntWidget *widget, int width, int height)
-{
-	int w, h;
-	gnt_widget_get_size(widget, &w, &h);
-	gaim_prefs_set_int(PREF_ROOT "/size/width", w);
-	gaim_prefs_set_int(PREF_ROOT "/size/height", h);
-}
-
-static void
-save_position_cb(GntWidget *w, int x, int y)
-{
-	gaim_prefs_set_int(PREF_ROOT "/position/x", x);
-	gaim_prefs_set_int(PREF_ROOT "/position/y", y);
-}
-
-static GaimConversation *
-find_conv_with_contact(GaimConversation *conv)
-{
-	GaimBlistNode *node;
-	GaimBuddy *buddy = gaim_find_buddy(conv->account, conv->name);
-	GaimConversation *ret = NULL;
-
-	if (!buddy)
-		return NULL;
-
-	for (node = ((GaimBlistNode*)buddy)->parent->child; node; node = node->next) {
-		if (node == (GaimBlistNode*)buddy)
-			continue;
-		if ((ret = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM,
-				((GaimBuddy*)node)->name, ((GaimBuddy*)node)->account)) != NULL)
-			break;
-	}
-	return ret;
-}
-
-static char *
-get_conversation_title(GaimConversation *conv, GaimAccount *account)
-{
-	return g_strdup_printf(_("%s (%s -- %s)"), gaim_conversation_get_title(conv),
-		gaim_account_get_username(account), gaim_account_get_protocol_name(account));
-}
-
-static void
-update_buddy_typing(GaimAccount *account, const char *who, gpointer null)
-{
-	GaimConversation *conv;
-	GGConv *ggc;
-	GaimConvIm *im = NULL;
-	char *title, *str;
-
-	conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, who, account);
-
-	if (!conv)
-		return;
-
-	im = GAIM_CONV_IM(conv);
-	ggc = conv->ui_data;
-
-	if (gaim_conv_im_get_typing_state(im) == GAIM_TYPING) {
-		int scroll;
-		str = get_conversation_title(conv, account);
-		title = g_strdup_printf(_("%s [%s]"), str,
-			gnt_ascii_only() ? "T" : "\342\243\277");
-		g_free(str);
-
-		scroll = gnt_text_view_get_lines_below(GNT_TEXT_VIEW(ggc->tv));
-		str = g_strdup_printf(_("\n%s is typing..."), gaim_conversation_get_name(conv));
-		/* Updating is a little buggy. So just remove and add a new one */
-		gnt_text_view_tag_change(GNT_TEXT_VIEW(ggc->tv), "typing", NULL, TRUE);
-		gnt_text_view_append_text_with_tag(GNT_TEXT_VIEW(ggc->tv),
-					str, GNT_TEXT_FLAG_DIM, "typing");
-		g_free(str);
-		if (scroll <= 1)
-			gnt_text_view_scroll(GNT_TEXT_VIEW(ggc->tv), 0);
- 	} else {
-		title = get_conversation_title(conv, account);
-		gnt_text_view_tag_change(GNT_TEXT_VIEW(ggc->tv), "typing", NULL, TRUE);
-	}
-	gnt_screen_rename_widget(ggc->window, title);
-	g_free(title);
-}
-
-static gpointer
-gg_conv_get_handle()
-{
-	static int handle;
-	return &handle;
-}
-
-static void
-gg_create_conversation(GaimConversation *conv)
-{
-	GGConv *ggc = conv->ui_data;
-	char *title;
-	GaimConversationType type;
-	GaimConversation *cc;
-	GaimAccount *account;
-
-	if (ggc)
-		return;
-
-	cc = find_conv_with_contact(conv);
-	if (cc && cc->ui_data)
-		ggc = cc->ui_data;
-	else
-		ggc = g_new0(GGConv, 1);
-
-	ggc->list = g_list_prepend(ggc->list, conv);
-	ggc->active_conv = conv;
-	conv->ui_data = ggc;
-
-	if (cc && cc->ui_data) {
-		gg_conversation_set_active(conv);
-		return;
-	}
-
-	account = gaim_conversation_get_account(conv);
-	type = gaim_conversation_get_type(conv);
-	title = get_conversation_title(conv, account);
-
-	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_box_set_pad(GNT_BOX(ggc->window), 0);
-	gnt_widget_set_name(ggc->window, "conversation-window");
-
-	ggc->tv = gnt_text_view_new();
-	gnt_box_add_widget(GNT_BOX(ggc->window), ggc->tv);
-	gnt_widget_set_name(ggc->tv, "conversation-window-textview");
-	gnt_widget_set_size(ggc->tv, gaim_prefs_get_int(PREF_ROOT "/size/width"),
-			gaim_prefs_get_int(PREF_ROOT "/size/height"));
-
-	ggc->entry = gnt_entry_new(NULL);
-	gnt_box_add_widget(GNT_BOX(ggc->window), ggc->entry);
-	gnt_widget_set_name(ggc->entry, "conversation-window-entry");
-	gnt_entry_set_history_length(GNT_ENTRY(ggc->entry), -1);
-	gnt_entry_set_word_suggest(GNT_ENTRY(ggc->entry), TRUE);
-	gnt_entry_set_always_suggest(GNT_ENTRY(ggc->entry), FALSE);
-
-	g_signal_connect_after(G_OBJECT(ggc->entry), "key_pressed", G_CALLBACK(entry_key_pressed), ggc);
-	g_signal_connect(G_OBJECT(ggc->window), "destroy", G_CALLBACK(closing_window), ggc);
-
-	gnt_widget_set_position(ggc->window, gaim_prefs_get_int(PREF_ROOT "/position/x"),
-			gaim_prefs_get_int(PREF_ROOT "/position/y"));
-	gnt_widget_show(ggc->window);
-
-	g_signal_connect(G_OBJECT(ggc->tv), "size_changed", G_CALLBACK(size_changed_cb), NULL);
-	g_signal_connect(G_OBJECT(ggc->window), "position_set", G_CALLBACK(save_position_cb), NULL);
-
-	if (type == GAIM_CONV_TYPE_IM) {
-		g_signal_connect(G_OBJECT(ggc->entry), "text_changed", G_CALLBACK(send_typing_notification), ggc);
-		gaim_signal_connect(gaim_conversations_get_handle(), "buddy-typing", gg_conv_get_handle(),
-						GAIM_CALLBACK(update_buddy_typing), NULL);
-		gaim_signal_connect(gaim_conversations_get_handle(), "buddy-typing-stopped", gg_conv_get_handle(),
-						GAIM_CALLBACK(update_buddy_typing), NULL);
-	}
-
-	g_free(title);
-}
-
-static void
-gg_destroy_conversation(GaimConversation *conv)
-{
-	/* do stuff here */
-	GGConv *ggc = conv->ui_data;
-	ggc->list = g_list_remove(ggc->list, conv);
-	if (ggc->list && conv == ggc->active_conv)
-		ggc->active_conv = ggc->list->data;
-	
-	if (ggc->list == NULL) {
-		gnt_widget_destroy(ggc->window);
-		g_free(ggc);
-	}
-}
-
-static void
-gg_write_common(GaimConversation *conv, const char *who, const char *message,
-		GaimMessageFlags flags, time_t mtime)
-{
-	GGConv *ggconv = conv->ui_data;
-	char *strip, *newline;
-	GntTextFormatFlags fl = 0;
-	int pos;
-	gboolean notify;
-
-	g_return_if_fail(ggconv != NULL);
-
-	if (ggconv->active_conv != conv) {
-		if (flags & (GAIM_MESSAGE_SEND | GAIM_MESSAGE_RECV))
-			gg_conversation_set_active(conv);
-		else
-			return;
-	}
-
-	pos = gnt_text_view_get_lines_below(GNT_TEXT_VIEW(ggconv->tv));
-
-	notify = !!gnt_text_view_tag_change(GNT_TEXT_VIEW(ggconv->tv), "typing", NULL, TRUE);
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv), "\n", GNT_TEXT_FLAG_NORMAL);
-
-	/* Unnecessary to print the timestamp for delayed message */
-	if (!(flags & GAIM_MESSAGE_DELAYED) &&
-			gaim_prefs_get_bool("/gaim/gnt/conversations/timestamps"))
-		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
-					gaim_utf8_strftime("(%H:%M:%S) ", localtime(&mtime)), GNT_TEXT_FLAG_DIM);
-
-	if (flags & GAIM_MESSAGE_AUTO_RESP)
-		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
-					_("<AUTO-REPLY> "), GNT_TEXT_FLAG_BOLD);
-
-	if (who && *who && (flags & (GAIM_MESSAGE_SEND | GAIM_MESSAGE_RECV)))
-	{
-		char * name = NULL;
-
-		if (gaim_message_meify((char*)message, -1))
-			name = g_strdup_printf("*** %s ", who);
-		else
-			name =  g_strdup_printf("%s: ", who);
-
-		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
-				name, GNT_TEXT_FLAG_BOLD);
-		g_free(name);
-	}
-	else
-		fl = GNT_TEXT_FLAG_DIM;
-
-	if (flags & GAIM_MESSAGE_ERROR)
-		fl |= GNT_TEXT_FLAG_BOLD;
-	if (flags & GAIM_MESSAGE_NICK)
-		fl |= GNT_TEXT_FLAG_UNDERLINE;
-
-	/* XXX: Remove this workaround when textview can parse messages. */
-	newline = gaim_strdup_withhtml(message);
-	strip = gaim_markup_strip_html(newline);
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
-				strip, fl);
-
-	g_free(newline);
-	g_free(strip);
-
-	if (notify) {
-		strip = g_strdup_printf(_("\n%s is typing..."), gaim_conversation_get_name(conv));
-		gnt_text_view_append_text_with_tag(GNT_TEXT_VIEW(ggconv->tv),
-					strip, GNT_TEXT_FLAG_DIM, "typing");
-		g_free(strip);
-	}
-
-	if (pos <= 1)
-		gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 0);
-
-	if (flags & (GAIM_MESSAGE_RECV | GAIM_MESSAGE_NICK | GAIM_MESSAGE_ERROR))
-		gnt_widget_set_urgent(ggconv->tv);
-}
-
-static void
-gg_write_chat(GaimConversation *conv, const char *who, const char *message,
-		GaimMessageFlags flags, time_t mtime)
-{
-	gaim_conversation_write(conv, who, message, flags, mtime);
-}
-
-static void
-gg_write_im(GaimConversation *conv, const char *who, const char *message,
-		GaimMessageFlags flags, time_t mtime)
-{
-	GaimAccount *account = gaim_conversation_get_account(conv);
-	if (flags & GAIM_MESSAGE_SEND)
-	{
-		who = gaim_connection_get_display_name(gaim_account_get_connection(account));
-		if (!who)
-			who = gaim_account_get_alias(account);
-		if (!who)
-			who = gaim_account_get_username(account);
-	}
-	else if (flags & GAIM_MESSAGE_RECV)
-	{
-		GaimBuddy *buddy;
-		who = gaim_conversation_get_name(conv);
-		buddy = gaim_find_buddy(account, who);
-		if (buddy)
-			who = gaim_buddy_get_contact_alias(buddy);
-	}
-
-	gaim_conversation_write(conv, who, message, flags, mtime);
-}
-
-static void
-gg_write_conv(GaimConversation *conv, const char *who, const char *alias,
-		const char *message, GaimMessageFlags flags, time_t mtime)
-{
-	const char *name;
-	if (alias && *alias)
-		name = alias;
-	else if (who && *who)
-		name = who;
-	else
-		name = NULL;
-
-	gg_write_common(conv, name, message, flags, mtime);
-}
-
-static void
-gg_chat_add_users(GaimConversation *conv, GList *users, gboolean new_arrivals)
-{
-	GGConv *ggc = conv->ui_data;
-	GntEntry *entry = GNT_ENTRY(ggc->entry);
-
-	if (!new_arrivals)
-	{
-		/* Print the list of users in the room */
-		GString *string = g_string_new(_("List of users:\n"));
-		GList *iter;
-
-		for (iter = users; iter; iter = iter->next)
-		{
-			GaimConvChatBuddy *cbuddy = iter->data;
-			char *str;
-
-			if ((str = cbuddy->alias) == NULL)
-				str = cbuddy->name;
-			g_string_append_printf(string, "[ %s ]", str);
-		}
-
-		gaim_conversation_write(conv, NULL, string->str,
-				GAIM_MESSAGE_SYSTEM, time(NULL));
-		g_string_free(string, TRUE);
-	}
-
-	for (; users; users = users->next)
-	{
-		GaimConvChatBuddy *cbuddy = users->data;
-		gnt_entry_add_suggest(entry, cbuddy->name);
-		gnt_entry_add_suggest(entry, cbuddy->alias);
-	}
-}
-
-static void
-gg_chat_rename_user(GaimConversation *conv, const char *old, const char *new_n, const char *new_a)
-{
-	/* Update the name for string completion */
-	GGConv *ggc = conv->ui_data;
-	GntEntry *entry = GNT_ENTRY(ggc->entry);
-	gnt_entry_remove_suggest(entry, old);
-	gnt_entry_add_suggest(entry, new_n);
-	gnt_entry_add_suggest(entry, new_a);
-}
-
-static void
-gg_chat_remove_user(GaimConversation *conv, GList *list)
-{
-	/* Remove the name from string completion */
-	GGConv *ggc = conv->ui_data;
-	GntEntry *entry = GNT_ENTRY(ggc->entry);
-	for (; list; list = list->next)
-		gnt_entry_remove_suggest(entry, list->data);
-}
-
-static void
-gg_chat_update_user(GaimConversation *conv, const char *user)
-{
-}
-
-static GaimConversationUiOps conv_ui_ops = 
-{
-	.create_conversation = gg_create_conversation,
-	.destroy_conversation = gg_destroy_conversation,
-	.write_chat = gg_write_chat,
-	.write_im = gg_write_im,
-	.write_conv = gg_write_conv,
-	.chat_add_users = gg_chat_add_users,
-	.chat_rename_user = gg_chat_rename_user,
-	.chat_remove_users = gg_chat_remove_user,
-	.chat_update_user = gg_chat_update_user,
-	.present = NULL,
-	.has_focus = NULL,
-	.custom_smiley_add = NULL,
-	.custom_smiley_write = NULL,
-	.custom_smiley_close = NULL
-};
-
-GaimConversationUiOps *gg_conv_get_ui_ops()
-{
-	return &conv_ui_ops;
-}
-
-/* Xerox */
-static GaimCmdRet
-say_command_cb(GaimConversation *conv,
-              const char *cmd, char **args, char **error, void *data)
-{
-	if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM)
-		gaim_conv_im_send(GAIM_CONV_IM(conv), args[0]);
-	else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT)
-		gaim_conv_chat_send(GAIM_CONV_CHAT(conv), args[0]);
-
-	return GAIM_CMD_RET_OK;
-}
-
-/* Xerox */
-static GaimCmdRet
-me_command_cb(GaimConversation *conv,
-              const char *cmd, char **args, char **error, void *data)
-{
-	char *tmp;
-
-	tmp = g_strdup_printf("/me %s", args[0]);
-
-	if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM)
-		gaim_conv_im_send(GAIM_CONV_IM(conv), tmp);
-	else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT)
-		gaim_conv_chat_send(GAIM_CONV_CHAT(conv), tmp);
-
-	g_free(tmp);
-	return GAIM_CMD_RET_OK;
-}
-
-/* Xerox */
-static GaimCmdRet
-debug_command_cb(GaimConversation *conv,
-                 const char *cmd, char **args, char **error, void *data)
-{
-	char *tmp, *markup;
-	GaimCmdStatus status;
-
-	if (!g_ascii_strcasecmp(args[0], "version")) {
-		tmp = g_strdup_printf("me is using %s.", VERSION);
-		markup = g_markup_escape_text(tmp, -1);
-
-		status = gaim_cmd_do_command(conv, tmp, markup, error);
-
-		g_free(tmp);
-		g_free(markup);
-		return status;
-	} else {
-		gaim_conversation_write(conv, NULL, _("Supported debug options are:  version"),
-		                        GAIM_MESSAGE_NO_LOG|GAIM_MESSAGE_ERROR, time(NULL));
-		return GAIM_CMD_STATUS_OK;
-	}
-}
-
-/* Xerox */
-static GaimCmdRet
-clear_command_cb(GaimConversation *conv,
-                 const char *cmd, char **args, char **error, void *data)
-{
-	GGConv *ggconv = conv->ui_data;
-	gnt_text_view_clear(GNT_TEXT_VIEW(ggconv->tv));
-	return GAIM_CMD_STATUS_OK;
-}
-
-/* Xerox */
-static GaimCmdRet
-help_command_cb(GaimConversation *conv,
-                 const char *cmd, char **args, char **error, void *data)
-{
-	GList *l, *text;
-	GString *s;
-
-	if (args[0] != NULL) {
-		s = g_string_new("");
-		text = gaim_cmd_help(conv, args[0]);
-
-		if (text) {
-			for (l = text; l; l = l->next)
-				if (l->next)
-					g_string_append_printf(s, "%s\n", (char *)l->data);
-				else
-					g_string_append_printf(s, "%s", (char *)l->data);
-		} else {
-			g_string_append(s, _("No such command (in this context)."));
-		}
-	} else {
-		s = g_string_new(_("Use \"/help &lt;command&gt;\" for help on a specific command.\n"
-											 "The following commands are available in this context:\n"));
-
-		text = gaim_cmd_list(conv);
-		for (l = text; l; l = l->next)
-			if (l->next)
-				g_string_append_printf(s, "%s, ", (char *)l->data);
-			else
-				g_string_append_printf(s, "%s.", (char *)l->data);
-		g_list_free(text);
-	}
-
-	gaim_conversation_write(conv, NULL, s->str, GAIM_MESSAGE_NO_LOG, time(NULL));
-	g_string_free(s, TRUE);
-
-	return GAIM_CMD_STATUS_OK;
-}
-
-static GaimCmdRet
-cmd_show_window(GaimConversation *conv, const char *cmd, char **args, char **error, gpointer data)
-{
-	void (*callback)() = data;
-	callback();
-	return GAIM_CMD_STATUS_OK;
-}
-
-void gg_conversation_init()
-{
-	gaim_prefs_add_none(PREF_ROOT);
-	gaim_prefs_add_none(PREF_ROOT "/size");
-	gaim_prefs_add_int(PREF_ROOT "/size/width", 70);
-	gaim_prefs_add_int(PREF_ROOT "/size/height", 20);
-	gaim_prefs_add_none(PREF_ROOT "/position");
-	gaim_prefs_add_int(PREF_ROOT "/position/x", 0);
-	gaim_prefs_add_int(PREF_ROOT "/position/y", 0);
-
-	/* Xerox the commands */
-	gaim_cmd_register("say", "S", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-	                  say_command_cb, _("say &lt;message&gt;:  Send a message normally as if you weren't using a command."), NULL);
-	gaim_cmd_register("me", "S", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-	                  me_command_cb, _("me &lt;action&gt;:  Send an IRC style action to a buddy or chat."), NULL);
-	gaim_cmd_register("debug", "w", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-	                  debug_command_cb, _("debug &lt;option&gt;:  Send various debug information to the current conversation."), NULL);
-	gaim_cmd_register("clear", "", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-	                  clear_command_cb, _("clear: Clears the conversation scrollback."), NULL);
-	gaim_cmd_register("help", "w", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, NULL,
-	                  help_command_cb, _("help &lt;command&gt;:  Help on a specific command."), NULL);
-
-	/* Now some commands to bring up some other windows */
-	gaim_cmd_register("plugins", "", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-	                  cmd_show_window, _("plugins: Show the plugins window."), gg_plugins_show_all);
-	gaim_cmd_register("buddylist", "", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-	                  cmd_show_window, _("buddylist: Show the buddylist."), gg_blist_show);
-	gaim_cmd_register("accounts", "", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-	                  cmd_show_window, _("accounts: Show the accounts window."), gg_accounts_show_all);
-	gaim_cmd_register("debugwin", "", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-	                  cmd_show_window, _("debugwin: Show the debug window."), gg_debug_window_show);
-	gaim_cmd_register("prefs", "", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-	                  cmd_show_window, _("prefs: Show the preference window."), gg_prefs_show_all);
-	gaim_cmd_register("status", "", GAIM_CMD_P_DEFAULT,
-	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-	                  cmd_show_window, _("statuses: Show the savedstatuses window."), gg_savedstatus_show_all);
-}
-
-void gg_conversation_uninit()
-{
-}
-
-void gg_conversation_set_active(GaimConversation *conv)
-{
-	GGConv *ggconv = conv->ui_data;
-	GaimAccount *account;
-	char *title;
-
-	g_return_if_fail(ggconv);
-	g_return_if_fail(g_list_find(ggconv->list, conv));
-
-	ggconv->active_conv = conv;
-	account = gaim_conversation_get_account(conv);
-	title = get_conversation_title(conv, account);
-	gnt_screen_rename_widget(ggconv->window, title);
-	g_free(title);
-}
-
--- a/console/gntconv.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/**
- * @file gntconv.h GNT Conversation API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_CONV_H
-#define _GNT_CONV_H
-
-#include <gnt.h>
-#include <gntwidget.h>
-
-#include "conversation.h"
-
-/***************************************************************************
- * @name GNT Conversations API
- ***************************************************************************/
-/*@{*/
-
-typedef struct _GGConv GGConv;
-typedef struct _GGConvChat GGConvChat;
-typedef struct _GGConvIm GGConvIm;
-
-struct _GGConv
-{
-	GList *list;
-	GaimConversation *active_conv;
-
-	GntWidget *window;        /* the container */
-	GntWidget *entry;         /* entry */
-	GntWidget *tv;            /* text-view */
-
-	union
-	{
-		GGConvChat *chat;
-		GGConvIm *im;
-	} u;
-};
-
-struct _GGConvChat
-{
-	GntWidget *userlist;       /* the userlist */
-};
-
-struct _GGConvIm
-{
-	void *nothing_for_now;
-};
-
-/**
- * Get the ui-functions.
- *
- * @return The GaimConversationUiOps populated with the appropriate functions.
- */
-GaimConversationUiOps *gg_conv_get_ui_ops(void);
-
-/**
- * Perform the necessary initializations.
- */
-void gg_conversation_init(void);
-
-/**
- * Perform the necessary uninitializations.
- */
-void gg_conversation_uninit(void);
-
-/**
- * Set a conversation as active in a contactized conversation
- *
- * @param conv The conversation to make active.
- */
-void gg_conversation_set_active(GaimConversation *conv);
-
-/*@}*/
-
-#endif
--- a/console/gntdebug.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,304 +0,0 @@
-/**
- * @file gntdebug.c GNT Debug API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <gnt.h>
-#include <gntbox.h>
-#include <gnttextview.h>
-#include <gntbutton.h>
-#include <gntcheckbox.h>
-#include <gntline.h>
-
-#include "gntdebug.h"
-#include "gntgaim.h"
-#include "util.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#define PREF_ROOT "/gaim/gnt/debug"
-
-static struct
-{
-	GntWidget *window;
-	GntWidget *tview;
-	gboolean paused;
-	gboolean timestamps;
-} debug;
-
-static gboolean
-debug_window_kpress_cb(GntWidget *wid, const char *key, GntTextView *view)
-{
-	if (key[0] == 27)
-	{
-		if (strcmp(key, GNT_KEY_DOWN) == 0)
-			gnt_text_view_scroll(view, 1);
-		else if (strcmp(key, GNT_KEY_UP) == 0)
-			gnt_text_view_scroll(view, -1);
-		else if (strcmp(key, GNT_KEY_PGDOWN) == 0)
-			gnt_text_view_scroll(view, wid->priv.height - 2);
-		else if (strcmp(key, GNT_KEY_PGUP) == 0)
-			gnt_text_view_scroll(view, -(wid->priv.height - 2));
-		else
-			return FALSE;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static void
-gg_debug_print(GaimDebugLevel level, const char *category,
-		const char *args)
-{
-	if (debug.window && !debug.paused)
-	{
-		int pos = gnt_text_view_get_lines_below(GNT_TEXT_VIEW(debug.tview));
-		GntTextFormatFlags flag = GNT_TEXT_FLAG_NORMAL;
-
-		if (debug.timestamps) {
-			const char *mdate;
-			time_t mtime = time(NULL);
-			mdate = gaim_utf8_strftime("%H:%M:%S ", localtime(&mtime));
-			gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(debug.tview),
-					mdate, flag);
-		}
-
-		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(debug.tview),
-				category, GNT_TEXT_FLAG_BOLD);
-		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(debug.tview),
-				": ", GNT_TEXT_FLAG_BOLD);
-
-		switch (level)
-		{
-			case GAIM_DEBUG_WARNING:
-				flag |= GNT_TEXT_FLAG_UNDERLINE;
-			case GAIM_DEBUG_ERROR:
-			case GAIM_DEBUG_FATAL:
-				flag |= GNT_TEXT_FLAG_BOLD;
-				break;
-			default:
-				break;
-		}
-
-		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(debug.tview), args, flag);
-		if (pos <= 1)
-			gnt_text_view_scroll(GNT_TEXT_VIEW(debug.tview), 0);
-	}
-}
-
-static GaimDebugUiOps uiops =
-{
-	gg_debug_print,
-};
-
-GaimDebugUiOps *gg_debug_get_ui_ops()
-{
-	return &uiops;
-}
-
-static void
-reset_debug_win(GntWidget *w, gpointer null)
-{
-	debug.window = debug.tview = NULL;
-}
-
-static void
-clear_debug_win(GntWidget *w, GntTextView *tv)
-{
-	gnt_text_view_clear(tv);
-}
-
-static void
-print_stderr(const char *string)
-{
-	g_printerr("%s", string);
-}
-
-static void
-suppress_error_messages(const char *message)
-{}
-
-static void
-toggle_pause(GntWidget *w, gpointer n)
-{
-	debug.paused = !debug.paused;
-}
-
-static void
-toggle_timestamps(GntWidget *w, gpointer n)
-{
-	debug.timestamps = !debug.timestamps;
-	gaim_prefs_set_bool("/core/debug/timestamps", debug.timestamps);
-}
-
-/* Xerox */
-static void
-gaim_glib_log_handler(const gchar *domain, GLogLevelFlags flags,
-					  const gchar *msg, gpointer user_data)
-{
-	GaimDebugLevel level;
-	char *new_msg = NULL;
-	char *new_domain = NULL;
-
-	if ((flags & G_LOG_LEVEL_ERROR) == G_LOG_LEVEL_ERROR)
-		level = GAIM_DEBUG_ERROR;
-	else if ((flags & G_LOG_LEVEL_CRITICAL) == G_LOG_LEVEL_CRITICAL)
-		level = GAIM_DEBUG_FATAL;
-	else if ((flags & G_LOG_LEVEL_WARNING) == G_LOG_LEVEL_WARNING)
-		level = GAIM_DEBUG_WARNING;
-	else if ((flags & G_LOG_LEVEL_MESSAGE) == G_LOG_LEVEL_MESSAGE)
-		level = GAIM_DEBUG_INFO;
-	else if ((flags & G_LOG_LEVEL_INFO) == G_LOG_LEVEL_INFO)
-		level = GAIM_DEBUG_INFO;
-	else if ((flags & G_LOG_LEVEL_DEBUG) == G_LOG_LEVEL_DEBUG)
-		level = GAIM_DEBUG_MISC;
-	else
-	{
-		gaim_debug_warning("gntdebug",
-				   "Unknown glib logging level in %d\n", flags);
-
-		level = GAIM_DEBUG_MISC; /* This will never happen. */
-	}
-
-	if (msg != NULL)
-		new_msg = gaim_utf8_try_convert(msg);
-
-	if (domain != NULL)
-		new_domain = gaim_utf8_try_convert(domain);
-
-	if (new_msg != NULL)
-	{
-		gaim_debug(level, (new_domain != NULL ? new_domain : "g_log"),
-				   "%s\n", new_msg);
-
-		g_free(new_msg);
-	}
-
-	g_free(new_domain);
-}
-
-static void
-size_changed_cb(GntWidget *widget, int oldw, int oldh)
-{
-	int w, h;
-	gnt_widget_get_size(widget, &w, &h);
-	gaim_prefs_set_int(PREF_ROOT "/size/width", w);
-	gaim_prefs_set_int(PREF_ROOT "/size/height", h);
-}
-
-void gg_debug_window_show()
-{
-	debug.paused = FALSE;
-	debug.timestamps = gaim_prefs_get_bool("/core/debug/timestamps");
-	if (debug.window == NULL)
-	{
-		GntWidget *wid, *box;
-		debug.window = gnt_vbox_new(FALSE);
-		gnt_box_set_toplevel(GNT_BOX(debug.window), TRUE);
-		gnt_box_set_title(GNT_BOX(debug.window), _("Debug Window"));
-		gnt_box_set_pad(GNT_BOX(debug.window), 0);
-		gnt_box_set_alignment(GNT_BOX(debug.window), GNT_ALIGN_MID);
-
-		debug.tview = gnt_text_view_new();
-		gnt_box_add_widget(GNT_BOX(debug.window), debug.tview);
-		gnt_widget_set_size(debug.tview,
-				gaim_prefs_get_int(PREF_ROOT "/size/width"),
-				gaim_prefs_get_int(PREF_ROOT "/size/height"));
-		g_signal_connect(G_OBJECT(debug.tview), "size_changed", G_CALLBACK(size_changed_cb), NULL);
-
-		gnt_box_add_widget(GNT_BOX(debug.window), gnt_line_new(FALSE));
-
-		box = gnt_hbox_new(FALSE);
-		gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID);
-		gnt_box_set_fill(GNT_BOX(box), FALSE);
-
-		/* XXX: Setting the GROW_Y for the following widgets don't make sense. But right now
-		 * it's necessary to make the width of the debug window resizable ... like I said,
-		 * it doesn't make sense. The bug is likely in the packing in gntbox.c.
-		 */
-		wid = gnt_button_new(_("Clear"));
-		g_signal_connect(G_OBJECT(wid), "activate", G_CALLBACK(clear_debug_win), debug.tview);
-		GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y);
-		gnt_box_add_widget(GNT_BOX(box), wid);
-
-		wid = gnt_check_box_new(_("Pause"));
-		g_signal_connect(G_OBJECT(wid), "toggled", G_CALLBACK(toggle_pause), NULL);
-		GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y);
-		gnt_box_add_widget(GNT_BOX(box), wid);
-
-		wid = gnt_check_box_new(_("Timestamps"));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(wid), debug.timestamps);
-		g_signal_connect(G_OBJECT(wid), "toggled", G_CALLBACK(toggle_timestamps), NULL);
-		GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y);
-		gnt_box_add_widget(GNT_BOX(box), wid);
-
-		gnt_box_add_widget(GNT_BOX(debug.window), box);
-		GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_GROW_Y);
-
-		gnt_widget_set_name(debug.window, "debug-window");
-
-		g_signal_connect(G_OBJECT(debug.window), "destroy", G_CALLBACK(reset_debug_win), NULL);
-		g_signal_connect(G_OBJECT(debug.window), "key_pressed", G_CALLBACK(debug_window_kpress_cb), debug.tview);
-	}
-
-	gnt_widget_show(debug.window);
-}
-
-static gboolean
-start_with_debugwin(gpointer null)
-{
-	gg_debug_window_show();
-	return FALSE;
-}
-
-void gg_debug_init()
-{
-/* Xerox */
-#define REGISTER_G_LOG_HANDLER(name) \
-	g_log_set_handler((name), G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL \
-					  | G_LOG_FLAG_RECURSION, \
-					  gaim_glib_log_handler, NULL)
-
-	/* Register the glib log handlers. */
-	REGISTER_G_LOG_HANDLER(NULL);
-	REGISTER_G_LOG_HANDLER("GLib");
-	REGISTER_G_LOG_HANDLER("GModule");
-	REGISTER_G_LOG_HANDLER("GLib-GObject");
-	REGISTER_G_LOG_HANDLER("GThread");
-
-	g_set_print_handler(print_stderr);   /* Redirect the debug messages to stderr */
-	g_set_printerr_handler(suppress_error_messages);
-
-	gaim_prefs_add_none(PREF_ROOT);
-	gaim_prefs_add_none(PREF_ROOT "/size");
-	gaim_prefs_add_int(PREF_ROOT "/size/width", 60);
-	gaim_prefs_add_int(PREF_ROOT "/size/height", 15);
-
-	if (gaim_debug_is_enabled())
-		g_timeout_add(0, start_with_debugwin, NULL);
-}
-
-void gg_debug_uninit()
-{
-}
-
--- a/console/gntdebug.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/**
- * @file gntdebug.h GNT Debug API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_DEBUG_H
-#define _GNT_DEBUG_H
-
-#include "debug.h"
-
-/**********************************************************************
- * @name GNT Debug API
- **********************************************************************/
-/*@{*/
-
-/**
- * Get the ui-functions.
- *
- * @return The GaimDebugUiOps structure populated with the appropriate functions.
- */
-GaimDebugUiOps *gg_debug_get_ui_ops(void);
-
-/**
- * Perform necessary initializations.
- */
-void gg_debug_init(void);
-
-/**
- * Perform necessary uninitializations.
- */
-void gg_debug_uninit(void);
-
-/**
- * Show the debug window.
- */
-void gg_debug_window_show(void);
-
-/*@}*/
-
-#endif
--- a/console/gntft.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,532 +0,0 @@
-/**
- * @file gntft.c GNT File Transfer UI
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntbutton.h>
-#include <gntcheckbox.h>
-#include <gntlabel.h>
-#include <gnttree.h>
-#include "internal.h"
-
-#include "debug.h"
-#include "notify.h"
-#include "ft.h"
-#include "prpl.h"
-#include "util.h"
-
-#include "gntft.h"
-#include "prefs.h"
-
-#define GAIM_GNTXFER(xfer) \
-	(GaimGntXferUiData *)(xfer)->ui_data
-
-typedef struct
-{
-	gboolean keep_open;
-	gboolean auto_clear;
-	gint num_transfers;
-
-	GntWidget *window;
-	GntWidget *tree;
-
-	GntWidget *remove_button;
-	GntWidget *stop_button;
-	GntWidget *close_button;
-} GaimGntXferDialog;
-
-static GaimGntXferDialog *xfer_dialog = NULL;
-
-typedef struct
-{
-	time_t last_updated_time;
-	gboolean in_list;
-
-	char *name;
-
-} GaimGntXferUiData;
-
-enum
-{
-	COLUMN_PROGRESS = 0,
-	COLUMN_FILENAME,
-	COLUMN_SIZE,
-	COLUMN_SPEED,
-	COLUMN_REMAINING,
-	COLUMN_STATUS,
-	NUM_COLUMNS
-};
-
-
-/**************************************************************************
- * Utility Functions
- **************************************************************************/
-
-static void
-update_title_progress()
-{
-	const GList *list;
-	int num_active_xfers = 0;
-	guint64 total_bytes_xferred = 0;
-	guint64 total_file_size = 0;
-
-	if (xfer_dialog == NULL || xfer_dialog->window == NULL)
-		return;
-
-	/* Find all active transfers */
-	for (list = gnt_tree_get_rows(GNT_TREE(xfer_dialog->tree)); list; list = list->next) {
-		GaimXfer *xfer = (GaimXfer *)list->data;
-
-		if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_STARTED) {
-			num_active_xfers++;
-			total_bytes_xferred += gaim_xfer_get_bytes_sent(xfer);
-			total_file_size += gaim_xfer_get_size(xfer);
-		}
-	}
-
-	/* Update the title */
-	if (num_active_xfers > 0) {
-		gchar *title;
-		int total_pct = 0;
-
-		if (total_file_size > 0) {
-			total_pct = 100 * total_bytes_xferred / total_file_size;
-		}
-
-		title = g_strdup_printf(_("File Transfers - %d%% of %d files"),
-				total_pct, num_active_xfers);
-		gnt_screen_rename_widget((xfer_dialog->window), title);
-		g_free(title);
-	} else {
-		gnt_screen_rename_widget((xfer_dialog->window), _("File Transfers"));
-	}
-}
-
-
-/**************************************************************************
- * Callbacks
- **************************************************************************/
-static void
-toggle_keep_open_cb(GntWidget *w)
-{
-	xfer_dialog->keep_open = !xfer_dialog->keep_open;
-	gaim_prefs_set_bool("/gaim/gnt/filetransfer/keep_open",
-						xfer_dialog->keep_open);
-}
-
-static void
-toggle_clear_finished_cb(GntWidget *w)
-{
-	xfer_dialog->auto_clear = !xfer_dialog->auto_clear;
-	gaim_prefs_set_bool("/gaim/gnt/filetransfer/clear_finished",
-						xfer_dialog->auto_clear);
-}
-
-static void
-remove_button_cb(GntButton *button)
-{
-	GaimXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree));
-	if (selected_xfer && (selected_xfer->status == GAIM_XFER_STATUS_CANCEL_LOCAL ||
-			selected_xfer->status == GAIM_XFER_STATUS_CANCEL_REMOTE ||
-			selected_xfer->status == GAIM_XFER_STATUS_DONE)) {
-		gg_xfer_dialog_remove_xfer(selected_xfer);
-	}
-}
-
-static void
-stop_button_cb(GntButton *button)
-{
-	GaimXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree));
-	if (selected_xfer && selected_xfer->status == GAIM_XFER_STATUS_STARTED)
-		gaim_xfer_cancel_local(selected_xfer);
-}
-
-#if 0
-static void
-tree_selection_changed_cb(GntTree *tree, GntTreeRow *old, GntTreeRow *current, gpointer n)
-{
-	xfer_dialog->selected_xfer = (GaimXfer *)gnt_tree_get_selection_data(tree);
-}
-#endif
-
-/**************************************************************************
- * Dialog Building Functions
- **************************************************************************/
-
-
-void
-gg_xfer_dialog_new(void)
-{
-	const GList *iter;
-	GntWidget *window;
-	GntWidget *bbox;
-	GntWidget *button;
-	GntWidget *checkbox;
-	GntWidget *tree;
-
-	if (!xfer_dialog)
-		xfer_dialog = g_new0(GaimGntXferDialog, 1);
-
-	xfer_dialog->keep_open =
-		gaim_prefs_get_bool("/gaim/gnt/filetransfer/keep_open");
-	xfer_dialog->auto_clear =
-		gaim_prefs_get_bool("/gaim/gnt/filetransfer/clear_finished");
-
-	/* Create the window. */
-	xfer_dialog->window = window = gnt_vbox_new(FALSE);
-	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gg_xfer_dialog_destroy), NULL);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-	gnt_box_set_title(GNT_BOX(window), _("File Transfers"));
-
-	xfer_dialog->tree = tree = gnt_tree_new_with_columns(NUM_COLUMNS);
-	gnt_tree_set_column_titles(GNT_TREE(tree), _("Progress"), _("Filename"), _("Size"), _("Speed"), _("Remaining"), _("Status"));
-	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_PROGRESS, 8);
-	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_FILENAME, 8);
-	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_SIZE, 10);
-	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_SPEED, 10);
-	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_REMAINING, 10);
-	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_STATUS, 10);
-	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
-	gnt_box_add_widget(GNT_BOX(window), tree);
-	/*g_signal_connect(G_OBJECT(tree), "selection-changed",*/
-					/*G_CALLBACK(tree_selection_changed_cb), NULL);*/
-	checkbox = gnt_check_box_new( _("Close this window when all transfers finish"));
-	gnt_check_box_set_checked(GNT_CHECK_BOX(checkbox),
-								 !xfer_dialog->keep_open);
-	g_signal_connect(G_OBJECT(checkbox), "toggled",
-					 G_CALLBACK(toggle_keep_open_cb), NULL);
-	gnt_box_add_widget(GNT_BOX(window), checkbox);
-
-	checkbox = gnt_check_box_new(_("Clear finished transfers"));
-	gnt_check_box_set_checked(GNT_CHECK_BOX(checkbox),
-								 xfer_dialog->auto_clear);
-	g_signal_connect(G_OBJECT(checkbox), "toggled",
-					 G_CALLBACK(toggle_clear_finished_cb), NULL);
-	gnt_box_add_widget(GNT_BOX(window), checkbox);
-
-	bbox = gnt_hbox_new(TRUE);
-
-	xfer_dialog->remove_button = button = gnt_button_new(_("Remove"));
-	g_signal_connect(G_OBJECT(button), "activate",
-					 G_CALLBACK(remove_button_cb), NULL);
-	gnt_box_add_widget(GNT_BOX(bbox), button);
-
-	xfer_dialog->stop_button = button = gnt_button_new(_("Stop"));
-	g_signal_connect(G_OBJECT(button), "activate",
-					 G_CALLBACK(stop_button_cb), NULL);
-	gnt_box_add_widget(GNT_BOX(bbox), button);
-
-	xfer_dialog->close_button = button = gnt_button_new(_("Close"));
-	g_signal_connect(G_OBJECT(button), "activate",
-					 G_CALLBACK(gg_xfer_dialog_destroy), NULL);
-	gnt_box_add_widget(GNT_BOX(bbox), button);
-
-	gnt_box_add_widget(GNT_BOX(window), bbox);
-
-	for (iter = gaim_xfers_get_all(); iter; iter = iter->next) {
-		GaimXfer *xfer = (GaimXfer *)iter->data;
-		GaimGntXferUiData *data = GAIM_GNTXFER(xfer);
-		if (data->in_list) {
-			gg_xfer_dialog_add_xfer(xfer);
-			gg_xfer_dialog_update_xfer(xfer);
-			gnt_tree_set_selected(GNT_TREE(tree), xfer);
-		}
-	}
-	gnt_widget_show(xfer_dialog->window);
-}
-
-void
-gg_xfer_dialog_destroy()
-{
-	gnt_widget_destroy(xfer_dialog->window);
-	g_free(xfer_dialog);
-	xfer_dialog = NULL;
-}
-
-void
-gg_xfer_dialog_show()
-{
-	if (xfer_dialog == NULL)
-		gg_xfer_dialog_new();
-}
-
-void
-gg_xfer_dialog_add_xfer(GaimXfer *xfer)
-{
-	GaimGntXferUiData *data;
-	GaimXferType type;
-	char *size_str, *remaining_str;
-	char *lfilename, *utf8;
-
-	g_return_if_fail(xfer_dialog != NULL);
-	g_return_if_fail(xfer != NULL);
-
-	gaim_xfer_ref(xfer);
-
-	data = GAIM_GNTXFER(xfer);
-	data->in_list = TRUE;
-
-	gg_xfer_dialog_show();
-
-	data->last_updated_time = 0;
-
-	type = gaim_xfer_get_type(xfer);
-
-	size_str      = gaim_str_size_to_units(gaim_xfer_get_size(xfer));
-	remaining_str = gaim_str_size_to_units(gaim_xfer_get_bytes_remaining(xfer));
-
-	lfilename = g_path_get_basename(gaim_xfer_get_local_filename(xfer));
-	utf8 = g_filename_to_utf8(lfilename, -1, NULL, NULL, NULL);
-	g_free(lfilename);
-	lfilename = utf8;
-	gnt_tree_add_row_last(GNT_TREE(xfer_dialog->tree), xfer,
-		gnt_tree_create_row(GNT_TREE(xfer_dialog->tree),
-			"0.0", (type == GAIM_XFER_RECEIVE) ? gaim_xfer_get_filename(xfer) : lfilename,
-			size_str, "0.0", "",_("Waiting for transfer to begin")), NULL);
-	g_free(lfilename);
-
-	g_free(size_str);
-	g_free(remaining_str);
-
-	xfer_dialog->num_transfers++;
-
-	update_title_progress();
-}
-
-void
-gg_xfer_dialog_remove_xfer(GaimXfer *xfer)
-{
-	GaimGntXferUiData *data;
-
-	g_return_if_fail(xfer_dialog != NULL);
-	g_return_if_fail(xfer != NULL);
-
-	data = GAIM_GNTXFER(xfer);
-
-	if (data == NULL)
-		return;
-
-	if (!data->in_list)
-		return;
-
-	data->in_list = FALSE;
-
-	gnt_tree_remove(GNT_TREE(xfer_dialog->tree), xfer);
-
-	xfer_dialog->num_transfers--;
-
-	if (xfer_dialog->num_transfers == 0 && !xfer_dialog->keep_open)
-		gg_xfer_dialog_destroy();
-	else 
-		update_title_progress();
-	gaim_xfer_unref(xfer);
-}
-
-void
-gg_xfer_dialog_cancel_xfer(GaimXfer *xfer)
-{
-	GaimGntXferUiData *data;
-	const gchar *status;
-
-	g_return_if_fail(xfer_dialog != NULL);
-	g_return_if_fail(xfer != NULL);
-
-	data = GAIM_GNTXFER(xfer);
-
-	if (data == NULL)
-		return;
-
-	if (!data->in_list)
-		return;
-
-	if ((gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) && (xfer_dialog->auto_clear)) {
-		gg_xfer_dialog_remove_xfer(xfer);
-		return;
-	}
-
-	data = GAIM_GNTXFER(xfer);
-
-	update_title_progress();
-
-	if (gaim_xfer_is_canceled(xfer))
-		status = _("Canceled");
-	else
-		status = _("Failed");
-
-	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, status);
-}
-
-void
-gg_xfer_dialog_update_xfer(GaimXfer *xfer)
-{
-	GaimGntXferUiData *data;
-	char *size_str, *remaining_str;
-	time_t current_time;
-	char prog_str[5];
-	double kb_sent, kb_rem;
-	double kbps = 0.0;
-	time_t elapsed, now;
-	char *kbsec;
-
-	if (xfer->end_time != 0)
-		now = xfer->end_time;
-	else
-		now = time(NULL);
-
-	kb_sent = gaim_xfer_get_bytes_sent(xfer) / 1024.0;
-	kb_rem  = gaim_xfer_get_bytes_remaining(xfer) / 1024.0;
-	elapsed = (xfer->start_time > 0 ? now - xfer->start_time : 0);
-	kbps    = (elapsed > 0 ? (kb_sent / elapsed) : 0);
-
-	kbsec = g_strdup_printf(_("%.2f KB/s"), kbps);
-
-	g_return_if_fail(xfer_dialog != NULL);
-	g_return_if_fail(xfer != NULL);
-
-	if ((data = GAIM_GNTXFER(xfer)) == NULL)
-		return;
-
-	if (data->in_list == FALSE)
-		return;
-
-	current_time = time(NULL);
-	if (((current_time - data->last_updated_time) == 0) &&
-		(!gaim_xfer_is_completed(xfer))) {
-		/* Don't update the window more than once per second */
-		return;
-	}
-	data->last_updated_time = current_time;
-
-	size_str      = gaim_str_size_to_units(gaim_xfer_get_size(xfer));
-	remaining_str = gaim_str_size_to_units(gaim_xfer_get_bytes_remaining(xfer));
-
-	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_PROGRESS,
-			g_ascii_dtostr(prog_str, sizeof(prog_str), gaim_xfer_get_progress(xfer) * 100.));
-	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SIZE, size_str);
-	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_REMAINING, remaining_str);
-	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SPEED, kbsec);
-	g_free(size_str);
-	g_free(remaining_str);
-	if (gaim_xfer_is_completed(xfer)) {
-		gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Finished"));
-	} else {
-		gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Transferring"));
-	}
-
-	update_title_progress();
-
-	if (gaim_xfer_is_completed(xfer) && xfer_dialog->auto_clear)
-		gg_xfer_dialog_remove_xfer(xfer);
-}
-
-/**************************************************************************
- * File Transfer UI Ops
- **************************************************************************/
-static void
-gg_xfer_new_xfer(GaimXfer *xfer)
-{
-	GaimGntXferUiData *data;
-
-	/* This is where we're setting xfer->ui_data for the first time. */
-	data = g_new0(GaimGntXferUiData, 1);
-	xfer->ui_data = data;
-}
-
-static void
-gg_xfer_destroy(GaimXfer *xfer)
-{
-	GaimGntXferUiData *data;
-
-	data = GAIM_GNTXFER(xfer);
-	if (data) {
-		g_free(data->name);
-		g_free(data);
-		xfer->ui_data = NULL;
-	}
-}
-
-static void
-gg_xfer_add_xfer(GaimXfer *xfer)
-{
-	if (!xfer_dialog)
-		gg_xfer_dialog_new();
-
-	gg_xfer_dialog_add_xfer(xfer);
-	gnt_tree_set_selected(GNT_TREE(xfer_dialog->tree), xfer);
-}
-
-static void
-gg_xfer_update_progress(GaimXfer *xfer, double percent)
-{
-	if (xfer_dialog)
-		gg_xfer_dialog_update_xfer(xfer);
-}
-
-static void
-gg_xfer_cancel_local(GaimXfer *xfer)
-{
-	if (xfer_dialog)
-		gg_xfer_dialog_cancel_xfer(xfer);
-}
-
-static void
-gg_xfer_cancel_remote(GaimXfer *xfer)
-{
-	if (xfer_dialog)
-		gg_xfer_dialog_cancel_xfer(xfer);
-}
-
-static GaimXferUiOps ops =
-{
-	gg_xfer_new_xfer,
-	gg_xfer_destroy,
-	gg_xfer_add_xfer,
-	gg_xfer_update_progress,
-	gg_xfer_cancel_local,
-	gg_xfer_cancel_remote
-};
-
-/**************************************************************************
- * GNT File Transfer API
- **************************************************************************/
-void
-gg_xfers_init(void)
-{
-	gaim_prefs_add_none("/gaim/gnt/filetransfer");
-	gaim_prefs_add_bool("/gaim/gnt/filetransfer/clear_finished", TRUE);
-	gaim_prefs_add_bool("/gaim/gnt/filetransfer/keep_open", FALSE);
-}
-
-void
-gg_xfers_uninit(void)
-{
-	if (xfer_dialog != NULL)
-		gg_xfer_dialog_destroy();
-}
-
-GaimXferUiOps *
-gg_xfers_get_ui_ops(void)
-{
-	return &ops;
-}
--- a/console/gntft.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/**
- * @file gntft.h GNT File Transfer UI
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GAIM_GNTFT_H_
-#define _GAIM_GNTFT_H_
-
-#include "ft.h"
-
-
-/**************************************************************************/
-/** @name GNT File Transfer Dialog API                                    */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Creates a new file transfer dialog.
- *
- * @return The new dialog.
- */
-void gg_xfer_dialog_new(void);
-
-/**
- * Destroys a file transfer dialog.
- *
- * @param dialog The file transfer dialog.
- */
-void gg_xfer_dialog_destroy(void);
-
-/**
- * Displays the file transfer dialog given.
- * If dialog is @c NULL, displays the default dialog, creating one if necessary
- *
- * @param dialog The file transfer dialog to show.
- */
-void gg_xfer_dialog_show(void);
-
-/**
- * Hides the file transfer dialog.
- *
- * @param dialog The file transfer dialog to hide.
- */
-void gg_xfer_dialog_hide();
-
-/**
- * Adds a file transfer to the dialog.
- *
- * @param dialog The file transfer dialog.
- * @param xfer   The file transfer.
- */
-void gg_xfer_dialog_add_xfer(GaimXfer *xfer);
-
-/**
- * Removes a file transfer from the dialog.
- *
- * @param dialog The file transfer dialog.
- * @param xfer   The file transfer.
- */
-void gg_xfer_dialog_remove_xfer(GaimXfer *xfer);
-
-/**
- * Indicate in a file transfer dialog that a transfer was canceled.
- *
- * @param dialog The file transfer dialog.
- * @param xfer   The file transfer that was canceled.
- */
-void gg_xfer_dialog_cancel_xfer(GaimXfer *xfer);
-
-/**
- * Updates the information for a transfer in the dialog.
- *
- * @param dialog The file transfer dialog.
- * @param xfer   The file transfer.
- */
-void gg_xfer_dialog_update_xfer(GaimXfer *xfer);
-
-/*@}*/
-
-/**************************************************************************/
-/** @name GNT  File Transfer API                                          */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Initializes the GNT file transfer system.
- */
-void gg_xfers_init(void);
-
-/**
- * Uninitializes the GNT file transfer system.
- */
-void gg_xfers_uninit(void);
-
-/**
- * Returns the UI operations structure for the GNT file transfer UI.
- *
- * @return The GNT file transfer UI operations structure.
- */
-GaimXferUiOps *gg_xfers_get_ui_ops(void);
-
-/*@}*/
-
-#endif /* _GAIM_GNTFT_H_ */
--- a/console/gntgaim.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,417 +0,0 @@
-/**
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#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 "prefix.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 "gntdebug.h"
-#include "gntgaim.h"
-#include "gntprefs.h"
-#include "gntui.h"
-#include "gntidle.h"
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#include "config.h"
-
-static void
-debug_init()
-{
-	gg_debug_init();
-	gaim_debug_set_ui_ops(gg_debug_get_ui_ops());
-}
-
-static GaimCoreUiOps core_ops =
-{
-	gg_prefs_init,
-	debug_init,
-	gnt_ui_init,
-	gnt_ui_uninit
-};
-
-static GaimCoreUiOps *
-gnt_core_get_ui_ops()
-{
-	return &core_ops;
-}
-
-/* Anything IO-related is directly copied from gtkgaim's source tree */
-
-#define GAIM_GNT_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
-#define GAIM_GNT_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
-
-typedef struct _GaimGntIOClosure {
-	GaimInputFunction function;
-	guint result;
-	gpointer data;
-
-} GaimGntIOClosure;
-
-static void gaim_gnt_io_destroy(gpointer data)
-{
-	g_free(data);
-}
-
-static gboolean gaim_gnt_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
-{
-	GaimGntIOClosure *closure = data;
-	GaimInputCondition gaim_cond = 0;
-
-	if (condition & GAIM_GNT_READ_COND)
-		gaim_cond |= GAIM_INPUT_READ;
-	if (condition & GAIM_GNT_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_misc("gnt_eventloop",
-			   "CLOSURE received GIOCondition of 0x%x, which does not"
-			   " match 0x%x (READ) or 0x%x (WRITE)\n",
-			   condition, GAIM_GNT_READ_COND, GAIM_GNT_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)
-{
-	GaimGntIOClosure *closure = g_new0(GaimGntIOClosure, 1);
-	GIOChannel *channel;
-	GIOCondition cond = 0;
-
-	closure->function = function;
-	closure->data = data;
-
-	if (condition & GAIM_INPUT_READ)
-		cond |= GAIM_GNT_READ_COND;
-	if (condition & GAIM_INPUT_WRITE)
-		cond |= GAIM_GNT_WRITE_COND;
-
-	channel = g_io_channel_unix_new(fd);
-	closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
-					      gaim_gnt_io_invoke, closure, gaim_gnt_io_destroy);
-
-	g_io_channel_unref(channel);
-	return closure->result;
-}
-
-static GaimEventLoopUiOps eventloop_ops =
-{
-	g_timeout_add,
-	g_source_remove,
-	gnt_input_add,
-	g_source_remove,
-	NULL /* input_get_error */
-};
-
-static GaimEventLoopUiOps *
-gnt_eventloop_get_ui_ops(void)
-{
-	return &eventloop_ops;
-}
-
-/* This is copied from gtkgaim */
-static char *
-gnt_find_binary_location(void *symbol, void *data)
-{
-	static char *fullname = NULL;
-	static gboolean first = TRUE;
-
-	char *argv0 = data;
-	struct stat st;
-	char *basebuf, *linkbuf, *fullbuf;
-
-	if (!first)
-		/* We've already been through this. */
-		return strdup(fullname);
-
-	first = FALSE;
-
-	if (!argv0)
-		return NULL;
-
-
-	basebuf = g_find_program_in_path(argv0);
-
-	/* But we still need to deal with symbolic links */
-	g_lstat(basebuf, &st);
-	while ((st.st_mode & S_IFLNK) == S_IFLNK) {
-		int written;
-		linkbuf = g_malloc(1024);
-		written = readlink(basebuf, linkbuf, 1024 - 1);
-		if (written == -1)
-		{
-			/* This really shouldn't happen, but do we
-			 * need something better here? */
-			g_free(linkbuf);
-			continue;
-		}
-		linkbuf[written] = '\0';
-		if (linkbuf[0] == G_DIR_SEPARATOR) {
-			/* an absolute path */
-			fullbuf = g_strdup(linkbuf);
-		} else {
-			char *dirbuf = g_path_get_dirname(basebuf);
-			/* a relative path */
-			fullbuf = g_strdup_printf("%s%s%s",
-					dirbuf, G_DIR_SEPARATOR_S,
-					linkbuf);
-			g_free(dirbuf);
-		}
-		/* There's no memory leak here.  Really! */
-		g_free(linkbuf);
-		g_free(basebuf);
-		basebuf = fullbuf;
-		g_lstat(basebuf, &st);
-	}
-
-	fullname = basebuf;
-	return strdup(fullname);
-}
-
-
-/* This is mostly copied from gtkgaim's source tree */
-static void
-show_usage(const char *name, gboolean terse)
-{
-	char *text;
-
-	if (terse) {
-		text = g_strdup_printf(_("%s. Try `%s -h' for more information.\n"), VERSION, name);
-	} else {
-		text = g_strdup_printf(_("%s\n"
-		       "Usage: %s [OPTION]...\n\n"
-		       "  -c, --config=DIR    use DIR for config files\n"
-		       "  -d, --debug         print debugging messages to stdout\n"
-		       "  -h, --help          display this help and exit\n"
-		       "  -n, --nologin       don't automatically login\n"
-		       "  -v, --version       display the current version and exit\n"), VERSION, name);
-	}
-
-	gaim_print_utf8_to_console(stdout, text);
-	g_free(text);
-}
-
-static int
-init_libgaim(int argc, char **argv)
-{
-	char *path;
-	int opt;
-	gboolean opt_help = FALSE;
-	gboolean opt_nologin = FALSE;
-	gboolean opt_version = FALSE;
-	char *opt_config_dir_arg = NULL;
-	char *opt_session_arg = NULL;
-	gboolean debug_enabled = FALSE;
-
-	struct option long_options[] = {
-		{"config",   required_argument, NULL, 'c'},
-		{"debug",    no_argument,       NULL, 'd'},
-		{"help",     no_argument,       NULL, 'h'},
-		{"nologin",  no_argument,       NULL, 'n'},
-		{"session",  required_argument, NULL, 's'},
-		{"version",  no_argument,       NULL, 'v'},
-		{0, 0, 0, 0}
-	};
-
-	gaim_br_set_locate_fallback_func(gnt_find_binary_location, argv[0]);
-
-#ifdef ENABLE_NLS
-	bindtextdomain(PACKAGE, LOCALEDIR);
-	bind_textdomain_codeset(PACKAGE, "UTF-8");
-	textdomain(PACKAGE);
-#endif
-
-#ifdef HAVE_SETLOCALE
-	setlocale(LC_ALL, "");
-#endif
-
-	/* scan command-line options */
-	opterr = 1;
-	while ((opt = getopt_long(argc, argv,
-#ifndef _WIN32
-				  "c:dhn::s:v",
-#else
-				  "c:dhn::v",
-#endif
-				  long_options, NULL)) != -1) {
-		switch (opt) {
-		case 'c':	/* config dir */
-			g_free(opt_config_dir_arg);
-			opt_config_dir_arg = g_strdup(optarg);
-			break;
-		case 'd':	/* debug */
-			debug_enabled = TRUE;
-			break;
-		case 'h':	/* help */
-			opt_help = TRUE;
-			break;
-		case 'n':	/* no autologin */
-			opt_nologin = TRUE;
-			break;
-		case 's':	/* use existing session ID */
-			g_free(opt_session_arg);
-			opt_session_arg = g_strdup(optarg);
-			break;
-		case 'v':	/* version */
-			opt_version = TRUE;
-			break;
-		case '?':	/* show terse help */
-		default:
-			show_usage(argv[0], TRUE);
-			return 0;
-			break;
-		}
-	}
-
-	/* show help message */
-	if (opt_help) {
-		show_usage(argv[0], FALSE);
-		return 0;
-	}
-	/* show version message */
-	if (opt_version) {
-		printf("gaim-text %s\n", VERSION);
-		return 0;
-	}
-
-	/* set a user-specified config directory */
-	if (opt_config_dir_arg != NULL) {
-		gaim_util_set_user_dir(opt_config_dir_arg);
-		g_free(opt_config_dir_arg);
-	}
-
-	/*
-	 * We're done piddling around with command line arguments.
-	 * Fire up this baby.
-	 */
-
-	/* Because we don't want debug-messages to show up and corrup the display */
-	gaim_debug_set_enabled(debug_enabled);
-
-	gaim_core_set_ui_ops(gnt_core_get_ui_ops());
-	gaim_eventloop_set_ui_ops(gnt_eventloop_get_ui_ops());
-	gaim_idle_set_ui_ops(gg_idle_get_ui_ops());
-
-	path = g_build_filename(gaim_user_dir(), "plugins", NULL);
-	gaim_plugins_add_search_path(path);
-	g_free(path);
-
-	gaim_plugins_add_search_path(LIBDIR);
-
-	if (!gaim_core_init(GAIM_GNT_UI))
-	{
-		fprintf(stderr,
-				"Initialization of the Gaim core failed. Dumping core.\n"
-				"Please report this!\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/gnt/plugins/loaded");
-
-	/* TODO: Move pounces loading into gaim_pounces_init() */
-	gaim_pounces_load();
-
-	if (opt_nologin)
-	{
-		/* Set all accounts to "offline" */
-		GaimSavedStatus *saved_status;
-
-		/* If we've used this type+message before, lookup the transient status */
-		saved_status = gaim_savedstatus_find_transient_by_type_and_message(
-							GAIM_STATUS_OFFLINE, NULL);
-
-		/* If this type+message is unique then create a new transient saved status */
-		if (saved_status == NULL)
-			saved_status = gaim_savedstatus_new(NULL, GAIM_STATUS_OFFLINE);
-
-		/* Set the status for each account */
-		gaim_savedstatus_activate(saved_status);
-	}
-	else
-	{
-		/* Everything is good to go--sign on already */
-		if (!gaim_prefs_get_bool("/core/savedstatus/startup_current_status"))
-			gaim_savedstatus_activate(gaim_savedstatus_get_startup());
-		gaim_accounts_restore_current_statuses();
-	}
-
-	return 1;
-}
-
-int main(int argc, char **argv)
-{
-	signal(SIGPIPE, SIG_IGN);
-
-	/* Initialize the libgaim stuff */
-	if (!init_libgaim(argc, argv))
-		return 0;
-
-	gaim_blist_show();
-	gnt_main();
-
-#ifdef STANDALONE
-	gaim_core_quit();
-#endif
-
-	return 0;
-}
-
--- a/console/gntgaim.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/**
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <glib.h>
-
-#include "libpurple/internal.h"
-
-#define GAIM_GNT_UI "gnt-gaim"
-
--- a/console/gntidle.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "internal.h"
-#include "gntidle.h"
-#include "gntwm.h"
-
-#include "idle.h"
-
-static time_t
-gg_get_idle_time()
-{
-	return gnt_wm_get_idle_time();
-}
-
-static GaimIdleUiOps ui_ops =
-{
-	gg_get_idle_time
-};
-
-GaimIdleUiOps *
-gg_idle_get_ui_ops()
-{
-	return &ui_ops;
-}
--- a/console/gntidle.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/**
- * @file gntidle.h GNT Idle API
- * @ingroup gntui
- *
- * gaim
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_IDLE_H_
-#define _GNT_IDLE_H_
-
-#include "idle.h"
-
-/**************************************************************************/
-/** @name GNT Idle API                                                    */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Returns the GNT idle UI ops.
- *
- * @return The UI operations structure.
- */
-GaimIdleUiOps *gg_idle_get_ui_ops(void);
-
-/*@}*/
-
-#endif /* _GG_IDLE_H_ */
--- a/console/gntnotify.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,374 +0,0 @@
-/**
- * @file gntnotify.c GNT Notify API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntbutton.h>
-#include <gntlabel.h>
-#include <gnttree.h>
-
-#include <util.h>
-
-#include "gntnotify.h"
-#include "gntgaim.h"
-
-static struct
-{
-	GntWidget *window;
-	GntWidget *tree;
-} emaildialog;
-
-static void
-notify_msg_window_destroy_cb(GntWidget *window, GaimNotifyMsgType type)
-{
-	gaim_notify_close(type, window);
-}
-
-static void *
-gg_notify_message(GaimNotifyMsgType type, const char *title,
-		const char *primary, const char *secondary)
-{
-	GntWidget *window, *button;
-	GntTextFormatFlags pf = 0, sf = 0;
-
-	switch (type)
-	{
-		case GAIM_NOTIFY_MSG_ERROR:
-			sf |= GNT_TEXT_FLAG_BOLD;
-		case GAIM_NOTIFY_MSG_WARNING:
-			pf |= GNT_TEXT_FLAG_UNDERLINE;
-		case GAIM_NOTIFY_MSG_INFO:
-			pf |= GNT_TEXT_FLAG_BOLD;
-			break;
-	}
-
-	window = gnt_box_new(FALSE, TRUE);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-	gnt_box_set_title(GNT_BOX(window), title);
-	gnt_box_set_fill(GNT_BOX(window), FALSE);
-	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
-
-	if (primary)
-		gnt_box_add_widget(GNT_BOX(window),
-				gnt_label_new_with_format(primary, pf));
-	if (secondary)
-		gnt_box_add_widget(GNT_BOX(window),
-				gnt_label_new_with_format(secondary, sf));
-
-	button = gnt_button_new(_("OK"));
-	gnt_box_add_widget(GNT_BOX(window), button);
-	g_signal_connect_swapped(G_OBJECT(button), "activate",
-			G_CALLBACK(gnt_widget_destroy), window);
-	g_signal_connect(G_OBJECT(window), "destroy",
-			G_CALLBACK(notify_msg_window_destroy_cb), GINT_TO_POINTER(type));
-
-	gnt_widget_show(window);
-	return window;
-}
-
-/* handle is, in all/most occasions, a GntWidget * */
-static void gg_close_notify(GaimNotifyType type, void *handle)
-{
-	GntWidget *widget = handle;
-
-	if (!widget)
-		return;
-
-	while (widget->parent)
-		widget = widget->parent;
-	
-	if (type == GAIM_NOTIFY_SEARCHRESULTS)
-		gaim_notify_searchresults_free(g_object_get_data(handle, "notify-results"));
-#if 1
-	/* This did not seem to be necessary */
-	g_signal_handlers_disconnect_by_func(G_OBJECT(widget),
-			G_CALLBACK(notify_msg_window_destroy_cb), GINT_TO_POINTER(type));
-#endif
-	gnt_widget_destroy(widget);
-}
-
-static void *gg_notify_formatted(const char *title, const char *primary,
-		const char *secondary, const char *text)
-{
-	/* XXX: For now, simply strip the html and use _notify_message. For future use,
-	 * there should be some way of parsing the makrups from GntTextView */
-	char *unformat = gaim_markup_strip_html(text);
-	char *t = g_strdup_printf("%s%s%s",
-			secondary ? secondary : "",
-			secondary ? "\n" : "",
-			unformat ? unformat : "");
-
-	void *ret = gg_notify_message(GAIM_NOTIFY_FORMATTED, title, primary, t);
-
-	g_free(t);
-	g_free(unformat);
-
-	return ret;
-}
-
-static void
-reset_email_dialog()
-{
-	emaildialog.window = NULL;
-	emaildialog.tree = NULL;
-}
-
-static void
-setup_email_dialog()
-{
-	GntWidget *box, *tree, *button;
-	if (emaildialog.window)
-		return;
-
-	emaildialog.window = box = gnt_vbox_new(FALSE);
-	gnt_box_set_toplevel(GNT_BOX(box), TRUE);
-	gnt_box_set_title(GNT_BOX(box), _("Emails"));
-	gnt_box_set_fill(GNT_BOX(box), FALSE);
-	gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID);
-	gnt_box_set_pad(GNT_BOX(box), 0);
-
-	gnt_box_add_widget(GNT_BOX(box),
-			gnt_label_new_with_format(_("You have mail!"), GNT_TEXT_FLAG_BOLD));
-
-	emaildialog.tree = tree = gnt_tree_new_with_columns(3);
-	gnt_tree_set_column_titles(GNT_TREE(tree), _("Account"), _("From"), _("Subject"));
-	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
-	gnt_tree_set_col_width(GNT_TREE(tree), 0, 15);
-	gnt_tree_set_col_width(GNT_TREE(tree), 1, 25);
-	gnt_tree_set_col_width(GNT_TREE(tree), 2, 25);
-
-	gnt_box_add_widget(GNT_BOX(box), tree);
-
-	button = gnt_button_new(_("Close"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-
-	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), box);
-	g_signal_connect(G_OBJECT(box), "destroy", G_CALLBACK(reset_email_dialog), NULL);
-}
-
-static void *
-gg_notify_emails(GaimConnection *gc, size_t count, gboolean detailed,
-		const char **subjects, const char **froms, const char **tos,
-		const char **urls)
-{
-	GaimAccount *account = gaim_connection_get_account(gc);
-	GString *message = g_string_new(NULL);
-	void *ret;
-
-	if (!detailed)
-	{
-		g_string_append_printf(message,
-				ngettext("%s (%s) has %d new message.",
-					     "%s (%s) has %d new messages.",
-						 (int)count),
-				tos ? *tos : gaim_account_get_username(account),
-				gaim_account_get_protocol_name(account), (int)count);
-	}
-	else
-	{
-		char *to;
-
-		setup_email_dialog();
-
-		to = g_strdup_printf("%s (%s)", tos ? *tos : gaim_account_get_username(account),
-					gaim_account_get_protocol_name(account));
-		gnt_tree_add_row_after(GNT_TREE(emaildialog.tree), GINT_TO_POINTER(time(NULL)),
-				gnt_tree_create_row(GNT_TREE(emaildialog.tree), to,
-					froms ? *froms : "[Unknown sender]",
-					*subjects),
-				NULL, NULL);
-		g_free(to);
-		gnt_widget_show(emaildialog.window);
-		return NULL;
-	}
-
-	ret = gg_notify_message(GAIM_NOTIFY_EMAIL, _("New Mail"), _("You have mail!"), message->str);
-	g_string_free(message, TRUE);
-	return ret;
-}
-
-static void *
-gg_notify_email(GaimConnection *gc, const char *subject, const char *from,
-		const char *to, const char *url)
-{
-	return gg_notify_emails(gc, 1, subject != NULL,
-			subject ? &subject : NULL,
-			from ? &from : NULL,
-			to ? &to : NULL,
-			url ? &url : NULL);
-}
-
-static void *
-gg_notify_userinfo(GaimConnection *gc, const char *who, GaimNotifyUserInfo *user_info)
-{
-	/* Xeroxed from gtknotify.c */
-	char *primary;
-	char *info;
-	void *ui_handle;
-	
-	primary = g_strdup_printf(_("Info for %s"), who);
-	info = gaim_notify_user_info_get_text_with_newline(user_info, "<BR>");
-	ui_handle = gg_notify_formatted(_("Buddy Information"), primary, NULL, info);
-	g_free(info);
-	g_free(primary);
-	return ui_handle;
-}
-
-static void
-notify_button_activated(GntWidget *widget, GaimNotifySearchButton *b)
-{
-	GList *list = NULL;
-	GaimAccount *account = g_object_get_data(G_OBJECT(widget), "notify-account");
-	gpointer data = g_object_get_data(G_OBJECT(widget), "notify-data");
-
-	list = gnt_tree_get_selection_text_list(GNT_TREE(widget));
-
-	b->callback(gaim_account_get_connection(account), list, data);
-	g_list_foreach(list, (GFunc)g_free, NULL);
-	g_list_free(list);
-}
-
-static void
-gg_notify_sr_new_rows(GaimConnection *gc,
-		GaimNotifySearchResults *results, void *data)
-{
-	GntTree *tree = GNT_TREE(data);
-	GList *o;
-
-	/* XXX: Do I need to empty the tree here? */
-
-	for (o = results->rows; o; o = o->next)
-	{
-		gnt_tree_add_row_after(GNT_TREE(tree), o->data,
-				gnt_tree_create_row_from_list(GNT_TREE(tree), o->data),
-				NULL, NULL);
-	}
-}
-
-static void *
-gg_notify_searchresults(GaimConnection *gc, const char *title,
-		const char *primary, const char *secondary,
-		GaimNotifySearchResults *results, gpointer data)
-{
-	GntWidget *window, *tree, *box, *button;
-	GList *iter;
-
-	window = gnt_vbox_new(FALSE);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-	gnt_box_set_title(GNT_BOX(window), title);
-	gnt_box_set_fill(GNT_BOX(window), FALSE);
-	gnt_box_set_pad(GNT_BOX(window), 0);
-	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
-
-	gnt_box_add_widget(GNT_BOX(window),
-			gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD));
-	gnt_box_add_widget(GNT_BOX(window),
-			gnt_label_new_with_format(secondary, GNT_TEXT_FLAG_NORMAL));
-
-	tree = gnt_tree_new_with_columns(g_list_length(results->columns));
-	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
-	gnt_box_add_widget(GNT_BOX(window), tree);
-
-	box = gnt_hbox_new(TRUE);
-
-	for (iter = results->buttons; iter; iter = iter->next)
-	{
-		GaimNotifySearchButton *b = iter->data;
-		const char *text;
-
-		switch (b->type)
-		{
-			case GAIM_NOTIFY_BUTTON_LABELED:
-				text = b->label;
-				break;
-			case GAIM_NOTIFY_BUTTON_CONTINUE:
-				text = _("Continue");
-				break;
-			case GAIM_NOTIFY_BUTTON_ADD:
-				text = _("Add");
-				break;
-			case GAIM_NOTIFY_BUTTON_INFO:
-				text = _("Info");
-				break;
-			case GAIM_NOTIFY_BUTTON_IM:
-				text = _("IM");
-				break;
-			case GAIM_NOTIFY_BUTTON_JOIN:
-				text = _("Join");
-				break;
-			case GAIM_NOTIFY_BUTTON_INVITE:
-				text = _("Invite");
-				break;
-			default:
-				text = _("(none)");
-		}
-
-		button = gnt_button_new(text);
-		g_object_set_data(G_OBJECT(button), "notify-account", gaim_connection_get_account(gc));
-		g_object_set_data(G_OBJECT(button), "notify-data", data);
-		g_signal_connect_swapped(G_OBJECT(button), "activate",
-				G_CALLBACK(notify_button_activated), b);
-
-		gnt_box_add_widget(GNT_BOX(box), button);
-	}
-
-	gnt_box_add_widget(GNT_BOX(window), box);
-
-	gg_notify_sr_new_rows(gc, results, tree);
-
-	gnt_widget_show(window);
-	g_object_set_data(G_OBJECT(window), "notify-results", results);
-
-	return tree;
-}
-
-static GaimNotifyUiOps ops = 
-{
-	.notify_message = gg_notify_message,
-	.close_notify = gg_close_notify,       /* The rest of the notify-uiops return a GntWidget.
-                                              These widgets should be destroyed from here. */
-	.notify_formatted = gg_notify_formatted,
-	.notify_email = gg_notify_email,
-	.notify_emails = gg_notify_emails,
-	.notify_userinfo = gg_notify_userinfo,
-
-	.notify_searchresults = gg_notify_searchresults,
-	.notify_searchresults_new_rows = gg_notify_sr_new_rows,
-	.notify_uri = NULL                     /* This is of low-priority to me */
-};
-
-GaimNotifyUiOps *gg_notify_get_ui_ops()
-{
-	return &ops;
-}
-
-void gg_notify_init()
-{
-}
-
-void gg_notify_uninit()
-{
-}
-
-
--- a/console/gntnotify.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/**
- * @file gntnotify.h GNT Notify API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_NOTIFY_H
-#define _GNT_NOTIFY_H
-
-#include "notify.h"
-
-/**********************************************************************
- * @name GNT Notify API
- **********************************************************************/
-/*@{*/
-
-/**
- * Get the ui-functions.
- *
- * @return The GaimNotifyUiOps structure populated with the appropriate functions.
- */
-GaimNotifyUiOps *gg_notify_get_ui_ops(void);
-
-/**
- * Perform necessary initializations.
- */
-void gg_notify_init(void);
-
-/**
- * Perform necessary uninitializations.
- */
-void gg_notify_uninit(void);
-
-/*@}*/
-
-#endif
-
--- a/console/gntplugin.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-/**
- * @file gntplugin.c GNT Plugins API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntbutton.h>
-#include <gntlabel.h>
-#include <gntline.h>
-#include <gnttree.h>
-
-#include "notify.h"
-
-#include "gntgaim.h"
-#include "gntplugin.h"
-
-static struct
-{
-	GntWidget *tree;
-	GntWidget *window;
-	GntWidget *aboot;
-	GntWidget *conf;
-} plugins;
-
-static GHashTable *confwins;
-
-static void
-decide_conf_button(GaimPlugin *plugin)
-{
-	if (gaim_plugin_is_loaded(plugin) && 
-		((GAIM_IS_GNT_PLUGIN(plugin) &&
-			GAIM_GNT_PLUGIN_UI_INFO(plugin) != NULL) ||
-		(plugin->info->prefs_info &&
-			plugin->info->prefs_info->get_plugin_pref_frame)))
-		gnt_widget_set_visible(plugins.conf, TRUE);
-	else
-		gnt_widget_set_visible(plugins.conf, FALSE);
-
-	gnt_box_readjust(GNT_BOX(plugins.window));
-	gnt_widget_draw(plugins.window);
-}
-
-static void
-plugin_toggled_cb(GntWidget *tree, GaimPlugin *plugin, gpointer null)
-{
-	if (gnt_tree_get_choice(GNT_TREE(tree), plugin))
-	{
-		if(!gaim_plugin_load(plugin))
-			gaim_notify_error(NULL, "ERROR", "loading plugin failed", NULL);
-	}
-	else
-	{
-		GntWidget *win;
-
-		if (!gaim_plugin_unload(plugin))
-			gaim_notify_error(NULL, "ERROR", "unloading plugin failed", NULL);
-
-		if ((win = g_hash_table_lookup(confwins, plugin)) != NULL)
-		{
-			gnt_widget_destroy(win);
-		}
-	}
-	decide_conf_button(plugin);
-	gg_plugins_save_loaded();
-}
-
-/* Xerox */
-void
-gg_plugins_save_loaded(void)
-{
-	gaim_plugins_save_loaded("/gaim/gnt/plugins/loaded");
-}
-
-static void
-selection_changed(GntWidget *widget, gpointer old, gpointer current, gpointer null)
-{
-	GaimPlugin *plugin = current;
-	char *text;
-
-	/* XXX: Use formatting and stuff */
-	gnt_text_view_clear(GNT_TEXT_VIEW(plugins.aboot));
-	text = g_strdup_printf(_("Name: %s\nVersion: %s\nDescription: %s\nAuthor: %s\nWebsite: %s\nFilename: %s\n"),
-			SAFE(plugin->info->name), SAFE(plugin->info->version), SAFE(plugin->info->description),
-			SAFE(plugin->info->author), SAFE(plugin->info->homepage), SAFE(plugin->path));
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(plugins.aboot),
-			text, GNT_TEXT_FLAG_NORMAL);
-	gnt_text_view_scroll(GNT_TEXT_VIEW(plugins.aboot), 0);
-	g_free(text);
-	decide_conf_button(plugin);
-}
-
-static void
-reset_plugin_window(GntWidget *window, gpointer null)
-{
-	plugins.window = NULL;
-	plugins.tree = NULL;
-	plugins.aboot = NULL;
-}
-
-static int
-plugin_compare(GaimPlugin *p1, GaimPlugin *p2)
-{
-	char *s1 = g_utf8_strup(p1->info->name, -1);
-	char *s2 = g_utf8_strup(p2->info->name, -1);
-	int ret = g_utf8_collate(s1, s2);
-	g_free(s1);
-	g_free(s2);
-	return ret;
-}
-
-static void
-confwin_init()
-{
-	confwins = g_hash_table_new(g_direct_hash, g_direct_equal);
-}
-
-static void
-remove_confwin(GntWidget *window, gpointer plugin)
-{
-	g_hash_table_remove(confwins, plugin);
-}
-
-static void
-configure_plugin_cb(GntWidget *button, gpointer null)
-{
-	GaimPlugin *plugin;
-	GGPluginFrame callback;
-
-	g_return_if_fail(plugins.tree != NULL);
-
-	plugin = gnt_tree_get_selection_data(GNT_TREE(plugins.tree));
-	if (!gaim_plugin_is_loaded(plugin))
-	{
-		gaim_notify_error(plugin, _("Error"),
-			_("Plugin need to be loaded before you can configure it."), NULL);
-		return;
-	}
-
-	if (confwins && g_hash_table_lookup(confwins, plugin))
-		return;
-
-	if (GAIM_IS_GNT_PLUGIN(plugin) &&
-			(callback = GAIM_GNT_PLUGIN_UI_INFO(plugin)) != NULL)
-	{
-		GntWidget *window = gnt_vbox_new(FALSE);
-		GntWidget *box, *button;
-
-		gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-		gnt_box_set_title(GNT_BOX(window), plugin->info->name);
-		gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
-
-		box = callback();
-		gnt_box_add_widget(GNT_BOX(window), box);
-
-		box = gnt_hbox_new(FALSE);
-		gnt_box_add_widget(GNT_BOX(window), box);
-
-		button = gnt_button_new(_("Close"));
-		gnt_box_add_widget(GNT_BOX(box), button);
-		g_signal_connect_swapped(G_OBJECT(button), "activate",
-				G_CALLBACK(gnt_widget_destroy), window);
-		g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(remove_confwin), plugin);
-
-		gnt_widget_show(window);
-
-		if (confwins == NULL)
-			confwin_init();
-		g_hash_table_insert(confwins, plugin, window);
-	}
-	else if (plugin->info->prefs_info &&
-			plugin->info->prefs_info->get_plugin_pref_frame)
-	{
-		gaim_notify_info(plugin, _("..."),
-			_("Still need to do something about this."), NULL);
-		return;
-	}
-	else
-	{
-		gaim_notify_info(plugin, _("Error"),
-			_("No configuration options for this plugin."), NULL);
-		return;
-	}
-}
-
-void gg_plugins_show_all()
-{
-	GntWidget *window, *tree, *box, *aboot, *button;
-	GList *iter;
-	if (plugins.window)
-		return;
-
-	gaim_plugins_probe(G_MODULE_SUFFIX);
-
-	plugins.window = window = gnt_vbox_new(FALSE);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-	gnt_box_set_title(GNT_BOX(window), _("Plugins"));
-	gnt_box_set_pad(GNT_BOX(window), 0);
-	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
-
-	gnt_box_add_widget(GNT_BOX(window),
-			gnt_label_new(_("You can (un)load plugins from the following list.")));
-	gnt_box_add_widget(GNT_BOX(window), gnt_hline_new());
-
-	box = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(window), box);
-	gnt_box_add_widget(GNT_BOX(window), gnt_hline_new());
-
-	gnt_box_set_pad(GNT_BOX(box), 0);
-	plugins.tree = tree = gnt_tree_new();
-	gnt_tree_set_compare_func(GNT_TREE(tree), (GCompareFunc)plugin_compare);
-	GNT_WIDGET_SET_FLAGS(tree, GNT_WIDGET_NO_BORDER);
-	gnt_box_add_widget(GNT_BOX(box), tree);
-	gnt_box_add_widget(GNT_BOX(box), gnt_vline_new());
-
-	plugins.aboot = aboot = gnt_text_view_new();
-	gnt_widget_set_size(aboot, 40, 20);
-	gnt_box_add_widget(GNT_BOX(box), aboot);
-
-	for (iter = gaim_plugins_get_all(); iter; iter = iter->next)
-	{
-		GaimPlugin *plug = iter->data;
-
-		if (plug->info->type != GAIM_PLUGIN_STANDARD ||
-			(plug->info->flags & GAIM_PLUGIN_FLAG_INVISIBLE) ||
-			plug->error)
-			continue;
-
-		gnt_tree_add_choice(GNT_TREE(tree), plug,
-				gnt_tree_create_row(GNT_TREE(tree), plug->info->name), NULL, NULL);
-		gnt_tree_set_choice(GNT_TREE(tree), plug, gaim_plugin_is_loaded(plug));
-	}
-	gnt_tree_set_col_width(GNT_TREE(tree), 0, 30);
-	g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(plugin_toggled_cb), NULL);
-	g_signal_connect(G_OBJECT(tree), "selection_changed", G_CALLBACK(selection_changed), NULL);
-
-	box = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(window), box);
-
-	button = gnt_button_new(_("Close"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect_swapped(G_OBJECT(button), "activate",
-			G_CALLBACK(gnt_widget_destroy), window);
-
-	plugins.conf = button = gnt_button_new(_("Configure Plugin"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(configure_plugin_cb), NULL);
-
-	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(reset_plugin_window), NULL);
-
-	gnt_widget_show(window);
-
-	decide_conf_button(gnt_tree_get_selection_data(GNT_TREE(tree)));
-}
-
--- a/console/gntplugin.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/**
- * @file gntplugin.h GNT Plugins API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_PLUGIN_H
-#define _GNT_PLUGIN_H
-
-#include <gnt.h>
-
-#include <plugin.h>
-
-#include <string.h>
-
-#include "gntgaim.h"
-
-/**********************************************************************
- * @name GNT Plugins API
- **********************************************************************/
-/*@{*/
-
-typedef GntWidget* (*GGPluginFrame) ();
-
-/* Guess where these came from */
-#define GAIM_GNT_PLUGIN_TYPE GAIM_GNT_UI
-
-/**
- * Decide whether a plugin is a GNT-plugin.
- */
-#define GAIM_IS_GNT_PLUGIN(plugin) \
-	((plugin)->info != NULL && (plugin)->info->ui_info != NULL && \
-	 !strcmp((plugin)->info->ui_requirement, GAIM_GNT_PLUGIN_TYPE))
-
-/**
- * Get the ui-info from GNT-plugins.
- */
-#define GAIM_GNT_PLUGIN_UI_INFO(plugin) \
-	(GGPluginFrame)((plugin)->info->ui_info)
-
-/**
- * Show a list of plugins.
- */
-void gg_plugins_show_all(void);
-
-/**
- * Save the list of loaded plugins.
- */
-void gg_plugins_save_loaded(void);
-
-/*@}*/
-
-#endif
--- a/console/gntpounce.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,956 +0,0 @@
-/**
- * @file gntpounce.c GNT Buddy Pounce API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntbutton.h>
-#include <gntcheckbox.h>
-#include <gntcombobox.h>
-#include <gntentry.h>
-#include <gntlabel.h>
-#include <gntline.h>
-#include <gnttree.h>
-#include "internal.h"
-#include "gntgaim.h"
-
-#include "account.h"
-#include "conversation.h"
-#include "debug.h"
-#include "notify.h"
-#include "prpl.h"
-#include "request.h"
-#include "server.h"
-#include "util.h"
-
-#include "gntpounce.h"
-
-
-typedef struct
-{
-	/* Pounce data */
-	GaimPounce  *pounce;
-	GaimAccount *account;
-
-	/* The window */
-	GntWidget *window;
-
-	/* Pounce on Whom */
-	GntWidget *account_menu;
-	GntWidget *buddy_entry;
-
-	/* Pounce options */
-	GntWidget *on_away;
-
-	/* Pounce When Buddy... */
-	GntWidget *signon;
-	GntWidget *signoff;
-	GntWidget *away;
-	GntWidget *away_return;
-	GntWidget *idle;
-	GntWidget *idle_return;
-	GntWidget *typing;
-	GntWidget *typed;
-	GntWidget *stop_typing;
-	GntWidget *message_recv;
-
-	/* Action */
-	GntWidget *open_win;
-	GntWidget *popup;
-	GntWidget *popup_entry;
-	GntWidget *send_msg;
-	GntWidget *send_msg_entry;
-	GntWidget *exec_cmd;
-	GntWidget *exec_cmd_entry;
-	GntWidget *play_sound;
-
-	GntWidget *save_pounce;
-
-	/* Buttons */
-	GntWidget *save_button;
-
-} GaimGntPounceDialog;
-
-typedef struct
-{
-	GntWidget *window;
-	GntWidget *tree;
-	GntWidget *modify_button;
-	GntWidget *delete_button;
-} PouncesManager;
-
-static PouncesManager *pounces_manager = NULL;
-
-/**************************************************************************
- * Callbacks
- **************************************************************************/
-static gint
-delete_win_cb(GntWidget *w, GaimGntPounceDialog *dialog)
-{
-	gnt_widget_destroy(dialog->window);
-	g_free(dialog);
-
-	return TRUE;
-}
-
-static void
-cancel_cb(GntWidget *w, GaimGntPounceDialog *dialog)
-{
-	gnt_widget_destroy(dialog->window);
-}
-
-static void
-add_pounce_to_treeview(GntTree *tree, GaimPounce *pounce)
-{
-	GaimAccount *account;
-	const char *pouncer;
-	const char *pouncee;
-
-	account = gaim_pounce_get_pouncer(pounce);
-	pouncer = gaim_account_get_username(account);
-	pouncee = gaim_pounce_get_pouncee(pounce);
-	gnt_tree_add_row_last(tree, pounce,
-		gnt_tree_create_row(tree, pouncer, pouncee), NULL);
-}
-
-static void
-populate_pounces_list(PouncesManager *dialog)
-{
-	const GList *pounces;
-
-	gnt_tree_remove_all(GNT_TREE(dialog->tree));
-
-	for (pounces = gaim_pounces_get_all(); pounces != NULL;
-			pounces = g_list_next(pounces))
-	{
-		add_pounce_to_treeview(GNT_TREE(dialog->tree), pounces->data);
-	}
-}
-
-static void
-update_pounces(void)
-{
-	/* Rebuild the pounces list if the pounces manager is open */
-	if (pounces_manager != NULL)
-	{
-		populate_pounces_list(pounces_manager);
-	}
-}
-
-static void
-signed_on_off_cb(GaimConnection *gc, gpointer user_data)
-{
-	update_pounces();
-}
-
-static void
-save_pounce_cb(GntWidget *w, GaimGntPounceDialog *dialog)
-{
-	const char *name;
-	const char *message, *command, *reason;
-	GaimPounceEvent events   = GAIM_POUNCE_NONE;
-	GaimPounceOption options = GAIM_POUNCE_OPTION_NONE;
-
-	name = gnt_entry_get_text(GNT_ENTRY(dialog->buddy_entry));
-
-	if (*name == '\0')
-	{
-		gaim_notify_error(NULL, NULL,
-						  _("Please enter a buddy to pounce."), NULL);
-		return;
-	}
-
-	/* Options */
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->on_away)))
-		options |= GAIM_POUNCE_OPTION_AWAY;
-
-	/* Events */
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->signon)))
-		events |= GAIM_POUNCE_SIGNON;
-
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->signoff)))
-		events |= GAIM_POUNCE_SIGNOFF;
-
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->away)))
-		events |= GAIM_POUNCE_AWAY;
-
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->away_return)))
-		events |= GAIM_POUNCE_AWAY_RETURN;
-
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->idle)))
-		events |= GAIM_POUNCE_IDLE;
-
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->idle_return)))
-		events |= GAIM_POUNCE_IDLE_RETURN;
-
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->typing)))
-		events |= GAIM_POUNCE_TYPING;
-
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->typed)))
-		events |= GAIM_POUNCE_TYPED;
-
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->stop_typing)))
-		events |= GAIM_POUNCE_TYPING_STOPPED;
-
-	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->message_recv)))
-		events |= GAIM_POUNCE_MESSAGE_RECEIVED;
-
-	/* Data fields */
-	message = gnt_entry_get_text(GNT_ENTRY(dialog->send_msg_entry));
-	command = gnt_entry_get_text(GNT_ENTRY(dialog->exec_cmd_entry));
-	reason  = gnt_entry_get_text(GNT_ENTRY(dialog->popup_entry));
-
-	if (*reason == '\0') reason = NULL;
-	if (*message == '\0') message = NULL;
-	if (*command == '\0') command = NULL;
-
-	if (dialog->pounce == NULL) {
-		dialog->pounce = gaim_pounce_new(GAIM_GNT_UI, dialog->account,
-										 name, events, options);
-	} else {
-		gaim_pounce_set_events(dialog->pounce, events);
-		gaim_pounce_set_options(dialog->pounce, options);
-		gaim_pounce_set_pouncer(dialog->pounce, dialog->account);
-		gaim_pounce_set_pouncee(dialog->pounce, name);
-	}
-
-	/* Actions */
-	gaim_pounce_action_set_enabled(dialog->pounce, "open-window",
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->open_win)));
-	gaim_pounce_action_set_enabled(dialog->pounce, "popup-notify",
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->popup)));
-	gaim_pounce_action_set_enabled(dialog->pounce, "send-message",
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->send_msg)));
-	gaim_pounce_action_set_enabled(dialog->pounce, "execute-command",
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->exec_cmd)));
-	gaim_pounce_action_set_enabled(dialog->pounce, "play-beep",
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->play_sound)));
-
-	gaim_pounce_action_set_attribute(dialog->pounce, "send-message",
-									 "message", message);
-	gaim_pounce_action_set_attribute(dialog->pounce, "execute-command",
-									 "command", command);
-	gaim_pounce_action_set_attribute(dialog->pounce, "popup-notify",
-									 "reason", reason);
-
-	/* Set the defaults for next time. */
-	gaim_prefs_set_bool("/gaim/gnt/pounces/default_actions/open-window",
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->open_win)));
-	gaim_prefs_set_bool("/gaim/gnt/pounces/default_actions/popup-notify",
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->popup)));
-	gaim_prefs_set_bool("/gaim/gnt/pounces/default_actions/send-message",
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->send_msg)));
-	gaim_prefs_set_bool("/gaim/gnt/pounces/default_actions/execute-command",
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->exec_cmd)));
-	gaim_prefs_set_bool("/gaim/gnt/pounces/default_actions/play-beep",
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->play_sound)));
-
-	gaim_pounce_set_save(dialog->pounce,
-		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->save_pounce)));
-
-	gaim_pounce_set_pouncer(dialog->pounce,
-		(GaimAccount *)gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->account_menu)));
-
-	update_pounces();
-
-	gnt_widget_destroy(dialog->window);
-}
-
-
-void
-gg_pounce_editor_show(GaimAccount *account, const char *name,
-							GaimPounce *cur_pounce)
-{
-	GaimGntPounceDialog *dialog;
-	GntWidget *window;
-	GntWidget *bbox;
-	GntWidget *hbox;
-	GntWidget *button;
-	GntWidget *combo;
-	GList *list;
-
-	g_return_if_fail((cur_pounce != NULL) ||
-	                 (account != NULL) ||
-	                 (gaim_accounts_get_all() != NULL));
-
-	dialog = g_new0(GaimGntPounceDialog, 1);
-
-	if (cur_pounce != NULL) {
-		dialog->pounce  = cur_pounce;
-		dialog->account = gaim_pounce_get_pouncer(cur_pounce);
-	} else if (account != NULL) {
-		dialog->pounce  = NULL;
-		dialog->account = account;
-	} else {
-		GList *connections = gaim_connections_get_all();
-		GaimConnection *gc;
-
-		if (connections != NULL) {
-			gc = (GaimConnection *)connections->data;
-			dialog->account = gaim_connection_get_account(gc);
-		} else
-			dialog->account = gaim_accounts_get_all()->data;
-
-		dialog->pounce  = NULL;
-	}
-
-	/* Create the window. */
-	dialog->window = window = gnt_vbox_new(FALSE);
-	gnt_box_set_pad(GNT_BOX(window), 0);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_LEFT);
-	gnt_box_set_title(GNT_BOX(window),
-						 (cur_pounce == NULL
-						  ? _("New Buddy Pounce") : _("Edit Buddy Pounce")));
-
-	g_signal_connect(G_OBJECT(window), "destroy",
-					 G_CALLBACK(delete_win_cb), dialog);
-
-	gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(_("Pounce Who"), GNT_TEXT_FLAG_BOLD));
-
-	/* Account: */
-	gnt_box_add_widget(GNT_BOX(window), gnt_label_new(_("Account:")));
-	dialog->account_menu = combo = gnt_combo_box_new();
-	list = gaim_accounts_get_all();
-	for (; list; list = list->next)
-	{
-		GaimAccount *account;
-		char *text;
-
-		account = list->data;
-		text = g_strdup_printf("%s (%s)",
-				gaim_account_get_username(account),
-				gaim_account_get_protocol_name(account));
-		gnt_combo_box_add_data(GNT_COMBO_BOX(combo), account, text);
-		g_free(text);
-	}
-	if (dialog->account)
-		gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), dialog->account);
-
-	gnt_box_add_widget(GNT_BOX(window), combo);
-
-	/* Buddy: */
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Buddy name:")));
-
-	dialog->buddy_entry = gnt_entry_new(NULL);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->buddy_entry);
-
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-
-	if (cur_pounce != NULL) {
-		gnt_entry_set_text(GNT_ENTRY(dialog->buddy_entry),
-						   gaim_pounce_get_pouncee(cur_pounce));
-	} else if (name != NULL) {
-		gnt_entry_set_text(GNT_ENTRY(dialog->buddy_entry), name);
-	}
-
-	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
-	gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(_("Pounce When Buddy..."), GNT_TEXT_FLAG_BOLD));
-
-	dialog->signon = gnt_check_box_new(_("Signs on"));
-	dialog->signoff = gnt_check_box_new(_("Signs off"));
-	dialog->away = gnt_check_box_new(_("Goes away"));
-	dialog->away_return = gnt_check_box_new(_("Returns from away"));
-	dialog->idle = gnt_check_box_new(_("Becomes idle"));
-	dialog->idle_return = gnt_check_box_new(_("Is no longer idle"));
-	dialog->typing = gnt_check_box_new(_("Starts typing"));
-	dialog->typed = gnt_check_box_new(_("Pauses while typing"));
-	dialog->stop_typing = gnt_check_box_new(_("Stops typing"));
-	dialog->message_recv = gnt_check_box_new(_("Sends a message"));
-
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_set_pad(GNT_BOX(hbox), 2);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->signon);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->signoff);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_set_pad(GNT_BOX(hbox), 2);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->away);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->away_return);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_set_pad(GNT_BOX(hbox), 2);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->idle);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->idle_return);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_set_pad(GNT_BOX(hbox), 2);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->typing);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->typed);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_set_pad(GNT_BOX(hbox), 2);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->stop_typing);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->message_recv);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-
-	/* Create the "Action" frame. */
-	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
-	gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(_("Action"), GNT_TEXT_FLAG_BOLD));
-
-	dialog->open_win = gnt_check_box_new(_("Open an IM window"));
-	dialog->popup = gnt_check_box_new(_("Pop up a notification"));
-	dialog->send_msg = gnt_check_box_new(_("Send a message"));
-	dialog->exec_cmd = gnt_check_box_new(_("Execute a command"));
-	dialog->play_sound = gnt_check_box_new(_("Play a sound"));
-
-	dialog->send_msg_entry    = gnt_entry_new(NULL);
-	dialog->exec_cmd_entry    = gnt_entry_new(NULL);
-	dialog->popup_entry       = gnt_entry_new(NULL);
-	dialog->exec_cmd_entry   = gnt_entry_new(NULL);
-
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->open_win);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->popup);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->popup_entry);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->send_msg);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->send_msg_entry);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->exec_cmd);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->exec_cmd_entry);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-	hbox = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(hbox), dialog->play_sound);
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-
-	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
-	gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(_("Options"), GNT_TEXT_FLAG_BOLD));
-	dialog->on_away = gnt_check_box_new(_("Pounce only when my status is not available"));
-	gnt_box_add_widget(GNT_BOX(window), dialog->on_away);
-	dialog->save_pounce = gnt_check_box_new(_("Recurring"));
-	gnt_box_add_widget(GNT_BOX(window), dialog->save_pounce);
-
-
-	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
-	/* Now the button box! */
-	bbox = gnt_hbox_new(TRUE);
-
-	/* Cancel button */
-	button = gnt_button_new(_("Cancel"));
-	gnt_box_add_widget(GNT_BOX(bbox), button);
-	g_signal_connect(G_OBJECT(button), "activate",
-					 G_CALLBACK(cancel_cb), dialog);
-
-	/* Save button */
-	dialog->save_button = button = gnt_button_new(_("Save"));
-	gnt_box_add_widget(GNT_BOX(bbox), button);
-	g_signal_connect(G_OBJECT(button), "activate",
-					 G_CALLBACK(save_pounce_cb), dialog);
-
-	gnt_box_add_widget(GNT_BOX(window), bbox);
-
-
-	/* Set the values of stuff. */
-	if (cur_pounce != NULL)
-	{
-		GaimPounceEvent events   = gaim_pounce_get_events(cur_pounce);
-		GaimPounceOption options = gaim_pounce_get_options(cur_pounce);
-		const char *value;
-
-		/* Options */
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->on_away),
-									(options & GAIM_POUNCE_OPTION_AWAY));
-
-		/* Events */
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->signon),
-									(events & GAIM_POUNCE_SIGNON));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->signoff),
-									(events & GAIM_POUNCE_SIGNOFF));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->away),
-									(events & GAIM_POUNCE_AWAY));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->away_return),
-									(events & GAIM_POUNCE_AWAY_RETURN));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->idle),
-									(events & GAIM_POUNCE_IDLE));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->idle_return),
-									(events & GAIM_POUNCE_IDLE_RETURN));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->typing),
-									(events & GAIM_POUNCE_TYPING));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->typed),
-									(events & GAIM_POUNCE_TYPED));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->stop_typing),
-									(events & GAIM_POUNCE_TYPING_STOPPED));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->message_recv),
-									(events & GAIM_POUNCE_MESSAGE_RECEIVED));
-
-		/* Actions */
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->open_win),
-			gaim_pounce_action_is_enabled(cur_pounce, "open-window"));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->popup),
-			gaim_pounce_action_is_enabled(cur_pounce, "popup-notify"));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->send_msg),
-			gaim_pounce_action_is_enabled(cur_pounce, "send-message"));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->exec_cmd),
-			gaim_pounce_action_is_enabled(cur_pounce, "execute-command"));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->play_sound),
-			gaim_pounce_action_is_enabled(cur_pounce, "play-beep"));
-
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->save_pounce),
-			gaim_pounce_get_save(cur_pounce));
-
-		if ((value = gaim_pounce_action_get_attribute(cur_pounce,
-		                                              "send-message",
-		                                              "message")) != NULL)
-		{
-			gnt_entry_set_text(GNT_ENTRY(dialog->send_msg_entry), value);
-		}
-
-		if ((value = gaim_pounce_action_get_attribute(cur_pounce,
-		                                              "popup-notify",
-		                                              "reason")) != NULL)
-		{
-			gnt_entry_set_text(GNT_ENTRY(dialog->popup_entry), value);
-		}
-
-		if ((value = gaim_pounce_action_get_attribute(cur_pounce,
-		                                              "execute-command",
-		                                              "command")) != NULL)
-		{
-			gnt_entry_set_text(GNT_ENTRY(dialog->exec_cmd_entry), value);
-		}
-	}
-	else
-	{
-		GaimBuddy *buddy = NULL;
-
-		if (name != NULL)
-			buddy = gaim_find_buddy(account, name);
-
-		/* Set some defaults */
-		if (buddy == NULL) {
-			gnt_check_box_set_checked(
-				GNT_CHECK_BOX(dialog->signon), TRUE);
-		} else {
-			if (!GAIM_BUDDY_IS_ONLINE(buddy)) {
-				gnt_check_box_set_checked(
-					GNT_CHECK_BOX(dialog->signon), TRUE);
-			} else {
-				gboolean default_set = FALSE;
-				GaimPresence *presence = gaim_buddy_get_presence(buddy);
-
-				if (gaim_presence_is_idle(presence))
-				{
-					gnt_check_box_set_checked(
-						GNT_CHECK_BOX(dialog->idle_return), TRUE);
-
-					default_set = TRUE;
-				}
-
-				if (!gaim_presence_is_available(presence))
-				{
-					gnt_check_box_set_checked(
-						GNT_CHECK_BOX(dialog->away_return), TRUE);
-
-					default_set = TRUE;
-				}
-
-				if (!default_set)
-				{
-					gnt_check_box_set_checked(
-						GNT_CHECK_BOX(dialog->signon), TRUE);
-				}
-			}
-		}
-
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->open_win),
-			gaim_prefs_get_bool("/gaim/gnt/pounces/default_actions/open-window"));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->popup),
-			gaim_prefs_get_bool("/gaim/gnt/pounces/default_actions/popup-notify"));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->send_msg),
-			gaim_prefs_get_bool("/gaim/gnt/pounces/default_actions/send-message"));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->exec_cmd),
-			gaim_prefs_get_bool("/gaim/gnt/pounces/default_actions/execute-command"));
-		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->play_sound),
-			gaim_prefs_get_bool("/gaim/gnt/pounces/default_actions/play-beep"));
-	}
-
-	gnt_widget_show(window);
-}
-
-
-
-static gboolean
-pounces_manager_destroy_cb(GntWidget *widget, gpointer user_data)
-{
-	PouncesManager *dialog = user_data;
-
-	dialog->window = NULL;
-	gg_pounces_manager_hide();
-
-	return FALSE;
-}
-
-
-static void
-pounces_manager_add_cb(GntButton *button, gpointer user_data)
-{
-	gg_pounce_editor_show(NULL, NULL, NULL);
-}
-
-
-static void
-pounces_manager_modify_cb(GntButton *button, gpointer user_data)
-{
-	PouncesManager *dialog = user_data;
-	GaimPounce *pounce = gnt_tree_get_selection_data(GNT_TREE(dialog->tree));
-	gg_pounce_editor_show(NULL, NULL, pounce);
-}
-
-static void
-pounces_manager_delete_confirm_cb(GaimPounce *pounce)
-{
-	gnt_tree_remove(GNT_TREE(pounces_manager->tree), pounce);
-
-	gaim_request_close_with_handle(pounce);
-	gaim_pounce_destroy(pounce);
-}
-
-
-static void
-pounces_manager_delete_cb(GntButton *button, gpointer user_data)
-{
-	PouncesManager *dialog = user_data;
-	GaimPounce *pounce;
-	GaimAccount *account;
-	const char *pouncer, *pouncee;
-	char *buf;
-
-	pounce = (GaimPounce *)gnt_tree_get_selection_data(GNT_TREE(dialog->tree));
-	account = gaim_pounce_get_pouncer(pounce);
-	pouncer = gaim_account_get_username(account);
-	pouncee = gaim_pounce_get_pouncee(pounce);
-	buf = g_strdup_printf(_("Are you sure you want to delete the pounce on %s for %s?"), pouncee, pouncer);
-	gaim_request_action(pounce, NULL, buf, NULL, 0, pounce, 2,
-						_("Delete"), pounces_manager_delete_confirm_cb,
-						_("Cancel"), NULL);
-	g_free(buf);
-}
-
-static void
-pounces_manager_close_cb(GntButton *button, gpointer user_data)
-{
-	gg_pounces_manager_hide();
-}
-
-
-void
-gg_pounces_manager_show(void)
-{
-	PouncesManager *dialog;
-	GntWidget *bbox;
-	GntWidget *button;
-	GntWidget *tree;
-	GntWidget *win;
-
-	if (pounces_manager != NULL) {
-		return;
-	}
-
-	pounces_manager = dialog = g_new0(PouncesManager, 1);
-
-	dialog->window = win = gnt_vbox_new(FALSE);
-	gnt_box_set_toplevel(GNT_BOX(win), TRUE);
-	gnt_box_set_title(GNT_BOX(win), _("Buddy Pounces"));
-	gnt_box_set_pad(GNT_BOX(win), 0);
-
-	g_signal_connect(G_OBJECT(win), "destroy",
-					 G_CALLBACK(pounces_manager_destroy_cb), dialog);
-
-	/* List of saved buddy pounces */
-	dialog->tree = tree = GNT_WIDGET(gnt_tree_new_with_columns(2));
-	gnt_tree_set_column_titles(GNT_TREE(tree), "Account", "Pouncee", NULL);
-	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
-
-	gnt_box_add_widget(GNT_BOX(win), tree);
-
-	/* Button box. */
-	bbox = gnt_hbox_new(TRUE);
-
-	/* Add button */
-	button = gnt_button_new(_("Add"));
-	gnt_box_add_widget(GNT_BOX(bbox), button);
-
-	g_signal_connect(G_OBJECT(button), "activate",
-					 G_CALLBACK(pounces_manager_add_cb), dialog);
-
-	/* Modify button */
-	button = gnt_button_new(_("Modify"));
-	dialog->modify_button = button;
-	gnt_box_add_widget(GNT_BOX(bbox), button);
-
-	g_signal_connect(G_OBJECT(button), "activate",
-					 G_CALLBACK(pounces_manager_modify_cb), dialog);
-
-	/* Delete button */
-	button = gnt_button_new(_("Delete"));
-	dialog->delete_button = button;
-	gnt_box_add_widget(GNT_BOX(bbox), button);
-
-	g_signal_connect(G_OBJECT(button), "activate",
-					 G_CALLBACK(pounces_manager_delete_cb), dialog);
-
-	/* Close button */
-	button = gnt_button_new(_("Close"));
-	gnt_box_add_widget(GNT_BOX(bbox), button);
-	gnt_widget_show(button);
-
-	g_signal_connect(G_OBJECT(button), "activate",
-					 G_CALLBACK(pounces_manager_close_cb), dialog);
-
-	gnt_box_add_widget(GNT_BOX(win), bbox);
-
-	gnt_widget_show(win);
-	populate_pounces_list(pounces_manager);
-}
-
-void
-gg_pounces_manager_hide(void)
-{
-	if (pounces_manager == NULL)
-		return;
-
-	if (pounces_manager->window != NULL)
-		gnt_widget_destroy(pounces_manager->window);
-
-	gaim_signals_disconnect_by_handle(pounces_manager);
-
-	g_free(pounces_manager);
-	pounces_manager = NULL;
-}
-
-static void
-pounce_cb(GaimPounce *pounce, GaimPounceEvent events, void *data)
-{
-	GaimConversation *conv;
-	GaimAccount *account;
-	GaimBuddy *buddy;
-	const char *pouncee;
-	const char *alias;
-
-	pouncee = gaim_pounce_get_pouncee(pounce);
-	account = gaim_pounce_get_pouncer(pounce);
-
-	buddy = gaim_find_buddy(account, pouncee);
-	if (buddy != NULL)
-	{
-		alias = gaim_buddy_get_alias(buddy);
-		if (alias == NULL)
-			alias = pouncee;
-	}
-	else
-		alias = pouncee;
-
-	if (gaim_pounce_action_is_enabled(pounce, "open-window"))
-	{
-		conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, pouncee, account);
-
-		if (conv == NULL)
-			conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, pouncee);
-	}
-
-	if (gaim_pounce_action_is_enabled(pounce, "popup-notify"))
-	{
-		char *tmp;
-		const char *name_shown;
-		const char *reason;
-		reason = gaim_pounce_action_get_attribute(pounce, "popup-notify",
-														  "reason");
-
-		/*
-		 * Here we place the protocol name in the pounce dialog to lessen
-		 * confusion about what protocol a pounce is for.
-		 */
-		tmp = g_strdup_printf(
-				   (events & GAIM_POUNCE_TYPING) ?
-				   _("%s has started typing to you (%s)") :
-				   (events & GAIM_POUNCE_TYPED) ?
-				   _("%s has paused while typing to you (%s)") :
-				   (events & GAIM_POUNCE_SIGNON) ?
-				   _("%s has signed on (%s)") :
-				   (events & GAIM_POUNCE_IDLE_RETURN) ?
-				   _("%s has returned from being idle (%s)") :
-				   (events & GAIM_POUNCE_AWAY_RETURN) ?
-				   _("%s has returned from being away (%s)") :
-				   (events & GAIM_POUNCE_TYPING_STOPPED) ?
-				   _("%s has stopped typing to you (%s)") :
-				   (events & GAIM_POUNCE_SIGNOFF) ?
-				   _("%s has signed off (%s)") :
-				   (events & GAIM_POUNCE_IDLE) ?
-				   _("%s has become idle (%s)") :
-				   (events & GAIM_POUNCE_AWAY) ?
-				   _("%s has gone away. (%s)") :
-				   (events & GAIM_POUNCE_MESSAGE_RECEIVED) ?
-				   _("%s has sent you a message. (%s)") :
-				   _("Unknown pounce event. Please report this!"),
-				   alias, gaim_account_get_protocol_name(account));
-
-		/*
-		 * Ok here is where I change the second argument, title, from
-		 * NULL to the account alias if we have it or the account
-		 * name if that's all we have
-		 */
-		if ((name_shown = gaim_account_get_alias(account)) == NULL)
-			name_shown = gaim_account_get_username(account);
-
-		if (reason == NULL)
-		{
-			gaim_notify_info(NULL, name_shown, tmp, gaim_date_format_full(NULL));
-		}
-		else
-		{
-			char *tmp2 = g_strdup_printf("%s\n\n%s", reason, gaim_date_format_full(NULL));
-			gaim_notify_info(NULL, name_shown, tmp, tmp2);
-			g_free(tmp2);
-		}
-		g_free(tmp);
-	}
-
-	if (gaim_pounce_action_is_enabled(pounce, "send-message"))
-	{
-		const char *message;
-
-		message = gaim_pounce_action_get_attribute(pounce, "send-message",
-												   "message");
-
-		if (message != NULL)
-		{
-			conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, pouncee, account);
-
-			if (conv == NULL)
-				conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, pouncee);
-
-			gaim_conversation_write(conv, NULL, message,
-									GAIM_MESSAGE_SEND, time(NULL));
-
-			serv_send_im(account->gc, (char *)pouncee, (char *)message, 0);
-		}
-	}
-
-	if (gaim_pounce_action_is_enabled(pounce, "execute-command"))
-	{
-		const char *command;
-
-		command = gaim_pounce_action_get_attribute(pounce,
-				"execute-command", "command");
-
-		if (command != NULL)
-		{
-			char *localecmd = g_locale_from_utf8(command, -1, NULL,
-					NULL, NULL);
-
-			if (localecmd != NULL)
-			{
-				int pid = fork();
-
-				if (pid == 0) {
-					char *args[4];
-
-					args[0] = "sh";
-					args[1] = "-c";
-					args[2] = (char *)localecmd;
-					args[3] = NULL;
-
-					execvp(args[0], args);
-
-					_exit(0);
-				}
-				g_free(localecmd);
-			}
-		}
-	}
-
-	if (gaim_pounce_action_is_enabled(pounce, "play-beep"))
-	{
-		beep();
-	}
-}
-
-static void
-free_pounce(GaimPounce *pounce)
-{
-	update_pounces();
-}
-
-static void
-new_pounce(GaimPounce *pounce)
-{
-	gaim_pounce_action_register(pounce, "open-window");
-	gaim_pounce_action_register(pounce, "popup-notify");
-	gaim_pounce_action_register(pounce, "send-message");
-	gaim_pounce_action_register(pounce, "execute-command");
-	gaim_pounce_action_register(pounce, "play-beep");
-
-	update_pounces();
-}
-
-void *
-gg_pounces_get_handle()
-{
-	static int handle;
-
-	return &handle;
-}
-
-void
-gg_pounces_init(void)
-{
-	gaim_pounces_register_handler(GAIM_GNT_UI, pounce_cb, new_pounce,
-								  free_pounce);
-
-	gaim_prefs_add_none("/gaim/gnt/pounces");
-	gaim_prefs_add_none("/gaim/gnt/pounces/default_actions");
-	gaim_prefs_add_bool("/gaim/gnt/pounces/default_actions/open-window",
-						FALSE);
-	gaim_prefs_add_bool("/gaim/gnt/pounces/default_actions/popup-notify",
-						TRUE);
-	gaim_prefs_add_bool("/gaim/gnt/pounces/default_actions/send-message",
-						FALSE);
-	gaim_prefs_add_bool("/gaim/gnt/pounces/default_actions/execute-command",
-						FALSE);
-	gaim_prefs_add_bool("/gaim/gnt/pounces/default_actions/play-beep",
-						FALSE);
-	gaim_prefs_add_none("/gaim/gnt/pounces/dialog");
-
-	gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
-						gg_pounces_get_handle(),
-						GAIM_CALLBACK(signed_on_off_cb), NULL);
-	gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
-						gg_pounces_get_handle(),
-						GAIM_CALLBACK(signed_on_off_cb), NULL);
-}
-
-/* XXX: There's no such thing in pidgin. Perhaps there should be? */
-void gg_pounces_uninit()
-{
-	gaim_pounces_register_handler(GAIM_GNT_UI, NULL, NULL, NULL);
-
-	gaim_signals_disconnect_by_handle(gg_pounces_get_handle());
-}
-
--- a/console/gntpounce.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/**
- * @file gntpounce.h GNT Buddy Pounce API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GAIM_GNTPOUNCE_H_
-#define _GAIM_GNTPOUNCE_H_
-
-#include "pounce.h"
-
-/**
- * Displays a New Buddy Pounce or Edit Buddy Pounce dialog.
- *
- * @param account    The optional account to use.
- * @param name       The optional name to pounce on.
- * @param cur_pounce The current buddy pounce, if editing an existing one.
- */
-void gg_pounce_editor_show(GaimAccount *account, const char *name,
-								GaimPounce *cur_pounce);
-
-/**
- * Shows the pounces manager window.
- */
-void gg_pounces_manager_show(void);
-
-/**
- * Hides the pounces manager window.
- */
-void gg_pounces_manager_hide(void);
-
-/**
- * Returns the gtkpounces handle
- *
- * @return The handle to the GTK+ pounces system
- */
-void *gg_pounces_get_handle(void);
-
-/**
- * Initializes the GNT pounces subsystem.
- */
-void gg_pounces_init(void);
-
-/**
- * Uninitializes the GNT pounces subsystem.
- */
-void gg_pounces_uninit(void);
-
-#endif /* _GAIM_GTKPOUNCE_H_ */
--- a/console/gntprefs.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,286 +0,0 @@
-/**
- * @file gntprefs.c GNT Preferences API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <prefs.h>
-#include <savedstatuses.h>
-
-#include "gntgaim.h"
-#include "gntprefs.h"
-#include "gntrequest.h"
-
-#include <string.h>
-
-static GList *freestrings;  /* strings to be freed when the pref-window is closed */
-
-void gg_prefs_init()
-{
-	gaim_prefs_add_none("/gaim");
-	gaim_prefs_add_none("/gaim/gnt");
-
-	gaim_prefs_add_none("/gaim/gnt/plugins");
-	gaim_prefs_add_path_list("/gaim/gnt/plugins/loaded", NULL);
-
-	gaim_prefs_add_none("/gaim/gnt/conversations");
-	gaim_prefs_add_bool("/gaim/gnt/conversations/timestamps", TRUE);
-	gaim_prefs_add_bool("/gaim/gnt/conversations/notify_typing", FALSE); /* XXX: Not functional yet */
-}
-
-typedef struct
-{
-	GaimPrefType type;
-	const char *pref;
-	const char *label;
-	GList *(*lv)();   /* If the value is to be selected from a number of choices */
-} Prefs;
-
-static GList *
-get_log_options()
-{
-	return gaim_log_logger_get_options();
-}
-
-static GList *
-get_idle_options()
-{
-	GList *list = NULL;
-	list = g_list_append(list, "Based on keyboard use"); /* XXX: string freeze */
-	list = g_list_append(list, "system");
-	list = g_list_append(list, (char*)_("From last sent message"));
-	list = g_list_append(list, "gaim");
-	list = g_list_append(list, (char*)_("Never"));
-	list = g_list_append(list, "never");
-	return list;
-}
-
-static GList *
-get_status_titles()
-{
-	GList *list = NULL;
-	const GList *iter;
-	for (iter = gaim_savedstatuses_get_all(); iter; iter = iter->next) {
-		char *str;
-		if (gaim_savedstatus_is_transient(iter->data))
-			continue;
-		str = g_strdup_printf("%ld", gaim_savedstatus_get_creation_time(iter->data));
-		list = g_list_append(list, (char*)gaim_savedstatus_get_title(iter->data));
-		list = g_list_append(list, str);
-		freestrings = g_list_prepend(freestrings, str);
-	}
-	return list;
-}
-
-static GaimRequestField *
-get_pref_field(Prefs *prefs)
-{
-	GaimRequestField *field = NULL;
-
-	if (prefs->lv == NULL)
-	{
-		switch (prefs->type)
-		{
-			case GAIM_PREF_BOOLEAN:
-				field = gaim_request_field_bool_new(prefs->pref, _(prefs->label),
-						gaim_prefs_get_bool(prefs->pref));
-				break;
-			case GAIM_PREF_INT:
-				field = gaim_request_field_int_new(prefs->pref, _(prefs->label),
-						gaim_prefs_get_int(prefs->pref));
-				break;
-			case GAIM_PREF_STRING:
-				field = gaim_request_field_string_new(prefs->pref, _(prefs->label),
-						gaim_prefs_get_string(prefs->pref), FALSE);
-				break;
-			default:
-				break;
-		}
-	}
-	else
-	{
-		GList *list = prefs->lv(), *iter;
-		if (list)
-			field = gaim_request_field_list_new(prefs->pref, _(prefs->label));
-		for (iter = list; iter; iter = iter->next)
-		{
-			gboolean select = FALSE;
-			const char *data = iter->data;
-			int idata;
-			iter = iter->next;
-			switch (prefs->type)
-			{
-				case GAIM_PREF_BOOLEAN:
-					sscanf(iter->data, "%d", &idata);
-					if (gaim_prefs_get_bool(prefs->pref) == idata)
-						select = TRUE;
-					break;
-				case GAIM_PREF_INT:
-					sscanf(iter->data, "%d", &idata);
-					if (gaim_prefs_get_int(prefs->pref) == idata)
-						select = TRUE;
-					break;
-				case GAIM_PREF_STRING:
-					if (strcmp(gaim_prefs_get_string(prefs->pref), iter->data) == 0)
-						select = TRUE;
-					break;
-				default:
-					break;
-			}
-			gaim_request_field_list_add(field, data, iter->data);
-			if (select)
-				gaim_request_field_list_add_selected(field, data);
-		}
-		g_list_free(list);
-	}
-	return field;
-}
-
-static Prefs blist[] = 
-{
-	{GAIM_PREF_BOOLEAN, "/gaim/gnt/blist/idletime", N_("Show Idle Time"), NULL},
-	{GAIM_PREF_BOOLEAN, "/gaim/gnt/blist/showoffline", N_("Show Offline Buddies"), NULL},
-	{GAIM_PREF_NONE, NULL, NULL, NULL}
-};
-
-static Prefs convs[] = 
-{
-	{GAIM_PREF_BOOLEAN, "/gaim/gnt/conversations/timestamps", N_("Show Timestamps"), NULL},
-	{GAIM_PREF_BOOLEAN, "/gaim/gnt/conversations/notify_typing", N_("Notify buddies when you are typing"), NULL},
-	{GAIM_PREF_NONE, NULL, NULL, NULL}
-};
-
-static Prefs logging[] = 
-{
-	{GAIM_PREF_STRING, "/core/logging/format", N_("Log format"), get_log_options},
-	{GAIM_PREF_BOOLEAN, "/core/logging/log_ims", N_("Log IMs"), NULL},
-	{GAIM_PREF_BOOLEAN, "/core/logging/log_chats", N_("Log chats"), NULL},
-	{GAIM_PREF_BOOLEAN, "/core/logging/log_system", N_("Log status change events"), NULL},
-	{GAIM_PREF_NONE, NULL, NULL, NULL},
-};
-
-/* XXX: Translate after the freeze */
-static Prefs idle[] =
-{
-	{GAIM_PREF_STRING, "/core/away/idle_reporting", "Report Idle time", get_idle_options},
-	{GAIM_PREF_BOOLEAN, "/core/away/away_when_idle", "Change status when idle", NULL},
-	{GAIM_PREF_INT, "/core/away/mins_before_away", "Minutes before changing status", NULL},
-	{GAIM_PREF_INT, "/core/savedstatus/idleaway", "Change status to", get_status_titles},
-	{GAIM_PREF_NONE, NULL, NULL, NULL},
-};
-
-static void
-free_strings()
-{
-	g_list_foreach(freestrings, (GFunc)g_free, NULL);
-	g_list_free(freestrings);
-	freestrings = NULL;
-}
-
-static void
-save_cb(void *data, GaimRequestFields *allfields)
-{
-	GList *list;
-	for (list = gaim_request_fields_get_groups(allfields); list; list = list->next)
-	{
-		GaimRequestFieldGroup *group = list->data;
-		GList *fields = gaim_request_field_group_get_fields(group);
-		
-		for (; fields ; fields = fields->next)
-		{
-			GaimRequestField *field = fields->data;
-			GaimRequestFieldType type = gaim_request_field_get_type(field);
-			GaimPrefType pt;
-			gpointer val = NULL;
-			const char *id = gaim_request_field_get_id(field);
-
-			switch (type)
-			{
-				case GAIM_REQUEST_FIELD_LIST:
-					val = gaim_request_field_list_get_selected(field)->data;
-					break;
-				case GAIM_REQUEST_FIELD_BOOLEAN:
-					val = GINT_TO_POINTER(gaim_request_field_bool_get_value(field));
-					break;
-				case GAIM_REQUEST_FIELD_INTEGER:
-					val = GINT_TO_POINTER(gaim_request_field_int_get_value(field));
-					break;
-				case GAIM_REQUEST_FIELD_STRING:
-					val = (gpointer)gaim_request_field_string_get_value(field);
-					break;
-				default:
-					break;
-			}
-
-			pt = gaim_prefs_get_type(id);
-			switch (pt)
-			{
-				case GAIM_PREF_INT:
-					if (type == GAIM_REQUEST_FIELD_LIST) /* Lists always return string */
-						sscanf(val, "%ld", (long int *)&val);
-					gaim_prefs_set_int(id, GPOINTER_TO_INT(val));
-					break;
-				case GAIM_PREF_BOOLEAN:
-					gaim_prefs_set_bool(id, GPOINTER_TO_INT(val));
-					break;
-				case GAIM_PREF_STRING:
-					gaim_prefs_set_string(id, val);
-					break;
-				default:
-					break;
-			}
-		}
-	}
-	free_strings();
-}
-
-static void
-add_pref_group(GaimRequestFields *fields, const char *title, Prefs *prefs)
-{
-	GaimRequestField *field;
-	GaimRequestFieldGroup *group;
-	int i;
-
-	group = gaim_request_field_group_new(title);
-	gaim_request_fields_add_group(fields, group);
-	for (i = 0; prefs[i].pref; i++)
-	{
-		field = get_pref_field(prefs + i);
-		if (field)
-			gaim_request_field_group_add_field(group, field);
-	}
-}
-
-void gg_prefs_show_all()
-{
-	GaimRequestFields *fields;
-
-	fields = gaim_request_fields_new();
-
-	add_pref_group(fields, _("Buddy List"), blist);
-	add_pref_group(fields, _("Conversations"), convs);
-	add_pref_group(fields, _("Logging"), logging);
-	add_pref_group(fields, _("Idle"), idle);
-
-	gaim_request_fields(NULL, _("Preferences"), NULL, NULL, fields,
-			_("Save"), G_CALLBACK(save_cb), _("Cancel"), free_strings, NULL);
-}
-
--- a/console/gntprefs.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/**
- * @file gntprefs.h GNT Preferences API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_PREFS_H
-#define _GNT_PREFS_H
-
-/**********************************************************************
- * @name GNT Preferences API
- **********************************************************************/
-/*@{*/
-
-/**
- * Perform necessary initializations.
- */
-void gg_prefs_init(void);
-
-/**
- * Show the preferences dialog.
- */
-void gg_prefs_show_all(void);
-
-/*@}*/
-
-#endif
--- a/console/gntrequest.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,619 +0,0 @@
-/**
- * @file gntrequest.c GNT Request API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntbutton.h>
-#include <gntcheckbox.h>
-#include <gntcombobox.h>
-#include <gntentry.h>
-#include <gntlabel.h>
-#include <gntline.h>
-#include <gnttree.h>
-
-#include "gntgaim.h"
-#include "gntrequest.h"
-#include "util.c"
-
-typedef struct
-{
-	void *user_data;
-	GntWidget *entry, *dialog;
-	GCallback *cbs;
-} GaimGntFileRequest;
-
-static GntWidget *
-setup_request_window(const char *title, const char *primary,
-		const char *secondary, GaimRequestType type)
-{
-	GntWidget *window;
-
-	window = gnt_vbox_new(FALSE);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-	gnt_box_set_title(GNT_BOX(window), title);
-	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
-
-	if (primary)
-		gnt_box_add_widget(GNT_BOX(window),
-				gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD));
-	if (secondary)
-		gnt_box_add_widget(GNT_BOX(window), gnt_label_new(secondary));
-
-	g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gaim_request_close),
-			GINT_TO_POINTER(type));
-
-	return window;
-}
-
-static GntWidget *
-setup_button_box(gpointer userdata, gpointer cb, gpointer data, ...)
-{
-	GntWidget *box, *button;
-	va_list list;
-	const char *text;
-	gpointer callback;
-
-	box = gnt_hbox_new(FALSE);
-
-	va_start(list, data);
-
-	while ((text = va_arg(list, const char *)))
-	{
-		callback = va_arg(list, gpointer);
-		button = gnt_button_new(text);
-		gnt_box_add_widget(GNT_BOX(box), button);
-		g_object_set_data(G_OBJECT(button), "activate-callback", callback);
-		g_object_set_data(G_OBJECT(button), "activate-userdata", userdata);
-		g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data);
-	}
-
-	va_end(list);
-	return box;
-}
-
-static void
-notify_input_cb(GntWidget *button, GntWidget *entry)
-{
-	GaimRequestInputCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
-	gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
-	const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
-
-	if (callback)
-		callback(data, text);
-
-	while (button->parent)
-		button = button->parent;
-
-	gaim_request_close(GAIM_REQUEST_INPUT, button);
-}
-
-static void *
-gg_request_input(const char *title, const char *primary,
-		const char *secondary, const char *default_value,
-		gboolean multiline, gboolean masked, gchar *hint,
-		const char *ok_text, GCallback ok_cb,
-		const char *cancel_text, GCallback cancel_cb,
-		void *user_data)
-{
-	GntWidget *window, *box, *entry;
-
-	window = setup_request_window(title, primary, secondary, GAIM_REQUEST_INPUT);
-
-	entry = gnt_entry_new(default_value);
-	if (masked)
-		gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
-	gnt_box_add_widget(GNT_BOX(window), entry);
-
-	box = setup_button_box(user_data, notify_input_cb, entry,
-			ok_text, ok_cb, cancel_text, cancel_cb, NULL);
-	gnt_box_add_widget(GNT_BOX(window), box);
-
-	gnt_widget_show(window);
-
-	return window;
-}
-
-static void
-gg_close_request(GaimRequestType type, gpointer ui_handle)
-{
-	GntWidget *widget = GNT_WIDGET(ui_handle);
-	while (widget->parent)
-		widget = widget->parent;
-	gnt_widget_destroy(widget);
-}
-
-static void
-request_choice_cb(GntWidget *button, GntComboBox *combo)
-{
-	GaimRequestChoiceCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
-	gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
-	int choice = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))) - 1;
-
-	if (callback)
-		callback(data, choice);
-
-	while (button->parent)
-		button = button->parent;
-
-	gaim_request_close(GAIM_REQUEST_INPUT, button);
-}
-
-static void *
-gg_request_choice(const char *title, const char *primary,
-		const char *secondary, unsigned int default_value,
-		const char *ok_text, GCallback ok_cb,
-		const char *cancel_text, GCallback cancel_cb,
-		void *user_data, va_list choices)
-{
-	GntWidget *window, *combo, *box;
-	const char *text;
-	int val;
-
-	window = setup_request_window(title, primary, secondary, GAIM_REQUEST_CHOICE);
-
-	combo = gnt_combo_box_new();
-	gnt_box_add_widget(GNT_BOX(window), combo);
-	while ((text = va_arg(choices, const char *)))
-	{
-		val = va_arg(choices, int);
-		gnt_combo_box_add_data(GNT_COMBO_BOX(combo), GINT_TO_POINTER(val + 1), text);
-	}
-	gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), GINT_TO_POINTER(default_value + 1));
-
-	box = setup_button_box(user_data, request_choice_cb, combo,
-			ok_text, ok_cb, cancel_text, cancel_cb, NULL);
-	gnt_box_add_widget(GNT_BOX(window), box);
-
-	gnt_widget_show(window);
-	
-	return window;
-}
-
-static void
-request_action_cb(GntWidget *button, GntWidget *window)
-{
-	GaimRequestActionCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
-	gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
-	int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "activate-id"));
-
-	if (callback)
-		callback(data, id);
-
-	gaim_request_close(GAIM_REQUEST_ACTION, window);
-}
-
-static void*
-gg_request_action(const char *title, const char *primary,
-		const char *secondary, unsigned int default_value,
-		void *user_data, size_t actioncount,
-		va_list actions)
-{
-	GntWidget *window, *box, *button;
-	int i;
-
-	window = setup_request_window(title, primary, secondary, GAIM_REQUEST_ACTION);
-
-	box = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(window), box);
-	for (i = 0; i < actioncount; i++)
-	{
-		const char *text = va_arg(actions, const char *);
-		GaimRequestActionCb callback = va_arg(actions, GaimRequestActionCb);
-
-		button = gnt_button_new(text);
-		gnt_box_add_widget(GNT_BOX(box), button);
-
-		g_object_set_data(G_OBJECT(button), "activate-callback", callback);
-		g_object_set_data(G_OBJECT(button), "activate-userdata", user_data);
-		g_object_set_data(G_OBJECT(button), "activate-id", GINT_TO_POINTER(i));
-		g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(request_action_cb), window);
-	}
-
-	gnt_widget_show(window);
-
-	return window;
-}
-
-static void
-request_fields_cb(GntWidget *button, GaimRequestFields *fields)
-{
-	GaimRequestFieldsCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
-	gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
-	GList *list;
-
-	/* Update the data of the fields. GtkGaim does this differently. Instead of
-	 * updating the fields at the end like here, it updates the appropriate field
-	 * instantly whenever a change is made. That allows it to make sure the
-	 * 'required' fields are entered before the user can hit OK. It's not the case
-	 * here, althought it can be done. I am not honouring the 'required' fields
-	 * for the moment. */
-	for (list = gaim_request_fields_get_groups(fields); list; list = list->next)
-	{
-		GaimRequestFieldGroup *group = list->data;
-		GList *fields = gaim_request_field_group_get_fields(group);
-		
-		for (; fields ; fields = fields->next)
-		{
-			GaimRequestField *field = fields->data;
-			GaimRequestFieldType type = gaim_request_field_get_type(field);
-			if (type == GAIM_REQUEST_FIELD_BOOLEAN)
-			{
-				GntWidget *check = field->ui_data;
-				gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check));
-				gaim_request_field_bool_set_value(field, value);
-			}
-			else if (type == GAIM_REQUEST_FIELD_STRING)
-			{
-				GntWidget *entry = field->ui_data;
-				const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
-				gaim_request_field_string_set_value(field, (text && *text) ? text : NULL);
-			}
-			else if (type == GAIM_REQUEST_FIELD_INTEGER)
-			{
-				GntWidget *entry = field->ui_data;
-				const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
-				int value = (text && *text) ? atoi(text) : 0;
-				gaim_request_field_int_set_value(field, value);
-			}
-			else if (type == GAIM_REQUEST_FIELD_CHOICE)
-			{
-				GntWidget *combo = field->ui_data;
-				int id;
-				id = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)));
-				gaim_request_field_choice_set_value(field, id);
-			}
-			else if (type == GAIM_REQUEST_FIELD_LIST)
-			{
-				GList *list = NULL;
-				if (gaim_request_field_list_get_multi_select(field))
-				{
-					const GList *iter;
-					GntWidget *tree = field->ui_data;
-
-					iter = gaim_request_field_list_get_items(field);
-					for (; iter; iter = iter->next)
-					{
-						const char *text = iter->data;
-						gpointer key = gaim_request_field_list_get_data(field, text);
-						if (gnt_tree_get_choice(GNT_TREE(tree), key))
-							list = g_list_prepend(list, key);
-					}
-				}
-				else
-				{
-					GntWidget *combo = field->ui_data;
-					gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
-					list = g_list_append(list, data);
-				}
-
-				gaim_request_field_list_set_selected(field, list);
-				g_list_free(list);
-			}
-			else if (type == GAIM_REQUEST_FIELD_ACCOUNT)
-			{
-				GntWidget *combo = field->ui_data;
-				GaimAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
-				gaim_request_field_account_set_value(field, acc);
-			}
-		}
-	}
-
-	if (callback)
-		callback(data, fields);
-
-	while (button->parent)
-		button = button->parent;
-
-	gaim_request_close(GAIM_REQUEST_FIELDS, button);
-}
-
-static void *
-gg_request_fields(const char *title, const char *primary,
-		const char *secondary, GaimRequestFields *allfields,
-		const char *ok, GCallback ok_cb,
-		const char *cancel, GCallback cancel_cb,
-		void *userdata)
-{
-	GntWidget *window, *box;
-	GList *grlist;
-
-	window = setup_request_window(title, primary, secondary, GAIM_REQUEST_FIELDS);
-
-	/* This is how it's going to work: the request-groups are going to be
-	 * stacked vertically one after the other. A GntLine will be separating
-	 * the groups. */
-	box = gnt_vbox_new(FALSE);
-	gnt_box_set_pad(GNT_BOX(box), 0);
-	gnt_box_set_fill(GNT_BOX(box), TRUE);
-	for (grlist = gaim_request_fields_get_groups(allfields); grlist; grlist = grlist->next)
-	{
-		GaimRequestFieldGroup *group = grlist->data;
-		GList *fields = gaim_request_field_group_get_fields(group);
-		GntWidget *hbox;
-		const char *title = gaim_request_field_group_get_title(group);
-
-		if (title)
-			gnt_box_add_widget(GNT_BOX(box),
-					gnt_label_new_with_format(title, GNT_TEXT_FLAG_BOLD));
-
-		for (; fields ; fields = fields->next)
-		{
-			/* XXX: Break each of the fields into a separate function? */
-			GaimRequestField *field = fields->data;
-			GaimRequestFieldType type = gaim_request_field_get_type(field);
-			const char *label = gaim_request_field_get_label(field);
-				
-			hbox = gnt_hbox_new(TRUE);   /* hrm */
-			gnt_box_add_widget(GNT_BOX(box), hbox);
-			
-			if (type != GAIM_REQUEST_FIELD_BOOLEAN && label)
-			{
-				GntWidget *l = gnt_label_new(label);
-				gnt_widget_set_size(l, 0, 1);
-				gnt_box_add_widget(GNT_BOX(hbox), l);
-			}
-
-			if (type == GAIM_REQUEST_FIELD_BOOLEAN)
-			{
-				GntWidget *check = gnt_check_box_new(label);
-				gnt_check_box_set_checked(GNT_CHECK_BOX(check),
-						gaim_request_field_bool_get_default_value(field));
-				gnt_box_add_widget(GNT_BOX(hbox), check);
-				field->ui_data = check;
-			}
-			else if (type == GAIM_REQUEST_FIELD_STRING)
-			{
-				GntWidget *entry = gnt_entry_new(
-							gaim_request_field_string_get_default_value(field));
-				gnt_entry_set_masked(GNT_ENTRY(entry),
-						gaim_request_field_string_is_masked(field));
-				gnt_box_add_widget(GNT_BOX(hbox), entry);
-				field->ui_data = entry;
-			}
-			else if (type == GAIM_REQUEST_FIELD_INTEGER)
-			{
-				char str[256];
-				int val = gaim_request_field_int_get_default_value(field);
-				GntWidget *entry;
-				
-				snprintf(str, sizeof(str), "%d", val);
-				entry = gnt_entry_new(str);
-				gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
-				gnt_box_add_widget(GNT_BOX(hbox), entry);
-				field->ui_data = entry;
-			}
-			else if (type == GAIM_REQUEST_FIELD_CHOICE)
-			{
-				int id;
-				const GList *list;
-				GntWidget *combo = gnt_combo_box_new();
-				gnt_box_add_widget(GNT_BOX(hbox), combo);
-				field->ui_data = combo;
-
-				list = gaim_request_field_choice_get_labels(field);
-				for (id = 1; list; list = list->next, id++)
-				{
-					gnt_combo_box_add_data(GNT_COMBO_BOX(combo),
-							GINT_TO_POINTER(id), list->data);
-				}
-				gnt_combo_box_set_selected(GNT_COMBO_BOX(combo),
-						GINT_TO_POINTER(gaim_request_field_choice_get_default_value(field)));
-			}
-			else if (type == GAIM_REQUEST_FIELD_LIST)
-			{
-				const GList *list;
-				gboolean multi = gaim_request_field_list_get_multi_select(field);
-				if (multi)
-				{
-					GntWidget *tree = gnt_tree_new();
-					gnt_box_add_widget(GNT_BOX(hbox), tree);
-					field->ui_data = tree;
-
-					list = gaim_request_field_list_get_items(field);
-					for (; list; list = list->next)
-					{
-						const char *text = list->data;
-						gpointer key = gaim_request_field_list_get_data(field, text);
-						gnt_tree_add_choice(GNT_TREE(tree), key,
-								gnt_tree_create_row(GNT_TREE(tree), text), NULL, NULL);
-						if (gaim_request_field_list_is_selected(field, text))
-							gnt_tree_set_choice(GNT_TREE(tree), key, TRUE);
-					}
-				}
-				else
-				{
-					GntWidget *combo = gnt_combo_box_new();
-					gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
-					gnt_box_add_widget(GNT_BOX(hbox), combo);
-					field->ui_data = combo;
-
-					list = gaim_request_field_list_get_items(field);
-					for (; list; list = list->next)
-					{
-						const char *text = list->data;
-						gpointer key = gaim_request_field_list_get_data(field, text);
-						gnt_combo_box_add_data(GNT_COMBO_BOX(combo), key, text);
-						if (gaim_request_field_list_is_selected(field, text))
-							gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), key);
-					}
-				}
-			}
-			else if (type == GAIM_REQUEST_FIELD_ACCOUNT)
-			{
-				gboolean all;
-				GaimAccount *def;
-				GList *list;
-				GntWidget *combo = gnt_combo_box_new();
-				gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
-				gnt_box_add_widget(GNT_BOX(hbox), combo);
-				field->ui_data = combo;
-
-				all = gaim_request_field_account_get_show_all(field);
-				def = gaim_request_field_account_get_default_value(field);
-
-				if (all)
-					list = gaim_accounts_get_all();
-				else
-					list = gaim_connections_get_all();
-
-				for (; list; list = list->next)
-				{
-					GaimAccount *account;
-					char *text;
-
-					if (all)
-						account = list->data;
-					else
-						account = gaim_connection_get_account(list->data);
-
-					text = g_strdup_printf("%s (%s)",
-							gaim_account_get_username(account),
-							gaim_account_get_protocol_name(account));
-					gnt_combo_box_add_data(GNT_COMBO_BOX(combo), account, text);
-					g_free(text);
-					if (account == def)
-						gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), account);
-				}
-				gnt_widget_set_size(combo, 20, 3); /* ew */
-			}
-			else
-			{
-				gnt_box_add_widget(GNT_BOX(hbox),
-						gnt_label_new_with_format(_("Not implemented yet."),
-							GNT_TEXT_FLAG_BOLD));
-			}
-		}
-		if (grlist->next)
-			gnt_box_add_widget(GNT_BOX(box), gnt_hline_new());
-	}
-	gnt_box_add_widget(GNT_BOX(window), box);
-
-	box = setup_button_box(userdata, request_fields_cb, allfields,
-			ok, ok_cb, cancel, cancel_cb, NULL);
-	gnt_box_add_widget(GNT_BOX(window), box);
-
-	gnt_widget_show(window);
-	
-	return window;
-}
-
-static void
-file_cancel_cb(GntWidget *wid, gpointer fq)
-{
-	GaimGntFileRequest *data = fq;
-	if (data->cbs[1] != NULL)
-		((GaimRequestFileCb)data->cbs[1])(data->user_data, NULL);
-
-	gaim_request_close(GAIM_REQUEST_FILE, data->dialog);
-}
-
-static void
-file_ok_cb(GntWidget *wid, gpointer fq)
-{
-	GaimGntFileRequest *data = fq;
-	if (data->cbs[0] != NULL)
-		((GaimRequestFileCb)data->cbs[0])(data->user_data, gnt_entry_get_text(GNT_ENTRY(data->entry)));
-
-	gaim_request_close(GAIM_REQUEST_FILE, data->dialog);
-}
-
-static void
-file_request_destroy(GaimGntFileRequest *data)
-{
-	g_free(data->cbs);
-	g_free(data);
-}
-
-static void *
-gg_request_file(const char *title, const char *filename,
-				gboolean savedialog,
-				GCallback ok_cb, GCallback cancel_cb,
-				void *user_data)
-{
-	GntWidget *window = gnt_vbox_new(FALSE);
-	GntWidget *entry, *hbox, *button;
-	GaimGntFileRequest *data = g_new0(GaimGntFileRequest, 1);
-
-	data->user_data = user_data;
-	data->cbs = g_new0(GCallback, 2);
-	data->cbs[0] = ok_cb;
-	data->cbs[1] = cancel_cb;
-	data->dialog = window;
-	data->entry = entry = gnt_entry_new(g_strconcat(gaim_home_dir(), G_DIR_SEPARATOR_S, filename, NULL));
-	gnt_widget_set_size(entry, 30, 1);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-	gnt_box_set_title(GNT_BOX(window), title ? title : (savedialog ? _("Save File...") : _("Open File...")));
-#if 0
-	/* After the string freeze */
-	gnt_box_add_widget(GNT_BOX(window), gnt_label_new(_("Please enter a full path for a file")));
-#endif
-	gnt_box_add_widget(GNT_BOX(window), entry);
-
-	hbox = gnt_hbox_new(TRUE);
-	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
-
-	button = gnt_button_new(_("Cancel"));
-	g_signal_connect(G_OBJECT(button), "activate",
-		G_CALLBACK(file_cancel_cb), data);
-	gnt_box_add_widget(GNT_BOX(hbox), button);
-
-	button = gnt_button_new(_("OK"));
-	g_signal_connect(G_OBJECT(button), "activate",
-		G_CALLBACK(file_ok_cb), data);
-	gnt_box_add_widget(GNT_BOX(hbox), button);
-
-	gnt_box_add_widget(GNT_BOX(window), hbox);
-
-	g_signal_connect_swapped(G_OBJECT(window), "destroy",
-			G_CALLBACK(file_request_destroy), data);
-
-	gnt_widget_show(window);
-
-	return window;
-}
-
-static GaimRequestUiOps uiops =
-{
-	.request_input = gg_request_input,
-	.close_request = gg_close_request,
-	.request_choice = gg_request_choice,
-	.request_action = gg_request_action,
-	.request_fields = gg_request_fields,
-	.request_file = gg_request_file,
-	.request_folder = NULL                        /* No plans for this */
-};
-
-GaimRequestUiOps *gg_request_get_ui_ops()
-{
-	return &uiops;
-}
-
-void gg_request_init()
-{
-}
-
-void gg_request_uninit()
-{
-}
-
--- a/console/gntrequest.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/**
- * @file gntrequest.h GNT Request API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_REQUEST_H
-#define _GNT_REQUEST_H
-
-#include "request.h"
-
-/**********************************************************************
- * @name GNT Request API
- **********************************************************************/
-/*@{*/
-
-/**
- * Get the ui-functions.
- *
- * @return The GaimRequestUiOps structure populated with the appropriate functions.
- */
-GaimRequestUiOps *gg_request_get_ui_ops(void);
-
-/**
- * Perform necessary initializations.
- */
-void gg_request_init(void);
-
-/**
- * Perform necessary uninitializations.
- */
-void gg_request_uninit(void);
-
-/*@}*/
-
-#endif
--- a/console/gntstatus.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,606 +0,0 @@
-/**
- * @file gntstatus.c GNT Status API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntbutton.h>
-#include <gntcombobox.h>
-#include <gntentry.h>
-#include <gntlabel.h>
-#include <gntline.h>
-#include <gnttree.h>
-
-#include <notify.h>
-#include <request.h>
-
-#include "gntgaim.h"
-#include "gntstatus.h"
-
-static struct
-{
-	GntWidget *window;
-	GntWidget *tree;
-} statuses;
-
-typedef struct
-{
-	GaimSavedStatus *saved;
-	GntWidget *window;
-	GntWidget *title;
-	GntWidget *type;
-	GntWidget *message;
-	GntWidget *tree;
-	GHashTable *hash;  /* list of windows for substatuses */
-} EditStatus;
-
-typedef struct
-{
-	GaimAccount *account;
-	const GaimStatusType *type;
-	char *message;
-} RowInfo;
-
-typedef struct
-{
-	GntWidget *window;
-	GntWidget *type;
-	GntWidget *message;
-
-	EditStatus *parent;
-	RowInfo *key;
-} EditSubStatus;
-
-static GList *edits;  /* List of opened edit-status dialogs */
-
-static void
-reset_status_window(GntWidget *widget, gpointer null)
-{
-	statuses.window = NULL;
-	statuses.tree = NULL;
-}
-
-static void
-populate_statuses(GntTree *tree)
-{
-	const GList *list;
-
-	for (list = gaim_savedstatuses_get_all(); list; list = list->next)
-	{
-		GaimSavedStatus *saved = list->data;
-		const char *title, *type, *message;
-
-		if (gaim_savedstatus_is_transient(saved))
-			continue;
-
-		title = gaim_savedstatus_get_title(saved);
-		type = gaim_primitive_get_name_from_type(gaim_savedstatus_get_type(saved));
-		message = gaim_savedstatus_get_message(saved);  /* XXX: Strip possible markups */
-
-		gnt_tree_add_row_last(tree, saved,
-				gnt_tree_create_row(tree, title, type, message), NULL);
-	}
-}
-
-static void
-really_delete_status(GaimSavedStatus *saved)
-{
-	GList *iter;
-
-	for (iter = edits; iter; iter = iter->next)
-	{
-		EditStatus *edit = iter->data;
-		if (edit->saved == saved)
-		{
-			gnt_widget_destroy(edit->window);
-			break;
-		}
-	}
-
-	if (statuses.tree)
-		gnt_tree_remove(GNT_TREE(statuses.tree), saved);
-
-	gaim_savedstatus_delete(gaim_savedstatus_get_title(saved));
-}
-
-static void
-ask_before_delete(GntWidget *button, gpointer null)
-{
-	char *ask;
-	GaimSavedStatus *saved;
-
-	g_return_if_fail(statuses.tree != NULL);
-
-	saved = gnt_tree_get_selection_data(GNT_TREE(statuses.tree));
-	ask = g_strdup_printf(_("Are you sure you want to delete \"%s\""),
-			gaim_savedstatus_get_title(saved));
-
-	gaim_request_action(saved, _("Delete Status"), ask, NULL, 0, saved, 2,
-			_("Delete"), really_delete_status, _("Cancel"), NULL);
-	g_free(ask);
-}
-
-static void
-use_savedstatus_cb(GntWidget *widget, gpointer null)
-{
-	g_return_if_fail(statuses.tree != NULL);
-
-	gaim_savedstatus_activate(gnt_tree_get_selection_data(GNT_TREE(statuses.tree)));
-}
-
-static void
-edit_savedstatus_cb(GntWidget *widget, gpointer null)
-{
-	g_return_if_fail(statuses.tree != NULL);
-
-	gg_savedstatus_edit(gnt_tree_get_selection_data(GNT_TREE(statuses.tree)));
-}
-
-void gg_savedstatus_show_all()
-{
-	GntWidget *window, *tree, *box, *button;
-	if (statuses.window)
-		return;
-
-	statuses.window = window = gnt_vbox_new(FALSE);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-	gnt_box_set_title(GNT_BOX(window), _("Saved Statuses"));
-	gnt_box_set_fill(GNT_BOX(window), FALSE);
-	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
-	gnt_box_set_pad(GNT_BOX(window), 0);
-
-	/* XXX: Add some sorting function to sort alphabetically, perhaps */
-	statuses.tree = tree = gnt_tree_new_with_columns(3);
-	gnt_tree_set_column_titles(GNT_TREE(tree), _("Title"), _("Type"), _("Message"));
-	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
-	gnt_tree_set_col_width(GNT_TREE(tree), 0, 25);
-	gnt_tree_set_col_width(GNT_TREE(tree), 1, 12);
-	gnt_tree_set_col_width(GNT_TREE(tree), 2, 35);
-	gnt_box_add_widget(GNT_BOX(window), tree);
-
-	populate_statuses(GNT_TREE(tree));
-
-	box = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(window), box);
-
-	button = gnt_button_new(_("Use"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate",
-			G_CALLBACK(use_savedstatus_cb), NULL);
-
-	button = gnt_button_new(_("Add"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect_swapped(G_OBJECT(button), "activate",
-			G_CALLBACK(gg_savedstatus_edit), NULL);
-
-	button = gnt_button_new(_("Edit"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate",
-			G_CALLBACK(edit_savedstatus_cb), NULL);
-
-	button = gnt_button_new(_("Delete"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate",
-			G_CALLBACK(ask_before_delete), NULL);
-
-	button = gnt_button_new(_("Close"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect_swapped(G_OBJECT(button), "activate",
-			G_CALLBACK(gnt_widget_destroy), window);
-
-	g_signal_connect(G_OBJECT(window), "destroy",
-			G_CALLBACK(reset_status_window), NULL);
-	gnt_widget_show(window);
-}
-
-static void
-destroy_substatus_win(GaimAccount *account, EditSubStatus *sub, gpointer null)
-{
-	gnt_widget_destroy(sub->window);   /* the "destroy" callback will remove entry from the hashtable */
-}
-
-static void
-free_key(gpointer key, gpointer n)
-{
-	RowInfo *row = key;
-	g_free(row->message);
-	g_free(key);
-}
-
-
-static void
-update_edit_list(GntWidget *widget, EditStatus *edit)
-{
-	edits = g_list_remove(edits, edit);
-	gaim_notify_close_with_handle(edit);
-	g_hash_table_foreach(edit->hash, (GHFunc)destroy_substatus_win, NULL);
-	g_list_foreach((GList*)gnt_tree_get_rows(GNT_TREE(edit->tree)), free_key, NULL);
-	g_free(edit);
-}
-
-static void
-set_substatuses(EditStatus *edit)
-{
-	const GList *iter;
-	for (iter = gnt_tree_get_rows(GNT_TREE(edit->tree)); iter; iter = iter->next) {
-		RowInfo *key = iter->data;
-		if (gnt_tree_get_choice(GNT_TREE(edit->tree), key)) {
-			gaim_savedstatus_set_substatus(edit->saved, key->account, key->type, key->message);
-		}
-	}
-}
-
-
-static void
-use_trans_status_cb(GntWidget *button, EditStatus *edit)
-{
-	const char *message;
-	GaimStatusPrimitive prim;
-	GaimSavedStatus *saved;
-
-	message = gnt_entry_get_text(GNT_ENTRY(edit->message));
-	prim = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(edit->type)));
-
-	saved = gaim_savedstatus_find_transient_by_type_and_message(prim, message);
-	if (saved == NULL) {
-		saved = gaim_savedstatus_new(NULL, prim);
-		edit->saved = saved;
-		set_substatuses(edit);
-	}
-	gaim_savedstatus_set_message(saved, message);
-	gaim_savedstatus_activate(saved);
-	gnt_widget_destroy(edit->window);
-}
-
-static void
-save_savedstatus_cb(GntWidget *button, EditStatus *edit)
-{
-	const char *title, *message;
-	GaimStatusPrimitive prim;
-	GaimSavedStatus *find;
-
-	title = gnt_entry_get_text(GNT_ENTRY(edit->title));
-	message = gnt_entry_get_text(GNT_ENTRY(edit->message));
-	if (!message || !*message)
-		message = NULL;
-
-	prim = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(edit->type)));
-
-	if (!title || !*title)
-	{
-		gaim_notify_error(edit, _("Error"), _("Invalid title"),
-				_("Please enter a non-empty title for the status."));
-		return;
-	}
-
-	find = gaim_savedstatus_find(title);
-	if (find && find != edit->saved)
-	{
-		gaim_notify_error(edit, _("Error"), _("Duplicate title"),
-				_("Please enter a different title for the status."));
-		return;
-	}
-	
-	if (edit->saved == NULL)
-	{
-		edit->saved = gaim_savedstatus_new(title, prim);
-		gaim_savedstatus_set_message(edit->saved, message);
-		set_substatuses(edit);
-		if (statuses.tree)
-			gnt_tree_add_row_last(GNT_TREE(statuses.tree), edit->saved,
-					gnt_tree_create_row(GNT_TREE(statuses.tree), title,
-						gaim_primitive_get_name_from_type(prim), message), NULL);
-	}
-	else
-	{
-		gaim_savedstatus_set_title(edit->saved, title);
-		gaim_savedstatus_set_type(edit->saved, prim);
-		gaim_savedstatus_set_message(edit->saved, message);
-		if (statuses.tree)
-		{
-			gnt_tree_change_text(GNT_TREE(statuses.tree), edit->saved, 0, title);
-			gnt_tree_change_text(GNT_TREE(statuses.tree), edit->saved, 1,
-						gaim_primitive_get_name_from_type(prim));
-			gnt_tree_change_text(GNT_TREE(statuses.tree), edit->saved, 2, message);
-		}
-	}
-
-	if (g_object_get_data(G_OBJECT(button), "use"))
-		gaim_savedstatus_activate(edit->saved);
-
-	gnt_widget_destroy(edit->window);
-}
-
-static void
-add_substatus(EditStatus *edit, GaimAccount *account)
-{
-	char *name;
-	const char *type = NULL, *message = NULL;
-	GaimSavedStatusSub *sub = NULL;
-	RowInfo *key;
-
-	if (!edit || !edit->tree)
-		return;
-
-	if (edit->saved)
-		sub = gaim_savedstatus_get_substatus(edit->saved, account);
-
-	key = g_new0(RowInfo, 1);
-	key->account = account;
-
-	if (sub)
-	{
-		key->type = gaim_savedstatus_substatus_get_type(sub);
-		type = gaim_status_type_get_name(key->type);
-		message = gaim_savedstatus_substatus_get_message(sub);
-		key->message = g_strdup(message);
-	}
-
-	name = g_strdup_printf("%s (%s)", gaim_account_get_username(account),
-			gaim_account_get_protocol_name(account));
-	gnt_tree_add_choice(GNT_TREE(edit->tree), key,
-			gnt_tree_create_row(GNT_TREE(edit->tree),
-				name, type ? type : "", message ? message : ""), NULL, NULL);
-
-	if (sub)
-		gnt_tree_set_choice(GNT_TREE(edit->tree), key, TRUE);
-	g_free(name);
-}
-
-static void
-substatus_window_destroy_cb(GntWidget *window, EditSubStatus *sub)
-{
-	g_hash_table_remove(sub->parent->hash, sub->key->account);
-	g_free(sub);
-}
-
-static void
-save_substatus_cb(GntWidget *widget, EditSubStatus *sub)
-{
-	GaimSavedStatus *saved = sub->parent->saved;
-	RowInfo *row = sub->key;
-	const char *message;
-	GaimStatusType *type;
-
-	type = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(sub->type));
-	message = gnt_entry_get_text(GNT_ENTRY(sub->message));
-
-	row->type = type;
-	row->message = g_strdup(message);
-
-	if (saved)    /* Save the substatus if the savedstatus actually exists. */
-		gaim_savedstatus_set_substatus(saved, row->account, type, message);
-
-	gnt_tree_set_choice(GNT_TREE(sub->parent->tree), row, TRUE);
-	gnt_tree_change_text(GNT_TREE(sub->parent->tree), row, 1,
-			gaim_status_type_get_name(type));
-	gnt_tree_change_text(GNT_TREE(sub->parent->tree), row, 2, message);
-	
-	gnt_widget_destroy(sub->window);
-}
-
-static gboolean
-popup_substatus(GntTree *tree, const char *key, EditStatus *edit)
-{
-	if (key[0] == ' ' && key[1] == 0)
-	{
-		EditSubStatus *sub;
-		GntWidget *window, *combo, *entry, *box, *button, *l;
-		GaimSavedStatusSub *substatus = NULL;
-		const GList *iter;
-		char *name;
-		RowInfo *selected = gnt_tree_get_selection_data(tree);
-		GaimAccount *account = selected->account;
-
-		if (gnt_tree_get_choice(tree, selected))
-		{
-			/* There was a savedstatus for this account. Now remove it. */
-			g_free(selected->message);
-			selected->type = NULL;
-			selected->message = NULL;
-			/* XXX: should we really be saving it right now? */
-			gaim_savedstatus_unset_substatus(edit->saved, account);
-			gnt_tree_change_text(tree, account, 1, NULL);
-			gnt_tree_change_text(tree, account, 2, NULL);
-			return FALSE;
-		}
-
-		if (g_hash_table_lookup(edit->hash, account))
-			return TRUE;
-
-		if (edit->saved)
-			substatus = gaim_savedstatus_get_substatus(edit->saved, account);
-
-		sub = g_new0(EditSubStatus, 1);
-		sub->parent = edit;
-		sub->key = selected;
-
-		sub->window = window = gnt_vbox_new(FALSE);
-		gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-		gnt_box_set_title(GNT_BOX(window), _("Substatus"));  /* XXX: a better title */
-
-		box = gnt_hbox_new(FALSE);
-		gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Account:")));
-		name = g_strdup_printf("%s (%s)", gaim_account_get_username(account),
-				gaim_account_get_protocol_name(account));
-		gnt_box_add_widget(GNT_BOX(box), gnt_label_new(name));
-		g_free(name);
-		gnt_box_add_widget(GNT_BOX(window), box);
-
-		box = gnt_hbox_new(FALSE);
-		gnt_box_add_widget(GNT_BOX(box), (l = gnt_label_new(_("Status:"))));
-		gnt_widget_set_size(l, 0, 1);   /* I don't like having to do this */
-		sub->type = combo = gnt_combo_box_new();
-		gnt_box_add_widget(GNT_BOX(box), combo);
-		gnt_box_add_widget(GNT_BOX(window), box);
-
-		for (iter = gaim_account_get_status_types(account); iter; iter = iter->next)
-		{
-			GaimStatusType *type = iter->data;
-			if (!gaim_status_type_is_user_settable(type))
-				continue;
-			gnt_combo_box_add_data(GNT_COMBO_BOX(combo), type, gaim_status_type_get_name(type));
-		}
-
-		box = gnt_hbox_new(FALSE);
-		gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Message:")));
-		sub->message = entry = gnt_entry_new(substatus ? gaim_savedstatus_substatus_get_message(substatus) : NULL);
-		gnt_box_add_widget(GNT_BOX(box), entry);
-		gnt_box_add_widget(GNT_BOX(window), box);
-
-		box  = gnt_hbox_new(FALSE);
-		button = gnt_button_new(_("Cancel"));
-		g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window);
-		gnt_box_add_widget(GNT_BOX(box), button);
-		button = gnt_button_new(_("Save"));
-		g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_substatus_cb), sub);
-		gnt_box_add_widget(GNT_BOX(box), button);
-		gnt_box_add_widget(GNT_BOX(window), box);
-
-		gnt_widget_show(window);
-
-		g_hash_table_insert(edit->hash, account, sub);
-
-		g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(substatus_window_destroy_cb), sub);
-
-		return TRUE;
-	}
-	return FALSE;
-}
-
-void gg_savedstatus_edit(GaimSavedStatus *saved)
-{
-	EditStatus *edit;
-	GntWidget *window, *box, *button, *entry, *combo, *label, *tree;
-	GaimStatusPrimitive prims[] = {GAIM_STATUS_AVAILABLE, GAIM_STATUS_AWAY,
-		GAIM_STATUS_INVISIBLE, GAIM_STATUS_OFFLINE, GAIM_STATUS_UNSET}, current;
-	GList *iter;
-	int i;
-
-	if (saved)
-	{
-		GList *iter;
-		for (iter = edits; iter; iter = iter->next)
-		{
-			edit = iter->data;
-			if (edit->saved == saved)
-				return;
-		}
-	}
-
-	edit = g_new0(EditStatus, 1);
-	edit->saved = saved;
-	edit->window = window = gnt_vbox_new(FALSE);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-	gnt_box_set_title(GNT_BOX(window), _("Edit Status"));
-	gnt_box_set_fill(GNT_BOX(window), TRUE);
-	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_LEFT);
-	gnt_box_set_pad(GNT_BOX(window), 0);
-
-	edits = g_list_append(edits, edit);
-
-	/* Title */
-	box = gnt_hbox_new(FALSE);
-	gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_LEFT);
-	gnt_box_add_widget(GNT_BOX(window), box);
-	gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Title")));
-
-	edit->title = entry = gnt_entry_new(saved ? gaim_savedstatus_get_title(saved) : NULL);
-	gnt_box_add_widget(GNT_BOX(box), entry);
-
-	/* Type */
-	box = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(window), box);
-	gnt_box_add_widget(GNT_BOX(box), label = gnt_label_new(_("Status")));
-	gnt_widget_set_size(label, 0, 1);
-
-	edit->type = combo = gnt_combo_box_new();
-	gnt_box_add_widget(GNT_BOX(box), combo);
-	current = saved ? gaim_savedstatus_get_type(saved) : GAIM_STATUS_UNSET;
-	for (i = 0; prims[i] != GAIM_STATUS_UNSET; i++)
-	{
-		gnt_combo_box_add_data(GNT_COMBO_BOX(combo), GINT_TO_POINTER(prims[i]),
-				gaim_primitive_get_name_from_type(prims[i]));
-		if (prims[i] == current)
-			gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), GINT_TO_POINTER(current));
-	}
-
-	/* Message */
-	box = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(window), box);
-	gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Message")));
-
-	edit->message = entry = gnt_entry_new(saved ? gaim_savedstatus_get_message(saved) : NULL);
-	gnt_box_add_widget(GNT_BOX(window), entry);
-
-	gnt_box_add_widget(GNT_BOX(window), gnt_hline_new());
-	gnt_box_add_widget(GNT_BOX(window), gnt_label_new(_("Use different status for following accounts")));
-
-	edit->hash = g_hash_table_new(g_direct_hash, g_direct_equal);
-	edit->tree = tree = gnt_tree_new_with_columns(3);
-	gnt_box_add_widget(GNT_BOX(window), tree);
-	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
-	gnt_tree_set_column_titles(GNT_TREE(tree), _("Account"), _("Status"), _("Message"));
-	gnt_tree_set_col_width(GNT_TREE(tree), 0, 30);
-	gnt_tree_set_col_width(GNT_TREE(tree), 1, 10);
-	gnt_tree_set_col_width(GNT_TREE(tree), 2, 30);
-
-	for (iter = gaim_accounts_get_all(); iter; iter = iter->next)
-	{
-		add_substatus(edit, iter->data);
-	}
-
-	g_signal_connect(G_OBJECT(tree), "key_pressed", G_CALLBACK(popup_substatus), edit);
-
-	/* The buttons */
-	box = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(window), box);
-
-	/* Use */
-	button = gnt_button_new(_("Use"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(use_trans_status_cb), edit);
-
-	/* Save */
-	button = gnt_button_new(_("Save"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_object_set_data(G_OBJECT(button), "use", NULL);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_savedstatus_cb), edit);
-
-	/* Save & Use */
-	button = gnt_button_new(_("Save & Use"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_object_set_data(G_OBJECT(button), "use", GINT_TO_POINTER(TRUE));
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_savedstatus_cb), edit);
-
-	/* Cancel */
-	button = gnt_button_new(_("Cancel"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect_swapped(G_OBJECT(button), "activate",
-			G_CALLBACK(gnt_widget_destroy), window);
-
-	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(update_edit_list), edit);
-
-	gnt_widget_show(window);
-}
-
--- a/console/gntstatus.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/**
- * @file gntstatus.h GNT Status API
- * @ingroup gntui
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_STATUS_H
-#define _GNT_STATUS_H
-
-#include <status.h>
-#include <savedstatuses.h>
-
-/**********************************************************************
- * @name GNT BuddyList API
- **********************************************************************/
-/*@{*/
-
-/**
- * Show a dialog with all the saved statuses.
- */
-void gg_savedstatus_show_all(void);
-
-/**
- * Show a dialog to edit a status.
- *
- * @param saved The saved status to edit. Set it to @c NULL to create a new status.
- */
-void gg_savedstatus_edit(GaimSavedStatus *saved);
-
-/*@}*/
-
-#endif
--- a/console/gntui.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/**
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include "gntui.h"
-
-#include "gntaccount.h"
-#include "gntblist.h"
-#include "gntconn.h"
-#include "gntconv.h"
-#include "gntdebug.h"
-#include "gntft.h"
-#include "gntnotify.h"
-#include "gntplugin.h"
-#include "gntpounce.h"
-#include "gntprefs.h"
-#include "gntrequest.h"
-#include "gntstatus.h"
-#include "internal.h"
-
-#include <prefs.h>
-
-void gnt_ui_init()
-{
-#ifdef STANDALONE
-	gnt_init();
-#endif
-
-	gaim_prefs_add_none("/gaim/gnt");
-	
-	/* Accounts */
-	gg_accounts_init();
-	gaim_accounts_set_ui_ops(gg_accounts_get_ui_ops());
-
-	/* Connections */
-	gg_connections_init();
-	gaim_connections_set_ui_ops(gg_connections_get_ui_ops());
-
-	/* Initialize the buddy list */
-	gg_blist_init();
-	gaim_blist_set_ui_ops(gg_blist_get_ui_ops());
-
-	/* Now the conversations */
-	gg_conversation_init();
-	gaim_conversations_set_ui_ops(gg_conv_get_ui_ops());
-
-	/* Notify */
-	gg_notify_init();
-	gaim_notify_set_ui_ops(gg_notify_get_ui_ops());
-
-	gg_request_init();
-	gaim_request_set_ui_ops(gg_request_get_ui_ops());
-
-	gg_pounces_init();
-
-	gg_xfers_init();
-	gaim_xfers_set_ui_ops(gg_xfers_get_ui_ops());
-
-	gnt_register_action(_("Accounts"), gg_accounts_show_all);
-	gnt_register_action(_("Buddy List"), gg_blist_show);
-	gnt_register_action(_("Buddy Pounces"), gg_pounces_manager_show);
-	gnt_register_action(_("Debug Window"), gg_debug_window_show);
-	gnt_register_action(_("File Transfers"), gg_xfer_dialog_show);
-	gnt_register_action(_("Plugins"), gg_plugins_show_all);
-	gnt_register_action(_("Preferences"), gg_prefs_show_all);
-	gnt_register_action(_("Statuses"), gg_savedstatus_show_all);
-
-#ifdef STANDALONE
-
-	gg_plugins_save_loaded();
-}
-
-void gnt_ui_uninit()
-{
-	gaim_accounts_set_ui_ops(NULL);
-	gg_accounts_uninit();
-
-	gaim_connections_set_ui_ops(NULL);
-	gg_connections_uninit();
-
-	gaim_blist_set_ui_ops(NULL);
-	gg_blist_uninit();
-
-	gaim_conversations_set_ui_ops(NULL);
-	gg_conversation_uninit();
-
-	gaim_notify_set_ui_ops(NULL);
-	gg_notify_uninit();
-
-	gaim_request_set_ui_ops(NULL);
-	gg_request_uninit();
-
-	gg_pounces_uninit();
-
-	gg_xfers_uninit();
-	gaim_xfers_set_ui_ops(NULL);
-
-	gnt_quit();
-#endif
-}
-
--- a/console/gntui.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/**
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GNT_UI_H
-#define _GNT_UI_H
-
-#include "gnt.h"
-
-void gnt_ui_init(void);
-void gnt_ui_uninit(void);
-
-#endif
--- a/console/libgnt/COPYING	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year  name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
--- a/console/libgnt/INSTALL	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
-Foundation, Inc.
-
-   This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-Basic Installation
-==================
-
-   These are generic installation instructions.
-
-   The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation.  It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions.  Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
-   It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring.  (Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.)
-
-   If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release.  If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
-   The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'.  You only need
-`configure.ac' if you want to change it or regenerate `configure' using
-a newer version of `autoconf'.
-
-The simplest way to compile this package is:
-
-  1. `cd' to the directory containing the package's source code and type
-     `./configure' to configure the package for your system.  If you're
-     using `csh' on an old version of System V, you might need to type
-     `sh ./configure' instead to prevent `csh' from trying to execute
-     `configure' itself.
-
-     Running `configure' takes awhile.  While running, it prints some
-     messages telling which features it is checking for.
-
-  2. Type `make' to compile the package.
-
-  3. Optionally, type `make check' to run any self-tests that come with
-     the package.
-
-  4. Type `make install' to install the programs and any data files and
-     documentation.
-
-  5. You can remove the program binaries and object files from the
-     source code directory by typing `make clean'.  To also remove the
-     files that `configure' created (so you can compile the package for
-     a different kind of computer), type `make distclean'.  There is
-     also a `make maintainer-clean' target, but that is intended mainly
-     for the package's developers.  If you use it, you may have to get
-     all sorts of other programs in order to regenerate files that came
-     with the distribution.
-
-Compilers and Options
-=====================
-
-   Some systems require unusual options for compilation or linking that
-the `configure' script does not know about.  Run `./configure --help'
-for details on some of the pertinent environment variables.
-
-   You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment.  Here
-is an example:
-
-     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
-
-   *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
-   You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory.  To do this, you must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'.  `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script.  `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
-   If you have to use a `make' that does not support the `VPATH'
-variable, you have to compile the package for one architecture at a
-time in the source code directory.  After you have installed the
-package for one architecture, use `make distclean' before reconfiguring
-for another architecture.
-
-Installation Names
-==================
-
-   By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc.  You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
-
-   You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files.  If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
-
-   In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
-kinds of files.  Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
-   If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
-   Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System).  The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
-   For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
-   There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on.  Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
-`--build=TYPE' option.  TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
-     CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
-     OS KERNEL-OS
-
-   See the file `config.sub' for the possible values of each field.  If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
-   If you are _building_ compiler tools for cross-compiling, you should
-use the `--target=TYPE' option to select the type of system they will
-produce code for.
-
-   If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
-   If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists.  Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
-   Variables not defined in a site shell script can be set in the
-environment passed to `configure'.  However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost.  In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'.  For example:
-
-     ./configure CC=/usr/local2/bin/gcc
-
-will cause the specified gcc to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-`configure' Invocation
-======================
-
-   `configure' recognizes the following options to control how it
-operates.
-
-`--help'
-`-h'
-     Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
-     Print the version of Autoconf used to generate the `configure'
-     script, and exit.
-
-`--cache-file=FILE'
-     Enable the cache: use and save the results of the tests in FILE,
-     traditionally `config.cache'.  FILE defaults to `/dev/null' to
-     disable caching.
-
-`--config-cache'
-`-C'
-     Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
-     Do not print messages saying which checks are being made.  To
-     suppress all normal output, redirect it to `/dev/null' (any error
-     messages will still be shown).
-
-`--srcdir=DIR'
-     Look for the package's source code in directory DIR.  Usually
-     `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options.  Run
-`configure --help' for more details.
-
--- a/console/libgnt/Makefile.am	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-EXTRA_DIST=genmarshal
-
-SUBDIRS = . wms
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = gnt.pc
-
-lib_LTLIBRARIES = libgnt.la
-
-libgnt_la_SOURCES = \
-	gntmarshal.c \
-	gntwidget.c \
-	gntbindable.c \
-	gntbox.c \
-	gntbutton.c \
-	gntcheckbox.c \
-	gntclipboard.c \
-	gntcolors.c \
-	gntcombobox.c \
-	gntentry.c \
-	gntkeys.c \
-	gntlabel.c \
-	gntline.c \
-	gntmenu.c \
-	gntmenuitem.c \
-	gntmenuitemcheck.c \
-	gntstyle.c \
-	gnttextview.c \
-	gnttree.c \
-	gntutils.c \
-	gntwindow.c \
-	gntwm.c \
-	gntmain.c
-
-libgnt_la_headers = \
-	gntwidget.h \
-	gntbindable.h \
-	gntbox.h \
-	gntbutton.h \
-	gntcheckbox.h \
-	gntclipboard.h \
-	gntcolors.h \
-	gntcombobox.h \
-	gntentry.h \
-	gntkeys.h \
-	gntlabel.h \
-	gntline.h \
-	gntmarshal.h \
-	gntmenu.h \
-	gntmenuitem.h \
-	gntmenuitemcheck.h \
-	gntstyle.h \
-	gnttextview.h \
-	gnttree.h \
-	gntutils.h \
-	gntwindow.h \
-	gntwm.h \
-	gnt.h
-
-CLEANFILES = \
-	gntmarshal.h \
-	gntmarshal.c
-
-gntmarshal.c: genmarshal gntmarshal.h
-	echo "#include \"gntmarshal.h\"" > $@
-	cat genmarshal | glib-genmarshal --prefix=gnt_closure_marshal --body >> $@
-
-gntmarshal.h: genmarshal
-	cat genmarshal | glib-genmarshal --prefix=gnt_closure_marshal --header > $@
-
-libgnt_laincludedir=$(includedir)/gnt
-libgnt_lainclude_HEADERS = \
-	$(libgnt_la_headers)
-
-libgnt_la_DEPENDENCIES = 
-libgnt_la_LDFLAGS = -export-dynamic
-libgnt_la_LIBADD = \
-	$(GLIB_LIBS) \
-	$(GNT_LIBS)
-
-AM_CPPFLAGS = \
-	$(GLIB_CFLAGS) \
-	$(GNT_CFLAGS) \
-	$(DEBUG_CFLAGS)
--- a/console/libgnt/autogen.sh	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#!/bin/sh
-
-(libtoolize --version) < /dev/null > /dev/null 2>&1 || {
-	echo;
-	echo "You must have libtool installed to compile LibGNT";
-	echo;
-	exit;
-}
-
-(automake --version) < /dev/null > /dev/null 2>&1 || {
-	echo;
-	echo "You must have automake installed to compile LibGNT";
-	echo;
-	exit;
-}
-
-(autoconf --version) < /dev/null > /dev/null 2>&1 || {
-	echo;
-	echo "You must have autoconf installed to compile LibGNT";
-	echo;
-	exit;
-}
-
-echo "Generating configuration files for LibGNT, please wait...."
-echo;
-
-echo "Running libtoolize, please ignore non-fatal messages...."
-echo n | libtoolize --copy --force || exit;
-
-# Add other directories to this list if people continue to experience
-# brokennesses ...  Obviously the real answer is for them to fix it
-# themselves, but for Luke's sake we have this.
-for dir in "/usr/local/share/aclocal" \
-           "/opt/gnome-1.4/share/aclocal"
-do
-	if test -d $dir ; then
-		ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I $dir"
-	fi
-done
-
-libtoolize -c -f --automake
-aclocal $ACLOCAL_FLAGS || exit;
-autoheader || exit;
-automake --add-missing --copy;
-autoconf || exit;
-automake || exit;
-./configure $@
-
--- a/console/libgnt/configure.ac	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-dnl Process this file with autoconf to produce a configure script.
-AC_INIT([libgnt], [0.0.0dev], [gaim-devel@lists.sourceforge.net])
-AC_CANONICAL_SYSTEM
-AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
-
-AC_PREREQ([2.50])
-
-AC_PATH_PROG(sedpath, sed)
-
-dnl Storing configure arguments
-AC_DEFINE_UNQUOTED(CONFIG_ARGS, "$ac_configure_args", [configure arguments])
-
-dnl Checks for programs.
-AC_PROG_CC
-AC_DISABLE_STATIC
-AM_PROG_LIBTOOL
-LIBTOOL="$LIBTOOL --silent"
-AC_PROG_INSTALL
-
-dnl we don't use autobreak on cygwin!!
-dnl AC_CYGWIN
-
-dnl Checks for header files.
-AC_HEADER_STDC
-AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS(arpa/nameser_compat.h fcntl.h sys/time.h unistd.h locale.h signal.h stdint.h regex.h)
-
-dnl Checks for typedefs, structures, and compiler characteristics.
-AC_C_CONST
-AC_STRUCT_TM
-
-AC_C_BIGENDIAN
-
-dnl Checks for library functions.
-AC_TYPE_SIGNAL
-AC_FUNC_STRFTIME
-AC_CHECK_FUNCS(strdup strstr atexit setlocale)
-
-dnl to prevent the g_stat()/g_unlink() crash,
-dnl (09:50:07) Robot101: LSchiere2: it's easy. +LC_SYS_LARGEFILE somewhere in configure.ac
-AC_SYS_LARGEFILE
-
-dnl FreeBSD doesn't have libdl, dlopen is provided by libc
-AC_CHECK_FUNC(dlopen, LIBDL="", [AC_CHECK_LIB(dl, dlopen, LIBDL="-ldl")])
-
-AC_MSG_CHECKING(for the %z format string in strftime())
-AC_TRY_RUN([
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <time.h>
-#include <stdio.h>
-
-int main()
-{
-	char buf[6];
-	time_t t = time(NULL);
-
-	if (strftime(buf, sizeof(buf), "%z", localtime(&t)) != 5)
-		return 1;
-
-	fprintf(stderr, "strftime(\"%%z\") yields: \"%s\"\n", buf);
-
-	return !((buf[0] == '-' || buf[0] == '+') &&
-	         (buf[1] >= '0' && buf[1] <= '9') &&
-	         (buf[2] >= '0' && buf[2] <= '9') &&
-	         (buf[3] >= '0' && buf[3] <= '9') &&
-	         (buf[4] >= '0' && buf[4] <= '9')
-	        );
-}
-],
-[
-	AC_MSG_RESULT(yes)
-	AC_DEFINE([HAVE_STRFTIME_Z_FORMAT], [1],
-                                      [Define to 1 if you have a strftime() that supports the %z format string.])
-],
-[
-	AC_MSG_RESULT(no)
-],
-[
-	# Fallback for Cross Compiling...
-	# This will enable the compatibility code.
-	AC_MSG_RESULT(no)
-]
-)
-
-
-AC_CHECK_HEADER(sys/utsname.h)
-AC_CHECK_FUNC(uname)
-
-if test "x$enable_debug" = "xyes" ; then
-	AC_DEFINE(DEBUG, 1, [Define if debugging is enabled.])
-	enable_fatal_asserts="yes"
-fi
-
-if test "x$enable_fatal_asserts" = "xyes" ; then
-	AC_DEFINE(GAIM_FATAL_ASSERTS, 1, [Define to make assertions fatal (useful for debugging).])
-fi
-
-if test "x$enable_deprecated" = "xno"; then
-	DEBUG_CFLAGS="$DEBUG_CFLAGS -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED"
-fi
-
-if test "x$GCC" = "xyes"; then
-	dnl We enable -Wall later.
-	dnl If it's set after the warning CFLAGS in the compiler invocation, it counteracts the -Wno... flags.
-	dnl This leads to warnings we don't want.
-	CFLAGS=`echo $CFLAGS |$sedpath 's/-Wall//'`
-
-	dnl ENABLE WARNINGS SUPPORTED BY THE VERSION OF GCC IN USE
-	dnl
-	dnl Future Possibilities
-	dnl
-	dnl Consider adding -Wbad-function-cast.
-	dnl	This leads to spurious warnings using GPOINTER_TO_INT(), et al. directly on a function call.
-	dnl		We'd need an intermediate variable.
-	dnl
-	dnl Consider adding -Wfloat-equal.
-	dnl	This leads to warnings with Perl.
-	dnl 		Perhaps we could write ugly configure magic and pass -Wno-float-equal down to that subdirectory.
-	dnl		On the other hand, it's probably actually broken, so maybe the Perl folks should fix that?
-	dnl
-	dnl Consider removing -Wno-sign-compare (from the -Wextra set) and fixing all those cases.
-	dnl	This is likely non-trivial.
-	dnl
-	for newflag in \
-			"-Waggregate-return" \
-			"-Wcast-align" \
-			"-Wdeclaration-after-statement" \
-			"-Werror-implicit-function-declaration" \
-			"-Wextra -Wno-sign-compare -Wno-unused-parameter" \
-			"-Winit-self" \
-			"-Wmissing-declarations" \
-			"-Wmissing-prototypes" \
-			"-Wnested-externs" \
-			"-Wpointer-arith" \
-			"-Wundef" \
-	; do
-		orig_CFLAGS="$CFLAGS"
-		CFLAGS="$CFLAGS $newflag"
-		AC_MSG_CHECKING(for $newflag option to gcc)
-		AC_TRY_COMPILE([], [
-			int main() {return 0;}
-		], [
-			AC_MSG_RESULT(yes)
-			CFLAGS="$orig_CFLAGS"
-			DEBUG_CFLAGS="$DEBUG_CFLAGS $newflag"
-		], [
-			AC_MSG_RESULT(no)
-			CFLAGS="$orig_CFLAGS"
-		])
-	done
-
-	if test "x$enable_fortify" = "xyes"; then
-		AC_MSG_CHECKING(for FORTIFY_SOURCE support)
-		AC_TRY_COMPILE([#include <features.h>], [
-			int main() {
-			#if !(__GNUC_PREREQ (4, 1) \
-				|| (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (4, 0)) \
-				|| (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (3, 4) \
-					&& __GNUC_MINOR__ == 4 \
-					&& (__GNUC_PATCHLEVEL__ > 2 \
-						|| (__GNUC_PATCHLEVEL__ == 2 && __GNUC_RH_RELEASE__ >= 8))))
-			#error No FORTIFY_SOURCE support
-			#endif
-				return 0;
-			}
-		], [
-			AC_MSG_RESULT(yes)
-			DEBUG_CFLAGS="$DEBUG_CFLAGS -D_FORTIFY_SOURCE=2"
-		], [
-			AC_MSG_RESULT(no)
-		])
-	fi
-
-	DEBUG_CFLAGS="-Wall $DEBUG_CFLAGS"
-	CFLAGS="-g $CFLAGS"
-fi
-AC_SUBST(CFLAGS)
-
-PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.0.0 gobject-2.0 gmodule-2.0],,
-	[
-		AC_MSG_ERROR([
-*** GLib 2.0 is required to build LibGNT; please make sure you have the GLib
-*** development headers installed. The latest version of GLib is
-*** always available at http://www.gtk.org/.])
-	])
-AC_SUBST(GLIB_CFLAGS)
-AC_SUBST(GLIB_LIBS)
-
-
-AC_MSG_CHECKING(for me pot o' gold)
-AC_MSG_RESULT(no)
-AC_CHECK_FUNCS(gethostid lrand48)
-AC_CHECK_FUNCS(memcpy memmove random strchr strerror vprintf)
-AC_CHECK_HEADERS(malloc.h paths.h sgtty.h stdarg.h sys/cdefs.h)
-AC_CHECK_HEADERS(sys/file.h sys/filio.h sys/ioctl.h sys/msgbuf.h)
-AC_CHECK_HEADERS(sys/select.h sys/uio.h sys/utsname.h sys/wait.h)
-AC_CHECK_HEADERS(termios.h)
-#AC_CHECK_FUNC(wcwidth, [AC_DEFINE([HAVE_WCWIDTH], [1], [Define to 1 if you have wcwidth function.])])
-#AC_VAR_TIMEZONE_EXTERNALS
-
-GNT_CFLAGS=
-GNT_LIBS=
-AC_CHECK_LIB(ncursesw, initscr, [GNT_LIBS="-lncursesw"], [enable_gnt=no])
-AC_CHECK_LIB(panelw, update_panels, [GNT_LIBS="$GNT_LIBS -lpanelw"], [enable_gnt=no])
-
-# If ncursesw is not found, look for plain old ncurses
-if test "x$enable_gnt" = "xno"; then
-	AC_CHECK_LIB(ncurses, initscr, [[GNT_LIBS="-lncurses"] [enable_gnt=yes]], [enable_gnt=no])
-	AC_CHECK_LIB(panel, update_panels, [[GNT_LIBS="$GNT_LIBS -lpanel"] [enable_gnt=yes]], [enable_gnt=no])
-	AC_DEFINE(NO_WIDECHAR, [1], [Define to 1 if you do not have ncursesw.])
-else
-	dnl # Some distros put the headers in ncursesw/, some don't
-	found_ncurses_h=no
-	for f in /usr/include/ncursesw/ncurses.h /usr/include/ncurses.h
-	do
-		AC_CHECK_HEADER($f,[
-			AC_MSG_CHECKING([if $f supports wide characters])
-			AC_TRY_COMPILE([
-				#define _XOPEN_SOURCE_EXTENDED
-				#include <$f>
-			], [
-				#ifndef get_wch
-				# error get_wch not found!
-				#endif
-			], [
-				dir=`dirname $f`
-				if test x"$dir" != x"." ; then
-					GNT_CFLAGS="-I$dir/"
-				else
-					GNT_CFLAGS=""
-				fi
-
-				found_ncurses_h=yes
-				AC_MSG_RESULT([yes])
-				break
-			], [
-				AC_MSG_RESULT([no])
-			])
-		])
-	done
-fi
-AC_SUBST(GNT_CFLAGS)
-AC_SUBST(GNT_LIBS)
-
-if test "x$enable_gnt" = "xno"; then
-	AC_MSG_ERROR([
-*** You need ncursesw or ncurses.])
-fi
-
-AC_OUTPUT([Makefile
-           gnt.pc
-           wms/Makefile
-		  ])
-
--- a/console/libgnt/genmarshal	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-BOOLEAN:VOID
-BOOLEAN:STRING
-VOID:INT,INT,INT,INT
-VOID:INT,INT
-VOID:POINTER,POINTER
-BOOLEAN:INT,INT
-BOOLEAN:INT,INT,INT
-BOOLEAN:POINTER,POINTER,POINTER
-BOOLEAN:INT,INT,INT,POINTER
-VOID:STRING,STRING
--- a/console/libgnt/gnt-skel.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-#include "gnt-skel.h"
-
-enum
-{
-	SIGS = 1,
-};
-
-static GntWidgetClass *parent_class = NULL;
-static guint signals[SIGS] = { 0 };
-
-static void
-gnt_skel_draw(GntWidget *widget)
-{
-	GNTDEBUG;
-}
-
-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);
-	GNTDEBUG;
-}
-
-static gboolean
-gnt_skel_key_pressed(GntWidget *widget, const char *text)
-{
-	return FALSE;
-}
-
-static void
-gnt_skel_destroy(GntWidget *widget)
-{
-}
-
-static void
-gnt_skel_class_init(GntSkelClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-
-	parent_class = GNT_WIDGET_CLASS(klass);
-	parent_class->destroy = gnt_skel_destroy;
-	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;
-
-	parent_class->actions = g_hash_table_duplicate(parent_class->actions, g_str_hash,
-				g_str_equal, NULL, (GDestroyNotify)gnt_widget_action_free);
-	parent_class->bindings = g_hash_table_duplicate(parent_class->bindings, g_str_hash,
-				g_str_equal, NULL, (GDestroyNotify)gnt_widget_action_param_free);
-
-	gnt_widget_actions_read(G_OBJECT_CLASS_TYPE(klass), klass);
-
-	GNTDEBUG;
-}
-
-static void
-gnt_skel_init(GTypeInstance *instance, gpointer class)
-{
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * 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;
-}
-
--- a/console/libgnt/gnt-skel.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-#ifndef GNT_SKEL_H
-#define GNT_SKEL_H
-
-#include "gntwidget.h"
-#include "gnt.h"
-#include "gntcolors.h"
-#include "gntkeys.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 */
--- a/console/libgnt/gnt.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-#include <glib.h>
-#include "gntwidget.h"
-#include "gntclipboard.h"
-#include "gntcolors.h"
-#include "gntkeys.h"
-
-void gnt_init(void);
-
-void gnt_main(void);
-
-gboolean gnt_ascii_only(void);
-
-void gnt_screen_occupy(GntWidget *widget);
-
-void gnt_screen_release(GntWidget *widget);
-
-void gnt_screen_update(GntWidget *widget);
-
-void gnt_screen_take_focus(GntWidget *widget);
-
-void gnt_screen_resize_widget(GntWidget *widget, int width, int height);
-
-void gnt_screen_move_widget(GntWidget *widget, int x, int y);
-
-void gnt_screen_rename_widget(GntWidget *widget, const char *text);
-
-gboolean gnt_widget_has_focus(GntWidget *widget);
-
-void gnt_widget_set_urgent(GntWidget *widget);
-
-void gnt_register_action(const char *label, void (*callback)());
-
-gboolean gnt_screen_menu_show(gpointer menu);
-
-void gnt_quit(void);
-
-GntClipboard *gnt_get_clipboard(void);
-
-gchar *gnt_get_clipboard_string(void);
-
-void gnt_set_clipboard_string(gchar *);
--- a/console/libgnt/gnt.pc.in	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
- 
-Name: LibGNT
-Description: Glib Ncurses Toolkit is a collection of curses-widgets.
-Version: @VERSION@
-Requires: glib-2.0
-Cflags: -I${includedir}/gnt
-Libs: -L${libdir} -lgnt
--- a/console/libgnt/gntbindable.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-#include "gntbindable.h"
-#include "gntstyle.h"
-#include "gnt.h"
-#include "gntutils.h"
-
-static GObjectClass *parent_class = NULL;
-
-static void
-gnt_bindable_class_init(GntBindableClass *klass)
-{
-	parent_class = g_type_class_peek_parent(klass);
-
-	klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-				(GDestroyNotify)gnt_bindable_action_free);
-	klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-				(GDestroyNotify)gnt_bindable_action_param_free);
-
-	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
-	GNTDEBUG;
-}
-
-static gpointer
-bindable_clone(GntBindableAction *action)
-{
-	GntBindableAction *ret = g_new0(GntBindableAction, 1);
-	ret->name = g_strdup(action->name);
-	ret->u = action->u;
-	return ret;
-}
-
-static gpointer
-binding_clone(GntBindableActionParam *param)
-{
-	GntBindableActionParam *p = g_new0(GntBindableActionParam, 1);
-	p->list = g_list_copy(param->list);
-	p->action = param->action;
-	return p;
-}
-
-static void
-duplicate_hashes(GntBindableClass *klass)
-{
-	/* Duplicate the bindings from parent class */
-	if (klass->actions) {
-		klass->actions = g_hash_table_duplicate(klass->actions, g_str_hash,
-					g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_free,
-					(GDupFunc)g_strdup, (GDupFunc)bindable_clone);
-		klass->bindings = g_hash_table_duplicate(klass->bindings, g_str_hash,
-					g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_param_free,
-					(GDupFunc)g_strdup, (GDupFunc)binding_clone);
-	} else {
-		klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-					(GDestroyNotify)gnt_bindable_action_free);
-		klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-					(GDestroyNotify)gnt_bindable_action_param_free);
-	}
-
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * GntBindable API
- *****************************************************************************/
-GType
-gnt_bindable_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0) {
-		static const GTypeInfo info = {
-			sizeof(GntBindableClass),
-			(GBaseInitFunc)duplicate_hashes,	/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_bindable_class_init,
-			NULL,
-			NULL,					/* class_data		*/
-			sizeof(GntBindable),
-			0,						/* n_preallocs		*/
-			NULL,					/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(G_TYPE_OBJECT,
-									  "GntBindable",
-									  &info, G_TYPE_FLAG_ABSTRACT);
-	}
-
-	return type;
-}
-
-/**
- * Key Remaps
- */
-const char *
-gnt_bindable_remap_keys(GntBindable *bindable, const char *text)
-{
-	const char *remap = NULL;
-	GType type = G_OBJECT_TYPE(bindable);
-	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
-
-	if (klass->remaps == NULL)
-	{
-		klass->remaps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-		gnt_styles_get_keyremaps(type, klass->remaps);
-	}
-
-	remap = g_hash_table_lookup(klass->remaps, text);
-
-	return (remap ? remap : text);
-}
-
-/**
- * Actions and Bindings
- */
-gboolean
-gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...)
-{
-	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
-	GList *list = NULL;
-	va_list args;
-	GntBindableAction *action;
-	void *p;
-
-	va_start(args, name);
-	while ((p = va_arg(args, void *)) != NULL)
-		list = g_list_append(list, p);
-	va_end(args);
-	
-	action = g_hash_table_lookup(klass->actions, name);
-	if (action && action->u.action) {
-		return action->u.action(bindable, list);
-	}
-	return FALSE;
-}
-
-gboolean
-gnt_bindable_perform_action_key(GntBindable *bindable, const char *keys)
-{
-	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
-	GntBindableActionParam *param = g_hash_table_lookup(klass->bindings, keys);
-
-	if (param && param->action) {
-		if (param->list)
-			return param->action->u.action(bindable, param->list);
-		else
-			return param->action->u.action_noparam(bindable);
-	}
-	return FALSE;
-}
-
-static void
-register_binding(GntBindableClass *klass, const char *name, const char *trigger, GList *list)
-{
-	GntBindableActionParam *param;
-	GntBindableAction *action;
-
-	if (name == NULL || *name == '\0') {
-		g_hash_table_remove(klass->bindings, (char*)trigger);
-		gnt_keys_del_combination(trigger);
-		return;
-	}
-
-	action = g_hash_table_lookup(klass->actions, name);
-	if (!action) {
-		g_printerr("GntWidget: Invalid action name %s for %s\n",
-				name, g_type_name(G_OBJECT_CLASS_TYPE(klass)));
-		if (list)
-			g_list_free(list);
-		return;
-	}
-
-	param = g_new0(GntBindableActionParam, 1);
-	param->action = action;
-	param->list = list;
-	g_hash_table_replace(klass->bindings, g_strdup(trigger), param);
-	gnt_keys_add_combination(trigger);
-}
-
-void gnt_bindable_register_binding(GntBindableClass *klass, const char *name,
-			const char *trigger, ...)
-{
-	GList *list = NULL;
-	va_list args;
-	void *data;
-
-	va_start(args, trigger);
-	while ((data = va_arg(args, void *))) {
-		list = g_list_append(list, data);
-	}
-	va_end(args);
-
-	register_binding(klass, name, trigger, list);
-}
-
-void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name,
-			GntBindableActionCallback callback, const char *trigger, ...)
-{
-	void *data;
-	va_list args;
-	GntBindableAction *action = g_new0(GntBindableAction, 1);
-	GList *list;
-
-	action->name = g_strdup(name);
-	action->u.action = callback;
-
-	g_hash_table_replace(klass->actions, g_strdup(name), action);
-
-	if (trigger && *trigger) {
-		list = NULL;
-		va_start(args, trigger);
-		while ((data = va_arg(args, void *))) {
-			list = g_list_append(list, data);
-		}
-		va_end(args);
-
-		register_binding(klass, name, trigger, list);
-	}
-}
-
-void gnt_bindable_action_free(GntBindableAction *action)
-{
-	g_free(action->name);
-	g_free(action);
-}
-
-void gnt_bindable_action_param_free(GntBindableActionParam *param)
-{
-	g_list_free(param->list);   /* XXX: There may be a leak here for string parameters */
-	g_free(param);
-}
-
-
--- a/console/libgnt/gntbindable.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-#ifndef GNT_BINDABLE_H
-#define GNT_BINDABLE_H
-
-#include <stdio.h>
-#include <glib.h>
-#include <glib-object.h>
-#include <ncurses.h>
-
-#define GNT_TYPE_BINDABLE				(gnt_bindable_get_gtype())
-#define GNT_BINDABLE(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_BINDABLE, GntBindable))
-#define GNT_BINDABLE_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_BINDABLE, GntBindableClass))
-#define GNT_IS_BINDABLE(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_BINDABLE))
-#define GNT_IS_BINDABLE_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_BINDABLE))
-#define GNT_BINDABLE_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_BINDABLE, GntBindableClass))
-
-#define	GNTDEBUG	g_printerr("%s\n", __FUNCTION__)
-
-typedef struct _GnBindable			GntBindable;
-typedef struct _GnBindableClass		GntBindableClass;
-
-struct _GnBindable
-{
-	GObject inherit;
-};
-
-struct _GnBindableClass
-{
-	GObjectClass parent;
-
-	GHashTable *remaps;   /* Key remaps */
-	GHashTable *actions;  /* name -> Action */
-	GHashTable *bindings; /* key -> ActionParam */
-
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_bindable_get_gtype(void);
-
-/******************/
-/*   Key Remaps   */
-/******************/
-const char * gnt_bindable_remap_keys(GntBindable *bindable, const char *text);
-
-/******************/
-/* Bindable Actions */
-/******************/
-typedef gboolean (*GntBindableActionCallback) (GntBindable *bindable, GList *params);
-typedef gboolean (*GntBindableActionCallbackNoParam)(GntBindable *bindable);
-
-typedef struct _GnBindableAction GntBindableAction;
-typedef struct _GnBindableActionParam GntBindableActionParam;
-
-struct _GnBindableAction
-{
-	char *name;        /* The name of the action */
-	union {
-		gboolean (*action)(GntBindable *bindable, GList *params);
-		gboolean (*action_noparam)(GntBindable *bindable);
-	} u;
-};
-
-struct _GnBindableActionParam
-{
-	GntBindableAction *action;
-	GList *list;
-};
-
-
-/*GntBindableAction *gnt_bindable_action_parse(const char *name);*/
-
-void gnt_bindable_action_free(GntBindableAction *action);
-void gnt_bindable_action_param_free(GntBindableActionParam *param);
-
-void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name,
-			GntBindableActionCallback callback, const char *trigger, ...);
-void gnt_bindable_register_binding(GntBindableClass *klass, const char *name,
-			const char *trigger, ...);
-
-gboolean gnt_bindable_perform_action_key(GntBindable *bindable, const char *keys);
-gboolean gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...);
-
-G_END_DECLS
-
-#endif /* GNT_BINDABLE_H */
-
--- a/console/libgnt/gntbox.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,788 +0,0 @@
-#include "gntbox.h"
-#include "gntutils.h"
-
-#include <string.h>
-
-enum
-{
-	SIGS = 1,
-};
-
-static GntWidgetClass *parent_class = NULL;
-
-static GntWidget * find_focusable_widget(GntBox *box);
-
-static void
-add_to_focus(gpointer value, gpointer data)
-{
-	GntBox *box = GNT_BOX(data);
-	GntWidget *w = GNT_WIDGET(value);
-
-	if (GNT_IS_BOX(w))
-		g_list_foreach(GNT_BOX(w)->list, add_to_focus, box);
-	else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_CAN_TAKE_FOCUS))
-		box->focus = g_list_append(box->focus, w);
-}
-
-static void
-get_title_thingies(GntBox *box, char *title, int *p, int *r)
-{
-	GntWidget *widget = GNT_WIDGET(box);
-	int len;
-	char *end = (char*)gnt_util_onscreen_width_to_pointer(title, widget->priv.width - 4, &len);
-	
-	if (p)
-		*p = (widget->priv.width - len) / 2;
-	if (r)
-		*r = (widget->priv.width + len) / 2;
-	*end = '\0';
-}
-
-static void
-gnt_box_draw(GntWidget *widget)
-{
-	GntBox *box = GNT_BOX(widget);
-
-	if (box->focus == NULL && widget->parent == NULL)
-		g_list_foreach(box->list, add_to_focus, box);
-
-	g_list_foreach(box->list, (GFunc)gnt_widget_draw, NULL);
-
-	gnt_box_sync_children(box);
-
-	if (box->title && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
-	{
-		int pos, right;
-		char *title = g_strdup(box->title);
-		
-		get_title_thingies(box, title, &pos, &right);
-
-		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));
-		mvwaddch(widget->window, 0, pos-1, ACS_RTEE | COLOR_PAIR(GNT_COLOR_NORMAL));
-		mvwaddstr(widget->window, 0, pos, title);
-		mvwaddch(widget->window, 0, right, ACS_LTEE | COLOR_PAIR(GNT_COLOR_NORMAL));
-		g_free(title);
-	}
-	
-	GNTDEBUG;
-}
-
-static void
-reposition_children(GntWidget *widget)
-{
-	GList *iter;
-	GntBox *box = GNT_BOX(widget);
-	int w, h, curx, cury, max;
-	gboolean has_border = FALSE;
-
-	w = h = 0;
-	max = 0;
-	curx = widget->priv.x;
-	cury = widget->priv.y;
-	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER))
-	{
-		has_border = TRUE;
-		curx += 1;
-		cury += 1;
-	}
-
-	for (iter = box->list; iter; iter = iter->next)
-	{
-		if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(iter->data), GNT_WIDGET_INVISIBLE))
-			continue;
-		gnt_widget_set_position(GNT_WIDGET(iter->data), curx, cury);
-		gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h);
-		if (box->vertical)
-		{
-			if (h)
-			{
-				cury += h + box->pad;
-				if (max < w)
-					max = w;
-			}
-		}
-		else
-		{
-			if (w)
-			{
-				curx += w + box->pad;
-				if (max < h)
-					max = h;
-			}
-		}
-	}
-
-	if (has_border)
-	{
-		curx += 1;
-		cury += 1;
-		max += 2;
-	}
-
-	if (box->list)
-	{
-		if (box->vertical)
-			cury -= box->pad;
-		else
-			curx -= box->pad;
-	}
-
-	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)
-{
-	GList *iter;
-	int changex, changey;
-
-	changex = widget->priv.x - x;
-	changey = widget->priv.y - y;
-
-	for (iter = GNT_BOX(widget)->list; iter; iter = iter->next)
-	{
-		GntWidget *w = GNT_WIDGET(iter->data);
-		gnt_widget_set_position(w, w->priv.x - changex,
-				w->priv.y - changey);
-	}
-}
-
-static void
-gnt_box_size_request(GntWidget *widget)
-{
-	GntBox *box = GNT_BOX(widget);
-	GList *iter;
-	int maxw = 0, maxh = 0;
-	
-	g_list_foreach(box->list, (GFunc)gnt_widget_size_request, NULL);
-
-	for (iter = box->list; iter; iter = iter->next)
-	{
-		int w, h;
-		gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h);
-		if (maxh < h)
-			maxh = h;
-		if (maxw < w)
-			maxw = w;
-	}
-
-	for (iter = box->list; iter; iter = iter->next)
-	{
-		int w, h;
-		GntWidget *wid = GNT_WIDGET(iter->data);
-
-		gnt_widget_get_size(wid, &w, &h);
-
-		if (box->homogeneous)
-		{
-			if (box->vertical)
-				h = maxh;
-			else
-				w = maxw;
-		}
-		if (box->fill)
-		{
-			if (box->vertical)
-				w = maxw;
-			else
-				h = maxh;
-		}
-
-		gnt_widget_set_size(wid, w, 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);
-		find_focusable_widget(GNT_BOX(widget));
-	}
-	GNTDEBUG;
-}
-
-/* Ensures that the current widget can take focus */
-static GntWidget *
-find_focusable_widget(GntBox *box)
-{
-	/* XXX: Make sure the widget is visible? */
-	if (box->focus == NULL && GNT_WIDGET(box)->parent == NULL)
-		g_list_foreach(box->list, add_to_focus, box);
-
-	if (box->active == NULL && box->focus)
-		box->active = box->focus->data;
-
-	return box->active;
-}
-
-static void
-find_next_focus(GntBox *box)
-{
-	gpointer last = box->active;
-	do
-	{
-		GList *iter = g_list_find(box->focus, box->active);
-		if (iter && iter->next)
-			box->active = iter->next->data;
-		else if (box->focus)
-			box->active = box->focus->data;
-		if (!GNT_WIDGET_IS_FLAG_SET(box->active, GNT_WIDGET_INVISIBLE))
-			break;
-	} while (box->active != last);
-}
-
-static void
-find_prev_focus(GntBox *box)
-{
-	gpointer last = box->active;
-
-	if (!box->focus)
-		return;
-
-	do
-	{
-		GList *iter = g_list_find(box->focus, box->active);
-		if (!iter)
-			box->active = box->focus->data;
-		else if (!iter->prev)
-			box->active = g_list_last(box->focus)->data;
-		else
-			box->active = iter->prev->data;
-		if (!GNT_WIDGET_IS_FLAG_SET(box->active, GNT_WIDGET_INVISIBLE))
-			break;
-	} while (box->active != last);
-}
-
-static gboolean
-gnt_box_key_pressed(GntWidget *widget, const char *text)
-{
-	GntBox *box = GNT_BOX(widget);
-	GntWidget *now;
-
-	if (box->active == NULL && !find_focusable_widget(box))
-		return FALSE;
-
-	if (gnt_widget_key_pressed(box->active, text))
-		return TRUE;
-	
-	now = box->active;
-
-	if (text[0] == 27)
-	{
-		if (strcmp(text, GNT_KEY_LEFT) == 0)
-		{
-			find_prev_focus(box);
-		}
-		else if (strcmp(text, GNT_KEY_RIGHT) == 0)
-		{
-			find_next_focus(box);
-		}
-	}
-	else if (text[0] == '\t')
-	{
-		find_next_focus(box);
-	}
-
-	if (now && now != box->active)
-	{
-		gnt_widget_set_focus(now, FALSE);
-		gnt_widget_set_focus(box->active, TRUE);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static void
-gnt_box_lost_focus(GntWidget *widget)
-{
-	GntWidget *w = GNT_BOX(widget)->active;
-	if (w)
-		gnt_widget_set_focus(w, FALSE);
-	gnt_widget_draw(widget);
-}
-
-static void
-gnt_box_gained_focus(GntWidget *widget)
-{
-	GntWidget *w = GNT_BOX(widget)->active;
-	if (w)
-		gnt_widget_set_focus(w, TRUE);
-	gnt_widget_draw(widget);
-}
-
-static void
-gnt_box_destroy(GntWidget *w)
-{
-	GntBox *box = GNT_BOX(w);
-
-	gnt_box_remove_all(box);
-	gnt_screen_release(w);
-}
-
-static void
-gnt_box_expose(GntWidget *widget, int x, int y, int width, int height)
-{
-	WINDOW *win = newwin(height, width, widget->priv.y + y, widget->priv.x + x);
-	copywin(widget->window, win, y, x, 0, 0, height - 1, width - 1, FALSE);
-	wrefresh(win);
-	delwin(win);
-}
-
-static gboolean
-gnt_box_confirm_size(GntWidget *widget, int width, int height)
-{
-	GList *iter;
-	GntBox *box = GNT_BOX(widget);
-	int wchange, hchange;
-
-	if (widget->priv.width != width && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_X))
-		return FALSE;
-	if (widget->priv.height != height && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_Y))
-		return FALSE;
-
-	if (!box->list)
-		return TRUE;
-
-	wchange = widget->priv.width - width;
-	hchange = widget->priv.height - height;
-
-	if (wchange == 0 && hchange == 0)
-		return TRUE;		/* Quit playing games */
-
-	/* XXX: Right now, I am trying to just apply all the changes to 
-	 * just one widget. It should be possible to distribute the
-	 * changes to all the widgets in the box. */
-	for (iter = box->list; iter; iter = iter->next)
-	{
-		GntWidget *wid = iter->data;
-		int w, h;
-
-		gnt_widget_get_size(wid, &w, &h);
-
-		if (gnt_widget_confirm_size(wid, w - wchange, h - hchange))
-		{
-			GList *i;
-
-			for (i = box->list; i; i = i->next)
-			{
-				int tw, th;
-				if (i == iter) continue;
-				gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th);
-				if (box->vertical)
-				{
-					if (!gnt_widget_confirm_size(i->data, tw - wchange, th))
-						return FALSE;
-				}
-				else
-				{
-					if (!gnt_widget_confirm_size(i->data, tw, th - hchange))
-						return FALSE;
-				}
-			}
-#if 0
-			gnt_widget_set_size(wid, w - wchange, h - hchange);
-			if (box->vertical)
-				hchange = 0;
-			else
-				wchange = 0;
-
-			for (i = box->list; i; i = i->next)
-			{
-				int tw, th;
-				if (i == iter) continue;
-				gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th);
-				gnt_widget_set_size(i->data, tw - wchange, th - hchange);
-			}
-#endif
-			g_object_set_data(G_OBJECT(box), "size-queued", wid);
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
-static void
-gnt_box_size_changed(GntWidget *widget, int oldw, int oldh)
-{
-	int wchange, hchange;
-	GList *i;
-	GntBox *box = GNT_BOX(widget);
-	GntWidget *wid;
-	int tw, th;
-		
-	wchange = widget->priv.width - oldw;
-	hchange = widget->priv.height - oldh;
-	
-	wid = g_object_get_data(G_OBJECT(box), "size-queued");
-	if (wid)
-	{
-		gnt_widget_get_size(wid, &tw, &th);
-		gnt_widget_set_size(wid, tw + wchange, th + hchange);
-		g_object_set_data(G_OBJECT(box), "size-queued", NULL);
-	}
-
-	if (box->vertical)
-		hchange = 0;
-	else
-		wchange = 0;
-
-	for (i = box->list; i; i = i->next)
-	{
-		if (wid != i->data)
-		{
-			gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th);
-			gnt_widget_set_size(i->data, tw + wchange, th + hchange);
-		}
-	}
-
-	reposition_children(widget);
-}
-
-static gboolean
-gnt_box_clicked(GntWidget *widget, GntMouseEvent event, int cx, int cy)
-{
-	GList *iter;
-	for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) {
-		int x, y, w, h;
-		GntWidget *wid = iter->data;
-
-		gnt_widget_get_position(wid, &x, &y);
-		gnt_widget_get_size(wid, &w, &h);
-
-		if (cx >= x && cx < x + w && cy >= y && cy < y + h) {
-			if (event <= GNT_MIDDLE_MOUSE_DOWN &&
-				GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_CAN_TAKE_FOCUS)) {
-				while (widget->parent)
-					widget = widget->parent;
-				gnt_box_give_focus_to_child(GNT_BOX(widget), wid);
-			}
-			return gnt_widget_clicked(wid, event, cx, cy);
-		}
-	}
-	return FALSE;
-}
-
-static void
-gnt_box_class_init(GntBoxClass *klass)
-{
-	parent_class = GNT_WIDGET_CLASS(klass);
-	parent_class->destroy = gnt_box_destroy;
-	parent_class->draw = gnt_box_draw;
-	parent_class->expose = gnt_box_expose;
-	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->clicked = gnt_box_clicked;
-	parent_class->lost_focus = gnt_box_lost_focus;
-	parent_class->gained_focus = gnt_box_gained_focus;
-	parent_class->confirm_size = gnt_box_confirm_size;
-	parent_class->size_changed = gnt_box_size_changed;
-
-	GNTDEBUG;
-}
-
-static void
-gnt_box_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	GntBox *box = GNT_BOX(widget);
-	/* Initially make both the height and width resizable.
-	 * Update the flags as necessary when widgets are added to it. */
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y);
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
-	box->pad = 1;
-	box->fill = TRUE;
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * 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	*/
-			NULL					/* value_table		*/
-		};
-
-		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;
-	box->alignment = vert ? GNT_ALIGN_LEFT : GNT_ALIGN_MID;
-
-	return widget;
-}
-
-void gnt_box_add_widget(GntBox *b, GntWidget *widget)
-{
-	b->list = g_list_append(b->list, widget);
-	widget->parent = GNT_WIDGET(b);
-
-	if (b->vertical)
-	{
-		if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_X))
-			GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(b), GNT_WIDGET_GROW_X);
-	}
-	else
-	{
-		if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_Y))
-			GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(b), GNT_WIDGET_GROW_Y);
-	}
-}
-
-void gnt_box_set_title(GntBox *b, const char *title)
-{
-	char *prev = b->title;
-	GntWidget *w = GNT_WIDGET(b);
-	b->title = g_strdup(title);
-	if (w->window && !GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_NO_BORDER)) {
-		/* Erase the old title */
-		int pos, right;
-		get_title_thingies(b, prev, &pos, &right);
-		mvwhline(w->window, 0, pos - 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL),
-				right - pos + 2);
-		g_free(prev);
-	}
-}
-
-void gnt_box_set_pad(GntBox *box, int pad)
-{
-	box->pad = pad;
-	/* XXX: Perhaps redraw if already showing? */
-}
-
-void gnt_box_set_toplevel(GntBox *box, gboolean set)
-{
-	GntWidget *widget = GNT_WIDGET(box);
-	if (set)
-	{
-		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
-		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
-	}
-	else
-	{
-		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
-		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
-	}
-}
-
-void gnt_box_sync_children(GntBox *box)
-{
-	GList *iter;
-	GntWidget *widget = GNT_WIDGET(box);
-	int pos = 1;
-
-	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
-		pos = 0;
-
-	for (iter = box->list; iter; iter = iter->next)
-	{
-		GntWidget *w = GNT_WIDGET(iter->data);
-		int height, width;
-		int x, y;
-
-		if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_INVISIBLE))
-			continue;
-
-		if (GNT_IS_BOX(w))
-			gnt_box_sync_children(GNT_BOX(w));
-
-		gnt_widget_get_size(w, &width, &height);
-
-		x = w->priv.x - widget->priv.x;
-		y = w->priv.y - widget->priv.y;
-
-		if (box->vertical)
-		{
-			x = pos;
-			if (box->alignment == GNT_ALIGN_RIGHT)
-				x += widget->priv.width - width;
-			else if (box->alignment == GNT_ALIGN_MID)
-				x += (widget->priv.width - width)/2;
-			if (x + width > widget->priv.width - pos)
-				x -= x + width - (widget->priv.width - pos);
-		}
-		else
-		{
-			y = pos;
-			if (box->alignment == GNT_ALIGN_BOTTOM)
-				y += widget->priv.height - height;
-			else if (box->alignment == GNT_ALIGN_MID)
-				y += (widget->priv.height - height)/2;
-			if (y + height >= widget->priv.height - pos)
-				y = widget->priv.height - height - pos;
-		}
-
-		copywin(w->window, widget->window, 0, 0,
-				y, x, y + height - 1, x + width - 1, FALSE);
-		gnt_widget_set_position(w, x + widget->priv.x, y + widget->priv.y);
-	}
-}
-
-void gnt_box_set_alignment(GntBox *box, GntAlignment alignment)
-{
-	box->alignment = alignment;
-}
-
-void gnt_box_remove(GntBox *box, GntWidget *widget)
-{
-	box->list = g_list_remove(box->list, widget);
-	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS)
-			&& GNT_WIDGET(box)->parent == NULL && box->focus)
-	{
-		if (widget == box->active)
-		{
-			find_next_focus(box);
-			if (box->active == widget) /* There's only one widget */
-				box->active = NULL;
-		}
-		box->focus = g_list_remove(box->focus, widget);
-	}
-
-	if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(box), GNT_WIDGET_MAPPED))
-		gnt_widget_draw(GNT_WIDGET(box));
-}
-
-void gnt_box_remove_all(GntBox *box)
-{
-	g_list_foreach(box->list, (GFunc)gnt_widget_destroy, NULL);
-	g_list_free(box->list);
-	g_list_free(box->focus);
-	box->list = NULL;
-	box->focus = NULL;
-	GNT_WIDGET(box)->priv.width = 0;
-	GNT_WIDGET(box)->priv.height = 0;
-}
-
-void gnt_box_readjust(GntBox *box)
-{
-	GList *iter;
-	GntWidget *wid;
-	int width, height;
-
-	if (GNT_WIDGET(box)->parent != NULL)
-		return;
-
-	for (iter = box->list; iter; iter = iter->next)
-	{
-		GntWidget *w = iter->data;
-		if (GNT_IS_BOX(w))
-			gnt_box_readjust(GNT_BOX(w));
-		else
-		{
-			GNT_WIDGET_UNSET_FLAGS(w, GNT_WIDGET_MAPPED);
-			w->priv.width = 0;
-			w->priv.height = 0;
-		}
-	}
-
-	wid = GNT_WIDGET(box);
-	GNT_WIDGET_UNSET_FLAGS(wid, GNT_WIDGET_MAPPED);
-	wid->priv.width = 0;
-	wid->priv.height = 0;
-
-	if (wid->parent == NULL)
-	{
-		g_list_free(box->focus);
-		box->focus = NULL;
-		box->active = NULL;
-		gnt_widget_size_request(wid);
-		gnt_widget_get_size(wid, &width, &height);
-		gnt_screen_resize_widget(wid, width, height);
-		find_focusable_widget(box);
-	}
-}
-
-void gnt_box_set_fill(GntBox *box, gboolean fill)
-{
-	box->fill = fill;
-}
-
-void gnt_box_move_focus(GntBox *box, int dir)
-{
-	GntWidget *now;
-
-	if (box->active == NULL)
-	{
-		find_focusable_widget(box);
-		return;
-	}
-
-	now = box->active;
-
-	if (dir == 1)
-		find_next_focus(box);
-	else if (dir == -1)
-		find_prev_focus(box);
-
-	if (now && now != box->active)
-	{
-		gnt_widget_set_focus(now, FALSE);
-		gnt_widget_set_focus(box->active, TRUE);
-	}
-
-	if (GNT_WIDGET(box)->window)
-		gnt_widget_draw(GNT_WIDGET(box));
-}
-
-void gnt_box_give_focus_to_child(GntBox *box, GntWidget *widget)
-{
-	GList *find = g_list_find(box->focus, widget);
-	gpointer now = box->active;
-	if (find)
-		box->active = widget;
-	if (now && now != box->active)
-	{
-		gnt_widget_set_focus(now, FALSE);
-		gnt_widget_set_focus(box->active, TRUE);
-	}
-
-	if (GNT_WIDGET(box)->window)
-		gnt_widget_draw(GNT_WIDGET(box));
-}
-
--- a/console/libgnt/gntbox.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-#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;
-
-typedef enum
-{
-	/* These for vertical boxes */
-	GNT_ALIGN_LEFT,
-	GNT_ALIGN_RIGHT,
-
-	GNT_ALIGN_MID,
-
-	/* These for horizontal boxes */
-	GNT_ALIGN_TOP,
-	GNT_ALIGN_BOTTOM
-} GntAlignment;
-
-struct _GnBox
-{
-	GntWidget parent;
-
-	gboolean vertical;
-	gboolean homogeneous;
-	gboolean fill;
-	GList *list;		/* List of widgets */
-
-	GntWidget *active;
-	int pad;			/* Number of spaces to use between widgets */
-	GntAlignment alignment;  /* How are the widgets going to be aligned? */
-
-	char *title;
-	GList *focus;		/* List of widgets to cycle focus (only valid for parent boxes) */
-
-    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);
-
-#define gnt_vbox_new(homo) gnt_box_new(homo, TRUE)
-#define gnt_hbox_new(homo) gnt_box_new(homo, FALSE)
-
-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);
-
-void gnt_box_set_pad(GntBox *box, int pad);
-
-void gnt_box_set_toplevel(GntBox *box, gboolean set);
-
-void gnt_box_sync_children(GntBox *box);
-
-void gnt_box_set_alignment(GntBox *box, GntAlignment alignment);
-
-void gnt_box_remove(GntBox *box, GntWidget *widget); /* XXX: does NOT destroy widget */
-
-void gnt_box_remove_all(GntBox *box);      /* Removes AND destroys all the widgets in it */
-
-void gnt_box_readjust(GntBox *box);
-
-void gnt_box_set_fill(GntBox *box, gboolean fill);
-
-void gnt_box_move_focus(GntBox *box, int dir);  /* +1 to move forward, -1 for backward */
-
-void gnt_box_give_focus_to_child(GntBox *box, GntWidget *widget);
-
-G_END_DECLS
-
-#endif /* GNT_BOX_H */
-
--- a/console/libgnt/gntbutton.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-#include <string.h>
-
-#include "gntbutton.h"
-#include "gntutils.h"
-
-enum
-{
-	SIGS = 1,
-};
-
-static GntWidgetClass *parent_class = NULL;
-
-static void
-gnt_button_draw(GntWidget *widget)
-{
-	GntButton *button = GNT_BUTTON(widget);
-	GntColorType type;
-
-	if (gnt_widget_has_focus(widget))
-		type = GNT_COLOR_HIGHLIGHT;
-	else
-		type = GNT_COLOR_NORMAL;
-	
-	wbkgdset(widget->window, '\0' | COLOR_PAIR(type));
-	mvwaddstr(widget->window, 1, 2, button->priv->text);
-
-	GNTDEBUG;
-}
-
-static void
-gnt_button_size_request(GntWidget *widget)
-{
-	GntButton *button = GNT_BUTTON(widget);
-	gnt_util_get_text_bound(button->priv->text,
-			&widget->priv.width, &widget->priv.height);
-	widget->priv.width += 4;
-	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
-		widget->priv.height += 2;
-}
-
-static void
-gnt_button_map(GntWidget *widget)
-{
-	if (widget->priv.width == 0 || widget->priv.height == 0)
-		gnt_widget_size_request(widget);
-	GNTDEBUG;
-}
-
-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 gboolean
-gnt_button_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
-{
-	if (event == GNT_LEFT_MOUSE_DOWN) {
-		gnt_widget_activate(widget);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static void
-gnt_button_class_init(GntWidgetClass *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;
-	parent_class->clicked = gnt_button_clicked;
-
-	GNTDEBUG;
-}
-
-static void
-gnt_button_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	GntButton *button = GNT_BUTTON(instance);
-	button->priv = g_new0(GntButtonPriv, 1);
-
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X);
-
-	widget->priv.minw = 4;
-	widget->priv.minh = 3;
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * 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	*/
-			NULL					/* value_table		*/
-		};
-
-		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 = gnt_util_onscreen_fit_string(text, -1);
-	gnt_widget_set_take_focus(widget, TRUE);
-
-	return widget;
-}
-
--- a/console/libgnt/gntbutton.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-#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 */
--- a/console/libgnt/gntcheckbox.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-#include "gntcheckbox.h"
-
-enum
-{
-	SIG_TOGGLED = 1,
-	SIGS,
-};
-
-static GntButtonClass *parent_class = NULL;
-static guint signals[SIGS] = { 0 };
-
-static void
-gnt_check_box_draw(GntWidget *widget)
-{
-	GntCheckBox *cb = GNT_CHECK_BOX(widget);
-	GntColorType type;
-	char *text;
-
-	if (gnt_widget_has_focus(widget))
-		type = GNT_COLOR_HIGHLIGHT;
-	else
-		type = GNT_COLOR_NORMAL;
-	
-	wbkgdset(widget->window, '\0' | COLOR_PAIR(type));
-
-	text = g_strdup_printf("[%c]", cb->checked ? 'X' : ' ');
-	mvwaddstr(widget->window, 0, 0, text);
-	g_free(text);
-
-	wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
-	mvwaddstr(widget->window, 0, 4, GNT_BUTTON(cb)->priv->text);
-	
-	GNTDEBUG;
-}
-
-static void
-toggle_selection(GntWidget *widget)
-{
-	GNT_CHECK_BOX(widget)->checked = !GNT_CHECK_BOX(widget)->checked;
-	g_signal_emit(widget, signals[SIG_TOGGLED], 0);
-	gnt_widget_draw(widget);
-}
-
-static gboolean
-gnt_check_box_key_pressed(GntWidget *widget, const char *text)
-{
-	if (text[0] == ' ' && text[1] == '\0')
-	{
-		toggle_selection(widget);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-gnt_check_box_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
-{
-	if (event == GNT_LEFT_MOUSE_DOWN) {
-		toggle_selection(widget);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static void
-gnt_check_box_class_init(GntCheckBoxClass *klass)
-{
-	GntWidgetClass *wclass = GNT_WIDGET_CLASS(klass);
-
-	parent_class = GNT_BUTTON_CLASS(klass);
-	/*parent_class->destroy = gnt_check_box_destroy;*/
-	wclass->draw = gnt_check_box_draw;
-	/*parent_class->map = gnt_check_box_map;*/
-	/*parent_class->size_request = gnt_check_box_size_request;*/
-	wclass->key_pressed = gnt_check_box_key_pressed;
-	wclass->clicked = gnt_check_box_clicked;
-
-	signals[SIG_TOGGLED] = 
-		g_signal_new("toggled",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntCheckBoxClass, toggled),
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__VOID,
-					 G_TYPE_NONE, 0);
-	GNTDEBUG;
-}
-
-static void
-gnt_check_box_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	widget->priv.minh = 1;
-	widget->priv.minw = 4;
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * GntCheckBox API
- *****************************************************************************/
-GType
-gnt_check_box_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0)
-	{
-		static const GTypeInfo info = {
-			sizeof(GntCheckBoxClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_check_box_class_init,
-			NULL,					/* class_finalize	*/
-			NULL,					/* class_data		*/
-			sizeof(GntCheckBox),
-			0,						/* n_preallocs		*/
-			gnt_check_box_init,			/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_BUTTON,
-									  "GntCheckBox",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-GntWidget *gnt_check_box_new(const char *text)
-{
-	GntWidget *widget = g_object_new(GNT_TYPE_CHECK_BOX, NULL);
-
-	GNT_BUTTON(widget)->priv->text = g_strdup(text);
-	gnt_widget_set_take_focus(widget, TRUE);
-
-	return widget;
-}
-
-void gnt_check_box_set_checked(GntCheckBox *box, gboolean set)
-{
-	if (set != box->checked)
-	{
-		box->checked = set;
-		g_signal_emit(box, signals[SIG_TOGGLED], 0);
-	}
-}
-
-gboolean gnt_check_box_get_checked(GntCheckBox *box)
-{
-	return box->checked;
-}
-
-
-
--- a/console/libgnt/gntcheckbox.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-#ifndef GNT_CHECK_BOX_H
-#define GNT_CHECK_BOX_H
-
-#include "gntbutton.h"
-#include "gnt.h"
-#include "gntcolors.h"
-#include "gntkeys.h"
-
-#define GNT_TYPE_CHECK_BOX				(gnt_check_box_get_gtype())
-#define GNT_CHECK_BOX(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_CHECK_BOX, GntCheckBox))
-#define GNT_CHECK_BOX_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_CHECK_BOX, GntCheckBoxClass))
-#define GNT_IS_CHECK_BOX(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_CHECK_BOX))
-#define GNT_IS_CHECK_BOX_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_CHECK_BOX))
-#define GNT_CHECK_BOX_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_CHECK_BOX, GntCheckBoxClass))
-
-#define GNT_CHECK_BOX_FLAGS(obj)				(GNT_CHECK_BOX(obj)->priv.flags)
-#define GNT_CHECK_BOX_SET_FLAGS(obj, flags)		(GNT_CHECK_BOX_FLAGS(obj) |= flags)
-#define GNT_CHECK_BOX_UNSET_FLAGS(obj, flags)	(GNT_CHECK_BOX_FLAGS(obj) &= ~(flags))
-
-typedef struct _GnCheckBox			GntCheckBox;
-typedef struct _GnCheckBoxPriv		GntCheckBoxPriv;
-typedef struct _GnCheckBoxClass		GntCheckBoxClass;
-
-struct _GnCheckBox
-{
-	GntButton parent;
-	gboolean checked;
-};
-
-struct _GnCheckBoxClass
-{
-	GntButtonClass parent;
-
-	void (*toggled)(void);
-
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_check_box_get_gtype(void);
-
-GntWidget *gnt_check_box_new(const char *text);
-
-void gnt_check_box_set_checked(GntCheckBox *box, gboolean set);
-
-gboolean gnt_check_box_get_checked(GntCheckBox *box);
-
-G_END_DECLS
-
-#endif /* GNT_CHECK_BOX_H */
--- a/console/libgnt/gntclipboard.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-#include "gntclipboard.h"
-
-gchar *string;
-
-enum {
-	SIG_CLIPBOARD = 0,
-	SIGS
-};
-
-static guint signals[SIGS] = { 0 };
-
-static void
-gnt_clipboard_class_init(GntClipboardClass *klass)
-{
-	signals[SIG_CLIPBOARD] = 
-		g_signal_new("clipboard_changed",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 0,
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__POINTER,
-					 G_TYPE_NONE, 1, G_TYPE_POINTER);
-
-}
-
-/******************************************************************************
- * GntClipboard API
- *****************************************************************************/
-
-void
-gnt_clipboard_set_string(GntClipboard *clipboard, gchar *string)
-{
-	g_free(clipboard->string);
-	clipboard->string = g_strdup(string);
-	g_signal_emit(clipboard, signals[SIG_CLIPBOARD], 0, clipboard->string);
-}
-
-gchar *
-gnt_clipboard_get_string(GntClipboard *clipboard)
-{
-	return g_strdup(clipboard->string);
-}
-
-static void gnt_clipboard_init(GTypeInstance *instance, gpointer class) {
-	GntClipboard *clipboard = GNT_CLIPBOARD(instance);
-	clipboard->string = g_strdup("");
-}
-
-GType
-gnt_clipboard_get_gtype(void)
-{
-	static GType type = 0;
-
-	if (type == 0) {
-		static const GTypeInfo info = {
-			sizeof(GntClipboardClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_clipboard_class_init,
-			NULL,
-			NULL,					/* class_data		*/
-			sizeof(GntClipboard),
-			0,						/* n_preallocs		*/
-			gnt_clipboard_init,		/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(G_TYPE_OBJECT,
-									  "GntClipboard",
-									  &info, 0);
-	}
-
-	return type;
-}
--- a/console/libgnt/gntclipboard.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-#ifndef GNT_CLIPBOARD_H
-#define GNT_CLIPBOARD_H
-
-#include <stdio.h>
-#include <glib.h>
-#include <glib-object.h>
-
-#define GNT_TYPE_CLIPBOARD				(gnt_clipboard_get_gtype())
-#define GNT_CLIPBOARD(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_CLIPBOARD, GntClipboard))
-#define GNT_CLIPBOARD_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_CLIPBOARD, GntClipboardClass))
-#define GNT_IS_CLIPBOARD(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_CLIPBOARD))
-#define GNT_IS_CLIPBOARD_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_CLIPBOARD))
-#define GNT_CLIPBOARD_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_CLIPBOARD, GntClipboardClass))
-
-#define	GNTDEBUG	g_printerr("%s\n", __FUNCTION__)
-
-typedef struct _GnClipboard			GntClipboard;
-typedef struct _GnClipboardClass		GntClipboardClass;
-
-struct _GnClipboard
-{
-	GObject inherit;
-	gchar *string;
-};
-
-struct _GnClipboardClass
-{
-	GObjectClass parent;
-
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_clipboard_get_gtype(void);
-
-gchar *gnt_clipboard_get_string(GntClipboard *);
-
-void gnt_clipboard_set_string(GntClipboard *, gchar *);
-
-G_END_DECLS
-
-#endif
--- a/console/libgnt/gntcolors.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,256 +0,0 @@
-#include "config.h"
-
-#include <ncurses.h>
-
-#include "gntcolors.h"
-#include "gntstyle.h"
-
-#include <glib.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-static struct
-{
-	short r, g, b;
-} colors[GNT_TOTAL_COLORS];
-
-static void
-backup_colors()
-{
-	short i;
-	for (i = 0; i < GNT_TOTAL_COLORS; i++)
-	{
-		color_content(i, &colors[i].r,
-				&colors[i].g, &colors[i].b);
-	}
-}
-
-static gboolean
-can_use_custom_color()
-{
-	return (gnt_style_get_bool(GNT_STYLE_COLOR, FALSE) && can_change_color());
-}
-
-static void
-restore_colors()
-{
-	short i;
-	for (i = 0; i < GNT_TOTAL_COLORS; i++)
-	{
-		init_color(i, colors[i].r,
-				colors[i].g, colors[i].b);
-	}
-}
-
-void gnt_init_colors()
-{
-	static gboolean init = FALSE;
-	int defaults;
-
-	if (init)
-		return;
-	init = TRUE;
-
-	start_color();
-	defaults = use_default_colors();
-
-	if (can_use_custom_color())
-	{
-		backup_colors();
-
-		/* 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, 250, 250, 700);
-		init_color(GNT_COLOR_WHITE, 1000, 1000, 1000);
-		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_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_BLUE);
-		init_pair(GNT_COLOR_TITLE_D, GNT_COLOR_WHITE, 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);
-		init_pair(GNT_COLOR_URGENT, GNT_COLOR_WHITE, GNT_COLOR_RED);
-	}
-	else
-	{
-		int bg;
-
-		if (defaults == OK) {
-			init_pair(GNT_COLOR_NORMAL, -1, -1);
-			bg = -1;
-		} else {
-			init_pair(GNT_COLOR_NORMAL, COLOR_BLACK, COLOR_WHITE);
-			bg = COLOR_WHITE;
-		}
-		init_pair(GNT_COLOR_DISABLED, COLOR_YELLOW, bg);
-		init_pair(GNT_COLOR_URGENT, COLOR_GREEN, bg);
-
-		init_pair(GNT_COLOR_HIGHLIGHT, COLOR_WHITE, COLOR_BLUE);
-		init_pair(GNT_COLOR_SHADOW, COLOR_BLACK, COLOR_BLACK);
-		init_pair(GNT_COLOR_TITLE, COLOR_WHITE, COLOR_BLUE);
-		init_pair(GNT_COLOR_TITLE_D, COLOR_WHITE, COLOR_BLACK);
-		init_pair(GNT_COLOR_TEXT_NORMAL, COLOR_WHITE, COLOR_BLUE);
-		init_pair(GNT_COLOR_HIGHLIGHT_D, COLOR_CYAN, COLOR_BLACK);
-	}
-}
-
-void
-gnt_uninit_colors()
-{
-	if (can_use_custom_color())
-		restore_colors();
-}
-
-static int
-get_color(char *key)
-{
-	int color;
-	gboolean custom = can_use_custom_color();
-
-	key = g_strstrip(key);
-
-	if (strcmp(key, "black") == 0)
-		color = custom ? GNT_COLOR_BLACK : COLOR_BLACK;
-	else if (strcmp(key, "red") == 0)
-		color = custom ? GNT_COLOR_RED : COLOR_RED;
-	else if (strcmp(key, "green") == 0)
-		color = custom ? GNT_COLOR_GREEN : COLOR_GREEN;
-	else if (strcmp(key, "blue") == 0)
-		color = custom ? GNT_COLOR_BLUE : COLOR_BLUE;
-	else if (strcmp(key, "white") == 0)
-		color = custom ? GNT_COLOR_WHITE : COLOR_WHITE;
-	else if (strcmp(key, "gray") == 0)
-		color = custom ? GNT_COLOR_GRAY : COLOR_YELLOW;  /* eh? */
-	else if (strcmp(key, "darkgray") == 0)
-		color = custom ? GNT_COLOR_DARK_GRAY : COLOR_BLACK;
-	else if (strcmp(key, "magenta") == 0)
-		color = COLOR_MAGENTA;
-	else if (strcmp(key, "cyan") == 0)
-		color = COLOR_CYAN;
-	else
-		color = -1;
-	return color;
-}
-
-#if GLIB_CHECK_VERSION(2,6,0)
-void gnt_colors_parse(GKeyFile *kfile)
-{
-	GError *error = NULL;
-	gsize nkeys;
-	char **keys = g_key_file_get_keys(kfile, "colors", &nkeys, &error);
-
-	if (error)
-	{
-		g_printerr("GntColors: %s\n", error->message);
-		g_error_free(error);
-		error = NULL;
-	}
-	else if (nkeys)
-	{
-		gnt_init_colors();
-		while (nkeys--)
-		{
-			gsize len;
-			gchar *key = keys[nkeys];
-			char **list = g_key_file_get_string_list(kfile, "colors", key, &len, NULL);
-			if (len == 3)
-			{
-				int r = atoi(list[0]);
-				int g = atoi(list[1]);
-				int b = atoi(list[2]);
-				int color = -1;
-
-				key = g_ascii_strdown(key, -1);
-				color = get_color(key);
-				g_free(key);
-				if (color == -1)
-					continue;
-
-				init_color(color, r, g, b);
-			}
-			g_strfreev(list);
-		}
-
-		g_strfreev(keys);
-	}
-
-	gnt_color_pairs_parse(kfile);
-}
-
-void gnt_color_pairs_parse(GKeyFile *kfile)
-{
-	GError *error = NULL;
-	gsize nkeys;
-	char **keys = g_key_file_get_keys(kfile, "colorpairs", &nkeys, &error);
-
-	if (error)
-	{
-		g_printerr("GntColors: %s\n", error->message);
-		g_error_free(error);
-		return;
-	}
-	else if (nkeys)
-		gnt_init_colors();
-
-	while (nkeys--)
-	{
-		gsize len;
-		gchar *key = keys[nkeys];
-		char **list = g_key_file_get_string_list(kfile, "colorpairs", key, &len, NULL);
-		if (len == 2)
-		{
-			GntColorType type = 0;
-			gchar *fgc = g_ascii_strdown(list[0], -1);
-			gchar *bgc = g_ascii_strdown(list[1], -1);
-			int fg = get_color(fgc);
-			int bg = get_color(bgc);
-			g_free(fgc);
-			g_free(bgc);
-			if (fg == -1 || bg == -1)
-				continue;
-
-			key = g_ascii_strdown(key, -1);
-
-			if (strcmp(key, "normal") == 0)
-				type = GNT_COLOR_NORMAL;
-			else if (strcmp(key, "highlight") == 0)
-				type = GNT_COLOR_HIGHLIGHT;
-			else if (strcmp(key, "highlightd") == 0)
-				type = GNT_COLOR_HIGHLIGHT_D;
-			else if (strcmp(key, "shadow") == 0)
-				type = GNT_COLOR_SHADOW;
-			else if (strcmp(key, "title") == 0)
-				type = GNT_COLOR_TITLE;
-			else if (strcmp(key, "titled") == 0)
-				type = GNT_COLOR_TITLE_D;
-			else if (strcmp(key, "text") == 0)
-				type = GNT_COLOR_TEXT_NORMAL;
-			else if (strcmp(key, "disabled") == 0)
-				type = GNT_COLOR_DISABLED;
-			else if (strcmp(key, "urgent") == 0)
-				type = GNT_COLOR_URGENT;
-			else {
-				g_free(key);
-				continue;
-			}
-			g_free(key);
-
-			init_pair(type, fg, bg);
-		}
-		g_strfreev(list);
-	}
-
-	g_strfreev(keys);
-}
-
-#endif  /* GKeyFile */
--- a/console/libgnt/gntcolors.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-#ifndef GNT_COLORS_H
-#define GNT_COLORS_H
-
-#include <glib.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_COLOR_TITLE_D,
-	GNT_COLOR_URGENT,       /* this is for the 'urgent' windows */
-	GNT_COLORS
-} GntColorType;
-
-enum
-{
-	GNT_COLOR_BLACK = 0,
-	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(void);
-
-void gnt_uninit_colors(void);
-
-#if GLIB_CHECK_VERSION(2,6,0)
-void gnt_colors_parse(GKeyFile *kfile);
-
-void gnt_color_pairs_parse(GKeyFile *kfile);
-#endif
-
-#endif
--- a/console/libgnt/gntcombobox.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,324 +0,0 @@
-#include "gntbox.h"
-#include "gntcombobox.h"
-#include "gnttree.h"
-#include "gntmarshal.h"
-#include "gntutils.h"
-
-#include <string.h>
-
-enum
-{
-	SIG_SELECTION_CHANGED,
-	SIGS,
-};
-
-static GntWidgetClass *parent_class = NULL;
-static guint signals[SIGS] = { 0 };
-static void (*widget_lost_focus)(GntWidget *widget);
-
-static void
-set_selection(GntComboBox *box, gpointer key)
-{
-	if (box->selected != key)
-	{
-		/* XXX: make sure the key actually does exist */
-		gpointer old = box->selected;
-		box->selected = key;
-		if (GNT_WIDGET(box)->window)
-			gnt_widget_draw(GNT_WIDGET(box));
-		if (box->dropdown)
-			gnt_tree_set_selected(GNT_TREE(box->dropdown), key);
-		g_signal_emit(box, signals[SIG_SELECTION_CHANGED], 0, old, key);
-	}
-}
-
-static void
-hide_popup(GntComboBox *box, gboolean set)
-{
-	gnt_widget_set_size(box->dropdown,
-		box->dropdown->priv.width - 1, box->dropdown->priv.height);
-	if (set)
-		set_selection(box, gnt_tree_get_selection_data(GNT_TREE(box->dropdown)));
-	else
-		gnt_tree_set_selected(GNT_TREE(box->dropdown), box->selected);
-	gnt_widget_hide(box->dropdown->parent);
-}
-
-static void
-gnt_combo_box_draw(GntWidget *widget)
-{
-	GntComboBox *box = GNT_COMBO_BOX(widget);
-	char *text = NULL, *s;
-	GntColorType type;
-	int len;
-	
-	if (box->dropdown && box->selected)
-		text = gnt_tree_get_selection_text(GNT_TREE(box->dropdown));
-
-	if (text == NULL)
-		text = g_strdup("");
-
-	if (gnt_widget_has_focus(widget))
-		type = GNT_COLOR_HIGHLIGHT;
-	else
-		type = GNT_COLOR_NORMAL;
-
-	wbkgdset(widget->window, '\0' | COLOR_PAIR(type));
-
-	s = (char*)gnt_util_onscreen_width_to_pointer(text, widget->priv.width - 4, &len);
-	*s = '\0';
-
-	mvwaddstr(widget->window, 1, 1, text);
-	whline(widget->window, ' ' | COLOR_PAIR(type), widget->priv.width - 4 - len);
-	mvwaddch(widget->window, 1, widget->priv.width - 3, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL));
-	mvwaddch(widget->window, 1, widget->priv.width - 2, ACS_DARROW | COLOR_PAIR(GNT_COLOR_NORMAL));
-
-	g_free(text);
-	GNTDEBUG;
-}
-
-static void
-gnt_combo_box_size_request(GntWidget *widget)
-{
-	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
-	{
-		GntWidget *dd = GNT_COMBO_BOX(widget)->dropdown;
-		gnt_widget_size_request(dd);
-		widget->priv.height = 3;   /* For now, a combobox will have border */
-		widget->priv.width = MAX(10, dd->priv.width + 4);
-	}
-}
-
-static void
-gnt_combo_box_map(GntWidget *widget)
-{
-	if (widget->priv.width == 0 || widget->priv.height == 0)
-		gnt_widget_size_request(widget);
-	GNTDEBUG;
-}
-
-static void
-popup_dropdown(GntComboBox *box)
-{
-	GntWidget *widget = GNT_WIDGET(box);
-	GntWidget *parent = box->dropdown->parent;
-	int height = g_list_length(GNT_TREE(box->dropdown)->list);
-	int y = widget->priv.y + widget->priv.height - 1;
-	gnt_widget_set_size(box->dropdown, widget->priv.width, height + 2);
-
-	if (y + height + 2 >= getmaxy(stdscr))
-		y = widget->priv.y - height - 1;
-	gnt_widget_set_position(parent, widget->priv.x, y);
-	if (parent->window)
-	{
-		mvwin(parent->window, y, widget->priv.x);
-		wresize(parent->window, height+2, widget->priv.width);
-	}
-	parent->priv.width = widget->priv.width;
-	parent->priv.height = height + 2;
-
-	GNT_WIDGET_UNSET_FLAGS(parent, GNT_WIDGET_INVISIBLE);
-	gnt_widget_draw(parent);
-}
-
-static gboolean
-gnt_combo_box_key_pressed(GntWidget *widget, const char *text)
-{
-	GntComboBox *box = GNT_COMBO_BOX(widget);
-	if (GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED))
-	{
-		if (text[1] == 0)
-		{
-			switch (text[0])
-			{
-				case '\r':
-				case '\t':
-					hide_popup(box, TRUE);
-					return TRUE;
-				case 27:
-					hide_popup(box, FALSE);
-					return TRUE;
-			}
-		}
-		if (gnt_widget_key_pressed(box->dropdown, text))
-			return TRUE;
-	}
-	else
-	{
-		if (text[0] == 27)
-		{
-			if (strcmp(text, GNT_KEY_UP) == 0 ||
-					strcmp(text, GNT_KEY_DOWN) == 0)
-			{
-				popup_dropdown(box);
-				return TRUE;
-			}
-		}
-	}
-
-	return FALSE;
-}
-
-static void
-gnt_combo_box_destroy(GntWidget *widget)
-{
-	gnt_widget_destroy(GNT_COMBO_BOX(widget)->dropdown->parent);
-}
-
-static void
-gnt_combo_box_lost_focus(GntWidget *widget)
-{
-	GntComboBox *combo = GNT_COMBO_BOX(widget);
-	if (GNT_WIDGET_IS_FLAG_SET(combo->dropdown->parent, GNT_WIDGET_MAPPED))
-		hide_popup(combo, FALSE);
-	widget_lost_focus(widget);
-}
-
-static gboolean
-gnt_combo_box_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
-{
-	GntComboBox *box = GNT_COMBO_BOX(widget);
-	gboolean dshowing = GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED);
-
-	if (event == GNT_MOUSE_SCROLL_UP) {
-		if (dshowing)
-			gnt_widget_key_pressed(box->dropdown, GNT_KEY_UP);
-	} else if (event == GNT_MOUSE_SCROLL_DOWN) {
-		if (dshowing)
-			gnt_widget_key_pressed(box->dropdown, GNT_KEY_DOWN);
-	} else if (event == GNT_LEFT_MOUSE_DOWN) {
-		if (dshowing) {
-			hide_popup(box, TRUE);
-		} else {
-			popup_dropdown(GNT_COMBO_BOX(widget));
-		}
-	} else
-		return FALSE;
-	return TRUE;
-}
-
-static void
-gnt_combo_box_size_changed(GntWidget *widget, int oldw, int oldh)
-{
-	GntComboBox *box = GNT_COMBO_BOX(widget);
-	gnt_widget_set_size(box->dropdown, widget->priv.width - 1, box->dropdown->priv.height);
-}
-
-static void
-gnt_combo_box_class_init(GntComboBoxClass *klass)
-{
-	parent_class = GNT_WIDGET_CLASS(klass);
-
-	parent_class->destroy = gnt_combo_box_destroy;
-	parent_class->draw = gnt_combo_box_draw;
-	parent_class->map = gnt_combo_box_map;
-	parent_class->size_request = gnt_combo_box_size_request;
-	parent_class->key_pressed = gnt_combo_box_key_pressed;
-	parent_class->clicked = gnt_combo_box_clicked;
-	parent_class->size_changed = gnt_combo_box_size_changed;
-
-	widget_lost_focus = parent_class->lost_focus;
-	parent_class->lost_focus = gnt_combo_box_lost_focus;
-
-	signals[SIG_SELECTION_CHANGED] = 
-		g_signal_new("selection-changed",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 0,
-					 NULL, NULL,
-					 gnt_closure_marshal_VOID__POINTER_POINTER,
-					 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
-
-	GNTDEBUG;
-}
-
-static void
-gnt_combo_box_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *box;
-	GntWidget *widget = GNT_WIDGET(instance);
-	GntComboBox *combo = GNT_COMBO_BOX(instance);
-
-	GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance),
-			GNT_WIDGET_GROW_X | GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_NO_SHADOW);
-	combo->dropdown = gnt_tree_new();
-
-	box = gnt_box_new(FALSE, FALSE);
-	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER | GNT_WIDGET_TRANSIENT);
-	gnt_box_set_pad(GNT_BOX(box), 0);
-	gnt_box_add_widget(GNT_BOX(box), combo->dropdown);
-	
-	widget->priv.minw = 4;
-	widget->priv.minh = 3;
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * GntComboBox API
- *****************************************************************************/
-GType
-gnt_combo_box_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0)
-	{
-		static const GTypeInfo info = {
-			sizeof(GntComboBoxClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_combo_box_class_init,
-			NULL,					/* class_finalize	*/
-			NULL,					/* class_data		*/
-			sizeof(GntComboBox),
-			0,						/* n_preallocs		*/
-			gnt_combo_box_init,			/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_WIDGET,
-									  "GntComboBox",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-GntWidget *gnt_combo_box_new()
-{
-	GntWidget *widget = g_object_new(GNT_TYPE_COMBO_BOX, NULL);
-
-	return widget;
-}
-
-void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text)
-{
-	gnt_tree_add_row_last(GNT_TREE(box->dropdown), key,
-			gnt_tree_create_row(GNT_TREE(box->dropdown), text), NULL);
-	if (box->selected == NULL)
-		set_selection(box, key);
-}
-
-gpointer gnt_combo_box_get_selected_data(GntComboBox *box)
-{
-	return box->selected;
-}
-
-void gnt_combo_box_set_selected(GntComboBox *box, gpointer key)
-{
-	set_selection(box, key);
-}
-
-void gnt_combo_box_remove(GntComboBox *box, gpointer key)
-{
-	gnt_tree_remove(GNT_TREE(box->dropdown), key);
-	if (box->selected == key)
-		set_selection(box, NULL);
-}
-
-void gnt_combo_box_remove_all(GntComboBox *box)
-{
-	gnt_tree_remove_all(GNT_TREE(box->dropdown));
-	set_selection(box, NULL);
-}
-
--- a/console/libgnt/gntcombobox.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-#ifndef GNT_COMBO_BOX_H
-#define GNT_COMBO_BOX_H
-
-#include "gnt.h"
-#include "gntcolors.h"
-#include "gntkeys.h"
-#include "gntwidget.h"
-
-#define GNT_TYPE_COMBO_BOX				(gnt_combo_box_get_gtype())
-#define GNT_COMBO_BOX(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_COMBO_BOX, GntComboBox))
-#define GNT_COMBO_BOX_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_COMBO_BOX, GntComboBoxClass))
-#define GNT_IS_COMBO_BOX(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_COMBO_BOX))
-#define GNT_IS_COMBO_BOX_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_COMBO_BOX))
-#define GNT_COMBO_BOX_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_COMBO_BOX, GntComboBoxClass))
-
-#define GNT_COMBO_BOX_FLAGS(obj)				(GNT_COMBO_BOX(obj)->priv.flags)
-#define GNT_COMBO_BOX_SET_FLAGS(obj, flags)		(GNT_COMBO_BOX_FLAGS(obj) |= flags)
-#define GNT_COMBO_BOX_UNSET_FLAGS(obj, flags)	(GNT_COMBO_BOX_FLAGS(obj) &= ~(flags))
-
-typedef struct _GnComboBox			GntComboBox;
-typedef struct _GnComboBoxPriv		GntComboBoxPriv;
-typedef struct _GnComboBoxClass		GntComboBoxClass;
-
-struct _GnComboBox
-{
-	GntWidget parent;
-
-	GntWidget *dropdown;   /* This is a GntTree */
-
-	void *selected;        /* Currently selected key */
-};
-
-struct _GnComboBoxClass
-{
-	GntWidgetClass parent;
-
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_combo_box_get_gtype(void);
-
-GntWidget *gnt_combo_box_new(void);
-
-void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text);
-
-void gnt_combo_box_remove(GntComboBox *box, gpointer key);
-
-void gnt_combo_box_remove_all(GntComboBox *box);
-
-gpointer gnt_combo_box_get_selected_data(GntComboBox *box);
-
-void gnt_combo_box_set_selected(GntComboBox *box, gpointer key);
-
-G_END_DECLS
-
-#endif /* GNT_COMBO_BOX_H */
--- a/console/libgnt/gntentry.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,932 +0,0 @@
-#include <ctype.h>
-#include <string.h>
-
-#include "gntbox.h"
-#include "gntentry.h"
-#include "gntstyle.h"
-#include "gnttree.h"
-#include "gntutils.h"
-
-enum
-{
-	SIG_TEXT_CHANGED,
-	SIGS,
-};
-static guint signals[SIGS] = { 0 };
-
-static GntWidgetClass *parent_class = NULL;
-
-static void gnt_entry_set_text_internal(GntEntry *entry, const char *text);
-
-static void
-destroy_suggest(GntEntry *entry)
-{
-	if (entry->ddown)
-	{
-		gnt_widget_destroy(entry->ddown->parent);
-		entry->ddown = NULL;
-	}
-}
-
-static char *
-get_beginning_of_word(GntEntry *entry)
-{
-	char *s = entry->cursor;
-	while (s > entry->start)
-	{
-		char *t = g_utf8_find_prev_char(entry->start, s);
-		if (isspace(*t))
-			break;
-		s = t;
-	}
-	return s;
-}
-
-static gboolean
-show_suggest_dropdown(GntEntry *entry)
-{
-	char *suggest = NULL;
-	int len;
-	int offset = 0, x, y;
-	int count = 0;
-	GList *iter;
-
-	if (entry->word)
-	{
-		char *s = get_beginning_of_word(entry);
-		suggest = g_strndup(s, entry->cursor - s);
-		if (entry->scroll < s)
-			offset = gnt_util_onscreen_width(entry->scroll, s);
-	}
-	else
-		suggest = g_strdup(entry->start);
-	len = strlen(suggest);  /* Don't need to use the utf8-function here */
-	
-	if (entry->ddown == NULL)
-	{
-		GntWidget *box = gnt_vbox_new(FALSE);
-		entry->ddown = gnt_tree_new();
-		gnt_tree_set_compare_func(GNT_TREE(entry->ddown), (GCompareFunc)g_utf8_collate);
-		gnt_box_add_widget(GNT_BOX(box), entry->ddown);
-		/* XXX: Connect to the "activate" signal for the dropdown tree */
-
-		GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_TRANSIENT);
-
-		gnt_widget_get_position(GNT_WIDGET(entry), &x, &y);
-		x += offset;
-		y++;
-		if (y + 10 >= getmaxy(stdscr))
-			y -= 11;
-		gnt_widget_set_position(box, x, y);
-	}
-	else
-		gnt_tree_remove_all(GNT_TREE(entry->ddown));
-
-	for (count = 0, iter = entry->suggests; iter; iter = iter->next)
-	{
-		const char *text = iter->data;
-		if (g_ascii_strncasecmp(suggest, text, len) == 0 && strlen(text) >= len)
-		{
-			gnt_tree_add_row_after(GNT_TREE(entry->ddown), (gpointer)text,
-					gnt_tree_create_row(GNT_TREE(entry->ddown), text),
-					NULL, NULL);
-			count++;
-		}
-	}
-	g_free(suggest);
-
-	if (count == 0)
-	{
-		destroy_suggest(entry);
-		return FALSE;
-	}
-
-	gnt_widget_draw(entry->ddown->parent);
-	return TRUE;
-}
-
-static void
-gnt_entry_draw(GntWidget *widget)
-{
-	GntEntry *entry = GNT_ENTRY(widget);
-	int stop;
-	gboolean focus;
-
-	if ((focus = 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));
-
-	if (entry->masked)
-	{
-		mvwhline(widget->window, 0, 0, gnt_ascii_only() ? '*' : ACS_BULLET,
-				g_utf8_pointer_to_offset(entry->scroll, entry->end));
-	}
-	else
-		mvwprintw(widget->window, 0, 0, "%s", entry->scroll);
-
-	stop = gnt_util_onscreen_width(entry->scroll, entry->end);
-	if (stop < widget->priv.width)
-		whline(widget->window, ENTRY_CHAR, widget->priv.width - stop);
-
-	if (focus)
-		mvwchgat(widget->window, 0, gnt_util_onscreen_width(entry->scroll, entry->cursor),
-				1, A_REVERSE, GNT_COLOR_TEXT_NORMAL, NULL);
-
-	GNTDEBUG;
-}
-
-static void
-gnt_entry_size_request(GntWidget *widget)
-{
-	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
-	{
-		widget->priv.height = 1;
-		widget->priv.width = 20;
-	}
-}
-
-static void
-gnt_entry_map(GntWidget *widget)
-{
-	if (widget->priv.width == 0 || widget->priv.height == 0)
-		gnt_widget_size_request(widget);
-	GNTDEBUG;
-}
-
-static void
-entry_redraw(GntWidget *widget)
-{
-	gnt_entry_draw(widget);
-	gnt_widget_queue_update(widget);
-}
-
-static void
-entry_text_changed(GntEntry *entry)
-{
-	g_signal_emit(entry, signals[SIG_TEXT_CHANGED], 0);
-}
-
-static gboolean
-move_back(GntBindable *bind, GList *null)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	if (entry->cursor <= entry->start)
-		return FALSE;
-	entry->cursor = g_utf8_find_prev_char(entry->start, entry->cursor);
-	if (entry->cursor < entry->scroll)
-		entry->scroll = entry->cursor;
-	entry_redraw(GNT_WIDGET(entry));
-	return TRUE;
-}
-
-static gboolean
-move_forward(GntBindable *bind, GList *list)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	if (entry->cursor >= entry->end)
-		return FALSE;
-	entry->cursor = g_utf8_find_next_char(entry->cursor, NULL);
-	while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width)
-		entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
-	entry_redraw(GNT_WIDGET(entry));
-	return TRUE;
-}
-
-static gboolean
-backspace(GntBindable *bind, GList *null)
-{
-	int len;
-	GntEntry *entry = GNT_ENTRY(bind);
-
-	if (entry->cursor <= entry->start)
-		return TRUE;
-	
-	len = entry->cursor - g_utf8_find_prev_char(entry->start, entry->cursor);
-	entry->cursor -= len;
-	memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor);
-	entry->end -= len;
-
-	if (entry->scroll > entry->start)
-		entry->scroll = g_utf8_find_prev_char(entry->start, entry->scroll);
-
-	entry_redraw(GNT_WIDGET(entry));
-	if (entry->ddown)
-		show_suggest_dropdown(entry);
-	entry_text_changed(entry);
-	return TRUE;
-}
-
-static gboolean
-delkey(GntBindable *bind, GList *null)
-{
-	int len;
-	GntEntry *entry = GNT_ENTRY(bind);
-
-	if (entry->cursor >= entry->end)
-		return FALSE;
-	
-	len = g_utf8_find_next_char(entry->cursor, NULL) - entry->cursor;
-	memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor - len + 1);
-	entry->end -= len;
-	entry_redraw(GNT_WIDGET(entry));
-
-	if (entry->ddown)
-		show_suggest_dropdown(entry);
-	entry_text_changed(entry);
-	return TRUE;
-}
-
-static gboolean
-move_start(GntBindable *bind, GList *null)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	entry->scroll = entry->cursor = entry->start;
-	entry_redraw(GNT_WIDGET(entry));
-	return TRUE;
-}
-
-static gboolean
-move_end(GntBindable *bind, GList *null)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	entry->cursor = entry->end;
-	/* This should be better than this */
-	while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width)
-		entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
-	entry_redraw(GNT_WIDGET(entry));
-	return TRUE;
-}
-
-static gboolean
-history_prev(GntBindable *bind, GList *null)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	if (entry->histlength && entry->history->prev)
-	{
-		entry->history = entry->history->prev;
-		gnt_entry_set_text_internal(entry, entry->history->data);
-		destroy_suggest(entry);
-		entry_text_changed(entry);
-
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static gboolean
-history_next(GntBindable *bind, GList *null)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	if (entry->histlength && entry->history->next)
-	{
-		if (entry->history->prev == NULL)
-		{
-			/* Save the current contents */
-			char *text = g_strdup(gnt_entry_get_text(entry));
-			g_free(entry->history->data);
-			entry->history->data = text;
-		}
-
-		entry->history = entry->history->next;
-		gnt_entry_set_text_internal(entry, entry->history->data);
-		destroy_suggest(entry);
-		entry_text_changed(entry);
-
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static gboolean
-clipboard_paste(GntBindable *bind, GList *n)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	gchar *i, *text, *a, *all;
-	text = i = gnt_get_clipboard_string();
-	while (*i != '\0') {
-		i = g_utf8_next_char(i);
-		if (*i == '\r' || *i == '\n')
-			*i = ' ';
-	}
-	a = g_strndup(entry->start, entry->cursor - entry->start);
-	all = g_strconcat(a, text, entry->cursor, NULL);
-	gnt_entry_set_text_internal(entry, all);
-	g_free(a);
-	g_free(text);
-	g_free(all);
-	return TRUE;
-}
-
-static gboolean
-suggest_show(GntBindable *bind, GList *null)
-{
-	return show_suggest_dropdown(GNT_ENTRY(bind));
-}
-
-static gboolean
-suggest_next(GntBindable *bind, GList *null)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	if (entry->ddown) {
-		gnt_bindable_perform_action_named(GNT_BINDABLE(entry->ddown), "move-down", NULL);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static gboolean
-suggest_prev(GntBindable *bind, GList *null)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	if (entry->ddown) {
-		gnt_bindable_perform_action_named(GNT_BINDABLE(entry->ddown), "move-up", NULL);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static gboolean
-del_to_home(GntBindable *bind, GList *null)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	if (entry->cursor <= entry->start)
-		return TRUE;
-	memmove(entry->start, entry->cursor, entry->end - entry->cursor);
-	entry->end -= (entry->cursor - entry->start);
-	entry->cursor = entry->scroll = entry->start;
-	memset(entry->end, '\0', entry->buffer - (entry->end - entry->start));
-	entry_redraw(GNT_WIDGET(bind));
-	entry_text_changed(entry);
-	return TRUE;
-}
-
-static gboolean
-del_to_end(GntBindable *bind, GList *null)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	if (entry->end <= entry->cursor)
-		return TRUE;
-	entry->end = entry->cursor;
-	memset(entry->end, '\0', entry->buffer - (entry->end - entry->start));
-	entry_redraw(GNT_WIDGET(bind));
-	entry_text_changed(entry);
-	return TRUE;
-}
-
-#define SAME(a,b)    ((g_unichar_isalpha(a) && g_unichar_isalpha(b)) || \
-				(g_unichar_isdigit(a) && g_unichar_isdigit(b)) || \
-				(g_unichar_isspace(a) && g_unichar_isspace(b)) || \
-				(g_unichar_iswide(a) && g_unichar_iswide(b)))
-
-static const char *
-begin_word(const char *text, const char *begin)
-{
-	gunichar ch = 0;
-	while (text > begin && (!*text || g_unichar_isspace(g_utf8_get_char(text))))
-		text = g_utf8_find_prev_char(begin, text);
-	ch = g_utf8_get_char(text);
-	while ((text = g_utf8_find_prev_char(begin, text)) >= begin) {
-		gunichar cur = g_utf8_get_char(text);
-		if (!SAME(ch, cur))
-			break;
-	}
-
-	return (text ? g_utf8_find_next_char(text, NULL) : begin);
-}
-
-static const char *
-next_begin_word(const char *text, const char *end)
-{
-	gunichar ch = 0;
-	ch = g_utf8_get_char(text);
-	while ((text = g_utf8_find_next_char(text, end)) != NULL && text <= end) {
-		gunichar cur = g_utf8_get_char(text);
-		if (!SAME(ch, cur))
-			break;
-	}
-
-	while (text && text < end && g_unichar_isspace(g_utf8_get_char(text)))
-		text = g_utf8_find_next_char(text, end);
-	return (text ? text : end);
-}
-
-#undef SAME
-static gboolean
-move_back_word(GntBindable *bind, GList *null)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	const char *iter = g_utf8_find_prev_char(entry->start, entry->cursor);
-
-	if (iter < entry->start)
-		return TRUE;
-	iter = begin_word(iter, entry->start);
-	entry->cursor = (char*)iter;
-	if (entry->cursor < entry->scroll)
-		entry->scroll = entry->cursor;
-	entry_redraw(GNT_WIDGET(bind));
-	return TRUE;
-}
-
-static gboolean
-del_prev_word(GntBindable *bind, GList *null)
-{
-	GntWidget *widget = GNT_WIDGET(bind);
-	GntEntry *entry = GNT_ENTRY(bind);
-	char *iter = g_utf8_find_prev_char(entry->start, entry->cursor);
-	int count;
-
-	if (iter < entry->start)
-		return TRUE;
-	iter = (char*)begin_word(iter, entry->start);
-	count = entry->cursor - iter;
-	memmove(iter, entry->cursor, entry->end - entry->cursor);
-	entry->end -= count;
-	entry->cursor = iter;
-	if (entry->cursor <= entry->scroll) {
-		entry->scroll = entry->cursor - widget->priv.width + 2;
-		if (entry->scroll < entry->start)
-			entry->scroll = entry->start;
-	}
-	memset(entry->end, '\0', entry->buffer - (entry->end - entry->start));
-	entry_redraw(widget);
-	entry_text_changed(entry);
-
-	return TRUE;
-}
-
-static gboolean
-move_forward_word(GntBindable *bind, GList *list)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	GntWidget *widget = GNT_WIDGET(bind);
-	entry->cursor = (char *)next_begin_word(entry->cursor, entry->end);
-	while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width) {
-		entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
-	}
-	entry_redraw(widget);
-	return TRUE;
-}
-
-static gboolean
-delete_forward_word(GntBindable *bind, GList *list)
-{
-	GntEntry *entry = GNT_ENTRY(bind);
-	GntWidget *widget = GNT_WIDGET(bind);
-	char *iter = (char *)next_begin_word(entry->cursor, entry->end);
-	int len = entry->end - iter + 1;
-	if (len <= 0)
-		return TRUE;
-	memmove(entry->cursor, iter, len);
-	len = iter - entry->cursor;
-	entry->end -= len;
-	memset(entry->end, '\0', len);
-	entry_redraw(widget);
-	entry_text_changed(entry);
-	return TRUE;
-}
-
-static gboolean
-gnt_entry_key_pressed(GntWidget *widget, const char *text)
-{
-	GntEntry *entry = GNT_ENTRY(widget);
-
-	if (text[0] == 27)
-	{
-		if (text[1] == 0)
-		{
-			destroy_suggest(entry);
-			return TRUE;
-		}
-
-		return FALSE;
-	}
-	else
-	{
-		if (text[0] == '\t')
-		{
-			if (entry->ddown)
-				destroy_suggest(entry);
-			else if (entry->suggests)
-				return show_suggest_dropdown(entry);
-
-			return FALSE;
-		}
-		else if (text[0] == '\r' && entry->ddown)
-		{
-			char *text = g_strdup(gnt_tree_get_selection_data(GNT_TREE(entry->ddown)));
-			destroy_suggest(entry);
-			if (entry->word)
-			{
-				char *s = get_beginning_of_word(entry);
-				char *iter = text;
-				while (*iter && toupper(*s) == toupper(*iter))
-				{
-					*s++ = *iter++;
-				}
-				gnt_entry_key_pressed(widget, iter);
-			}
-			else
-			{
-				gnt_entry_set_text_internal(entry, text);
-			}
-			g_free(text);
-			entry_text_changed(entry);
-			return TRUE;
-		}
-
-		if (!iscntrl(text[0]))
-		{
-			const char *str, *next;
-
-			for (str = text; *str; str = next)
-			{
-				int len;
-				next = g_utf8_find_next_char(str, NULL);
-				len = next - str;
-
-				/* Valid input? */
-				/* XXX: Is it necessary to use _unichar_ variants here? */
-				if (ispunct(*str) && (entry->flag & GNT_ENTRY_FLAG_NO_PUNCT))
-					continue;
-				if (isspace(*str) && (entry->flag & GNT_ENTRY_FLAG_NO_SPACE))
-					continue;
-				if (isalpha(*str) && !(entry->flag & GNT_ENTRY_FLAG_ALPHA))
-					continue;
-				if (isdigit(*str) && !(entry->flag & GNT_ENTRY_FLAG_INT))
-					continue;
-
-				/* Reached the max? */
-				if (entry->max && g_utf8_pointer_to_offset(entry->start, entry->end) >= entry->max)
-					continue;
-
-				if (entry->end + len - entry->start >= entry->buffer)
-				{
-					/* This will cause the buffer to grow */
-					char *tmp = g_strdup(entry->start);
-					gnt_entry_set_text_internal(entry, tmp);
-					g_free(tmp);
-				}
-
-				memmove(entry->cursor + len, entry->cursor, entry->end - entry->cursor + 1);
-				entry->end += len;
-
-				while (str < next)
-				{
-					if (*str == '\r' || *str == '\n')
-						*entry->cursor = ' ';
-					else
-						*entry->cursor = *str;
-					entry->cursor++;
-					str++;
-				}
-
-				while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width)
-					entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
-
-				if (entry->ddown)
-					show_suggest_dropdown(entry);
-			}
-			entry_redraw(widget);
-			entry_text_changed(entry);
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
-static void
-gnt_entry_destroy(GntWidget *widget)
-{
-	GntEntry *entry = GNT_ENTRY(widget);
-	g_free(entry->start);
-
-	if (entry->history)
-	{
-		entry->history = g_list_first(entry->history);
-		g_list_foreach(entry->history, (GFunc)g_free, NULL);
-		g_list_free(entry->history);
-	}
-
-	if (entry->suggests)
-	{
-		g_list_foreach(entry->suggests, (GFunc)g_free, NULL);
-		g_list_free(entry->suggests);
-	}
-
-	if (entry->ddown)
-	{
-		gnt_widget_destroy(entry->ddown->parent);
-	}
-}
-
-static void
-gnt_entry_lost_focus(GntWidget *widget)
-{
-	GntEntry *entry = GNT_ENTRY(widget);
-	destroy_suggest(entry);
-	entry_redraw(widget);
-}
-
-static void
-gnt_entry_class_init(GntEntryClass *klass)
-{
-	GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass);
-	char s[2] = {erasechar(), 0};
-
-	parent_class = GNT_WIDGET_CLASS(klass);
-	parent_class->destroy = gnt_entry_destroy;
-	parent_class->draw = gnt_entry_draw;
-	parent_class->map = gnt_entry_map;
-	parent_class->size_request = gnt_entry_size_request;
-	parent_class->key_pressed = gnt_entry_key_pressed;
-	parent_class->lost_focus = gnt_entry_lost_focus;
-
-	signals[SIG_TEXT_CHANGED] =
-		g_signal_new("text_changed",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntEntryClass, text_changed),
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__VOID,
-					 G_TYPE_NONE, 0);
-
-	gnt_bindable_class_register_action(bindable, "cursor-home", move_start,
-				GNT_KEY_CTRL_A, NULL);
-	gnt_bindable_register_binding(bindable, "cursor-home", GNT_KEY_HOME, NULL);
-	gnt_bindable_class_register_action(bindable, "cursor-end", move_end,
-				GNT_KEY_CTRL_E, NULL);
-	gnt_bindable_register_binding(bindable, "cursor-end", GNT_KEY_END, NULL);
-	gnt_bindable_class_register_action(bindable, "delete-prev", backspace,
-				GNT_KEY_BACKSPACE, NULL);
-	gnt_bindable_register_binding(bindable, "delete-prev", s, NULL);
-	gnt_bindable_register_binding(bindable, "delete-prev", GNT_KEY_CTRL_H, NULL);
-	gnt_bindable_class_register_action(bindable, "delete-next", delkey,
-				GNT_KEY_DEL, NULL);
-	gnt_bindable_register_binding(bindable, "delete-next", GNT_KEY_CTRL_D, NULL);
-	gnt_bindable_class_register_action(bindable, "delete-start", del_to_home,
-				GNT_KEY_CTRL_U, NULL);
-	gnt_bindable_class_register_action(bindable, "delete-end", del_to_end,
-				GNT_KEY_CTRL_K, NULL);
-	gnt_bindable_class_register_action(bindable, "delete-prev-word", del_prev_word,
-				GNT_KEY_CTRL_W, NULL);
-	gnt_bindable_class_register_action(bindable, "cursor-prev-word", move_back_word,
-				"\033" "b", NULL);
-	gnt_bindable_class_register_action(bindable, "cursor-prev", move_back,
-				GNT_KEY_LEFT, NULL);
-	gnt_bindable_register_binding(bindable, "cursor-prev", GNT_KEY_CTRL_B, NULL);
-	gnt_bindable_class_register_action(bindable, "cursor-next", move_forward,
-				GNT_KEY_RIGHT, NULL);
-	gnt_bindable_register_binding(bindable, "cursor-next", GNT_KEY_CTRL_F, NULL);
-	gnt_bindable_class_register_action(bindable, "cursor-next-word", move_forward_word,
-				"\033" "f", NULL);
-	gnt_bindable_class_register_action(bindable, "delete-next-word", delete_forward_word,
-				"\033" "d", NULL);
-	gnt_bindable_class_register_action(bindable, "suggest-show", suggest_show,
-				"\t", NULL);
-	gnt_bindable_class_register_action(bindable, "suggest-next", suggest_next,
-				GNT_KEY_DOWN, NULL);
-	gnt_bindable_class_register_action(bindable, "suggest-prev", suggest_prev,
-				GNT_KEY_UP, NULL);
-	gnt_bindable_class_register_action(bindable, "history-prev", history_prev,
-				GNT_KEY_CTRL_DOWN, NULL);
-	gnt_bindable_class_register_action(bindable, "history-next", history_next,
-				GNT_KEY_CTRL_UP, NULL);
-	gnt_bindable_class_register_action(bindable, "clipboard-paste", clipboard_paste,
-				GNT_KEY_CTRL_V, NULL);
-
-	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
-	GNTDEBUG;
-}
-
-static void
-gnt_entry_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	GntEntry *entry = GNT_ENTRY(instance);
-
-	entry->flag = GNT_ENTRY_FLAG_ALL;
-	entry->max = 0;
-	
-	entry->histlength = 0;
-	entry->history = NULL;
-
-	entry->word = TRUE;
-	entry->always = FALSE;
-	entry->suggests = NULL;
-
-	GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry),
-			GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW | GNT_WIDGET_CAN_TAKE_FOCUS);
-	GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry), GNT_WIDGET_GROW_X);
-
-	widget->priv.minw = 3;
-	widget->priv.minh = 1;
-	
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * GntEntry API
- *****************************************************************************/
-GType
-gnt_entry_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0)
-	{
-		static const GTypeInfo info = {
-			sizeof(GntEntryClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_entry_class_init,
-			NULL,					/* class_finalize	*/
-			NULL,					/* class_data		*/
-			sizeof(GntEntry),
-			0,						/* n_preallocs		*/
-			gnt_entry_init,			/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_WIDGET,
-									  "GntEntry",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-GntWidget *gnt_entry_new(const char *text)
-{
-	GntWidget *widget = g_object_new(GNT_TYPE_ENTRY, NULL);
-	GntEntry *entry = GNT_ENTRY(widget);
-
-	gnt_entry_set_text_internal(entry, text);
-
-	return widget;
-}
-
-static void
-gnt_entry_set_text_internal(GntEntry *entry, const char *text)
-{
-	int len;
-	int scroll, cursor;
-
-	g_free(entry->start);
-
-	if (text && text[0])
-	{
-		len = strlen(text);
-	}
-	else
-	{
-		len = 0;
-	}
-
-	entry->buffer = len + 128;
-
-	scroll = entry->scroll - entry->start;
-	cursor = entry->end - entry->cursor;
-
-	entry->start = g_new0(char, entry->buffer);
-	if (text)
-		snprintf(entry->start, len + 1, "%s", text);
-	entry->end = entry->start + len;
-
-	entry->scroll = entry->start + scroll;
-	entry->cursor = entry->end - cursor;
-
-	if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(entry), GNT_WIDGET_MAPPED))
-		entry_redraw(GNT_WIDGET(entry));
-}
-
-void gnt_entry_set_text(GntEntry *entry, const char *text)
-{
-	gboolean changed = TRUE;
-	if (text == NULL && entry->start == NULL)
-		changed = FALSE;
-	if (text && entry->start && g_utf8_collate(text, entry->start) == 0)
-		changed = FALSE;
-	gnt_entry_set_text_internal(entry, text);
-	if (changed)
-		entry_text_changed(entry);
-}
-
-void gnt_entry_set_max(GntEntry *entry, int max)
-{
-	entry->max = max;
-}
-
-void gnt_entry_set_flag(GntEntry *entry, GntEntryFlag flag)
-{
-	entry->flag = flag;
-	/* XXX: Check the existing string to make sure the flags are respected? */
-}
-
-const char *gnt_entry_get_text(GntEntry *entry)
-{
-	return entry->start;
-}
-
-void gnt_entry_clear(GntEntry *entry)
-{
-	gnt_entry_set_text_internal(entry, NULL);
-	entry->scroll = entry->cursor = entry->end = entry->start;
-	entry_redraw(GNT_WIDGET(entry));
-	destroy_suggest(entry);
-	entry_text_changed(entry);
-}
-
-void gnt_entry_set_masked(GntEntry *entry, gboolean set)
-{
-	entry->masked = set;
-}
-
-void gnt_entry_add_to_history(GntEntry *entry, const char *text)
-{
-	g_return_if_fail(entry->history != NULL);   /* Need to set_history_length first */
-
-	if (g_list_length(entry->history) >= entry->histlength)
-		return;
-
-	entry->history = g_list_first(entry->history);
-	g_free(entry->history->data);
-	entry->history->data = g_strdup(text);
-	entry->history = g_list_prepend(entry->history, NULL);
-}
-
-void gnt_entry_set_history_length(GntEntry *entry, int num)
-{
-	if (num == 0)
-	{
-		entry->histlength = num;
-		if (entry->history)
-		{
-			entry->history = g_list_first(entry->history);
-			g_list_foreach(entry->history, (GFunc)g_free, NULL);
-			g_list_free(entry->history);
-			entry->history = NULL;
-		}
-		return;
-	}
-
-	if (entry->histlength == 0)
-	{
-		entry->histlength = num;
-		entry->history = g_list_append(NULL, NULL);
-		return;
-	}
-
-	if (num > 0 && num < entry->histlength)
-	{
-		GList *first, *iter;
-		int index = 0;
-		for (first = entry->history, index = 0; first->prev; first = first->prev, index++);
-		while ((iter = g_list_nth(first, num)) != NULL)
-		{
-			g_free(iter->data);
-			first = g_list_delete_link(first, iter);
-		}
-		entry->histlength = num;
-		if (index >= num)
-			entry->history = g_list_last(first);
-		return;
-	}
-
-	entry->histlength = num;
-}
-
-void gnt_entry_set_word_suggest(GntEntry *entry, gboolean word)
-{
-	entry->word = word;
-}
-
-void gnt_entry_set_always_suggest(GntEntry *entry, gboolean always)
-{
-	entry->always = always;
-}
-
-void gnt_entry_add_suggest(GntEntry *entry, const char *text)
-{
-	GList *find;
-
-	if (!text || !*text)
-		return;
-	
-	find = g_list_find_custom(entry->suggests, text, (GCompareFunc)g_utf8_collate);
-	if (find)
-		return;
-	entry->suggests = g_list_append(entry->suggests, g_strdup(text));
-}
-
-void gnt_entry_remove_suggest(GntEntry *entry, const char *text)
-{
-	GList *find = g_list_find_custom(entry->suggests, text, (GCompareFunc)g_utf8_collate);
-	if (find)
-	{
-		g_free(find->data);
-		entry->suggests = g_list_delete_link(entry->suggests, find);
-	}
-}
-
--- a/console/libgnt/gntentry.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-#ifndef GNT_ENTRY_H
-#define GNT_ENTRY_H
-
-#include "gntwidget.h"
-#include "gnt.h"
-#include "gntcolors.h"
-#include "gntkeys.h"
-
-#define GNT_TYPE_ENTRY				(gnt_entry_get_gtype())
-#define GNT_ENTRY(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_ENTRY, GntEntry))
-#define GNT_ENTRY_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_ENTRY, GntEntryClass))
-#define GNT_IS_ENTRY(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_ENTRY))
-#define GNT_IS_ENTRY_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_ENTRY))
-#define GNT_ENTRY_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_ENTRY, GntEntryClass))
-
-#define GNT_ENTRY_FLAGS(obj)				(GNT_ENTRY(obj)->priv.flags)
-#define GNT_ENTRY_SET_FLAGS(obj, flags)		(GNT_ENTRY_FLAGS(obj) |= flags)
-#define GNT_ENTRY_UNSET_FLAGS(obj, flags)	(GNT_ENTRY_FLAGS(obj) &= ~(flags))
-
-#define	ENTRY_CHAR		'_'			/* The character to use to fill in the blank places */
-
-typedef struct _GnEntry			GntEntry;
-typedef struct _GnEntryPriv		GntEntryPriv;
-typedef struct _GnEntryClass	GntEntryClass;
-
-typedef enum
-{
-	GNT_ENTRY_FLAG_ALPHA    = 1 << 0,  /* Only alpha */
-	GNT_ENTRY_FLAG_INT      = 1 << 1,  /* Only integer */
-	GNT_ENTRY_FLAG_NO_SPACE = 1 << 2,  /* No blank space is allowed */
-	GNT_ENTRY_FLAG_NO_PUNCT = 1 << 3,  /* No punctuations */
-	GNT_ENTRY_FLAG_MASK     = 1 << 4,  /* Mask the inputs */
-} GntEntryFlag;
-
-#define GNT_ENTRY_FLAG_ALL    (GNT_ENTRY_FLAG_ALPHA | GNT_ENTRY_FLAG_INT)
-
-struct _GnEntry
-{
-	GntWidget parent;
-
-	GntEntryFlag flag;
-
-	char *start;
-	char *end;
-	char *scroll;   /* Current scrolling position */
-	char *cursor;   /* Cursor location */
-	                /* 0 <= cursor - scroll < widget-width */
-	
-	size_t buffer;  /* Size of the buffer */
-	
-	int max;        /* 0 means infinite */
-	gboolean masked;
-
-	GList *history; /* History of the strings. User can use this by pressing ctrl+up/down */
-	int histlength; /* How long can the history be? */
-
-	GList *suggests;    /* List of suggestions */
-	gboolean word;      /* Are the suggestions for only a word, or for the whole thing? */
-	gboolean always;    /* Should the list of suggestions show at all times, or only on tab-press? */
-	GntWidget *ddown;   /* The dropdown with the suggested list */
-};
-
-struct _GnEntryClass
-{
-	GntWidgetClass parent;
-
-	void (*text_changed)(GntEntry *entry);
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_entry_get_gtype(void);
-
-GntWidget *gnt_entry_new(const char *text);
-
-void gnt_entry_set_max(GntEntry *entry, int max);
-
-void gnt_entry_set_text(GntEntry *entry, const char *text);
-
-void gnt_entry_set_flag(GntEntry *entry, GntEntryFlag flag);
-
-const char *gnt_entry_get_text(GntEntry *entry);
-
-void gnt_entry_clear(GntEntry *entry);
-
-void gnt_entry_set_masked(GntEntry *entry, gboolean set);
-
-void gnt_entry_add_to_history(GntEntry *entry, const char *text);
-
-void gnt_entry_set_history_length(GntEntry *entry, int num);
-
-void gnt_entry_set_word_suggest(GntEntry *entry, gboolean word);
-
-void gnt_entry_set_always_suggest(GntEntry *entry, gboolean always);
-
-void gnt_entry_add_suggest(GntEntry *entry, const char *text);
-
-void gnt_entry_remove_suggest(GntEntry *entry, const char *text);
-
-G_END_DECLS
-
-#endif /* GNT_ENTRY_H */
--- a/console/libgnt/gntkeys.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
-#include "gntkeys.h"
-
-#include <glib.h>
-#include <stdlib.h>
-#include <string.h>
-
-char *gnt_key_cup;
-char *gnt_key_cdown;
-char *gnt_key_cleft;
-char *gnt_key_cright;
-
-static const char *term;
-static GHashTable *specials;
-
-void gnt_init_keys()
-{
-	const char *controls[] = {"", "c-", "ctrl-", "ctr-", "ctl-", NULL};
-	const char *alts[] = {"", "alt-", "a-", "m-", "meta-", NULL};
-	int c, a, ch;
-	char key[32];
-
-	if (term == NULL) {
-		term = getenv("TERM");
-		if (!term)
-			term = "";  /* Just in case */
-	}
-
-	if (strcmp(term, "xterm") == 0 || strcmp(term, "rxvt") == 0) {
-		gnt_key_cup    = "\033" "[1;5A";
-		gnt_key_cdown  = "\033" "[1;5B";
-		gnt_key_cright = "\033" "[1;5C";
-		gnt_key_cleft  = "\033" "[1;5D";
-	} else if (strcmp(term, "screen") == 0 || strcmp(term, "rxvt-unicode") == 0) {
-		gnt_key_cup    = "\033" "Oa";
-		gnt_key_cdown  = "\033" "Ob";
-		gnt_key_cright = "\033" "Oc";
-		gnt_key_cleft  = "\033" "Od";
-	}
-
-	specials = g_hash_table_new(g_str_hash, g_str_equal);
-
-#define INSERT_KEY(k, code) do { \
-		g_hash_table_insert(specials, g_strdup(k), g_strdup(code)); \
-		gnt_keys_add_combination(code); \
-	} while (0)
-
-	INSERT_KEY("home",     GNT_KEY_HOME);
-	INSERT_KEY("end",      GNT_KEY_END);
-	INSERT_KEY("pageup",   GNT_KEY_PGUP);
-	INSERT_KEY("pagedown", GNT_KEY_PGDOWN);
-	INSERT_KEY("insert",   GNT_KEY_INS);
-	INSERT_KEY("delete",   GNT_KEY_DEL);
-
-	INSERT_KEY("left",   GNT_KEY_LEFT);
-	INSERT_KEY("right",  GNT_KEY_RIGHT);
-	INSERT_KEY("up",     GNT_KEY_UP);
-	INSERT_KEY("down",   GNT_KEY_DOWN);
-
-	INSERT_KEY("tab",    "\t");
-	INSERT_KEY("menu",   GNT_KEY_POPUP);
-
-	INSERT_KEY("f1",   GNT_KEY_F1);
-	INSERT_KEY("f2",   GNT_KEY_F2);
-	INSERT_KEY("f3",   GNT_KEY_F3);
-	INSERT_KEY("f4",   GNT_KEY_F4);
-	INSERT_KEY("f5",   GNT_KEY_F5);
-	INSERT_KEY("f6",   GNT_KEY_F6);
-	INSERT_KEY("f7",   GNT_KEY_F7);
-	INSERT_KEY("f8",   GNT_KEY_F8);
-	INSERT_KEY("f9",   GNT_KEY_F9);
-	INSERT_KEY("f10",  GNT_KEY_F10);
-	INSERT_KEY("f11",  GNT_KEY_F11);
-	INSERT_KEY("f12",  GNT_KEY_F12);
-
-#define REM_LENGTH  (sizeof(key) - (cur - key))
-#define INSERT_COMB(k, code) do { \
-		snprintf(key, sizeof(key), "%s%s%s", controls[c], alts[a], k);  \
-		INSERT_KEY(key, code);  \
-	} while (0);
-
-	/* Lower-case alphabets */
-	for (a = 0, c = 0; controls[c]; c++, a = 0) {
-		if (c) {
-			INSERT_COMB("up",    gnt_key_cup);
-			INSERT_COMB("down",  gnt_key_cdown);
-			INSERT_COMB("left",  gnt_key_cleft);
-			INSERT_COMB("right", gnt_key_cright);
-		}
-
-		for (a = 0; alts[a]; a++) {
-			for (ch = 0; ch < 26; ch++) {
-				char str[2] = {'a' + ch, 0}, code[4] = "\0\0\0\0";
-				int ind = 0;
-				if (a)
-					code[ind++] = '\033';
-				code[ind] = (c ? 1 : 'a') + ch;
-				INSERT_COMB(str, code);
-			}
-		}
-	}
-	c = 0;
-	for (a = 0; alts[a]; a++) {
-		/* Upper-case alphabets */
-		for (ch = 0; ch < 26; ch++) {
-			char str[2] = {'A' + ch, 0}, code[] = {'\033', 'A' + ch, 0};
-			INSERT_COMB(str, code);
-		}
-		/* Digits */
-		for (ch = 0; ch < 10; ch++) {
-			char str[2] = {'0' + ch, 0}, code[] = {'\033', '0' + ch, 0};
-			INSERT_COMB(str, code);
-		}
-	}
-}
-
-void gnt_keys_refine(char *text)
-{
-	if (*text == 27 && *(text + 1) == '[' &&
-			(*(text + 2) >= 'A' && *(text + 2) <= 'D')) {
-		/* Apparently this is necessary for urxvt and screen and xterm */
-		if (strcmp(term, "screen") == 0 || strcmp(term, "rxvt-unicode") == 0 ||
-				strcmp(term, "xterm") == 0)
-			*(text + 1) = 'O';
-	} else if (*(unsigned char*)text == 195) {
-		if (*(text + 2) == 0 && strcmp(term, "xterm") == 0) {
-			*(text) = 27;
-			*(text + 1) -= 64;  /* Say wha? */
-		}
-	}
-}
-
-const char *gnt_key_translate(const char *name)
-{
-	return g_hash_table_lookup(specials, name);
-}
-
-/**
- * The key-bindings will be saved in a tree. When a keystroke happens, GNT will
- * find the sequence that matches a binding and return the length.
- * A sequence should not be a prefix of another sequence. If it is, then only
- * the shortest one will be processed. If we want to change that, we will need
- * to allow getting the k-th prefix that matches the input, and pay attention
- * to the return value of gnt_wm_process_input in gntmain.c.
- */
-#define SIZE 256
-
-#define IS_END         1 << 0
-struct _node
-{
-	struct _node *next[SIZE];
-	int ref;
-	int flags;
-};
-
-static struct _node root = {.ref = 1, .flags = 0};
-
-static void add_path(struct _node *node, const char *path)
-{
-	struct _node *n = NULL;
-	if (!path || !*path) {
-		node->flags |= IS_END;
-		return;
-	}
-	while (*path && node->next[*path]) {
-		node = node->next[*path];
-		node->ref++;
-		path++;
-	}
-	if (!*path)
-		return;
-	n = g_new0(struct _node, 1);
-	n->ref = 1;
-	node->next[*path++] = n;
-	add_path(n, path);
-}
-
-void gnt_keys_add_combination(const char *path)
-{
-	add_path(&root, path);
-}
-
-static void del_path(struct _node *node, const char *path)
-{
-	struct _node *next = NULL;
-
-	if (!*path)
-		return;
-	next = node->next[*path];
-	if (!next)
-		return;
-	del_path(next, path + 1);
-	next->ref--;
-	if (next->ref == 0) {
-		node->next[*path] = NULL;
-		g_free(next);
-	}
-}
-
-void gnt_keys_del_combination(const char *path)
-{
-	del_path(&root, path);
-}
-
-int gnt_keys_find_combination(const char *path)
-{
-	int depth = 0;
-	struct _node *n = &root;
-
-	root.flags &= ~IS_END;
-	while (*path && n->next[*path] && !(n->flags & IS_END)) {
-		if (g_utf8_find_next_char(path, NULL) - path > 1)
-			return 0;
-		n = n->next[*path++];
-		depth++;
-	}
-
-	if (!(n->flags & IS_END))
-		depth = 0;
-	return depth;
-}
-
-static void
-print_path(struct _node *node, int depth)
-{
-	int i;
-	for (i = 0; i < SIZE; i++) {
-		if (node->next[i]) {
-			g_printerr("%*c (%d:%d)\n", depth * 4, i, node->next[i]->ref,
-						node->next[i]->flags);
-			print_path(node->next[i], depth + 1);
-		}
-	}
-}
-
-/* this is purely for debugging purposes. */
-void gnt_keys_print_combinations(void);
-void gnt_keys_print_combinations()
-{
-	g_printerr("--------\n");
-	print_path(&root, 1);
-	g_printerr("--------\n");
-}
-
--- a/console/libgnt/gntkeys.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-#ifndef GNT_KEYS_H
-#define GNT_KEYS_H
-
-#include <curses.h>
-#include <term.h>
-
-/**
- * terminfo/termcap doesn't provide all the information that I want to use, eg.
- * ctrl-up, ctrl-down etc. So I am going to hard-code some of the information
- * for some popular $TERMs
- */
-extern char *gnt_key_cup;
-extern char *gnt_key_cdown;
-extern char *gnt_key_cleft;
-extern char *gnt_key_cright;
-
-#define SAFE(x)   ((x) ? (x) : "")
-
-#define GNT_KEY_POPUP   SAFE(key_f16)   /* Apparently */
-
-/* Arrow keys */
-#define GNT_KEY_LEFT   SAFE(key_left)
-#define GNT_KEY_RIGHT  SAFE(key_right)
-#define GNT_KEY_UP     SAFE(key_up)
-#define GNT_KEY_DOWN   SAFE(key_down)
-
-#define GNT_KEY_CTRL_UP     SAFE(gnt_key_cup)
-#define GNT_KEY_CTRL_DOWN   SAFE(gnt_key_cdown)
-#define GNT_KEY_CTRL_RIGHT  SAFE(gnt_key_cright)
-#define GNT_KEY_CTRL_LEFT   SAFE(gnt_key_cleft)
-
-#define GNT_KEY_PGUP   SAFE(key_ppage)
-#define GNT_KEY_PGDOWN SAFE(key_npage)
-#define GNT_KEY_HOME   SAFE(key_home)
-#define GNT_KEY_END    SAFE(key_end)
-
-#define GNT_KEY_ENTER  carriage_return
-
-#define GNT_KEY_BACKSPACE SAFE(key_backspace)
-#define GNT_KEY_DEL    SAFE(key_dc)
-#define GNT_KEY_INS    SAFE(key_ic)
-
-#define GNT_KEY_CTRL_A     "\001"
-#define GNT_KEY_CTRL_B     "\002"
-#define GNT_KEY_CTRL_D     "\004"
-#define GNT_KEY_CTRL_E     "\005"
-#define GNT_KEY_CTRL_F     "\006"
-#define GNT_KEY_CTRL_G     "\007"
-#define GNT_KEY_CTRL_H     "\010"
-#define GNT_KEY_CTRL_I     "\011"
-#define GNT_KEY_CTRL_J     "\012"
-#define GNT_KEY_CTRL_K     "\013"
-#define GNT_KEY_CTRL_L     "\014"
-#define GNT_KEY_CTRL_M     "\012"
-#define GNT_KEY_CTRL_N     "\016"
-#define GNT_KEY_CTRL_O     "\017"
-#define GNT_KEY_CTRL_P     "\020"
-#define GNT_KEY_CTRL_R     "\022"
-#define GNT_KEY_CTRL_T     "\024"
-#define GNT_KEY_CTRL_U     "\025"
-#define GNT_KEY_CTRL_V     "\026"
-#define GNT_KEY_CTRL_W     "\027"
-#define GNT_KEY_CTRL_X     "\030"
-#define GNT_KEY_CTRL_Y     "\031"
-
-#define GNT_KEY_F1         SAFE(key_f1)
-#define GNT_KEY_F2         SAFE(key_f2)
-#define GNT_KEY_F3         SAFE(key_f3)
-#define GNT_KEY_F4         SAFE(key_f4)
-#define GNT_KEY_F5         SAFE(key_f5)
-#define GNT_KEY_F6         SAFE(key_f6)
-#define GNT_KEY_F7         SAFE(key_f7)
-#define GNT_KEY_F8         SAFE(key_f8)
-#define GNT_KEY_F9         SAFE(key_f9)
-#define GNT_KEY_F10        SAFE(key_f10)
-#define GNT_KEY_F11        SAFE(key_f11)
-#define GNT_KEY_F12        SAFE(key_f12)
-
-/**
- * This will do stuff with the terminal settings and stuff.
- */
-void gnt_init_keys(void);
-void gnt_keys_refine(char *text);
-const char *gnt_key_translate(const char *name);
-
-void gnt_keys_add_combination(const char *path);
-void gnt_keys_del_combination(const char *path);
-int gnt_keys_find_combination(const char *path);
-
-
-/* A lot of commonly used variable names are defined in <term.h>. 
- * #undef them to make life easier for everyone. */
-
-#undef columns
-#undef lines
-#undef buttons
-#undef newline
-
-#endif
--- a/console/libgnt/gntlabel.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-#include "gntlabel.h"
-#include "gntutils.h"
-
-#include <string.h>
-
-enum
-{
-	SIGS = 1,
-};
-
-static GntWidgetClass *parent_class = NULL;
-
-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);
-	chtype flag = gnt_text_format_flag_to_chtype(label->flags);
-
-	wbkgdset(widget->window, '\0' | flag);
-	mvwaddstr(widget->window, 0, 0, label->text);
-
-	GNTDEBUG;
-}
-
-static void
-gnt_label_size_request(GntWidget *widget)
-{
-	GntLabel *label = GNT_LABEL(widget);
-
-	gnt_util_get_text_bound(label->text,
-			&widget->priv.width, &widget->priv.height);
-}
-
-static void
-gnt_label_class_init(GntLabelClass *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;
-
-	GNTDEBUG;
-}
-
-static void
-gnt_label_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X);
-	widget->priv.minw = 3;
-	widget->priv.minh = 1;
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * 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	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_WIDGET,
-									  "GntLabel",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-GntWidget *gnt_label_new(const char *text)
-{
-	return gnt_label_new_with_format(text, 0);
-}
-
-GntWidget *gnt_label_new_with_format(const char *text, GntTextFormatFlags flags)
-{
-	GntWidget *widget = g_object_new(GNT_TYPE_LABEL, NULL);
-	GntLabel *label = GNT_LABEL(widget);
-
-	label->text = gnt_util_onscreen_fit_string(text, -1);
-	label->flags = flags;
-	gnt_widget_set_take_focus(widget, FALSE);
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
-
-	return widget;
-}
-
-void gnt_label_set_text(GntLabel *label, const char *text)
-{
-	g_free(label->text);
-	label->text = gnt_util_onscreen_fit_string(text, -1);
-
-	if (GNT_WIDGET(label)->window)
-	{
-		gnt_widget_hide(GNT_WIDGET(label));
-		gnt_label_size_request(GNT_WIDGET(label));
-		gnt_widget_draw(GNT_WIDGET(label));
-	}
-}
-
--- a/console/libgnt/gntlabel.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-#ifndef GNT_LABEL_H
-#define GNT_LABEL_H
-
-#include "gnt.h"
-#include "gntwidget.h"
-#include "gnttextview.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;
-	GntTextFormatFlags flags;
-
-    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);
-
-GntWidget *gnt_label_new_with_format(const char *text, GntTextFormatFlags flags);
-
-void gnt_label_set_text(GntLabel *label, const char *text);
-
-G_END_DECLS
-
-#endif /* GNT_LABEL_H */
-
--- a/console/libgnt/gntline.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-#include "gntline.h"
-
-enum
-{
-	SIGS = 1,
-};
-
-static GntWidgetClass *parent_class = NULL;
-
-static void
-gnt_line_draw(GntWidget *widget)
-{
-	GntLine *line = GNT_LINE(widget);
-	if (line->vertical)
-		mvwvline(widget->window, 1, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL),
-				widget->priv.height - 2);
-	else
-		mvwhline(widget->window, 0, 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL),
-				widget->priv.width - 2);
-}
-
-static void
-gnt_line_size_request(GntWidget *widget)
-{
-	if (GNT_LINE(widget)->vertical)
-	{
-		widget->priv.width = 1;
-		widget->priv.height = 5;
-	}
-	else
-	{
-		widget->priv.width = 5;
-		widget->priv.height = 1;
-	}
-}
-
-static void
-gnt_line_map(GntWidget *widget)
-{
-	if (widget->priv.width == 0 || widget->priv.height == 0)
-		gnt_widget_size_request(widget);
-	GNTDEBUG;
-}
-
-static void
-gnt_line_class_init(GntLineClass *klass)
-{
-	parent_class = GNT_WIDGET_CLASS(klass);
-	parent_class->draw = gnt_line_draw;
-	parent_class->map = gnt_line_map;
-	parent_class->size_request = gnt_line_size_request;
-
-	GNTDEBUG;
-}
-
-static void
-gnt_line_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER);
-	widget->priv.minw = 1;
-	widget->priv.minh = 1;
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * GntLine API
- *****************************************************************************/
-GType
-gnt_line_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0)
-	{
-		static const GTypeInfo info = {
-			sizeof(GntLineClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_line_class_init,
-			NULL,					/* class_finalize	*/
-			NULL,					/* class_data		*/
-			sizeof(GntLine),
-			0,						/* n_preallocs		*/
-			gnt_line_init,			/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_WIDGET,
-									  "GntLine",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-GntWidget *gnt_line_new(gboolean vertical)
-{
-	GntWidget *widget = g_object_new(GNT_TYPE_LINE, NULL);
-	GntLine *line = GNT_LINE(widget);
-
-	line->vertical = vertical;
-
-	if (vertical)
-	{
-		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_Y);
-	}
-	else
-	{
-		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X);
-	}
-
-	return widget;
-}
-
--- a/console/libgnt/gntline.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-#ifndef GNT_LINE_H
-#define GNT_LINE_H
-
-#include "gntwidget.h"
-#include "gnt.h"
-#include "gntcolors.h"
-#include "gntkeys.h"
-
-#define GNT_TYPE_LINE				(gnt_line_get_gtype())
-#define GNT_LINE(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_LINE, GntLine))
-#define GNT_LINE_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_LINE, GntLineClass))
-#define GNT_IS_LINE(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_LINE))
-#define GNT_IS_LINE_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_LINE))
-#define GNT_LINE_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_LINE, GntLineClass))
-
-#define GNT_LINE_FLAGS(obj)				(GNT_LINE(obj)->priv.flags)
-#define GNT_LINE_SET_FLAGS(obj, flags)		(GNT_LINE_FLAGS(obj) |= flags)
-#define GNT_LINE_UNSET_FLAGS(obj, flags)	(GNT_LINE_FLAGS(obj) &= ~(flags))
-
-typedef struct _GnLine			GntLine;
-typedef struct _GnLinePriv		GntLinePriv;
-typedef struct _GnLineClass		GntLineClass;
-
-struct _GnLine
-{
-	GntWidget parent;
-
-	gboolean vertical;
-};
-
-struct _GnLineClass
-{
-	GntWidgetClass parent;
-
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_line_get_gtype(void);
-
-#define gnt_hline_new() gnt_line_new(FALSE)
-#define gnt_vline_new() gnt_line_new(TRUE)
-
-GntWidget *gnt_line_new(gboolean vertical);
-
-G_END_DECLS
-
-#endif /* GNT_LINE_H */
--- a/console/libgnt/gntmain.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,535 +0,0 @@
-#define _GNU_SOURCE
-#if defined(__APPLE__)
-#define _XOPEN_SOURCE_EXTENDED
-#endif
-
-#include "config.h"
-
-#include <gmodule.h>
-
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include "gnt.h"
-#include "gntbox.h"
-#include "gntcolors.h"
-#include "gntclipboard.h"
-#include "gntkeys.h"
-#include "gntmenu.h"
-#include "gntstyle.h"
-#include "gnttree.h"
-#include "gntutils.h"
-#include "gntwm.h"
-
-#include <panel.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <locale.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-/**
- * Notes: Interesting functions to look at:
- * 	scr_dump, scr_init, scr_restore: for workspaces
- *
- * 	Need to wattrset for colors to use with PDCurses.
- */
-
-static GIOChannel *channel = NULL;
-
-static gboolean ascii_only;
-static gboolean mouse_enabled;
-
-static void setup_io(void);
-
-static gboolean refresh_screen();
-
-GntWM *wm;
-static GntClipboard *clipboard;
-
-#define HOLDING_ESCAPE  (escape_stuff.timer != 0)
-
-static struct {
-	int timer;
-} escape_stuff;
-
-static gboolean
-escape_timeout(gpointer data)
-{
-	gnt_wm_process_input(wm, "\033");
-	escape_stuff.timer = 0;
-	return FALSE;
-}
-
-/**
- * Mouse support:
- *  - bring a window on top if you click on its taskbar
- *  - click on the top-bar of the active window and drag+drop to move a window
- *  - click on a window to bring it to focus
- *   - allow scrolling in tree/textview on wheel-scroll event
- *   - click to activate button or select a row in tree
- *  wishlist:
- *   - have a little [X] on the windows, and clicking it will close that window.
- */
-static gboolean
-detect_mouse_action(const char *buffer)
-{
-	int x, y;
-	static enum {
-		MOUSE_NONE,
-		MOUSE_LEFT,
-		MOUSE_RIGHT,
-		MOUSE_MIDDLE
-	} button = MOUSE_NONE;
-	static GntWidget *remember = NULL;
-	static int offset = 0;
-	GntMouseEvent event;
-	GntWidget *widget = NULL;
-	PANEL *p = NULL;
-
-	if (!wm->ordered || buffer[0] != 27)
-		return FALSE;
-	
-	buffer++;
-	if (strlen(buffer) < 5)
-		return FALSE;
-
-	x = buffer[3];
-	y = buffer[4];
-	if (x < 0)	x += 256;
-	if (y < 0)	y += 256;
-	x -= 33;
-	y -= 33;
-
-	while ((p = panel_below(p)) != NULL) {
-		const GntNode *node = panel_userptr(p);
-		GntWidget *wid;
-		if (!node)
-			continue;
-		wid = node->me;
-		if (x >= wid->priv.x && x < wid->priv.x + wid->priv.width) {
-			if (y >= wid->priv.y && y < wid->priv.y + wid->priv.height) {
-				widget = wid;
-				break;
-			}
-		}
-	}
-
-	if (strncmp(buffer, "[M ", 3) == 0) {
-		/* left button down */
-		/* Bring the window you clicked on to front */
-		/* If you click on the topbar, then you can drag to move the window */
-		event = GNT_LEFT_MOUSE_DOWN;
-	} else if (strncmp(buffer, "[M\"", 3) == 0) {
-		/* right button down */
-		event = GNT_RIGHT_MOUSE_DOWN;
-	} else if (strncmp(buffer, "[M!", 3) == 0) {
-		/* middle button down */
-		event = GNT_MIDDLE_MOUSE_DOWN;
-	} else if (strncmp(buffer, "[M`", 3) == 0) {
-		/* wheel up*/
-		event = GNT_MOUSE_SCROLL_UP;
-	} else if (strncmp(buffer, "[Ma", 3) == 0) {
-		/* wheel down */
-		event = GNT_MOUSE_SCROLL_DOWN;
-	} else if (strncmp(buffer, "[M#", 3) == 0) {
-		/* button up */
-		event = GNT_MOUSE_UP;
-	} else
-		return FALSE;
-	
-	if (gnt_wm_process_click(wm, event, x, y, widget))
-		return TRUE;
-	
-	if (event == GNT_LEFT_MOUSE_DOWN && widget && widget != wm->_list.window &&
-			!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) {
-		if (widget != wm->ordered->data) {
-			gnt_wm_raise_window(wm, widget);
-		}
-		if (y == widget->priv.y) {
-			offset = x - widget->priv.x;
-			remember = widget;
-			button = MOUSE_LEFT;
-		}
-	} else if (event == GNT_MOUSE_UP) {
-		if (button == MOUSE_NONE && y == getmaxy(stdscr) - 1) {
-			/* Clicked on the taskbar */
-			int n = g_list_length(wm->list);
-			if (n) {
-				int width = getmaxx(stdscr) / n;
-				gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "switch-window-n", x/width, NULL);
-			}
-		} else if (button == MOUSE_LEFT && remember) {
-			x -= offset;
-			if (x < 0)	x = 0;
-			if (y < 0)	y = 0;
-			gnt_screen_move_widget(remember, x, y);
-		}
-		button = MOUSE_NONE;
-		remember = NULL;
-		offset = 0;
-	}
-
-	gnt_widget_clicked(widget, event, x, y);
-	return TRUE;
-}
-
-static gboolean
-io_invoke_error(GIOChannel *source, GIOCondition cond, gpointer data)
-{
-	int id = GPOINTER_TO_INT(data);
-	g_source_remove(id);
-	g_io_channel_unref(source);
-
-	channel = NULL;
-	setup_io();
-	return TRUE;
-}
-
-static gboolean
-io_invoke(GIOChannel *source, GIOCondition cond, gpointer null)
-{
-	char keys[256];
-	int rd = read(STDIN_FILENO, keys + HOLDING_ESCAPE, sizeof(keys) - 1 - HOLDING_ESCAPE);
-	char *k;
-	if (rd < 0)
-	{
-		int ch = getch(); /* This should return ERR, but let's see what it really returns */
-		endwin();
-		printf("ERROR: %s\n", strerror(errno));
-		printf("File descriptor is: %d\n\nGIOChannel is: %p\ngetch() = %d\n", STDIN_FILENO, source, ch);
-		raise(SIGABRT);
-	}
-	else if (rd == 0)
-	{
-		endwin();
-		printf("EOF\n");
-		raise(SIGABRT);
-	}
-
-	rd += HOLDING_ESCAPE;
-	keys[rd] = 0;
-	if (mouse_enabled && detect_mouse_action(keys))
-		return TRUE;
-
-	if (HOLDING_ESCAPE)
-		keys[0] = '\033';
-	k = keys;
-	while (rd) {
-		char back;
-		int p;
-
-		if (k[0] == '\033' && rd == 1) {
-			if (escape_stuff.timer) {
-				gnt_wm_process_input(wm, "\033\033");
-				g_source_remove(escape_stuff.timer);
-				escape_stuff.timer = 0;
-				break;
-			}
-			escape_stuff.timer = g_timeout_add(250, escape_timeout, NULL);
-			break;
-		}
-
-		gnt_keys_refine(k);
-		p = MAX(1, gnt_keys_find_combination(k));
-		back = k[p];
-		k[p] = '\0';
-		gnt_wm_process_input(wm, k);     /* XXX: */
-		k[p] = back;
-		rd -= p;
-		k += p;
-	}
-
-	return TRUE;
-}
-
-static void
-setup_io()
-{
-	int result;
-	channel = g_io_channel_unix_new(STDIN_FILENO);
-	g_io_channel_set_close_on_unref(channel, TRUE);
-
-#if 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 );
-#endif
-
-	result = g_io_add_watch_full(channel,  G_PRIORITY_HIGH,
-					(G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
-					io_invoke, NULL, NULL);
-	
-	g_io_add_watch_full(channel,  G_PRIORITY_HIGH,
-					(G_IO_NVAL),
-					io_invoke_error, GINT_TO_POINTER(result), NULL);
-	
-	g_io_channel_unref(channel);  /* Apparently this caused crashes for some people.
-	                                 But irssi does this, so I am going to assume the
-	                                 crashes were caused by some other stuff. */
-
-	g_printerr("gntmain: setting up IO\n");
-}
-
-static gboolean
-refresh_screen()
-{
-	gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "refresh-screen", NULL);
-	return FALSE;
-}
-
-/* Xerox */
-static void
-clean_pid(void)
-{
-	int status;
-	pid_t pid;
-
-	do {
-		pid = waitpid(-1, &status, WNOHANG);
-	} while (pid != 0 && pid != (pid_t)-1);
-
-	if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
-		char errmsg[BUFSIZ];
-		g_snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
-		perror(errmsg);
-	}
-}
-
-static void
-sighandler(int sig)
-{
-	switch (sig) {
-#ifdef SIGWINCH
-	case SIGWINCH:
-		werase(stdscr);
-		wrefresh(stdscr);
-		g_idle_add(refresh_screen, NULL);
-		signal(SIGWINCH, sighandler);
-		break;
-#endif
-	case SIGCHLD:
-		clean_pid();
-		signal(SIGCHLD, sighandler);
-		break;
-	}
-}
-
-static void
-init_wm()
-{
-	const char *name = gnt_style_get(GNT_STYLE_WM);
-	gpointer handle;
-	
-	if (name && *name) {
-		handle = g_module_open(name, G_MODULE_BIND_LAZY);
-		if (handle) {
-			gboolean (*init)(GntWM **);
-			if (g_module_symbol(handle, "gntwm_init", (gpointer)&init)) {
-				init(&wm);
-			}
-		}
-	}
-	if (wm == NULL)
-		wm = g_object_new(GNT_TYPE_WM, NULL);
-}
-
-void gnt_init()
-{
-	char *filename;
-	const char *locale;
-
-	if (channel)
-		return;
-	
-	locale = setlocale(LC_ALL, "");
-
-	setup_io();
-
-	if (locale && (strstr(locale, "UTF") || strstr(locale, "utf")))
-		ascii_only = FALSE;
-	else
-		ascii_only = TRUE;
-
-	initscr();
-	typeahead(-1);
-	noecho();
-	curs_set(0);
-
-	gnt_init_keys();
-	gnt_init_styles();
-
-	filename = g_build_filename(g_get_home_dir(), ".gntrc", NULL);
-	gnt_style_read_configure_file(filename);
-	g_free(filename);
-
-	gnt_init_colors();
-
-	wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
-	refresh();
-
-#ifdef ALL_MOUSE_EVENTS
-	if ((mouse_enabled = gnt_style_get_bool(GNT_STYLE_MOUSE, FALSE)))
-		mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
-#endif
-
-	wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
-	werase(stdscr);
-	wrefresh(stdscr);
-
-#ifdef SIGWINCH
-	signal(SIGWINCH, sighandler);
-#endif
-	signal(SIGCHLD, sighandler);
-	signal(SIGPIPE, SIG_IGN);
-
-	g_type_init();
-
-	init_wm();
-
-	clipboard = g_object_new(GNT_TYPE_CLIPBOARD, NULL);
-}
-
-void gnt_main()
-{
-	wm->loop = g_main_loop_new(NULL, FALSE);
-	g_main_loop_run(wm->loop);
-}
-
-/*********************************
- * Stuff for 'window management' *
- *********************************/
-
-void gnt_screen_occupy(GntWidget *widget)
-{
-	gnt_wm_new_window(wm, widget);
-}
-
-void gnt_screen_release(GntWidget *widget)
-{
-	gnt_wm_window_close(wm, widget);
-}
-
-void gnt_screen_update(GntWidget *widget)
-{
-	gnt_wm_update_window(wm, widget);
-}
-
-gboolean gnt_widget_has_focus(GntWidget *widget)
-{
-	GntWidget *w;
-	if (!widget)
-		return FALSE;
-	
-	if (GNT_IS_MENU(widget))
-		return TRUE;
-
-	w = widget;
-
-	while (widget->parent)
-		widget = widget->parent;
-
-	if (widget == wm->_list.window)
-		return TRUE;
-	if (wm->ordered && wm->ordered->data == widget) {
-		if (GNT_IS_BOX(widget) &&
-				(GNT_BOX(widget)->active == w || widget == w))
-			return TRUE;
-	}
-	return FALSE;
-}
-
-void gnt_widget_set_urgent(GntWidget *widget)
-{
-	while (widget->parent)
-		widget = widget->parent;
-
-	if (wm->ordered && wm->ordered->data == widget)
-		return;
-
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_URGENT);
-
-	gnt_wm_update_window(wm, widget);
-}
-
-void gnt_quit()
-{
-	g_hash_table_destroy(wm->nodes); /* XXX: */
-	update_panels();
-	doupdate();
-	gnt_uninit_colors();
-	gnt_uninit_styles();
-	endwin();
-}
-
-gboolean gnt_ascii_only()
-{
-	return ascii_only;
-}
-
-void gnt_screen_resize_widget(GntWidget *widget, int width, int height)
-{
-	gnt_wm_resize_window(wm, widget, width, height);
-}
-
-void gnt_screen_move_widget(GntWidget *widget, int x, int y)
-{
-	gnt_wm_move_window(wm, widget, x, y);
-}
-
-void gnt_screen_rename_widget(GntWidget *widget, const char *text)
-{
-	gnt_box_set_title(GNT_BOX(widget), text);
-	gnt_widget_draw(widget);
-	gnt_wm_update_window(wm, widget);
-}
-
-void gnt_register_action(const char *label, void (*callback)())
-{
-	GntAction *action = g_new0(GntAction, 1);
-	action->label = g_strdup(label);
-	action->callback = callback;
-
-	wm->acts = g_list_append(wm->acts, action);
-}
-
-static void
-reset_menu(GntWidget *widget, gpointer null)
-{
-	wm->menu = NULL;
-}
-
-gboolean gnt_screen_menu_show(gpointer newmenu)
-{
-	if (wm->menu) {
-		/* For now, if a menu is being displayed, then another menu
-		 * can NOT take over. */
-		return FALSE;
-	}
-
-	wm->menu = newmenu;
-	GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(wm->menu), GNT_WIDGET_INVISIBLE);
-	gnt_widget_draw(GNT_WIDGET(wm->menu));
-
-	g_signal_connect(G_OBJECT(wm->menu), "hide", G_CALLBACK(reset_menu), NULL);
-
-	return TRUE;
-}
-
-void gnt_set_clipboard_string(gchar *string)
-{
-	gnt_clipboard_set_string(clipboard, string);
-}
-
-GntClipboard *gnt_get_clipboard()
-{
-	return clipboard;
-}
-gchar *gnt_get_clipboard_string()
-{
-	return gnt_clipboard_get_string(clipboard);
-}
--- a/console/libgnt/gntmenu.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,317 +0,0 @@
-#include "gntmenu.h"
-#include "gntmenuitemcheck.h"
-
-#include <string.h>
-
-enum
-{
-	SIGS = 1,
-};
-
-static GntTreeClass *parent_class = NULL;
-
-static void (*org_draw)(GntWidget *wid);
-static void (*org_destroy)(GntWidget *wid);
-static void (*org_map)(GntWidget *wid);
-static gboolean (*org_key_pressed)(GntWidget *w, const char *t);
-
-static void
-gnt_menu_draw(GntWidget *widget)
-{
-	GntMenu *menu = GNT_MENU(widget);
-	GList *iter;
-	chtype type;
-	int i;
-
-	if (menu->type == GNT_MENU_TOPLEVEL) {
-		wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT));
-		werase(widget->window);
-
-		for (i = 0, iter = menu->list; iter; iter = iter->next, i++) {
-			GntMenuItem *item = GNT_MENUITEM(iter->data);
-			type = ' ' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT);
-			if (i == menu->selected)
-				type |= A_REVERSE;
-			item->priv.x = getcurx(widget->window) + widget->priv.x;
-			item->priv.y = getcury(widget->window) + widget->priv.y + 1;
-			wbkgdset(widget->window, type);
-			wprintw(widget->window, " %s   ", item->text);
-		}
-	} else {
-		org_draw(widget);
-	}
-
-	GNTDEBUG;
-}
-
-static void
-gnt_menu_size_request(GntWidget *widget)
-{
-	GntMenu *menu = GNT_MENU(widget);
-
-	if (menu->type == GNT_MENU_TOPLEVEL) {
-		widget->priv.height = 1;
-		widget->priv.width = getmaxx(stdscr);
-	} else {
-		widget->priv.height = g_list_length(menu->list) + 2;
-		widget->priv.width = 25;  /* XXX: */
-	}
-}
-
-static void
-menu_tree_add(GntMenu *menu, GntMenuItem *item, GntMenuItem *parent)
-{
-	if (GNT_IS_MENUITEM_CHECK(item)) {
-		gnt_tree_add_choice(GNT_TREE(menu), item,
-			gnt_tree_create_row(GNT_TREE(menu), item->text, " "), parent, NULL);
-		gnt_tree_set_choice(GNT_TREE(menu), item, gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item)));
-	} else
-		gnt_tree_add_row_last(GNT_TREE(menu), item,
-			gnt_tree_create_row(GNT_TREE(menu), item->text, item->submenu ? ">" : " "), parent);
-
-	if (0 && item->submenu) {
-		GntMenu *sub = GNT_MENU(item->submenu);
-		GList *iter;
-		for (iter = sub->list; iter; iter = iter->next) {
-			GntMenuItem *it = GNT_MENUITEM(iter->data);
-			menu_tree_add(menu, it, item);
-		}
-	}
-}
-
-static void
-gnt_menu_map(GntWidget *widget)
-{
-	GntMenu *menu = GNT_MENU(widget);
-
-	if (menu->type == GNT_MENU_TOPLEVEL) {
-		gnt_widget_size_request(widget);
-	} else {
-		/* Populate the tree */
-		GList *iter;
-		gnt_tree_remove_all(GNT_TREE(widget));
-		for (iter = menu->list; iter; iter = iter->next) {
-			GntMenuItem *item = GNT_MENUITEM(iter->data);
-			menu_tree_add(menu, item, NULL);
-		}
-		org_map(widget);
-		gnt_tree_adjust_columns(GNT_TREE(widget));
-	}
-	GNTDEBUG;
-}
-
-static void
-menuitem_activate(GntMenu *menu, GntMenuItem *item)
-{
-	if (item) {
-		if (item->submenu) {
-			GntMenu *sub = GNT_MENU(item->submenu);
-			menu->submenu = sub;
-			sub->type = GNT_MENU_POPUP;	/* Submenus are *never* toplevel */
-			sub->parentmenu = menu;
-			if (menu->type != GNT_MENU_TOPLEVEL) {
-				GntWidget *widget = GNT_WIDGET(menu);
-				item->priv.x = widget->priv.x + widget->priv.width - 1;
-				item->priv.y = widget->priv.y + gnt_tree_get_selection_visible_line(GNT_TREE(menu));
-			}
-			gnt_widget_set_position(GNT_WIDGET(sub), item->priv.x, item->priv.y);
-			GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(sub), GNT_WIDGET_INVISIBLE);
-			gnt_widget_draw(GNT_WIDGET(sub));
-		} else if (item->callback) {
-			item->callback(item, item->callbackdata);
-			while (menu) {
-				gnt_widget_hide(GNT_WIDGET(menu));
-				menu = menu->parentmenu;
-			}
-		}
-	}
-}
-
-static gboolean
-gnt_menu_key_pressed(GntWidget *widget, const char *text)
-{
-	GntMenu *menu = GNT_MENU(widget);
-	int current = menu->selected;
-
-	if (menu->submenu) {
-		do menu = menu->submenu; while (menu->submenu);
-		return (gnt_widget_key_pressed(GNT_WIDGET(menu), text));
-	}
-
-	if (text[0] == 27 && text[1] == 0) {
-		/* Escape closes menu */
-		GntMenu *par = menu->parentmenu;
-		if (par != NULL) {
-			par->submenu = NULL;
-			gnt_widget_hide(widget);
-		} else
-			gnt_widget_hide(widget);
-		return TRUE;
-	}
-
-	if (menu->type == GNT_MENU_TOPLEVEL) {
-		if (strcmp(text, GNT_KEY_LEFT) == 0) {
-			menu->selected--;
-			if (menu->selected < 0)
-				menu->selected = g_list_length(menu->list) - 1;
-		} else if (strcmp(text, GNT_KEY_RIGHT) == 0) {
-			menu->selected++;
-			if (menu->selected >= g_list_length(menu->list))
-				menu->selected = 0;
-		} else if (strcmp(text, GNT_KEY_ENTER) == 0) {
-			gnt_widget_activate(widget);
-		}
-
-		if (current != menu->selected) {
-			gnt_widget_draw(widget);
-			return TRUE;
-		}
-	} else {
-		return org_key_pressed(widget, text);
-	}
-
-	return FALSE;
-}
-
-static void
-gnt_menu_destroy(GntWidget *widget)
-{
-	GntMenu *menu = GNT_MENU(widget);
-	g_list_foreach(menu->list, (GFunc)g_object_unref, NULL);
-	g_list_free(menu->list);
-	org_destroy(widget);
-}
-
-static void
-gnt_menu_toggled(GntTree *tree, gpointer key)
-{
-	GntMenuItem *item = GNT_MENUITEM(key);
-	GntMenu *menu = GNT_MENU(tree);
-	gboolean check = gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item));
-	gnt_menuitem_check_set_checked(GNT_MENUITEM_CHECK(item), !check);
-	if (item->callback)
-		item->callback(item, item->callbackdata);
-	while (menu) {
-		gnt_widget_hide(GNT_WIDGET(menu));
-		menu = menu->parentmenu;
-	}
-}
-
-static void
-gnt_menu_activate(GntWidget *widget)
-{
-	GntMenu *menu = GNT_MENU(widget);
-	GntMenuItem *item;
-
-	if (menu->type == GNT_MENU_TOPLEVEL) {
-		item = g_list_nth_data(menu->list, menu->selected);
-	} else {
-		item = gnt_tree_get_selection_data(GNT_TREE(menu));
-	}
-
-	if (item) {
-		if (GNT_IS_MENUITEM_CHECK(item))
-			gnt_menu_toggled(GNT_TREE(widget), item);
-		else
-			menuitem_activate(menu, item);
-	}
-}
-
-static void
-gnt_menu_hide(GntWidget *widget)
-{
-	GntMenu *menu = GNT_MENU(widget);
-	if (menu->parentmenu)
-		menu->parentmenu->submenu = NULL;
-}
-
-static void
-gnt_menu_class_init(GntMenuClass *klass)
-{
-	GntWidgetClass *wid_class = GNT_WIDGET_CLASS(klass);
-	parent_class = GNT_TREE_CLASS(klass);
-
-	org_destroy = wid_class->destroy;
-	org_map = wid_class->map;
-	org_draw = wid_class->draw;
-	org_key_pressed = wid_class->key_pressed;
-
-	wid_class->destroy = gnt_menu_destroy;
-	wid_class->draw = gnt_menu_draw;
-	wid_class->map = gnt_menu_map;
-	wid_class->size_request = gnt_menu_size_request;
-	wid_class->key_pressed = gnt_menu_key_pressed;
-	wid_class->activate = gnt_menu_activate;
-	wid_class->hide = gnt_menu_hide;
-
-	parent_class->toggled = gnt_menu_toggled;
-
-	GNTDEBUG;
-}
-
-static void
-gnt_menu_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER |
-			GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_TRANSIENT);
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * GntMenu API
- *****************************************************************************/
-GType
-gnt_menu_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0)
-	{
-		static const GTypeInfo info = {
-			sizeof(GntMenuClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_menu_class_init,
-			NULL,					/* class_finalize	*/
-			NULL,					/* class_data		*/
-			sizeof(GntMenu),
-			0,						/* n_preallocs		*/
-			gnt_menu_init,			/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_TREE,
-									  "GntMenu",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-GntWidget *gnt_menu_new(GntMenuType type)
-{
-	GntWidget *widget = g_object_new(GNT_TYPE_MENU, NULL);
-	GntMenu *menu = GNT_MENU(widget);
-	menu->list = NULL;
-	menu->selected = 0;
-	menu->type = type;
-
-	if (type == GNT_MENU_TOPLEVEL) {
-		widget->priv.x = 0;
-		widget->priv.y = 0;
-	} else {
-		GNT_TREE(widget)->show_separator = FALSE;
-		_gnt_tree_init_internals(GNT_TREE(widget), 2);
-		gnt_tree_set_col_width(GNT_TREE(widget), 1, 1);  /* The second column is to indicate that it has a submenu */
-		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
-	}
-
-	return widget;
-}
-
-void gnt_menu_add_item(GntMenu *menu, GntMenuItem *item)
-{
-	menu->list = g_list_append(menu->list, item);
-}
-
--- a/console/libgnt/gntmenu.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-#ifndef GNT_MENU_H
-#define GNT_MENU_H
-
-#include "gnttree.h"
-#include "gntcolors.h"
-#include "gntkeys.h"
-
-#define GNT_TYPE_MENU				(gnt_menu_get_gtype())
-#define GNT_MENU(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_MENU, GntMenu))
-#define GNT_MENU_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_MENU, GntMenuClass))
-#define GNT_IS_MENU(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_MENU))
-#define GNT_IS_MENU_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_MENU))
-#define GNT_MENU_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_MENU, GntMenuClass))
-
-#define GNT_MENU_FLAGS(obj)				(GNT_MENU(obj)->priv.flags)
-#define GNT_MENU_SET_FLAGS(obj, flags)		(GNT_MENU_FLAGS(obj) |= flags)
-#define GNT_MENU_UNSET_FLAGS(obj, flags)	(GNT_MENU_FLAGS(obj) &= ~(flags))
-
-typedef struct _GnMenu			GntMenu;
-typedef struct _GnMenuPriv		GntMenuPriv;
-typedef struct _GnMenuClass		GntMenuClass;
-
-#include "gntmenuitem.h"
-
-/**
- * A toplevel-menu is displayed at the top of the screen, and it spans accross
- * the entire width of the screen.
- * A popup-menu could be displayed, for example, as a context menu for widgets.
- */
-typedef enum
-{
-	GNT_MENU_TOPLEVEL = 1,  /* Menu for a toplevel window */
-	GNT_MENU_POPUP,         /* A popup menu */
-} GntMenuType;
-
-struct _GnMenu
-{
-	GntTree parent;
-	GntMenuType type;
-	
-	GList *list;
-	int selected;
-
-	/* This will keep track of its immediate submenu which is visible so that
-	 * keystrokes can be passed to it. */
-	GntMenu *submenu;
-	GntMenu *parentmenu;
-};
-
-struct _GnMenuClass
-{
-	GntTreeClass parent;
-
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_menu_get_gtype(void);
-
-GntWidget *gnt_menu_new(GntMenuType type);
-
-void gnt_menu_add_item(GntMenu *menu, GntMenuItem *item);
-
-G_END_DECLS
-
-#endif /* GNT_MENU_H */
--- a/console/libgnt/gntmenuitem.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-#include "gntmenu.h"
-#include "gntmenuitem.h"
-
-static GObjectClass *parent_class = NULL;
-
-static void
-gnt_menuitem_destroy(GObject *obj)
-{
-	GntMenuItem *item = GNT_MENUITEM(obj);
-	g_free(item->text);
-	item->text = NULL;
-	if (item->submenu)
-		gnt_widget_destroy(GNT_WIDGET(item->submenu));
-	parent_class->dispose(obj);
-}
-
-static void
-gnt_menuitem_class_init(GntMenuItemClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-	parent_class = g_type_class_peek_parent(klass);
-
-	obj_class->dispose = gnt_menuitem_destroy;
-}
-
-static void
-gnt_menuitem_init(GTypeInstance *instance, gpointer class)
-{
-}
-
-/******************************************************************************
- * GntMenuItem API
- *****************************************************************************/
-GType
-gnt_menuitem_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0)
-	{
-		static const GTypeInfo info = {
-			sizeof(GntMenuItemClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_menuitem_class_init,
-			NULL,					/* class_finalize	*/
-			NULL,					/* class_data		*/
-			sizeof(GntMenuItem),
-			0,						/* n_preallocs		*/
-			gnt_menuitem_init,			/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(G_TYPE_OBJECT,
-									  "GntMenuItem",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-GntMenuItem *gnt_menuitem_new(const char *text)
-{
-	GObject *item = g_object_new(GNT_TYPE_MENUITEM, NULL);
-	GntMenuItem *menuitem = GNT_MENUITEM(item);
-
-	menuitem->text = g_strdup(text);
-
-	return menuitem;
-}
-
-void gnt_menuitem_set_callback(GntMenuItem *item, GntMenuItemCallback callback, gpointer data)
-{
-	item->callback = callback;
-	item->callbackdata = data;
-}
-
-void gnt_menuitem_set_submenu(GntMenuItem *item, GntMenu *menu)
-{
-	if (item->submenu)
-		gnt_widget_destroy(GNT_WIDGET(item->submenu));
-	item->submenu = menu;
-}
-
--- a/console/libgnt/gntmenuitem.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#ifndef GNT_MENUITEM_H
-#define GNT_MENUITEM_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#define GNT_TYPE_MENUITEM				(gnt_menuitem_get_gtype())
-#define GNT_MENUITEM(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_MENUITEM, GntMenuItem))
-#define GNT_MENUITEM_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_MENUITEM, GntMenuItemClass))
-#define GNT_IS_MENUITEM(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_MENUITEM))
-#define GNT_IS_MENUITEM_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_MENUITEM))
-#define GNT_MENUITEM_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_MENUITEM, GntMenuItemClass))
-
-#define GNT_MENUITEM_FLAGS(obj)				(GNT_MENUITEM(obj)->priv.flags)
-#define GNT_MENUITEM_SET_FLAGS(obj, flags)		(GNT_MENUITEM_FLAGS(obj) |= flags)
-#define GNT_MENUITEM_UNSET_FLAGS(obj, flags)	(GNT_MENUITEM_FLAGS(obj) &= ~(flags))
-
-typedef struct _GnMenuItem			GntMenuItem;
-typedef struct _GnMenuItemPriv		GntMenuItemPriv;
-typedef struct _GnMenuItemClass		GntMenuItemClass;
-
-#include "gntmenu.h"
-
-struct _GnMenuItemPriv
-{
-	/* These will be used to determine the position of the submenu */
-	int x;
-	int y;
-};
-
-typedef void (*GntMenuItemCallback)(GntMenuItem *item, gpointer data);
-
-struct _GnMenuItem
-{
-	GObject parent;
-	GntMenuItemPriv priv;
-
-	char *text;
-
-	/* A GntMenuItem can have a callback associated with it.
-	 * The callback will be activated whenever the suer selects it and presses enter (or clicks).
-	 * However, if the GntMenuItem has some child, then the callback and callbackdata will be ignored. */
-	gpointer callbackdata;
-	GntMenuItemCallback callback;
-
-	GntMenu *submenu;
-};
-
-struct _GnMenuItemClass
-{
-	GObjectClass parent;
-
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_menuitem_get_gtype(void);
-
-GntMenuItem *gnt_menuitem_new(const char *text);
-
-void gnt_menuitem_set_callback(GntMenuItem *item, GntMenuItemCallback callback, gpointer data);
-
-void gnt_menuitem_set_submenu(GntMenuItem *item, GntMenu *menu);
-
-G_END_DECLS
-
-#endif /* GNT_MENUITEM_H */
--- a/console/libgnt/gntmenuitemcheck.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-#include "gntmenuitemcheck.h"
-
-static GntMenuItemClass *parent_class = NULL;
-
-static void
-gnt_menuitem_check_class_init(GntMenuItemCheckClass *klass)
-{
-	parent_class = GNT_MENUITEM_CLASS(klass);
-
-	GNTDEBUG;
-}
-
-static void
-gnt_menuitem_check_init(GTypeInstance *instance, gpointer class)
-{
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * GntMenuItemCheck API
- *****************************************************************************/
-GType
-gnt_menuitem_check_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0)
-	{
-		static const GTypeInfo info = {
-			sizeof(GntMenuItemCheckClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_menuitem_check_class_init,
-			NULL,					/* class_finalize	*/
-			NULL,					/* class_data		*/
-			sizeof(GntMenuItemCheck),
-			0,						/* n_preallocs		*/
-			gnt_menuitem_check_init,			/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_MENUITEM,
-									  "GntMenuItemCheck",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-GntMenuItem *gnt_menuitem_check_new(const char *text)
-{
-	GntMenuItem *item = g_object_new(GNT_TYPE_MENUITEM_CHECK, NULL);
-	GntMenuItem *menuitem = GNT_MENUITEM(item);
-
-	menuitem->text = g_strdup(text);
-	return item;
-}
-
-gboolean gnt_menuitem_check_get_checked(GntMenuItemCheck *item)
-{
-		return item->checked;
-}
-
-void gnt_menuitem_check_set_checked(GntMenuItemCheck *item, gboolean set)
-{
-		item->checked = set;
-}
-
--- a/console/libgnt/gntmenuitemcheck.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-#ifndef GNT_MENUITEM_CHECK_H
-#define GNT_MENUITEM_CHECK_H
-
-#include "gnt.h"
-#include "gntcolors.h"
-#include "gntkeys.h"
-#include "gntmenuitem.h"
-
-#define GNT_TYPE_MENUITEM_CHECK				(gnt_menuitem_check_get_gtype())
-#define GNT_MENUITEM_CHECK(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_MENUITEM_CHECK, GntMenuItemCheck))
-#define GNT_MENUITEM_CHECK_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_MENUITEM_CHECK, GntMenuItemCheckClass))
-#define GNT_IS_MENUITEM_CHECK(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_MENUITEM_CHECK))
-#define GNT_IS_MENUITEM_CHECK_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_MENUITEM_CHECK))
-#define GNT_MENUITEM_CHECK_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_MENUITEM_CHECK, GntMenuItemCheckClass))
-
-#define GNT_MENUITEM_CHECK_FLAGS(obj)				(GNT_MENUITEM_CHECK(obj)->priv.flags)
-#define GNT_MENUITEM_CHECK_SET_FLAGS(obj, flags)		(GNT_MENUITEM_CHECK_FLAGS(obj) |= flags)
-#define GNT_MENUITEM_CHECK_UNSET_FLAGS(obj, flags)	(GNT_MENUITEM_CHECK_FLAGS(obj) &= ~(flags))
-
-typedef struct _GnMenuItemCheck			GntMenuItemCheck;
-typedef struct _GnMenuItemCheckPriv		GntMenuItemCheckPriv;
-typedef struct _GnMenuItemCheckClass		GntMenuItemCheckClass;
-
-struct _GnMenuItemCheck
-{
-	GntMenuItem parent;
-	gboolean checked;
-};
-
-struct _GnMenuItemCheckClass
-{
-	GntMenuItemClass parent;
-
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_menuitem_check_get_gtype(void);
-
-GntMenuItem *gnt_menuitem_check_new(const char *text);
-
-gboolean gnt_menuitem_check_get_checked(GntMenuItemCheck *item);
-
-void gnt_menuitem_check_set_checked(GntMenuItemCheck *item, gboolean set);
-
-G_END_DECLS
-
-#endif /* GNT_MENUITEM_CHECK_H */
--- a/console/libgnt/gntrc.sample	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-[general]
-shadow = 0
-
-[colors]
-black = 0; 0; 0
-red = 1000; 0; 0
-green = 0; 1000; 0
-blue = 250; 250; 700
-white = 1000; 1000; 1000
-gray = 700; 700; 700
-darkgray = 256; 256; 256
-
-[colorpairs]
-normal = black; white
-highlight = white; blue
-highlightd = black; gray
-shadow = black; darkgray
-title = white; blue
-titled = white; gray
-text = white; blue
-disabled = gray; white
--- a/console/libgnt/gntstyle.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,268 +0,0 @@
-#include "gntstyle.h"
-#include "gntcolors.h"
-
-#include <ctype.h>
-#include <string.h>
-
-#if GLIB_CHECK_VERSION(2,6,0)
-static GKeyFile *gkfile;
-#endif
-
-static char * str_styles[GNT_STYLES];
-static int int_styles[GNT_STYLES];
-static int bool_styles[GNT_STYLES];
-
-const char *gnt_style_get(GntStyle style)
-{
-	return str_styles[style];
-}
-
-gboolean gnt_style_get_bool(GntStyle style, gboolean def)
-{
-	int i;
-	const char * str;
-
-	if (bool_styles[style] != -1)
-		return bool_styles[style];
-	
-	str = gnt_style_get(style);
-
-	if (str)
-	{
-		if (strcmp(str, "false") == 0)
-			def = FALSE;
-		else if (strcmp(str, "true") == 0)
-			def = TRUE;
-		else if (sscanf(str, "%d", &i) == 1)
-		{
-			if (i)
-				def = TRUE;
-			else
-				def = FALSE;
-		}
-	}
-
-	bool_styles[style] = def;
-	return bool_styles[style];
-}
-
-static void
-refine(char *text)
-{
-	char *s = text, *t = text;
-
-	while (*s)
-	{
-		if (*s == '^' && *(s + 1) == '[')
-		{
-			*t = '\033';  /* escape */
-			s++;
-		}
-		else if (*s == '\\')
-		{
-			if (*(s + 1) == '\0')
-				*t = ' ';
-			else
-			{
-				s++;
-				if (*s == 'r' || *s == 'n')
-					*t = '\r';
-				else if (*s == 't')
-					*t = '\t';
-				else
-					*t = *s;
-			}
-		}
-		else
-			*t = *s;
-		t++;
-		s++;
-	}
-	*t = '\0';
-}
-
-static char *
-parse_key(const char *key)
-{
-	return (char *)gnt_key_translate(key);
-}
-
-void gnt_style_read_actions(GType type, GntBindableClass *klass)
-{
-#if GLIB_CHECK_VERSION(2,6,0)
-	char *name;
-	GError *error = NULL;
-
-	name = g_strdup_printf("%s::binding", g_type_name(type));
-
-	if (g_key_file_has_group(gkfile, name))
-	{
-		gsize len = 0;
-		char **keys;
-		
-		keys = g_key_file_get_keys(gkfile, name, &len, &error);
-		if (error)
-		{
-			g_printerr("GntStyle: %s\n", error->message);
-			g_error_free(error);
-			g_free(name);
-			return;
-		}
-
-		while (len--)
-		{
-			char *key, *action;
-
-			key = g_strdup(keys[len]);
-			action = g_key_file_get_string(gkfile, name, keys[len], &error);
-
-			if (error)
-			{
-				g_printerr("GntStyle: %s\n", error->message);
-				g_error_free(error);
-				error = NULL;
-			}
-			else
-			{
-				const char *keycode = parse_key(key);
-				if (keycode == NULL) {
-					g_printerr("GntStyle: Invalid key-binding %s\n", key);
-				} else {
-					gnt_bindable_register_binding(klass, action, keycode, NULL);
-				}
-			}
-			g_free(key);
-			g_free(action);
-		}
-		g_strfreev(keys);
-	}
-	g_free(name);
-#endif
-}
-
-void gnt_styles_get_keyremaps(GType type, GHashTable *hash)
-{
-#if GLIB_CHECK_VERSION(2,6,0)
-	char *name;
-	GError *error = NULL;
-	
-	name = g_strdup_printf("%s::remap", g_type_name(type));
-
-	if (g_key_file_has_group(gkfile, name))
-	{
-		gsize len = 0;
-		char **keys;
-		
-		keys = g_key_file_get_keys(gkfile, name, &len, &error);
-		if (error)
-		{
-			g_printerr("GntStyle: %s\n", error->message);
-			g_error_free(error);
-			g_free(name);
-			return;
-		}
-
-		while (len--)
-		{
-			char *key, *replace;
-
-			key = g_strdup(keys[len]);
-			replace = g_key_file_get_string(gkfile, name, keys[len], &error);
-
-			if (error)
-			{
-				g_printerr("GntStyle: %s\n", error->message);
-				g_error_free(error);
-				error = NULL;
-				g_free(key);
-			}
-			else
-			{
-				refine(key);
-				refine(replace);
-				g_hash_table_insert(hash, key, replace);
-			}
-		}
-		g_strfreev(keys);
-	}
-
-	g_free(name);
-#endif
-}
-
-#if GLIB_CHECK_VERSION(2,6,0)
-static void
-read_general_style(GKeyFile *kfile)
-{
-	GError *error = NULL;
-	gsize nkeys;
-	char **keys = g_key_file_get_keys(kfile, "general", &nkeys, &error);
-	int i;
-	struct
-	{
-		const char *style;
-		GntStyle en;
-	} styles[] = {{"shadow", GNT_STYLE_SHADOW},
-	              {"customcolor", GNT_STYLE_COLOR},
-	              {"mouse", GNT_STYLE_MOUSE},
-	              {"wm", GNT_STYLE_WM},
-	              {"remember_position", GNT_STYLE_REMPOS},
-	              {NULL, 0}};
-
-	if (error)
-	{
-		g_printerr("GntStyle: %s\n", error->message);
-		g_error_free(error);
-	}
-	else
-	{
-		for (i = 0; styles[i].style; i++)
-		{
-			error = NULL;
-			str_styles[styles[i].en] =
-					g_key_file_get_string(kfile, "general", styles[i].style, &error);
-		}
-	}
-	g_strfreev(keys);
-}
-#endif
-
-void gnt_style_read_configure_file(const char *filename)
-{
-#if GLIB_CHECK_VERSION(2,6,0)
-	GError *error = NULL;
-	gkfile = g_key_file_new();
-
-	if (!g_key_file_load_from_file(gkfile, filename, G_KEY_FILE_NONE, &error))
-	{
-		g_printerr("GntStyle: %s\n", error->message);
-		g_error_free(error);
-		return;
-	}
-	gnt_colors_parse(gkfile);
-	read_general_style(gkfile);
-#endif
-}
-
-void gnt_init_styles()
-{
-	int i;
-	for (i = 0; i < GNT_STYLES; i++)
-	{
-		str_styles[i] = NULL;
-		int_styles[i] = -1;
-		bool_styles[i] = -1;
-	}
-}
-
-void gnt_uninit_styles()
-{
-	int i;
-	for (i = 0; i < GNT_STYLES; i++)
-		g_free(str_styles[i]);
-
-#if GLIB_CHECK_VERSION(2,6,0)
-	g_key_file_free(gkfile);
-#endif
-}
-
--- a/console/libgnt/gntstyle.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#include "gnt.h"
-
-typedef enum
-{
-	GNT_STYLE_SHADOW = 0,
-	GNT_STYLE_COLOR = 1,
-	GNT_STYLE_MOUSE = 2,
-	GNT_STYLE_WM = 3,
-	GNT_STYLE_REMPOS = 4,
-	GNT_STYLES
-} GntStyle;
-
-void gnt_style_read_configure_file(const char *filename);
-
-const char *gnt_style_get(GntStyle style);
-
-gboolean gnt_style_get_bool(GntStyle style, gboolean def);
-
-/* This should be called only once for the each type */
-void gnt_styles_get_keyremaps(GType type, GHashTable *hash);
-
-void gnt_style_read_actions(GType type, GntBindableClass *klass);
-
-void gnt_init_styles(void);
-
-void gnt_uninit_styles(void);
-
--- a/console/libgnt/gnttextview.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,727 +0,0 @@
-#include "gnttextview.h"
-#include "gntutils.h"
-
-#include <string.h>
-
-enum
-{
-	SIGS = 1,
-};
-
-typedef struct
-{
-	GntTextFormatFlags tvflag;
-	chtype flags;
-	int start;
-	int end;     /* This is the next byte of the last character of this segment */
-} GntTextSegment;
-
-typedef struct
-{
-	GList *segments;         /* A list of GntTextSegments */
-	int length;              /* The current length of the line so far (ie. onscreen width) */
-	gboolean soft;           /* TRUE if it's an overflow from prev. line */
-} GntTextLine;
-
-typedef struct
-{
-	char *name;
-	int start;
-	int end;
-} GntTextTag;
-
-static GntWidgetClass *parent_class = NULL;
-
-static gchar *select_start;
-static gchar *select_end;
-static gboolean double_click;
-
-static void
-gnt_text_view_draw(GntWidget *widget)
-{
-	GntTextView *view = GNT_TEXT_VIEW(widget);
-	int i = 0;
-	GList *lines;
-	int rows, scrcol;
-
-	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;
-			char *end = view->string->str + seg->end;
-			char back = *end;
-			chtype fl = seg->flags;
-			*end = '\0';
-			if (select_start < view->string->str + seg->start && select_end > view->string->str + seg->end) {
-				fl |= A_REVERSE;
-				wattrset(widget->window, fl);
-				wprintw(widget->window, "%s", (view->string->str + seg->start));
-			} else if (select_start && select_end &&
-				((select_start >= view->string->str + seg->start && select_start <= view->string->str + seg->end) ||
-				(select_end <= view->string->str + seg->end && select_start <= view->string->str + seg->start))) {
-				char *cur = view->string->str + seg->start;
-				while (*cur != '\0') {
-					gchar *last = g_utf8_next_char(cur);
-					gchar *str;
-					if (cur >= select_start && cur <= select_end)
-						fl |= A_REVERSE;
-					else
-						fl = seg->flags;
-					str = g_strndup(cur, last - cur);
-					wattrset(widget->window, fl);
-					waddstr(widget->window, str);
-					g_free(str);
-					cur = g_utf8_next_char(cur);
-				}
-			} else {
-				wattrset(widget->window, fl);
-				wprintw(widget->window, "%s", (view->string->str + seg->start));
-			}
-			*end = back;
-		}
-		wattroff(widget->window, A_UNDERLINE | A_BLINK | A_REVERSE);
-		whline(widget->window, ' ', widget->priv.width - line->length - 1);
-	}
-
-	scrcol = widget->priv.width - 1;
-	rows = widget->priv.height - 2;
-	if (rows > 0)
-	{
-		int total = g_list_length(g_list_first(view->list));
-		int showing, position, up, down;
-
-		showing = rows * rows / total + 1;
-		showing = MIN(rows, showing);
-
-		total -= rows;
-		up = g_list_length(lines);
-		down = total - up;
-
-		position = (rows - showing) * up / MAX(1, up + down);
-		position = MAX((lines != NULL), position);
-
-		if (showing + position > rows)
-			position = rows - showing;
-		
-		if (showing + position == rows && view->list && view->list->prev)
-			position = MAX(1, rows - 1 - showing);
-		else if (showing + position < rows && view->list && !view->list->prev)
-			position = rows - showing;
-
-		mvwvline(widget->window, position + 1, scrcol,
-				ACS_CKBOARD | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D), showing);
-	}
-
-	mvwaddch(widget->window, 0, scrcol,
-			(lines ? ACS_UARROW : ' ') | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
-	mvwaddch(widget->window, widget->priv.height - 1, scrcol,
-			((view->list && view->list->prev) ? ACS_DARROW : ' ') |
-				COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
-
-	GNTDEBUG;
-}
-
-static void
-gnt_text_view_size_request(GntWidget *widget)
-{
-	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
-	{
-		gnt_widget_set_size(widget, 64, 20);
-	}
-}
-
-static void
-gnt_text_view_map(GntWidget *widget)
-{
-	if (widget->priv.width == 0 || widget->priv.height == 0)
-		gnt_widget_size_request(widget);
-	GNTDEBUG;
-}
-
-static gboolean
-gnt_text_view_key_pressed(GntWidget *widget, const char *text)
-{
-	return FALSE;
-}
-
-static void
-free_text_segment(gpointer data, gpointer null)
-{
-	GntTextSegment *seg = data;
-	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
-free_tag(gpointer data, gpointer null)
-{
-	GntTextTag *tag = data;
-	g_free(tag->name);
-	g_free(tag);
-}
-
-static void
-gnt_text_view_destroy(GntWidget *widget)
-{
-	GntTextView *view = GNT_TEXT_VIEW(widget);
-	view->list = g_list_first(view->list);
-	g_list_foreach(view->list, free_text_line, NULL);
-	g_list_free(view->list);
-	g_list_foreach(view->tags, free_tag, NULL);
-	g_list_free(view->tags);
-	g_string_free(view->string, TRUE);
-}
-
-static char *
-gnt_text_view_get_p(GntTextView *view, int x, int y)
-{
-	int i = 0;
-	GntWidget *wid = GNT_WIDGET(view);
-	GntTextLine *line;
-	GList *lines;
-	GList *segs;
-	GntTextSegment *seg;
-	gchar *pos;
-
-	y = wid->priv.height - y;
-	if (g_list_length(view->list) < y) {
-		x = 0;
-		y = g_list_length(view->list) - 1;
-	}
-
-	lines = g_list_nth(view->list, y - 1);
-	if (!lines)
-		return NULL;
-	do {
-		line = lines->data;
-		lines = lines->next;
-	} while (line && !line->segments && lines);
-
-	if (!line || !line->segments) /* no valid line */
-		return NULL;
-	segs = line->segments;
-	seg = (GntTextSegment *)segs->data;
-	pos = view->string->str + seg->start;
-	x = MIN(x, line->length);
-	while (++i <= x) {
-		gunichar *u;
-		pos = g_utf8_next_char(pos);
-		u = g_utf8_to_ucs4(pos, -1, NULL, NULL, NULL);
-		if (u && g_unichar_iswide(*u))
-			i++;
-		g_free(u);
-	}
-	return pos;
-}
-
-static GString *
-select_word_text(GntTextView *view, gchar *c)
-{
-	gchar *start = c;
-	gchar *end = c;
-	gchar *t, *endsize;
-	while ((t = g_utf8_prev_char(start))) {
-		if (!g_ascii_isspace(*t)) {
-			if (start == view->string->str)
-				break;
-			start = t;
-		} else
-			break;
-	}
-	while ((t = g_utf8_next_char(end))) {
-		if (!g_ascii_isspace(*t))
-			end = t;
-		else
-			break;
-	}
-	select_start = start;
-	select_end = end;
-	endsize = g_utf8_next_char(select_end); /* End at the correct byte */
-	return g_string_new_len(start, endsize - start);
-}
-
-static gboolean too_slow(gpointer n)
-{
-	double_click = FALSE;
-	return FALSE;
-}
-
-static gboolean
-gnt_text_view_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
-{
-	if (event == GNT_MOUSE_SCROLL_UP) {
-		gnt_text_view_scroll(GNT_TEXT_VIEW(widget), -1);
-	} else if (event == GNT_MOUSE_SCROLL_DOWN) {
-		gnt_text_view_scroll(GNT_TEXT_VIEW(widget), 1);
-	} else if (event == GNT_LEFT_MOUSE_DOWN) {
-		select_start = gnt_text_view_get_p(GNT_TEXT_VIEW(widget), x - widget->priv.x, y - widget->priv.y);
-		g_timeout_add(500, too_slow, NULL);
-	} else if (event == GNT_MOUSE_UP) {
-		if (select_start) {
-			GString *clip;
-			select_end = gnt_text_view_get_p(GNT_TEXT_VIEW(widget), x - widget->priv.x, y - widget->priv.y);
-			if (select_end < select_start) {
-				gchar *t = select_start;
-				select_start = select_end;
-				select_end = t;
-			}
-			if (select_start == select_end) {
-				if (double_click) {
-					clip = select_word_text(GNT_TEXT_VIEW(widget), select_start);
-					double_click = FALSE;
-				} else {
-					double_click = TRUE;
-					select_start = 0;
-					select_end = 0;
-					gnt_widget_draw(widget);
-					return TRUE;
-				}
-			} else {
-				gchar *endsize = g_utf8_next_char(select_end); /* End at the correct byte */
-				clip = g_string_new_len(select_start, endsize - select_start);
-			}
-			gnt_widget_draw(widget);
-			gnt_set_clipboard_string(clip->str);
-			g_string_free(clip, TRUE);
-		}
-	} else
-		return FALSE;
-	return TRUE;
-}
-
-static void
-gnt_text_view_reflow(GntTextView *view)
-{
-	/* This is pretty ugly, and inefficient. Someone do something about it. */
-	GntTextLine *line;
-	GList *back, *iter, *list;
-	GString *string;
-	int pos = 0;    /* no. of 'real' lines */
-
-	list = view->list;
-	while (list->prev) {
-		line = list->data;
-		if (!line->soft)
-			pos++;
-		list = list->prev;
-	}
-
-	back = g_list_last(view->list);
-	view->list = NULL;
-
-	string = view->string;
-	view->string = NULL;
-	gnt_text_view_clear(view);
-
-	view->string = g_string_set_size(view->string, string->len);
-	view->string->len = 0;
-	GNT_WIDGET_SET_FLAGS(GNT_WIDGET(view), GNT_WIDGET_DRAWING);
-
-	for (; back; back = back->prev) {
-		line = back->data;
-		if (back->next && !line->soft) {
-			gnt_text_view_append_text_with_flags(view, "\n", GNT_TEXT_FLAG_NORMAL);
-		}
-
-		for (iter = line->segments; iter; iter = iter->next) {
-			GntTextSegment *seg = iter->data;
-			char *start = string->str + seg->start;
-			char *end = string->str + seg->end;
-			char back = *end;
-			*end = '\0';
-			gnt_text_view_append_text_with_flags(view, start, seg->tvflag);
-			*end = back;
-		}
-		free_text_line(line, NULL);
-	}
-	g_list_free(list);
-
-	list = view->list = g_list_first(view->list);
-	/* Go back to the line that was in view before resizing started */
-	while (pos--) {
-		while (((GntTextLine*)list->data)->soft)
-			list = list->next;
-		list = list->next;
-	}
-	view->list = list;
-	GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(view), GNT_WIDGET_DRAWING);
-	if (GNT_WIDGET(view)->window)
-		gnt_widget_draw(GNT_WIDGET(view));
-	g_string_free(string, TRUE);
-}
-
-static void
-gnt_text_view_size_changed(GntWidget *widget, int w, int h)
-{
-	if (w != widget->priv.width) {
-		gnt_text_view_reflow(GNT_TEXT_VIEW(widget));
-	}
-}
-
-static void
-gnt_text_view_class_init(GntTextViewClass *klass)
-{
-	parent_class = GNT_WIDGET_CLASS(klass);
-	parent_class->destroy = gnt_text_view_destroy;
-	parent_class->draw = gnt_text_view_draw;
-	parent_class->map = gnt_text_view_map;
-	parent_class->size_request = gnt_text_view_size_request;
-	parent_class->key_pressed = gnt_text_view_key_pressed;
-	parent_class->clicked = gnt_text_view_clicked;
-	parent_class->size_changed = gnt_text_view_size_changed;
-
-	GNTDEBUG;
-}
-
-static void
-gnt_text_view_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	
-	GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), GNT_WIDGET_GROW_Y | GNT_WIDGET_GROW_X);
-
-	widget->priv.minw = 5;
-	widget->priv.minh = 2;
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * GntTextView API
- *****************************************************************************/
-GType
-gnt_text_view_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0)
-	{
-		static const GTypeInfo info = {
-			sizeof(GntTextViewClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_text_view_class_init,
-			NULL,					/* class_finalize	*/
-			NULL,					/* class_data		*/
-			sizeof(GntTextView),
-			0,						/* n_preallocs		*/
-			gnt_text_view_init,			/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_WIDGET,
-									  "GntTextView",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-GntWidget *gnt_text_view_new()
-{
-	GntWidget *widget = g_object_new(GNT_TYPE_TEXTVIEW, NULL);
-	GntTextView *view = GNT_TEXT_VIEW(widget);
-	GntTextLine *line = g_new0(GntTextLine, 1);
-
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
-
-	view->string = g_string_new(NULL);
-	view->list = g_list_append(view->list, line);
-
-	return widget;
-}
-
-void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags)
-{
-	gnt_text_view_append_text_with_tag(view, text, flags, NULL);
-}
-
-void gnt_text_view_append_text_with_tag(GntTextView *view, const char *text,
-			GntTextFormatFlags flags, const char *tagname)
-{
-	GntWidget *widget = GNT_WIDGET(view);
-	int fl = 0;
-	const char *start, *end;
-	GList *list = view->list;
-	GntTextLine *line;
-	int len;
-
-	if (text == NULL || *text == '\0')
-		return;
-
-	fl = gnt_text_format_flag_to_chtype(flags);
-
-	len = view->string->len;
-	view->string = g_string_append(view->string, text);
-
-	if (tagname) {
-		GntTextTag *tag = g_new0(GntTextTag, 1);
-		tag->name = g_strdup(tagname);
-		tag->start = len;
-		tag->end = view->string->len;
-		view->tags = g_list_append(view->tags, tag);
-	}
-
-	view->list = g_list_first(view->list);
-
-	start = end = view->string->str + len;
-
-	while (*start) {
-		GntTextSegment *seg = NULL;
-
-		if (*end == '\n' || *end == '\r') {
-			end++;
-			start = end;
-			gnt_text_view_next_line(view);
-			view->list = g_list_first(view->list);
-			continue;
-		}
-
-		line = view->list->data;
-		if (line->length == widget->priv.width - 1) {
-			/* The last added line was exactly the same width as the widget */
-			line = g_new0(GntTextLine, 1);
-			line->soft = TRUE;
-			view->list = g_list_prepend(view->list, line);
-		}
-
-		if ((end = strchr(start, '\n')) != NULL ||
-			(end = strchr(start, '\r')) != NULL) {
-			len = gnt_util_onscreen_width(start, end - 1);
-			if (len >= widget->priv.width - line->length - 1) {
-				end = NULL;
-			}
-		}
-
-		if (end == NULL)
-			end = gnt_util_onscreen_width_to_pointer(start,
-					widget->priv.width - line->length - 1, &len);
-
-		/* Try to append to the previous segment if possible */
-		if (line->segments) {
-			seg = g_list_last(line->segments)->data;
-			if (seg->flags != fl)
-				seg = NULL;
-		}
-
-		if (seg == NULL) {
-			seg = g_new0(GntTextSegment, 1);
-			seg->start = start - view->string->str;
-			seg->tvflag = flags;
-			seg->flags = fl;
-			line->segments = g_list_append(line->segments, seg);
-		}
-		seg->end = end - view->string->str;
-		line->length += len;
-
-		start = end;
-		if (*end && *end != '\n' && *end != '\r') {
-			line = g_new0(GntTextLine, 1);
-			line->soft = TRUE;
-			view->list = g_list_prepend(view->list, line);
-		}
-	}
-
-	view->list = list;
-
-	gnt_widget_draw(widget);
-}
-
-void gnt_text_view_scroll(GntTextView *view, int scroll)
-{
-	if (scroll == 0)
-	{
-		view->list = g_list_first(view->list);
-	}
-	else if (scroll > 0)
-	{
-		GList *list = g_list_nth_prev(view->list, scroll);
-		if (list == NULL)
-			list = g_list_first(view->list);
-		view->list = list;
-	}
-	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)
-{
-	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));
-}
-
-chtype gnt_text_format_flag_to_chtype(GntTextFormatFlags flags)
-{
-	chtype fl = 0;
-
-	if (flags & GNT_TEXT_FLAG_BOLD)
-		fl |= A_BOLD;
-	if (flags & GNT_TEXT_FLAG_UNDERLINE)
-		fl |= A_UNDERLINE;
-	if (flags & GNT_TEXT_FLAG_BLINK)
-		fl |= A_BLINK;
-
-	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);
-
-	return fl;
-}
-
-void gnt_text_view_clear(GntTextView *view)
-{
-	GntTextLine *line;
-
-	g_list_foreach(view->list, free_text_line, NULL);
-	g_list_free(view->list);
-	view->list = NULL;
-
-	line = g_new0(GntTextLine, 1);
-	view->list = g_list_append(view->list, line);
-	if (view->string)
-		g_string_free(view->string, TRUE);
-	view->string = g_string_new(NULL);
-
-	if (GNT_WIDGET(view)->window)
-		gnt_widget_draw(GNT_WIDGET(view));
-}
-
-int gnt_text_view_get_lines_below(GntTextView *view)
-{
-	int below = 0;
-	GList *list = view->list;
-	while ((list = list->prev))
-		++below;
-	return below;
-}
-
-int gnt_text_view_get_lines_above(GntTextView *view)
-{
-	int above = 0;
-	GList *list = view->list;
-	list = g_list_nth(view->list, GNT_WIDGET(view)->priv.height);
-	if (!list)
-		return 0;
-	while ((list = list->next))
-		++above;
-	return above;
-}
-
-/**
- * XXX: There are quite possibly more than a few bugs here.
- */
-int gnt_text_view_tag_change(GntTextView *view, const char *name, const char *text, gboolean all)
-{
-	GList *alllines = g_list_first(view->list);
-	GList *list, *next, *iter, *inext;
-	const int text_length = text ? strlen(text) : 0;
-	int count = 0;
-	for (list = view->tags; list; list = next) {
-		GntTextTag *tag = list->data;
-		next = list->next;
-		if (strcmp(tag->name, name) == 0) {
-			int change;
-			char *before, *after;
-
-			count++;
-
-			before = g_strndup(view->string->str, tag->start);
-			after = g_strdup(view->string->str + tag->end);
-			change = (tag->end - tag->start) - text_length;
-
-			g_string_printf(view->string, "%s%s%s", before, text ? text : "", after);
-			g_free(before);
-			g_free(after);
-
-			/* Update the offsets of the next tags */
-			for (iter = next; iter; iter = iter->next) {
-				GntTextTag *t = iter->data;
-				t->start -= change;
-				t->end -= change;
-			}
-
-			/* Update the offsets of the segments */
-			for (iter = alllines; iter; iter = inext) {
-				GList *segs, *snext;
-				GntTextLine *line = iter->data;
-				inext = iter->next;
-				for (segs = line->segments; segs; segs = snext) {
-					GntTextSegment *seg = segs->data;
-					snext = segs->next;
-					if (seg->start >= tag->end) {
-						/* The segment is somewhere after the tag */
-						seg->start -= change;
-						seg->end -= change;
-					} else if (seg->end <= tag->start) {
-						/* This segment is somewhere in front of the tag */
-					} else if (seg->start >= tag->start) {
-						/* This segment starts in the middle of the tag */
-						if (text == NULL) {
-							free_text_segment(seg, NULL);
-							line->segments = g_list_delete_link(line->segments, segs);
-							if (line->segments == NULL) {
-								free_text_line(line, NULL);
-								if (view->list == iter) {
-									if (inext)
-										view->list = inext;
-									else
-										view->list = iter->prev;
-								}
-								alllines = g_list_delete_link(alllines, iter);
-							}
-						} else {
-							/* XXX: (null) */
-							seg->start = tag->start;
-							seg->end = tag->end - change;
-						}
-						line->length -= change;
-						/* XXX: Make things work if the tagged text spans over several lines. */
-					} else {
-						/* XXX: handle the rest of the conditions */
-						g_printerr("WTF! This needs to be handled properly!!\n");
-					}
-				}
-			}
-			if (text == NULL) {
-				/* Remove the tag */
-				view->tags = g_list_delete_link(view->tags, list);
-				free_tag(tag, NULL);
-			} else {
-				tag->end -= change;
-			}
-			if (!all)
-				break;
-		}
-	}
-	return count;
-}
-
--- a/console/libgnt/gnttextview.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-#ifndef GNT_TEXT_VIEW_H
-#define GNT_TEXT_VIEW_H
-
-#include "gntwidget.h"
-#include "gnt.h"
-#include "gntcolors.h"
-#include "gntkeys.h"
-
-#define GNT_TYPE_TEXTVIEW				(gnt_text_view_get_gtype())
-#define GNT_TEXT_VIEW(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_TEXTVIEW, GntTextView))
-#define GNT_TEXT_VIEW_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_TEXTVIEW, GntTextViewClass))
-#define GNT_IS_TEXTVIEW(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_TEXTVIEW))
-#define GNT_IS_TEXTVIEW_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_TEXTVIEW))
-#define GNT_TEXT_VIEW_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_TEXTVIEW, GntTextViewClass))
-
-#define GNT_TEXT_VIEW_FLAGS(obj)				(GNT_TEXT_VIEW(obj)->priv.flags)
-#define GNT_TEXT_VIEW_SET_FLAGS(obj, flags)		(GNT_TEXT_VIEW_FLAGS(obj) |= flags)
-#define GNT_TEXT_VIEW_UNSET_FLAGS(obj, flags)	(GNT_TEXT_VIEW_FLAGS(obj) &= ~(flags))
-
-typedef struct _GnTextView			GntTextView;
-typedef struct _GnTextViewPriv		GntTextViewPriv;
-typedef struct _GnTextViewClass		GntTextViewClass;
-
-struct _GnTextView
-{
-	GntWidget parent;
-
-	GString *string;
-	GList *list;        /* List of GntTextLine */
-
-	GList *tags;       /* A list of tags */
-};
-
-typedef enum
-{
-	GNT_TEXT_FLAG_NORMAL      = 0,
-	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,
-} GntTextFormatFlags;
-
-struct _GnTextViewClass
-{
-	GntWidgetClass parent;
-
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_text_view_get_gtype(void);
-
-/* XXX: For now, don't set a textview to have any border.
- *      If you want borders real bad, put it in a box. */
-GntWidget *gnt_text_view_new(void);
-
-/* scroll > 0 means scroll up, < 0 means scroll down, == 0 means scroll to the end */
-void gnt_text_view_scroll(GntTextView *view, int scroll);
-
-void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags);
-
-void gnt_text_view_append_text_with_tag(GntTextView *view, const char *text, GntTextFormatFlags flags, const char *tag);
-
-/* Move the cursor to the beginning of the next line and resets text-attributes.
- * It first completes the current line with the current text-attributes. */
-void gnt_text_view_next_line(GntTextView *view);
-
-chtype gnt_text_format_flag_to_chtype(GntTextFormatFlags flags);
-
-void gnt_text_view_clear(GntTextView *view);
-
-int gnt_text_view_get_lines_below(GntTextView *view);
-
-int gnt_text_view_get_lines_above(GntTextView *view);
-
-/* If text is NULL, then the tag is removed. */
-int gnt_text_view_tag_change(GntTextView *view, const char *name, const char *text, gboolean all);
-
-G_END_DECLS
-
-#endif /* GNT_TEXT_VIEW_H */
--- a/console/libgnt/gnttree.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1499 +0,0 @@
-#include "gntmarshal.h"
-#include "gntstyle.h"
-#include "gnttree.h"
-#include "gntutils.h"
-
-#include <string.h>
-#include <ctype.h>
-
-#define SEARCH_TIMEOUT 4000   /* 4 secs */
-
-enum
-{
-	SIG_SELECTION_CHANGED,
-	SIG_SCROLLED,
-	SIG_TOGGLED,
-	SIGS,
-};
-
-#define	TAB_SIZE 3
-
-/* XXX: Make this one into a GObject?
- * 		 ... Probably not */
-struct _GnTreeRow
-{
-	void *key;
-	void *data;		/* XXX: unused */
-
-	gboolean collapsed;
-	gboolean choice;            /* Is this a choice-box?
-	                               If choice is true, then child will be NULL */
-	gboolean isselected;
-	GntTextFormatFlags flags;
-
-	GntTreeRow *parent;
-	GntTreeRow *child;
-	GntTreeRow *next;
-	GntTreeRow *prev;
-
-	GList *columns;
-	GntTree *tree;
-};
-
-struct _GnTreeCol
-{
-	char *text;
-	int span;       /* How many columns does it span? */
-};
-
-static GntWidgetClass *parent_class = NULL;
-static guint signals[SIGS] = { 0 };
-
-/* Move the item at position old to position new */
-static GList *
-g_list_reposition_child(GList *list, int old, int new)
-{
-	gpointer item = g_list_nth_data(list, old);
-	list = g_list_remove(list, item);
-	if (old < new)
-		new--;   /* because the positions would have shifted after removing the item */
-	list = g_list_insert(list, item, new);
-	return list;
-}
-
-static GntTreeRow *
-_get_next(GntTreeRow *row, gboolean godeep)
-{
-	if (row == NULL)
-		return NULL;
-	if (godeep && row->child)
-		return row->child;
-	if (row->next)
-		return row->next;
-	return _get_next(row->parent, FALSE);
-}
-
-static gboolean
-row_matches_search(GntTreeRow *row)
-{
-	GntTree *t = row->tree;
-	if (t->search && t->search->len > 0) {
-		char *one = g_utf8_casefold(((GntTreeCol*)row->columns->data)->text, -1);
-		char *two = g_utf8_casefold(t->search->str, -1);
-		char *z = strstr(one, two);
-		g_free(one);
-		g_free(two);
-		if (z == NULL)
-			return FALSE;
-	}
-	return TRUE;
-}
-
-static GntTreeRow *
-get_next(GntTreeRow *row)
-{
-	if (row == NULL)
-		return NULL;
-	while ((row = _get_next(row, !row->collapsed)) != NULL) {
-		if (row_matches_search(row))
-			break;
-	}
-	return row;
-}
-
-/* Returns the n-th next row. If it doesn't exist, returns NULL */
-static GntTreeRow *
-get_next_n(GntTreeRow *row, int n)
-{
-	while (row && n--)
-		row = get_next(row);
-	return row;
-}
-
-/* Returns the n-th next row. If it doesn't exist, then the last non-NULL node */
-static GntTreeRow *
-get_next_n_opt(GntTreeRow *row, int n, int *pos)
-{
-	GntTreeRow *next = row;
-	int r = 0;
-
-	if (row == NULL)
-		return NULL;
-
-	while (row && n--)
-	{
-		row = get_next(row);
-		if (row)
-		{
-			next = row;
-			r++;
-		}
-	}
-
-	if (pos)
-		*pos = r;
-
-	return next;
-}
-
-static GntTreeRow *
-get_last_child(GntTreeRow *row)
-{
-	if (row == NULL)
-		return NULL;
-	if (!row->collapsed && row->child)
-		row = row->child;
-	else
-		return row;
-
-	while(row->next)
-		row = row->next;
-	if (!row->collapsed && row->child)
-		row = get_last_child(row->child);
-	return row;
-}
-
-static GntTreeRow *
-get_prev(GntTreeRow *row)
-{
-	if (row == NULL)
-		return NULL;
-	while (row) {
-		if (row->prev)
-			row = get_last_child(row->prev);
-		else
-			row = row->parent;
-		if (!row || row_matches_search(row))
-			break;
-	}
-	return row;
-}
-
-static GntTreeRow *
-get_prev_n(GntTreeRow *row, int n)
-{
-	while (row && n--)
-		row = get_prev(row);
-	return row;
-}
-
-/* Distance of row from the root */
-/* XXX: This is uber-inefficient */
-static int
-get_root_distance(GntTreeRow *row)
-{
-	if (row == NULL)
-		return -1;
-	return get_root_distance(get_prev(row)) + 1;
-}
-
-/* Returns the distance between a and b. 
- * If a is 'above' b, then the distance is positive */
-static int
-get_distance(GntTreeRow *a, GntTreeRow *b)
-{
-	/* First get the distance from a to the root.
-	 * Then the distance from b to the root.
-	 * Subtract.
-	 * It's not that good, but it works. */
-	int ha = get_root_distance(a);
-	int hb = get_root_distance(b);
-
-	return (hb - ha);
-}
-
-static int
-find_depth(GntTreeRow *row)
-{
-	int dep = -1;
-
-	while (row)
-	{
-		dep++;
-		row = row->parent;
-	}
-
-	return dep;
-}
-
-static char *
-update_row_text(GntTree *tree, GntTreeRow *row)
-{
-	GString *string = g_string_new(NULL);
-	GList *iter;
-	int i;
-
-	for (i = 0, iter = row->columns; i < tree->ncol && iter; i++, iter = iter->next)
-	{
-		GntTreeCol *col = iter->data;
-		const char *text;
-		int len = gnt_util_onscreen_width(col->text, NULL);
-		int fl = 0;
-		gboolean cut = FALSE;
-
-		if (i == 0)
-		{
-			if (row->choice)
-			{
-				g_string_append_printf(string, "[%c] ",
-						row->isselected ? 'X' : ' ');
-				fl = 4;
-			}
-			else if (row->parent == NULL && row->child)
-			{
-				if (row->collapsed)
-				{
-					string = g_string_append(string, "+ ");
-				}
-				else
-				{
-					string = g_string_append(string, "- ");
-				}
-				fl = 2;
-			}
-			else
-			{
-				fl = TAB_SIZE * find_depth(row);
-				g_string_append_printf(string, "%*s", fl, "");
-			}
-			len += fl;
-		}
-		else
-			g_string_append_c(string, '|');
-
-		if (len > tree->columns[i].width) {
-			len = tree->columns[i].width - 1;
-			cut = TRUE;
-		}
-		text = gnt_util_onscreen_width_to_pointer(col->text, len - fl, NULL);
-		string = g_string_append_len(string, col->text, text - col->text);
-		if (cut) { /* ellipsis */
-			if (gnt_ascii_only())
-				g_string_append_c(string, '~');
-			else
-				string = g_string_append(string, "\342\200\246");
-			len++;
-		}
-
-		if (len < tree->columns[i].width && iter->next)
-			g_string_append_printf(string, "%*s", tree->columns[i].width - len, "");
-	}
-	return g_string_free(string, FALSE);
-}
-
-static void
-tree_mark_columns(GntTree *tree, int pos, int y, chtype type)
-{
-	GntWidget *widget = GNT_WIDGET(tree);
-	int i;
-	int x = pos;
-
-	for (i = 0; i < tree->ncol - 1; i++)
-	{
-		x += tree->columns[i].width;
-		mvwaddch(widget->window, y, x + i, type);
-	}
-}
-
-static void
-redraw_tree(GntTree *tree)
-{
-	int start, i;
-	GntWidget *widget = GNT_WIDGET(tree);
-	GntTreeRow *row;
-	int pos, up, down;
-	int rows, scrcol;
-
-	if (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_MAPPED))
-		return;
-
-	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
-		pos = 0;
-	else
-		pos = 1;
-
-	if (tree->top == NULL)
-		tree->top = tree->root;
-	if (tree->current == NULL)
-		tree->current = tree->root;
-
-	wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL));
-
-	start = 0;
-	if (tree->show_title)
-	{
-		int i;
-		int x = pos;
-
-		mvwhline(widget->window, pos + 1, pos, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL),
-				widget->priv.width - pos - 1);
-		
-		for (i = 0; i < tree->ncol; i++)
-		{
-			mvwaddstr(widget->window, pos, x + i, tree->columns[i].title);
-			x += tree->columns[i].width;
-		}
-		if (pos)
-		{
-			tree_mark_columns(tree, pos, 0, ACS_TTEE | COLOR_PAIR(GNT_COLOR_NORMAL));
-			tree_mark_columns(tree, pos, widget->priv.height - pos,
-					ACS_BTEE | COLOR_PAIR(GNT_COLOR_NORMAL));
-		}
-		tree_mark_columns(tree, pos, pos + 1,
-			(tree->show_separator ? ACS_PLUS : ACS_HLINE) | COLOR_PAIR(GNT_COLOR_NORMAL));
-		tree_mark_columns(tree, pos, pos,
-			(tree->show_separator ? ACS_VLINE : ' ') | COLOR_PAIR(GNT_COLOR_NORMAL));
-		start = 2;
-	}
-
-	rows = widget->priv.height - pos * 2 - start - 1;
-	tree->bottom = get_next_n_opt(tree->top, rows, &down);
-	if (down < rows)
-	{
-		tree->top = get_prev_n(tree->bottom, rows);
-		if (tree->top == NULL)
-			tree->top = tree->root;
-	}
-
-	up = get_distance(tree->top, tree->current);
-	if (up < 0)
-		tree->top = tree->current;
-	else if (up >= widget->priv.height - pos)
-		tree->top = get_prev_n(tree->current, rows);
-
-	if (tree->top && !row_matches_search(tree->top))
-		tree->top = get_next(tree->top);
-	row = tree->top;
-	scrcol = widget->priv.width - 1 - 2 * pos;  /* exclude the borders and the scrollbar */
-	for (i = start + pos; row && i < widget->priv.height - pos;
-				i++, row = get_next(row))
-	{
-		char *str;
-		int wr;
-
-		GntTextFormatFlags flags = row->flags;
-		int attr = 0;
-
-		if (!row_matches_search(row))
-			continue;
-		str = update_row_text(tree, row);
-
-		if ((wr = gnt_util_onscreen_width(str, NULL)) > scrcol)
-		{
-			char *s = (char*)gnt_util_onscreen_width_to_pointer(str, scrcol, &wr);
-			*s = '\0';
-		}
-
-		if (flags & GNT_TEXT_FLAG_BOLD)
-			attr |= A_BOLD;
-		if (flags & GNT_TEXT_FLAG_UNDERLINE)
-			attr |= A_UNDERLINE;
-		if (flags & GNT_TEXT_FLAG_BLINK)
-			attr |= A_BLINK;
-
-		if (row == tree->current)
-		{
-			if (gnt_widget_has_focus(widget))
-				attr |= COLOR_PAIR(GNT_COLOR_HIGHLIGHT);
-			else
-				attr |= COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D);
-		}
-		else
-		{
-			if (flags & GNT_TEXT_FLAG_DIM)
-				attr |= (A_DIM | COLOR_PAIR(GNT_COLOR_DISABLED));
-			else if (flags & GNT_TEXT_FLAG_HIGHLIGHT)
-				attr |= (A_DIM | COLOR_PAIR(GNT_COLOR_HIGHLIGHT));
-			else
-				attr |= COLOR_PAIR(GNT_COLOR_NORMAL);
-		}
-
-		wbkgdset(widget->window, '\0' | attr);
-		mvwaddstr(widget->window, i, pos, str);
-		whline(widget->window, ' ', scrcol - wr);
-		tree->bottom = row;
-		g_free(str);
-		tree_mark_columns(tree, pos, i,
-			(tree->show_separator ? ACS_VLINE : ' ') | attr);
-	}
-
-	wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
-	while (i < widget->priv.height - pos)
-	{
-		mvwhline(widget->window, i, pos, ' ',
-				widget->priv.width - pos * 2 - 1);
-		tree_mark_columns(tree, pos, i,
-			(tree->show_separator ? ACS_VLINE : ' '));
-		i++;
-	}
-
-	scrcol = widget->priv.width - pos - 1;  /* position of the scrollbar */
-	rows--;
-	if (rows > 0)
-	{
-		int total;
-		int showing, position;
-
-		get_next_n_opt(tree->root, g_list_length(tree->list), &total);
-		showing = rows * rows / MAX(total, 1) + 1;
-		showing = MIN(rows, showing);
-
-		total -= rows;
-		up = get_distance(tree->root, tree->top);
-		down = total - up;
-
-		position = (rows - showing) * up / MAX(1, up + down);
-		position = MAX((tree->top != tree->root), position);
-
-		if (showing + position > rows)
-			position = rows - showing;
-
-		if (showing + position == rows  && row)
-			position = MAX(0, rows - 1 - showing);
-		else if (showing + position < rows && !row)
-			position = rows - showing;
-
-		position += pos + start + 1;
-
-		mvwvline(widget->window, pos + start + 1, scrcol,
-				' ' | COLOR_PAIR(GNT_COLOR_NORMAL), rows);
-		mvwvline(widget->window, position, scrcol,
-				ACS_CKBOARD | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D), showing);
-	}
-
-	mvwaddch(widget->window, start + pos, scrcol,
-			((tree->top != tree->root) ?  ACS_UARROW : ' ') |
-				COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
-
-	mvwaddch(widget->window, widget->priv.height - pos - 1, scrcol,
-			(row ?  ACS_DARROW : ' ') | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
-
-	gnt_widget_queue_update(widget);
-}
-
-static void
-gnt_tree_draw(GntWidget *widget)
-{
-	GntTree *tree = GNT_TREE(widget);
-
-	redraw_tree(tree);
-	
-	GNTDEBUG;
-}
-
-static void
-gnt_tree_size_request(GntWidget *widget)
-{
-	if (widget->priv.height == 0)
-		widget->priv.height = 10;	/* XXX: Why?! */
-	if (widget->priv.width == 0)
-	{
-		GntTree *tree = GNT_TREE(widget);
-		int i, width = 0;
-		for (i = 0; i < tree->ncol; i++)
-			width += tree->columns[i].width;
-		widget->priv.width = width + i;
-	}
-}
-
-static void
-gnt_tree_map(GntWidget *widget)
-{
-	GntTree *tree = GNT_TREE(widget);
-	if (widget->priv.width == 0 || widget->priv.height == 0)
-	{
-		gnt_widget_size_request(widget);
-	}
-	tree->top = tree->root;
-	tree->current = tree->root;
-	GNTDEBUG;
-}
-
-static void
-tree_selection_changed(GntTree *tree, GntTreeRow *old, GntTreeRow *current)
-{
-	g_signal_emit(tree, signals[SIG_SELECTION_CHANGED], 0, old ? old->key : NULL,
-				current ? current->key : NULL);
-}
-
-static gboolean
-action_down(GntBindable *bind, GList *null)
-{
-	int dist;
-	GntTree *tree = GNT_TREE(bind);
-	GntTreeRow *old = tree->current;
-	GntTreeRow *row = get_next(tree->current);
-	if (row == NULL)
-		return FALSE;
-	tree->current = row;
-	if ((dist = get_distance(tree->current, tree->bottom)) < 0)
-		gnt_tree_scroll(tree, -dist);
-	else
-		redraw_tree(tree);
-	if (old != tree->current)
-		tree_selection_changed(tree, old, tree->current);
-	return TRUE;
-}
-
-static gboolean
-action_up(GntBindable *bind, GList *list)
-{
-	int dist;
-	GntTree *tree = GNT_TREE(bind);
-	GntTreeRow *old = tree->current;
-	GntTreeRow *row = get_prev(tree->current);
-	if (!row)
-		return FALSE;
-	tree->current = row;
-	if ((dist = get_distance(tree->current, tree->top)) > 0)
-		gnt_tree_scroll(tree, -dist);
-	else
-		redraw_tree(tree);
-	if (old != tree->current)
-		tree_selection_changed(tree, old, tree->current);
-
-	return TRUE;
-}
-
-static gboolean
-action_page_down(GntBindable *bind, GList *null)
-{
-	GntTree *tree = GNT_TREE(bind);
-	GntTreeRow *old = tree->current;
-	GntTreeRow *row = get_next(tree->bottom);
-	if (row)
-	{
-		int dist = get_distance(tree->top, tree->current);
-		tree->top = tree->bottom;
-		tree->current = get_next_n_opt(tree->top, dist, NULL);
-		redraw_tree(tree);
-	}
-	else if (tree->current != tree->bottom)
-	{
-		tree->current = tree->bottom;
-		redraw_tree(tree);
-	}
-
-	if (old != tree->current)
-		tree_selection_changed(tree, old, tree->current);
-	return TRUE;
-}
-
-static gboolean
-action_page_up(GntBindable *bind, GList *null)
-{
-	GntWidget *widget = GNT_WIDGET(bind);
-	GntTree *tree = GNT_TREE(bind);
-	GntTreeRow *row;
-	GntTreeRow *old = tree->current;
-
-	if (tree->top != tree->root)
-	{
-		int dist = get_distance(tree->top, tree->current);
-		row = get_prev_n(tree->top, widget->priv.height - 1 -
-			tree->show_title * 2 - 2 * (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER) == 0));
-		if (row == NULL)
-			row = tree->root;
-		tree->top = row;
-		tree->current = get_next_n_opt(tree->top, dist, NULL);
-		redraw_tree(tree);
-	}
-	else if (tree->current != tree->top)
-	{
-		tree->current = tree->top;
-		redraw_tree(tree);
-	}
-	if (old != tree->current)
-		tree_selection_changed(tree, old, tree->current);
-	return TRUE;
-}
-
-static void
-end_search(GntTree *tree)
-{
-	if (tree->search) {
-		g_source_remove(tree->search_timeout);
-		g_string_free(tree->search, TRUE);
-		tree->search = NULL;
-		tree->search_timeout = 0;
-	}
-}
-
-static gboolean
-search_timeout(gpointer data)
-{
-	GntTree *tree = data;
-
-	end_search(tree);
-	redraw_tree(tree);
-
-	return FALSE;
-}
-
-static gboolean
-gnt_tree_key_pressed(GntWidget *widget, const char *text)
-{
-	GntTree *tree = GNT_TREE(widget);
-	GntTreeRow *old = tree->current;
-
-	if (text[0] == '\r') {
-		end_search(tree);
-		gnt_widget_activate(widget);
-	} else if (tree->search) {
-		if (isalnum(*text)) {
-			tree->search = g_string_append_c(tree->search, *text);
-			redraw_tree(tree);
-			g_source_remove(tree->search_timeout);
-			tree->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree);
-		}
-		return TRUE;
-	} else if (text[0] == ' ' && text[1] == 0) {
-		/* Space pressed */
-		GntTreeRow *row = tree->current;
-		if (row && row->child)
-		{
-			row->collapsed = !row->collapsed;
-			redraw_tree(tree);
-		}
-		else if (row && row->choice)
-		{
-			row->isselected = !row->isselected;
-			g_signal_emit(tree, signals[SIG_TOGGLED], 0, row->key);
-			redraw_tree(tree);
-		}
-	}
-
-	if (old != tree->current)
-	{
-		tree_selection_changed(tree, old, tree->current);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static void
-gnt_tree_destroy(GntWidget *widget)
-{
-	GntTree *tree = GNT_TREE(widget);
-	int i;
-
-	end_search(tree);
-	if (tree->hash)
-		g_hash_table_destroy(tree->hash);
-	g_list_free(tree->list);
-
-	for (i = 0; i < tree->ncol; i++)
-	{
-		g_free(tree->columns[i].title);
-	}
-	g_free(tree->columns);
-}
-
-static gboolean
-gnt_tree_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
-{
-	GntTree *tree = GNT_TREE(widget);
-	GntTreeRow *old = tree->current;
-	if (event == GNT_MOUSE_SCROLL_UP) {
-		action_up(GNT_BINDABLE(widget), NULL);
-	} else if (event == GNT_MOUSE_SCROLL_DOWN) {
-		action_down(GNT_BINDABLE(widget), NULL);
-	} else if (event == GNT_LEFT_MOUSE_DOWN) {
-		GntTreeRow *row;
-		GntTree *tree = GNT_TREE(widget);
-		int pos = 1;
-		if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
-			pos = 0;
-		if (tree->show_title)
-			pos += 2;
-		pos = y - widget->priv.y - pos;
-		row = get_next_n(tree->top, pos);
-		if (row && tree->current != row) {
-			GntTreeRow *old = tree->current;
-			tree->current = row;
-			redraw_tree(tree);
-			tree_selection_changed(tree, old, tree->current);
-		} else if (row && row == tree->current) {
-			if (row->choice) {
-				row->isselected = !row->isselected;
-				g_signal_emit(tree, signals[SIG_TOGGLED], 0, row->key);
-				redraw_tree(tree);
-			} else {
-				gnt_widget_activate(widget);
-			}
-		}
-	} else {
-		return FALSE;
-	}
-	if (old != tree->current) {
-		tree_selection_changed(tree, old, tree->current);
-	}
-	return TRUE;
-}
-
-static void
-gnt_tree_size_changed(GntWidget *widget, int w, int h)
-{
-	GntTree *tree = GNT_TREE(widget);
-	int i;
-	int n = 0;
-	if (widget->priv.width <= 0)
-		return;
-	for (i = 0; i < tree->ncol; ++i)
-		n += tree->columns[i].width;
-	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
-		tree->columns[tree->ncol - 1].width += widget->priv.width - n - 1 * tree->ncol;
-	else
-		tree->columns[tree->ncol - 1].width += widget->priv.width - n - 2 - 1 * tree->ncol;
-}
-
-static gboolean
-start_search(GntBindable *bindable, GList *list)
-{
-	GntTree *tree = GNT_TREE(bindable);
-	if (tree->search)
-		return FALSE;
-	tree->search = g_string_new(NULL);
-	tree->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree);
-	return TRUE;
-}
-
-static gboolean
-end_search_action(GntBindable *bindable, GList *list)
-{
-	GntTree *tree = GNT_TREE(bindable);
-	if (tree->search == NULL)
-		return FALSE;
-	end_search(tree);
-	redraw_tree(tree);
-	return TRUE;
-}
-
-static void
-gnt_tree_class_init(GntTreeClass *klass)
-{
-	GntBindableClass *bindable = GNT_BINDABLE_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;
-	parent_class->clicked = gnt_tree_clicked;
-	parent_class->size_changed = gnt_tree_size_changed;
-
-	signals[SIG_SELECTION_CHANGED] = 
-		g_signal_new("selection-changed",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntTreeClass, selection_changed),
-					 NULL, NULL,
-					 gnt_closure_marshal_VOID__POINTER_POINTER,
-					 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
-	signals[SIG_SCROLLED] = 
-		g_signal_new("scrolled",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 0,
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__INT,
-					 G_TYPE_NONE, 1, G_TYPE_INT);
-	signals[SIG_TOGGLED] = 
-		g_signal_new("toggled",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntTreeClass, toggled),
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__POINTER,
-					 G_TYPE_NONE, 1, G_TYPE_POINTER);
-
-	gnt_bindable_class_register_action(bindable, "move-up", action_up,
-				GNT_KEY_UP, NULL);
-	gnt_bindable_register_binding(bindable, "move-up", GNT_KEY_CTRL_P, NULL);
-	gnt_bindable_class_register_action(bindable, "move-down", action_down,
-				GNT_KEY_DOWN, NULL);
-	gnt_bindable_register_binding(bindable, "move-down", GNT_KEY_CTRL_N, NULL);
-	gnt_bindable_class_register_action(bindable, "page-up", action_page_up,
-				GNT_KEY_PGUP, NULL);
-	gnt_bindable_class_register_action(bindable, "page-down", action_page_down,
-				GNT_KEY_PGDOWN, NULL);
-	gnt_bindable_class_register_action(bindable, "start-search", start_search,
-				"/", NULL);
-	gnt_bindable_class_register_action(bindable, "end-search", end_search_action,
-				"\033", NULL);
-
-	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), bindable);
-	GNTDEBUG;
-}
-
-static void
-gnt_tree_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	GntTree *tree = GNT_TREE(widget);
-	tree->show_separator = TRUE;
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y);
-	widget->priv.minw = 4;
-	widget->priv.minh = 1;
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * 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	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_WIDGET,
-									  "GntTree",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-static void
-free_tree_col(gpointer data)
-{
-	GntTreeCol *col = data;
-
-	g_free(col->text);
-	g_free(col);
-}
-
-static void
-free_tree_row(gpointer data)
-{
-	GntTreeRow *row = data;
-
-	if (!row)
-		return;
-
-	g_list_foreach(row->columns, (GFunc)free_tree_col, NULL);
-	g_list_free(row->columns);
-	g_free(row);
-}
-
-GntWidget *gnt_tree_new()
-{
-	return gnt_tree_new_with_columns(1);
-}
-
-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))
-		ret -= 2;
-	return ret;
-}
-
-const GList *gnt_tree_get_rows(GntTree *tree)
-{
-	return tree->list;
-}
-
-void gnt_tree_scroll(GntTree *tree, int count)
-{
-	GntTreeRow *row;
-
-	if (count < 0)
-	{
-		if (get_root_distance(tree->top) == 0)
-			return;
-		row = get_prev_n(tree->top, -count);
-		if (row == NULL)
-			row = tree->root;
-		tree->top = row;
-	}
-	else
-	{
-		get_next_n_opt(tree->bottom, count, &count);
-		tree->top = get_next_n(tree->top, count);
-	}
-
-	redraw_tree(tree);
-	g_signal_emit(tree, signals[SIG_SCROLLED], 0, count);
-}
-
-static gpointer
-find_position(GntTree *tree, gpointer key, gpointer parent)
-{
-	GntTreeRow *row;
-
-	if (tree->compare == NULL)
-		return NULL;
-
-	if (parent == NULL)
-		row = tree->root;
-	else
-		row = g_hash_table_lookup(tree->hash, parent);
-
-	if (!row)
-		return NULL;
-
-	if (parent)
-		row = row->child;
-
-	while (row)
-	{
-		if (tree->compare(key, row->key) < 0)
-			return (row->prev ? row->prev->key : NULL);
-		if (row->next)
-			row = row->next;
-		else
-			return row->key;
-	}
-	return NULL;
-}
-
-void gnt_tree_sort_row(GntTree *tree, gpointer key)
-{
-	GntTreeRow *row, *q, *s;
-	int current, newp;
-
-	if (!tree->compare)
-		return;
-
-	row = g_hash_table_lookup(tree->hash, key);
-	g_return_if_fail(row != NULL);
-
-	current = g_list_index(tree->list, key);
-
-	if (row->parent)
-		s = row->parent->child;
-	else
-		s = tree->root;
-
-	q = NULL;
-	while (s) {
-		if (tree->compare(row->key, s->key) < 0)
-			break;
-		q = s;
-		s = s->next;
-	}
-
-	/* Move row between q and s */
-	if (row == q || row == s)
-		return;
-
-	if (q == NULL) {
-		/* row becomes the first child of its parent */
-		row->prev->next = row->next;  /* row->prev cannot be NULL at this point */
-		if (row->next)
-			row->next->prev = row->prev;
-		if (row->parent)
-			row->parent->child = row;
-		else
-			tree->root = row;
-		row->next = s;
-		s->prev = row;  /* s cannot be NULL */
-		row->prev = NULL;
-		newp = g_list_index(tree->list, s) - 1;
-	} else {
-		if (row->prev) {
-			row->prev->next = row->next;
-		} else {
-			/* row was the first child of its parent */
-			if (row->parent)
-				row->parent->child = row->next;
-			else
-				tree->top = row->next;
-		}
-
-		if (row->next)
-			row->next->prev = row->prev;
-
-		q->next = row;
-		row->prev = q;
-		if (s)
-			s->prev = row;
-		row->next = s;
-		newp = g_list_index(tree->list, q) + 1;
-	}
-	tree->list = g_list_reposition_child(tree->list, current, newp);
-
-	redraw_tree(tree);
-}
-
-GntTreeRow *gnt_tree_add_row_after(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro)
-{
-	GntTreeRow *pr = NULL;
-
-	g_hash_table_replace(tree->hash, key, row);
-	row->tree = tree;
-
-	if (bigbro == NULL && tree->compare)
-	{
-		bigbro = find_position(tree, key, parent);
-	}
-
-	if (tree->root == NULL)
-	{
-		tree->root = row;
-		tree->list = g_list_prepend(tree->list, key);
-	}
-	else
-	{
-		int position = 0;
-
-		if (bigbro)
-		{
-			pr = g_hash_table_lookup(tree->hash, bigbro);
-			if (pr)
-			{
-				if (pr->next)	pr->next->prev = row;
-				row->next = pr->next;
-				row->prev = pr;
-				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)
-			{
-				if (pr->child)	pr->child->prev = row;
-				row->next = pr->child;
-				pr->child = row;
-				row->parent = pr;
-
-				position = g_list_index(tree->list, parent);
-			}
-		}
-
-		if (pr == NULL)
-		{
-			GntTreeRow *r = tree->root;
-			row->next = r;
-			if (r) r->prev = row;
-			if (tree->current == tree->root)
-				tree->current = row;
-			tree->root = row;
-			tree->list = g_list_prepend(tree->list, key);
-		}
-		else
-		{
-			tree->list = g_list_insert(tree->list, key, position + 1);
-		}
-	}
-
-	row->key = key;
-	row->data = NULL;
-
-	redraw_tree(tree);
-
-	return row;
-}
-
-GntTreeRow *gnt_tree_add_row_last(GntTree *tree, void *key, GntTreeRow *row, void *parent)
-{
-	GntTreeRow *pr = NULL, *br = NULL;
-
-	if (parent)
-		pr = g_hash_table_lookup(tree->hash, parent);
-
-	if (pr)
-		br = pr->child;
-	else
-		br = tree->root;
-
-	if (br)
-	{
-		while (br->next)
-			br = br->next;
-	}
-
-	return gnt_tree_add_row_after(tree, key, row, parent, br ? br->key : NULL);
-}
-
-gpointer gnt_tree_get_selection_data(GntTree *tree)
-{
-	if (tree->current)
-		return tree->current->key;	/* XXX: perhaps we should just get rid of 'data' */
-	return NULL;
-}
-
-char *gnt_tree_get_selection_text(GntTree *tree)
-{
-	if (tree->current)
-		return update_row_text(tree, tree->current);
-	return NULL;
-}
-
-GList *gnt_tree_get_selection_text_list(GntTree *tree)
-{
-	GList *list = NULL, *iter;
-	int i;
-
-	if (!tree->current)
-		return NULL;
-
-	for (i = 0, iter = tree->current->columns; i < tree->ncol && iter;
-			i++, iter = iter->next)
-	{
-		GntTreeCol *col = iter->data;
-		list = g_list_append(list, g_strdup(col->text));
-	}
-
-	return list;
-}
-
-void gnt_tree_remove(GntTree *tree, gpointer key)
-{
-	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
-	static int depth = 0; /* Only redraw after all child nodes are removed */
-	if (row)
-	{
-		gboolean redraw = FALSE;
-
-		if (row->child) {
-			depth++;
-			while (row->child) {
-				gnt_tree_remove(tree, row->child->key);
-			}
-			depth--;
-		}
-
-		if (get_distance(tree->top, row) >= 0 && get_distance(row, tree->bottom) >= 0)
-			redraw = TRUE;
-
-		/* Update root/top/current/bottom if necessary */
-		if (tree->root == row)
-			tree->root = get_next(row);
-		if (tree->top == row)
-		{
-			if (tree->top != tree->root)
-				tree->top = get_prev(row);
-			else
-				tree->top = get_next(row);
-		}
-		if (tree->current == row)
-		{
-			if (tree->current != tree->root)
-				tree->current = get_prev(row);
-			else
-				tree->current = get_next(row);
-			tree_selection_changed(tree, row, tree->current);
-		}
-		if (tree->bottom == row)
-		{
-			tree->bottom = get_prev(row);
-		}
-
-		/* Fix the links */
-		if (row->next)
-			row->next->prev = row->prev;
-		if (row->parent && row->parent->child == row)
-			row->parent->child = row->next;
-		if (row->prev)
-			row->prev->next = row->next;
-
-		g_hash_table_remove(tree->hash, key);
-		tree->list = g_list_remove(tree->list, key);
-
-		if (redraw && depth == 0)
-		{
-			redraw_tree(tree);
-		}
-	}
-}
-
-static gboolean
-return_true(gpointer key, gpointer data, gpointer null)
-{
-	return TRUE;
-}
-
-void gnt_tree_remove_all(GntTree *tree)
-{
-	tree->root = NULL;
-	g_hash_table_foreach_remove(tree->hash, (GHRFunc)return_true, tree);
-	g_list_free(tree->list);
-	tree->list = NULL;
-	tree->current = tree->top = tree->bottom = NULL;
-}
-
-int gnt_tree_get_selection_visible_line(GntTree *tree)
-{
-	return get_distance(tree->top, tree->current) +
-			!!(GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER));
-}
-
-void gnt_tree_change_text(GntTree *tree, gpointer key, int colno, const char *text)
-{
-	GntTreeRow *row;
-	GntTreeCol *col;
-
-	g_return_if_fail(colno < tree->ncol);
-	
-	row = g_hash_table_lookup(tree->hash, key);
-	if (row)
-	{
-		col = g_list_nth_data(row->columns, colno);
-		g_free(col->text);
-		col->text = g_strdup(text);
-
-		if (get_distance(tree->top, row) >= 0 && get_distance(row, tree->bottom) >= 0)
-			redraw_tree(tree);
-	}
-}
-
-GntTreeRow *gnt_tree_add_choice(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro)
-{
-	GntTreeRow *r;
-	r = g_hash_table_lookup(tree->hash, key);
-	g_return_val_if_fail(!r || !r->choice, NULL);
-
-	if (bigbro == NULL) {
-		if (tree->compare)
-			bigbro = find_position(tree, key, parent);
-		else {
-			r = g_hash_table_lookup(tree->hash, parent);
-			if (!r)
-				r = tree->root;
-			else
-				r = r->child;
-			if (r) {
-				while (r->next)
-					r = r->next;
-				bigbro = r->key;
-			} 
-		}
-	}
-	row = gnt_tree_add_row_after(tree, key, row, parent, bigbro);
-	row->choice = TRUE;
-
-	return row;
-}
-
-void gnt_tree_set_choice(GntTree *tree, void *key, gboolean set)
-{
-	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
-
-	if (!row)
-		return;
-	g_return_if_fail(row->choice);
-
-	row->isselected = set;
-	redraw_tree(tree);
-}
-
-gboolean gnt_tree_get_choice(GntTree *tree, void *key)
-{
-	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
-
-	if (!row)
-		return FALSE;
-	g_return_val_if_fail(row->choice, FALSE);
-
-	return row->isselected;
-}
-
-void gnt_tree_set_row_flags(GntTree *tree, void *key, GntTextFormatFlags flags)
-{
-	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
-	if (!row || row->flags == flags)
-		return;
-
-	row->flags = flags;
-	redraw_tree(tree);	/* XXX: It shouldn't be necessary to redraw the whole darned tree */
-}
-
-void gnt_tree_set_selected(GntTree *tree , void *key)
-{
-	int dist;
-	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
-	if (!row)
-		return;
-
-	if (tree->top == NULL)
-		tree->top = row;
-	if (tree->bottom == NULL)
-		tree->bottom = row;
-
-	tree->current = row;
-	if ((dist = get_distance(tree->current, tree->bottom)) < 0)
-		gnt_tree_scroll(tree, -dist);
-	else if ((dist = get_distance(tree->current, tree->top)) > 0)
-		gnt_tree_scroll(tree, -dist);
-	else
-		redraw_tree(tree);
-}
-
-void _gnt_tree_init_internals(GntTree *tree, int col)
-{
-	tree->ncol = col;
-	tree->hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_tree_row);
-	tree->columns = g_new0(struct _GntTreeColInfo, col);
-	while (col--)
-	{
-		tree->columns[col].width = 15;
-	}
-	tree->list = NULL;
-	tree->show_title = FALSE;
-}
-
-GntWidget *gnt_tree_new_with_columns(int col)
-{
-	GntWidget *widget = g_object_new(GNT_TYPE_TREE, NULL);
-	GntTree *tree = GNT_TREE(widget);
-
-	_gnt_tree_init_internals(tree, col);
-	
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW);
-	gnt_widget_set_take_focus(widget, TRUE);
-
-	return widget;
-}
-
-GntTreeRow *gnt_tree_create_row_from_list(GntTree *tree, GList *list)
-{
-	GList *iter;
-	int i;
-	GntTreeRow *row = g_new0(GntTreeRow, 1);
-
-	for (i = 0, iter = list; i < tree->ncol && iter; iter = iter->next, i++)
-	{
-		GntTreeCol *col = g_new0(GntTreeCol, 1);
-		col->span = 1;
-		col->text = g_strdup(iter->data ? iter->data : "");
-
-		row->columns = g_list_append(row->columns, col);
-	}
-
-	return row;
-}
-
-GntTreeRow *gnt_tree_create_row(GntTree *tree, ...)
-{
-	int i;
-	va_list args;
-	GList *list = NULL;
-	GntTreeRow *row;
-
-	va_start(args, tree);
-	for (i = 0; i < tree->ncol; i++)
-	{
-		list = g_list_append(list, va_arg(args, char *));
-	}
-	va_end(args);
-
-	row = gnt_tree_create_row_from_list(tree, list);
-	g_list_free(list);
-
-	return row;
-}
-
-void gnt_tree_set_col_width(GntTree *tree, int col, int width)
-{
-	g_return_if_fail(col < tree->ncol);
-
-	tree->columns[col].width = width;
-}
-
-void gnt_tree_set_column_titles(GntTree *tree, ...)
-{
-	int i;
-	va_list args;
-
-	va_start(args, tree);
-	for (i = 0; i < tree->ncol; i++)
-	{
-		const char *title = va_arg(args, const char *);
-		tree->columns[i].title = g_strdup(title);
-	}
-	va_end(args);
-}
-
-void gnt_tree_set_show_title(GntTree *tree, gboolean set)
-{
-	tree->show_title = set;
-	GNT_WIDGET(tree)->priv.minh = (set ? 6 : 4);
-}
-
-void gnt_tree_set_compare_func(GntTree *tree, GCompareFunc func)
-{
-	tree->compare = func;
-}
-
-void gnt_tree_set_expanded(GntTree *tree, void *key, gboolean expanded)
-{
-	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
-	if (row) {
-		row->collapsed = !expanded;
-		if (GNT_WIDGET(tree)->window)
-			gnt_widget_draw(GNT_WIDGET(tree));
-	}
-}
-
-void gnt_tree_set_show_separator(GntTree *tree, gboolean set)
-{
-	tree->show_separator = set;
-}
-
-void gnt_tree_adjust_columns(GntTree *tree)
-{
-	GntTreeRow *row = tree->root;
-	int *widths, i, twidth, height;
-
-	widths = g_new0(int, tree->ncol);
-	while (row) {
-		GList *iter;
-		for (i = 0, iter = row->columns; iter; iter = iter->next, i++) {
-			GntTreeCol *col = iter->data;
-			int w = gnt_util_onscreen_width(col->text, NULL);
-			if (widths[i] < w)
-				widths[i] = w;
-		}
-		row = row->next;
-	}
-
-	twidth = 1 + 2 * (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER));
-	for (i = 0; i < tree->ncol; i++) {
-		gnt_tree_set_col_width(tree, i, widths[i]);
-		twidth += widths[i] + (tree->show_separator ? 1 : 0) + 1;
-	}
-	g_free(widths);
-
-	gnt_widget_get_size(GNT_WIDGET(tree), NULL, &height);
-	gnt_widget_set_size(GNT_WIDGET(tree), twidth, height);
-}
-
-void gnt_tree_set_hash_fns(GntTree *tree, gpointer hash, gpointer eq, gpointer kd)
-{
-	g_hash_table_foreach_remove(tree->hash, return_true, NULL);
-	g_hash_table_destroy(tree->hash);
-	tree->hash = g_hash_table_new_full(hash, eq, kd, free_tree_row);
-}
-
--- a/console/libgnt/gnttree.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-#ifndef GNT_TREE_H
-#define GNT_TREE_H
-
-#include "gntwidget.h"
-#include "gnt.h"
-#include "gntcolors.h"
-#include "gntkeys.h"
-#include "gnttextview.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;
-typedef struct _GnTreeCol		GntTreeCol;
-
-struct _GnTree
-{
-	GntWidget parent;
-
-	GntTreeRow *current;    /* current selection */
-
-	GntTreeRow *top;        /* The topmost visible item */
-	GntTreeRow *bottom;     /* The bottommost visible item */
-	
-	GntTreeRow *root;       /* The root of all evil */
-	
-	GList *list;            /* List of GntTreeRow s */
-	GHashTable *hash;       /* We need this for quickly referencing the rows */
-	guint (*hash_func)(gconstpointer);
-	gboolean (*hash_eq_func)(gconstpointer, gconstpointer);
-	GDestroyNotify key_destroy;
-	GDestroyNotify value_destroy;
-
-	int ncol;               /* No. of columns */
-	struct _GntTreeColInfo
-	{
-		int width;
-		char *title;
-	} *columns;             /* Would a GList be better? */
-	gboolean show_title;
-	gboolean show_separator; /* Whether to show column separators */
-
-	GString *search;
-	int search_timeout;
-
-	GCompareFunc compare;
-};
-
-struct _GnTreeClass
-{
-	GntWidgetClass parent;
-
-	void (*selection_changed)(GntTreeRow *old, GntTreeRow * current);
-	void (*toggled)(GntTree *tree, gpointer key);
-
-	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);      /* A tree with just one column */
-
-GntWidget *gnt_tree_new_with_columns(int columns);
-
-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);
-
-GntTreeRow *gnt_tree_add_row_after(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro);
-
-GntTreeRow *gnt_tree_add_row_last(GntTree *tree, void *key, GntTreeRow *row, void *parent);
-
-gpointer gnt_tree_get_selection_data(GntTree *tree);
-
-/* Returned string needs to be freed */
-char *gnt_tree_get_selection_text(GntTree *tree);
-
-GList *gnt_tree_get_selection_text_list(GntTree *tree);
-
-const GList *gnt_tree_get_rows(GntTree *tree);
-
-void gnt_tree_remove(GntTree *tree, gpointer key);
-
-void gnt_tree_remove_all(GntTree *tree);
-
-/* Returns the visible line number of the selected row */
-int gnt_tree_get_selection_visible_line(GntTree *tree);
-
-void gnt_tree_change_text(GntTree *tree, gpointer key, int colno, const char *text);
-
-GntTreeRow *gnt_tree_add_choice(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro);
-
-void gnt_tree_set_choice(GntTree *tree, void *key, gboolean set);
-
-gboolean gnt_tree_get_choice(GntTree *tree, void *key);
-
-void gnt_tree_set_row_flags(GntTree *tree, void *key, GntTextFormatFlags flags);
-
-void gnt_tree_set_selected(GntTree *tree , void *key);
-
-GntTreeRow *gnt_tree_create_row(GntTree *tree, ...);
-
-GntTreeRow *gnt_tree_create_row_from_list(GntTree *tree, GList *list);
-
-void gnt_tree_set_col_width(GntTree *tree, int col, int width);
-
-void gnt_tree_set_column_titles(GntTree *tree, ...);
-
-void gnt_tree_set_show_title(GntTree *tree, gboolean set);
-
-void gnt_tree_set_compare_func(GntTree *tree, GCompareFunc func);
-
-void gnt_tree_set_expanded(GntTree *tree, void *key, gboolean expanded);
-
-void gnt_tree_set_show_separator(GntTree *tree, gboolean set);
-
-void gnt_tree_sort_row(GntTree *tree, void *row);
-
-/* This will try to automatically adjust the width of the columns in the tree */
-void gnt_tree_adjust_columns(GntTree *tree);
-
-void gnt_tree_set_hash_fns(GntTree *tree, gpointer hash, gpointer eq, gpointer kd);
-
-G_END_DECLS
-
-/* The following functions should NOT be used by applications. */
-
-/* This should be called by the subclasses of GntTree's in their _new function */
-void _gnt_tree_init_internals(GntTree *tree, int col);
-
-#endif /* GNT_TREE_H */
--- a/console/libgnt/gntutils.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,147 +0,0 @@
-#include "gntutils.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-
-void gnt_util_get_text_bound(const char *text, int *width, int *height)
-{
-	const char *s = text, *last;
-	int count = 1, max = 0;
-	int len;
-
-	/* XXX: ew ... everyone look away */
-	last = s;
-	if (s)
-	{
-		while (*s)
-		{
-			if (*s == '\n' || *s == '\r')
-			{
-				count++;
-				len = gnt_util_onscreen_width(last, s);
-				if (max < len)
-					max = len;
-				last = s + 1;
-			}
-			s = g_utf8_next_char(s);
-		}
-
-		len = gnt_util_onscreen_width(last, s);
-		if (max < len)
-			max = len;
-	}
-
-	if (height)
-		*height = count;
-	if (width)
-		*width = max + (count > 1);
-}
-
-int gnt_util_onscreen_width(const char *start, const char *end)
-{
-	int width = 0;
-
-	if (end == NULL)
-		end = start + strlen(start);
-
-	while (start < end) {
-		width += g_unichar_iswide(g_utf8_get_char(start)) ? 2 : 1;
-		start = g_utf8_next_char(start);
-	}
-	return width;
-}
-
-const char *gnt_util_onscreen_width_to_pointer(const char *string, int len, int *w)
-{
-	int size;
-	int width = 0;
-	const char *str = string;
-
-	if (len <= 0) {
-		len = gnt_util_onscreen_width(string, NULL);
-	}
-
-	while (width < len && *str) {
-		size = g_unichar_iswide(g_utf8_get_char(str)) ? 2 : 1;
-		if (width + size > len)
-			break;
-		str = g_utf8_next_char(str);
-		width += size;
-	}
-	if (w)
-		*w = width;
-	return str;
-}
-
-char *gnt_util_onscreen_fit_string(const char *string, int maxw)
-{
-	const char *start, *end;
-	GString *str;
-
-	if (maxw <= 0)
-		maxw = getmaxx(stdscr) - 4;
-
-	start = string;
-	str = g_string_new(NULL);
-
-	while (*start) {
-		if ((end = strchr(start, '\n')) != NULL ||
-			(end = strchr(start, '\r')) != NULL) {
-			if (gnt_util_onscreen_width(start, end) > maxw)
-				end = NULL;
-		}
-		if (end == NULL)
-			end = gnt_util_onscreen_width_to_pointer(start, maxw, NULL);
-		str = g_string_append_len(str, start, end - start);
-		if (*end) {
-			str = g_string_append_c(str, '\n');
-			if (*end == '\n' || *end == '\r')
-				end++;
-		}
-		start = end;
-	}
-	return g_string_free(str, FALSE);
-}
-
-struct duplicate_fns
-{
-	GDupFunc key_dup;
-	GDupFunc value_dup;
-	GHashTable *table;
-};
-
-static void
-duplicate_values(gpointer key, gpointer value, gpointer data)
-{
-	struct duplicate_fns *fns = data;
-	g_hash_table_insert(fns->table, fns->key_dup ? fns->key_dup(key) : key,
-			fns->value_dup ? fns->value_dup(value) : value);
-}
-
-GHashTable *g_hash_table_duplicate(GHashTable *src, GHashFunc hash,
-		GEqualFunc equal, GDestroyNotify key_d, GDestroyNotify value_d,
-		GDupFunc key_dup, GDupFunc value_dup)
-{
-	GHashTable *dest = g_hash_table_new_full(hash, equal, key_d, value_d);
-	struct duplicate_fns fns = {key_dup, value_dup, dest};
-	g_hash_table_foreach(src, duplicate_values, &fns);
-	return dest;
-}
-
-gboolean gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint,
-				  GValue                *return_accu,
-				  const GValue          *handler_return,
-				  gpointer               dummy)
-{
-	gboolean continue_emission;
-	gboolean signal_handled;
-
-	signal_handled = g_value_get_boolean (handler_return);
-	g_value_set_boolean (return_accu, signal_handled);
-	continue_emission = !signal_handled;
-
-	return continue_emission;
-}
-
--- a/console/libgnt/gntutils.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-#include <glib.h>
-
-#include "gnt.h"
-#include "gntwidget.h"
-
-typedef gpointer (*GDupFunc)(gconstpointer data);
-
-void gnt_util_get_text_bound(const char *text, int *width, int *height);
-
-/* excluding *end */
-int gnt_util_onscreen_width(const char *start, const char *end);
-
-const char *gnt_util_onscreen_width_to_pointer(const char *str, int len, int *w);
-
-/* Inserts newlines in 'string' where necessary so that its onscreen width is
- * no more than 'maxw'.
- * 'maxw' can be <= 0, in which case the maximum screen width is considered.
- *
- * Returns a newly allocated string.
- */
-char *gnt_util_onscreen_fit_string(const char *string, int maxw);
-
-GHashTable *g_hash_table_duplicate(GHashTable *src, GHashFunc hash,
-		GEqualFunc equal, GDestroyNotify key_d, GDestroyNotify value_d,
-		GDupFunc key_dup, GDupFunc value_dup);
-
-
-/**
- * To be used with g_signal_new. Look in the key_pressed signal-definition in
- * gntwidget.c for usage.
- */
-gboolean gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint,
-				  GValue                *return_accu,
-				  const GValue          *handler_return,
-				  gpointer               dummy);
-
--- a/console/libgnt/gntwidget.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,630 +0,0 @@
-/* Stuff brutally ripped from Gflib */
-
-#include "gntwidget.h"
-#include "gntstyle.h"
-#include "gntmarshal.h"
-#include "gntutils.h"
-#include "gnt.h"
-
-enum
-{
-	SIG_DESTROY,
-	SIG_DRAW,
-	SIG_HIDE,
-	SIG_GIVE_FOCUS,
-	SIG_LOST_FOCUS,
-	SIG_KEY_PRESSED,
-	SIG_MAP,
-	SIG_ACTIVATE,
-	SIG_EXPOSE,
-	SIG_SIZE_REQUEST,
-	SIG_CONFIRM_SIZE,
-	SIG_SIZE_CHANGED,
-	SIG_POSITION,
-	SIG_CLICKED,
-	SIG_CONTEXT_MENU,
-	SIGS
-};
-
-static GObjectClass *parent_class = NULL;
-static guint signals[SIGS] = { 0 };
-
-static void init_widget(GntWidget *widget);
-
-static void
-gnt_widget_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	widget->priv.name = NULL;
-	GNTDEBUG;
-}
-
-static void
-gnt_widget_map(GntWidget *widget)
-{
-	/* Get some default size for the widget */
-	GNTDEBUG;
-	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);
-	GNTDEBUG;
-}
-
-static void
-gnt_widget_focus_change(GntWidget *widget)
-{
-	if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED)
-		gnt_widget_draw(widget);
-}
-
-static gboolean
-gnt_widget_dummy_confirm_size(GntWidget *widget, int width, int height)
-{
-	if (width < widget->priv.minw || height < widget->priv.minh)
-		return FALSE;
-	if (widget->priv.width != width && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_X))
-		return FALSE;
-	if (widget->priv.height != height && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_Y))
-		return FALSE;
-	return TRUE;
-}
-
-static gboolean
-context_menu(GntBindable *bind, GList *null)
-{
-	gboolean ret = FALSE;
-	g_signal_emit(bind, signals[SIG_CONTEXT_MENU], 0, &ret);
-	return ret;
-}
-
-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->confirm_size = gnt_widget_dummy_confirm_size;
-	
-	klass->key_pressed = NULL;
-	klass->activate = NULL;
-	klass->clicked = 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_HIDE] = 
-		g_signal_new("hide",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWidgetClass, hide),
-					 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_SIZE_CHANGED] = 
-		g_signal_new("size_changed",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWidgetClass, size_changed),
-					 NULL, NULL,
-					 gnt_closure_marshal_VOID__INT_INT,
-					 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
-	signals[SIG_CONFIRM_SIZE] = 
-		g_signal_new("confirm_size",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWidgetClass, confirm_size),
-					 NULL, NULL,
-					 gnt_closure_marshal_BOOLEAN__INT_INT,
-					 G_TYPE_BOOLEAN, 2, G_TYPE_INT, G_TYPE_INT);
-	signals[SIG_KEY_PRESSED] = 
-		g_signal_new("key_pressed",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWidgetClass, key_pressed),
-					 gnt_boolean_handled_accumulator, NULL,
-					 gnt_closure_marshal_BOOLEAN__STRING,
-					 G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
-
-	signals[SIG_CLICKED] = 
-		g_signal_new("clicked",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWidgetClass, clicked),
-					 gnt_boolean_handled_accumulator, NULL,
-					 gnt_closure_marshal_BOOLEAN__INT_INT_INT,
-					 G_TYPE_BOOLEAN, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
-
-	signals[SIG_CONTEXT_MENU] = 
-		g_signal_new("context-menu",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 0,
-					 gnt_boolean_handled_accumulator, NULL,
-					 gnt_closure_marshal_BOOLEAN__VOID,
-					 G_TYPE_BOOLEAN, 0);
-
-	/* This is relevant for all widgets */
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "context-menu", context_menu,
-				GNT_KEY_POPUP, NULL);
-	gnt_bindable_register_binding(GNT_BINDABLE_CLASS(klass), "context-menu", GNT_KEY_F11, NULL);
-
-	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * 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,
-			NULL,					/* class_data		*/
-			sizeof(GntWidget),
-			0,						/* n_preallocs		*/
-			gnt_widget_init,					/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_BINDABLE,
-									  "GntWidget",
-									  &info, G_TYPE_FLAG_ABSTRACT);
-	}
-
-	return type;
-}
-
-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));
-
-	gnt_widget_hide(obj);
-	delwin(obj->window);
-	if(!(GNT_WIDGET_FLAGS(obj) & GNT_WIDGET_DESTROYING))
-		g_object_run_dispose(G_OBJECT(obj));
-	GNTDEBUG;
-}
-
-void
-gnt_widget_show(GntWidget *widget)
-{
-	gnt_widget_draw(widget);
-	gnt_screen_occupy(widget);
-}
-
-void
-gnt_widget_draw(GntWidget *widget)
-{
-	/* Draw the widget */
-	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_DRAWING))
-		return;
-
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_DRAWING);
-	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED)) {
-		gnt_widget_map(widget);
-	}
-
-	if (widget->window == NULL)
-	{
-#if 0
-		int x, y, maxx, maxy, w, h;
-		int oldw, oldh;
-		gboolean shadow = TRUE;
-
-		if (!gnt_widget_has_shadow(widget))
-			shadow = FALSE;
-
-		x = widget->priv.x;
-		y = widget->priv.y;
-		w = oldw = widget->priv.width + shadow;
-		h = oldh = widget->priv.height + shadow;
-
-		getmaxyx(stdscr, maxy, maxx);
-		maxy -= 1;		/* room for the taskbar */
-
-		x = MAX(0, x);
-		y = MAX(0, y);
-		if (x + w >= maxx)
-			x = MAX(0, maxx - w);
-		if (y + h >= maxy)
-			y = MAX(0, maxy - h);
-
-		w = MIN(w, maxx);
-		h = MIN(h, maxy);
-
-		widget->priv.x = x;
-		widget->priv.y = y;
-		if (w != oldw || h != oldh) {
-			widget->priv.width = w - shadow;
-			widget->priv.height = h - shadow;
-			g_signal_emit(widget, signals[SIG_SIZE_CHANGED], 0, oldw, oldh);
-		}
-#else
-		widget->window = newpad(widget->priv.height + 20, widget->priv.width + 20);  /* XXX: */
-#endif
-		init_widget(widget);
-	}
-
-	g_signal_emit(widget, signals[SIG_DRAW], 0);
-	gnt_widget_queue_update(widget);
-	GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_DRAWING);
-}
-
-gboolean
-gnt_widget_key_pressed(GntWidget *widget, const char *keys)
-{
-	gboolean ret;
-	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS))
-		return FALSE;
-
-	if (gnt_bindable_perform_action_key(GNT_BINDABLE(widget), keys))
-		return TRUE;
-
-	keys = gnt_bindable_remap_keys(GNT_BINDABLE(widget), keys);
-	g_signal_emit(widget, signals[SIG_KEY_PRESSED], 0, keys, &ret);
-	return ret;
-}
-
-gboolean
-gnt_widget_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
-{
-	gboolean ret;
-	g_signal_emit(widget, signals[SIG_CLICKED], 0, event, x, y, &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)
-{
-	g_signal_emit(widget, signals[SIG_HIDE], 0);
-	wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
-#if 0
-	/* XXX: I have no clue why, but this seemed to be necessary. */
-	if (gnt_widget_has_shadow(widget))
-		mvwvline(widget->window, 1, widget->priv.width, ' ', widget->priv.height);
-#endif
-	gnt_screen_release(widget);
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_INVISIBLE);
-	GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_MAPPED);
-}
-
-void
-gnt_widget_set_position(GntWidget *wid, int x, int y)
-{
-	g_signal_emit(wid, signals[SIG_POSITION], 0, x, y);
-	/* XXX: Need to install properties for these and g_object_notify */
-	wid->priv.x = x;
-	wid->priv.y = 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)
-{
-	gboolean shadow = TRUE;
-	if (!gnt_widget_has_shadow(wid))
-		shadow = FALSE;
-
-	if (width)
-		*width = wid->priv.width + shadow;
-	if (height)
-		*height = wid->priv.height + shadow;
-	
-}
-
-static void
-init_widget(GntWidget *widget)
-{
-	gboolean shadow = TRUE;
-
-	if (!gnt_widget_has_shadow(widget))
-		shadow = FALSE;
-
-	wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL));
-	werase(widget->window);
-
-	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER))
-	{
-		/* - This is ugly. */
-		/* - What's your point? */
-		mvwvline(widget->window, 0, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.height);
-		mvwvline(widget->window, 0, widget->priv.width - 1,
-				ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.height);
-		mvwhline(widget->window, widget->priv.height - 1, 0,
-				ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.width);
-		mvwhline(widget->window, 0, 0, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.width);
-		mvwaddch(widget->window, 0, 0, ACS_ULCORNER | COLOR_PAIR(GNT_COLOR_NORMAL));
-		mvwaddch(widget->window, 0, widget->priv.width - 1,
-				ACS_URCORNER | COLOR_PAIR(GNT_COLOR_NORMAL));
-		mvwaddch(widget->window, widget->priv.height - 1, 0,
-				ACS_LLCORNER | COLOR_PAIR(GNT_COLOR_NORMAL));
-		mvwaddch(widget->window, widget->priv.height - 1, widget->priv.width - 1,
-				ACS_LRCORNER | COLOR_PAIR(GNT_COLOR_NORMAL));
-	}
-
-	if (shadow)
-	{
-		wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_SHADOW));
-		mvwvline(widget->window, 1, widget->priv.width, ' ', widget->priv.height);
-		mvwhline(widget->window, widget->priv.height, 1, ' ', widget->priv.width);
-	}
-}
-
-gboolean
-gnt_widget_set_size(GntWidget *widget, int width, int height)
-{
-	gboolean ret = TRUE;
-
-	if (gnt_widget_has_shadow(widget))
-	{
-		width--;
-		height--;
-	}
-	if (width <= 0)
-		width = widget->priv.width;
-	if (height <= 0)
-		height = widget->priv.height;
-
-	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
-	{
-		ret = gnt_widget_confirm_size(widget, width, height);
-	}
-
-	if (ret)
-	{
-		gboolean shadow = TRUE;
-		int oldw, oldh;
-
-		if (!gnt_widget_has_shadow(widget))
-			shadow = FALSE;
-
-		oldw = widget->priv.width;
-		oldh = widget->priv.height;
-
-		widget->priv.width = width;
-		widget->priv.height = height;
-		if (width >= getmaxx(widget->window) || height >= getmaxy(widget->window)) {
-			delwin(widget->window);
-			widget->window = newpad(height + 20, width + 20);
-		}
-
-		g_signal_emit(widget, signals[SIG_SIZE_CHANGED], 0, oldw, oldh);
-
-		if (widget->window)
-		{
-			init_widget(widget);
-		}
-		if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
-			init_widget(widget);
-		else
-			GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_MAPPED);
-	}
-
-	return ret;
-}
-
-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))
-	{
-		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);
-}
-
-const char *gnt_widget_get_name(GntWidget *widget)
-{
-	return widget->priv.name;
-}
-
-void gnt_widget_activate(GntWidget *widget)
-{
-	g_signal_emit(widget, signals[SIG_ACTIVATE], 0);
-}
-
-static gboolean
-update_queue_callback(gpointer data)
-{
-	GntWidget *widget = GNT_WIDGET(data);
-
-	if (!g_object_get_data(G_OBJECT(widget), "gnt:queue_update"))
-		return FALSE;
-	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
-		gnt_screen_update(widget);
-	g_object_set_data(G_OBJECT(widget), "gnt:queue_update", NULL);
-	return FALSE;
-}
-
-void gnt_widget_queue_update(GntWidget *widget)
-{
-	if (widget->window == NULL)
-		return;
-	while (widget->parent)
-		widget = widget->parent;
-	
-	if (!g_object_get_data(G_OBJECT(widget), "gnt:queue_update"))
-	{
-		int id = g_timeout_add(0, update_queue_callback, widget);
-		g_object_set_data_full(G_OBJECT(widget), "gnt:queue_update", GINT_TO_POINTER(id),
-				(GDestroyNotify)g_source_remove);
-	}
-}
-
-gboolean gnt_widget_confirm_size(GntWidget *widget, int width, int height)
-{
-	gboolean ret = FALSE;
-	g_signal_emit(widget, signals[SIG_CONFIRM_SIZE], 0, width, height, &ret);
-	return ret;
-}
-
-void gnt_widget_set_visible(GntWidget *widget, gboolean set)
-{
-	if (set)
-		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_INVISIBLE);
-	else
-		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_INVISIBLE);
-}
-
-gboolean gnt_widget_has_shadow(GntWidget *widget)
-{
-	return (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_SHADOW) &&
-			gnt_style_get_bool(GNT_STYLE_SHADOW, FALSE));
-}
-
--- a/console/libgnt/gntwidget.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-#ifndef GNT_WIDGET_H
-#define GNT_WIDGET_H
-
-#include <stdio.h>
-#include <glib.h>
-#include <ncurses.h>
-
-#include "gntbindable.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_WIDGET_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))
-
-typedef struct _GnWidget			GntWidget;
-typedef struct _GnWidgetPriv		GntWidgetPriv;
-typedef struct _GnWidgetClass		GntWidgetClass;
-
-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,
-	GNT_WIDGET_DRAWING        = 1 << 6,
-	GNT_WIDGET_URGENT         = 1 << 7,
-	GNT_WIDGET_GROW_X         = 1 << 8,
-	GNT_WIDGET_GROW_Y         = 1 << 9,
-	GNT_WIDGET_INVISIBLE      = 1 << 10,
-	GNT_WIDGET_TRANSIENT      = 1 << 11,
-} GntWidgetFlags;
-
-/* XXX: This will probably move elsewhere */
-typedef enum _GnMouseEvent
-{
-	GNT_LEFT_MOUSE_DOWN = 1,
-	GNT_RIGHT_MOUSE_DOWN,
-	GNT_MIDDLE_MOUSE_DOWN,
-	GNT_MOUSE_UP,
-	GNT_MOUSE_SCROLL_UP,
-	GNT_MOUSE_SCROLL_DOWN
-} GntMouseEvent;
-
-/* XXX: I'll have to ask grim what he's using this for in guifications. */
-typedef enum _GnParamFlags
-{
-	GNT_PARAM_SERIALIZABLE	= 1 << G_PARAM_USER_SHIFT
-} GntParamFlags;
-
-struct _GnWidgetPriv
-{
-	int x, y;
-	int width, height;
-	GntWidgetFlags flags;
-	char *name;
-
-	int minw, minh;    /* Minimum size for the widget */
-};
-
-struct _GnWidget
-{
-	GntBindable inherit;
-
-	GntWidget *parent;
-
-	GntWidgetPriv priv;
-	WINDOW *window;
-
-    void (*gnt_reserved1)(void);
-    void (*gnt_reserved2)(void);
-    void (*gnt_reserved3)(void);
-    void (*gnt_reserved4)(void);
-};
-
-struct _GnWidgetClass
-{
-	GntBindableClass 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 (*hide)(GntWidget *obj);
-	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);
-	gboolean (*confirm_size)(GntWidget *widget, int x, int y);
-	void (*size_changed)(GntWidget *widget, int w, int h);
-	void (*set_position)(GntWidget *widget, int x, int y);
-	gboolean (*key_pressed)(GntWidget *widget, const char *key);
-	void (*activate)(GntWidget *widget);
-	gboolean (*clicked)(GntWidget *widget, GntMouseEvent event, int x, int y);
-
-	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);
-gboolean gnt_widget_set_size(GntWidget *widget, int width, int height);
-gboolean gnt_widget_confirm_size(GntWidget *widget, int width, int height);
-
-gboolean gnt_widget_key_pressed(GntWidget *widget, const char *keys);
-
-gboolean gnt_widget_clicked(GntWidget *widget, GntMouseEvent event, int x, int y);
-
-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);
-
-const char *gnt_widget_get_name(GntWidget *widget);
-
-/* Widget-subclasses should call this from the draw-callback.
- * Applications should just call gnt_widget_draw instead of this. */
-void gnt_widget_queue_update(GntWidget *widget);
-
-void gnt_widget_set_take_focus(GntWidget *widget, gboolean set);
-
-void gnt_widget_set_visible(GntWidget *widget, gboolean set);
-
-gboolean gnt_widget_has_shadow(GntWidget *widget);
-
-G_END_DECLS
-
-#endif /* GNT_WIDGET_H */
--- a/console/libgnt/gntwindow.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-#include "gntstyle.h"
-#include "gntwindow.h"
-
-#include <string.h>
-
-enum
-{
-	SIGS = 1,
-};
-
-static GntBoxClass *parent_class = NULL;
-
-static void (*org_destroy)(GntWidget *widget);
-
-static gboolean
-show_menu(GntBindable *bind, GList *null)
-{
-	GntWindow *win = GNT_WINDOW(bind);
-	if (win->menu) {
-		gnt_screen_menu_show(win->menu);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static void
-gnt_window_destroy(GntWidget *widget)
-{
-	GntWindow *window = GNT_WINDOW(widget);
-	if (window->menu)
-		gnt_widget_destroy(GNT_WIDGET(window->menu));
-	org_destroy(widget);
-}
-
-static void
-gnt_window_class_init(GntWindowClass *klass)
-{
-	GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass);
-	GntWidgetClass *wid_class = GNT_WIDGET_CLASS(klass);
-	parent_class = GNT_BOX_CLASS(klass);
-
-	org_destroy = wid_class->destroy;
-	wid_class->destroy = gnt_window_destroy;
-
-	gnt_bindable_class_register_action(bindable, "show-menu", show_menu,
-				GNT_KEY_CTRL_O, NULL);
-	gnt_bindable_register_binding(bindable, "show-menu", GNT_KEY_F10, NULL);
-	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), bindable);
-
-	GNTDEBUG;
-}
-
-static void
-gnt_window_init(GTypeInstance *instance, gpointer class)
-{
-	GntWidget *widget = GNT_WIDGET(instance);
-	GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
-	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * GntWindow API
- *****************************************************************************/
-GType
-gnt_window_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0)
-	{
-		static const GTypeInfo info = {
-			sizeof(GntWindowClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_window_class_init,
-			NULL,					/* class_finalize	*/
-			NULL,					/* class_data		*/
-			sizeof(GntWindow),
-			0,						/* n_preallocs		*/
-			gnt_window_init,			/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_BOX,
-									  "GntWindow",
-									  &info, 0);
-	}
-
-	return type;
-}
-
-GntWidget *gnt_window_new()
-{
-	GntWidget *widget = g_object_new(GNT_TYPE_WINDOW, NULL);
-
-	return widget;
-}
-
-GntWidget *gnt_window_box_new(gboolean homo, gboolean vert)
-{
-	GntWidget *wid = gnt_window_new();
-	GntBox *box = GNT_BOX(wid);
-
-	box->homogeneous = homo;
-	box->vertical = vert;
-	box->alignment = vert ? GNT_ALIGN_LEFT : GNT_ALIGN_MID;
-
-	return wid;
-}
-
-void gnt_window_set_menu(GntWindow *window, GntMenu *menu)
-{
-	/* If a menu already existed, then destroy that first. */
-	if (window->menu)
-		gnt_widget_destroy(GNT_WIDGET(window->menu));
-	window->menu = menu;
-}
-
--- a/console/libgnt/gntwindow.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-#ifndef GNT_WINDOW_H
-#define GNT_WINDOW_H
-
-#include "gnt.h"
-#include "gntbox.h"
-#include "gntcolors.h"
-#include "gntkeys.h"
-#include "gntmenu.h"
-
-#define GNT_TYPE_WINDOW				(gnt_window_get_gtype())
-#define GNT_WINDOW(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_WINDOW, GntWindow))
-#define GNT_WINDOW_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_WINDOW, GntWindowClass))
-#define GNT_IS_WINDOW(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_WINDOW))
-#define GNT_IS_WINDOW_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WINDOW))
-#define GNT_WINDOW_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WINDOW, GntWindowClass))
-
-#define GNT_WINDOW_FLAGS(obj)				(GNT_WINDOW(obj)->priv.flags)
-#define GNT_WINDOW_SET_FLAGS(obj, flags)		(GNT_WINDOW_FLAGS(obj) |= flags)
-#define GNT_WINDOW_UNSET_FLAGS(obj, flags)	(GNT_WINDOW_FLAGS(obj) &= ~(flags))
-
-typedef struct _GnWindow			GntWindow;
-typedef struct _GnWindowPriv		GntWindowPriv;
-typedef struct _GnWindowClass		GntWindowClass;
-
-struct _GnWindow
-{
-	GntBox parent;
-	GntMenu *menu;
-};
-
-struct _GnWindowClass
-{
-	GntBoxClass parent;
-
-	void (*gnt_reserved1)(void);
-	void (*gnt_reserved2)(void);
-	void (*gnt_reserved3)(void);
-	void (*gnt_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_window_get_gtype(void);
-
-#define gnt_vwindow_new(homo) gnt_window_box_new(homo, TRUE)
-#define gnt_hwindow_new(homo) gnt_window_box_new(homo, FALSE)
-
-GntWidget *gnt_window_new(void);
-
-GntWidget *gnt_window_box_new(gboolean homo, gboolean vert);
-
-void gnt_window_set_menu(GntWindow *window, GntMenu *menu);
-
-G_END_DECLS
-
-#endif /* GNT_WINDOW_H */
--- a/console/libgnt/gntwm.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1504 +0,0 @@
-#define _GNU_SOURCE
-#if defined(__APPLE__)
-#define _XOPEN_SOURCE_EXTENDED
-#endif
-
-#include "config.h"
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "gntwm.h"
-#include "gntstyle.h"
-#include "gntmarshal.h"
-#include "gnt.h"
-#include "gntbox.h"
-#include "gntmenu.h"
-#include "gnttextview.h"
-#include "gnttree.h"
-#include "gntutils.h"
-
-#define IDLE_CHECK_INTERVAL 5 /* 5 seconds */
-
-enum
-{
-	SIG_NEW_WIN,
-	SIG_DECORATE_WIN,
-	SIG_CLOSE_WIN,
-	SIG_CONFIRM_RESIZE,
-	SIG_RESIZED,
-	SIG_CONFIRM_MOVE,
-	SIG_MOVED,
-	SIG_UPDATE_WIN,
-	SIG_GIVE_FOCUS,
-	SIG_KEY_PRESS,
-	SIG_MOUSE_CLICK,
-	SIGS
-};
-
-static guint signals[SIGS] = { 0 };
-static void gnt_wm_new_window_real(GntWM *wm, GntWidget *widget);
-static void gnt_wm_win_resized(GntWM *wm, GntNode *node);
-static void gnt_wm_win_moved(GntWM *wm, GntNode *node);
-static void gnt_wm_give_focus(GntWM *wm, GntWidget *widget);
-static void update_window_in_list(GntWM *wm, GntWidget *wid);
-static void shift_window(GntWM *wm, GntWidget *widget, int dir);
-
-static gboolean write_already(gpointer data);
-static int write_timeout;
-static time_t last_active_time;
-static gboolean idle_update;
-
-static GList *
-g_list_bring_to_front(GList *list, gpointer data)
-{
-	list = g_list_remove(list, data);
-	list = g_list_prepend(list, data);
-	return list;
-}
-
-static void
-free_node(gpointer data)
-{
-	GntNode *node = data;
-	hide_panel(node->panel);
-	del_panel(node->panel);
-	g_free(node);
-}
-
-static void
-draw_taskbar(GntWM *wm, gboolean reposition)
-{
-	static WINDOW *taskbar = NULL;
-	GList *iter;
-	int n, width = 0;
-	int i;
-
-	if (taskbar == NULL) {
-		taskbar = newwin(1, getmaxx(stdscr), getmaxy(stdscr) - 1, 0);
-	} else if (reposition) {
-		int Y_MAX = getmaxy(stdscr) - 1;
-		mvwin(taskbar, Y_MAX, 0);
-	}
-
-	wbkgdset(taskbar, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
-	werase(taskbar);
-
-	n = g_list_length(wm->list);
-	if (n)
-		width = getmaxx(stdscr) / n;
-
-	for (i = 0, iter = wm->list; iter; iter = iter->next, i++)
-	{
-		GntWidget *w = iter->data;
-		int color;
-		const char *title;
-
-		if (w == wm->ordered->data) {
-			/* This is the current window in focus */
-			color = GNT_COLOR_TITLE;
-		} else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_URGENT)) {
-			/* This is a window with the URGENT hint set */
-			color = GNT_COLOR_URGENT;
-		} else {
-			color = GNT_COLOR_NORMAL;
-		}
-		wbkgdset(taskbar, '\0' | COLOR_PAIR(color));
-		if (iter->next)
-			mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), width);
-		else
-			mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), getmaxx(stdscr) - width * i);
-		title = GNT_BOX(w)->title;
-		mvwprintw(taskbar, 0, width * i, "%s", title ? title : "<gnt>");
-		if (i)
-			mvwaddch(taskbar, 0, width *i - 1, ACS_VLINE | A_STANDOUT | COLOR_PAIR(GNT_COLOR_NORMAL));
-
-		update_window_in_list(wm, w);
-	}
-
-	wrefresh(taskbar);
-}
-
-static void
-copy_win(GntWidget *widget, GntNode *node)
-{
-	WINDOW *src, *dst;
-	int shadow;
-	if (!node)
-		return;
-	src = widget->window;
-	dst = node->window;
-	shadow = gnt_widget_has_shadow(widget) ? 1 : 0;
-	copywin(src, dst, node->scroll, 0, 0, 0, getmaxy(dst) - 1, getmaxx(dst) - 1, 0);
-}
-
-static gboolean
-update_screen(GntWM *wm)
-{
-	if (wm->menu) {
-		GntMenu *top = wm->menu;
-		while (top) {
-			GntNode *node = g_hash_table_lookup(wm->nodes, top);
-			if (node)
-				top_panel(node->panel);
-			top = top->submenu;
-		}
-	}
-	update_panels();
-	doupdate();
-	return TRUE;
-}
-
-static gboolean
-sanitize_position(GntWidget *widget, int *x, int *y)
-{
-	int X_MAX = getmaxx(stdscr);
-	int Y_MAX = getmaxy(stdscr) - 1;
-	int w, h;
-	int nx, ny;
-	gboolean changed = FALSE;
-
-	gnt_widget_get_size(widget, &w, &h);
-	if (x) {
-		if (*x + w > X_MAX) {
-			nx = MAX(0, X_MAX - w);
-			if (nx != *x) {
-				*x = nx;
-				changed = TRUE;
-			}
-		}
-	}
-	if (y) {
-		if (*y + h > Y_MAX) {
-			ny = MAX(0, Y_MAX - h);
-			if (ny != *y) {
-				*y = ny;
-				changed = TRUE;
-			}
-		}
-	}
-	return changed;
-}
-
-static void
-refresh_node(GntWidget *widget, GntNode *node, gpointer null)
-{
-	int x, y, w, h;
-	int nw, nh;
-
-	int X_MAX = getmaxx(stdscr);
-	int Y_MAX = getmaxy(stdscr) - 1;
-
-	gnt_widget_get_position(widget, &x, &y);
-	gnt_widget_get_size(widget, &w, &h);
-
-	if (sanitize_position(widget, &x, &y))
-		gnt_screen_move_widget(widget, x, y);
-
-	nw = MIN(w, X_MAX);
-	nh = MIN(h, Y_MAX);
-	if (nw != w || nh != h)
-		gnt_screen_resize_widget(widget, nw, nh);
-}
-
-static void
-read_window_positions(GntWM *wm)
-{
-#if GLIB_CHECK_VERSION(2,6,0)
-	GKeyFile *gfile = g_key_file_new();
-	char *filename = g_build_filename(g_get_home_dir(), ".gntpositions", NULL);
-	GError *error = NULL;
-	char **keys;
-	gsize nk;
-
-	if (!g_key_file_load_from_file(gfile, filename, G_KEY_FILE_NONE, &error)) {
-		g_printerr("GntWM: %s\n", error->message);
-		g_error_free(error);
-		g_free(filename);
-		return;
-	}
-
-	keys = g_key_file_get_keys(gfile, "positions", &nk, &error);
-	if (error) {
-		g_printerr("GntWM: %s\n", error->message);
-		g_error_free(error);
-		error = NULL;
-	} else {
-		while (nk--) {
-			char *title = keys[nk];
-			gsize l;
-			char **coords = g_key_file_get_string_list(gfile, "positions", title, &l, NULL);
-			if (l == 2) {
-				int x = atoi(coords[0]);
-				int y = atoi(coords[1]);
-				GntPosition *p = g_new0(GntPosition, 1);
-				p->x = x;
-				p->y = y;
-				g_hash_table_replace(wm->positions, g_strdup(title + 1), p);
-			} else {
-				g_printerr("GntWM: Invalid number of arguments for positioing a window.\n");
-			}
-			g_strfreev(coords);
-		}
-		g_strfreev(keys);
-	}
-
-	g_free(filename);
-#endif
-}
-
-static gboolean check_idle(gpointer n)
-{
-	if (idle_update) {
-		time(&last_active_time);
-		idle_update = FALSE;
-	}
-	return TRUE;
-}
-
-static void
-gnt_wm_init(GTypeInstance *instance, gpointer class)
-{
-	GntWM *wm = GNT_WM(instance);
-	wm->list = NULL;
-	wm->ordered = NULL;
-	wm->event_stack = FALSE;
-	wm->windows = NULL;
-	wm->actions = NULL;
-	wm->nodes = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_node);
-	wm->positions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	if (gnt_style_get_bool(GNT_STYLE_REMPOS, TRUE))
-		read_window_positions(wm);
-	g_timeout_add(IDLE_CHECK_INTERVAL * 1000, check_idle, NULL);
-	time(&last_active_time);
-}
-
-static void
-switch_window(GntWM *wm, int direction)
-{
-	GntWidget *w = NULL, *wid = NULL;
-	int pos;
-
-	if (wm->_list.window || wm->menu)
-		return;
-
-	if (!wm->ordered || !wm->ordered->next)
-		return;
-
-	w = wm->ordered->data;
-	pos = g_list_index(wm->list, w);
-	pos += direction;
-
-	if (pos < 0)
-		wid = g_list_last(wm->list)->data;
-	else if (pos >= g_list_length(wm->list))
-		wid = wm->list->data;
-	else if (pos >= 0)
-		wid = g_list_nth_data(wm->list, pos);
-
-	wm->ordered = g_list_bring_to_front(wm->ordered, wid);
-
-	gnt_wm_raise_window(wm, wm->ordered->data);
-
-	if (w != wid) {
-		gnt_widget_set_focus(w, FALSE);
-	}
-}
-
-static gboolean
-window_next(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-	switch_window(wm, 1);
-	return TRUE;
-}
-
-static gboolean
-window_prev(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-	switch_window(wm, -1);
-	return TRUE;
-}
-
-static gboolean
-switch_window_n(GntBindable *bind, GList *list)
-{
-	GntWM *wm = GNT_WM(bind);
-	GntWidget *w = NULL;
-	GList *l;
-	int n;
-
-	if (!wm->ordered)
-		return TRUE;
-
-	if (list)
-		n = GPOINTER_TO_INT(list->data);
-	else
-		n = 0;
-
-	w = wm->ordered->data;
-
-	if ((l = g_list_nth(wm->list, n)) != NULL)
-	{
-		gnt_wm_raise_window(wm, l->data);
-	}
-
-	if (l && w != l->data)
-	{
-		gnt_widget_set_focus(w, FALSE);
-	}
-	return TRUE;
-}
-
-static gboolean
-window_scroll_up(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-	GntWidget *window;
-	GntNode *node;
-
-	if (!wm->ordered)
-		return TRUE;
-
-	window = wm->ordered->data;
-	node = g_hash_table_lookup(wm->nodes, window);
-	if (!node)
-		return TRUE;
-
-	if (node->scroll) {
-		node->scroll--;
-		copy_win(window, node);
-		update_screen(wm);
-	}
-	return TRUE;
-}
-
-static gboolean
-window_scroll_down(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-	GntWidget *window;
-	GntNode *node;
-	int w, h;
-
-	if (!wm->ordered)
-		return TRUE;
-
-	window = wm->ordered->data;
-	node = g_hash_table_lookup(wm->nodes, window);
-	if (!node)
-		return TRUE;
-
-	gnt_widget_get_size(window, &w, &h);
-	if (h - node->scroll > getmaxy(node->window)) {
-		node->scroll++;
-		copy_win(window, node);
-		update_screen(wm);
-	}
-	return TRUE;
-}
-
-static gboolean
-window_close(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-
-	if (wm->_list.window)
-		return TRUE;
-
-	if (wm->ordered) {
-		gnt_widget_destroy(wm->ordered->data);
-	}
-
-	return TRUE;
-}
-
-static void
-destroy__list(GntWidget *widget, GntWM *wm)
-{
-	wm->_list.window = NULL;
-	wm->_list.tree = NULL;
-	wm->windows = NULL;
-	wm->actions = NULL;
-	update_screen(wm);
-}
-
-static void
-setup__list(GntWM *wm)
-{
-	GntWidget *tree, *win;
-	win = wm->_list.window = gnt_box_new(FALSE, FALSE);
-	gnt_box_set_toplevel(GNT_BOX(win), TRUE);
-	gnt_box_set_pad(GNT_BOX(win), 0);
-	GNT_WIDGET_SET_FLAGS(win, GNT_WIDGET_TRANSIENT);
-
-	tree = wm->_list.tree = gnt_tree_new();
-	gnt_box_add_widget(GNT_BOX(win), tree);
-
-	g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(destroy__list), wm);
-}
-
-static void
-window_list_activate(GntTree *tree, GntWM *wm)
-{
-	GntWidget *widget = gnt_tree_get_selection_data(GNT_TREE(tree));
-
-	if (!wm->ordered || !widget)
-		return;
-
-	gnt_widget_destroy(wm->_list.window);
-	gnt_wm_raise_window(wm, widget);
-}
-
-static void
-populate_window_list(GntWM *wm)
-{
-	GList *iter;
-	GntTree *tree = GNT_TREE(wm->windows->tree);
-	for (iter = wm->list; iter; iter = iter->next) {
-		GntBox *box = GNT_BOX(iter->data);
-
-		gnt_tree_add_row_last(tree, box,
-				gnt_tree_create_row(tree, box->title), NULL);
-		update_window_in_list(wm, GNT_WIDGET(box));
-	}
-}
-
-static gboolean
-window_list_key_pressed(GntWidget *widget, const char *text, GntWM *wm)
-{
-	if (text[1] == 0 && wm->ordered) {
-		GntWidget *sel = gnt_tree_get_selection_data(GNT_TREE(widget));
-		switch (text[0]) {
-			case '-':
-			case '<':
-				shift_window(wm, sel, -1);
-				break;
-			case '+':
-			case '>':
-				shift_window(wm, sel, 1);
-				break;
-			default:
-				return FALSE;
-		}
-		gnt_tree_remove_all(GNT_TREE(widget));
-		populate_window_list(wm);
-		gnt_tree_set_selected(GNT_TREE(widget), sel);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static gboolean
-window_list(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-	GntWidget *tree, *win;
-
-	if (wm->_list.window || wm->menu)
-		return TRUE;
-
-	if (!wm->ordered)
-		return TRUE;
-
-	setup__list(wm);
-	wm->windows = &wm->_list;
-
-	win = wm->windows->window;
-	tree = wm->windows->tree;
-
-	gnt_box_set_title(GNT_BOX(win), "Window List");
-	
-	populate_window_list(wm);
-
-	gnt_tree_set_selected(GNT_TREE(tree), wm->ordered->data);
-	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(window_list_activate), wm);
-	g_signal_connect(G_OBJECT(tree), "key_pressed", G_CALLBACK(window_list_key_pressed), wm);
-
-	gnt_tree_set_col_width(GNT_TREE(tree), 0, getmaxx(stdscr) / 3);
-	gnt_widget_set_size(tree, 0, getmaxy(stdscr) / 2);
-	gnt_widget_set_position(win, getmaxx(stdscr) / 3, getmaxy(stdscr) / 4);
-
-	gnt_widget_show(win);
-	return TRUE;
-}
-
-static gboolean
-dump_screen(GntBindable *bindable, GList *null)
-{
-	int x, y;
-	chtype old = 0, now = 0;
-	FILE *file = fopen("dump.html", "w");
-
-	fprintf(file, "<pre>");
-	for (y = 0; y < getmaxy(stdscr); y++) {
-		for (x = 0; x < getmaxx(stdscr); x++) {
-			char ch;
-			now = mvwinch(curscr, y, x);
-			ch = now & A_CHARTEXT;
-			now ^= ch;
-
-#define CHECK(attr, start, end) \
-			do \
-			{  \
-				if (now & attr)  \
-				{  \
-					if (!(old & attr))  \
-						fprintf(file, "%s", start);  \
-				}  \
-				else if (old & attr)  \
-				{  \
-					fprintf(file, "%s", end);  \
-				}  \
-			} while (0) 
-
-			CHECK(A_BOLD, "<b>", "</b>");
-			CHECK(A_UNDERLINE, "<u>", "</u>");
-			CHECK(A_BLINK, "<blink>", "</blink>");
-
-			if ((now & A_COLOR) != (old & A_COLOR) ||
-				(now & A_REVERSE) != (old & A_REVERSE))
-			{
-				int ret;
-				short fgp, bgp, r, g, b;
-				struct
-				{
-					int r, g, b;
-				} fg, bg;
-
-				ret = pair_content(PAIR_NUMBER(now & A_COLOR), &fgp, &bgp);
-				if (fgp == -1)
-					fgp = COLOR_BLACK;
-				if (bgp == -1)
-					bgp = COLOR_WHITE;
-				if (now & A_REVERSE)
-					fgp ^= bgp ^= fgp ^= bgp;  /* *wink* */
-				ret = color_content(fgp, &r, &g, &b);
-				fg.r = r; fg.b = b; fg.g = g;
-				ret = color_content(bgp, &r, &g, &b);
-				bg.r = r; bg.b = b; bg.g = g;
-#define ADJUST(x) (x = x * 255 / 1000)
-				ADJUST(fg.r);
-				ADJUST(fg.g);
-				ADJUST(fg.b);
-				ADJUST(bg.r);
-				ADJUST(bg.b);
-				ADJUST(bg.g);
-				
-				if (x) fprintf(file, "</span>");
-				fprintf(file, "<span style=\"background:#%02x%02x%02x;color:#%02x%02x%02x\">",
-						bg.r, bg.g, bg.b, fg.r, fg.g, fg.b);
-			}
-			if (now & A_ALTCHARSET)
-			{
-				switch (ch)
-				{
-					case 'q':
-						ch = '-'; break;
-					case 't':
-					case 'u':
-					case 'x':
-						ch = '|'; break;
-					case 'v':
-					case 'w':
-					case 'l':
-					case 'm':
-					case 'k':
-					case 'j':
-					case 'n':
-						ch = '+'; break;
-					case '-':
-						ch = '^'; break;
-					case '.':
-						ch = 'v'; break;
-					case 'a':
-						ch = '#'; break;
-					default:
-						ch = ' '; break;
-				}
-			}
-			if (ch == '&')
-				fprintf(file, "&amp;");
-			else if (ch == '<')
-				fprintf(file, "&lt;");
-			else if (ch == '>')
-				fprintf(file, "&gt;");
-			else
-				fprintf(file, "%c", ch);
-			old = now;
-		}
-		fprintf(file, "</span>\n");
-		old = 0;
-	}
-	fprintf(file, "</pre>");
-	fclose(file);
-	return TRUE;
-}
-
-static void
-shift_window(GntWM *wm, GntWidget *widget, int dir)
-{
-	GList *all = wm->list;
-	GList *list = g_list_find(all, widget);
-	int length, pos;
-	if (!list)
-		return;
-
-	length = g_list_length(all);
-	pos = g_list_position(all, list);
-
-	pos += dir;
-	if (dir > 0)
-		pos++;
-
-	if (pos < 0)
-		pos = length;
-	else if (pos > length)
-		pos = 0;
-
-	all = g_list_insert(all, widget, pos);
-	all = g_list_delete_link(all, list);
-	wm->list = all;
-	draw_taskbar(wm, FALSE);
-}
-
-static gboolean
-shift_left(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-	if (wm->_list.window)
-		return TRUE;
-
-	shift_window(wm, wm->ordered->data, -1);
-	return TRUE;
-}
-
-static gboolean
-shift_right(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-	if (wm->_list.window)
-		return TRUE;
-
-	shift_window(wm, wm->ordered->data, 1);
-	return TRUE;
-}
-
-static void
-action_list_activate(GntTree *tree, GntWM *wm)
-{
-	GntAction *action = gnt_tree_get_selection_data(tree);
-	action->callback();
-	gnt_widget_destroy(wm->_list.window);
-}
-
-static int
-compare_action(gconstpointer p1, gconstpointer p2)
-{
-	const GntAction *a1 = p1;
-	const GntAction *a2 = p2;
-
-	return g_utf8_collate(a1->label, a2->label);
-}
-
-static gboolean
-list_actions(GntBindable *bindable, GList *null)
-{
-	GntWidget *tree, *win;
-	GList *iter;
-	GntWM *wm = GNT_WM(bindable);
-	if (wm->_list.window || wm->menu)
-		return TRUE;
-
-	if (wm->acts == NULL)
-		return TRUE;
-
-	setup__list(wm);
-	wm->actions = &wm->_list;
-
-	win = wm->actions->window;
-	tree = wm->actions->tree;
-
-	gnt_box_set_title(GNT_BOX(win), "Actions");
-	GNT_WIDGET_SET_FLAGS(tree, GNT_WIDGET_NO_BORDER);
-	/* XXX: Do we really want this? */
-	gnt_tree_set_compare_func(GNT_TREE(tree), compare_action);
-
-	for (iter = wm->acts; iter; iter = iter->next) {
-		GntAction *action = iter->data;
-		gnt_tree_add_row_last(GNT_TREE(tree), action,
-				gnt_tree_create_row(GNT_TREE(tree), action->label), NULL);
-	}
-	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(action_list_activate), wm);
-	gnt_widget_set_size(tree, 0, g_list_length(wm->acts));
-	gnt_widget_set_position(win, 0, getmaxy(stdscr) - 3 - g_list_length(wm->acts));
-
-	gnt_widget_show(win);
-	return TRUE;
-}
-
-#ifndef NO_WIDECHAR
-static int
-widestringwidth(wchar_t *wide)
-{
-	int len, ret;
-	char *string;
-
-	len = wcstombs(NULL, wide, 0) + 1;
-	string = g_new0(char, len);
-	wcstombs(string, wide, len);
-	ret = gnt_util_onscreen_width(string, NULL);
-	g_free(string);
-	return ret;
-}
-#endif
-
-/* Returns the onscreen width of the character at the position */
-static int
-reverse_char(WINDOW *d, int y, int x, gboolean set)
-{
-#define DECIDE(ch) (set ? ((ch) | A_REVERSE) : ((ch) & ~A_REVERSE))
-
-#ifdef NO_WIDECHAR
-	chtype ch;
-	ch = mvwinch(d, y, x);
-	mvwaddch(d, y, x, DECIDE(ch));
-	return 1;
-#else
-	cchar_t ch;
-	int wc = 1;
-	if (mvwin_wch(d, y, x, &ch) == OK) {
-		wc = widestringwidth(ch.chars);
-		ch.attr = DECIDE(ch.attr);
-		ch.attr &= WA_ATTRIBUTES;   /* XXX: This is a workaround for a bug */
-		mvwadd_wch(d, y, x, &ch);
-	}
-
-	return wc;
-#endif
-}
-
-static void
-window_reverse(GntWidget *win, gboolean set, GntWM *wm)
-{
-	int i;
-	int w, h;
-	WINDOW *d;
-
-	if (GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_NO_BORDER))
-		return;
-	
-	d = win->window;
-	gnt_widget_get_size(win, &w, &h);
-
-	if (gnt_widget_has_shadow(win)) {
-		--w;
-		--h;
-	}
-
-	/* the top and bottom */
-	for (i = 0; i < w; i += reverse_char(d, 0, i, set));
-	for (i = 0; i < w; i += reverse_char(d, h-1, i, set));
-
-	/* the left and right */
-	for (i = 0; i < h; i += reverse_char(d, i, 0, set));
-	for (i = 0; i < h; i += reverse_char(d, i, w-1, set));
-
-	copy_win(win, g_hash_table_lookup(wm->nodes, win));
-	update_screen(wm);
-}
-
-static gboolean
-start_move(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-	if (wm->_list.window || wm->menu)
-		return TRUE;
-	if (!wm->ordered)
-		return TRUE;
-
-	wm->mode = GNT_KP_MODE_MOVE;
-	window_reverse(GNT_WIDGET(wm->ordered->data), TRUE, wm);
-
-	return TRUE;
-}
-
-static gboolean
-start_resize(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-	if (wm->_list.window || wm->menu)
-		return TRUE;
-	if (!wm->ordered)
-		return TRUE;
-
-	wm->mode = GNT_KP_MODE_RESIZE;
-	window_reverse(GNT_WIDGET(wm->ordered->data), TRUE, wm);
-
-	return TRUE;
-}
-
-static gboolean
-wm_quit(GntBindable *bindable, GList *list)
-{
-	GntWM *wm = GNT_WM(bindable);
-	if (write_timeout)
-		write_already(wm);
-	g_main_loop_quit(wm->loop);
-	return TRUE;
-}
-
-static gboolean
-return_true(GntWM *wm, GntWidget *w, int *a, int *b)
-{
-	return TRUE;
-}
-
-static gboolean
-refresh_screen(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-
-	endwin();
-	refresh();
-	curs_set(0);   /* endwin resets the cursor to normal */
-
-	g_hash_table_foreach(wm->nodes, (GHFunc)refresh_node, NULL);
-	update_screen(wm);
-	draw_taskbar(wm, TRUE);
-
-	return FALSE;
-}
-
-static void
-gnt_wm_class_init(GntWMClass *klass)
-{
-	int i;
-
-	klass->new_window = gnt_wm_new_window_real;
-	klass->decorate_window = NULL;
-	klass->close_window = NULL;
-	klass->window_resize_confirm = return_true;
-	klass->window_resized = gnt_wm_win_resized;
-	klass->window_move_confirm = return_true;
-	klass->window_moved = gnt_wm_win_moved;
-	klass->window_update = NULL;
-	klass->key_pressed  = NULL;
-	klass->mouse_clicked = NULL;
-	klass->give_focus = gnt_wm_give_focus;
-	
-	signals[SIG_NEW_WIN] = 
-		g_signal_new("new_win",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWMClass, new_window),
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__POINTER,
-					 G_TYPE_NONE, 1, G_TYPE_POINTER);
-	signals[SIG_DECORATE_WIN] = 
-		g_signal_new("decorate_win",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWMClass, decorate_window),
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__POINTER,
-					 G_TYPE_NONE, 1, G_TYPE_POINTER);
-	signals[SIG_CLOSE_WIN] = 
-		g_signal_new("close_win",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWMClass, close_window),
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__POINTER,
-					 G_TYPE_NONE, 1, G_TYPE_POINTER);
-	signals[SIG_CONFIRM_RESIZE] = 
-		g_signal_new("confirm_resize",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWMClass, window_resize_confirm),
-					 gnt_boolean_handled_accumulator, NULL,
-					 gnt_closure_marshal_BOOLEAN__POINTER_POINTER_POINTER,
-					 G_TYPE_BOOLEAN, 3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER);
-
-	signals[SIG_CONFIRM_MOVE] = 
-		g_signal_new("confirm_move",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWMClass, window_move_confirm),
-					 gnt_boolean_handled_accumulator, NULL,
-					 gnt_closure_marshal_BOOLEAN__POINTER_POINTER_POINTER,
-					 G_TYPE_BOOLEAN, 3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER);
-
-	signals[SIG_RESIZED] = 
-		g_signal_new("window_resized",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWMClass, window_resized),
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__POINTER,
-					 G_TYPE_NONE, 1, G_TYPE_POINTER);
-	signals[SIG_MOVED] = 
-		g_signal_new("window_moved",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWMClass, window_moved),
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__POINTER,
-					 G_TYPE_NONE, 1, G_TYPE_POINTER);
-	signals[SIG_UPDATE_WIN] = 
-		g_signal_new("window_update",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWMClass, window_update),
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__POINTER,
-					 G_TYPE_NONE, 1, G_TYPE_POINTER);
-
-	signals[SIG_GIVE_FOCUS] = 
-		g_signal_new("give_focus",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWMClass, give_focus),
-					 NULL, NULL,
-					 g_cclosure_marshal_VOID__POINTER,
-					 G_TYPE_NONE, 1, G_TYPE_POINTER);
-
-	signals[SIG_MOUSE_CLICK] = 
-		g_signal_new("mouse_clicked",
-					 G_TYPE_FROM_CLASS(klass),
-					 G_SIGNAL_RUN_LAST,
-					 G_STRUCT_OFFSET(GntWMClass, mouse_clicked),
-					 gnt_boolean_handled_accumulator, NULL,
-					 gnt_closure_marshal_BOOLEAN__INT_INT_INT_POINTER,
-					 G_TYPE_BOOLEAN, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_POINTER);
-
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-next", window_next,
-				"\033" "n", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-prev", window_prev,
-				"\033" "p", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-close", window_close,
-				"\033" "c", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-list", window_list,
-				"\033" "w", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "dump-screen", dump_screen,
-				"\033" "d", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "shift-left", shift_left,
-				"\033" ",", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "shift-right", shift_right,
-				"\033" ".", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "action-list", list_actions,
-				"\033" "a", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "start-move", start_move,
-				"\033" "m", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "start-resize", start_resize,
-				"\033" "r", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "wm-quit", wm_quit,
-				"\033" "q", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "refresh-screen", refresh_screen,
-				"\033" "l", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "switch-window-n", switch_window_n,
-				NULL, NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-scroll-down", window_scroll_down,
-				"\033" GNT_KEY_CTRL_J, NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-scroll-up", window_scroll_up,
-				"\033" GNT_KEY_CTRL_K, NULL);
-
-	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
-
-	/* Make sure Alt+x are detected properly. */
-	for (i = '0'; i <= '9'; i++) {
-		char str[] = "\033X";
-		str[1] = i;
-		gnt_keys_add_combination(str);
-	}
-
-	GNTDEBUG;
-}
-
-/******************************************************************************
- * GntWM API
- *****************************************************************************/
-GType
-gnt_wm_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0) {
-		static const GTypeInfo info = {
-			sizeof(GntWMClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)gnt_wm_class_init,
-			NULL,
-			NULL,					/* class_data		*/
-			sizeof(GntWM),
-			0,						/* n_preallocs		*/
-			gnt_wm_init,			/* instance_init	*/
-			NULL					/* value_table		*/
-		};
-
-		type = g_type_register_static(GNT_TYPE_BINDABLE,
-									  "GntWM",
-									  &info, 0);
-	}
-
-	return type;
-}
-static void
-update_window_in_list(GntWM *wm, GntWidget *wid)
-{
-	GntTextFormatFlags flag = 0;
-
-	if (wm->windows == NULL)
-		return;
-
-	if (wid == wm->ordered->data)
-		flag |= GNT_TEXT_FLAG_DIM;
-	else if (GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_URGENT))
-		flag |= GNT_TEXT_FLAG_BOLD;
-
-	gnt_tree_set_row_flags(GNT_TREE(wm->windows->tree), wid, flag);
-}
-
-static void
-gnt_wm_new_window_real(GntWM *wm, GntWidget *widget)
-{
-	GntNode *node;
-	gboolean transient = FALSE;
-
-	if (widget->window == NULL)
-		return;
-
-	node = g_new0(GntNode, 1);
-	node->me = widget;
-	node->scroll = 0;
-
-	g_hash_table_replace(wm->nodes, widget, node);
-
-	refresh_node(widget, node, NULL);
-
-	transient = !!GNT_WIDGET_IS_FLAG_SET(node->me, GNT_WIDGET_TRANSIENT);
-
-#if 1
-	{
-		int x, y, w, h, maxx, maxy;
-		gboolean shadow = TRUE;
-
-		if (!gnt_widget_has_shadow(widget))
-			shadow = FALSE;
-		x = widget->priv.x;
-		y = widget->priv.y;
-		w = widget->priv.width;
-		h = widget->priv.height;
-
-		getmaxyx(stdscr, maxy, maxx);
-		maxy -= 1;              /* room for the taskbar */
-		maxy -= shadow;
-		maxx -= shadow;
-
-		x = MAX(0, x);
-		y = MAX(0, y);
-		if (x + w >= maxx)
-			x = MAX(0, maxx - w);
-		if (y + h >= maxy)
-			y = MAX(0, maxy - h);
-
-		w = MIN(w, maxx);
-		h = MIN(h, maxy);
-		node->window = newwin(h + shadow, w + shadow, y, x);
-		copy_win(widget, node);
-	}
-#endif
-
-	node->panel = new_panel(node->window);
-	set_panel_userptr(node->panel, node);
-
-	if (!transient) {
-		if (node->me != wm->_list.window) {
-			GntWidget *w = NULL;
-
-			if (wm->ordered)
-				w = wm->ordered->data;
-
-			wm->list = g_list_append(wm->list, widget);
-
-			if (wm->event_stack)
-				wm->ordered = g_list_prepend(wm->ordered, widget);
-			else
-				wm->ordered = g_list_append(wm->ordered, widget);
-
-			gnt_widget_set_focus(widget, TRUE);
-			if (w)
-				gnt_widget_set_focus(w, FALSE);
-		}
-
-		if (wm->event_stack || node->me == wm->_list.window) {
-			gnt_wm_raise_window(wm, node->me);
-		} else {
-			bottom_panel(node->panel);     /* New windows should not grab focus */
-			gnt_widget_set_urgent(node->me);
-		}
-	}
-}
-
-void gnt_wm_new_window(GntWM *wm, GntWidget *widget)
-{
-	while (widget->parent)
-		widget = widget->parent;
-	
-	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_INVISIBLE) ||
-			g_hash_table_lookup(wm->nodes, widget)) {
-		update_screen(wm);
-		return;
-	}
-
-	if (GNT_IS_BOX(widget)) {
-		const char *title = GNT_BOX(widget)->title;
-		GntPosition *p = NULL;
-		if (title && (p = g_hash_table_lookup(wm->positions, title)) != NULL) {
-			sanitize_position(widget, &p->x, &p->y);
-			gnt_widget_set_position(widget, p->x, p->y);
-			mvwin(widget->window, p->y, p->x);
-		}
-	}
-
-	g_signal_emit(wm, signals[SIG_NEW_WIN], 0, widget);
-	g_signal_emit(wm, signals[SIG_DECORATE_WIN], 0, widget);
-
-	if (wm->windows && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) {
-		if ((GNT_IS_BOX(widget) && GNT_BOX(widget)->title) && wm->_list.window != widget
-				&& GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS)) {
-			gnt_tree_add_row_last(GNT_TREE(wm->windows->tree), widget,
-					gnt_tree_create_row(GNT_TREE(wm->windows->tree), GNT_BOX(widget)->title),
-					NULL);
-			update_window_in_list(wm, widget);
-		}
-	}
-
-	update_screen(wm);
-	draw_taskbar(wm, FALSE);
-}
-
-void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget)
-{
-	g_signal_emit(wm, signals[SIG_DECORATE_WIN], 0, widget);
-}
-
-void gnt_wm_window_close(GntWM *wm, GntWidget *widget)
-{
-	GntNode *node;
-	int pos;
-
-	if ((node = g_hash_table_lookup(wm->nodes, widget)) == NULL)
-		return;
-
-	g_signal_emit(wm, signals[SIG_CLOSE_WIN], 0, widget);
-	g_hash_table_remove(wm->nodes, widget);
-
-	if (wm->windows) {
-		gnt_tree_remove(GNT_TREE(wm->windows->tree), widget);
-	}
-
-	pos = g_list_index(wm->list, widget);
-
-	if (pos != -1) {
-		wm->list = g_list_remove(wm->list, widget);
-		wm->ordered = g_list_remove(wm->ordered, widget);
-
-		if (wm->ordered)
-			gnt_wm_raise_window(wm, wm->ordered->data);
-	}
-
-	update_screen(wm);
-	draw_taskbar(wm, FALSE);
-}
-
-time_t gnt_wm_get_idle_time()
-{
-	return time(NULL) - last_active_time;
-}
-
-gboolean gnt_wm_process_input(GntWM *wm, const char *keys)
-{
-	gboolean ret = FALSE;
-
-	keys = gnt_bindable_remap_keys(GNT_BINDABLE(wm), keys);
-
-	idle_update = TRUE;
-
-	if (gnt_bindable_perform_action_key(GNT_BINDABLE(wm), keys))
-		return TRUE;
-
-	/* Do some manual checking */
-	if (wm->ordered && wm->mode != GNT_KP_MODE_NORMAL) {
-		int xmin = 0, ymin = 0, xmax = getmaxx(stdscr), ymax = getmaxy(stdscr) - 1;
-		int x, y, w, h;
-		GntWidget *widget = GNT_WIDGET(wm->ordered->data);
-		int ox, oy, ow, oh;
-
-		gnt_widget_get_position(widget, &x, &y);
-		gnt_widget_get_size(widget, &w, &h);
-		ox = x;	oy = y;
-		ow = w;	oh = h;
-
-		if (wm->mode == GNT_KP_MODE_MOVE) {
-			if (strcmp(keys, GNT_KEY_LEFT) == 0) {
-				if (x > xmin)
-					x--;
-			} else if (strcmp(keys, GNT_KEY_RIGHT) == 0) {
-				if (x + w < xmax)
-					x++;
-			} else if (strcmp(keys, GNT_KEY_UP) == 0) {
-				if (y > ymin)
-					y--;
-			} else if (strcmp(keys, GNT_KEY_DOWN) == 0) {
-				if (y + h < ymax)
-					y++;
-			}
-			if (ox != x || oy != y) {
-				gnt_screen_move_widget(widget, x, y);
-				window_reverse(widget, TRUE, wm);
-				return TRUE;
-			}
-		} else if (wm->mode == GNT_KP_MODE_RESIZE) {
-			if (strcmp(keys, GNT_KEY_LEFT) == 0) {
-				w--;
-			} else if (strcmp(keys, GNT_KEY_RIGHT) == 0) {
-				if (x + w < xmax)
-					w++;
-			} else if (strcmp(keys, GNT_KEY_UP) == 0) {
-				h--;
-			} else if (strcmp(keys, GNT_KEY_DOWN) == 0) {
-				if (y + h < ymax)
-					h++;
-			}
-			if (oh != h || ow != w) {
-				gnt_screen_resize_widget(widget, w, h);
-				window_reverse(widget, TRUE, wm);
-				return TRUE;
-			}
-		}
-		if (strcmp(keys, "\r") == 0 || strcmp(keys, "\033") == 0) {
-			window_reverse(widget, FALSE, wm);
-			wm->mode = GNT_KP_MODE_NORMAL;
-		}
-		return TRUE;
-	}
-
-	wm->event_stack = TRUE;
-
-	/* Escape to close the window-list or action-list window */
-	if (strcmp(keys, "\033") == 0) {
-		if (wm->_list.window) {
-			gnt_widget_destroy(wm->_list.window);
-			wm->event_stack = FALSE;
-			return TRUE;
-		}
-	} else if (keys[0] == '\033' && isdigit(keys[1]) && keys[2] == '\0') {
-		/* Alt+x for quick switch */
-		int n = *(keys + 1) - '0';
-		GList *list = NULL;
-
-		if (n == 0)
-			n = 10;
-
-		list = g_list_append(list, GINT_TO_POINTER(n - 1));
-		switch_window_n(GNT_BINDABLE(wm), list);
-		g_list_free(list);
-		return TRUE;
-	}
-
-	if (wm->menu)
-		ret = gnt_widget_key_pressed(GNT_WIDGET(wm->menu), keys);
-	else if (wm->_list.window)
-		ret = gnt_widget_key_pressed(wm->_list.window, keys);
-	else if (wm->ordered)
-		ret = gnt_widget_key_pressed(GNT_WIDGET(wm->ordered->data), keys);
-	wm->event_stack = FALSE;
-	return ret;
-}
-
-static void
-gnt_wm_win_resized(GntWM *wm, GntNode *node)
-{
-	/*refresh_node(node->me, node, NULL);*/
-}
-
-static void
-gnt_wm_win_moved(GntWM *wm, GntNode *node)
-{
-	refresh_node(node->me, node, NULL);
-}
-
-void gnt_wm_resize_window(GntWM *wm, GntWidget *widget, int width, int height)
-{
-	gboolean ret = TRUE;
-	GntNode *node;
-	int shadow;
-	int maxx, maxy;
-	
-	while (widget->parent)
-		widget = widget->parent;
-	node = g_hash_table_lookup(wm->nodes, widget);
-	if (!node)
-		return;
-
-	g_signal_emit(wm, signals[SIG_CONFIRM_RESIZE], 0, widget, &width, &height, &ret);
-	if (!ret)
-		return;    /* resize is not permitted */
-	hide_panel(node->panel);
-	gnt_widget_set_size(widget, width, height);
-	gnt_widget_draw(widget);
-
-	shadow = gnt_widget_has_shadow(widget) ? 1 : 0;
-	maxx = getmaxx(stdscr) - shadow;
-	maxy = getmaxy(stdscr) - 1 - shadow;
-	height = MIN(height, maxy);
-	width = MIN(width, maxx);
-	wresize(node->window, height + shadow, width + shadow);
-	replace_panel(node->panel, node->window);
-
-	g_signal_emit(wm, signals[SIG_RESIZED], 0, node);
-
-	show_panel(node->panel);
-	update_screen(wm);
-}
-
-static void
-write_gdi(gpointer key, gpointer value, gpointer data)
-{
-	GntPosition *p = value;
-	fprintf(data, ".%s = %d;%d\n", (char *)key, p->x, p->y);
-}
-
-static gboolean
-write_already(gpointer data)
-{
-	GntWM *wm = data;
-	FILE *file;
-	char *filename;
-
-	filename = g_build_filename(g_get_home_dir(), ".gntpositions", NULL);
-
-	file = fopen(filename, "wb");
-	if (file == NULL) {
-		g_printerr("GntWM: error opening file to save positions\n");
-	} else {
-		fprintf(file, "[positions]\n");
-		g_hash_table_foreach(wm->positions, write_gdi, file);
-		fclose(file);
-	}
-
-	g_free(filename);
-	g_source_remove(write_timeout);
-	write_timeout = 0;
-	return FALSE;
-}
-
-static void
-write_positions_to_file(GntWM *wm)
-{
-	if (write_timeout) {
-		g_source_remove(write_timeout);
-	}
-	write_timeout = g_timeout_add(10000, write_already, wm);
-}
-
-void gnt_wm_move_window(GntWM *wm, GntWidget *widget, int x, int y)
-{
-	gboolean ret = TRUE;
-	GntNode *node;
-
-	while (widget->parent)
-		widget = widget->parent;
-	node = g_hash_table_lookup(wm->nodes, widget);
-	if (!node)
-		return;
-
-	g_signal_emit(wm, signals[SIG_CONFIRM_MOVE], 0, widget, &x, &y, &ret);
-	if (!ret)
-		return;    /* resize is not permitted */
-
-	gnt_widget_set_position(widget, x, y);
-	move_panel(node->panel, y, x);
-
-	g_signal_emit(wm, signals[SIG_MOVED], 0, node);
-	if (gnt_style_get_bool(GNT_STYLE_REMPOS, TRUE) && GNT_IS_BOX(widget)) {
-		const char *title = GNT_BOX(widget)->title;
-		if (title) {
-			GntPosition *p = g_new0(GntPosition, 1);
-			GntWidget *wid = node->me;
-			p->x = wid->priv.x;
-			p->y = wid->priv.y;
-			g_hash_table_replace(wm->positions, g_strdup(title), p);
-			write_positions_to_file(wm);
-		}
-	}
-
-	update_screen(wm);
-}
-
-static void
-gnt_wm_give_focus(GntWM *wm, GntWidget *widget)
-{
-	GntNode *node = g_hash_table_lookup(wm->nodes, widget);
-
-	if (!node)
-		return;
-	
-	if (widget != wm->_list.window && !GNT_IS_MENU(widget) &&
-				wm->ordered->data != widget) {
-		GntWidget *w = wm->ordered->data;
-		wm->ordered = g_list_bring_to_front(wm->ordered, widget);
-		gnt_widget_set_focus(w, FALSE);
-	}
-
-	gnt_widget_set_focus(widget, TRUE);
-	GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_URGENT);
-	gnt_widget_draw(widget);
-	top_panel(node->panel);
-
-	if (wm->_list.window) {
-		GntNode *nd = g_hash_table_lookup(wm->nodes, wm->_list.window);
-		top_panel(nd->panel);
-	}
-	update_screen(wm);
-	draw_taskbar(wm, FALSE);
-}
-
-void gnt_wm_update_window(GntWM *wm, GntWidget *widget)
-{
-	GntNode *node;
-
-	while (widget->parent)
-		widget = widget->parent;
-	if (!GNT_IS_MENU(widget))
-		gnt_box_sync_children(GNT_BOX(widget));
-
-	node = g_hash_table_lookup(wm->nodes, widget);
-	if (node == NULL) {
-		gnt_wm_new_window(wm, widget);
-	} else
-		g_signal_emit(wm, signals[SIG_UPDATE_WIN], 0, node);
-
-	copy_win(widget, node);
-	update_screen(wm);
-	draw_taskbar(wm, FALSE);
-}
-
-gboolean gnt_wm_process_click(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget)
-{
-	gboolean ret = TRUE;
-	idle_update = TRUE;
-	g_signal_emit(wm, signals[SIG_MOUSE_CLICK], 0, event, x, y, widget, &ret);
-	return ret;
-}
-
-void gnt_wm_raise_window(GntWM *wm, GntWidget *widget)
-{
-	g_signal_emit(wm, signals[SIG_GIVE_FOCUS], 0, widget);
-}
-
--- a/console/libgnt/gntwm.h	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-
-#include "gntwidget.h"
-#include "gntmenu.h"
-
-#include <panel.h>
-
-#define GNT_TYPE_WM				(gnt_wm_get_gtype())
-#define GNT_WM(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_WM, GntWM))
-#define GNT_WM_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_WM, GntWMClass))
-#define GNT_IS_WM(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_WM))
-#define GNT_IS_WM_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WM))
-#define GNT_WM_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WM, GntWMClass))
-
-typedef enum
-{
-	GNT_KP_MODE_NORMAL,
-	GNT_KP_MODE_RESIZE,
-	GNT_KP_MODE_MOVE,
-} GntKeyPressMode;
-
-typedef struct
-{
-	GntWidget *me;
-
-	WINDOW *window;
-	int scroll;
-	PANEL *panel;
-} GntNode;
-
-typedef struct _GntWM GntWM;
-
-typedef struct _GnPosition
-{
-	int x;
-	int y;
-} GntPosition;
-
-/**
- * An application can register actions which will show up in a 'start-menu' like popup
- */
-typedef struct _GnAction
-{
-	const char *label;
-	void (*callback)();
-} GntAction;
-
-struct _GntWM
-{
-	GntBindable inherit;
-
-	GMainLoop *loop;
-
-	GList *list;      /* List of windows ordered on their creation time */
-	GList *ordered;   /* List of windows ordered on their focus */
-
-	struct {
-		GntWidget *window;
-		GntWidget *tree;
-	} _list,
-		*windows,         /* Window-list window */
-		*actions;         /* Action-list window */
-
-	GHashTable *nodes;    /* GntWidget -> GntNode */
-
-	GList *acts;          /* List of actions */
-
-	/**
-	 * There can be at most one menu at a time on the screen.
-	 * If there is a menu being displayed, then all the keystrokes will be sent to
-	 * the menu until it is closed, either when the user activates a menuitem, or
-	 * presses Escape to cancel the menu.
-	 */
-	GntMenu *menu;        /* Currently active menu */
-
-	/**
-	 * 'event_stack' will be set to TRUE when a user-event, ie. a mouse-click
-	 * or a key-press is being processed. This variable will be used to determine
-	 * whether to give focus to a new window.
-	 */
-	gboolean event_stack;
-	
-	GntKeyPressMode mode;
-
-	GHashTable *positions;
-
-	void *res1;
-	void *res2;
-	void *res3;
-	void *res4;
-};
-
-typedef struct _GnWMClass GntWMClass;
-
-struct _GnWMClass
-{
-	GntBindableClass parent;
-
-	/* This is called when a new window is shown */
-	void (*new_window)(GntWM *wm, GntWidget *win);
-
-	void (*decorate_window)(GntWM *wm, GntWidget *win);
-	/* This is called when a window is being closed */
-	gboolean (*close_window)(GntWM *wm, GntWidget *win);
-
-	/* The WM may want to confirm a size for a window first */
-	gboolean (*window_resize_confirm)(GntWM *wm, GntWidget *win, int *w, int *h);
-
-	void (*window_resized)(GntWM *wm, GntNode *node);
-
-	/* The WM may want to confirm the position of a window */
-	gboolean (*window_move_confirm)(GntWM *wm, GntWidget *win, int *x, int *y);
-
-	void (*window_moved)(GntWM *wm, GntNode *node);
-
-	/* This gets called when:
-	 * 	 - the title of the window changes
-	 * 	 - the 'urgency' of the window changes
-	 */
-	void (*window_update)(GntWM *wm, GntNode *node);
-
-	/* This should usually return NULL if the keys were processed by the WM.
-	 * If not, the WM can simply return the original string, which will be
-	 * processed by the default WM. The custom WM can also return a different
-	 * static string for the default WM to process.
-	 */
-	gboolean (*key_pressed)(GntWM *wm, const char *key);
-
-	gboolean (*mouse_clicked)(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget);
-
-	/* Whatever the WM wants to do when a window is given focus */
-	void (*give_focus)(GntWM *wm, GntWidget *widget);
-
-	/* List of windows. Although the WM can keep a list of its own for the windows,
-	 * it'd be better if there was a way to share between the 'core' and the WM.
-	 */
-	/*const GList *(*window_list)();*/
-
-	void (*res1)(void);
-	void (*res2)(void);
-	void (*res3)(void);
-	void (*res4)(void);
-};
-
-G_BEGIN_DECLS
-
-GType gnt_wm_get_gtype(void);
-
-void gnt_wm_new_window(GntWM *wm, GntWidget *widget);
-
-void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget);
-
-void gnt_wm_window_close(GntWM *wm, GntWidget *widget);
-
-gboolean gnt_wm_process_input(GntWM *wm, const char *string);
-
-gboolean gnt_wm_process_click(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget);
-
-void gnt_wm_resize_window(GntWM *wm, GntWidget *widget, int width, int height);
-
-void gnt_wm_move_window(GntWM *wm, GntWidget *widget, int x, int y);
-
-void gnt_wm_update_window(GntWM *wm, GntWidget *widget);
-
-void gnt_wm_raise_window(GntWM *wm, GntWidget *widget);
-
-time_t gnt_wm_get_idle_time(void);
-
-G_END_DECLS
--- a/console/libgnt/test.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-#include "gntbutton.h"
-#include "gnt.h"
-#include "gntkeys.h"
-#include "gnttree.h"
-#include "gntbox.h"
-
-static gboolean
-key_pressed(GntWidget *widget, const char *text, gpointer null)
-{
-	GntWidget *w = null;
-	GntWidget *box = gnt_box_new(FALSE, FALSE);
-	GntWidget *label = gnt_label_new("so wassup!!");
-
-	gnt_box_add_widget(GNT_BOX(box), label);
-	GNT_WIDGET_UNSET_FLAGS(box, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
-	gnt_box_set_title(GNT_BOX(box), "This is a test");
-
-	gnt_widget_show(box);
-#if 0
-
-	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);
-#endif
-
-	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(GNT_BOX(vbox), widget);
-	gnt_box_add_widget(GNT_BOX(vbox), widget2);
-
-	gnt_box_add_widget(GNT_BOX(hbox), label);
-	/*gnt_box_add_widget(GNT_BOX(hbox), vbox);*/
-
-	gnt_box_add_widget(GNT_BOX(hbox), gnt_entry_new("a"));
-
-	tree = gnt_tree_new();
-	gnt_box_add_widget(GNT_BOX(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(GNT_BOX(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), tree);
-	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;
-}
-
--- a/console/libgnt/test/Makefile	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-CC=gcc
-CFLAGS=`pkg-config --cflags gobject-2.0 gmodule-2.0` -g -I../ -DSTANDALONE
-LDFLAGS=`pkg-config --libs gobject-2.0 gmodule-2.0 gnt` -pg
-
-EXAMPLES=combo focus tv multiwin keys menu
-
-all:
-	make examples
-
-clean:
-	rm -f $(EXAMPLES) *.so wm
-
-WM: wm
-	for i in $(EXAMPLES); do gcc -shared $(CFLAGS) -USTANDALONE $(LDFLAGS) $${i}.c -o $${i}.so ; done
-
-examples: $(EXAMPLES)
--- a/console/libgnt/test/combo.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntbutton.h>
-#include <gntcheckbox.h>
-#include <gntcombobox.h>
-#include <gntlabel.h>
-
-static void
-button_activated(GntWidget *b, GntComboBox *combo)
-{
-	GntWidget *w = b->parent;
-
-	gnt_box_add_widget(GNT_BOX(w),
-			gnt_label_new(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))));
-	fprintf(stderr, "%s\n", gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)));
-	gnt_box_readjust(GNT_BOX(w->parent));
-}
-
-int main()
-{
-	GntWidget *box, *combo, *button;
-	GntWidget *hbox;
-
-#ifdef STANDALONE
-	freopen(".error", "w", stderr);
-	gnt_init();
-#endif
-	
-	box = gnt_box_new(FALSE, TRUE);
-	gnt_widget_set_name(box, "box");
-	gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID);
-	gnt_box_set_pad(GNT_BOX(box), 0);
-
-	gnt_box_set_toplevel(GNT_BOX(box), TRUE);
-	gnt_box_set_title(GNT_BOX(box), "Checkbox");
-
-	hbox = gnt_box_new(FALSE, FALSE);
-	gnt_box_set_pad(GNT_BOX(hbox), 0);
-	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
-	gnt_widget_set_name(hbox, "upper");
-
-	combo = gnt_combo_box_new();
-	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "1", "1");
-	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "2", "2");
-	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "3", "3abcdefghijklmnopqrstuvwxyz");
-	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "4", "4");
-	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "5", "5");
-	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "6", "6");
-	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "7", "7");
-	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "8", "8");
-	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "9", "9");
-
-	GntWidget *l = gnt_label_new("Select");
-	gnt_box_add_widget(GNT_BOX(hbox), l);
-	gnt_widget_set_size(l, 0, 1);
-	gnt_box_add_widget(GNT_BOX(hbox), combo);
-
-	gnt_box_add_widget(GNT_BOX(box), hbox);
-
-	hbox = gnt_box_new(TRUE, FALSE);
-	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
-	gnt_widget_set_name(hbox, "lower");
-
-	button = gnt_button_new("OK");
-	gnt_box_add_widget(GNT_BOX(hbox), button);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(button_activated), combo);
-
-	gnt_box_add_widget(GNT_BOX(box), hbox);
-
-	gnt_box_add_widget(GNT_BOX(box), gnt_check_box_new("check box"));
-
-	gnt_widget_show(box);
-
-#ifdef STANDALONE
-	gnt_main();
-
-	gnt_quit();
-#endif
-
-	return 0;
-}
-
--- a/console/libgnt/test/focus.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-#include "gntbutton.h"
-#include "gnt.h"
-#include "gntkeys.h"
-#include "gnttree.h"
-#include "gntbox.h"
-#include "gntentry.h"
-#include "gntlabel.h"
-
-static void
-toggled(GntWidget *tree, gpointer key, gpointer null)
-{
-	GntWidget *w = gnt_box_new(FALSE, FALSE);
-
-	gnt_box_set_toplevel(GNT_BOX(w), TRUE);
-
-	gnt_box_add_widget(GNT_BOX(w),
-			gnt_label_new(gnt_tree_get_choice(GNT_TREE(tree), key) ? "Selected" : "NOT"));
-	gnt_widget_show(w);
-}
-
-int main()
-{
-#ifdef STANDALONE
-	freopen(".error", "w", stderr);
-	gnt_init();
-#endif
-	
-	GntWidget *label = gnt_label_new("So wassup dudes and dudettes!!\u4e0a1\u6d772\u67003\u4f4e4\u67085\nSo this is, like,\nthe third line!! \\o/");
-	GntWidget *vbox, *hbox, *tree, *box, *button;
-	WINDOW *test;
-
-	vbox = gnt_box_new(FALSE, FALSE);
-	hbox = gnt_box_new(FALSE, TRUE);
-	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
-
-	gnt_widget_set_name(vbox, "vbox");
-	gnt_widget_set_name(hbox, "hbox");
-
-	gnt_box_add_widget(GNT_BOX(hbox), label);
-
-	GntWidget *entry = gnt_entry_new("a");
-	gnt_widget_set_name(entry, "entry");
-	gnt_box_add_widget(GNT_BOX(hbox), entry);
-
-	box = gnt_box_new(FALSE, FALSE);
-	tree = gnt_tree_new();
-	gnt_tree_set_compare_func(GNT_TREE(tree), g_utf8_collate);
-	gnt_widget_set_name(tree, "tree");
-	gnt_box_add_widget(GNT_BOX(box), tree);
-	gnt_box_add_widget(GNT_BOX(hbox), box);
-
-	gnt_tree_add_row_after(GNT_TREE(tree), "c", gnt_tree_create_row(GNT_TREE(tree), "c"), NULL, NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "a", gnt_tree_create_row(GNT_TREE(tree), "a"), NULL, NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "z", gnt_tree_create_row(GNT_TREE(tree), "z"), "a", NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "y", gnt_tree_create_row(GNT_TREE(tree), "y"), "a", NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "g", gnt_tree_create_row(GNT_TREE(tree), "g"), "a", NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "d", gnt_tree_create_row(GNT_TREE(tree), "d"), NULL, NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "x", gnt_tree_create_row(GNT_TREE(tree), "x"), "a", NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "k", gnt_tree_create_row(GNT_TREE(tree), "k"), "a", NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "e", gnt_tree_create_row(GNT_TREE(tree), "e"), "a", NULL);
-	gnt_tree_add_choice(GNT_TREE(tree), "b", gnt_tree_create_row(GNT_TREE(tree), "b"), "d", NULL);
-
-	GNT_WIDGET_UNSET_FLAGS(hbox, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
-	gnt_box_set_title(GNT_BOX(hbox), "\u4e0a\u6d77\u6700\u4f4e\u6708\u5de5 \u4e0a\u6d77\u6700\u4f4e\u6708\u5de5 ……\u4e0a\u6d77\u6700\u4f4e\u6708\u5de5 …");
-
-	g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(toggled), NULL);
-
-	button = gnt_button_new("one");
-	gnt_widget_set_name(button, "one");
-	gnt_box_add_widget(GNT_BOX(vbox), button);
-
-	button = gnt_button_new("two");
-	gnt_widget_set_name(button, "two");
-	gnt_box_add_widget(GNT_BOX(vbox), button);
-
-	button = gnt_button_new("three");
-	gnt_widget_set_name(button, "three");
-	gnt_box_add_widget(GNT_BOX(vbox), button);
-
-	gnt_box_add_widget(GNT_BOX(hbox), vbox);
-	
-	gnt_widget_show(hbox);
-
-#ifdef STANDALONE
-	gnt_main();
-
-	gnt_quit();
-#endif
-
-	return 0;
-}
-
--- a/console/libgnt/test/key.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-#include <ncurses.h>
-
-int main()
-{
-	int ch;
-	initscr();
-
-	noecho();
-
-	while ((ch = getch())) {
-		printw("%d ", ch);
-		refresh();
-	}
-
-	endwin();
-	return 0;
-}
-
--- a/console/libgnt/test/keys.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntentry.h>
-#include <gntlabel.h>
-
-static gboolean
-print_keycode(GntEntry *entry, const char *text, gpointer null)
-{
-	char *s = g_strdup_printf("%s ", text);
-	gnt_entry_set_text(entry, s);
-	g_free(s);
-	if (text[0] == 27)
-	{
-		if (strncmp(text + 1, "[M ", 3) == 0)
-		{
-			int x = (unsigned)text[4];
-			int y = (unsigned)text[5];
-			if (x < 0)	x += 256;
-			if (y < 0)	y += 256;
-			x -= 33;
-			y -= 33;
-			s = g_strdup_printf("ldown %d %d", x, y);
-			gnt_entry_set_text(entry, s);
-			g_free(s);
-		}
-		else if (strncmp(text + 1, "[M#", 3) == 0)
-			gnt_entry_set_text(entry, "up");
-		else
-			return FALSE;
-		return TRUE;
-	}
-	else
-		return TRUE;
-}
-
-int main()
-{
-	GntWidget *window, *entry;
-
-	gnt_init();
-
-	freopen(".error", "w", stderr);
-
-	window = gnt_hbox_new(FALSE);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-
-	gnt_box_add_widget(GNT_BOX(window), gnt_label_new("Press any key: "));
-
-	entry = gnt_entry_new(NULL);
-	gnt_box_add_widget(GNT_BOX(window), entry);
-	g_signal_connect(G_OBJECT(entry), "key_pressed", G_CALLBACK(print_keycode), NULL);
-
-	gnt_widget_set_position(window, getmaxx(stdscr) / 2 - 12, getmaxy(stdscr) / 2 - 3);
-	gnt_widget_show(window);
-
-	gnt_main();
-	gnt_quit();
-	return 0;
-}
-
--- a/console/libgnt/test/menu.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-#include "gnt.h"
-#include "gntbox.h"
-#include "gntlabel.h"
-#include "gntmenu.h"
-#include "gntmenuitem.h"
-#include "gntwindow.h"
-
-void dothis(GntMenuItem *item, gpointer null)
-{
-	GntWidget *w = gnt_vbox_new(FALSE);
-	gnt_box_set_toplevel(GNT_BOX(w), TRUE);
-	gnt_box_add_widget(GNT_BOX(w),
-			gnt_label_new("Callback to a menuitem"));
-	gnt_widget_show(w);
-}
-
-int main()
-{
-	freopen(".error", "w", stderr);
-	gnt_init();
-
-	GntWidget *menu = gnt_menu_new(GNT_MENU_TOPLEVEL);
-	GObject *item = gnt_menuitem_new("File");
-
-	gnt_menu_add_item(GNT_MENU(menu), GNT_MENUITEM(item));
-
-	item = gnt_menuitem_new("Edit");
-	gnt_menu_add_item(GNT_MENU(menu), GNT_MENUITEM(item));
-
-	item = gnt_menuitem_new("Help");
-	gnt_menu_add_item(GNT_MENU(menu), GNT_MENUITEM(item));
-
-	GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
-	gnt_menuitem_set_submenu(GNT_MENUITEM(item), GNT_MENU(sub));
-
-	item = gnt_menuitem_new("Online Help");
-	gnt_menu_add_item(GNT_MENU(sub), GNT_MENUITEM(item));
-
-	item = gnt_menuitem_new("About");
-	gnt_menu_add_item(GNT_MENU(sub), GNT_MENUITEM(item));
-
-	sub = gnt_menu_new(GNT_MENU_POPUP);
-	gnt_menuitem_set_submenu(GNT_MENUITEM(item), GNT_MENU(sub));
-
-	item = gnt_menuitem_new("Online Help");
-	gnt_menu_add_item(GNT_MENU(sub), GNT_MENUITEM(item));
-	gnt_menuitem_set_callback(GNT_MENUITEM(item), dothis, NULL);
-
-	gnt_screen_menu_show(menu);
-
-	GntWidget *win = gnt_window_new();
-	gnt_box_add_widget(GNT_BOX(win),
-		gnt_label_new("..."));
-	gnt_box_set_title(GNT_BOX(win), "Title");
-	gnt_window_set_menu(GNT_WINDOW(win), GNT_MENU(menu));
-	gnt_widget_show(win);
-
-	gnt_main();
-
-	gnt_quit();
-
-	return  0;
-}
-
--- a/console/libgnt/test/multiwin.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-#include "gnt.h"
-#include "gntbutton.h"
-#include "gntentry.h"
-#include "gntkeys.h"
-#include "gntlabel.h"
-#include "gnttree.h"
-#include "gntbox.h"
-
-gboolean show(GntWidget *w)
-{
-	return FALSE;
-}
-
-int main()
-{
-#ifdef STANDALONE
-	freopen(".error", "w", stderr);
-	gnt_init();
-#endif
-
-	GntWidget *hbox, *tree, *box2;
-
-	hbox = gnt_box_new(FALSE, TRUE);
-	box2 = gnt_box_new(FALSE, TRUE);
-
-	gnt_widget_set_name(hbox, "hbox");
-	gnt_widget_set_name(box2, "box2");
-
-	tree = gnt_tree_new_with_columns(3);
-	GNT_WIDGET_SET_FLAGS(tree, GNT_WIDGET_NO_BORDER);
-	gnt_tree_set_column_titles(GNT_TREE(tree), "12345678901234567890", "column 2", "column3");
-	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
-	gnt_widget_set_name(tree, "tree");
-	gnt_box_add_widget(GNT_BOX(hbox), tree);
-
-	gnt_box_set_toplevel(GNT_BOX(hbox), TRUE);
-	gnt_box_set_title(GNT_BOX(hbox), "Testing the tree widget");
-
-	gnt_box_set_toplevel(GNT_BOX(box2), TRUE);
-	gnt_box_set_title(GNT_BOX(box2), "On top");
-
-	gnt_box_add_widget(GNT_BOX(box2), gnt_label_new("asdasd"));
-	gnt_box_add_widget(GNT_BOX(box2), gnt_entry_new(NULL));
-
-	gnt_widget_show(hbox);
-	gnt_widget_set_position(box2, 80, 40);
-	gnt_widget_show(box2);
-
-	gnt_tree_add_row_after(GNT_TREE(tree), "a",
-			gnt_tree_create_row(GNT_TREE(tree), "alaskdjfkashfashfah kfalkdhflsiafhlasf", " long text", "a2"), NULL, NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "c",
-			gnt_tree_create_row(GNT_TREE(tree), "casdgertqhyeqgasfeytwfga fg arf  agfwa ", " long text", "a2"), NULL, NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "d", gnt_tree_create_row(GNT_TREE(tree), "d", " long text", "a2"), NULL, NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "e", gnt_tree_create_row(GNT_TREE(tree), "e", " long text", "a2"), "a", NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "b", gnt_tree_create_row(GNT_TREE(tree), "b", "this is", "a2"), "d", NULL);
-
-	gnt_tree_add_choice(GNT_TREE(tree), "1", gnt_tree_create_row(GNT_TREE(tree), "1", " long text", "a2"), NULL, NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "2", gnt_tree_create_row(GNT_TREE(tree), "2", " long text", "a2"), NULL, NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "3", gnt_tree_create_row(GNT_TREE(tree), "3", " long text", "a2"), NULL, NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "4", gnt_tree_create_row(GNT_TREE(tree), "4", " long text", "a2"), "a", NULL);
-	gnt_tree_add_row_after(GNT_TREE(tree), "5", gnt_tree_create_row(GNT_TREE(tree), "5", " long text", "a2"), "d", NULL);
-
-	gnt_tree_add_row_after(GNT_TREE(tree), "6", gnt_tree_create_row(GNT_TREE(tree), "6", " long text", "a2"), "4", NULL);
-
-	int i;
-	for (i = 110; i < 430; i++)
-	{
-		char *s;
-		s = g_strdup_printf("%d", i); /* XXX: yes, leaking */
-		gnt_tree_add_row_after(GNT_TREE(tree), s, gnt_tree_create_row(GNT_TREE(tree), s, " long text", "a2"), "4", NULL);
-	}
-
-	gnt_tree_set_row_flags(GNT_TREE(tree), "e", GNT_TEXT_FLAG_DIM);
-
-	gnt_tree_set_selected(GNT_TREE(tree), "2");
-
-	g_timeout_add(5000, (GSourceFunc)show, box2);
-
-#ifdef STANDALONE
-	gnt_main();
-
-	gnt_quit();
-#endif
-
-	return 0;
-}
-
--- a/console/libgnt/test/tv.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-#include "gntbutton.h"
-#include "gnt.h"
-#include "gntkeys.h"
-#include "gnttree.h"
-#include "gntbox.h"
-#include "gntentry.h"
-#include "gnttextview.h"
-
-static gboolean
-key_pressed(GntWidget *w, const char *key, GntWidget *view)
-{
-	if (key[0] == '\r' && key[1] == 0)
-	{
-		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view),
-				gnt_entry_get_text(GNT_ENTRY(w)),
-				GNT_TEXT_FLAG_UNDERLINE | GNT_TEXT_FLAG_HIGHLIGHT);
-		gnt_entry_add_to_history(GNT_ENTRY(w), gnt_entry_get_text(GNT_ENTRY(w)));
-		gnt_text_view_next_line(GNT_TEXT_VIEW(view));
-		gnt_entry_clear(GNT_ENTRY(w));
-		if (gnt_text_view_get_lines_below(GNT_TEXT_VIEW(view)) <= 1)
-			gnt_text_view_scroll(GNT_TEXT_VIEW(view), 0);
-		gnt_entry_remove_suggest(GNT_ENTRY(w), "acb");
-
-		return TRUE;
-	}
-	else if (key[0] == 27)
-	{
-		if (strcmp(key, GNT_KEY_UP) == 0)
-			gnt_text_view_scroll(GNT_TEXT_VIEW(view), -1);
-		else if (strcmp(key, GNT_KEY_DOWN) == 0)
-			gnt_text_view_scroll(GNT_TEXT_VIEW(view), 1);
-		else
-			return FALSE;
-		return TRUE;
-	}
-		
-	return FALSE;
-}
-
-int main()
-{
-	GntWidget *hbox, *entry, *view;
-
-#ifdef STANDALONE
-	freopen(".error", "w", stderr);
-
-	gnt_init();
-#endif
-
-	hbox = gnt_box_new(FALSE, TRUE);
-	gnt_widget_set_name(hbox, "hbox");
-	gnt_box_set_toplevel(GNT_BOX(hbox), TRUE);
-	gnt_box_set_fill(GNT_BOX(hbox), FALSE);
-	gnt_box_set_title(GNT_BOX(hbox), "Textview test");
-	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
-
-	entry = gnt_entry_new(NULL);
-	gnt_widget_set_name(entry, "entry");
-	GNT_WIDGET_SET_FLAGS(entry, GNT_WIDGET_CAN_TAKE_FOCUS);
-
-	gnt_entry_set_word_suggest(GNT_ENTRY(entry), TRUE);
-	gnt_entry_set_always_suggest(GNT_ENTRY(entry), FALSE);
-	gnt_entry_add_suggest(GNT_ENTRY(entry), "a");
-	gnt_entry_add_suggest(GNT_ENTRY(entry), "ab");
-	gnt_entry_add_suggest(GNT_ENTRY(entry), "abe");
-	gnt_entry_add_suggest(GNT_ENTRY(entry), "abc");
-	gnt_entry_add_suggest(GNT_ENTRY(entry), "abcde");
-	gnt_entry_add_suggest(GNT_ENTRY(entry), "abcd");
-	gnt_entry_add_suggest(GNT_ENTRY(entry), "acb");
-
-	view = gnt_text_view_new();
-	gnt_widget_set_name(view, "view");
-
-	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);
-	gnt_box_add_widget(GNT_BOX(hbox), gnt_button_new("OK"));
-
-	gnt_widget_show(hbox);
-
-	gnt_entry_set_history_length(GNT_ENTRY(entry), -1);
-	g_signal_connect_after(G_OBJECT(entry), "key_pressed", G_CALLBACK(key_pressed), view);
-
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "\n", GNT_TEXT_FLAG_NORMAL);
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "plugins: ", GNT_TEXT_FLAG_BOLD);
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "this is the 1st line\n", GNT_TEXT_FLAG_NORMAL);
-
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "plugins: ", GNT_TEXT_FLAG_BOLD);
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "this is the 2nd line\n", GNT_TEXT_FLAG_NORMAL);
-
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "plugins: ", GNT_TEXT_FLAG_BOLD);
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "this is the 3rd line\n", GNT_TEXT_FLAG_NORMAL);
-
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "plugins: ", GNT_TEXT_FLAG_BOLD);
-	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "this is the 4th line\n", GNT_TEXT_FLAG_NORMAL);
-
-#ifdef STANDALONE
-	gnt_main();
-
-	gnt_quit();
-#endif
-
-	return 0;
-}
-
--- a/console/libgnt/test/wm.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-#include <gmodule.h>
-
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntentry.h>
-#include <gntlabel.h>
-
-static gboolean
-key_pressed(GntEntry *entry, const char *text, gpointer null)
-{
-	if (*text != '\r')
-		return FALSE;
-
-	{
-		const char *cmd;
-		void *handle;
-		void (*func)();
-
-		cmd = gnt_entry_get_text(entry);
-		handle = g_module_open(cmd, G_MODULE_BIND_LOCAL);
-		if (handle && g_module_symbol(handle, "main", (gpointer)&func))
-		{
-			char *argv[] = {cmd, NULL};
-			gnt_entry_clear(entry);
-			func(1, argv);
-		}
-		else
-		{
-			GntWidget *widget = gnt_vbox_new(FALSE);
-			gnt_box_set_toplevel(GNT_BOX(widget), TRUE);
-			gnt_box_set_title(GNT_BOX(widget), "Error");
-			gnt_box_add_widget(GNT_BOX(widget), gnt_label_new("Could not execute."));
-			gnt_box_add_widget(GNT_BOX(widget), gnt_label_new(g_module_error()));
-
-			gnt_widget_show(widget);
-		}
-	}
-	
-	return TRUE;
-}
-
-int main()
-{
-	GntWidget *window, *entry;
-
-	freopen(".error", "w", stderr);
-
-	gnt_init();
-
-	window = gnt_hbox_new(FALSE);
-
-	gnt_box_add_widget(GNT_BOX(window), gnt_label_new("Command"));
-
-	entry = gnt_entry_new(NULL);
-	g_signal_connect(G_OBJECT(entry), "key_pressed", G_CALLBACK(key_pressed), NULL);
-	gnt_box_add_widget(GNT_BOX(window), entry);
-
-	gnt_widget_set_position(window, 0, getmaxy(stdscr) - 2);
-	gnt_widget_show(window);
-
-	gnt_main();
-
-	gnt_quit();
-	
-	return 0;
-}
-
--- a/console/libgnt/wms/Makefile.am	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-s_la_LDFLAGS             = -module -avoid-version
-
-plugin_LTLIBRARIES = \
-	s.la
-
-plugindir = $(libdir)/gaim
-
-s_la_SOURCES = s.c
-s_la_LIBADD =  \
-  $(GLIB_LIBS) \
-  $(top_builddir)/console/libgnt/libgnt.la \
-  $(top_builddir)/libpurple/libpurple.la
-
-EXTRA_DIST = 
-
-AM_CPPFLAGS = \
-	-DDATADIR=\"$(datadir)\" \
-	-DVERSION=\"$(VERSION)\" \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_srcdir)/console \
-	-I$(top_srcdir)/console/libgnt \
-	$(DEBUG_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(GNT_CFLAGS) \
-	$(PLUGIN_CFLAGS)
-
--- a/console/libgnt/wms/s.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,247 +0,0 @@
-#include <string.h>
-#include <sys/types.h>
-
-#include "gnt.h"
-#include "gntbox.h"
-#include "gntmenu.h"
-#include "gntstyle.h"
-#include "gntwm.h"
-#include "gntwindow.h"
-#include "gntlabel.h"
-
-#include "blist.h"
-
-#define TYPE_S				(s_get_gtype())
-
-typedef struct _S
-{
-	GntWM inherit;
-} S;
-
-typedef struct _SClass
-{
-	GntWMClass inherit;
-} SClass;
-
-GType s_get_gtype(void);
-void gntwm_init(GntWM **wm);
-
-static void (*org_new_window)(GntWM *wm, GntWidget *win);
-
-static void
-envelope_buddylist(GntWidget *win)
-{
-	int w, h;
-	gnt_widget_get_size(win, &w, &h);
-	wresize(win->window, h, w + 1);
-	mvwvline(win->window, 0, w, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), h);
-	touchwin(win->window);
-}
-
-static void
-envelope_normal_window(GntWidget *win)
-{
-	int w, h;
-
-	if (GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_NO_BORDER | GNT_WIDGET_TRANSIENT))
-		return;
-
-	gnt_widget_get_size(win, &w, &h);
-	wbkgdset(win->window, ' ' | COLOR_PAIR(GNT_COLOR_NORMAL));
-	mvwprintw(win->window, 0, w - 4, "[X]");
-}
-
-static void
-s_decorate_window(GntWM *wm, GntWidget *win)
-{
-	const char *name;
-
-	name = gnt_widget_get_name(win);
-	if (name && strcmp(name, "buddylist") == 0) {
-		envelope_buddylist(win);
-	} else {
-		envelope_normal_window(win);
-	}
-}
-
-static void
-s_window_update(GntWM *wm, GntNode *node)
-{
-	s_decorate_window(wm, node->me);
-}
-
-static void
-s_new_window(GntWM *wm, GntWidget *win)
-{
-	int x, y, w, h;
-	int maxx, maxy;
-	const char *name;
-	gboolean blist = FALSE;
-
-	if (!GNT_IS_MENU(win)) {
-		getmaxyx(stdscr, maxy, maxx);
-
-		gnt_widget_get_position(win, &x, &y);
-		gnt_widget_get_size(win, &w, &h);
-
-		name = gnt_widget_get_name(win);
-
-		if (name && strcmp(name, "buddylist") == 0) {
-			/* The buddylist doesn't have no border nor nothing! */
-			x = 0;
-			y = 0;
-			h = maxy - 1;
-			blist = TRUE;
-
-			gnt_box_set_toplevel(GNT_BOX(win), FALSE);
-			GNT_WIDGET_SET_FLAGS(win, GNT_WIDGET_CAN_TAKE_FOCUS);
-
-			gnt_widget_set_position(win, x, y);
-			mvwin(win->window, y, x);
-
-			gnt_widget_set_size(win, -1, h + 2);  /* XXX: Why is the +2 needed here? -- sadrul */
-		} else if (!GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_TRANSIENT)) {
-			const char *title = GNT_BOX(win)->title;
-			if (title == NULL || !g_hash_table_lookup(wm->positions, title)) {
-				/* In the middle of the screen */
-				x = (maxx - w) / 2;
-				y = (maxy - h) / 2;
-
-				gnt_widget_set_position(win, x, y);
-				mvwin(win->window, y, x);
-			}
-		}
-	}
-	org_new_window(wm, win);
-
-	if (blist)
-		gnt_wm_raise_window(wm, win);
-}
-
-static GntWidget *
-find_widget(GntWM *wm, const char *wname)
-{
-	const GList *iter = wm->list;
-	for (; iter; iter = iter->next) {
-		GntWidget *widget = iter->data;
-		const char *name = gnt_widget_get_name(widget);
-		if (name && strcmp(name, wname) == 0) {
-			return widget;
-		}
-	}
-	return NULL;
-}
-
-static gboolean
-s_mouse_clicked(GntWM *wm, GntMouseEvent event, int cx, int cy, GntWidget *widget)
-{
-	int x, y, w, h;
-
-	if (!widget)
-		return FALSE;
-		/* This might be a place to bring up a context menu */
-	
-	if (event != GNT_LEFT_MOUSE_DOWN ||
-			GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
-		return FALSE;
-	
-	gnt_widget_get_position(widget, &x, &y);
-	gnt_widget_get_size(widget, &w, &h);
-
-	if (cy == y && cx == x + w - 3) {
-		gnt_widget_destroy(widget);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-toggle_buddylist(GntBindable *bindable, GList *null)
-{
-	GntWM *wm = GNT_WM(bindable);
-	GntWidget *blist = find_widget(wm, "buddylist");
-	if (blist)
-		gnt_widget_destroy(blist);
-	else
-		gaim_blist_show();
-	return TRUE;
-}
-
-static gboolean
-toggle_clipboard(GntBindable *bindable, GList *n)
-{
-	static GntWidget *clip;
-	gchar *text;
-	int maxx, maxy;
-	if (clip) {
-		gnt_widget_destroy(clip);
-		clip = NULL;
-		return TRUE;
-	}
-	getmaxyx(stdscr, maxy, maxx);
-	text = gnt_get_clipboard_string();
-	clip = gnt_hwindow_new(FALSE);
-	GNT_WIDGET_SET_FLAGS(clip, GNT_WIDGET_TRANSIENT);
-	GNT_WIDGET_SET_FLAGS(clip, GNT_WIDGET_NO_BORDER);
-	gnt_box_set_pad(GNT_BOX(clip), 0);
-	gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(" "));
-	gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(text));
-	gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(" "));
-	gnt_widget_set_position(clip, 0, 0);
-	gnt_widget_draw(clip);
-	g_free(text);
-	return TRUE;
-}
-
-static void
-s_class_init(SClass *klass)
-{
-	GntWMClass *pclass = GNT_WM_CLASS(klass);
-
-	org_new_window = pclass->new_window;
-
-	pclass->new_window = s_new_window;
-	pclass->decorate_window = s_decorate_window;
-	pclass->window_update = s_window_update;
-	pclass->mouse_clicked = s_mouse_clicked;
-
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-buddylist",
-				toggle_buddylist, "\033" "b", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-clipboard",
-				toggle_clipboard, "\033" "C", NULL);
-	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
-	GNTDEBUG;
-}
-
-void gntwm_init(GntWM **wm)
-{
-	*wm = g_object_new(TYPE_S, NULL);
-}
-
-GType s_get_gtype(void)
-{
-	static GType type = 0;
-
-	if(type == 0) {
-		static const GTypeInfo info = {
-			sizeof(SClass),
-			NULL,					/* base_init		*/
-			NULL,					/* base_finalize	*/
-			(GClassInitFunc)s_class_init,
-			NULL,
-			NULL,                   /* class_data		*/
-			sizeof(S),
-			0,                      /* n_preallocs		*/
-			NULL,	            /* instance_init	*/
-			NULL
-		};
-
-		type = g_type_register_static(GNT_TYPE_WM,
-									  "GntS",
-									  &info, 0);
-	}
-
-	return type;
-}
-
--- a/console/plugins/Makefile.am	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-gntgf_la_LDFLAGS      = -module -avoid-version
-gnthistory_la_LDFLAGS = -module -avoid-version
-gntlastlog_la_LDFLAGS    = -module -avoid-version
-
-if PLUGINS
-
-plugin_LTLIBRARIES = \
-	gntgf.la \
-	gnthistory.la \
-	gntlastlog.la
-
-plugindir = $(libdir)/gaim
-
-gntgf_la_SOURCES      = gntgf.c
-gnthistory_la_SOURCES = gnthistory.c
-gntlastlog_la_SOURCES = lastlog.c
-
-gntgf_la_CFLAGS = $(X11_CFLAGS)
-
-gntgf_la_LIBADD       = $(GLIB_LIBS) $(X11_LIBS) $(top_builddir)/console/libgnt/libgnt.la
-gnthistory_la_LIBADD  = $(GLIB_LIBS)
-gntlastlog_la_LIBADD  = $(GLIB_LIBS)
-
-endif # PLUGINS
-
-EXTRA_DIST = 
-
-AM_CPPFLAGS = \
-	-DDATADIR=\"$(datadir)\" \
-	-DVERSION=\"$(VERSION)\" \
-	-I$(top_builddir)/libpurple \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/console \
-	-I$(top_srcdir)/console/libgnt \
-	$(DEBUG_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(GNT_CFLAGS) \
-	$(PLUGIN_CFLAGS)
-
-#
-# This part allows people to build their own plugins in here.
-# Yes, it's a mess.
-#
-SUFFIXES = .c .so
-.c.so:
-	$(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_srcdir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS)
-	$(LIBTOOL) --mode=link    $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS)
-	@rm -f tmp$@.lo tmp$@.o libtmp$@.la
-	@cp .libs/libtmp$@.so* $@
-	@rm -f .libs/libtmp$@.*
--- a/console/plugins/gntclipboard.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/**
- * @file gntclipboard.c
- *
- * Copyright (C) 2007 Richard Nelson <wabz@whatsbeef.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "internal.h"
-#include <glib.h>
-
-#define PLUGIN_STATIC_NAME	"GntClipboard"
-
-#ifdef HAVE_X11
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#endif
-
-#include <sys/types.h>
-#include <signal.h>
-
-#include <glib.h>
-
-#include <plugin.h>
-#include <version.h>
-#include <debug.h>
-#include <gntwm.h>
-
-#include <gntplugin.h>
-
-static pid_t child = 0;
-
-static gulong sig_handle;
-
-static void
-set_clip(gchar *string)
-{
-#ifdef HAVE_X11
-	Window w;
-	XEvent e, respond;
-	XSelectionRequestEvent *req;
-	const char *ids;
-	Display *dpy = XOpenDisplay(NULL);
-
-	if (!dpy)
-		return;
-	ids = getenv("WINDOWID");
-	if (ids == NULL)
-		return;
-	w = atoi(ids);
-	XSetSelectionOwner(dpy, XA_PRIMARY, w, CurrentTime);
-	XFlush(dpy);
-	XSelectInput(dpy, w, StructureNotifyMask);
-	while (TRUE) {
-		XNextEvent(dpy, &e); /* this blocks. */
-		req = &e.xselectionrequest;
-		if (e.type == SelectionRequest) {
-			XChangeProperty(dpy,
-				req->requestor,
-				req->property,
-				XA_STRING,
-				8, PropModeReplace,
-				(unsigned char *)string,
-				strlen(string));
-			respond.xselection.property = req->property;
-			respond.xselection.type = SelectionNotify;
-			respond.xselection.display = req->display;
-			respond.xselection.requestor = req->requestor;
-			respond.xselection.selection = req->selection;
-			respond.xselection.target= req->target;
-			respond.xselection.time = req->time;
-			XSendEvent(dpy, req->requestor, 0, 0, &respond);
-			XFlush (dpy);
-		} else if (e.type == SelectionClear) {
-			return;
-		}
-	}
-#endif
-	return;
-}
-
-static void
-clipboard_changed(GntWM *wm, gchar *string)
-{
-#ifdef HAVE_X11
-	if (child) {
-		kill(child, SIGTERM);
-	}
-	if ((child = fork() == 0)) {
-		set_clip(string);
-		_exit(0);
-	}
-#endif
-}
-
-static gboolean
-plugin_load(GaimPlugin *plugin)
-{
-	if (!XOpenDisplay(NULL)) {
-		gaim_debug_warning("gntclipboard", "Couldn't find X display\n");
-		return FALSE;
-	}
-	if (!getenv("WINDOWID")) {
-		gaim_debug_warning("gntclipboard", "Couldn't find window\n");
-		return FALSE;
-	}
-	sig_handle = g_signal_connect(G_OBJECT(gnt_get_clipboard()), "clipboard_changed", G_CALLBACK(clipboard_changed), NULL);
-	return TRUE;
-}
-
-static gboolean
-plugin_unload(GaimPlugin *plugin)
-{
-	if (child) {
-		kill(child, SIGTERM);
-		child = 0;
-	}
-	g_signal_handler_disconnect(G_OBJECT(gnt_get_clipboard()), sig_handle);
-	return TRUE;
-}
-
-static GaimPluginInfo info =
-{
-	GAIM_PLUGIN_MAGIC,
-	GAIM_MAJOR_VERSION,
-	GAIM_MINOR_VERSION,
-	GAIM_PLUGIN_STANDARD,
-	GAIM_GNT_PLUGIN_TYPE,
-	0,
-	NULL,
-	GAIM_PRIORITY_DEFAULT,
-	"gntclipboard",
-	N_("GntClipboard"),
-	VERSION,
-	N_("Clipboard plugin"),
-	N_("When the gnt clipboard contents change, "
-		"the contents are made available to X, if possible."),
-	"Richard Nelson <wabz@whatsbeef.net>",
-	"http://gaim.sourceforge.net",
-	plugin_load,
-	plugin_unload,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(GaimPlugin *plugin)
-{
-}
-
-GAIM_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
--- a/console/plugins/gntgf.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,390 +0,0 @@
-/**
- * @file gntgf.c Minimal toaster plugin in Gnt.
- *
- * Copyright (C) 2006 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "internal.h"
-
-#define PLUGIN_STATIC_NAME	"GntGf"
-
-#define PREFS_PREFIX          "/plugins/gnt/gntgf"
-#define PREFS_EVENT           PREFS_PREFIX "/events"
-#define PREFS_EVENT_SIGNONF   PREFS_EVENT "/signonf"
-#define PREFS_EVENT_IM_MSG    PREFS_EVENT "/immsg"
-#define PREFS_EVENT_CHAT_MSG  PREFS_EVENT "/chatmsg"
-#define PREFS_EVENT_CHAT_NICK PREFS_EVENT "/chatnick"
-#define PREFS_BEEP            PREFS_PREFIX "/beep"
-
-#define MAX_COLS	3
-
-#ifdef HAVE_X11
-#define PREFS_URGENT          PREFS_PREFIX "/urgent"
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#endif
-
-#include <glib.h>
-
-#include <plugin.h>
-#include <version.h>
-#include <blist.h>
-#include <conversation.h>
-#include <debug.h>
-#include <util.h>
-
-#include <gnt.h>
-#include <gntbox.h>
-#include <gntbutton.h>
-#include <gntcheckbox.h>
-#include <gntlabel.h>
-#include <gnttree.h>
-
-#include <gntplugin.h>
-
-typedef struct
-{
-	GntWidget *window;
-	int timer;
-	int column;
-} GntToast;
-
-static GList *toasters;
-static int gpsy[MAX_COLS];
-static int gpsw[MAX_COLS];
-
-static void
-destroy_toaster(GntToast *toast)
-{
-	toasters = g_list_remove(toasters, toast);
-	gnt_widget_destroy(toast->window);
-	g_source_remove(toast->timer);
-	g_free(toast);
-}
-
-static gboolean
-remove_toaster(GntToast *toast)
-{
-	GList *iter;
-	int h;
-	int col;
-	int nwin[MAX_COLS];
-
-	gnt_widget_get_size(toast->window, NULL, &h);
-	gpsy[toast->column] -= h;
-	col = toast->column;
-
-	memset(&nwin, 0, sizeof(nwin));
-	destroy_toaster(toast);
-
-	for (iter = toasters; iter; iter = iter->next)
-	{
-		int x, y;
-		toast = iter->data;
-		nwin[toast->column]++;
-		if (toast->column != col) continue;
-		gnt_widget_get_position(toast->window, &x, &y);
-		y += h;
-		gnt_screen_move_widget(toast->window, x, y);
-	}
-
-	if (nwin[col] == 0)
-		gpsw[col] = 0;
-
-	return FALSE;
-}
-
-#ifdef HAVE_X11
-static void
-urgent()
-{
-	/* This is from deryni/tuomov's urgent_test.c */
-	Display *dpy;
-	Window id;
-	const char *ids;
-	XWMHints *hints;
-
-	ids = getenv("WINDOWID");
-	if (ids == NULL)
-		return;
-	
-	id = atoi(ids);
-
-	dpy = XOpenDisplay(NULL);
-	if (dpy == NULL)
-		return;
-
-	hints = XGetWMHints(dpy, id);
-	hints->flags|=XUrgencyHint;
-	XSetWMHints(dpy, id, hints);
-
-	XFlush(dpy);
-	XCloseDisplay(dpy);
-}
-#endif
-
-static void
-notify(const char *fmt, ...)
-{
-	GntWidget *window;
-	GntToast *toast;
-	char *str;
-	int h, w, i;
-	va_list args;
-
-	if (gaim_prefs_get_bool(PREFS_BEEP))
-		beep();
-#ifdef HAVE_X11
-	if (gaim_prefs_get_bool(PREFS_URGENT))
-		urgent();
-#endif
-
-	window = gnt_vbox_new(FALSE);
-	GNT_WIDGET_SET_FLAGS(window, GNT_WIDGET_TRANSIENT);
-	GNT_WIDGET_UNSET_FLAGS(window, GNT_WIDGET_NO_BORDER);
-
-	va_start(args, fmt);
-	str = g_strdup_vprintf(fmt, args);
-	va_end(args);
-
-	gnt_box_add_widget(GNT_BOX(window),
-			gnt_label_new_with_format(str, GNT_TEXT_FLAG_HIGHLIGHT));
-
-	g_free(str);
-	gnt_widget_size_request(window);
-	gnt_widget_get_size(window, &w, &h);
-	for (i = 0; i < MAX_COLS && gpsy[i] + h >= getmaxy(stdscr) ; ++i)
-		;
-	if (i >= MAX_COLS) {
-		gaim_debug_warning("GntGf", "Dude, that's way too many popups\n");
-		gnt_widget_destroy(window);
-		return;
-	}
-
-	toast = g_new0(GntToast, 1);
-	toast->window = window;
-	toast->column = i;
-	gpsy[i] += h;
-	if (w > gpsw[i]) {
-		if (i == 0)
-			gpsw[i] = w;
-		else
-			gpsw[i] = gpsw[i - 1] + w + 1;
-	}
-
-	if (i == 0 || (w + gpsw[i - 1] >= getmaxx(stdscr))) {
-		/* if it's going to be too far left, overlap. */
-		gnt_widget_set_position(window, getmaxx(stdscr) - w - 1,
-				getmaxy(stdscr) - gpsy[i] - 1);
-	} else {
-		gnt_widget_set_position(window, getmaxx(stdscr) - gpsw[i - 1] - w - 1,
-				getmaxy(stdscr) - gpsy[i] - 1);
-	}
-	gnt_widget_draw(window);
-
-	toast->timer = g_timeout_add(4000, (GSourceFunc)remove_toaster, toast);
-	toasters = g_list_prepend(toasters, toast);
-}
-
-static void
-buddy_signed_on(GaimBuddy *buddy, gpointer null)
-{
-	if (gaim_prefs_get_bool(PREFS_EVENT_SIGNONF))
-		notify(_("%s just signed on"), gaim_buddy_get_alias(buddy));
-}
-
-static void
-buddy_signed_off(GaimBuddy *buddy, gpointer null)
-{
-	if (gaim_prefs_get_bool(PREFS_EVENT_SIGNONF))
-		notify(_("%s just signed off"), gaim_buddy_get_alias(buddy));
-}
-
-static void
-received_im_msg(GaimAccount *account, const char *sender, const char *msg,
-		GaimConversation *conv, GaimMessageFlags flags, gpointer null)
-{
-	if (gaim_prefs_get_bool(PREFS_EVENT_IM_MSG))
-		notify(_("%s sent you a message"), sender);
-}
-
-static void
-received_chat_msg(GaimAccount *account, const char *sender, const char *msg,
-		GaimConversation *conv, GaimMessageFlags flags, gpointer null)
-{
-	const char *nick;
-
-	if (flags & GAIM_MESSAGE_WHISPER)
-		return;
-	
-	nick = GAIM_CONV_CHAT(conv)->nick;
-
-	if (g_utf8_collate(sender, nick) == 0)
-		return;
-
-	if (gaim_prefs_get_bool(PREFS_EVENT_CHAT_NICK) &&
-			(gaim_utf8_has_word(msg, nick)))
-		notify(_("%s said your nick in %s"), sender, gaim_conversation_get_name(conv));
-	else if (gaim_prefs_get_bool(PREFS_EVENT_CHAT_MSG))
-		notify(_("%s sent a message in %s"), sender, gaim_conversation_get_name(conv));
-}
-
-static gboolean
-plugin_load(GaimPlugin *plugin)
-{
-	gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-on", plugin,
-			GAIM_CALLBACK(buddy_signed_on), NULL);
-	gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-off", plugin,
-			GAIM_CALLBACK(buddy_signed_off), NULL);
-	gaim_signal_connect(gaim_conversations_get_handle(), "received-im-msg", plugin,
-			GAIM_CALLBACK(received_im_msg), NULL);
-	gaim_signal_connect(gaim_conversations_get_handle(), "received-chat-msg", plugin,
-			GAIM_CALLBACK(received_chat_msg), NULL);
-
-	memset(&gpsy, 0, sizeof(gpsy));
-	memset(&gpsw, 0, sizeof(gpsw));
-
-	return TRUE;
-}
-
-static gboolean
-plugin_unload(GaimPlugin *plugin)
-{
-	while (toasters)
-	{
-		GntToast *toast = toasters->data;
-		destroy_toaster(toast);
-	}
-	return TRUE;
-}
-
-static struct
-{
-	char *pref;
-	char *display;
-} prefs[] =
-{
-	{PREFS_EVENT_SIGNONF, N_("Buddy signs on/off")},
-	{PREFS_EVENT_IM_MSG, N_("You receive an IM")},
-	{PREFS_EVENT_CHAT_MSG, N_("Someone speaks in a chat")},
-	{PREFS_EVENT_CHAT_NICK, N_("Someone says your name in a chat")},
-	{NULL, NULL}
-};
-
-static void
-pref_toggled(GntTree *tree, char *key, gpointer null)
-{
-	gaim_prefs_set_bool(key, gnt_tree_get_choice(tree, key));
-}
-
-static void
-toggle_option(GntCheckBox *check, gpointer str)
-{
-	gaim_prefs_set_bool(str, gnt_check_box_get_checked(check));
-}
-
-static GntWidget *
-config_frame()
-{
-	GntWidget *window, *tree, *check;
-	int i;
-
-	window = gnt_vbox_new(FALSE);
-	gnt_box_set_pad(GNT_BOX(window), 0);
-	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
-	gnt_box_set_fill(GNT_BOX(window), TRUE);
-
-	gnt_box_add_widget(GNT_BOX(window),
-			gnt_label_new(_("Notify with a toaster when")));
-
-	tree = gnt_tree_new();
-	gnt_box_add_widget(GNT_BOX(window), tree);
-
-	for (i = 0; prefs[i].pref; i++)
-	{
-		gnt_tree_add_choice(GNT_TREE(tree), prefs[i].pref,
-				gnt_tree_create_row(GNT_TREE(tree), prefs[i].display), NULL, NULL);
-		gnt_tree_set_choice(GNT_TREE(tree), prefs[i].pref,
-				gaim_prefs_get_bool(prefs[i].pref));
-	}
-	gnt_tree_set_col_width(GNT_TREE(tree), 0, 40);
-	g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(pref_toggled), NULL);
-
-	check = gnt_check_box_new(_("Beep too!"));
-	gnt_check_box_set_checked(GNT_CHECK_BOX(check), gaim_prefs_get_bool(PREFS_BEEP));
-	g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(toggle_option), PREFS_BEEP);
-	gnt_box_add_widget(GNT_BOX(window), check);
-
-#ifdef HAVE_X11
-	check = gnt_check_box_new(_("Set URGENT for the terminal window."));
-	gnt_check_box_set_checked(GNT_CHECK_BOX(check), gaim_prefs_get_bool(PREFS_URGENT));
-	g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(toggle_option), PREFS_URGENT);
-	gnt_box_add_widget(GNT_BOX(window), check);
-#endif
-
-	return window;
-}
-
-static GaimPluginInfo info =
-{
-	GAIM_PLUGIN_MAGIC,
-	GAIM_MAJOR_VERSION,
-	GAIM_MINOR_VERSION,
-	GAIM_PLUGIN_STANDARD,
-	GAIM_GNT_PLUGIN_TYPE,
-	0,
-	NULL,
-	GAIM_PRIORITY_DEFAULT,
-	"gntgf",
-	N_("GntGf"),
-	VERSION,
-	N_("Toaster plugin"),
-	N_("Toaster plugin"),
-	"Sadrul H Chowdhury <sadrul@users.sourceforge.net>",
-	"http://gaim.sourceforge.net",
-	plugin_load,
-	plugin_unload,
-	NULL,
-	config_frame,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(GaimPlugin *plugin)
-{
-	gaim_prefs_add_none("/plugins");
-	gaim_prefs_add_none("/plugins/gnt");
-	
-	gaim_prefs_add_none("/plugins/gnt/gntgf");
-	gaim_prefs_add_none(PREFS_EVENT);
-
-	gaim_prefs_add_bool(PREFS_EVENT_SIGNONF, TRUE);
-	gaim_prefs_add_bool(PREFS_EVENT_IM_MSG, TRUE);
-	gaim_prefs_add_bool(PREFS_EVENT_CHAT_MSG, TRUE);
-	gaim_prefs_add_bool(PREFS_EVENT_CHAT_NICK, TRUE);
-
-	gaim_prefs_add_bool(PREFS_BEEP, TRUE);
-#ifdef HAVE_X11
-	gaim_prefs_add_bool(PREFS_URGENT, FALSE);
-#endif
-}
-
-GAIM_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
--- a/console/plugins/gnthistory.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-/**
- * @file gnthistory.c Show log from previous conversation
- *
- * Copyright (C) 2006 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* Ripped from gtk/plugins/history.c */
-
-#include "internal.h"
-
-#include "conversation.h"
-#include "debug.h"
-#include "log.h"
-#include "notify.h"
-#include "prefs.h"
-#include "signals.h"
-#include "util.h"
-#include "version.h"
-
-#include "gntplugin.h"
-
-#define HISTORY_PLUGIN_ID "gnt-history"
-
-#define HISTORY_SIZE (4 * 1024)
-
-static void historize(GaimConversation *c)
-{
-	GaimAccount *account = gaim_conversation_get_account(c);
-	const char *name = gaim_conversation_get_name(c);
-	GaimConversationType convtype;
-	GList *logs = NULL;
-	const char *alias = name;
-	GaimLogReadFlags flags;
-	char *history;
-	char *header;
-	GaimMessageFlags mflag;
-
-	convtype = gaim_conversation_get_type(c);
-	if (convtype == GAIM_CONV_TYPE_IM)
-	{
-		GSList *buddies;
-		GSList *cur;
-
-		/* If we're not logging, don't show anything.
-		 * Otherwise, we might show a very old log. */
-		if (!gaim_prefs_get_bool("/core/logging/log_ims"))
-			return;
-
-		/* Find buddies for this conversation. */
-	        buddies = gaim_find_buddies(account, name);
-
-		/* If we found at least one buddy, save the first buddy's alias. */
-		if (buddies != NULL)
-			alias = gaim_buddy_get_contact_alias((GaimBuddy *)buddies->data);
-
-	        for (cur = buddies; cur != NULL; cur = cur->next)
-	        {
-	                GaimBlistNode *node = cur->data;
-	                if ((node != NULL) && ((node->prev != NULL) || (node->next != NULL)))
-	                {
-				GaimBlistNode *node2;
-
-				alias = gaim_buddy_get_contact_alias((GaimBuddy *)node);
-
-				/* We've found a buddy that matches this conversation.  It's part of a
-				 * GaimContact with more than one GaimBuddy.  Loop through the GaimBuddies
-				 * in the contact and get all the logs. */
-				for (node2 = node->parent->child ; node2 != NULL ; node2 = node2->next)
-				{
-					logs = g_list_concat(
-						gaim_log_get_logs(GAIM_LOG_IM,
-							gaim_buddy_get_name((GaimBuddy *)node2),
-							gaim_buddy_get_account((GaimBuddy *)node2)),
-						logs);
-				}
-				break;
-	                }
-	        }
-	        g_slist_free(buddies);
-
-		if (logs == NULL)
-			logs = gaim_log_get_logs(GAIM_LOG_IM, name, account);
-		else
-			logs = g_list_sort(logs, gaim_log_compare);
-	}
-	else if (convtype == GAIM_CONV_TYPE_CHAT)
-	{
-		/* If we're not logging, don't show anything.
-		 * Otherwise, we might show a very old log. */
-		if (!gaim_prefs_get_bool("/core/logging/log_chats"))
-			return;
-
-		logs = gaim_log_get_logs(GAIM_LOG_CHAT, name, account);
-	}
-
-	if (logs == NULL)
-		return;
-
-	mflag = GAIM_MESSAGE_NO_LOG | GAIM_MESSAGE_SYSTEM | GAIM_MESSAGE_DELAYED;
-	history = gaim_log_read((GaimLog*)logs->data, &flags);
-
-	header = g_strdup_printf(_("<b>Conversation with %s on %s:</b><br>"), alias,
-							 gaim_date_format_full(localtime(&((GaimLog *)logs->data)->time)));
-	gaim_conversation_write(c, "", header, mflag, time(NULL));
-	g_free(header);
-
-	if (flags & GAIM_LOG_READ_NO_NEWLINE)
-		gaim_str_strip_char(history, '\n');
-	gaim_conversation_write(c, "", history, mflag, time(NULL));
-	g_free(history);
-
-	gaim_conversation_write(c, "", "<hr>", mflag, time(NULL));
-
-	g_list_foreach(logs, (GFunc)gaim_log_free, NULL);
-	g_list_free(logs);
-}
-
-static void
-history_prefs_check(GaimPlugin *plugin)
-{
-	if (!gaim_prefs_get_bool("/core/logging/log_ims") &&
-	    !gaim_prefs_get_bool("/core/logging/log_chats"))
-	{
-		gaim_notify_warning(plugin, NULL, _("History Plugin Requires Logging"),
-							_("Logging can be enabled from Tools -> Preferences -> Logging.\n\n"
-							  "Enabling logs for instant messages and/or chats will activate "
-							  "history for the same conversation type(s)."));
-	}
-}
-
-static void history_prefs_cb(const char *name, GaimPrefType type,
-							 gconstpointer val, gpointer data)
-{
-	history_prefs_check((GaimPlugin *)data);
-}
-
-static gboolean
-plugin_load(GaimPlugin *plugin)
-{
-	gaim_signal_connect(gaim_conversations_get_handle(),
-						"conversation-created",
-						plugin, GAIM_CALLBACK(historize), NULL);
-
-	gaim_prefs_connect_callback(plugin, "/core/logging/log_ims",
-								history_prefs_cb, plugin);
-	gaim_prefs_connect_callback(plugin, "/core/logging/log_chats",
-								history_prefs_cb, plugin);
-
-	history_prefs_check(plugin);
-
-	return TRUE;
-}
-
-static GaimPluginInfo info =
-{
-	GAIM_PLUGIN_MAGIC,
-	GAIM_MAJOR_VERSION,
-	GAIM_MINOR_VERSION,
-	GAIM_PLUGIN_STANDARD,
-	NULL,
-	0,
-	NULL,
-	GAIM_PRIORITY_DEFAULT,
-	HISTORY_PLUGIN_ID,
-	N_("GntHistory"),
-	VERSION,
-	N_("Shows recently logged conversations in new conversations."),
-	N_("When a new conversation is opened this plugin will insert "
-	   "the last conversation into the current conversation."),
-	"Sean Egan <seanegan@gmail.com>\n"
-	"Sadrul H Chowdhury <sadrul@users.sourceforge.net>",
-	GAIM_WEBSITE,
-	plugin_load,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(GaimPlugin *plugin)
-{
-}
-
-GAIM_INIT_PLUGIN(gnthistory, init_plugin, info)
-
--- a/console/plugins/lastlog.c	Sun Mar 18 18:17:14 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/**
- * @file lastlog.c Lastlog plugin for gaim-text.
- *
- * Copyright (C) 2006 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#define PLUGIN_STATIC_NAME	"GntLastlog"
-
-#include "internal.h"
-
-#include <plugin.h>
-#include <version.h>
-
-#include <cmds.h>
-
-#include <gnt.h>
-#include <gnttextview.h>
-#include <gntwindow.h>
-
-#include <gntconv.h>
-#include <gntplugin.h>
-
-static GaimCmdId cmd;
-
-static gboolean
-window_kpress_cb(GntWidget *wid, const char *key, GntTextView *view)
-{
-	if (key[0] == 27)
-	{
-		if (strcmp(key, GNT_KEY_DOWN) == 0)
-			gnt_text_view_scroll(view, 1);
-		else if (strcmp(key, GNT_KEY_UP) == 0)
-			gnt_text_view_scroll(view, -1);
-		else if (strcmp(key, GNT_KEY_PGDOWN) == 0)
-			gnt_text_view_scroll(view, wid->priv.height - 2);
-		else if (strcmp(key, GNT_KEY_PGUP) == 0)
-			gnt_text_view_scroll(view, -(wid->priv.height - 2));
-		else
-			return FALSE;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static GaimCmdRet
-lastlog_cb(GaimConversation *conv, const char *cmd, char **args, char **error, gpointer null)
-{
-	GGConv *ggconv = conv->ui_data;
-	char **strings = g_strsplit(GNT_TEXT_VIEW(ggconv->tv)->string->str, "\n", 0);
-	GntWidget *win, *tv;
-	int i, j;
-
-	win = gnt_window_new();
-	gnt_box_set_title(GNT_BOX(win), _("Lastlog"));
-
-	tv = gnt_text_view_new();
-	gnt_box_add_widget(GNT_BOX(win), tv);
-
-	gnt_widget_show(win);
-
-	for (i = 0; strings[i]; i++) {
-		if (strstr(strings[i], args[0]) != NULL) {
-			char **finds = g_strsplit(strings[i], args[0], 0);
-			for (j = 0; finds[j]; j++) {
-				if (j)
-					gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(tv), args[0], GNT_TEXT_FLAG_BOLD);
-				gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(tv), finds[j], GNT_TEXT_FLAG_NORMAL);
-			}
-			g_strfreev(finds);
-			gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(tv), "\n", GNT_TEXT_FLAG_NORMAL);
-		}
-	}
-
-	g_signal_connect(G_OBJECT(win), "key_pressed", G_CALLBACK(window_kpress_cb), tv);
-	g_strfreev(strings);
-	return GAIM_CMD_STATUS_OK;
-}
-
-static gboolean
-plugin_load(GaimPlugin *plugin)
-{
-	cmd = gaim_cmd_register("lastlog", "s", GAIM_CMD_P_DEFAULT,
-			GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
-			lastlog_cb, _("lastlog: Searches for a substring in the backlog."), NULL);
-	return TRUE;
-}
-
-static gboolean
-plugin_unload(GaimPlugin *plugin)
-{
-	gaim_cmd_unregister(cmd);
-	return TRUE;
-}
-
-static GaimPluginInfo info =
-{
-	GAIM_PLUGIN_MAGIC,
-	GAIM_MAJOR_VERSION,
-	GAIM_MINOR_VERSION,
-	GAIM_PLUGIN_STANDARD,
-	GAIM_GNT_PLUGIN_TYPE,
-	0,
-	NULL,
-	GAIM_PRIORITY_DEFAULT,
-	"gntlastlog",
-	N_("GntLastlog"),
-	VERSION,
-	N_("Lastlog plugin."),
-	N_("Lastlog plugin."),
-	"Sadrul H Chowdhury <sadrul@users.sourceforge.net>",
-	"http://gaim.sourceforge.net",
-	plugin_load,
-	plugin_unload,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(GaimPlugin *plugin)
-{
-}
-
-GAIM_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/Makefile.am	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,77 @@
+if ENABLE_GNT
+
+EXTRA_DIST = \
+		getopt.c \
+		getopt.h \
+		getopt1.c
+
+SUBDIRS = libgnt plugins
+
+bin_PROGRAMS = finch
+
+finch_SOURCES = \
+	gntaccount.c \
+	gntblist.c \
+	gntconn.c \
+	gntconv.c \
+	gntdebug.c \
+	gntft.c \
+	gntgaim.c \
+	gntidle.c \
+	gntnotify.c \
+	gntplugin.c \
+	gntpounce.c \
+	gntprefs.c \
+	gntrequest.c \
+	gntstatus.c \
+	gntui.c
+
+finch_headers = \
+	gntaccount.h \
+	gntblist.h \
+	gntconn.h \
+	gntconv.h \
+	gntdebug.h \
+	gntft.h \
+	gntgaim.h \
+	gntidle.h \
+	gntnotify.h \
+	gntplugin.h \
+	gntpounce.h \
+	gntprefs.h \
+	gntrequest.h \
+	gntstatus.h \
+	gntui.h
+
+finchincludedir=$(includedir)/gaim/gnt
+finchinclude_HEADERS = \
+	$(finch_headers)
+
+finch_DEPENDENCIES = @LIBOBJS@
+finch_LDFLAGS = -export-dynamic
+finch_LDADD = \
+	@LIBOBJS@ \
+	$(DBUS_LIBS) \
+	$(INTLLIBS) \
+	$(GLIB_LIBS) \
+	$(LIBXML_LIBS) \
+	$(GNT_LIBS) \
+	./libgnt/libgnt.la \
+	$(top_builddir)/libpurple/libpurple.la
+
+AM_CPPFLAGS = \
+	-DSTANDALONE \
+	-DBR_PTHREADS=0 \
+	-DDATADIR=\"$(datadir)\" \
+	-DLIBDIR=\"$(libdir)/gaim/\" \
+	-DLOCALEDIR=\"$(datadir)/locale\" \
+	-DSYSCONFDIR=\"$(sysconfdir)\" \
+	-I$(top_srcdir)/libpurple/ \
+	-I$(top_srcdir) \
+	-I$(srcdir)/libgnt/ \
+	$(DEBUG_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	$(DBUS_CFLAGS) \
+	$(LIBXML_CFLAGS) \
+	$(GNT_CFLAGS)
+endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/getopt.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,737 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+   before changing it!
+
+   Gaim is the legal property of its developers, whose names are too numerous
+   to list here.  Please refer to the COPYRIGHT file distributed with this
+   source distribution.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* NOTE!!!  AIX requires this to be the first thing in the file.
+   Do not put ANYTHING before it!  */
+#if !defined (__GNUC__) && defined (_AIX)
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Alver says we need this for IRIX. */
+#if HAVE_STRING_H
+#include "string.h"
+#endif
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__))))
+#include <alloca.h>
+#else
+#ifndef _AIX
+char *alloca ();
+#endif
+#endif /* alloca.h */
+#endif /* not __GNUC__ */
+
+#if !__STDC__ && !defined(const) && IN_GCC
+#define const
+#endif
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.  */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef	__GNU_LIBRARY__
+#undef	alloca
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+   contain conflicting prototypes for getopt.  */
+#include <stdlib.h>
+#else	/* Not GNU C library.  */
+#define	__alloca	alloca
+#endif	/* GNU C library.  */
+
+/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
+   long-named option.  Because this is not POSIX.2 compliant, it is
+   being phased out.  */
+/* #define GETOPT_COMPAT */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg = 0;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* XXX 1003.2 says this must be 1 before any call.  */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
+
+static enum
+{
+  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+#ifdef	__GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+   because there are many ways it can cause trouble.
+   On some systems, it contains special magic macros that don't work
+   in GCC.  */
+#include <string.h>
+#define	my_index	strchr
+#define	my_bcopy(src, dst, n)	memcpy ((dst), (src), (n))
+#else
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+     const char *str;
+     int chr;
+{
+  while (*str)
+    {
+      if (*str == chr)
+	return (char *) str;
+      str++;
+    }
+  return 0;
+}
+
+static void
+my_bcopy (from, to, size)
+     const char *from;
+     char *to;
+     int size;
+{
+  int i;
+  for (i = 0; i < size; i++)
+    to[i] = from[i];
+}
+#endif				/* GNU C library.  */
+
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (argv)
+     char **argv;
+{
+  int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
+  char **temp = (char **) __alloca (nonopts_size);
+
+  /* Interchange the two blocks of data in ARGV.  */
+
+  my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size);
+  my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt],
+	    (optind - last_nonopt) * sizeof (char *));
+  my_bcopy ((char *) temp,
+	    (char *) &argv[first_nonopt + optind - last_nonopt],
+	    nonopts_size);
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns `EOF'.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+     const struct option *longopts;
+     int *longind;
+     int long_only;
+{
+  int option_index;
+
+  optarg = 0;
+
+  /* Initialize the internal data when the first call is made.
+     Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  if (optind == 0)
+    {
+      first_nonopt = last_nonopt = optind = 1;
+
+      nextchar = NULL;
+
+      /* Determine how to handle the ordering of options and nonoptions.  */
+
+      if (optstring[0] == '-')
+	{
+	  ordering = RETURN_IN_ORDER;
+	  ++optstring;
+	}
+      else if (optstring[0] == '+')
+	{
+	  ordering = REQUIRE_ORDER;
+	  ++optstring;
+	}
+      else if (getenv ("POSIXLY_CORRECT") != NULL)
+	ordering = REQUIRE_ORDER;
+      else
+	ordering = PERMUTE;
+    }
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      if (ordering == PERMUTE)
+	{
+	  /* If we have just processed some options following some non-options,
+	     exchange them so that the options come first.  */
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (last_nonopt != optind)
+	    first_nonopt = optind;
+
+	  /* Now skip any additional non-options
+	     and extend the range of non-options previously skipped.  */
+
+	  while (optind < argc
+		 && (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+		 && (longopts == NULL
+		     || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif				/* GETOPT_COMPAT */
+		 )
+	    optind++;
+	  last_nonopt = optind;
+	}
+
+      /* Special ARGV-element `--' means premature end of options.
+	 Skip it like a null option,
+	 then exchange with previous non-options as if it were an option,
+	 then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+	{
+	  optind++;
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (first_nonopt == last_nonopt)
+	    first_nonopt = optind;
+	  last_nonopt = argc;
+
+	  optind = argc;
+	}
+
+      /* If we have done all the ARGV-elements, stop the scan
+	 and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+	{
+	  /* Set the next-arg-index to point at the non-options
+	     that we previously skipped, so the caller will digest them.  */
+	  if (first_nonopt != last_nonopt)
+	    optind = first_nonopt;
+	  return EOF;
+	}
+
+      /* If we have come to a non-option and did not permute it,
+	 either stop the scan or describe it to the caller and pass it by.  */
+
+      if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+	  && (longopts == NULL
+	      || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif				/* GETOPT_COMPAT */
+	  )
+	{
+	  if (ordering == REQUIRE_ORDER)
+	    return EOF;
+	  optarg = argv[optind++];
+	  return 1;
+	}
+
+      /* We have found another option-ARGV-element.
+	 Start decoding its characters.  */
+
+      nextchar = (argv[optind] + 1
+		  + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  if (longopts != NULL
+      && ((argv[optind][0] == '-'
+	   && (argv[optind][1] == '-' || long_only))
+#ifdef GETOPT_COMPAT
+	  || argv[optind][0] == '+'
+#endif				/* GETOPT_COMPAT */
+	  ))
+    {
+      const struct option *p;
+      char *s = nextchar;
+      int exact = 0;
+      int ambig = 0;
+      const struct option *pfound = NULL;
+      int indfound;
+
+      while (*s && *s != '=')
+	s++;
+
+      /* Test all options for either exact match or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name;
+	   p++, option_index++)
+	if (!strncmp (p->name, nextchar, s - nextchar))
+	  {
+	    if (s - nextchar == strlen (p->name))
+	      {
+		/* Exact match found.  */
+		pfound = p;
+		indfound = option_index;
+		exact = 1;
+		break;
+	      }
+	    else if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else
+	      /* Second nonexact match found.  */
+	      ambig = 1;
+	  }
+
+      if (ambig && !exact)
+	{
+	  if (opterr)
+	    fprintf (stderr, "%s: option `%s' is ambiguous\n",
+		     argv[0], argv[optind]);
+	  nextchar += strlen (nextchar);
+	  optind++;
+	  return '?';
+	}
+
+      if (pfound != NULL)
+	{
+	  option_index = indfound;
+	  optind++;
+	  if (*s)
+	    {
+	      /* Don't test has_arg with >, because some C compilers don't
+		 allow it to be used on enums.  */
+	      if (pfound->has_arg)
+		optarg = s + 1;
+	      else
+		{
+		  if (opterr)
+		    {
+		      if (argv[optind - 1][1] == '-')
+			/* --option */
+			fprintf (stderr,
+				 "%s: option `--%s' doesn't allow an argument\n",
+				 argv[0], pfound->name);
+		      else
+			/* +option or -option */
+			fprintf (stderr,
+			     "%s: option `%c%s' doesn't allow an argument\n",
+			     argv[0], argv[optind - 1][0], pfound->name);
+		    }
+		  nextchar += strlen (nextchar);
+		  return '?';
+		}
+	    }
+	  else if (pfound->has_arg == 1)
+	    {
+	      if (optind < argc)
+		optarg = argv[optind++];
+	      else
+		{
+		  if (opterr)
+		    fprintf (stderr, "%s: option `%s' requires an argument\n",
+			     argv[0], argv[optind - 1]);
+		  nextchar += strlen (nextchar);
+		  return optstring[0] == ':' ? ':' : '?';
+		}
+	    }
+	  nextchar += strlen (nextchar);
+	  if (longind != NULL)
+	    *longind = option_index;
+	  if (pfound->flag)
+	    {
+	      *(pfound->flag) = pfound->val;
+	      return 0;
+	    }
+	  return pfound->val;
+	}
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+	 or the option starts with '--' or is not a valid short
+	 option, then it's an error.
+	 Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+#ifdef GETOPT_COMPAT
+	  || argv[optind][0] == '+'
+#endif				/* GETOPT_COMPAT */
+	  || my_index (optstring, *nextchar) == NULL)
+	{
+	  if (opterr)
+	    {
+	      if (argv[optind][1] == '-')
+		/* --option */
+		fprintf (stderr, "%s: unrecognized option `--%s'\n",
+			 argv[0], nextchar);
+	      else
+		/* +option or -option */
+		fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+			 argv[0], argv[optind][0], nextchar);
+	    }
+	  nextchar = (char *) "";
+	  optind++;
+	  return '?';
+	}
+    }
+
+  /* Look at and handle the next option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+	if (opterr)
+	  {
+#if 0
+	    if (c < 040 || c >= 0177)
+	      fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
+		       argv[0], c);
+	    else
+	      fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
+#else
+	    /* 1003.2 specifies the format of this message.  */
+	    fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+#endif
+	  }
+	optopt = c;
+	return '?';
+      }
+    if (temp[1] == ':')
+      {
+	if (temp[2] == ':')
+	  {
+	    /* This is an option that accepts an argument optionally.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		optind++;
+	      }
+	    else
+	      optarg = 0;
+	    nextchar = NULL;
+	  }
+	else
+	  {
+	    /* This is an option that requires an argument.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		/* If we end this ARGV-element by taking the rest as an arg,
+		   we must advance to the next element now.  */
+		optind++;
+	      }
+	    else if (optind == argc)
+	      {
+		if (opterr)
+		  {
+#if 0
+		    fprintf (stderr, "%s: option `-%c' requires an argument\n",
+			     argv[0], c);
+#else
+		    /* 1003.2 specifies the format of this message.  */
+		    fprintf (stderr, "%s: option requires an argument -- %c\n",
+			     argv[0], c);
+#endif
+		  }
+		optopt = c;
+		if (optstring[0] == ':')
+		  c = ':';
+		else
+		  c = '?';
+	      }
+	    else
+	      /* We already incremented `optind' once;
+		 increment it again when taking next ARGV-elt as argument.  */
+	      optarg = argv[optind++];
+	    nextchar = NULL;
+	  }
+      }
+    return c;
+  }
+}
+
+int
+getopt (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  return _getopt_internal (argc, argv, optstring,
+			   (const struct option *) 0,
+			   (int *) 0,
+			   0);
+}
+
+#endif	/* _LIBC or not __GNU_LIBRARY__.  */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == EOF)
+	break;
+
+      switch (c)
+	{
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/getopt.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,136 @@
+/* Declarations for getopt.
+
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+   before changing it!
+
+   Gaim is the legal property of its developers, whose names are too numerous
+   to list here.  Please refer to the COPYRIGHT file distributed with this
+   source distribution.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument		(or 0) if the option does not take an argument,
+   required_argument	(or 1) if the option requires an argument,
+   optional_argument 	(or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+#if	__STDC__
+  const char *name;
+#else
+  char *name;
+#endif
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define	no_argument		0
+#define required_argument	1
+#define optional_argument	2
+
+#if __STDC__
+#if defined(__GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* not __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+		        const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+			     const char *shortopts,
+		             const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+extern int _getopt_internal (int argc, char *const *argv,
+			     const char *shortopts,
+		             const struct option *longopts, int *longind,
+			     int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* not __STDC__ */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/getopt1.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,177 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+   Gaim is the legal property of its developers, whose names are too numerous
+   to list here.  Please refer to the COPYRIGHT file distributed with this
+   source distribution.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "getopt.h"
+
+#if !__STDC__ && !defined(const) && IN_GCC
+#define const
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#else
+char *getenv ();
+#endif
+
+#ifndef	NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif	/* _LIBC or not __GNU_LIBRARY__.  */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+      int option_index = 0;
+      static struct option long_options[] =
+      {
+	{"add", 1, 0, 0},
+	{"append", 0, 0, 0},
+	{"delete", 1, 0, 0},
+	{"verbose", 0, 0, 0},
+	{"create", 0, 0, 0},
+	{"file", 1, 0, 0},
+	{0, 0, 0, 0}
+      };
+
+      c = getopt_long (argc, argv, "abc:d:0123456789",
+		       long_options, &option_index);
+      if (c == EOF)
+	break;
+
+      switch (c)
+	{
+	case 0:
+	  printf ("option %s", long_options[option_index].name);
+	  if (optarg)
+	    printf (" with arg %s", optarg);
+	  printf ("\n");
+	  break;
+
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case 'd':
+	  printf ("option d with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntaccount.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,936 @@
+/**
+ * @file gntaccount.c GNT Account API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntcheckbox.h>
+#include <gntcombobox.h>
+#include <gntentry.h>
+#include <gntlabel.h>
+#include <gntline.h>
+#include <gnttree.h>
+
+#include <account.h>
+#include <accountopt.h>
+#include <connection.h>
+#include <notify.h>
+#include <plugin.h>
+#include <request.h>
+
+#include "gntaccount.h"
+#include "gntgaim.h"
+
+#include <string.h>
+
+typedef struct
+{
+	GntWidget *window;
+	GntWidget *tree;
+} FinchAccountList;
+
+static FinchAccountList accounts;
+
+typedef struct
+{
+	GaimAccount *account;          /* NULL for a new account */
+
+	GntWidget *window;
+
+	GntWidget *protocol;
+	GntWidget *screenname;
+	GntWidget *password;
+	GntWidget *alias;
+	
+	GntWidget *splits;
+	GList *split_entries;
+
+	GList *prpl_entries;
+	GntWidget *prpls;
+
+	GntWidget *newmail;
+	GntWidget *remember;
+} AccountEditDialog;
+
+/* This is necessary to close an edit-dialog when an account is deleted */
+static GList *accountdialogs;
+
+static void
+account_add(GaimAccount *account)
+{
+	gnt_tree_add_choice(GNT_TREE(accounts.tree), account,
+			gnt_tree_create_row(GNT_TREE(accounts.tree),
+				gaim_account_get_username(account),
+				gaim_account_get_protocol_name(account)),
+			NULL, NULL);
+	gnt_tree_set_choice(GNT_TREE(accounts.tree), account,
+			gaim_account_get_enabled(account, GAIM_GNT_UI));
+}
+
+static void
+edit_dialog_destroy(AccountEditDialog *dialog)
+{
+	accountdialogs = g_list_remove(accountdialogs, dialog);
+	g_list_free(dialog->prpl_entries);
+	g_list_free(dialog->split_entries);
+	g_free(dialog);
+}
+
+static void
+save_account_cb(AccountEditDialog *dialog)
+{
+	GaimAccount *account;
+	GaimPlugin *plugin;
+	GaimPluginProtocolInfo *prplinfo;
+	const char *value;
+	GString *username;
+
+	/* XXX: Do some error checking first. */
+
+	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
+	prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
+
+	/* Screenname && user-splits */
+	value = gnt_entry_get_text(GNT_ENTRY(dialog->screenname));
+
+	if (value == NULL || *value == '\0')
+	{
+		gaim_notify_error(NULL, _("Error"), _("Account was not added"),
+				_("Screenname of an account must be non-empty."));
+		return;
+	}
+	
+	username = g_string_new(value);
+
+	if (prplinfo != NULL)
+	{
+		GList *iter, *entries;
+		for (iter = prplinfo->user_splits, entries = dialog->split_entries;
+				iter && entries; iter = iter->next, entries = entries->next)
+		{
+			GaimAccountUserSplit *split = iter->data;
+			GntWidget *entry = entries->data;
+
+			value = gnt_entry_get_text(GNT_ENTRY(entry));
+			if (value == NULL || *value == '\0')
+				value = gaim_account_user_split_get_default_value(split);
+			g_string_append_printf(username, "%c%s",
+					gaim_account_user_split_get_separator(split),
+					value);
+		}
+	}
+
+	if (dialog->account == NULL)
+	{
+		account = gaim_account_new(username->str, gaim_plugin_get_id(plugin));
+		gaim_accounts_add(account);
+	}
+	else
+	{
+		account = dialog->account;
+
+		/* Protocol */
+		gaim_account_set_protocol_id(account, gaim_plugin_get_id(plugin));
+		gaim_account_set_username(account, username->str);
+	}
+	g_string_free(username, TRUE);
+
+	/* Alias */
+	value = gnt_entry_get_text(GNT_ENTRY(dialog->alias));
+	if (value && *value)
+		gaim_account_set_alias(account, value);
+
+	/* Remember password and password */
+	gaim_account_set_remember_password(account,
+			gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->remember)));
+	value = gnt_entry_get_text(GNT_ENTRY(dialog->password));
+	if (value && *value && gaim_account_get_remember_password(account))
+		gaim_account_set_password(account, value);
+	else
+		gaim_account_set_password(account, NULL);
+
+	/* Mail notification */
+	gaim_account_set_check_mail(account,
+			gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->newmail)));
+
+	/* Protocol options */
+	if (prplinfo)
+	{
+		GList *iter, *entries;
+		
+		for (iter = prplinfo->protocol_options, entries = dialog->prpl_entries;
+				iter && entries; iter = iter->next, entries = entries->next)
+		{
+			GaimAccountOption *option = iter->data;
+			GntWidget *entry = entries->data;
+			GaimPrefType type = gaim_account_option_get_type(option);
+			const char *setting = gaim_account_option_get_setting(option);
+
+			if (type == GAIM_PREF_STRING)
+			{
+				const char *value = gnt_entry_get_text(GNT_ENTRY(entry));
+				gaim_account_set_string(account, setting, value);
+			}
+			else if (type == GAIM_PREF_INT)
+			{
+				const char *str = gnt_entry_get_text(GNT_ENTRY(entry));
+				int value = 0;
+				if (str)
+					value = atoi(str);
+				gaim_account_set_int(account, setting, value);
+			}
+			else if (type == GAIM_PREF_BOOLEAN)
+			{
+				gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(entry));
+				gaim_account_set_bool(account, setting, value);
+			}
+			else if (type == GAIM_PREF_STRING_LIST)
+			{
+				/* TODO: */
+			}
+			else
+			{
+				g_assert_not_reached();
+			}
+		}
+	}
+
+	/* XXX: Proxy options */
+
+	gnt_widget_destroy(dialog->window);
+}
+
+static void
+update_user_splits(AccountEditDialog *dialog)
+{
+	GntWidget *hbox;
+	GaimPlugin *plugin;
+	GaimPluginProtocolInfo *prplinfo;
+	GList *iter, *entries;
+	char *username = NULL;
+
+	if (dialog->splits)
+	{
+		gnt_box_remove_all(GNT_BOX(dialog->splits));
+		g_list_free(dialog->split_entries);
+	}
+	else
+	{
+		dialog->splits = gnt_vbox_new(FALSE);
+		gnt_box_set_pad(GNT_BOX(dialog->splits), 0);
+		gnt_box_set_fill(GNT_BOX(dialog->splits), TRUE);
+	}
+
+	dialog->split_entries = NULL;
+
+	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
+	if (!plugin)
+		return;
+	prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
+	
+	username = dialog->account ? g_strdup(gaim_account_get_username(dialog->account)) : NULL;
+
+	for (iter = prplinfo->user_splits; iter; iter = iter->next)
+	{
+		GaimAccountUserSplit *split = iter->data;
+		GntWidget *entry;
+		char *buf;
+
+		hbox = gnt_hbox_new(TRUE);
+		gnt_box_add_widget(GNT_BOX(dialog->splits), hbox);
+
+		buf = g_strdup_printf("%s:", gaim_account_user_split_get_text(split));
+		gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(buf));
+
+		entry = gnt_entry_new(NULL);
+		gnt_box_add_widget(GNT_BOX(hbox), entry);
+
+		dialog->split_entries = g_list_append(dialog->split_entries, entry);
+		g_free(buf);
+	}
+
+	for (iter = g_list_last(prplinfo->user_splits), entries = g_list_last(dialog->split_entries);
+			iter && entries; iter = iter->prev, entries = entries->prev)
+	{
+		GntWidget *entry = entries->data;
+		GaimAccountUserSplit *split = iter->data;
+		const char *value = NULL;
+		char *s;
+
+		if (dialog->account)
+		{
+			s = strrchr(username, gaim_account_user_split_get_separator(split));
+			if (s != NULL)
+			{
+				*s = '\0';
+				s++;
+				value = s;
+			}
+		}
+		if (value == NULL)
+			value = gaim_account_user_split_get_default_value(split);
+
+		if (value != NULL)
+			gnt_entry_set_text(GNT_ENTRY(entry), value);
+	}
+
+	if (username != NULL)
+		gnt_entry_set_text(GNT_ENTRY(dialog->screenname), username);
+
+	g_free(username);
+}
+
+static void
+add_protocol_options(AccountEditDialog *dialog)
+{
+	GaimPlugin *plugin;
+	GaimPluginProtocolInfo *prplinfo;
+	GList *iter;
+	GntWidget *vbox, *box;
+	GaimAccount *account;
+
+	if (dialog->prpls)
+		gnt_box_remove_all(GNT_BOX(dialog->prpls));
+	else
+	{
+		dialog->prpls = vbox = gnt_vbox_new(FALSE);
+		gnt_box_set_pad(GNT_BOX(vbox), 0);
+		gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_LEFT);
+		gnt_box_set_fill(GNT_BOX(vbox), TRUE);
+	}
+
+	if (dialog->prpl_entries)
+	{
+		g_list_free(dialog->prpl_entries);
+		dialog->prpl_entries = NULL;
+	}
+
+	vbox = dialog->prpls;
+
+	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
+	if (!plugin)
+		return;
+
+	prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
+
+	account = dialog->account;
+
+	for (iter = prplinfo->protocol_options; iter; iter = iter->next)
+	{
+		GaimAccountOption *option = iter->data;
+		GaimPrefType type = gaim_account_option_get_type(option);
+
+		box = gnt_hbox_new(TRUE);
+		gnt_box_set_pad(GNT_BOX(box), 0);
+		gnt_box_add_widget(GNT_BOX(vbox), box);
+
+		if (type == GAIM_PREF_BOOLEAN)
+		{
+			GntWidget *widget = gnt_check_box_new(gaim_account_option_get_text(option));
+			gnt_box_add_widget(GNT_BOX(box), widget);
+			dialog->prpl_entries = g_list_append(dialog->prpl_entries, widget);
+
+			if (account)
+				gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
+						gaim_account_get_bool(account,
+							gaim_account_option_get_setting(option),
+							gaim_account_option_get_default_bool(option)));
+			else
+				gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
+						gaim_account_option_get_default_bool(option));
+		}
+		else
+		{
+			gnt_box_add_widget(GNT_BOX(box),
+					gnt_label_new(gaim_account_option_get_text(option)));
+
+			if (type == GAIM_PREF_STRING_LIST)
+			{
+				/* TODO: Use a combobox */
+				/*       Don't forget to append the widget to prpl_entries */
+			}
+			else
+			{
+				GntWidget *entry = gnt_entry_new(NULL);
+				gnt_box_add_widget(GNT_BOX(box), entry);
+				dialog->prpl_entries = g_list_append(dialog->prpl_entries, entry);
+
+				if (type == GAIM_PREF_STRING)
+				{
+					const char *dv = gaim_account_option_get_default_string(option);
+
+					if (account)
+						gnt_entry_set_text(GNT_ENTRY(entry),
+								gaim_account_get_string(account,
+									gaim_account_option_get_setting(option), dv));
+					else
+						gnt_entry_set_text(GNT_ENTRY(entry), dv);
+				}
+				else if (type == GAIM_PREF_INT)
+				{
+					char str[32];
+					int value = gaim_account_option_get_default_int(option);
+					if (account)
+						value = gaim_account_get_int(account,
+								gaim_account_option_get_setting(option), value);
+					snprintf(str, sizeof(str), "%d", value);
+					gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
+					gnt_entry_set_text(GNT_ENTRY(entry), str);
+				}
+				else
+				{
+					g_assert_not_reached();
+				}
+			}
+		}
+	}
+}
+
+static void
+update_user_options(AccountEditDialog *dialog)
+{
+	GaimPlugin *plugin;
+	GaimPluginProtocolInfo *prplinfo;
+
+	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
+	if (!plugin)
+		return;
+
+	prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
+
+	if (dialog->newmail == NULL)
+		dialog->newmail = gnt_check_box_new(_("New mail notifications"));
+	if (dialog->account)
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->newmail),
+				gaim_account_get_check_mail(dialog->account));
+	if (!prplinfo || !(prplinfo->options & OPT_PROTO_MAIL_CHECK))
+		gnt_widget_set_visible(dialog->newmail, FALSE);
+	else
+		gnt_widget_set_visible(dialog->newmail, TRUE);
+
+	if (dialog->remember == NULL)
+		dialog->remember = gnt_check_box_new(_("Remember password"));
+	if (dialog->account)
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->remember),
+				gaim_account_get_remember_password(dialog->account));
+}
+
+static void
+prpl_changed_cb(GntWidget *combo, GaimPlugin *old, GaimPlugin *new, AccountEditDialog *dialog)
+{
+	update_user_splits(dialog);
+	add_protocol_options(dialog);
+	update_user_options(dialog);  /* This may not be necessary here */
+	gnt_box_readjust(GNT_BOX(dialog->window));
+	gnt_widget_draw(dialog->window);
+}
+
+static void
+edit_account(GaimAccount *account)
+{
+	GntWidget *window, *hbox;
+	GntWidget *combo, *button, *entry;
+	GList *list, *iter;
+	AccountEditDialog *dialog;
+
+	if (account)
+	{
+		GList *iter;
+		for (iter = accountdialogs; iter; iter = iter->next)
+		{
+			AccountEditDialog *dlg = iter->data;
+			if (dlg->account == account)
+				return;
+		}
+	}
+
+	dialog = g_new0(AccountEditDialog, 1);
+	accountdialogs = g_list_prepend(accountdialogs, dialog);
+
+	dialog->window = window = gnt_vbox_new(FALSE);
+	dialog->account = account;
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_title(GNT_BOX(window), account ? _("Modify Account") : _("New Account"));
+	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
+	gnt_box_set_pad(GNT_BOX(window), 0);
+	gnt_widget_set_name(window, "edit-account");
+	gnt_box_set_fill(GNT_BOX(window), TRUE);
+
+	hbox = gnt_hbox_new(TRUE);
+	gnt_box_set_pad(GNT_BOX(hbox), 0);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+
+	dialog->protocol = combo = gnt_combo_box_new();
+	list = gaim_plugins_get_protocols();
+	for (iter = list; iter; iter = iter->next)
+	{
+		gnt_combo_box_add_data(GNT_COMBO_BOX(combo), iter->data,
+				((GaimPlugin*)iter->data)->info->name);
+	}
+
+	if (account)
+		gnt_combo_box_set_selected(GNT_COMBO_BOX(combo),
+				gaim_plugins_find_with_id(gaim_account_get_protocol_id(account)));
+	else
+		gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), list->data);
+
+	g_signal_connect(G_OBJECT(combo), "selection-changed", G_CALLBACK(prpl_changed_cb), dialog);
+
+	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Protocol:")));
+	gnt_box_add_widget(GNT_BOX(hbox), combo);
+
+	hbox = gnt_hbox_new(TRUE);
+	gnt_box_set_pad(GNT_BOX(hbox), 0);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+
+	dialog->screenname = entry = gnt_entry_new(NULL);
+	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Screen name:")));
+	gnt_box_add_widget(GNT_BOX(hbox), entry);
+
+	/* User splits */
+	update_user_splits(dialog);
+	gnt_box_add_widget(GNT_BOX(window), dialog->splits);
+
+	hbox = gnt_hbox_new(TRUE);
+	gnt_box_set_pad(GNT_BOX(hbox), 0);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+
+	dialog->password = entry = gnt_entry_new(NULL);
+	gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
+	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Password:")));
+	gnt_box_add_widget(GNT_BOX(hbox), entry);
+	if (account)
+		gnt_entry_set_text(GNT_ENTRY(entry), gaim_account_get_password(account));
+
+	hbox = gnt_hbox_new(TRUE);
+	gnt_box_set_pad(GNT_BOX(hbox), 0);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+
+	dialog->alias = entry = gnt_entry_new(NULL);
+	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Alias:")));
+	gnt_box_add_widget(GNT_BOX(hbox), entry);
+	if (account)
+		gnt_entry_set_text(GNT_ENTRY(entry), gaim_account_get_alias(account));
+
+	/* User options */
+	update_user_options(dialog);
+	gnt_box_add_widget(GNT_BOX(window), dialog->remember);
+	gnt_box_add_widget(GNT_BOX(window), dialog->newmail);
+
+	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
+
+	/* The advanced box */
+	add_protocol_options(dialog);
+	gnt_box_add_widget(GNT_BOX(window), dialog->prpls);
+
+	/* TODO: Add proxy options */
+
+	/* The button box */
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
+
+	button = gnt_button_new(_("Cancel"));
+	gnt_box_add_widget(GNT_BOX(hbox), button);
+	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window);
+	
+	button = gnt_button_new(_("Save"));
+	gnt_box_add_widget(GNT_BOX(hbox), button);
+	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(save_account_cb), dialog);
+
+	g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(edit_dialog_destroy), dialog);
+
+	gnt_widget_show(window);
+	gnt_box_readjust(GNT_BOX(window));
+	gnt_widget_draw(window);
+}
+
+static void
+add_account_cb(GntWidget *widget, gpointer null)
+{
+	edit_account(NULL);
+}
+
+static void
+modify_account_cb(GntWidget *widget, GntTree *tree)
+{
+	GaimAccount *account = gnt_tree_get_selection_data(tree);
+	if (!account)
+		return;
+	edit_account(account);
+}
+
+static void
+really_delete_account(GaimAccount *account)
+{
+	GList *iter;
+	for (iter = accountdialogs; iter; iter = iter->next)
+	{
+		AccountEditDialog *dlg = iter->data;
+		if (dlg->account == account)
+		{
+			gnt_widget_destroy(dlg->window);
+			break;
+		}
+	}
+	gaim_request_close_with_handle(account); /* Close any other opened delete window */
+	gaim_accounts_delete(account);
+}
+
+static void
+delete_account_cb(GntWidget *widget, GntTree *tree)
+{
+	GaimAccount *account;
+	char *prompt;
+
+	account  = gnt_tree_get_selection_data(tree);
+	if (!account)
+		return;
+
+	prompt = g_strdup_printf(_("Are you sure you want to delete %s?"),
+			gaim_account_get_username(account));
+
+	gaim_request_action(account, _("Delete Account"), prompt, NULL, 0, account, 2,
+			_("Delete"), really_delete_account, _("Cancel"), NULL);
+	g_free(prompt);
+}
+
+static void
+account_toggled(GntWidget *widget, void *key, gpointer null)
+{
+	GaimAccount *account = key;
+
+	gaim_account_set_enabled(account, GAIM_GNT_UI, gnt_tree_get_choice(GNT_TREE(widget), key));
+}
+
+static void
+reset_accounts_win(GntWidget *widget, gpointer null)
+{
+	accounts.window = NULL;
+	accounts.tree = NULL;
+}
+
+void finch_accounts_show_all()
+{
+	GList *iter;
+	GntWidget *box, *button;
+
+	if (accounts.window)
+		return;
+
+	accounts.window = gnt_vbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(accounts.window), TRUE);
+	gnt_box_set_title(GNT_BOX(accounts.window), _("Accounts"));
+	gnt_box_set_pad(GNT_BOX(accounts.window), 0);
+	gnt_box_set_alignment(GNT_BOX(accounts.window), GNT_ALIGN_MID);
+	gnt_widget_set_name(accounts.window, "accounts");
+
+	gnt_box_add_widget(GNT_BOX(accounts.window),
+			gnt_label_new(_("You can enable/disable accounts from the following list.")));
+
+	gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE));
+
+	accounts.tree = gnt_tree_new_with_columns(2);
+	GNT_WIDGET_SET_FLAGS(accounts.tree, GNT_WIDGET_NO_BORDER);
+
+	for (iter = gaim_accounts_get_all(); iter; iter = iter->next)
+	{
+		GaimAccount *account = iter->data;
+		account_add(account);
+	}
+
+	g_signal_connect(G_OBJECT(accounts.tree), "toggled", G_CALLBACK(account_toggled), NULL);
+	
+	gnt_tree_set_col_width(GNT_TREE(accounts.tree), 0, 40);
+	gnt_tree_set_col_width(GNT_TREE(accounts.tree), 1, 10);
+	gnt_box_add_widget(GNT_BOX(accounts.window), accounts.tree);
+
+	gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE));
+
+	box = gnt_hbox_new(FALSE);
+
+	button = gnt_button_new(_("Add"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(add_account_cb), NULL);
+
+	button = gnt_button_new(_("Modify"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(modify_account_cb), accounts.tree);
+
+	button = gnt_button_new(_("Delete"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(delete_account_cb), accounts.tree);
+	
+	gnt_box_add_widget(GNT_BOX(accounts.window), box);
+
+	g_signal_connect(G_OBJECT(accounts.window), "destroy", G_CALLBACK(reset_accounts_win), NULL);
+	
+	gnt_widget_show(accounts.window);
+}
+
+static gpointer
+finch_accounts_get_handle()
+{
+	static int handle;
+
+	return &handle;
+}
+
+static void
+account_added_callback(GaimAccount *account)
+{
+	if (accounts.window == NULL)
+		return;
+	account_add(account);
+	gnt_widget_draw(accounts.tree);
+}
+
+static void
+account_removed_callback(GaimAccount *account)
+{
+	if (accounts.window == NULL)
+		return;
+
+	gnt_tree_remove(GNT_TREE(accounts.tree), account);
+}
+
+void finch_accounts_init()
+{
+	GList *iter;
+
+	gaim_signal_connect(gaim_accounts_get_handle(), "account-added",
+			finch_accounts_get_handle(), GAIM_CALLBACK(account_added_callback),
+			NULL);
+	gaim_signal_connect(gaim_accounts_get_handle(), "account-removed",
+			finch_accounts_get_handle(), GAIM_CALLBACK(account_removed_callback),
+			NULL);
+	
+	for (iter = gaim_accounts_get_all(); iter; iter = iter->next) {
+		if (gaim_account_get_enabled(iter->data, GAIM_GNT_UI))
+			break;
+	}
+	if (!iter)
+		finch_accounts_show_all();
+}
+
+void finch_accounts_uninit()
+{
+	if (accounts.window)
+		gnt_widget_destroy(accounts.window);
+}
+
+/* The following uiops stuff are copied from gtkaccount.c */
+typedef struct
+{
+	GaimAccount *account;
+	char *username;
+	char *alias;
+} AddUserData;
+
+static char *
+make_info(GaimAccount *account, GaimConnection *gc, const char *remote_user,
+          const char *id, const char *alias, const char *msg)
+{
+	if (msg != NULL && *msg == '\0')
+		msg = NULL;
+
+	return g_strdup_printf(_("%s%s%s%s has made %s his or her buddy%s%s"),
+	                       remote_user,
+	                       (alias != NULL ? " ("  : ""),
+	                       (alias != NULL ? alias : ""),
+	                       (alias != NULL ? ")"   : ""),
+	                       (id != NULL
+	                        ? id
+	                        : (gaim_connection_get_display_name(gc) != NULL
+	                           ? gaim_connection_get_display_name(gc)
+	                           : gaim_account_get_username(account))),
+	                       (msg != NULL ? ": " : "."),
+	                       (msg != NULL ? msg  : ""));
+}
+
+static void
+notify_added(GaimAccount *account, const char *remote_user,
+			const char *id, const char *alias,
+			const char *msg)
+{
+	char *buffer;
+	GaimConnection *gc;
+
+	gc = gaim_account_get_connection(account);
+
+	buffer = make_info(account, gc, remote_user, id, alias, msg);
+
+	gaim_notify_info(NULL, NULL, buffer, NULL);
+
+	g_free(buffer);
+}
+
+static void
+free_add_user_data(AddUserData *data)
+{
+	g_free(data->username);
+
+	if (data->alias != NULL)
+		g_free(data->alias);
+
+	g_free(data);
+}
+
+static void
+add_user_cb(AddUserData *data)
+{
+	GaimConnection *gc = gaim_account_get_connection(data->account);
+
+	if (g_list_find(gaim_connections_get_all(), gc))
+	{
+		gaim_blist_request_add_buddy(data->account, data->username,
+									 NULL, data->alias);
+	}
+
+	free_add_user_data(data);
+}
+
+static void
+request_add(GaimAccount *account, const char *remote_user,
+		  const char *id, const char *alias,
+		  const char *msg)
+{
+	char *buffer;
+	GaimConnection *gc;
+	AddUserData *data;
+
+	gc = gaim_account_get_connection(account);
+
+	data = g_new0(AddUserData, 1);
+	data->account  = account;
+	data->username = g_strdup(remote_user);
+	data->alias    = (alias != NULL ? g_strdup(alias) : NULL);
+
+	buffer = make_info(account, gc, remote_user, id, alias, msg);
+	gaim_request_action(NULL, NULL, _("Add buddy to your list?"),
+	                    buffer, GAIM_DEFAULT_ACTION_NONE, data, 2,
+	                    _("Add"),    G_CALLBACK(add_user_cb),
+	                    _("Cancel"), G_CALLBACK(free_add_user_data));
+	g_free(buffer);
+}
+
+/* Copied from gtkaccount.c */
+typedef struct {
+	GaimAccountRequestAuthorizationCb auth_cb;
+	GaimAccountRequestAuthorizationCb deny_cb;
+	void *data;
+	char *username;
+	char *alias;
+	GaimAccount *account;
+} auth_and_add;
+
+static void
+authorize_and_add_cb(auth_and_add *aa)
+{
+	aa->auth_cb(aa->data);
+	gaim_blist_request_add_buddy(aa->account, aa->username,
+	 	                    NULL, aa->alias);
+
+	g_free(aa->username);
+	g_free(aa->alias);
+	g_free(aa);
+}
+
+static void
+deny_no_add_cb(auth_and_add *aa)
+{
+	aa->deny_cb(aa->data);
+
+	g_free(aa->username);
+	g_free(aa->alias);
+	g_free(aa);
+}
+
+static void *
+finch_request_authorize(GaimAccount *account, const char *remote_user,
+					const char *id, const char *alias, const char *message, gboolean on_list,
+					GCallback auth_cb, GCallback deny_cb, void *user_data)
+{
+	char *buffer;
+	GaimConnection *gc;
+	void *uihandle;
+
+	gc = gaim_account_get_connection(account);
+	if (message != NULL && *message == '\0')
+		message = NULL;
+
+	buffer = g_strdup_printf(_("%s%s%s%s wants to add %s to his or her buddy list%s%s"),
+				remote_user,
+	 	                (alias != NULL ? " ("  : ""),
+		                (alias != NULL ? alias : ""),
+		                (alias != NULL ? ")"   : ""),
+		                (id != NULL
+		                ? id
+		                : (gaim_connection_get_display_name(gc) != NULL
+		                ? gaim_connection_get_display_name(gc)
+		                : gaim_account_get_username(account))),
+		                (message != NULL ? ": " : "."),
+		                (message != NULL ? message  : ""));
+	if (!on_list) {
+		auth_and_add *aa = g_new(auth_and_add, 1);
+		aa->auth_cb = (GaimAccountRequestAuthorizationCb)auth_cb;
+		aa->deny_cb = (GaimAccountRequestAuthorizationCb)deny_cb;
+		aa->data = user_data;
+		aa->username = g_strdup(remote_user);
+		aa->alias = g_strdup(alias);
+		aa->account = account;
+		uihandle = gaim_request_action(NULL, _("Authorize buddy?"), buffer, NULL,
+			GAIM_DEFAULT_ACTION_NONE, aa, 2,
+			_("Authorize"), authorize_and_add_cb,
+			_("Deny"), deny_no_add_cb);
+	} else {
+		uihandle = gaim_request_action(NULL, _("Authorize buddy?"), buffer, NULL,
+			GAIM_DEFAULT_ACTION_NONE, user_data, 2,
+			_("Authorize"), auth_cb,
+			_("Deny"), deny_cb);
+	}
+	g_free(buffer);
+	return uihandle;
+}
+
+static void
+finch_request_close(void *uihandle)
+{
+	gaim_request_close(GAIM_REQUEST_ACTION, uihandle);
+}
+
+static GaimAccountUiOps ui_ops =
+{
+	.notify_added = notify_added,
+	.status_changed = NULL,
+	.request_add  = request_add,
+	.request_authorize = finch_request_authorize,
+	.close_account_request = finch_request_close
+};
+
+GaimAccountUiOps *finch_accounts_get_ui_ops()
+{
+	return &ui_ops;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntaccount.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,59 @@
+/**
+ * @file gntaccount.h GNT Account API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_ACCOUNT_H
+#define _GNT_ACCOUNT_H
+
+#include "account.h"
+
+/**********************************************************************
+ * @name GNT Account API
+ **********************************************************************/
+/*@{*/
+
+/**
+ * Get the ui-functions.
+ *
+ * @return The GaimAccountUiOps structure populated with the appropriate functions.
+ */
+GaimAccountUiOps *finch_accounts_get_ui_ops(void);
+
+/**
+ * Perform necessary initializations.
+ */
+void finch_accounts_init(void);
+
+/**
+ * Perform necessary uninitializations.
+ */
+void finch_accounts_uninit(void);
+
+/**
+ * Show the account-manager dialog.
+ */
+void finch_accounts_show_all(void);
+
+/*@}*/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntblist.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,2233 @@
+/**
+ * @file gntblist.c GNT BuddyList API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <account.h>
+#include <blist.h>
+#include <notify.h>
+#include <request.h>
+#include <savedstatuses.h>
+#include <server.h>
+#include <signal.h>
+#include <status.h>
+#include <util.h>
+#include "debug.h"
+
+#include "gntgaim.h"
+#include "gntbox.h"
+#include "gntcombobox.h"
+#include "gntentry.h"
+#include "gntft.h"
+#include "gntlabel.h"
+#include "gntline.h"
+#include "gntmenu.h"
+#include "gntmenuitem.h"
+#include "gntmenuitemcheck.h"
+#include "gntpounce.h"
+#include "gnttree.h"
+#include "gntutils.h"
+#include "gntwindow.h"
+
+#include "gntblist.h"
+#include "gntconv.h"
+#include "gntstatus.h"
+#include <string.h>
+
+#define PREF_ROOT "/gaim/gnt/blist"
+#define TYPING_TIMEOUT 4000
+
+typedef struct
+{
+	GntWidget *window;
+	GntWidget *tree;
+
+	GntWidget *tooltip;
+	GaimBlistNode *tnode;		/* Who is the tooltip being displayed for? */
+	GList *tagged;          /* A list of tagged blistnodes */
+
+	GntWidget *context;
+	GaimBlistNode *cnode;
+
+	/* XXX: I am KISSing */
+	GntWidget *status;          /* Dropdown with the statuses  */
+	GntWidget *statustext;      /* Status message */
+	int typing;
+
+	GntWidget *menu;
+	/* These are the menuitems that get regenerated */
+	GntMenuItem *accounts;
+	GntMenuItem *plugins;
+} FinchBlist;
+
+typedef enum
+{
+	STATUS_PRIMITIVE = 0,
+	STATUS_SAVED_POPULAR,
+	STATUS_SAVED_ALL,
+	STATUS_SAVED_NEW
+} StatusType;
+
+typedef struct
+{
+	StatusType type;
+	union
+	{
+		GaimStatusPrimitive prim;
+		GaimSavedStatus *saved;
+	} u;
+} StatusBoxItem;
+
+FinchBlist *ggblist;
+
+static void add_buddy(GaimBuddy *buddy, FinchBlist *ggblist);
+static void add_contact(GaimContact *contact, FinchBlist *ggblist);
+static void add_group(GaimGroup *group, FinchBlist *ggblist);
+static void add_chat(GaimChat *chat, FinchBlist *ggblist);
+static void add_node(GaimBlistNode *node, FinchBlist *ggblist);
+static void draw_tooltip(FinchBlist *ggblist);
+static gboolean remove_typing_cb(gpointer null);
+static void remove_peripherals(FinchBlist *ggblist);
+static const char * get_display_name(GaimBlistNode *node);
+static void savedstatus_changed(GaimSavedStatus *now, GaimSavedStatus *old);
+static void blist_show(GaimBuddyList *list);
+static void update_buddy_display(GaimBuddy *buddy, FinchBlist *ggblist);
+static void account_signed_on_cb(void);
+
+/* Sort functions */
+static int blist_node_compare_text(GaimBlistNode *n1, GaimBlistNode *n2);
+static int blist_node_compare_status(GaimBlistNode *n1, GaimBlistNode *n2);
+static int blist_node_compare_log(GaimBlistNode *n1, GaimBlistNode *n2);
+
+static gboolean
+is_contact_online(GaimContact *contact)
+{
+	GaimBlistNode *node;
+	for (node = ((GaimBlistNode*)contact)->child; node; node = node->next) {
+		if (GAIM_BUDDY_IS_ONLINE((GaimBuddy*)node))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+is_group_online(GaimGroup *group)
+{
+	GaimBlistNode *node;
+	for (node = ((GaimBlistNode*)group)->child; node; node = node->next) {
+		if (GAIM_BLIST_NODE_IS_CHAT(node))
+			return TRUE;
+		else if (is_contact_online((GaimContact*)node))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static void
+new_node(GaimBlistNode *node)
+{
+}
+
+static void add_node(GaimBlistNode *node, FinchBlist *ggblist)
+{
+	if (GAIM_BLIST_NODE_IS_BUDDY(node))
+		add_buddy((GaimBuddy*)node, ggblist);
+	else if (GAIM_BLIST_NODE_IS_CONTACT(node))
+		add_contact((GaimContact*)node, ggblist);
+	else if (GAIM_BLIST_NODE_IS_GROUP(node))
+		add_group((GaimGroup*)node, ggblist);
+	else if (GAIM_BLIST_NODE_IS_CHAT(node))
+		add_chat((GaimChat *)node, ggblist);
+	draw_tooltip(ggblist);
+}
+
+static void
+remove_tooltip(FinchBlist *ggblist)
+{
+	gnt_widget_destroy(ggblist->tooltip);
+	ggblist->tooltip = NULL;
+	ggblist->tnode = NULL;
+}
+
+static void
+node_remove(GaimBuddyList *list, GaimBlistNode *node)
+{
+	FinchBlist *ggblist = list->ui_data;
+
+	if (ggblist == NULL || node->ui_data == NULL)
+		return;
+
+	gnt_tree_remove(GNT_TREE(ggblist->tree), node);
+	node->ui_data = NULL;
+	if (ggblist->tagged)
+		ggblist->tagged = g_list_remove(ggblist->tagged, node);
+
+	if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
+		GaimContact *contact = (GaimContact*)node->parent;
+		if ((!gaim_prefs_get_bool(PREF_ROOT "/showoffline") && !is_contact_online(contact)) ||
+				contact->currentsize < 1)
+			node_remove(list, (GaimBlistNode*)contact);
+	} else if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
+		GaimGroup *group = (GaimGroup*)node->parent;
+		if ((!gaim_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group)) ||
+				group->currentsize < 1)
+			node_remove(list, node->parent);
+		for (node = node->child; node; node = node->next)
+			node->ui_data = NULL;
+	}
+
+	draw_tooltip(ggblist);
+}
+
+static void
+node_update(GaimBuddyList *list, GaimBlistNode *node)
+{
+	/* It really looks like this should never happen ... but it does.
+           This will at least emit a warning to the log when it
+           happens, so maybe someone will figure it out. */
+	g_return_if_fail(node != NULL);
+
+	if (list->ui_data == NULL)
+		return;   /* XXX: this is probably the place to auto-join chats */
+
+	if (node->ui_data != NULL) {
+		gnt_tree_change_text(GNT_TREE(ggblist->tree), node,
+				0, get_display_name(node));
+		gnt_tree_sort_row(GNT_TREE(ggblist->tree), node);
+	}
+
+	if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
+		GaimBuddy *buddy = (GaimBuddy*)node;
+		if (gaim_account_is_connected(buddy->account) &&
+				(GAIM_BUDDY_IS_ONLINE(buddy) || gaim_prefs_get_bool(PREF_ROOT "/showoffline")))
+			add_node((GaimBlistNode*)buddy, list->ui_data);
+		else
+			node_remove(gaim_get_blist(), node);
+
+		node_update(list, node->parent);
+	} else if (GAIM_BLIST_NODE_IS_CHAT(node)) {
+		add_chat((GaimChat *)node, list->ui_data);
+	} else if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
+		GaimContact *contact = (GaimContact*)node;
+		if ((!gaim_prefs_get_bool(PREF_ROOT "/showoffline") && !is_contact_online(contact)) ||
+				contact->currentsize < 1)
+			node_remove(gaim_get_blist(), node);
+		else
+			add_node(node, list->ui_data);
+	} else if (GAIM_BLIST_NODE_IS_GROUP(node)) {
+		GaimGroup *group = (GaimGroup*)node;
+		if ((!gaim_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group)) ||
+				group->currentsize < 1)
+			node_remove(list, node);
+	}
+}
+
+static void
+new_list(GaimBuddyList *list)
+{
+	if (ggblist)
+		return;
+
+	ggblist = g_new0(FinchBlist, 1);
+	list->ui_data = ggblist;
+}
+
+static void
+add_buddy_cb(void *data, GaimRequestFields *allfields)
+{
+	const char *username = gaim_request_fields_get_string(allfields, "screenname");
+	const char *alias = gaim_request_fields_get_string(allfields, "alias");
+	const char *group = gaim_request_fields_get_string(allfields, "group");
+	GaimAccount *account = gaim_request_fields_get_account(allfields, "account");
+	const char *error = NULL;
+	GaimGroup *grp;
+	GaimBuddy *buddy;
+
+	if (!username)
+		error = _("You must provide a screename for the buddy.");
+	else if (!group)
+		error = _("You must provide a group.");
+	else if (!account)
+		error = _("You must select an account.");
+
+	if (error)
+	{
+		gaim_notify_error(NULL, _("Error"), _("Error adding buddy"), error);
+		return;
+	}
+
+	grp = gaim_find_group(group);
+	if (!grp)
+	{
+		grp = gaim_group_new(group);
+		gaim_blist_add_group(grp, NULL);
+	}
+
+	buddy = gaim_buddy_new(account, username, alias);
+	gaim_blist_add_buddy(buddy, NULL, grp, NULL);
+	gaim_account_add_buddy(account, buddy);
+}
+
+static void
+finch_request_add_buddy(GaimAccount *account, const char *username, const char *grp, const char *alias)
+{
+	GaimRequestFields *fields = gaim_request_fields_new();
+	GaimRequestFieldGroup *group = gaim_request_field_group_new(NULL);
+	GaimRequestField *field;
+
+	gaim_request_fields_add_group(fields, group);
+
+	field = gaim_request_field_string_new("screenname", _("Screen Name"), username, FALSE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("alias", _("Alias"), alias, FALSE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("group", _("Group"), grp, FALSE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_account_new("account", _("Account"), NULL);
+	gaim_request_field_account_set_show_all(field, FALSE);
+	if (account)
+		gaim_request_field_account_set_value(field, account);
+	gaim_request_field_group_add_field(group, field);
+
+	gaim_request_fields(NULL, _("Add Buddy"), NULL, _("Please enter buddy information."),
+			fields, _("Add"), G_CALLBACK(add_buddy_cb), _("Cancel"), NULL, NULL);
+}
+
+static void
+add_chat_cb(void *data, GaimRequestFields *allfields)
+{
+	GaimAccount *account;
+	const char *alias, *name, *group;
+	GaimChat *chat;
+	GaimGroup *grp;
+	GHashTable *hash = NULL;
+	GaimConnection *gc;
+
+	account = gaim_request_fields_get_account(allfields, "account");
+	name = gaim_request_fields_get_string(allfields, "name");
+	alias = gaim_request_fields_get_string(allfields, "alias");
+	group = gaim_request_fields_get_string(allfields, "group");
+
+	if (!gaim_account_is_connected(account) || !name || !*name)
+		return;
+	
+	if (!group || !*group)
+		group = _("Chats");
+
+	gc = gaim_account_get_connection(account);
+
+	if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL)
+		hash = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, name);
+	
+	chat = gaim_chat_new(account, name, hash);
+
+	if (chat != NULL) {
+		if ((grp = gaim_find_group(group)) == NULL) {
+			grp = gaim_group_new(group);
+			gaim_blist_add_group(grp, NULL);
+		}
+		gaim_blist_add_chat(chat, grp, NULL);
+		gaim_blist_alias_chat(chat, alias);
+	}
+}
+
+static void
+finch_request_add_chat(GaimAccount *account, GaimGroup *grp, const char *alias, const char *name)
+{
+	GaimRequestFields *fields = gaim_request_fields_new();
+	GaimRequestFieldGroup *group = gaim_request_field_group_new(NULL);
+	GaimRequestField *field;
+
+	gaim_request_fields_add_group(fields, group);
+
+	field = gaim_request_field_account_new("account", _("Account"), NULL);
+	gaim_request_field_account_set_show_all(field, FALSE);
+	if (account)
+		gaim_request_field_account_set_value(field, account);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("name", _("Name"), name, FALSE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("alias", _("Alias"), alias, FALSE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("group", _("Group"), grp ? grp->name : NULL, FALSE);
+	gaim_request_field_group_add_field(group, field);
+
+	gaim_request_fields(NULL, _("Add Chat"), NULL,
+			_("You can edit more information from the context menu later."),
+			fields, _("Add"), G_CALLBACK(add_chat_cb), _("Cancel"), NULL, NULL);
+}
+
+static void
+add_group_cb(gpointer null, const char *group)
+{
+	GaimGroup *grp;
+
+	if (!group || !*group)
+	{
+		gaim_notify_error(NULL, _("Error"), _("Error adding group"),
+				_("You must give a name for the group to add."));
+		return;
+	}
+
+	grp = gaim_find_group(group);
+	if (!grp)
+	{
+		grp = gaim_group_new(group);
+		gaim_blist_add_group(grp, NULL);
+	}
+	else
+	{
+		gaim_notify_error(NULL, _("Error"), _("Error adding group"),
+				_("A group with the name already exists."));
+	}
+}
+
+static void
+finch_request_add_group()
+{
+	gaim_request_input(NULL, _("Add Group"), NULL, _("Enter the name of the group"),
+			NULL, FALSE, FALSE, NULL,
+			_("Add"), G_CALLBACK(add_group_cb), _("Cancel"), NULL, NULL);
+}
+
+static GaimBlistUiOps blist_ui_ops =
+{
+	new_list,
+	new_node,
+	blist_show,
+	node_update,
+	node_remove,
+	NULL,
+	NULL,
+	.request_add_buddy = finch_request_add_buddy,
+	.request_add_chat = finch_request_add_chat,
+	.request_add_group = finch_request_add_group
+};
+
+static gpointer
+finch_blist_get_handle()
+{
+	static int handle;
+
+	return &handle;
+}
+
+static void
+add_group(GaimGroup *group, FinchBlist *ggblist)
+{
+	GaimBlistNode *node = (GaimBlistNode *)group;
+	if (node->ui_data)
+		return;
+	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group,
+			gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)), NULL, NULL);
+}
+
+static const char *
+get_display_name(GaimBlistNode *node)
+{
+	static char text[2096];
+	char status[8] = " ";
+	const char *name = NULL;
+
+	if (GAIM_BLIST_NODE_IS_CONTACT(node))
+		node = (GaimBlistNode*)gaim_contact_get_priority_buddy((GaimContact*)node);  /* XXX: this can return NULL?! */
+	
+	if (node == NULL)
+		return NULL;
+
+	if (GAIM_BLIST_NODE_IS_BUDDY(node))
+	{
+		GaimBuddy *buddy = (GaimBuddy *)node;
+		GaimStatusPrimitive prim;
+		GaimPresence *presence;
+		GaimStatus *now;
+		gboolean ascii = gnt_ascii_only();
+		
+		presence = gaim_buddy_get_presence(buddy);
+		now = gaim_presence_get_active_status(presence);
+
+		prim = gaim_status_type_get_primitive(gaim_status_get_type(now));
+
+		switch(prim)
+		{
+			case GAIM_STATUS_OFFLINE:
+				strncpy(status, ascii ? "x" : "⊗", sizeof(status) - 1);
+				break;
+			case GAIM_STATUS_AVAILABLE:
+				strncpy(status, ascii ? "o" : "◯", sizeof(status) - 1);
+				break;
+			default:
+				strncpy(status, ascii ? "." : "⊖", sizeof(status) - 1);
+				break;
+		}
+		name = gaim_buddy_get_alias(buddy);
+	}
+	else if (GAIM_BLIST_NODE_IS_CHAT(node))
+	{
+		GaimChat *chat = (GaimChat*)node;
+		name = gaim_chat_get_name(chat);
+
+		strncpy(status, "~", sizeof(status) - 1);
+	}
+	else if (GAIM_BLIST_NODE_IS_GROUP(node))
+		return ((GaimGroup*)node)->name;
+
+	snprintf(text, sizeof(text) - 1, "%s %s", status, name);
+
+	return text;
+}
+
+static void
+add_chat(GaimChat *chat, FinchBlist *ggblist)
+{
+	GaimGroup *group;
+	GaimBlistNode *node = (GaimBlistNode *)chat;
+	if (node->ui_data)
+		return;
+	if (!gaim_account_is_connected(chat->account))
+		return;
+
+	group = gaim_chat_get_group(chat);
+	add_node((GaimBlistNode*)group, ggblist);
+
+	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), chat,
+				gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)),
+				group, NULL);
+}
+
+static void
+add_contact(GaimContact *contact, FinchBlist *ggblist)
+{
+	GaimGroup *group;
+	GaimBlistNode *node = (GaimBlistNode*)contact;
+	const char *name;
+
+	if (node->ui_data)
+		return;
+	
+	name = get_display_name(node);
+	if (name == NULL)
+		return;
+	
+	group = (GaimGroup*)node->parent;
+	add_node((GaimBlistNode*)group, ggblist);
+
+	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), contact,
+				gnt_tree_create_row(GNT_TREE(ggblist->tree), name),
+				group, NULL);
+
+	gnt_tree_set_expanded(GNT_TREE(ggblist->tree), contact, FALSE);
+}
+
+static void
+add_buddy(GaimBuddy *buddy, FinchBlist *ggblist)
+{
+	GaimContact *contact;
+	GaimBlistNode *node = (GaimBlistNode *)buddy;
+	if (node->ui_data)
+		return;
+
+	contact = (GaimContact*)node->parent;
+	if (!contact)   /* When a new buddy is added and show-offline is set */
+		return;
+	add_node((GaimBlistNode*)contact, ggblist);
+
+	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy,
+				gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)),
+				contact, NULL);
+	if (gaim_presence_is_idle(gaim_buddy_get_presence(buddy))) {
+		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, GNT_TEXT_FLAG_DIM);
+		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, GNT_TEXT_FLAG_DIM);
+	} else {
+		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, 0);
+		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, 0);
+	}
+}
+
+#if 0
+static void
+buddy_signed_on(GaimBuddy *buddy, FinchBlist *ggblist)
+{
+	add_node((GaimBlistNode*)buddy, ggblist);
+}
+
+static void
+buddy_signed_off(GaimBuddy *buddy, FinchBlist *ggblist)
+{
+	node_remove(gaim_get_blist(), (GaimBlistNode*)buddy);
+}
+#endif
+
+GaimBlistUiOps *finch_blist_get_ui_ops()
+{
+	return &blist_ui_ops;
+}
+
+static void
+selection_activate(GntWidget *widget, FinchBlist *ggblist)
+{
+	GntTree *tree = GNT_TREE(ggblist->tree);
+	GaimBlistNode *node = gnt_tree_get_selection_data(tree);
+
+	if (!node)
+		return;
+	
+	if (GAIM_BLIST_NODE_IS_CONTACT(node))
+		node = (GaimBlistNode*)gaim_contact_get_priority_buddy((GaimContact*)node);
+
+	if (GAIM_BLIST_NODE_IS_BUDDY(node))
+	{
+		GaimBuddy *buddy = (GaimBuddy *)node;
+		GaimConversation *conv =  gaim_conversation_new(GAIM_CONV_TYPE_IM,
+					gaim_buddy_get_account(buddy),
+					gaim_buddy_get_name(buddy));
+		finch_conversation_set_active(conv);
+	}
+	else if (GAIM_BLIST_NODE_IS_CHAT(node))
+	{
+		GaimChat *chat = (GaimChat*)node;
+		serv_join_chat(chat->account->gc, chat->components);
+	}
+}
+
+static void
+context_menu_callback(GntMenuItem *item, gpointer data)
+{
+	GaimMenuAction *action = data;
+	GaimBlistNode *node = ggblist->cnode;
+	if (action) {
+		void (*callback)(GaimBlistNode *, gpointer);
+		callback = (void (*)(GaimBlistNode *, gpointer))action->callback;
+		if (callback)
+			callback(action->data, node);
+		else
+			return;
+	}
+}
+
+static void
+gnt_append_menu_action(GntMenu *menu, GaimMenuAction *action, gpointer parent)
+{
+	GList *list;
+	GntMenuItem *item;
+
+	if (action == NULL)
+		return;
+
+	item = gnt_menuitem_new(action->label);
+	if (action->callback)
+		gnt_menuitem_set_callback(GNT_MENUITEM(item), context_menu_callback, action);
+	gnt_menu_add_item(menu, GNT_MENUITEM(item));
+
+	if (action->children) {
+		GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
+		gnt_menuitem_set_submenu(item, GNT_MENU(sub));
+		for (list = action->children; list; list = list->next)
+			gnt_append_menu_action(GNT_MENU(sub), list->data, action);
+	}
+}
+
+static void
+append_proto_menu(GntMenu *menu, GaimConnection *gc, GaimBlistNode *node)
+{
+	GList *list;
+	GaimPluginProtocolInfo *prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
+
+	if(!prpl_info || !prpl_info->blist_node_menu)
+		return;
+
+	for(list = prpl_info->blist_node_menu(node); list;
+			list = g_list_delete_link(list, list))
+	{
+		GaimMenuAction *act = (GaimMenuAction *) list->data;
+		act->data = node;
+		gnt_append_menu_action(menu, act, NULL);
+	}
+}
+
+static void
+add_custom_action(GntMenu *menu, const char *label, GaimCallback callback,
+		gpointer data)
+{
+	GaimMenuAction *action = gaim_menu_action_new(label, callback, data, NULL);
+	gnt_append_menu_action(menu, action, NULL);
+	g_signal_connect_swapped(G_OBJECT(menu), "destroy",
+			G_CALLBACK(gaim_menu_action_free), action);
+}
+
+static void
+chat_components_edit_ok(GaimChat *chat, GaimRequestFields *allfields)
+{
+	GList *groups, *fields;
+
+	for (groups = gaim_request_fields_get_groups(allfields); groups; groups = groups->next) {
+		fields = gaim_request_field_group_get_fields(groups->data);
+		for (; fields; fields = fields->next) {
+			GaimRequestField *field = fields->data;
+			const char *id;
+			char *val;
+
+			id = gaim_request_field_get_id(field);
+			if (gaim_request_field_get_type(field) == GAIM_REQUEST_FIELD_INTEGER)
+				val = g_strdup_printf("%d", gaim_request_field_int_get_value(field));
+			else
+				val = g_strdup(gaim_request_field_string_get_value(field));
+
+			g_hash_table_replace(chat->components, g_strdup(id), val);  /* val should not be free'd */
+		}
+	}
+}
+
+static void
+chat_components_edit(GaimChat *chat, GaimBlistNode *selected)
+{
+	GaimRequestFields *fields = gaim_request_fields_new();
+	GaimRequestFieldGroup *group = gaim_request_field_group_new(NULL);
+	GaimRequestField *field;
+	GList *parts, *iter;
+	struct proto_chat_entry *pce;
+
+	gaim_request_fields_add_group(fields, group);
+
+	parts = GAIM_PLUGIN_PROTOCOL_INFO(chat->account->gc->prpl)->chat_info(chat->account->gc);
+
+	for (iter = parts; iter; iter = iter->next) {
+		pce = iter->data;
+		if (pce->is_int) {
+			int val;
+			const char *str = g_hash_table_lookup(chat->components, pce->identifier);
+			if (!str || sscanf(str, "%d", &val) != 1)
+				val = pce->min;
+			field = gaim_request_field_int_new(pce->identifier, pce->label, val);
+		} else {
+			field = gaim_request_field_string_new(pce->identifier, pce->label,
+					g_hash_table_lookup(chat->components, pce->identifier), FALSE);
+		}
+
+		gaim_request_field_group_add_field(group, field);
+		g_free(pce);
+	}
+
+	g_list_free(parts);
+
+	gaim_request_fields(NULL, _("Edit Chat"), NULL, _("Please Update the necessary fields."),
+			fields, _("Edit"), G_CALLBACK(chat_components_edit_ok), _("Cancel"), NULL, chat);
+}
+
+static void
+autojoin_toggled(GntMenuItem *item, gpointer data)
+{
+	GaimMenuAction *action = data;
+	gaim_blist_node_set_bool(action->data, "gnt-autojoin",
+				gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item)));
+}
+
+static void
+create_chat_menu(GntMenu *menu, GaimChat *chat)
+{
+	GaimMenuAction *action = gaim_menu_action_new(_("Auto-join"), NULL, chat, NULL);
+	GntMenuItem *check = gnt_menuitem_check_new(action->label);
+	gnt_menuitem_check_set_checked(GNT_MENUITEM_CHECK(check),
+				gaim_blist_node_get_bool((GaimBlistNode*)chat, "gnt-autojoin"));
+	gnt_menu_add_item(menu, check);
+	gnt_menuitem_set_callback(check, autojoin_toggled, action);
+	g_signal_connect_swapped(G_OBJECT(menu), "destroy",
+			G_CALLBACK(gaim_menu_action_free), action);
+
+	add_custom_action(menu, _("Edit Settings"), (GaimCallback)chat_components_edit, chat);
+}
+
+static void
+finch_add_buddy(GaimGroup *grp, GaimBlistNode *selected)
+{
+	gaim_blist_request_add_buddy(NULL, NULL, grp ? grp->name : NULL, NULL);
+}
+
+static void
+finch_add_group(GaimGroup *grp, GaimBlistNode *selected)
+{
+	gaim_blist_request_add_group();
+}
+
+static void
+finch_add_chat(GaimGroup *grp, GaimBlistNode *selected)
+{
+	gaim_blist_request_add_chat(NULL, grp, NULL, NULL);
+}
+
+static void
+create_group_menu(GntMenu *menu, GaimGroup *group)
+{
+	add_custom_action(menu, _("Add Buddy"),
+			GAIM_CALLBACK(finch_add_buddy), group);
+	add_custom_action(menu, _("Add Chat"),
+			GAIM_CALLBACK(finch_add_chat), group);
+	add_custom_action(menu, _("Add Group"),
+			GAIM_CALLBACK(finch_add_group), group);
+}
+
+static void
+finch_blist_get_buddy_info_cb(GaimBuddy *buddy, GaimBlistNode *selected)
+{
+	serv_get_info(buddy->account->gc, gaim_buddy_get_name(buddy));
+}
+
+static void
+finch_blist_menu_send_file_cb(GaimBuddy *buddy, GaimBlistNode *selected)
+{
+	serv_send_file(buddy->account->gc, buddy->name, NULL);
+}
+
+static void
+finch_blist_pounce_node_cb(GaimBlistNode *node, GaimBlistNode *selected)
+{
+	GaimBuddy *b;
+	if (GAIM_BLIST_NODE_IS_CONTACT(node))
+		b = gaim_contact_get_priority_buddy((GaimContact *)node);
+	else
+		b = (GaimBuddy *)node;
+	finch_pounce_editor_show(b->account, b->name, NULL);
+}
+
+
+static void
+create_buddy_menu(GntMenu *menu, GaimBuddy *buddy)
+{
+	GaimPluginProtocolInfo *prpl_info;
+
+	prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(buddy->account->gc->prpl);
+	if (prpl_info && prpl_info->get_info)
+	{
+		add_custom_action(menu, _("Get Info"),
+				GAIM_CALLBACK(finch_blist_get_buddy_info_cb), buddy);
+	}
+
+	add_custom_action(menu, _("Add Buddy Pounce"),
+			GAIM_CALLBACK(finch_blist_pounce_node_cb), buddy);
+
+	if (prpl_info && prpl_info->send_file)
+	{
+		if (!prpl_info->can_receive_file ||
+			prpl_info->can_receive_file(buddy->account->gc, buddy->name))
+			add_custom_action(menu, _("Send File"),
+					GAIM_CALLBACK(finch_blist_menu_send_file_cb), buddy);
+	}
+#if 0
+	add_custom_action(tree, _("View Log"),
+			GAIM_CALLBACK(finch_blist_view_log_cb)), buddy);
+#endif
+
+	/* Protocol actions */
+	append_proto_menu(menu,
+			gaim_account_get_connection(gaim_buddy_get_account(buddy)),
+			(GaimBlistNode*)buddy);
+}
+
+static void
+append_extended_menu(GntMenu *menu, GaimBlistNode *node)
+{
+	GList *iter;
+
+	for (iter = gaim_blist_node_get_extended_menu(node);
+			iter; iter = g_list_delete_link(iter, iter))
+	{
+		gnt_append_menu_action(menu, iter->data, NULL);
+	}
+}
+
+/* Xerox'd from gtkdialogs.c:gaim_gtkdialogs_remove_contact_cb */
+static void
+remove_contact(GaimContact *contact)
+{
+	GaimBlistNode *bnode, *cnode;
+	GaimGroup *group;
+
+	cnode = (GaimBlistNode *)contact;
+	group = (GaimGroup*)cnode->parent;
+	for (bnode = cnode->child; bnode; bnode = bnode->next) {
+		GaimBuddy *buddy = (GaimBuddy*)bnode;
+		if (gaim_account_is_connected(buddy->account))
+			gaim_account_remove_buddy(buddy->account, buddy, group);
+	}
+	gaim_blist_remove_contact(contact);
+}
+
+static void
+rename_blist_node(GaimBlistNode *node, const char *newname)
+{
+	const char *name = newname;
+	if (name && !*name)
+		name = NULL;
+
+	if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
+		GaimContact *contact = (GaimContact*)node;
+		GaimBuddy *buddy = gaim_contact_get_priority_buddy(contact);
+		gaim_blist_alias_contact(contact, name);
+		gaim_blist_alias_buddy(buddy, name);
+		serv_alias_buddy(buddy);
+	} else if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
+		gaim_blist_alias_buddy((GaimBuddy*)node, name);
+		serv_alias_buddy((GaimBuddy*)node);
+	} else if (GAIM_BLIST_NODE_IS_CHAT(node))
+		gaim_blist_alias_chat((GaimChat*)node, name);
+	else if (GAIM_BLIST_NODE_IS_GROUP(node) && (name != NULL))
+		gaim_blist_rename_group((GaimGroup*)node, name);
+	else
+		g_return_if_reached();
+}
+
+static void
+finch_blist_rename_node_cb(GaimBlistNode *node, GaimBlistNode *selected)
+{
+	const char *name = NULL;
+	char *prompt;
+
+	if (GAIM_BLIST_NODE_IS_CONTACT(node))
+		name = gaim_contact_get_alias((GaimContact*)node);
+	else if (GAIM_BLIST_NODE_IS_BUDDY(node))
+		name = gaim_buddy_get_contact_alias((GaimBuddy*)node);
+	else if (GAIM_BLIST_NODE_IS_CHAT(node))
+		name = gaim_chat_get_name((GaimChat*)node);
+	else if (GAIM_BLIST_NODE_IS_GROUP(node))
+		name = ((GaimGroup*)node)->name;
+	else
+		g_return_if_reached();
+
+	prompt = g_strdup_printf(_("Please enter the new name for %s"), name);
+
+	gaim_request_input(node, _("Rename"), prompt, _("Enter empty string to reset the name."),
+			name, FALSE, FALSE, NULL, _("Rename"), G_CALLBACK(rename_blist_node),
+			_("Cancel"), NULL, node);
+
+	g_free(prompt);
+}
+
+/* Xeroxed from gtkdialogs.c:gaim_gtkdialogs_remove_group_cb*/
+static void
+remove_group(GaimGroup *group)
+{
+	GaimBlistNode *cnode, *bnode;
+
+	cnode = ((GaimBlistNode*)group)->child;
+
+	while (cnode) {
+		if (GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
+			bnode = cnode->child;
+			cnode = cnode->next;
+			while (bnode) {
+				GaimBuddy *buddy;
+				if (GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
+					buddy = (GaimBuddy*)bnode;
+					bnode = bnode->next;
+					if (gaim_account_is_connected(buddy->account)) {
+						gaim_account_remove_buddy(buddy->account, buddy, group);
+						gaim_blist_remove_buddy(buddy);
+					}
+				} else {
+					bnode = bnode->next;
+				}
+			}
+		} else if (GAIM_BLIST_NODE_IS_CHAT(cnode)) {
+			GaimChat *chat = (GaimChat *)cnode;
+			cnode = cnode->next;
+			if (gaim_account_is_connected(chat->account))
+				gaim_blist_remove_chat(chat);
+		} else {
+			cnode = cnode->next;
+		}
+	}
+
+	gaim_blist_remove_group(group);
+}
+
+static void
+finch_blist_remove_node(GaimBlistNode *node)
+{
+	if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
+		remove_contact((GaimContact*)node);
+	} else if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
+		GaimBuddy *buddy = (GaimBuddy*)node;
+		GaimGroup *group = gaim_buddy_get_group(buddy);
+		gaim_account_remove_buddy(gaim_buddy_get_account(buddy), buddy, group);
+		gaim_blist_remove_buddy(buddy);
+	} else if (GAIM_BLIST_NODE_IS_CHAT(node)) {
+		gaim_blist_remove_chat((GaimChat*)node);
+	} else if (GAIM_BLIST_NODE_IS_GROUP(node)) {
+		remove_group((GaimGroup*)node);
+	}
+}
+
+static void
+finch_blist_remove_node_cb(GaimBlistNode *node, GaimBlistNode *selected)
+{
+	char *primary;
+	const char *name, *sec = NULL;
+
+	/* XXX: could be a contact */
+	if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
+		GaimContact *c = (GaimContact*)node;
+		name = gaim_contact_get_alias(c);
+		if (c->totalsize > 1)
+			sec = _("Removing this contact will also remove all the buddies in the contact");
+	} else if (GAIM_BLIST_NODE_IS_BUDDY(node))
+		name = gaim_buddy_get_name((GaimBuddy*)node);
+	else if (GAIM_BLIST_NODE_IS_CHAT(node))
+		name = gaim_chat_get_name((GaimChat*)node);
+	else if (GAIM_BLIST_NODE_IS_GROUP(node))
+	{
+		name = ((GaimGroup*)node)->name;
+		sec = _("Removing this group will also remove all the buddies in the group");
+	}
+	else
+		return;
+
+	primary = g_strdup_printf(_("Are you sure you want to remove %s?"), name);
+
+	/* XXX: anything to do with the returned ui-handle? */
+	gaim_request_action(node, _("Confirm Remove"),
+			primary, sec,
+			1, node, 2,
+			_("Remove"), finch_blist_remove_node,
+			_("Cancel"), NULL);
+	g_free(primary);
+}
+
+static void
+finch_blist_toggle_tag_buddy(GaimBlistNode *node)
+{
+	GList *iter;
+	if (node == NULL)
+		return;
+	if (GAIM_BLIST_NODE_IS_CHAT(node) || GAIM_BLIST_NODE_IS_GROUP(node))
+		return;
+	if (ggblist->tagged && (iter = g_list_find(ggblist->tagged, node)) != NULL) {
+		ggblist->tagged = g_list_delete_link(ggblist->tagged, iter);
+	} else {
+		ggblist->tagged = g_list_prepend(ggblist->tagged, node);
+	}
+	if (GAIM_BLIST_NODE_IS_CONTACT(node))
+		node = (GaimBlistNode*)gaim_contact_get_priority_buddy((GaimContact*)node);
+	update_buddy_display((GaimBuddy*)node, ggblist);
+}
+
+static void
+finch_blist_place_tagged(GaimBlistNode *target)
+{
+	GaimGroup *tg = NULL;
+	GaimContact *tc = NULL;
+
+	if (target == NULL)
+		return;
+
+	/* This target resolution probably needs more clarification; for
+	 * example, if I tag a buddy in a contact, then place on
+	 * another buddy in the same contact, I probably intend to
+	 * place the tagged buddy immediately after (before?) the
+	 * target buddy -- this will simply move the tagged buddy
+	 * within the same contact without reference to position. */
+	if (GAIM_BLIST_NODE_IS_GROUP(target))
+		tg = (GaimGroup*)target;
+	else if (GAIM_BLIST_NODE_IS_CONTACT(target))
+		tc = (GaimContact*)target;
+	else /* Buddy or Chat */
+		tc = (GaimContact*)target->parent;
+
+	if (ggblist->tagged) {
+		GList *list = ggblist->tagged;
+		ggblist->tagged = NULL;
+
+		while (list) {
+			GaimBlistNode *node = list->data;
+			list = g_list_delete_link(list, list);
+			if (tg) {
+				if (GAIM_BLIST_NODE_IS_CONTACT(node))
+					gaim_blist_add_contact((GaimContact*)node, tg, NULL);
+				else
+					gaim_blist_add_buddy((GaimBuddy*)node, NULL, tg, NULL);
+			} else {
+				if (GAIM_BLIST_NODE_IS_BUDDY(node))
+					gaim_blist_add_buddy((GaimBuddy*)node, tc,
+						gaim_buddy_get_group(gaim_contact_get_priority_buddy(tc)), NULL);
+				else if (GAIM_BLIST_NODE_IS_CONTACT(node))
+					gaim_blist_merge_contact((GaimContact*)node, target);
+			}
+		}
+	}
+}
+
+static void
+context_menu_destroyed(GntWidget *widget, FinchBlist *ggblist)
+{
+	ggblist->context = NULL;
+}
+
+static void
+draw_context_menu(FinchBlist *ggblist)
+{
+	GaimBlistNode *node = NULL;
+	GntWidget *context = NULL;
+	GntTree *tree = NULL;
+	int x, y, top, width;
+	char *title = NULL;
+
+	tree = GNT_TREE(ggblist->tree);
+
+	node = gnt_tree_get_selection_data(tree);
+
+	if (ggblist->tooltip)
+		remove_tooltip(ggblist);
+
+	ggblist->cnode = node;
+
+	ggblist->context = context = gnt_menu_new(GNT_MENU_POPUP);
+	g_signal_connect(G_OBJECT(context), "destroy", G_CALLBACK(context_menu_destroyed), ggblist);
+
+	if (!node) {
+		create_group_menu(GNT_MENU(context), NULL);
+		title = g_strdup(_("Buddy List"));
+	} else if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
+		create_buddy_menu(GNT_MENU(context),
+			gaim_contact_get_priority_buddy((GaimContact*)node));
+		title = g_strdup(gaim_contact_get_alias((GaimContact*)node));
+	} else if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
+		GaimBuddy *buddy = (GaimBuddy *)node;
+		create_buddy_menu(GNT_MENU(context), buddy);
+		title = g_strdup(gaim_buddy_get_name(buddy));
+	} else if (GAIM_BLIST_NODE_IS_CHAT(node)) {
+		GaimChat *chat = (GaimChat*)node;
+		create_chat_menu(GNT_MENU(context), chat);
+		title = g_strdup(gaim_chat_get_name(chat));
+	} else if (GAIM_BLIST_NODE_IS_GROUP(node)) {
+		GaimGroup *group = (GaimGroup *)node;
+		create_group_menu(GNT_MENU(context), group);
+		title = g_strdup(group->name);
+	}
+
+	append_extended_menu(GNT_MENU(context), node);
+
+	/* These are common for everything */
+	if (node) {
+		add_custom_action(GNT_MENU(context), _("Rename"),
+				GAIM_CALLBACK(finch_blist_rename_node_cb), node);
+		add_custom_action(GNT_MENU(context), _("Remove"),
+				GAIM_CALLBACK(finch_blist_remove_node_cb), node);
+
+		if (ggblist->tagged && (GAIM_BLIST_NODE_IS_CONTACT(node)
+				|| GAIM_BLIST_NODE_IS_GROUP(node))) {
+			add_custom_action(GNT_MENU(context), _("Place tagged"),
+					GAIM_CALLBACK(finch_blist_place_tagged), node);
+		}
+
+		if (GAIM_BLIST_NODE_IS_BUDDY(node) || GAIM_BLIST_NODE_IS_CONTACT(node)) {
+			add_custom_action(GNT_MENU(context), _("Toggle Tag"),
+					GAIM_CALLBACK(finch_blist_toggle_tag_buddy), node);
+		}
+	}
+
+	/* Set the position for the popup */
+	gnt_widget_get_position(GNT_WIDGET(tree), &x, &y);
+	gnt_widget_get_size(GNT_WIDGET(tree), &width, NULL);
+	top = gnt_tree_get_selection_visible_line(tree);
+
+	x += width;
+	y += top - 1;
+
+	gnt_widget_set_position(context, x, y);
+	gnt_screen_menu_show(GNT_MENU(context));
+	g_free(title);
+}
+
+static void
+tooltip_for_buddy(GaimBuddy *buddy, GString *str)
+{
+	GaimPlugin *prpl;
+	GaimPluginProtocolInfo *prpl_info;
+	GaimAccount *account;
+	GaimNotifyUserInfo *user_info;
+	const char *alias = gaim_buddy_get_alias(buddy);
+	char *tmp, *strip;
+
+	user_info = gaim_notify_user_info_new();
+
+	account = gaim_buddy_get_account(buddy);
+
+	if (g_utf8_collate(gaim_buddy_get_name(buddy), alias))
+		gaim_notify_user_info_add_pair(user_info, _("Nickname"), alias);
+
+	tmp = g_strdup_printf("%s (%s)",
+			gaim_account_get_username(account),
+			gaim_account_get_protocol_name(account));
+	gaim_notify_user_info_add_pair(user_info, _("Account"), tmp);
+	g_free(tmp);
+	
+	prpl = gaim_find_prpl(gaim_account_get_protocol_id(account));
+	prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
+	if (prpl_info && prpl_info->tooltip_text) {
+		prpl_info->tooltip_text(buddy, user_info, TRUE);
+	}
+
+	if (gaim_prefs_get_bool("/gaim/gnt/blist/idletime")) {
+		GaimPresence *pre = gaim_buddy_get_presence(buddy);
+		if (gaim_presence_is_idle(pre)) {
+			time_t idle = gaim_presence_get_idle_time(pre);
+			if (idle > 0) {
+				char *st = gaim_str_seconds_to_string(time(NULL) - idle);
+				gaim_notify_user_info_add_pair(user_info, _("Idle"), st);
+				g_free(st);
+			}
+		}
+	}
+	
+	tmp = gaim_notify_user_info_get_text_with_newline(user_info, "<BR>");
+	gaim_notify_user_info_destroy(user_info);
+
+	strip = gaim_markup_strip_html(tmp);
+	g_string_append(str, strip);
+	g_free(strip);
+	g_free(tmp);
+}
+
+static GString*
+make_sure_text_fits(GString *string)
+{
+	int maxw = getmaxx(stdscr) - 3;
+	char *str = gnt_util_onscreen_fit_string(string->str, maxw);
+	string = g_string_assign(string, str);
+	g_free(str);
+	return string;
+}
+
+static gboolean
+draw_tooltip_real(FinchBlist *ggblist)
+{
+	GaimBlistNode *node;
+	int x, y, top, width, w, h;
+	GString *str;
+	GntTree *tree;
+	GntWidget *widget, *box, *tv;
+	char *title = NULL;
+	int lastseen = 0;
+
+	widget = ggblist->tree;
+	tree = GNT_TREE(widget);
+
+	if (!gnt_widget_has_focus(ggblist->tree) || 
+			(ggblist->context && !GNT_WIDGET_IS_FLAG_SET(ggblist->context, GNT_WIDGET_INVISIBLE)))
+		return FALSE;
+
+	if (ggblist->tooltip)
+	{
+		/* XXX: Once we can properly redraw on expose events, this can be removed at the end
+		 * to avoid the blinking*/
+		remove_tooltip(ggblist);
+	}
+
+	node = gnt_tree_get_selection_data(tree);
+	if (!node)
+		return FALSE;
+
+	str = g_string_new("");
+
+	if (GAIM_BLIST_NODE_IS_CONTACT(node)) {
+		GaimBuddy *pr = gaim_contact_get_priority_buddy((GaimContact*)node);
+		gboolean offline = !GAIM_BUDDY_IS_ONLINE(pr);
+		gboolean showoffline = gaim_prefs_get_bool(PREF_ROOT "/showoffline");
+		const char *name = gaim_buddy_get_name(pr);
+
+		title = g_strdup(name);
+		tooltip_for_buddy(pr, str);
+		for (node = node->child; node; node = node->next) {
+			GaimBuddy *buddy = (GaimBuddy*)node;
+			if (offline) {
+				int value = gaim_blist_node_get_int(node, "last_seen");
+				if (value > lastseen)
+					lastseen = value;
+			}
+			if (node == (GaimBlistNode*)pr)
+				continue;
+			if (!gaim_account_is_connected(buddy->account))
+				continue;
+			if (!showoffline && !GAIM_BUDDY_IS_ONLINE(buddy))
+				continue;
+			str = g_string_append(str, "\n----------\n");
+			tooltip_for_buddy(buddy, str);
+		}
+	} else if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
+		GaimBuddy *buddy = (GaimBuddy *)node;
+		tooltip_for_buddy(buddy, str);
+		title = g_strdup(gaim_buddy_get_name(buddy));
+		if (!GAIM_BUDDY_IS_ONLINE((GaimBuddy*)node))
+			lastseen = gaim_blist_node_get_int(node, "last_seen");
+	} else if (GAIM_BLIST_NODE_IS_GROUP(node)) {
+		GaimGroup *group = (GaimGroup *)node;
+
+		g_string_append_printf(str, _("Online: %d\nTotal: %d"),
+						gaim_blist_get_group_online_count(group),
+						gaim_blist_get_group_size(group, FALSE));
+
+		title = g_strdup(group->name);
+	} else if (GAIM_BLIST_NODE_IS_CHAT(node)) {
+		GaimChat *chat = (GaimChat *)node;
+		GaimAccount *account = chat->account;
+
+		g_string_append_printf(str, _("Account: %s (%s)"),
+				gaim_account_get_username(account),
+				gaim_account_get_protocol_name(account));
+
+		title = g_strdup(gaim_chat_get_name(chat));
+	} else {
+		g_string_free(str, TRUE);
+		return FALSE;
+	}
+
+	if (lastseen > 0) {
+		char *tmp = gaim_str_seconds_to_string(time(NULL) - lastseen);
+		g_string_append_printf(str, _("\nLast Seen: %s ago"), tmp);
+		g_free(tmp);
+	}
+
+	gnt_widget_get_position(widget, &x, &y);
+	gnt_widget_get_size(widget, &width, NULL);
+	top = gnt_tree_get_selection_visible_line(tree);
+
+	x += width;
+	y += top - 1;
+
+	box = gnt_box_new(FALSE, FALSE);
+	gnt_box_set_toplevel(GNT_BOX(box), TRUE);
+	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW);
+	gnt_box_set_title(GNT_BOX(box), title);
+
+	str = make_sure_text_fits(str);
+	gnt_util_get_text_bound(str->str, &w, &h);
+	h = MAX(2, h);
+	tv = gnt_text_view_new();
+	gnt_widget_set_size(tv, w + 1, h);
+	gnt_box_add_widget(GNT_BOX(box), tv);
+
+	gnt_widget_set_position(box, x, y);
+	GNT_WIDGET_UNSET_FLAGS(box, GNT_WIDGET_CAN_TAKE_FOCUS);
+	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_TRANSIENT);
+	gnt_widget_draw(box);
+
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(tv), str->str, GNT_TEXT_FLAG_NORMAL);
+	gnt_text_view_scroll(GNT_TEXT_VIEW(tv), 0);
+
+	g_free(title);
+	g_string_free(str, TRUE);
+	ggblist->tooltip = box;
+	ggblist->tnode = node;
+
+	gnt_widget_set_name(ggblist->tooltip, "tooltip");
+	return FALSE;
+}
+
+static void
+draw_tooltip(FinchBlist *ggblist)
+{
+	/* When an account has signed off, it removes one buddy at a time.
+	 * Drawing the tooltip after removing each buddy is expensive. On
+	 * top of that, if the selected buddy belongs to the disconnected
+	 * account, then retreiving the tooltip for that causes crash. So
+	 * let's make sure we wait for all the buddies to be removed first.*/
+	int id = g_timeout_add(0, (GSourceFunc)draw_tooltip_real, ggblist);
+	g_object_set_data_full(G_OBJECT(ggblist->window), "draw_tooltip_calback",
+				GINT_TO_POINTER(id), (GDestroyNotify)g_source_remove);
+}
+
+static void
+selection_changed(GntWidget *widget, gpointer old, gpointer current, FinchBlist *ggblist)
+{
+	draw_tooltip(ggblist);
+}
+
+static gboolean
+context_menu(GntWidget *widget, FinchBlist *ggblist)
+{
+	draw_context_menu(ggblist);
+	return TRUE;
+}
+
+static gboolean
+key_pressed(GntWidget *widget, const char *text, FinchBlist *ggblist)
+{
+	if (text[0] == 27 && text[1] == 0) {
+		/* Escape was pressed */
+		remove_peripherals(ggblist);
+	} else if (strcmp(text, GNT_KEY_CTRL_O) == 0) {
+		gaim_prefs_set_bool(PREF_ROOT "/showoffline",
+				!gaim_prefs_get_bool(PREF_ROOT "/showoffline"));
+	} else if (GNT_TREE(ggblist->tree)->search == NULL) {
+		if (strcmp(text, "t") == 0) {
+			finch_blist_toggle_tag_buddy(gnt_tree_get_selection_data(GNT_TREE(ggblist->tree)));
+			gnt_bindable_perform_action_named(GNT_BINDABLE(ggblist->tree), "move-down");
+		} else if (strcmp(text, "a") == 0) {
+			finch_blist_place_tagged(gnt_tree_get_selection_data(GNT_TREE(ggblist->tree)));
+		} else
+			return FALSE;
+	} else
+		return FALSE;
+
+	return TRUE;
+}
+
+static void
+update_buddy_display(GaimBuddy *buddy, FinchBlist *ggblist)
+{
+	GaimContact *contact;
+	GntTextFormatFlags bflag = 0, cflag = 0;
+	
+	contact = gaim_buddy_get_contact(buddy);
+
+	gnt_tree_change_text(GNT_TREE(ggblist->tree), buddy, 0, get_display_name((GaimBlistNode*)buddy));
+	gnt_tree_change_text(GNT_TREE(ggblist->tree), contact, 0, get_display_name((GaimBlistNode*)contact));
+
+	if (ggblist->tagged && g_list_find(ggblist->tagged, buddy))
+		bflag |= GNT_TEXT_FLAG_BOLD;
+	if (ggblist->tagged && g_list_find(ggblist->tagged, contact))
+		cflag |= GNT_TEXT_FLAG_BOLD;
+
+	if (ggblist->tnode == (GaimBlistNode*)buddy)
+		draw_tooltip(ggblist);
+
+	if (gaim_presence_is_idle(gaim_buddy_get_presence(buddy))) {
+		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, bflag | GNT_TEXT_FLAG_DIM);
+		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, cflag | GNT_TEXT_FLAG_DIM);
+	} else {
+		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, bflag);
+		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, cflag);
+	}
+}
+
+static void
+buddy_status_changed(GaimBuddy *buddy, GaimStatus *old, GaimStatus *now, FinchBlist *ggblist)
+{
+	update_buddy_display(buddy, ggblist);
+}
+
+static void
+buddy_idle_changed(GaimBuddy *buddy, int old, int new, FinchBlist *ggblist)
+{
+	update_buddy_display(buddy, ggblist);
+}
+
+static void
+remove_peripherals(FinchBlist *ggblist)
+{
+	if (ggblist->tooltip)
+		remove_tooltip(ggblist);
+	else if (ggblist->context)
+		gnt_widget_destroy(ggblist->context);
+}
+
+static void
+size_changed_cb(GntWidget *w, int wi, int h)
+{
+	int width, height;
+	gnt_widget_get_size(w, &width, &height);
+	gaim_prefs_set_int(PREF_ROOT "/size/width", width);
+	gaim_prefs_set_int(PREF_ROOT "/size/height", height);
+}
+
+static void
+save_position_cb(GntWidget *w, int x, int y)
+{
+	gaim_prefs_set_int(PREF_ROOT "/position/x", x);
+	gaim_prefs_set_int(PREF_ROOT "/position/y", y);
+}
+
+static void
+reset_blist_window(GntWidget *window, gpointer null)
+{
+	GaimBlistNode *node;
+	gaim_signals_disconnect_by_handle(finch_blist_get_handle());
+	gaim_get_blist()->ui_data = NULL;
+
+	node = gaim_blist_get_root();
+	while (node) {
+		node->ui_data = NULL;
+		node = gaim_blist_node_next(node, TRUE);
+	}
+
+	if (ggblist->typing)
+		g_source_remove(ggblist->typing);
+	remove_peripherals(ggblist);
+	if (ggblist->tagged)
+		g_list_free(ggblist->tagged);
+	g_free(ggblist);
+	ggblist = NULL;
+}
+
+static void
+populate_buddylist()
+{
+	GaimBlistNode *node;
+	GaimBuddyList *list;
+
+	if (strcmp(gaim_prefs_get_string(PREF_ROOT "/sort_type"), "text") == 0) {
+		gnt_tree_set_compare_func(GNT_TREE(ggblist->tree),
+			(GCompareFunc)blist_node_compare_text);
+	} else if (strcmp(gaim_prefs_get_string(PREF_ROOT "/sort_type"), "status") == 0) {
+		gnt_tree_set_compare_func(GNT_TREE(ggblist->tree),
+			(GCompareFunc)blist_node_compare_status);
+	} else if (strcmp(gaim_prefs_get_string(PREF_ROOT "/sort_type"), "log") == 0) {
+		gnt_tree_set_compare_func(GNT_TREE(ggblist->tree),
+			(GCompareFunc)blist_node_compare_log);
+	}
+	
+	list = gaim_get_blist();
+	node = gaim_blist_get_root();
+	while (node)
+	{
+		node_update(list, node);
+		node = gaim_blist_node_next(node, FALSE);
+	}
+}
+
+static void
+destroy_status_list(GList *list)
+{
+	g_list_foreach(list, (GFunc)g_free, NULL);
+	g_list_free(list);
+}
+
+static void
+populate_status_dropdown()
+{
+	int i;
+	GList *iter;
+	GList *items = NULL;
+	StatusBoxItem *item = NULL;
+
+	/* First the primitives */
+	GaimStatusPrimitive prims[] = {GAIM_STATUS_AVAILABLE, GAIM_STATUS_AWAY,
+			GAIM_STATUS_INVISIBLE, GAIM_STATUS_OFFLINE, GAIM_STATUS_UNSET};
+
+	gnt_combo_box_remove_all(GNT_COMBO_BOX(ggblist->status));
+
+	for (i = 0; prims[i] != GAIM_STATUS_UNSET; i++)
+	{
+		item = g_new0(StatusBoxItem, 1);
+		item->type = STATUS_PRIMITIVE;
+		item->u.prim = prims[i];
+		items = g_list_prepend(items, item);
+		gnt_combo_box_add_data(GNT_COMBO_BOX(ggblist->status), item,
+				gaim_primitive_get_name_from_type(prims[i]));
+	}
+
+	/* Now the popular statuses */
+	for (iter = gaim_savedstatuses_get_popular(6); iter; iter = iter->next)
+	{
+		item = g_new0(StatusBoxItem, 1);
+		item->type = STATUS_SAVED_POPULAR;
+		item->u.saved = iter->data;
+		items = g_list_prepend(items, item);
+		gnt_combo_box_add_data(GNT_COMBO_BOX(ggblist->status), item,
+				gaim_savedstatus_get_title(iter->data));
+	}
+
+	/* New savedstatus */
+	item = g_new0(StatusBoxItem, 1);
+	item->type = STATUS_SAVED_NEW;
+	items = g_list_prepend(items, item);
+	gnt_combo_box_add_data(GNT_COMBO_BOX(ggblist->status), item,
+			_("New..."));
+
+	/* More savedstatuses */
+	item = g_new0(StatusBoxItem, 1);
+	item->type = STATUS_SAVED_ALL;
+	items = g_list_prepend(items, item);
+	gnt_combo_box_add_data(GNT_COMBO_BOX(ggblist->status), item,
+			_("Saved..."));
+
+	/* The keys for the combobox are created here, and never used
+	 * anywhere else. So make sure the keys are freed when the widget
+	 * is destroyed. */
+	g_object_set_data_full(G_OBJECT(ggblist->status), "list of statuses",
+			items, (GDestroyNotify)destroy_status_list);
+}
+
+static void
+redraw_blist(const char *name, GaimPrefType type, gconstpointer val, gpointer data)
+{
+	GaimBlistNode *node, *sel;
+	if (ggblist == NULL || ggblist->window == NULL)
+		return;
+
+	sel = gnt_tree_get_selection_data(GNT_TREE(ggblist->tree));
+	gnt_tree_remove_all(GNT_TREE(ggblist->tree));
+	node = gaim_blist_get_root();
+	for (; node; node = gaim_blist_node_next(node, TRUE))
+		node->ui_data = NULL;
+	populate_buddylist();
+	gnt_tree_set_selected(GNT_TREE(ggblist->tree), sel);
+	draw_tooltip(ggblist);
+}
+
+void finch_blist_init()
+{
+	gaim_prefs_add_none(PREF_ROOT);
+	gaim_prefs_add_none(PREF_ROOT "/size");
+	gaim_prefs_add_int(PREF_ROOT "/size/width", 20);
+	gaim_prefs_add_int(PREF_ROOT "/size/height", 17);
+	gaim_prefs_add_none(PREF_ROOT "/position");
+	gaim_prefs_add_int(PREF_ROOT "/position/x", 0);
+	gaim_prefs_add_int(PREF_ROOT "/position/y", 0);
+	gaim_prefs_add_bool(PREF_ROOT "/idletime", TRUE);
+	gaim_prefs_add_bool(PREF_ROOT "/showoffline", FALSE);
+	gaim_prefs_add_string(PREF_ROOT "/sort_type", "text");
+
+	gaim_prefs_connect_callback(finch_blist_get_handle(),
+			PREF_ROOT "/showoffline", redraw_blist, NULL);
+	gaim_prefs_connect_callback(finch_blist_get_handle(),
+			PREF_ROOT "/sort_type", redraw_blist, NULL);
+
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-on", gaim_blist_get_handle(),
+			G_CALLBACK(account_signed_on_cb), NULL);
+	return;
+}
+
+static gboolean
+remove_typing_cb(gpointer null)
+{
+	GaimSavedStatus *current;
+	const char *message, *newmessage;
+	GaimStatusPrimitive prim, newprim;
+	StatusBoxItem *item;
+
+	current = gaim_savedstatus_get_current();
+	message = gaim_savedstatus_get_message(current);
+	prim = gaim_savedstatus_get_type(current);
+
+	newmessage = gnt_entry_get_text(GNT_ENTRY(ggblist->statustext));
+	item = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(ggblist->status));
+	g_return_val_if_fail(item->type == STATUS_PRIMITIVE, FALSE);
+	newprim = item->u.prim;
+
+	if (newprim != prim || ((message && !newmessage) ||
+				(!message && newmessage) ||
+				(message && newmessage && g_utf8_collate(message, newmessage) != 0)))
+	{
+		GaimSavedStatus *status = gaim_savedstatus_find_transient_by_type_and_message(newprim, newmessage);
+									/* Holy Crap! That's a LAWNG function name */
+		if (status == NULL)
+		{
+			status = gaim_savedstatus_new(NULL, newprim);
+			gaim_savedstatus_set_message(status, newmessage);
+		}
+
+		gaim_savedstatus_activate(status);
+	}
+
+	gnt_box_give_focus_to_child(GNT_BOX(ggblist->window), ggblist->tree);
+	if (ggblist->typing)
+		g_source_remove(ggblist->typing);
+	ggblist->typing = 0;
+	return FALSE;
+}
+
+static void
+status_selection_changed(GntComboBox *box, StatusBoxItem *old, StatusBoxItem *now, gpointer null)
+{
+	gnt_entry_set_text(GNT_ENTRY(ggblist->statustext), NULL);
+	if (now->type == STATUS_SAVED_POPULAR)
+	{
+		/* Set the status immediately */
+		gaim_savedstatus_activate(now->u.saved);
+	}
+	else if (now->type == STATUS_PRIMITIVE)
+	{
+		/* Move the focus to the entry box */
+		/* XXX: Make sure the selected status can have a message */
+		gnt_box_move_focus(GNT_BOX(ggblist->window), 1);
+		ggblist->typing = g_timeout_add(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, NULL);
+	}
+	else if (now->type == STATUS_SAVED_ALL)
+	{
+		/* Restore the selection to reflect current status. */
+		savedstatus_changed(gaim_savedstatus_get_current(), NULL);
+		gnt_box_give_focus_to_child(GNT_BOX(ggblist->window), ggblist->tree);
+		finch_savedstatus_show_all();
+	}
+	else if (now->type == STATUS_SAVED_NEW)
+	{
+		savedstatus_changed(gaim_savedstatus_get_current(), NULL);
+		gnt_box_give_focus_to_child(GNT_BOX(ggblist->window), ggblist->tree);
+		finch_savedstatus_edit(NULL);
+	}
+	else
+		g_return_if_reached();
+}
+
+static gboolean
+status_text_changed(GntEntry *entry, const char *text, gpointer null)
+{
+	if ((text[0] == 27 || (text[0] == '\t' && text[1] == '\0')) && ggblist->typing == 0)
+		return FALSE;
+
+	if (ggblist->typing)
+		g_source_remove(ggblist->typing);
+	ggblist->typing = 0;
+
+	if (text[0] == '\r' && text[1] == 0)
+	{
+		/* Set the status only after you press 'Enter' */
+		remove_typing_cb(NULL);
+		return TRUE;
+	}
+
+	ggblist->typing = g_timeout_add(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, NULL);
+	return FALSE;
+}
+
+static void
+savedstatus_changed(GaimSavedStatus *now, GaimSavedStatus *old)
+{
+	GList *list;
+	GaimStatusPrimitive prim;
+	const char *message;
+	gboolean found = FALSE, saved = TRUE;
+
+	if (!ggblist)
+		return;
+
+	/* Block the signals we don't want to emit */
+	g_signal_handlers_block_matched(ggblist->status, G_SIGNAL_MATCH_FUNC,
+			0, 0, NULL, status_selection_changed, NULL);
+	g_signal_handlers_block_matched(ggblist->statustext, G_SIGNAL_MATCH_FUNC,
+			0, 0, NULL, status_text_changed, NULL);
+
+	prim = gaim_savedstatus_get_type(now);
+	message = gaim_savedstatus_get_message(now);
+
+	/* Rebuild the status dropdown */
+	populate_status_dropdown();
+
+	while (!found) {
+		list = g_object_get_data(G_OBJECT(ggblist->status), "list of statuses");
+		for (; list; list = list->next)
+		{
+			StatusBoxItem *item = list->data;
+			if ((saved && item->type != STATUS_PRIMITIVE && item->u.saved == now) ||
+					(!saved && item->type == STATUS_PRIMITIVE && item->u.prim == prim))
+			{
+				char *mess = gaim_unescape_html(message);
+				gnt_combo_box_set_selected(GNT_COMBO_BOX(ggblist->status), item);
+				gnt_entry_set_text(GNT_ENTRY(ggblist->statustext), mess);
+				gnt_widget_draw(ggblist->status);
+				g_free(mess);
+				found = TRUE;
+				break;
+			}
+		}
+		if (!saved)
+			break;
+		saved = FALSE;
+	}
+
+	g_signal_handlers_unblock_matched(ggblist->status, G_SIGNAL_MATCH_FUNC,
+			0, 0, NULL, status_selection_changed, NULL);
+	g_signal_handlers_unblock_matched(ggblist->statustext, G_SIGNAL_MATCH_FUNC,
+			0, 0, NULL, status_text_changed, NULL);
+}
+
+static int
+blist_node_compare_text(GaimBlistNode *n1, GaimBlistNode *n2)
+{
+	const char *s1, *s2;
+	char *us1, *us2;
+	int ret;
+	
+	g_return_val_if_fail(n1->type == n2->type, -1);
+	
+	switch (n1->type)
+	{
+		case GAIM_BLIST_GROUP_NODE:
+			s1 = ((GaimGroup*)n1)->name;
+			s2 = ((GaimGroup*)n2)->name;
+			break;
+		case GAIM_BLIST_CHAT_NODE:
+			s1 = gaim_chat_get_name((GaimChat*)n1);
+			s2 = gaim_chat_get_name((GaimChat*)n2);
+			break;
+		case GAIM_BLIST_BUDDY_NODE:
+			return gaim_presence_compare(gaim_buddy_get_presence((GaimBuddy*)n1),
+					gaim_buddy_get_presence((GaimBuddy*)n2));
+			break;
+		case GAIM_BLIST_CONTACT_NODE:
+			s1 = gaim_contact_get_alias((GaimContact*)n1);
+			s2 = gaim_contact_get_alias((GaimContact*)n2);
+			break;
+		default:
+			return -1;
+	}
+
+	us1 = g_utf8_strup(s1, -1);
+	us2 = g_utf8_strup(s2, -1);
+	ret = g_utf8_collate(us1, us2);
+	g_free(us1);
+	g_free(us2);
+
+	return ret;
+}
+
+static int
+blist_node_compare_status(GaimBlistNode *n1, GaimBlistNode *n2)
+{
+	int ret;
+
+	g_return_val_if_fail(n1->type == n2->type, -1);
+
+	switch (n1->type) {
+		case GAIM_BLIST_CONTACT_NODE:
+			n1 = (GaimBlistNode*)gaim_contact_get_priority_buddy((GaimContact*)n1);
+			n2 = (GaimBlistNode*)gaim_contact_get_priority_buddy((GaimContact*)n2);
+			/* now compare the presence of the priority buddies */
+		case GAIM_BLIST_BUDDY_NODE:
+			ret = gaim_presence_compare(gaim_buddy_get_presence((GaimBuddy*)n1),
+					gaim_buddy_get_presence((GaimBuddy*)n2));
+			if (ret != 0)
+				return ret;
+			break;
+		default:
+			break;
+	}
+
+	/* Sort alphabetically if presence is not comparable */
+	ret = blist_node_compare_text(n1, n2);
+
+	return ret;
+}
+
+static int
+get_contact_log_size(GaimBlistNode *c)
+{
+	int log = 0;
+	GaimBlistNode *node;
+
+	for (node = c->child; node; node = node->next) {
+		GaimBuddy *b = (GaimBuddy*)node;
+		log += gaim_log_get_total_size(GAIM_LOG_IM, b->name, b->account);
+	}
+
+	return log;
+}
+
+static int
+blist_node_compare_log(GaimBlistNode *n1, GaimBlistNode *n2)
+{
+	int ret;
+	GaimBuddy *b1, *b2;
+
+	g_return_val_if_fail(n1->type == n2->type, -1);
+
+	switch (n1->type) {
+		case GAIM_BLIST_BUDDY_NODE:
+			b1 = (GaimBuddy*)n1;
+			b2 = (GaimBuddy*)n2;
+			ret = gaim_log_get_total_size(GAIM_LOG_IM, b2->name, b2->account) - 
+					gaim_log_get_total_size(GAIM_LOG_IM, b1->name, b1->account);
+			if (ret != 0)
+				return ret;
+			break;
+		case GAIM_BLIST_CONTACT_NODE:
+			ret = get_contact_log_size(n2) - get_contact_log_size(n1);
+			if (ret != 0)
+				return ret;
+			break;
+		default:
+			break;
+	}
+	ret = blist_node_compare_text(n1, n2);
+	return ret;
+}
+
+static gboolean
+blist_clicked(GntTree *tree, GntMouseEvent event, int x, int y, gpointer ggblist)
+{
+	if (event == GNT_RIGHT_MOUSE_DOWN) {
+		draw_context_menu(ggblist);
+	}
+	return FALSE;
+}
+
+static void
+plugin_action(GntMenuItem *item, gpointer data)
+{
+	GaimPluginAction *action = data;
+	if (action && action->callback)
+		action->callback(action);
+}
+
+static void
+build_plugin_actions(GntMenuItem *item, GaimPlugin *plugin, gpointer context)
+{
+	GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
+	GList *actions;
+	GntMenuItem *menuitem;
+
+	gnt_menuitem_set_submenu(item, GNT_MENU(sub));
+	for (actions = GAIM_PLUGIN_ACTIONS(plugin, context); actions;
+			actions = g_list_delete_link(actions, actions)) {
+		if (actions->data) {
+			GaimPluginAction *action = actions->data;
+			action->plugin = plugin;
+			action->context = context;
+			menuitem = gnt_menuitem_new(action->label);
+			gnt_menu_add_item(GNT_MENU(sub), menuitem);
+
+			gnt_menuitem_set_callback(menuitem, plugin_action, action);
+			g_object_set_data_full(G_OBJECT(menuitem), "plugin_action",
+								   action, (GDestroyNotify)gaim_plugin_action_free);
+		}
+	}
+}
+
+static void
+reconstruct_plugins_menu()
+{
+	GntWidget *sub;
+	GntMenuItem *plg;
+	GList *iter;
+
+	if (!ggblist)
+		return;
+
+	if (ggblist->plugins == NULL)
+		ggblist->plugins = gnt_menuitem_new(_("Plugins"));
+
+	plg = ggblist->plugins;
+	sub = gnt_menu_new(GNT_MENU_POPUP);
+	gnt_menuitem_set_submenu(plg, GNT_MENU(sub));
+
+	for (iter = gaim_plugins_get_loaded(); iter; iter = iter->next) {
+		GaimPlugin *plugin = iter->data;
+		GntMenuItem *item;
+		if (GAIM_IS_PROTOCOL_PLUGIN(plugin))
+			continue;
+
+		if (!GAIM_PLUGIN_HAS_ACTIONS(plugin))
+			continue;
+
+		item = gnt_menuitem_new(_(plugin->info->name));
+		gnt_menu_add_item(GNT_MENU(sub), item);
+		build_plugin_actions(item, plugin, NULL);
+	}
+}
+
+static void
+reconstruct_accounts_menu()
+{
+	GntWidget *sub;
+	GntMenuItem *acc, *item;
+	GList *iter;
+
+	if (!ggblist)
+		return;
+
+	if (ggblist->accounts == NULL)
+		ggblist->accounts = gnt_menuitem_new(_("Accounts"));
+
+	acc = ggblist->accounts;
+	sub = gnt_menu_new(GNT_MENU_POPUP);
+	gnt_menuitem_set_submenu(acc, GNT_MENU(sub));
+
+	for (iter = gaim_accounts_get_all_active(); iter;
+			iter = g_list_delete_link(iter, iter)) {
+		GaimAccount *account = iter->data;
+		GaimConnection *gc = gaim_account_get_connection(account);
+		GaimPlugin *prpl;
+		
+		if (!gc || !GAIM_CONNECTION_IS_CONNECTED(gc))
+			continue;
+		prpl = gc->prpl;
+
+		if (GAIM_PLUGIN_HAS_ACTIONS(prpl)) {
+			item = gnt_menuitem_new(gaim_account_get_username(account));
+			gnt_menu_add_item(GNT_MENU(sub), item);
+			build_plugin_actions(item, prpl, gc);
+		}
+	}
+}
+
+static void
+account_signed_on_cb()
+{
+	GaimBlistNode *node;
+
+	for (node = gaim_blist_get_root(); node;
+			node = gaim_blist_node_next(node, FALSE)) {
+		if (GAIM_BLIST_NODE_IS_CHAT(node)) {
+			GaimChat *chat = (GaimChat*)node;
+			if (gaim_blist_node_get_bool(node, "gnt-autojoin"))
+				serv_join_chat(gaim_account_get_connection(chat->account), chat->components);
+		}
+	}
+}
+
+static void show_offline_cb(GntMenuItem *item, gpointer n)
+{
+	gaim_prefs_set_bool(PREF_ROOT "/showoffline",
+		!gaim_prefs_get_bool(PREF_ROOT "/showoffline"));
+}
+
+static void sort_blist_change_cb(GntMenuItem *item, gpointer n)
+{
+	gaim_prefs_set_string(PREF_ROOT "/sort_type", n);
+}
+
+/* XXX: send_im_select* -- Xerox */
+static void
+send_im_select_cb(gpointer data, GaimRequestFields *fields)
+{
+	GaimAccount *account;
+	const char *username;
+
+	account  = gaim_request_fields_get_account(fields, "account");
+	username = gaim_request_fields_get_string(fields,  "screenname");
+
+	gaim_conversation_new(GAIM_CONV_TYPE_IM, account, username);
+}
+
+static void
+send_im_select(GntMenuItem *item, gpointer n)
+{
+	GaimRequestFields *fields;
+	GaimRequestFieldGroup *group;
+	GaimRequestField *field;
+
+	fields = gaim_request_fields_new();
+
+	group = gaim_request_field_group_new(NULL);
+	gaim_request_fields_add_group(fields, group);
+
+	field = gaim_request_field_string_new("screenname", _("_Name"), NULL, FALSE);
+	gaim_request_field_set_type_hint(field, "screenname");
+	gaim_request_field_set_required(field, TRUE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_account_new("account", _("_Account"), NULL);
+	gaim_request_field_set_type_hint(field, "account");
+	gaim_request_field_set_visible(field,
+		(gaim_connections_get_all() != NULL &&
+		 gaim_connections_get_all()->next != NULL));
+	gaim_request_field_set_required(field, TRUE);
+	gaim_request_field_group_add_field(group, field);
+
+	gaim_request_fields(gaim_get_blist(), _("New Instant Message"),
+						NULL,
+						_("Please enter the screen name or alias of the person "
+						  "you would like to IM."),
+						fields,
+						_("OK"), G_CALLBACK(send_im_select_cb),
+						_("Cancel"), NULL,
+						NULL);
+}
+
+static void
+create_menu()
+{
+	GntWidget *menu, *sub;
+	GntMenuItem *item;
+	GntWindow *window;
+
+	if (!ggblist)
+		return;
+
+	window = GNT_WINDOW(ggblist->window);
+	ggblist->menu = menu = gnt_menu_new(GNT_MENU_TOPLEVEL);
+	gnt_window_set_menu(window, GNT_MENU(menu));
+
+	item = gnt_menuitem_new(_("Options"));
+	gnt_menu_add_item(GNT_MENU(menu), item);
+
+	sub = gnt_menu_new(GNT_MENU_POPUP);
+	gnt_menuitem_set_submenu(item, GNT_MENU(sub));
+
+	item = gnt_menuitem_new(_("Send IM..."));
+	gnt_menu_add_item(GNT_MENU(sub), item);
+	gnt_menuitem_set_callback(GNT_MENUITEM(item), send_im_select, NULL);
+
+	item = gnt_menuitem_check_new(_("Toggle offline buddies"));
+	gnt_menuitem_check_set_checked(GNT_MENUITEM_CHECK(item),
+				gaim_prefs_get_bool(PREF_ROOT "/showoffline"));
+	gnt_menu_add_item(GNT_MENU(sub), item);
+	gnt_menuitem_set_callback(GNT_MENUITEM(item), show_offline_cb, NULL);
+
+	item = gnt_menuitem_new(_("Sort by status"));
+	gnt_menu_add_item(GNT_MENU(sub), item);
+	gnt_menuitem_set_callback(GNT_MENUITEM(item), sort_blist_change_cb, "status");
+
+	item = gnt_menuitem_new(_("Sort alphabetically"));
+	gnt_menu_add_item(GNT_MENU(sub), item);
+	gnt_menuitem_set_callback(GNT_MENUITEM(item), sort_blist_change_cb, "text");
+
+	item = gnt_menuitem_new(_("Sort by log size"));
+	gnt_menu_add_item(GNT_MENU(sub), item);
+	gnt_menuitem_set_callback(GNT_MENUITEM(item), sort_blist_change_cb, "log");
+
+	reconstruct_accounts_menu();
+	gnt_menu_add_item(GNT_MENU(menu), ggblist->accounts);
+
+	reconstruct_plugins_menu();
+	gnt_menu_add_item(GNT_MENU(menu), ggblist->plugins);
+}
+
+void finch_blist_show()
+{
+	blist_show(gaim_get_blist());
+}
+
+static void
+blist_show(GaimBuddyList *list)
+{
+	if (ggblist == NULL)
+		new_list(list);
+	else if (ggblist->window)
+		return;
+
+	ggblist->window = gnt_vwindow_new(FALSE);
+	gnt_widget_set_name(ggblist->window, "buddylist");
+	gnt_box_set_toplevel(GNT_BOX(ggblist->window), TRUE);
+	gnt_box_set_title(GNT_BOX(ggblist->window), _("Buddy List"));
+	gnt_box_set_pad(GNT_BOX(ggblist->window), 0);
+
+	ggblist->tree = gnt_tree_new();
+
+	GNT_WIDGET_SET_FLAGS(ggblist->tree, GNT_WIDGET_NO_BORDER);
+	gnt_widget_set_size(ggblist->tree, gaim_prefs_get_int(PREF_ROOT "/size/width"),
+			gaim_prefs_get_int(PREF_ROOT "/size/height"));
+	gnt_widget_set_position(ggblist->window, gaim_prefs_get_int(PREF_ROOT "/position/x"),
+			gaim_prefs_get_int(PREF_ROOT "/position/y"));
+
+	gnt_tree_set_col_width(GNT_TREE(ggblist->tree), 0,
+			gaim_prefs_get_int(PREF_ROOT "/size/width") - 1);
+
+	gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->tree);
+
+	ggblist->status = gnt_combo_box_new();
+	gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->status);
+	ggblist->statustext = gnt_entry_new(NULL);
+	gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->statustext);
+
+	gnt_widget_show(ggblist->window);
+
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-on", finch_blist_get_handle(),
+				GAIM_CALLBACK(reconstruct_accounts_menu), NULL);
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-off", finch_blist_get_handle(),
+				GAIM_CALLBACK(reconstruct_accounts_menu), NULL);
+	gaim_signal_connect(gaim_blist_get_handle(), "buddy-status-changed", finch_blist_get_handle(),
+				GAIM_CALLBACK(buddy_status_changed), ggblist);
+	gaim_signal_connect(gaim_blist_get_handle(), "buddy-idle-changed", finch_blist_get_handle(),
+				GAIM_CALLBACK(buddy_idle_changed), ggblist);
+
+	gaim_signal_connect(gaim_plugins_get_handle(), "plugin-load", finch_blist_get_handle(),
+				GAIM_CALLBACK(reconstruct_plugins_menu), NULL);
+	gaim_signal_connect(gaim_plugins_get_handle(), "plugin-unload", finch_blist_get_handle(),
+				GAIM_CALLBACK(reconstruct_plugins_menu), NULL);
+
+#if 0
+	gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-on", finch_blist_get_handle(),
+				GAIM_CALLBACK(buddy_signed_on), ggblist);
+	gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-off", finch_blist_get_handle(),
+				GAIM_CALLBACK(buddy_signed_off), ggblist);
+
+	/* These I plan to use to indicate unread-messages etc. */
+	gaim_signal_connect(gaim_conversations_get_handle(), "received-im-msg", finch_blist_get_handle(),
+				GAIM_CALLBACK(received_im_msg), list);
+	gaim_signal_connect(gaim_conversations_get_handle(), "sent-im-msg", finch_blist_get_handle(),
+				GAIM_CALLBACK(sent_im_msg), NULL);
+
+	gaim_signal_connect(gaim_conversations_get_handle(), "received-chat-msg", finch_blist_get_handle(),
+				GAIM_CALLBACK(received_chat_msg), list);
+#endif
+
+	g_signal_connect(G_OBJECT(ggblist->tree), "selection_changed", G_CALLBACK(selection_changed), ggblist);
+	g_signal_connect(G_OBJECT(ggblist->tree), "key_pressed", G_CALLBACK(key_pressed), ggblist);
+	g_signal_connect(G_OBJECT(ggblist->tree), "context-menu", G_CALLBACK(context_menu), ggblist);
+	g_signal_connect_after(G_OBJECT(ggblist->tree), "clicked", G_CALLBACK(blist_clicked), ggblist);
+	g_signal_connect(G_OBJECT(ggblist->tree), "activate", G_CALLBACK(selection_activate), ggblist);
+	g_signal_connect_data(G_OBJECT(ggblist->tree), "gained-focus", G_CALLBACK(draw_tooltip),
+				ggblist, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+	g_signal_connect_data(G_OBJECT(ggblist->tree), "lost-focus", G_CALLBACK(remove_peripherals),
+				ggblist, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+	g_signal_connect(G_OBJECT(ggblist->tree), "size_changed", G_CALLBACK(size_changed_cb), NULL);
+	g_signal_connect(G_OBJECT(ggblist->window), "position_set", G_CALLBACK(save_position_cb), NULL);
+	g_signal_connect(G_OBJECT(ggblist->window), "destroy", G_CALLBACK(reset_blist_window), NULL);
+
+	/* Status signals */
+	gaim_signal_connect(gaim_savedstatuses_get_handle(), "savedstatus-changed", finch_blist_get_handle(),
+				GAIM_CALLBACK(savedstatus_changed), NULL);
+	g_signal_connect(G_OBJECT(ggblist->status), "selection_changed",
+				G_CALLBACK(status_selection_changed), NULL);
+	g_signal_connect(G_OBJECT(ggblist->statustext), "key_pressed",
+				G_CALLBACK(status_text_changed), NULL);
+
+	create_menu();
+
+	populate_buddylist();
+
+	savedstatus_changed(gaim_savedstatus_get_current(), NULL);
+}
+
+void finch_blist_uninit()
+{
+	if (ggblist == NULL)
+		return;
+
+	gnt_widget_destroy(ggblist->window);
+	g_free(ggblist);
+	ggblist = NULL;
+}
+
+gboolean finch_blist_get_position(int *x, int *y)
+{
+	if (!ggblist || !ggblist->window)
+		return FALSE;
+	gnt_widget_get_position(ggblist->window, x, y);
+	return TRUE;
+}
+
+void finch_blist_set_position(int x, int y)
+{
+	gnt_widget_set_position(ggblist->window, x, y);
+}
+
+gboolean finch_blist_get_size(int *width, int *height)
+{
+	if (!ggblist || !ggblist->window)
+		return FALSE;
+	gnt_widget_get_size(ggblist->window, width, height);
+	return TRUE;
+}
+
+void finch_blist_set_size(int width, int height)
+{
+	gnt_widget_set_size(ggblist->window, width, height);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntblist.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,95 @@
+/**
+ * @file gntblist.h GNT BuddyList API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_BLIST_H
+#define _GNT_BLIST_H
+
+#include "blist.h"
+
+/**********************************************************************
+ * @name GNT BuddyList API
+ **********************************************************************/
+/*@{*/
+
+/**
+ * Get the ui-functions.
+ *
+ * @return The GaimBlistUiOps structure populated with the appropriate functions.
+ */
+GaimBlistUiOps * finch_blist_get_ui_ops(void);
+
+/**
+ * Perform necessary initializations.
+ */
+void finch_blist_init(void);
+
+/**
+ * Perform necessary uninitializations.
+ */
+void finch_blist_uninit(void);
+
+/**
+ * Show the buddy list.
+ */
+void finch_blist_show(void);
+
+/**
+ * Get the position of the buddy list.
+ *
+ * @param x The x-coordinate is set here if not @ NULL.
+ * @param y The y-coordinate is set here if not @c NULL.
+ *
+ * @return Returns @c TRUE if the values were set, @c FALSE otherwise.
+ */
+gboolean finch_blist_get_position(int *x, int *y);
+
+/**
+ * Set the position of the buddy list.
+ *
+ * @param x The x-coordinate of the buddy list.
+ * @param y The y-coordinate of the buddy list.
+ */
+void finch_blist_set_position(int x, int y);
+
+/**
+ * Get the size of the buddy list.
+ *
+ * @param width  The width is set here if not @ NULL.
+ * @param height The height is set here if not @c NULL.
+ *
+ * @return Returns @c TRUE if the values were set, @c FALSE otherwise.
+ */
+gboolean finch_blist_get_size(int *width, int *height);
+
+/**
+ * Set the size of the buddy list.
+ *
+ * @param width  The width of the buddy list.
+ * @param height The height of the buddy list.
+ */
+void finch_blist_set_size(int width, int height);
+
+/*@}*/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntconn.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,75 @@
+/**
+ * @file gntconn.c GNT Connection API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "account.h"
+#include "core.h"
+#include "request.h"
+
+#include "gntconn.h"
+#include "gntgaim.h"
+
+static void
+finch_connection_report_disconnect(GaimConnection *gc, const char *text)
+{
+	char *act, *primary, *secondary;
+	GaimAccount *account = gaim_connection_get_account(gc);
+
+	act = g_strdup_printf(_("%s (%s)"), gaim_account_get_username(account),
+			gaim_account_get_protocol_name(account));
+
+	primary = g_strdup_printf(_("%s disconnected."), act);
+	secondary = g_strdup_printf(_("%s was disconnected due to the following error:\n%s"),
+			act, text);
+
+	gaim_request_action(account, _("Connection Error"), primary, secondary, 1,
+						account, 2,
+						_("OK"), NULL,
+						_("Connect"),
+						GAIM_CALLBACK(gaim_account_connect));
+
+	g_free(act);
+	g_free(primary);
+	g_free(secondary);
+}
+
+static GaimConnectionUiOps ops = 
+{
+	.connect_progress = NULL,
+	.connected = NULL,
+	.disconnected = NULL,
+	.notice = NULL,
+	.report_disconnect = finch_connection_report_disconnect
+};
+
+GaimConnectionUiOps *finch_connections_get_ui_ops()
+{
+	return &ops;
+}
+
+void finch_connections_init()
+{}
+
+void finch_connections_uninit()
+{}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntconn.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,54 @@
+/**
+ * @file gntconn.h GNT Connection API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_CONN_H
+#define _GNT_CONN_H
+
+#include "connection.h"
+
+/**********************************************************************
+ * @name GNT Connection API
+ **********************************************************************/
+/*@{*/
+
+/**
+ * Get the ui-functions.
+ *
+ * @return The GaimConnectionUiOps structure populated with the appropriate functions.
+ */
+GaimConnectionUiOps *finch_connections_get_ui_ops(void);
+
+/**
+ * Perform necessary initializations.
+ */
+void finch_connections_init(void);
+
+/**
+ * Perform necessary uninitializations.
+ */
+void finch_connections_uninit(void);
+
+/*@}*/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntconv.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,760 @@
+/**
+ * @file gntconv.c GNT Conversation API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <string.h>
+
+#include <cmds.h>
+#include <idle.h>
+#include <prefs.h>
+#include <util.h>
+
+#include "gntgaim.h"
+#include "gntaccount.h"
+#include "gntblist.h"
+#include "gntconv.h"
+#include "gntdebug.h"
+#include "gntplugin.h"
+#include "gntprefs.h"
+#include "gntstatus.h"
+
+#include "gnt.h"
+#include "gntbox.h"
+#include "gntentry.h"
+#include "gnttextview.h"
+
+#define PREF_ROOT	"/gaim/gnt/conversations"
+
+#include "config.h"
+
+static void
+send_typing_notification(GntWidget *w, FinchConv *ggconv)
+{
+	const char *text = gnt_entry_get_text(GNT_ENTRY(ggconv->entry));
+	gboolean empty = (!text || !*text);
+	if (gaim_prefs_get_bool("/gaim/gnt/conversations/notify_typing")) {
+		GaimConversation *conv = ggconv->active_conv;
+		GaimConvIm *im = GAIM_CONV_IM(conv);
+		if (!empty) {
+			gboolean send = (gaim_conv_im_get_send_typed_timeout(im) == 0);
+
+			gaim_conv_im_stop_send_typed_timeout(im);
+			gaim_conv_im_start_send_typed_timeout(im);
+			if (send || (gaim_conv_im_get_type_again(im) != 0 &&
+						  time(NULL) > gaim_conv_im_get_type_again(im))) {
+				unsigned int timeout;
+				timeout = serv_send_typing(gaim_conversation_get_gc(conv),
+										   gaim_conversation_get_name(conv),
+										   GAIM_TYPING);
+				gaim_conv_im_set_type_again(im, timeout);
+			}
+		} else {
+			gaim_conv_im_stop_send_typed_timeout(im);
+
+			serv_send_typing(gaim_conversation_get_gc(conv),
+							 gaim_conversation_get_name(conv),
+							 GAIM_NOT_TYPING);
+		}
+	}
+}
+
+static gboolean
+entry_key_pressed(GntWidget *w, const char *key, FinchConv *ggconv)
+{
+	if (key[0] == '\r' && key[1] == 0)
+	{
+		const char *text = gnt_entry_get_text(GNT_ENTRY(ggconv->entry));
+		if (*text == '/')
+		{
+			GaimConversation *conv = ggconv->active_conv;
+			GaimCmdStatus status;
+			const char *cmdline = text + 1;
+			char *error = NULL, *escape;
+
+			escape = g_markup_escape_text(cmdline, -1);
+			status = gaim_cmd_do_command(conv, cmdline, escape, &error);
+			g_free(escape);
+
+			switch (status)
+			{
+				case GAIM_CMD_STATUS_OK:
+					break;
+				case GAIM_CMD_STATUS_NOT_FOUND:
+					gaim_conversation_write(conv, "", _("No such command."),
+							GAIM_MESSAGE_NO_LOG, time(NULL));
+					break;
+				case GAIM_CMD_STATUS_WRONG_ARGS:
+					gaim_conversation_write(conv, "", _("Syntax Error:  You typed the wrong number of arguments "
+										"to that command."),
+							GAIM_MESSAGE_NO_LOG, time(NULL));
+					break;
+				case GAIM_CMD_STATUS_FAILED:
+					gaim_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."),
+							GAIM_MESSAGE_NO_LOG, time(NULL));
+					break;
+				case GAIM_CMD_STATUS_WRONG_TYPE:
+					if(gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM)
+						gaim_conversation_write(conv, "", _("That command only works in chats, not IMs."),
+								GAIM_MESSAGE_NO_LOG, time(NULL));
+					else
+						gaim_conversation_write(conv, "", _("That command only works in IMs, not chats."),
+								GAIM_MESSAGE_NO_LOG, time(NULL));
+					break;
+				case GAIM_CMD_STATUS_WRONG_PRPL:
+					gaim_conversation_write(conv, "", _("That command doesn't work on this protocol."),
+							GAIM_MESSAGE_NO_LOG, time(NULL));
+					break;
+			}
+			g_free(error);
+#if 0
+			gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
+					_("Commands are not supported yet. Message was NOT sent."),
+					GNT_TEXT_FLAG_DIM | GNT_TEXT_FLAG_UNDERLINE);
+			gnt_text_view_next_line(GNT_TEXT_VIEW(ggconv->tv));
+			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 0);
+#endif
+		}
+		else
+		{
+			char *escape = g_markup_escape_text(text, -1);
+			char *apos = gaim_strreplace(escape, "&apos;", "'");
+			g_free(escape);
+			escape = apos;
+			switch (gaim_conversation_get_type(ggconv->active_conv))
+			{
+				case GAIM_CONV_TYPE_IM:
+					gaim_conv_im_send_with_flags(GAIM_CONV_IM(ggconv->active_conv), escape, GAIM_MESSAGE_SEND);
+					break;
+				case GAIM_CONV_TYPE_CHAT:
+					gaim_conv_chat_send(GAIM_CONV_CHAT(ggconv->active_conv), escape);
+					break;
+				default:
+					g_free(escape);
+					g_return_val_if_reached(FALSE);
+			}
+			g_free(escape);
+			gaim_idle_touch();
+		}
+		gnt_entry_add_to_history(GNT_ENTRY(ggconv->entry), text);
+		gnt_entry_clear(GNT_ENTRY(ggconv->entry));
+		return TRUE;
+	}
+	else if (key[0] == 27)
+	{
+		if (strcmp(key, GNT_KEY_DOWN) == 0)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 1);
+		else if (strcmp(key, GNT_KEY_UP) == 0)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), -1);
+		else if (strcmp(key, GNT_KEY_PGDOWN) == 0)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), ggconv->tv->priv.height - 2);
+		else if (strcmp(key, GNT_KEY_PGUP) == 0)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), -(ggconv->tv->priv.height - 2));
+		else
+			return FALSE;
+		return TRUE;
+	}
+	else
+	{
+	}
+
+	return FALSE;
+}
+
+static void
+closing_window(GntWidget *window, FinchConv *ggconv)
+{
+	GList *list = ggconv->list;
+	ggconv->window = NULL;
+	while (list) {
+		GaimConversation *conv = list->data;
+		list = list->next;
+		gaim_conversation_destroy(conv);
+	}
+}
+
+static void
+size_changed_cb(GntWidget *widget, int width, int height)
+{
+	int w, h;
+	gnt_widget_get_size(widget, &w, &h);
+	gaim_prefs_set_int(PREF_ROOT "/size/width", w);
+	gaim_prefs_set_int(PREF_ROOT "/size/height", h);
+}
+
+static void
+save_position_cb(GntWidget *w, int x, int y)
+{
+	gaim_prefs_set_int(PREF_ROOT "/position/x", x);
+	gaim_prefs_set_int(PREF_ROOT "/position/y", y);
+}
+
+static GaimConversation *
+find_conv_with_contact(GaimConversation *conv)
+{
+	GaimBlistNode *node;
+	GaimBuddy *buddy = gaim_find_buddy(conv->account, conv->name);
+	GaimConversation *ret = NULL;
+
+	if (!buddy)
+		return NULL;
+
+	for (node = ((GaimBlistNode*)buddy)->parent->child; node; node = node->next) {
+		if (node == (GaimBlistNode*)buddy)
+			continue;
+		if ((ret = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM,
+				((GaimBuddy*)node)->name, ((GaimBuddy*)node)->account)) != NULL)
+			break;
+	}
+	return ret;
+}
+
+static char *
+get_conversation_title(GaimConversation *conv, GaimAccount *account)
+{
+	return g_strdup_printf(_("%s (%s -- %s)"), gaim_conversation_get_title(conv),
+		gaim_account_get_username(account), gaim_account_get_protocol_name(account));
+}
+
+static void
+update_buddy_typing(GaimAccount *account, const char *who, gpointer null)
+{
+	GaimConversation *conv;
+	FinchConv *ggc;
+	GaimConvIm *im = NULL;
+	char *title, *str;
+
+	conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, who, account);
+
+	if (!conv)
+		return;
+
+	im = GAIM_CONV_IM(conv);
+	ggc = conv->ui_data;
+
+	if (gaim_conv_im_get_typing_state(im) == GAIM_TYPING) {
+		int scroll;
+		str = get_conversation_title(conv, account);
+		title = g_strdup_printf(_("%s [%s]"), str,
+			gnt_ascii_only() ? "T" : "\342\243\277");
+		g_free(str);
+
+		scroll = gnt_text_view_get_lines_below(GNT_TEXT_VIEW(ggc->tv));
+		str = g_strdup_printf(_("\n%s is typing..."), gaim_conversation_get_name(conv));
+		/* Updating is a little buggy. So just remove and add a new one */
+		gnt_text_view_tag_change(GNT_TEXT_VIEW(ggc->tv), "typing", NULL, TRUE);
+		gnt_text_view_append_text_with_tag(GNT_TEXT_VIEW(ggc->tv),
+					str, GNT_TEXT_FLAG_DIM, "typing");
+		g_free(str);
+		if (scroll <= 1)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(ggc->tv), 0);
+ 	} else {
+		title = get_conversation_title(conv, account);
+		gnt_text_view_tag_change(GNT_TEXT_VIEW(ggc->tv), "typing", NULL, TRUE);
+	}
+	gnt_screen_rename_widget(ggc->window, title);
+	g_free(title);
+}
+
+static gpointer
+finch_conv_get_handle()
+{
+	static int handle;
+	return &handle;
+}
+
+static void
+finch_create_conversation(GaimConversation *conv)
+{
+	FinchConv *ggc = conv->ui_data;
+	char *title;
+	GaimConversationType type;
+	GaimConversation *cc;
+	GaimAccount *account;
+
+	if (ggc)
+		return;
+
+	cc = find_conv_with_contact(conv);
+	if (cc && cc->ui_data)
+		ggc = cc->ui_data;
+	else
+		ggc = g_new0(FinchConv, 1);
+
+	ggc->list = g_list_prepend(ggc->list, conv);
+	ggc->active_conv = conv;
+	conv->ui_data = ggc;
+
+	if (cc && cc->ui_data) {
+		finch_conversation_set_active(conv);
+		return;
+	}
+
+	account = gaim_conversation_get_account(conv);
+	type = gaim_conversation_get_type(conv);
+	title = get_conversation_title(conv, account);
+
+	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_box_set_pad(GNT_BOX(ggc->window), 0);
+	gnt_widget_set_name(ggc->window, "conversation-window");
+
+	ggc->tv = gnt_text_view_new();
+	gnt_box_add_widget(GNT_BOX(ggc->window), ggc->tv);
+	gnt_widget_set_name(ggc->tv, "conversation-window-textview");
+	gnt_widget_set_size(ggc->tv, gaim_prefs_get_int(PREF_ROOT "/size/width"),
+			gaim_prefs_get_int(PREF_ROOT "/size/height"));
+
+	ggc->entry = gnt_entry_new(NULL);
+	gnt_box_add_widget(GNT_BOX(ggc->window), ggc->entry);
+	gnt_widget_set_name(ggc->entry, "conversation-window-entry");
+	gnt_entry_set_history_length(GNT_ENTRY(ggc->entry), -1);
+	gnt_entry_set_word_suggest(GNT_ENTRY(ggc->entry), TRUE);
+	gnt_entry_set_always_suggest(GNT_ENTRY(ggc->entry), FALSE);
+
+	g_signal_connect_after(G_OBJECT(ggc->entry), "key_pressed", G_CALLBACK(entry_key_pressed), ggc);
+	g_signal_connect(G_OBJECT(ggc->window), "destroy", G_CALLBACK(closing_window), ggc);
+
+	gnt_widget_set_position(ggc->window, gaim_prefs_get_int(PREF_ROOT "/position/x"),
+			gaim_prefs_get_int(PREF_ROOT "/position/y"));
+	gnt_widget_show(ggc->window);
+
+	g_signal_connect(G_OBJECT(ggc->tv), "size_changed", G_CALLBACK(size_changed_cb), NULL);
+	g_signal_connect(G_OBJECT(ggc->window), "position_set", G_CALLBACK(save_position_cb), NULL);
+
+	if (type == GAIM_CONV_TYPE_IM) {
+		g_signal_connect(G_OBJECT(ggc->entry), "text_changed", G_CALLBACK(send_typing_notification), ggc);
+		gaim_signal_connect(gaim_conversations_get_handle(), "buddy-typing", finch_conv_get_handle(),
+						GAIM_CALLBACK(update_buddy_typing), NULL);
+		gaim_signal_connect(gaim_conversations_get_handle(), "buddy-typing-stopped", finch_conv_get_handle(),
+						GAIM_CALLBACK(update_buddy_typing), NULL);
+	}
+
+	g_free(title);
+}
+
+static void
+finch_destroy_conversation(GaimConversation *conv)
+{
+	/* do stuff here */
+	FinchConv *ggc = conv->ui_data;
+	ggc->list = g_list_remove(ggc->list, conv);
+	if (ggc->list && conv == ggc->active_conv)
+		ggc->active_conv = ggc->list->data;
+	
+	if (ggc->list == NULL) {
+		gnt_widget_destroy(ggc->window);
+		g_free(ggc);
+	}
+}
+
+static void
+finch_write_common(GaimConversation *conv, const char *who, const char *message,
+		GaimMessageFlags flags, time_t mtime)
+{
+	FinchConv *ggconv = conv->ui_data;
+	char *strip, *newline;
+	GntTextFormatFlags fl = 0;
+	int pos;
+	gboolean notify;
+
+	g_return_if_fail(ggconv != NULL);
+
+	if (ggconv->active_conv != conv) {
+		if (flags & (GAIM_MESSAGE_SEND | GAIM_MESSAGE_RECV))
+			finch_conversation_set_active(conv);
+		else
+			return;
+	}
+
+	pos = gnt_text_view_get_lines_below(GNT_TEXT_VIEW(ggconv->tv));
+
+	notify = !!gnt_text_view_tag_change(GNT_TEXT_VIEW(ggconv->tv), "typing", NULL, TRUE);
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv), "\n", GNT_TEXT_FLAG_NORMAL);
+
+	/* Unnecessary to print the timestamp for delayed message */
+	if (!(flags & GAIM_MESSAGE_DELAYED) &&
+			gaim_prefs_get_bool("/gaim/gnt/conversations/timestamps"))
+		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
+					gaim_utf8_strftime("(%H:%M:%S) ", localtime(&mtime)), GNT_TEXT_FLAG_DIM);
+
+	if (flags & GAIM_MESSAGE_AUTO_RESP)
+		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
+					_("<AUTO-REPLY> "), GNT_TEXT_FLAG_BOLD);
+
+	if (who && *who && (flags & (GAIM_MESSAGE_SEND | GAIM_MESSAGE_RECV)))
+	{
+		char * name = NULL;
+
+		if (gaim_message_meify((char*)message, -1))
+			name = g_strdup_printf("*** %s ", who);
+		else
+			name =  g_strdup_printf("%s: ", who);
+
+		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
+				name, GNT_TEXT_FLAG_BOLD);
+		g_free(name);
+	}
+	else
+		fl = GNT_TEXT_FLAG_DIM;
+
+	if (flags & GAIM_MESSAGE_ERROR)
+		fl |= GNT_TEXT_FLAG_BOLD;
+	if (flags & GAIM_MESSAGE_NICK)
+		fl |= GNT_TEXT_FLAG_UNDERLINE;
+
+	/* XXX: Remove this workaround when textview can parse messages. */
+	newline = gaim_strdup_withhtml(message);
+	strip = gaim_markup_strip_html(newline);
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
+				strip, fl);
+
+	g_free(newline);
+	g_free(strip);
+
+	if (notify) {
+		strip = g_strdup_printf(_("\n%s is typing..."), gaim_conversation_get_name(conv));
+		gnt_text_view_append_text_with_tag(GNT_TEXT_VIEW(ggconv->tv),
+					strip, GNT_TEXT_FLAG_DIM, "typing");
+		g_free(strip);
+	}
+
+	if (pos <= 1)
+		gnt_text_view_scroll(GNT_TEXT_VIEW(ggconv->tv), 0);
+
+	if (flags & (GAIM_MESSAGE_RECV | GAIM_MESSAGE_NICK | GAIM_MESSAGE_ERROR))
+		gnt_widget_set_urgent(ggconv->tv);
+}
+
+static void
+finch_write_chat(GaimConversation *conv, const char *who, const char *message,
+		GaimMessageFlags flags, time_t mtime)
+{
+	gaim_conversation_write(conv, who, message, flags, mtime);
+}
+
+static void
+finch_write_im(GaimConversation *conv, const char *who, const char *message,
+		GaimMessageFlags flags, time_t mtime)
+{
+	GaimAccount *account = gaim_conversation_get_account(conv);
+	if (flags & GAIM_MESSAGE_SEND)
+	{
+		who = gaim_connection_get_display_name(gaim_account_get_connection(account));
+		if (!who)
+			who = gaim_account_get_alias(account);
+		if (!who)
+			who = gaim_account_get_username(account);
+	}
+	else if (flags & GAIM_MESSAGE_RECV)
+	{
+		GaimBuddy *buddy;
+		who = gaim_conversation_get_name(conv);
+		buddy = gaim_find_buddy(account, who);
+		if (buddy)
+			who = gaim_buddy_get_contact_alias(buddy);
+	}
+
+	gaim_conversation_write(conv, who, message, flags, mtime);
+}
+
+static void
+finch_write_conv(GaimConversation *conv, const char *who, const char *alias,
+		const char *message, GaimMessageFlags flags, time_t mtime)
+{
+	const char *name;
+	if (alias && *alias)
+		name = alias;
+	else if (who && *who)
+		name = who;
+	else
+		name = NULL;
+
+	finch_write_common(conv, name, message, flags, mtime);
+}
+
+static void
+finch_chat_add_users(GaimConversation *conv, GList *users, gboolean new_arrivals)
+{
+	FinchConv *ggc = conv->ui_data;
+	GntEntry *entry = GNT_ENTRY(ggc->entry);
+
+	if (!new_arrivals)
+	{
+		/* Print the list of users in the room */
+		GString *string = g_string_new(_("List of users:\n"));
+		GList *iter;
+
+		for (iter = users; iter; iter = iter->next)
+		{
+			GaimConvChatBuddy *cbuddy = iter->data;
+			char *str;
+
+			if ((str = cbuddy->alias) == NULL)
+				str = cbuddy->name;
+			g_string_append_printf(string, "[ %s ]", str);
+		}
+
+		gaim_conversation_write(conv, NULL, string->str,
+				GAIM_MESSAGE_SYSTEM, time(NULL));
+		g_string_free(string, TRUE);
+	}
+
+	for (; users; users = users->next)
+	{
+		GaimConvChatBuddy *cbuddy = users->data;
+		gnt_entry_add_suggest(entry, cbuddy->name);
+		gnt_entry_add_suggest(entry, cbuddy->alias);
+	}
+}
+
+static void
+finch_chat_rename_user(GaimConversation *conv, const char *old, const char *new_n, const char *new_a)
+{
+	/* Update the name for string completion */
+	FinchConv *ggc = conv->ui_data;
+	GntEntry *entry = GNT_ENTRY(ggc->entry);
+	gnt_entry_remove_suggest(entry, old);
+	gnt_entry_add_suggest(entry, new_n);
+	gnt_entry_add_suggest(entry, new_a);
+}
+
+static void
+finch_chat_remove_user(GaimConversation *conv, GList *list)
+{
+	/* Remove the name from string completion */
+	FinchConv *ggc = conv->ui_data;
+	GntEntry *entry = GNT_ENTRY(ggc->entry);
+	for (; list; list = list->next)
+		gnt_entry_remove_suggest(entry, list->data);
+}
+
+static void
+finch_chat_update_user(GaimConversation *conv, const char *user)
+{
+}
+
+static GaimConversationUiOps conv_ui_ops = 
+{
+	.create_conversation = finch_create_conversation,
+	.destroy_conversation = finch_destroy_conversation,
+	.write_chat = finch_write_chat,
+	.write_im = finch_write_im,
+	.write_conv = finch_write_conv,
+	.chat_add_users = finch_chat_add_users,
+	.chat_rename_user = finch_chat_rename_user,
+	.chat_remove_users = finch_chat_remove_user,
+	.chat_update_user = finch_chat_update_user,
+	.present = NULL,
+	.has_focus = NULL,
+	.custom_smiley_add = NULL,
+	.custom_smiley_write = NULL,
+	.custom_smiley_close = NULL
+};
+
+GaimConversationUiOps *finch_conv_get_ui_ops()
+{
+	return &conv_ui_ops;
+}
+
+/* Xerox */
+static GaimCmdRet
+say_command_cb(GaimConversation *conv,
+              const char *cmd, char **args, char **error, void *data)
+{
+	if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM)
+		gaim_conv_im_send(GAIM_CONV_IM(conv), args[0]);
+	else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT)
+		gaim_conv_chat_send(GAIM_CONV_CHAT(conv), args[0]);
+
+	return GAIM_CMD_RET_OK;
+}
+
+/* Xerox */
+static GaimCmdRet
+me_command_cb(GaimConversation *conv,
+              const char *cmd, char **args, char **error, void *data)
+{
+	char *tmp;
+
+	tmp = g_strdup_printf("/me %s", args[0]);
+
+	if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM)
+		gaim_conv_im_send(GAIM_CONV_IM(conv), tmp);
+	else if (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT)
+		gaim_conv_chat_send(GAIM_CONV_CHAT(conv), tmp);
+
+	g_free(tmp);
+	return GAIM_CMD_RET_OK;
+}
+
+/* Xerox */
+static GaimCmdRet
+debug_command_cb(GaimConversation *conv,
+                 const char *cmd, char **args, char **error, void *data)
+{
+	char *tmp, *markup;
+	GaimCmdStatus status;
+
+	if (!g_ascii_strcasecmp(args[0], "version")) {
+		tmp = g_strdup_printf("me is using %s.", VERSION);
+		markup = g_markup_escape_text(tmp, -1);
+
+		status = gaim_cmd_do_command(conv, tmp, markup, error);
+
+		g_free(tmp);
+		g_free(markup);
+		return status;
+	} else {
+		gaim_conversation_write(conv, NULL, _("Supported debug options are:  version"),
+		                        GAIM_MESSAGE_NO_LOG|GAIM_MESSAGE_ERROR, time(NULL));
+		return GAIM_CMD_STATUS_OK;
+	}
+}
+
+/* Xerox */
+static GaimCmdRet
+clear_command_cb(GaimConversation *conv,
+                 const char *cmd, char **args, char **error, void *data)
+{
+	FinchConv *ggconv = conv->ui_data;
+	gnt_text_view_clear(GNT_TEXT_VIEW(ggconv->tv));
+	return GAIM_CMD_STATUS_OK;
+}
+
+/* Xerox */
+static GaimCmdRet
+help_command_cb(GaimConversation *conv,
+                 const char *cmd, char **args, char **error, void *data)
+{
+	GList *l, *text;
+	GString *s;
+
+	if (args[0] != NULL) {
+		s = g_string_new("");
+		text = gaim_cmd_help(conv, args[0]);
+
+		if (text) {
+			for (l = text; l; l = l->next)
+				if (l->next)
+					g_string_append_printf(s, "%s\n", (char *)l->data);
+				else
+					g_string_append_printf(s, "%s", (char *)l->data);
+		} else {
+			g_string_append(s, _("No such command (in this context)."));
+		}
+	} else {
+		s = g_string_new(_("Use \"/help &lt;command&gt;\" for help on a specific command.\n"
+											 "The following commands are available in this context:\n"));
+
+		text = gaim_cmd_list(conv);
+		for (l = text; l; l = l->next)
+			if (l->next)
+				g_string_append_printf(s, "%s, ", (char *)l->data);
+			else
+				g_string_append_printf(s, "%s.", (char *)l->data);
+		g_list_free(text);
+	}
+
+	gaim_conversation_write(conv, NULL, s->str, GAIM_MESSAGE_NO_LOG, time(NULL));
+	g_string_free(s, TRUE);
+
+	return GAIM_CMD_STATUS_OK;
+}
+
+static GaimCmdRet
+cmd_show_window(GaimConversation *conv, const char *cmd, char **args, char **error, gpointer data)
+{
+	void (*callback)() = data;
+	callback();
+	return GAIM_CMD_STATUS_OK;
+}
+
+void finch_conversation_init()
+{
+	gaim_prefs_add_none(PREF_ROOT);
+	gaim_prefs_add_none(PREF_ROOT "/size");
+	gaim_prefs_add_int(PREF_ROOT "/size/width", 70);
+	gaim_prefs_add_int(PREF_ROOT "/size/height", 20);
+	gaim_prefs_add_none(PREF_ROOT "/position");
+	gaim_prefs_add_int(PREF_ROOT "/position/x", 0);
+	gaim_prefs_add_int(PREF_ROOT "/position/y", 0);
+
+	/* Xerox the commands */
+	gaim_cmd_register("say", "S", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+	                  say_command_cb, _("say &lt;message&gt;:  Send a message normally as if you weren't using a command."), NULL);
+	gaim_cmd_register("me", "S", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+	                  me_command_cb, _("me &lt;action&gt;:  Send an IRC style action to a buddy or chat."), NULL);
+	gaim_cmd_register("debug", "w", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+	                  debug_command_cb, _("debug &lt;option&gt;:  Send various debug information to the current conversation."), NULL);
+	gaim_cmd_register("clear", "", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+	                  clear_command_cb, _("clear: Clears the conversation scrollback."), NULL);
+	gaim_cmd_register("help", "w", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, NULL,
+	                  help_command_cb, _("help &lt;command&gt;:  Help on a specific command."), NULL);
+
+	/* Now some commands to bring up some other windows */
+	gaim_cmd_register("plugins", "", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+	                  cmd_show_window, _("plugins: Show the plugins window."), finch_plugins_show_all);
+	gaim_cmd_register("buddylist", "", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+	                  cmd_show_window, _("buddylist: Show the buddylist."), finch_blist_show);
+	gaim_cmd_register("accounts", "", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+	                  cmd_show_window, _("accounts: Show the accounts window."), finch_accounts_show_all);
+	gaim_cmd_register("debugwin", "", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+	                  cmd_show_window, _("debugwin: Show the debug window."), finch_debug_window_show);
+	gaim_cmd_register("prefs", "", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+	                  cmd_show_window, _("prefs: Show the preference window."), finch_prefs_show_all);
+	gaim_cmd_register("status", "", GAIM_CMD_P_DEFAULT,
+	                  GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+	                  cmd_show_window, _("statuses: Show the savedstatuses window."), finch_savedstatus_show_all);
+}
+
+void finch_conversation_uninit()
+{
+}
+
+void finch_conversation_set_active(GaimConversation *conv)
+{
+	FinchConv *ggconv = conv->ui_data;
+	GaimAccount *account;
+	char *title;
+
+	g_return_if_fail(ggconv);
+	g_return_if_fail(g_list_find(ggconv->list, conv));
+
+	ggconv->active_conv = conv;
+	account = gaim_conversation_get_account(conv);
+	title = get_conversation_title(conv, account);
+	gnt_screen_rename_widget(ggconv->window, title);
+	g_free(title);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntconv.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,94 @@
+/**
+ * @file gntconv.h GNT Conversation API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_CONV_H
+#define _GNT_CONV_H
+
+#include <gnt.h>
+#include <gntwidget.h>
+
+#include "conversation.h"
+
+/***************************************************************************
+ * @name GNT Conversations API
+ ***************************************************************************/
+/*@{*/
+
+typedef struct _FinchConv FinchConv;
+typedef struct _FinchConvChat FinchConvChat;
+typedef struct _FinchConvIm FinchConvIm;
+
+struct _FinchConv
+{
+	GList *list;
+	GaimConversation *active_conv;
+
+	GntWidget *window;        /* the container */
+	GntWidget *entry;         /* entry */
+	GntWidget *tv;            /* text-view */
+
+	union
+	{
+		FinchConvChat *chat;
+		FinchConvIm *im;
+	} u;
+};
+
+struct _FinchConvChat
+{
+	GntWidget *userlist;       /* the userlist */
+};
+
+struct _FinchConvIm
+{
+	void *nothing_for_now;
+};
+
+/**
+ * Get the ui-functions.
+ *
+ * @return The GaimConversationUiOps populated with the appropriate functions.
+ */
+GaimConversationUiOps *finch_conv_get_ui_ops(void);
+
+/**
+ * Perform the necessary initializations.
+ */
+void finch_conversation_init(void);
+
+/**
+ * Perform the necessary uninitializations.
+ */
+void finch_conversation_uninit(void);
+
+/**
+ * Set a conversation as active in a contactized conversation
+ *
+ * @param conv The conversation to make active.
+ */
+void finch_conversation_set_active(GaimConversation *conv);
+
+/*@}*/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntdebug.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,304 @@
+/**
+ * @file gntdebug.c GNT Debug API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <gnt.h>
+#include <gntbox.h>
+#include <gnttextview.h>
+#include <gntbutton.h>
+#include <gntcheckbox.h>
+#include <gntline.h>
+
+#include "gntdebug.h"
+#include "gntgaim.h"
+#include "util.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#define PREF_ROOT "/gaim/gnt/debug"
+
+static struct
+{
+	GntWidget *window;
+	GntWidget *tview;
+	gboolean paused;
+	gboolean timestamps;
+} debug;
+
+static gboolean
+debug_window_kpress_cb(GntWidget *wid, const char *key, GntTextView *view)
+{
+	if (key[0] == 27)
+	{
+		if (strcmp(key, GNT_KEY_DOWN) == 0)
+			gnt_text_view_scroll(view, 1);
+		else if (strcmp(key, GNT_KEY_UP) == 0)
+			gnt_text_view_scroll(view, -1);
+		else if (strcmp(key, GNT_KEY_PGDOWN) == 0)
+			gnt_text_view_scroll(view, wid->priv.height - 2);
+		else if (strcmp(key, GNT_KEY_PGUP) == 0)
+			gnt_text_view_scroll(view, -(wid->priv.height - 2));
+		else
+			return FALSE;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static void
+finch_debug_print(GaimDebugLevel level, const char *category,
+		const char *args)
+{
+	if (debug.window && !debug.paused)
+	{
+		int pos = gnt_text_view_get_lines_below(GNT_TEXT_VIEW(debug.tview));
+		GntTextFormatFlags flag = GNT_TEXT_FLAG_NORMAL;
+
+		if (debug.timestamps) {
+			const char *mdate;
+			time_t mtime = time(NULL);
+			mdate = gaim_utf8_strftime("%H:%M:%S ", localtime(&mtime));
+			gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(debug.tview),
+					mdate, flag);
+		}
+
+		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(debug.tview),
+				category, GNT_TEXT_FLAG_BOLD);
+		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(debug.tview),
+				": ", GNT_TEXT_FLAG_BOLD);
+
+		switch (level)
+		{
+			case GAIM_DEBUG_WARNING:
+				flag |= GNT_TEXT_FLAG_UNDERLINE;
+			case GAIM_DEBUG_ERROR:
+			case GAIM_DEBUG_FATAL:
+				flag |= GNT_TEXT_FLAG_BOLD;
+				break;
+			default:
+				break;
+		}
+
+		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(debug.tview), args, flag);
+		if (pos <= 1)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(debug.tview), 0);
+	}
+}
+
+static GaimDebugUiOps uiops =
+{
+	finch_debug_print,
+};
+
+GaimDebugUiOps *finch_debug_get_ui_ops()
+{
+	return &uiops;
+}
+
+static void
+reset_debug_win(GntWidget *w, gpointer null)
+{
+	debug.window = debug.tview = NULL;
+}
+
+static void
+clear_debug_win(GntWidget *w, GntTextView *tv)
+{
+	gnt_text_view_clear(tv);
+}
+
+static void
+print_stderr(const char *string)
+{
+	g_printerr("%s", string);
+}
+
+static void
+suppress_error_messages(const char *message)
+{}
+
+static void
+toggle_pause(GntWidget *w, gpointer n)
+{
+	debug.paused = !debug.paused;
+}
+
+static void
+toggle_timestamps(GntWidget *w, gpointer n)
+{
+	debug.timestamps = !debug.timestamps;
+	gaim_prefs_set_bool("/core/debug/timestamps", debug.timestamps);
+}
+
+/* Xerox */
+static void
+gaim_glib_log_handler(const gchar *domain, GLogLevelFlags flags,
+					  const gchar *msg, gpointer user_data)
+{
+	GaimDebugLevel level;
+	char *new_msg = NULL;
+	char *new_domain = NULL;
+
+	if ((flags & G_LOG_LEVEL_ERROR) == G_LOG_LEVEL_ERROR)
+		level = GAIM_DEBUG_ERROR;
+	else if ((flags & G_LOG_LEVEL_CRITICAL) == G_LOG_LEVEL_CRITICAL)
+		level = GAIM_DEBUG_FATAL;
+	else if ((flags & G_LOG_LEVEL_WARNING) == G_LOG_LEVEL_WARNING)
+		level = GAIM_DEBUG_WARNING;
+	else if ((flags & G_LOG_LEVEL_MESSAGE) == G_LOG_LEVEL_MESSAGE)
+		level = GAIM_DEBUG_INFO;
+	else if ((flags & G_LOG_LEVEL_INFO) == G_LOG_LEVEL_INFO)
+		level = GAIM_DEBUG_INFO;
+	else if ((flags & G_LOG_LEVEL_DEBUG) == G_LOG_LEVEL_DEBUG)
+		level = GAIM_DEBUG_MISC;
+	else
+	{
+		gaim_debug_warning("gntdebug",
+				   "Unknown glib logging level in %d\n", flags);
+
+		level = GAIM_DEBUG_MISC; /* This will never happen. */
+	}
+
+	if (msg != NULL)
+		new_msg = gaim_utf8_try_convert(msg);
+
+	if (domain != NULL)
+		new_domain = gaim_utf8_try_convert(domain);
+
+	if (new_msg != NULL)
+	{
+		gaim_debug(level, (new_domain != NULL ? new_domain : "g_log"),
+				   "%s\n", new_msg);
+
+		g_free(new_msg);
+	}
+
+	g_free(new_domain);
+}
+
+static void
+size_changed_cb(GntWidget *widget, int oldw, int oldh)
+{
+	int w, h;
+	gnt_widget_get_size(widget, &w, &h);
+	gaim_prefs_set_int(PREF_ROOT "/size/width", w);
+	gaim_prefs_set_int(PREF_ROOT "/size/height", h);
+}
+
+void finch_debug_window_show()
+{
+	debug.paused = FALSE;
+	debug.timestamps = gaim_prefs_get_bool("/core/debug/timestamps");
+	if (debug.window == NULL)
+	{
+		GntWidget *wid, *box;
+		debug.window = gnt_vbox_new(FALSE);
+		gnt_box_set_toplevel(GNT_BOX(debug.window), TRUE);
+		gnt_box_set_title(GNT_BOX(debug.window), _("Debug Window"));
+		gnt_box_set_pad(GNT_BOX(debug.window), 0);
+		gnt_box_set_alignment(GNT_BOX(debug.window), GNT_ALIGN_MID);
+
+		debug.tview = gnt_text_view_new();
+		gnt_box_add_widget(GNT_BOX(debug.window), debug.tview);
+		gnt_widget_set_size(debug.tview,
+				gaim_prefs_get_int(PREF_ROOT "/size/width"),
+				gaim_prefs_get_int(PREF_ROOT "/size/height"));
+		g_signal_connect(G_OBJECT(debug.tview), "size_changed", G_CALLBACK(size_changed_cb), NULL);
+
+		gnt_box_add_widget(GNT_BOX(debug.window), gnt_line_new(FALSE));
+
+		box = gnt_hbox_new(FALSE);
+		gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID);
+		gnt_box_set_fill(GNT_BOX(box), FALSE);
+
+		/* XXX: Setting the GROW_Y for the following widgets don't make sense. But right now
+		 * it's necessary to make the width of the debug window resizable ... like I said,
+		 * it doesn't make sense. The bug is likely in the packing in gntbox.c.
+		 */
+		wid = gnt_button_new(_("Clear"));
+		g_signal_connect(G_OBJECT(wid), "activate", G_CALLBACK(clear_debug_win), debug.tview);
+		GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y);
+		gnt_box_add_widget(GNT_BOX(box), wid);
+
+		wid = gnt_check_box_new(_("Pause"));
+		g_signal_connect(G_OBJECT(wid), "toggled", G_CALLBACK(toggle_pause), NULL);
+		GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y);
+		gnt_box_add_widget(GNT_BOX(box), wid);
+
+		wid = gnt_check_box_new(_("Timestamps"));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(wid), debug.timestamps);
+		g_signal_connect(G_OBJECT(wid), "toggled", G_CALLBACK(toggle_timestamps), NULL);
+		GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y);
+		gnt_box_add_widget(GNT_BOX(box), wid);
+
+		gnt_box_add_widget(GNT_BOX(debug.window), box);
+		GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_GROW_Y);
+
+		gnt_widget_set_name(debug.window, "debug-window");
+
+		g_signal_connect(G_OBJECT(debug.window), "destroy", G_CALLBACK(reset_debug_win), NULL);
+		g_signal_connect(G_OBJECT(debug.window), "key_pressed", G_CALLBACK(debug_window_kpress_cb), debug.tview);
+	}
+
+	gnt_widget_show(debug.window);
+}
+
+static gboolean
+start_with_debugwin(gpointer null)
+{
+	finch_debug_window_show();
+	return FALSE;
+}
+
+void finch_debug_init()
+{
+/* Xerox */
+#define REGISTER_G_LOG_HANDLER(name) \
+	g_log_set_handler((name), G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL \
+					  | G_LOG_FLAG_RECURSION, \
+					  gaim_glib_log_handler, NULL)
+
+	/* Register the glib log handlers. */
+	REGISTER_G_LOG_HANDLER(NULL);
+	REGISTER_G_LOG_HANDLER("GLib");
+	REGISTER_G_LOG_HANDLER("GModule");
+	REGISTER_G_LOG_HANDLER("GLib-GObject");
+	REGISTER_G_LOG_HANDLER("GThread");
+
+	g_set_print_handler(print_stderr);   /* Redirect the debug messages to stderr */
+	g_set_printerr_handler(suppress_error_messages);
+
+	gaim_prefs_add_none(PREF_ROOT);
+	gaim_prefs_add_none(PREF_ROOT "/size");
+	gaim_prefs_add_int(PREF_ROOT "/size/width", 60);
+	gaim_prefs_add_int(PREF_ROOT "/size/height", 15);
+
+	if (gaim_debug_is_enabled())
+		g_timeout_add(0, start_with_debugwin, NULL);
+}
+
+void finch_debug_uninit()
+{
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntdebug.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,59 @@
+/**
+ * @file gntdebug.h GNT Debug API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_DEBUG_H
+#define _GNT_DEBUG_H
+
+#include "debug.h"
+
+/**********************************************************************
+ * @name GNT Debug API
+ **********************************************************************/
+/*@{*/
+
+/**
+ * Get the ui-functions.
+ *
+ * @return The GaimDebugUiOps structure populated with the appropriate functions.
+ */
+GaimDebugUiOps *finch_debug_get_ui_ops(void);
+
+/**
+ * Perform necessary initializations.
+ */
+void finch_debug_init(void);
+
+/**
+ * Perform necessary uninitializations.
+ */
+void finch_debug_uninit(void);
+
+/**
+ * Show the debug window.
+ */
+void finch_debug_window_show(void);
+
+/*@}*/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntft.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,532 @@
+/**
+ * @file gntft.c GNT File Transfer UI
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntcheckbox.h>
+#include <gntlabel.h>
+#include <gnttree.h>
+#include "internal.h"
+
+#include "debug.h"
+#include "notify.h"
+#include "ft.h"
+#include "prpl.h"
+#include "util.h"
+
+#include "gntft.h"
+#include "prefs.h"
+
+#define GAIM_GNTXFER(xfer) \
+	(GaimGntXferUiData *)(xfer)->ui_data
+
+typedef struct
+{
+	gboolean keep_open;
+	gboolean auto_clear;
+	gint num_transfers;
+
+	GntWidget *window;
+	GntWidget *tree;
+
+	GntWidget *remove_button;
+	GntWidget *stop_button;
+	GntWidget *close_button;
+} GaimGntXferDialog;
+
+static GaimGntXferDialog *xfer_dialog = NULL;
+
+typedef struct
+{
+	time_t last_updated_time;
+	gboolean in_list;
+
+	char *name;
+
+} GaimGntXferUiData;
+
+enum
+{
+	COLUMN_PROGRESS = 0,
+	COLUMN_FILENAME,
+	COLUMN_SIZE,
+	COLUMN_SPEED,
+	COLUMN_REMAINING,
+	COLUMN_STATUS,
+	NUM_COLUMNS
+};
+
+
+/**************************************************************************
+ * Utility Functions
+ **************************************************************************/
+
+static void
+update_title_progress()
+{
+	const GList *list;
+	int num_active_xfers = 0;
+	guint64 total_bytes_xferred = 0;
+	guint64 total_file_size = 0;
+
+	if (xfer_dialog == NULL || xfer_dialog->window == NULL)
+		return;
+
+	/* Find all active transfers */
+	for (list = gnt_tree_get_rows(GNT_TREE(xfer_dialog->tree)); list; list = list->next) {
+		GaimXfer *xfer = (GaimXfer *)list->data;
+
+		if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_STARTED) {
+			num_active_xfers++;
+			total_bytes_xferred += gaim_xfer_get_bytes_sent(xfer);
+			total_file_size += gaim_xfer_get_size(xfer);
+		}
+	}
+
+	/* Update the title */
+	if (num_active_xfers > 0) {
+		gchar *title;
+		int total_pct = 0;
+
+		if (total_file_size > 0) {
+			total_pct = 100 * total_bytes_xferred / total_file_size;
+		}
+
+		title = g_strdup_printf(_("File Transfers - %d%% of %d files"),
+				total_pct, num_active_xfers);
+		gnt_screen_rename_widget((xfer_dialog->window), title);
+		g_free(title);
+	} else {
+		gnt_screen_rename_widget((xfer_dialog->window), _("File Transfers"));
+	}
+}
+
+
+/**************************************************************************
+ * Callbacks
+ **************************************************************************/
+static void
+toggle_keep_open_cb(GntWidget *w)
+{
+	xfer_dialog->keep_open = !xfer_dialog->keep_open;
+	gaim_prefs_set_bool("/gaim/gnt/filetransfer/keep_open",
+						xfer_dialog->keep_open);
+}
+
+static void
+toggle_clear_finished_cb(GntWidget *w)
+{
+	xfer_dialog->auto_clear = !xfer_dialog->auto_clear;
+	gaim_prefs_set_bool("/gaim/gnt/filetransfer/clear_finished",
+						xfer_dialog->auto_clear);
+}
+
+static void
+remove_button_cb(GntButton *button)
+{
+	GaimXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree));
+	if (selected_xfer && (selected_xfer->status == GAIM_XFER_STATUS_CANCEL_LOCAL ||
+			selected_xfer->status == GAIM_XFER_STATUS_CANCEL_REMOTE ||
+			selected_xfer->status == GAIM_XFER_STATUS_DONE)) {
+		finch_xfer_dialog_remove_xfer(selected_xfer);
+	}
+}
+
+static void
+stop_button_cb(GntButton *button)
+{
+	GaimXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree));
+	if (selected_xfer && selected_xfer->status == GAIM_XFER_STATUS_STARTED)
+		gaim_xfer_cancel_local(selected_xfer);
+}
+
+#if 0
+static void
+tree_selection_changed_cb(GntTree *tree, GntTreeRow *old, GntTreeRow *current, gpointer n)
+{
+	xfer_dialog->selected_xfer = (GaimXfer *)gnt_tree_get_selection_data(tree);
+}
+#endif
+
+/**************************************************************************
+ * Dialog Building Functions
+ **************************************************************************/
+
+
+void
+finch_xfer_dialog_new(void)
+{
+	const GList *iter;
+	GntWidget *window;
+	GntWidget *bbox;
+	GntWidget *button;
+	GntWidget *checkbox;
+	GntWidget *tree;
+
+	if (!xfer_dialog)
+		xfer_dialog = g_new0(GaimGntXferDialog, 1);
+
+	xfer_dialog->keep_open =
+		gaim_prefs_get_bool("/gaim/gnt/filetransfer/keep_open");
+	xfer_dialog->auto_clear =
+		gaim_prefs_get_bool("/gaim/gnt/filetransfer/clear_finished");
+
+	/* Create the window. */
+	xfer_dialog->window = window = gnt_vbox_new(FALSE);
+	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(finch_xfer_dialog_destroy), NULL);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_title(GNT_BOX(window), _("File Transfers"));
+
+	xfer_dialog->tree = tree = gnt_tree_new_with_columns(NUM_COLUMNS);
+	gnt_tree_set_column_titles(GNT_TREE(tree), _("Progress"), _("Filename"), _("Size"), _("Speed"), _("Remaining"), _("Status"));
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_PROGRESS, 8);
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_FILENAME, 8);
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_SIZE, 10);
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_SPEED, 10);
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_REMAINING, 10);
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_STATUS, 10);
+	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
+	gnt_box_add_widget(GNT_BOX(window), tree);
+	/*g_signal_connect(G_OBJECT(tree), "selection-changed",*/
+					/*G_CALLBACK(tree_selection_changed_cb), NULL);*/
+	checkbox = gnt_check_box_new( _("Close this window when all transfers finish"));
+	gnt_check_box_set_checked(GNT_CHECK_BOX(checkbox),
+								 !xfer_dialog->keep_open);
+	g_signal_connect(G_OBJECT(checkbox), "toggled",
+					 G_CALLBACK(toggle_keep_open_cb), NULL);
+	gnt_box_add_widget(GNT_BOX(window), checkbox);
+
+	checkbox = gnt_check_box_new(_("Clear finished transfers"));
+	gnt_check_box_set_checked(GNT_CHECK_BOX(checkbox),
+								 xfer_dialog->auto_clear);
+	g_signal_connect(G_OBJECT(checkbox), "toggled",
+					 G_CALLBACK(toggle_clear_finished_cb), NULL);
+	gnt_box_add_widget(GNT_BOX(window), checkbox);
+
+	bbox = gnt_hbox_new(TRUE);
+
+	xfer_dialog->remove_button = button = gnt_button_new(_("Remove"));
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(remove_button_cb), NULL);
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+
+	xfer_dialog->stop_button = button = gnt_button_new(_("Stop"));
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(stop_button_cb), NULL);
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+
+	xfer_dialog->close_button = button = gnt_button_new(_("Close"));
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(finch_xfer_dialog_destroy), NULL);
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+
+	gnt_box_add_widget(GNT_BOX(window), bbox);
+
+	for (iter = gaim_xfers_get_all(); iter; iter = iter->next) {
+		GaimXfer *xfer = (GaimXfer *)iter->data;
+		GaimGntXferUiData *data = GAIM_GNTXFER(xfer);
+		if (data->in_list) {
+			finch_xfer_dialog_add_xfer(xfer);
+			finch_xfer_dialog_update_xfer(xfer);
+			gnt_tree_set_selected(GNT_TREE(tree), xfer);
+		}
+	}
+	gnt_widget_show(xfer_dialog->window);
+}
+
+void
+finch_xfer_dialog_destroy()
+{
+	gnt_widget_destroy(xfer_dialog->window);
+	g_free(xfer_dialog);
+	xfer_dialog = NULL;
+}
+
+void
+finch_xfer_dialog_show()
+{
+	if (xfer_dialog == NULL)
+		finch_xfer_dialog_new();
+}
+
+void
+finch_xfer_dialog_add_xfer(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+	GaimXferType type;
+	char *size_str, *remaining_str;
+	char *lfilename, *utf8;
+
+	g_return_if_fail(xfer_dialog != NULL);
+	g_return_if_fail(xfer != NULL);
+
+	gaim_xfer_ref(xfer);
+
+	data = GAIM_GNTXFER(xfer);
+	data->in_list = TRUE;
+
+	finch_xfer_dialog_show();
+
+	data->last_updated_time = 0;
+
+	type = gaim_xfer_get_type(xfer);
+
+	size_str      = gaim_str_size_to_units(gaim_xfer_get_size(xfer));
+	remaining_str = gaim_str_size_to_units(gaim_xfer_get_bytes_remaining(xfer));
+
+	lfilename = g_path_get_basename(gaim_xfer_get_local_filename(xfer));
+	utf8 = g_filename_to_utf8(lfilename, -1, NULL, NULL, NULL);
+	g_free(lfilename);
+	lfilename = utf8;
+	gnt_tree_add_row_last(GNT_TREE(xfer_dialog->tree), xfer,
+		gnt_tree_create_row(GNT_TREE(xfer_dialog->tree),
+			"0.0", (type == GAIM_XFER_RECEIVE) ? gaim_xfer_get_filename(xfer) : lfilename,
+			size_str, "0.0", "",_("Waiting for transfer to begin")), NULL);
+	g_free(lfilename);
+
+	g_free(size_str);
+	g_free(remaining_str);
+
+	xfer_dialog->num_transfers++;
+
+	update_title_progress();
+}
+
+void
+finch_xfer_dialog_remove_xfer(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+
+	g_return_if_fail(xfer_dialog != NULL);
+	g_return_if_fail(xfer != NULL);
+
+	data = GAIM_GNTXFER(xfer);
+
+	if (data == NULL)
+		return;
+
+	if (!data->in_list)
+		return;
+
+	data->in_list = FALSE;
+
+	gnt_tree_remove(GNT_TREE(xfer_dialog->tree), xfer);
+
+	xfer_dialog->num_transfers--;
+
+	if (xfer_dialog->num_transfers == 0 && !xfer_dialog->keep_open)
+		finch_xfer_dialog_destroy();
+	else 
+		update_title_progress();
+	gaim_xfer_unref(xfer);
+}
+
+void
+finch_xfer_dialog_cancel_xfer(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+	const gchar *status;
+
+	g_return_if_fail(xfer_dialog != NULL);
+	g_return_if_fail(xfer != NULL);
+
+	data = GAIM_GNTXFER(xfer);
+
+	if (data == NULL)
+		return;
+
+	if (!data->in_list)
+		return;
+
+	if ((gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) && (xfer_dialog->auto_clear)) {
+		finch_xfer_dialog_remove_xfer(xfer);
+		return;
+	}
+
+	data = GAIM_GNTXFER(xfer);
+
+	update_title_progress();
+
+	if (gaim_xfer_is_canceled(xfer))
+		status = _("Canceled");
+	else
+		status = _("Failed");
+
+	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, status);
+}
+
+void
+finch_xfer_dialog_update_xfer(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+	char *size_str, *remaining_str;
+	time_t current_time;
+	char prog_str[5];
+	double kb_sent, kb_rem;
+	double kbps = 0.0;
+	time_t elapsed, now;
+	char *kbsec;
+
+	if (xfer->end_time != 0)
+		now = xfer->end_time;
+	else
+		now = time(NULL);
+
+	kb_sent = gaim_xfer_get_bytes_sent(xfer) / 1024.0;
+	kb_rem  = gaim_xfer_get_bytes_remaining(xfer) / 1024.0;
+	elapsed = (xfer->start_time > 0 ? now - xfer->start_time : 0);
+	kbps    = (elapsed > 0 ? (kb_sent / elapsed) : 0);
+
+	kbsec = g_strdup_printf(_("%.2f KB/s"), kbps);
+
+	g_return_if_fail(xfer_dialog != NULL);
+	g_return_if_fail(xfer != NULL);
+
+	if ((data = GAIM_GNTXFER(xfer)) == NULL)
+		return;
+
+	if (data->in_list == FALSE)
+		return;
+
+	current_time = time(NULL);
+	if (((current_time - data->last_updated_time) == 0) &&
+		(!gaim_xfer_is_completed(xfer))) {
+		/* Don't update the window more than once per second */
+		return;
+	}
+	data->last_updated_time = current_time;
+
+	size_str      = gaim_str_size_to_units(gaim_xfer_get_size(xfer));
+	remaining_str = gaim_str_size_to_units(gaim_xfer_get_bytes_remaining(xfer));
+
+	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_PROGRESS,
+			g_ascii_dtostr(prog_str, sizeof(prog_str), gaim_xfer_get_progress(xfer) * 100.));
+	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SIZE, size_str);
+	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_REMAINING, remaining_str);
+	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SPEED, kbsec);
+	g_free(size_str);
+	g_free(remaining_str);
+	if (gaim_xfer_is_completed(xfer)) {
+		gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Finished"));
+	} else {
+		gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Transferring"));
+	}
+
+	update_title_progress();
+
+	if (gaim_xfer_is_completed(xfer) && xfer_dialog->auto_clear)
+		finch_xfer_dialog_remove_xfer(xfer);
+}
+
+/**************************************************************************
+ * File Transfer UI Ops
+ **************************************************************************/
+static void
+finch_xfer_new_xfer(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+
+	/* This is where we're setting xfer->ui_data for the first time. */
+	data = g_new0(GaimGntXferUiData, 1);
+	xfer->ui_data = data;
+}
+
+static void
+finch_xfer_destroy(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+
+	data = GAIM_GNTXFER(xfer);
+	if (data) {
+		g_free(data->name);
+		g_free(data);
+		xfer->ui_data = NULL;
+	}
+}
+
+static void
+finch_xfer_add_xfer(GaimXfer *xfer)
+{
+	if (!xfer_dialog)
+		finch_xfer_dialog_new();
+
+	finch_xfer_dialog_add_xfer(xfer);
+	gnt_tree_set_selected(GNT_TREE(xfer_dialog->tree), xfer);
+}
+
+static void
+finch_xfer_update_progress(GaimXfer *xfer, double percent)
+{
+	if (xfer_dialog)
+		finch_xfer_dialog_update_xfer(xfer);
+}
+
+static void
+finch_xfer_cancel_local(GaimXfer *xfer)
+{
+	if (xfer_dialog)
+		finch_xfer_dialog_cancel_xfer(xfer);
+}
+
+static void
+finch_xfer_cancel_remote(GaimXfer *xfer)
+{
+	if (xfer_dialog)
+		finch_xfer_dialog_cancel_xfer(xfer);
+}
+
+static GaimXferUiOps ops =
+{
+	finch_xfer_new_xfer,
+	finch_xfer_destroy,
+	finch_xfer_add_xfer,
+	finch_xfer_update_progress,
+	finch_xfer_cancel_local,
+	finch_xfer_cancel_remote
+};
+
+/**************************************************************************
+ * GNT File Transfer API
+ **************************************************************************/
+void
+finch_xfers_init(void)
+{
+	gaim_prefs_add_none("/gaim/gnt/filetransfer");
+	gaim_prefs_add_bool("/gaim/gnt/filetransfer/clear_finished", TRUE);
+	gaim_prefs_add_bool("/gaim/gnt/filetransfer/keep_open", FALSE);
+}
+
+void
+finch_xfers_uninit(void)
+{
+	if (xfer_dialog != NULL)
+		finch_xfer_dialog_destroy();
+}
+
+GaimXferUiOps *
+finch_xfers_get_ui_ops(void)
+{
+	return &ops;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntft.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,123 @@
+/**
+ * @file gntft.h GNT File Transfer UI
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GAIM_GNTFT_H_
+#define _GAIM_GNTFT_H_
+
+#include "ft.h"
+
+
+/**************************************************************************/
+/** @name GNT File Transfer Dialog API                                    */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Creates a new file transfer dialog.
+ *
+ * @return The new dialog.
+ */
+void finch_xfer_dialog_new(void);
+
+/**
+ * Destroys a file transfer dialog.
+ *
+ * @param dialog The file transfer dialog.
+ */
+void finch_xfer_dialog_destroy(void);
+
+/**
+ * Displays the file transfer dialog given.
+ * If dialog is @c NULL, displays the default dialog, creating one if necessary
+ *
+ * @param dialog The file transfer dialog to show.
+ */
+void finch_xfer_dialog_show(void);
+
+/**
+ * Hides the file transfer dialog.
+ *
+ * @param dialog The file transfer dialog to hide.
+ */
+void finch_xfer_dialog_hide();
+
+/**
+ * Adds a file transfer to the dialog.
+ *
+ * @param dialog The file transfer dialog.
+ * @param xfer   The file transfer.
+ */
+void finch_xfer_dialog_add_xfer(GaimXfer *xfer);
+
+/**
+ * Removes a file transfer from the dialog.
+ *
+ * @param dialog The file transfer dialog.
+ * @param xfer   The file transfer.
+ */
+void finch_xfer_dialog_remove_xfer(GaimXfer *xfer);
+
+/**
+ * Indicate in a file transfer dialog that a transfer was canceled.
+ *
+ * @param dialog The file transfer dialog.
+ * @param xfer   The file transfer that was canceled.
+ */
+void finch_xfer_dialog_cancel_xfer(GaimXfer *xfer);
+
+/**
+ * Updates the information for a transfer in the dialog.
+ *
+ * @param dialog The file transfer dialog.
+ * @param xfer   The file transfer.
+ */
+void finch_xfer_dialog_update_xfer(GaimXfer *xfer);
+
+/*@}*/
+
+/**************************************************************************/
+/** @name GNT  File Transfer API                                          */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Initializes the GNT file transfer system.
+ */
+void finch_xfers_init(void);
+
+/**
+ * Uninitializes the GNT file transfer system.
+ */
+void finch_xfers_uninit(void);
+
+/**
+ * Returns the UI operations structure for the GNT file transfer UI.
+ *
+ * @return The GNT file transfer UI operations structure.
+ */
+GaimXferUiOps *finch_xfers_get_ui_ops(void);
+
+/*@}*/
+
+#endif /* _GAIM_GNTFT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntgaim.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,417 @@
+/**
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#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 "prefix.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 "gntdebug.h"
+#include "gntgaim.h"
+#include "gntprefs.h"
+#include "gntui.h"
+#include "gntidle.h"
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include "config.h"
+
+static void
+debug_init()
+{
+	finch_debug_init();
+	gaim_debug_set_ui_ops(finch_debug_get_ui_ops());
+}
+
+static GaimCoreUiOps core_ops =
+{
+	finch_prefs_init,
+	debug_init,
+	gnt_ui_init,
+	gnt_ui_uninit
+};
+
+static GaimCoreUiOps *
+gnt_core_get_ui_ops()
+{
+	return &core_ops;
+}
+
+/* Anything IO-related is directly copied from gtkgaim's source tree */
+
+#define GAIM_GNT_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
+#define GAIM_GNT_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
+
+typedef struct _GaimGntIOClosure {
+	GaimInputFunction function;
+	guint result;
+	gpointer data;
+
+} GaimGntIOClosure;
+
+static void gaim_gnt_io_destroy(gpointer data)
+{
+	g_free(data);
+}
+
+static gboolean gaim_gnt_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+	GaimGntIOClosure *closure = data;
+	GaimInputCondition gaim_cond = 0;
+
+	if (condition & GAIM_GNT_READ_COND)
+		gaim_cond |= GAIM_INPUT_READ;
+	if (condition & GAIM_GNT_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_misc("gnt_eventloop",
+			   "CLOSURE received GIOCondition of 0x%x, which does not"
+			   " match 0x%x (READ) or 0x%x (WRITE)\n",
+			   condition, GAIM_GNT_READ_COND, GAIM_GNT_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)
+{
+	GaimGntIOClosure *closure = g_new0(GaimGntIOClosure, 1);
+	GIOChannel *channel;
+	GIOCondition cond = 0;
+
+	closure->function = function;
+	closure->data = data;
+
+	if (condition & GAIM_INPUT_READ)
+		cond |= GAIM_GNT_READ_COND;
+	if (condition & GAIM_INPUT_WRITE)
+		cond |= GAIM_GNT_WRITE_COND;
+
+	channel = g_io_channel_unix_new(fd);
+	closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
+					      gaim_gnt_io_invoke, closure, gaim_gnt_io_destroy);
+
+	g_io_channel_unref(channel);
+	return closure->result;
+}
+
+static GaimEventLoopUiOps eventloop_ops =
+{
+	g_timeout_add,
+	g_source_remove,
+	gnt_input_add,
+	g_source_remove,
+	NULL /* input_get_error */
+};
+
+static GaimEventLoopUiOps *
+gnt_eventloop_get_ui_ops(void)
+{
+	return &eventloop_ops;
+}
+
+/* This is copied from gtkgaim */
+static char *
+gnt_find_binary_location(void *symbol, void *data)
+{
+	static char *fullname = NULL;
+	static gboolean first = TRUE;
+
+	char *argv0 = data;
+	struct stat st;
+	char *basebuf, *linkbuf, *fullbuf;
+
+	if (!first)
+		/* We've already been through this. */
+		return strdup(fullname);
+
+	first = FALSE;
+
+	if (!argv0)
+		return NULL;
+
+
+	basebuf = g_find_program_in_path(argv0);
+
+	/* But we still need to deal with symbolic links */
+	g_lstat(basebuf, &st);
+	while ((st.st_mode & S_IFLNK) == S_IFLNK) {
+		int written;
+		linkbuf = g_malloc(1024);
+		written = readlink(basebuf, linkbuf, 1024 - 1);
+		if (written == -1)
+		{
+			/* This really shouldn't happen, but do we
+			 * need something better here? */
+			g_free(linkbuf);
+			continue;
+		}
+		linkbuf[written] = '\0';
+		if (linkbuf[0] == G_DIR_SEPARATOR) {
+			/* an absolute path */
+			fullbuf = g_strdup(linkbuf);
+		} else {
+			char *dirbuf = g_path_get_dirname(basebuf);
+			/* a relative path */
+			fullbuf = g_strdup_printf("%s%s%s",
+					dirbuf, G_DIR_SEPARATOR_S,
+					linkbuf);
+			g_free(dirbuf);
+		}
+		/* There's no memory leak here.  Really! */
+		g_free(linkbuf);
+		g_free(basebuf);
+		basebuf = fullbuf;
+		g_lstat(basebuf, &st);
+	}
+
+	fullname = basebuf;
+	return strdup(fullname);
+}
+
+
+/* This is mostly copied from gtkgaim's source tree */
+static void
+show_usage(const char *name, gboolean terse)
+{
+	char *text;
+
+	if (terse) {
+		text = g_strdup_printf(_("%s. Try `%s -h' for more information.\n"), VERSION, name);
+	} else {
+		text = g_strdup_printf(_("%s\n"
+		       "Usage: %s [OPTION]...\n\n"
+		       "  -c, --config=DIR    use DIR for config files\n"
+		       "  -d, --debug         print debugging messages to stdout\n"
+		       "  -h, --help          display this help and exit\n"
+		       "  -n, --nologin       don't automatically login\n"
+		       "  -v, --version       display the current version and exit\n"), VERSION, name);
+	}
+
+	gaim_print_utf8_to_console(stdout, text);
+	g_free(text);
+}
+
+static int
+init_libgaim(int argc, char **argv)
+{
+	char *path;
+	int opt;
+	gboolean opt_help = FALSE;
+	gboolean opt_nologin = FALSE;
+	gboolean opt_version = FALSE;
+	char *opt_config_dir_arg = NULL;
+	char *opt_session_arg = NULL;
+	gboolean debug_enabled = FALSE;
+
+	struct option long_options[] = {
+		{"config",   required_argument, NULL, 'c'},
+		{"debug",    no_argument,       NULL, 'd'},
+		{"help",     no_argument,       NULL, 'h'},
+		{"nologin",  no_argument,       NULL, 'n'},
+		{"session",  required_argument, NULL, 's'},
+		{"version",  no_argument,       NULL, 'v'},
+		{0, 0, 0, 0}
+	};
+
+	gaim_br_set_locate_fallback_func(gnt_find_binary_location, argv[0]);
+
+#ifdef ENABLE_NLS
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	bind_textdomain_codeset(PACKAGE, "UTF-8");
+	textdomain(PACKAGE);
+#endif
+
+#ifdef HAVE_SETLOCALE
+	setlocale(LC_ALL, "");
+#endif
+
+	/* scan command-line options */
+	opterr = 1;
+	while ((opt = getopt_long(argc, argv,
+#ifndef _WIN32
+				  "c:dhn::s:v",
+#else
+				  "c:dhn::v",
+#endif
+				  long_options, NULL)) != -1) {
+		switch (opt) {
+		case 'c':	/* config dir */
+			g_free(opt_config_dir_arg);
+			opt_config_dir_arg = g_strdup(optarg);
+			break;
+		case 'd':	/* debug */
+			debug_enabled = TRUE;
+			break;
+		case 'h':	/* help */
+			opt_help = TRUE;
+			break;
+		case 'n':	/* no autologin */
+			opt_nologin = TRUE;
+			break;
+		case 's':	/* use existing session ID */
+			g_free(opt_session_arg);
+			opt_session_arg = g_strdup(optarg);
+			break;
+		case 'v':	/* version */
+			opt_version = TRUE;
+			break;
+		case '?':	/* show terse help */
+		default:
+			show_usage(argv[0], TRUE);
+			return 0;
+			break;
+		}
+	}
+
+	/* show help message */
+	if (opt_help) {
+		show_usage(argv[0], FALSE);
+		return 0;
+	}
+	/* show version message */
+	if (opt_version) {
+		printf("gaim-text %s\n", VERSION);
+		return 0;
+	}
+
+	/* set a user-specified config directory */
+	if (opt_config_dir_arg != NULL) {
+		gaim_util_set_user_dir(opt_config_dir_arg);
+		g_free(opt_config_dir_arg);
+	}
+
+	/*
+	 * We're done piddling around with command line arguments.
+	 * Fire up this baby.
+	 */
+
+	/* Because we don't want debug-messages to show up and corrup the display */
+	gaim_debug_set_enabled(debug_enabled);
+
+	gaim_core_set_ui_ops(gnt_core_get_ui_ops());
+	gaim_eventloop_set_ui_ops(gnt_eventloop_get_ui_ops());
+	gaim_idle_set_ui_ops(finch_idle_get_ui_ops());
+
+	path = g_build_filename(gaim_user_dir(), "plugins", NULL);
+	gaim_plugins_add_search_path(path);
+	g_free(path);
+
+	gaim_plugins_add_search_path(LIBDIR);
+
+	if (!gaim_core_init(GAIM_GNT_UI))
+	{
+		fprintf(stderr,
+				"Initialization of the Gaim core failed. Dumping core.\n"
+				"Please report this!\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/gnt/plugins/loaded");
+
+	/* TODO: Move pounces loading into gaim_pounces_init() */
+	gaim_pounces_load();
+
+	if (opt_nologin)
+	{
+		/* Set all accounts to "offline" */
+		GaimSavedStatus *saved_status;
+
+		/* If we've used this type+message before, lookup the transient status */
+		saved_status = gaim_savedstatus_find_transient_by_type_and_message(
+							GAIM_STATUS_OFFLINE, NULL);
+
+		/* If this type+message is unique then create a new transient saved status */
+		if (saved_status == NULL)
+			saved_status = gaim_savedstatus_new(NULL, GAIM_STATUS_OFFLINE);
+
+		/* Set the status for each account */
+		gaim_savedstatus_activate(saved_status);
+	}
+	else
+	{
+		/* Everything is good to go--sign on already */
+		if (!gaim_prefs_get_bool("/core/savedstatus/startup_current_status"))
+			gaim_savedstatus_activate(gaim_savedstatus_get_startup());
+		gaim_accounts_restore_current_statuses();
+	}
+
+	return 1;
+}
+
+int main(int argc, char **argv)
+{
+	signal(SIGPIPE, SIG_IGN);
+
+	/* Initialize the libgaim stuff */
+	if (!init_libgaim(argc, argv))
+		return 0;
+
+	gaim_blist_show();
+	gnt_main();
+
+#ifdef STANDALONE
+	gaim_core_quit();
+#endif
+
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntgaim.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,27 @@
+/**
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <glib.h>
+
+#include "libpurple/internal.h"
+
+#define GAIM_GNT_UI "gnt-gaim"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntidle.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,45 @@
+/*
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "internal.h"
+#include "gntidle.h"
+#include "gntwm.h"
+
+#include "idle.h"
+
+static time_t
+finch_get_idle_time()
+{
+	return gnt_wm_get_idle_time();
+}
+
+static GaimIdleUiOps ui_ops =
+{
+	finch_get_idle_time
+};
+
+GaimIdleUiOps *
+finch_idle_get_ui_ops()
+{
+	return &ui_ops;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntidle.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,44 @@
+/**
+ * @file gntidle.h GNT Idle API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_IDLE_H_
+#define _GNT_IDLE_H_
+
+#include "idle.h"
+
+/**************************************************************************/
+/** @name GNT Idle API                                                    */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Returns the GNT idle UI ops.
+ *
+ * @return The UI operations structure.
+ */
+GaimIdleUiOps *finch_idle_get_ui_ops(void);
+
+/*@}*/
+
+#endif /* _Finch_IDLE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntnotify.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,374 @@
+/**
+ * @file gntnotify.c GNT Notify API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntlabel.h>
+#include <gnttree.h>
+
+#include <util.h>
+
+#include "gntnotify.h"
+#include "gntgaim.h"
+
+static struct
+{
+	GntWidget *window;
+	GntWidget *tree;
+} emaildialog;
+
+static void
+notify_msg_window_destroy_cb(GntWidget *window, GaimNotifyMsgType type)
+{
+	gaim_notify_close(type, window);
+}
+
+static void *
+finch_notify_message(GaimNotifyMsgType type, const char *title,
+		const char *primary, const char *secondary)
+{
+	GntWidget *window, *button;
+	GntTextFormatFlags pf = 0, sf = 0;
+
+	switch (type)
+	{
+		case GAIM_NOTIFY_MSG_ERROR:
+			sf |= GNT_TEXT_FLAG_BOLD;
+		case GAIM_NOTIFY_MSG_WARNING:
+			pf |= GNT_TEXT_FLAG_UNDERLINE;
+		case GAIM_NOTIFY_MSG_INFO:
+			pf |= GNT_TEXT_FLAG_BOLD;
+			break;
+	}
+
+	window = gnt_box_new(FALSE, TRUE);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_title(GNT_BOX(window), title);
+	gnt_box_set_fill(GNT_BOX(window), FALSE);
+	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
+
+	if (primary)
+		gnt_box_add_widget(GNT_BOX(window),
+				gnt_label_new_with_format(primary, pf));
+	if (secondary)
+		gnt_box_add_widget(GNT_BOX(window),
+				gnt_label_new_with_format(secondary, sf));
+
+	button = gnt_button_new(_("OK"));
+	gnt_box_add_widget(GNT_BOX(window), button);
+	g_signal_connect_swapped(G_OBJECT(button), "activate",
+			G_CALLBACK(gnt_widget_destroy), window);
+	g_signal_connect(G_OBJECT(window), "destroy",
+			G_CALLBACK(notify_msg_window_destroy_cb), GINT_TO_POINTER(type));
+
+	gnt_widget_show(window);
+	return window;
+}
+
+/* handle is, in all/most occasions, a GntWidget * */
+static void finch_close_notify(GaimNotifyType type, void *handle)
+{
+	GntWidget *widget = handle;
+
+	if (!widget)
+		return;
+
+	while (widget->parent)
+		widget = widget->parent;
+	
+	if (type == GAIM_NOTIFY_SEARCHRESULTS)
+		gaim_notify_searchresults_free(g_object_get_data(handle, "notify-results"));
+#if 1
+	/* This did not seem to be necessary */
+	g_signal_handlers_disconnect_by_func(G_OBJECT(widget),
+			G_CALLBACK(notify_msg_window_destroy_cb), GINT_TO_POINTER(type));
+#endif
+	gnt_widget_destroy(widget);
+}
+
+static void *finch_notify_formatted(const char *title, const char *primary,
+		const char *secondary, const char *text)
+{
+	/* XXX: For now, simply strip the html and use _notify_message. For future use,
+	 * there should be some way of parsing the makrups from GntTextView */
+	char *unformat = gaim_markup_strip_html(text);
+	char *t = g_strdup_printf("%s%s%s",
+			secondary ? secondary : "",
+			secondary ? "\n" : "",
+			unformat ? unformat : "");
+
+	void *ret = finch_notify_message(GAIM_NOTIFY_FORMATTED, title, primary, t);
+
+	g_free(t);
+	g_free(unformat);
+
+	return ret;
+}
+
+static void
+reset_email_dialog()
+{
+	emaildialog.window = NULL;
+	emaildialog.tree = NULL;
+}
+
+static void
+setup_email_dialog()
+{
+	GntWidget *box, *tree, *button;
+	if (emaildialog.window)
+		return;
+
+	emaildialog.window = box = gnt_vbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(box), TRUE);
+	gnt_box_set_title(GNT_BOX(box), _("Emails"));
+	gnt_box_set_fill(GNT_BOX(box), FALSE);
+	gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID);
+	gnt_box_set_pad(GNT_BOX(box), 0);
+
+	gnt_box_add_widget(GNT_BOX(box),
+			gnt_label_new_with_format(_("You have mail!"), GNT_TEXT_FLAG_BOLD));
+
+	emaildialog.tree = tree = gnt_tree_new_with_columns(3);
+	gnt_tree_set_column_titles(GNT_TREE(tree), _("Account"), _("From"), _("Subject"));
+	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
+	gnt_tree_set_col_width(GNT_TREE(tree), 0, 15);
+	gnt_tree_set_col_width(GNT_TREE(tree), 1, 25);
+	gnt_tree_set_col_width(GNT_TREE(tree), 2, 25);
+
+	gnt_box_add_widget(GNT_BOX(box), tree);
+
+	button = gnt_button_new(_("Close"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+
+	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), box);
+	g_signal_connect(G_OBJECT(box), "destroy", G_CALLBACK(reset_email_dialog), NULL);
+}
+
+static void *
+finch_notify_emails(GaimConnection *gc, size_t count, gboolean detailed,
+		const char **subjects, const char **froms, const char **tos,
+		const char **urls)
+{
+	GaimAccount *account = gaim_connection_get_account(gc);
+	GString *message = g_string_new(NULL);
+	void *ret;
+
+	if (!detailed)
+	{
+		g_string_append_printf(message,
+				ngettext("%s (%s) has %d new message.",
+					     "%s (%s) has %d new messages.",
+						 (int)count),
+				tos ? *tos : gaim_account_get_username(account),
+				gaim_account_get_protocol_name(account), (int)count);
+	}
+	else
+	{
+		char *to;
+
+		setup_email_dialog();
+
+		to = g_strdup_printf("%s (%s)", tos ? *tos : gaim_account_get_username(account),
+					gaim_account_get_protocol_name(account));
+		gnt_tree_add_row_after(GNT_TREE(emaildialog.tree), GINT_TO_POINTER(time(NULL)),
+				gnt_tree_create_row(GNT_TREE(emaildialog.tree), to,
+					froms ? *froms : "[Unknown sender]",
+					*subjects),
+				NULL, NULL);
+		g_free(to);
+		gnt_widget_show(emaildialog.window);
+		return NULL;
+	}
+
+	ret = finch_notify_message(GAIM_NOTIFY_EMAIL, _("New Mail"), _("You have mail!"), message->str);
+	g_string_free(message, TRUE);
+	return ret;
+}
+
+static void *
+finch_notify_email(GaimConnection *gc, const char *subject, const char *from,
+		const char *to, const char *url)
+{
+	return finch_notify_emails(gc, 1, subject != NULL,
+			subject ? &subject : NULL,
+			from ? &from : NULL,
+			to ? &to : NULL,
+			url ? &url : NULL);
+}
+
+static void *
+finch_notify_userinfo(GaimConnection *gc, const char *who, GaimNotifyUserInfo *user_info)
+{
+	/* Xeroxed from gtknotify.c */
+	char *primary;
+	char *info;
+	void *ui_handle;
+	
+	primary = g_strdup_printf(_("Info for %s"), who);
+	info = gaim_notify_user_info_get_text_with_newline(user_info, "<BR>");
+	ui_handle = finch_notify_formatted(_("Buddy Information"), primary, NULL, info);
+	g_free(info);
+	g_free(primary);
+	return ui_handle;
+}
+
+static void
+notify_button_activated(GntWidget *widget, GaimNotifySearchButton *b)
+{
+	GList *list = NULL;
+	GaimAccount *account = g_object_get_data(G_OBJECT(widget), "notify-account");
+	gpointer data = g_object_get_data(G_OBJECT(widget), "notify-data");
+
+	list = gnt_tree_get_selection_text_list(GNT_TREE(widget));
+
+	b->callback(gaim_account_get_connection(account), list, data);
+	g_list_foreach(list, (GFunc)g_free, NULL);
+	g_list_free(list);
+}
+
+static void
+finch_notify_sr_new_rows(GaimConnection *gc,
+		GaimNotifySearchResults *results, void *data)
+{
+	GntTree *tree = GNT_TREE(data);
+	GList *o;
+
+	/* XXX: Do I need to empty the tree here? */
+
+	for (o = results->rows; o; o = o->next)
+	{
+		gnt_tree_add_row_after(GNT_TREE(tree), o->data,
+				gnt_tree_create_row_from_list(GNT_TREE(tree), o->data),
+				NULL, NULL);
+	}
+}
+
+static void *
+finch_notify_searchresults(GaimConnection *gc, const char *title,
+		const char *primary, const char *secondary,
+		GaimNotifySearchResults *results, gpointer data)
+{
+	GntWidget *window, *tree, *box, *button;
+	GList *iter;
+
+	window = gnt_vbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_title(GNT_BOX(window), title);
+	gnt_box_set_fill(GNT_BOX(window), FALSE);
+	gnt_box_set_pad(GNT_BOX(window), 0);
+	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
+
+	gnt_box_add_widget(GNT_BOX(window),
+			gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD));
+	gnt_box_add_widget(GNT_BOX(window),
+			gnt_label_new_with_format(secondary, GNT_TEXT_FLAG_NORMAL));
+
+	tree = gnt_tree_new_with_columns(g_list_length(results->columns));
+	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
+	gnt_box_add_widget(GNT_BOX(window), tree);
+
+	box = gnt_hbox_new(TRUE);
+
+	for (iter = results->buttons; iter; iter = iter->next)
+	{
+		GaimNotifySearchButton *b = iter->data;
+		const char *text;
+
+		switch (b->type)
+		{
+			case GAIM_NOTIFY_BUTTON_LABELED:
+				text = b->label;
+				break;
+			case GAIM_NOTIFY_BUTTON_CONTINUE:
+				text = _("Continue");
+				break;
+			case GAIM_NOTIFY_BUTTON_ADD:
+				text = _("Add");
+				break;
+			case GAIM_NOTIFY_BUTTON_INFO:
+				text = _("Info");
+				break;
+			case GAIM_NOTIFY_BUTTON_IM:
+				text = _("IM");
+				break;
+			case GAIM_NOTIFY_BUTTON_JOIN:
+				text = _("Join");
+				break;
+			case GAIM_NOTIFY_BUTTON_INVITE:
+				text = _("Invite");
+				break;
+			default:
+				text = _("(none)");
+		}
+
+		button = gnt_button_new(text);
+		g_object_set_data(G_OBJECT(button), "notify-account", gaim_connection_get_account(gc));
+		g_object_set_data(G_OBJECT(button), "notify-data", data);
+		g_signal_connect_swapped(G_OBJECT(button), "activate",
+				G_CALLBACK(notify_button_activated), b);
+
+		gnt_box_add_widget(GNT_BOX(box), button);
+	}
+
+	gnt_box_add_widget(GNT_BOX(window), box);
+
+	finch_notify_sr_new_rows(gc, results, tree);
+
+	gnt_widget_show(window);
+	g_object_set_data(G_OBJECT(window), "notify-results", results);
+
+	return tree;
+}
+
+static GaimNotifyUiOps ops = 
+{
+	.notify_message = finch_notify_message,
+	.close_notify = finch_close_notify,       /* The rest of the notify-uiops return a GntWidget.
+                                              These widgets should be destroyed from here. */
+	.notify_formatted = finch_notify_formatted,
+	.notify_email = finch_notify_email,
+	.notify_emails = finch_notify_emails,
+	.notify_userinfo = finch_notify_userinfo,
+
+	.notify_searchresults = finch_notify_searchresults,
+	.notify_searchresults_new_rows = finch_notify_sr_new_rows,
+	.notify_uri = NULL                     /* This is of low-priority to me */
+};
+
+GaimNotifyUiOps *finch_notify_get_ui_ops()
+{
+	return &ops;
+}
+
+void finch_notify_init()
+{
+}
+
+void finch_notify_uninit()
+{
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntnotify.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,55 @@
+/**
+ * @file gntnotify.h GNT Notify API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_NOTIFY_H
+#define _GNT_NOTIFY_H
+
+#include "notify.h"
+
+/**********************************************************************
+ * @name GNT Notify API
+ **********************************************************************/
+/*@{*/
+
+/**
+ * Get the ui-functions.
+ *
+ * @return The GaimNotifyUiOps structure populated with the appropriate functions.
+ */
+GaimNotifyUiOps *finch_notify_get_ui_ops(void);
+
+/**
+ * Perform necessary initializations.
+ */
+void finch_notify_init(void);
+
+/**
+ * Perform necessary uninitializations.
+ */
+void finch_notify_uninit(void);
+
+/*@}*/
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntplugin.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,274 @@
+/**
+ * @file gntplugin.c GNT Plugins API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntlabel.h>
+#include <gntline.h>
+#include <gnttree.h>
+
+#include "notify.h"
+
+#include "gntgaim.h"
+#include "gntplugin.h"
+
+static struct
+{
+	GntWidget *tree;
+	GntWidget *window;
+	GntWidget *aboot;
+	GntWidget *conf;
+} plugins;
+
+static GHashTable *confwins;
+
+static void
+decide_conf_button(GaimPlugin *plugin)
+{
+	if (gaim_plugin_is_loaded(plugin) && 
+		((GAIM_IS_GNT_PLUGIN(plugin) &&
+			GAIM_GNT_PLUGIN_UI_INFO(plugin) != NULL) ||
+		(plugin->info->prefs_info &&
+			plugin->info->prefs_info->get_plugin_pref_frame)))
+		gnt_widget_set_visible(plugins.conf, TRUE);
+	else
+		gnt_widget_set_visible(plugins.conf, FALSE);
+
+	gnt_box_readjust(GNT_BOX(plugins.window));
+	gnt_widget_draw(plugins.window);
+}
+
+static void
+plugin_toggled_cb(GntWidget *tree, GaimPlugin *plugin, gpointer null)
+{
+	if (gnt_tree_get_choice(GNT_TREE(tree), plugin))
+	{
+		if(!gaim_plugin_load(plugin))
+			gaim_notify_error(NULL, "ERROR", "loading plugin failed", NULL);
+	}
+	else
+	{
+		GntWidget *win;
+
+		if (!gaim_plugin_unload(plugin))
+			gaim_notify_error(NULL, "ERROR", "unloading plugin failed", NULL);
+
+		if ((win = g_hash_table_lookup(confwins, plugin)) != NULL)
+		{
+			gnt_widget_destroy(win);
+		}
+	}
+	decide_conf_button(plugin);
+	finch_plugins_save_loaded();
+}
+
+/* Xerox */
+void
+finch_plugins_save_loaded(void)
+{
+	gaim_plugins_save_loaded("/gaim/gnt/plugins/loaded");
+}
+
+static void
+selection_changed(GntWidget *widget, gpointer old, gpointer current, gpointer null)
+{
+	GaimPlugin *plugin = current;
+	char *text;
+
+	/* XXX: Use formatting and stuff */
+	gnt_text_view_clear(GNT_TEXT_VIEW(plugins.aboot));
+	text = g_strdup_printf(_("Name: %s\nVersion: %s\nDescription: %s\nAuthor: %s\nWebsite: %s\nFilename: %s\n"),
+			SAFE(plugin->info->name), SAFE(plugin->info->version), SAFE(plugin->info->description),
+			SAFE(plugin->info->author), SAFE(plugin->info->homepage), SAFE(plugin->path));
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(plugins.aboot),
+			text, GNT_TEXT_FLAG_NORMAL);
+	gnt_text_view_scroll(GNT_TEXT_VIEW(plugins.aboot), 0);
+	g_free(text);
+	decide_conf_button(plugin);
+}
+
+static void
+reset_plugin_window(GntWidget *window, gpointer null)
+{
+	plugins.window = NULL;
+	plugins.tree = NULL;
+	plugins.aboot = NULL;
+}
+
+static int
+plugin_compare(GaimPlugin *p1, GaimPlugin *p2)
+{
+	char *s1 = g_utf8_strup(p1->info->name, -1);
+	char *s2 = g_utf8_strup(p2->info->name, -1);
+	int ret = g_utf8_collate(s1, s2);
+	g_free(s1);
+	g_free(s2);
+	return ret;
+}
+
+static void
+confwin_init()
+{
+	confwins = g_hash_table_new(g_direct_hash, g_direct_equal);
+}
+
+static void
+remove_confwin(GntWidget *window, gpointer plugin)
+{
+	g_hash_table_remove(confwins, plugin);
+}
+
+static void
+configure_plugin_cb(GntWidget *button, gpointer null)
+{
+	GaimPlugin *plugin;
+	FinchPluginFrame callback;
+
+	g_return_if_fail(plugins.tree != NULL);
+
+	plugin = gnt_tree_get_selection_data(GNT_TREE(plugins.tree));
+	if (!gaim_plugin_is_loaded(plugin))
+	{
+		gaim_notify_error(plugin, _("Error"),
+			_("Plugin need to be loaded before you can configure it."), NULL);
+		return;
+	}
+
+	if (confwins && g_hash_table_lookup(confwins, plugin))
+		return;
+
+	if (GAIM_IS_GNT_PLUGIN(plugin) &&
+			(callback = GAIM_GNT_PLUGIN_UI_INFO(plugin)) != NULL)
+	{
+		GntWidget *window = gnt_vbox_new(FALSE);
+		GntWidget *box, *button;
+
+		gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+		gnt_box_set_title(GNT_BOX(window), plugin->info->name);
+		gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
+
+		box = callback();
+		gnt_box_add_widget(GNT_BOX(window), box);
+
+		box = gnt_hbox_new(FALSE);
+		gnt_box_add_widget(GNT_BOX(window), box);
+
+		button = gnt_button_new(_("Close"));
+		gnt_box_add_widget(GNT_BOX(box), button);
+		g_signal_connect_swapped(G_OBJECT(button), "activate",
+				G_CALLBACK(gnt_widget_destroy), window);
+		g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(remove_confwin), plugin);
+
+		gnt_widget_show(window);
+
+		if (confwins == NULL)
+			confwin_init();
+		g_hash_table_insert(confwins, plugin, window);
+	}
+	else if (plugin->info->prefs_info &&
+			plugin->info->prefs_info->get_plugin_pref_frame)
+	{
+		gaim_notify_info(plugin, _("..."),
+			_("Still need to do something about this."), NULL);
+		return;
+	}
+	else
+	{
+		gaim_notify_info(plugin, _("Error"),
+			_("No configuration options for this plugin."), NULL);
+		return;
+	}
+}
+
+void finch_plugins_show_all()
+{
+	GntWidget *window, *tree, *box, *aboot, *button;
+	GList *iter;
+	if (plugins.window)
+		return;
+
+	gaim_plugins_probe(G_MODULE_SUFFIX);
+
+	plugins.window = window = gnt_vbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_title(GNT_BOX(window), _("Plugins"));
+	gnt_box_set_pad(GNT_BOX(window), 0);
+	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
+
+	gnt_box_add_widget(GNT_BOX(window),
+			gnt_label_new(_("You can (un)load plugins from the following list.")));
+	gnt_box_add_widget(GNT_BOX(window), gnt_hline_new());
+
+	box = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(window), box);
+	gnt_box_add_widget(GNT_BOX(window), gnt_hline_new());
+
+	gnt_box_set_pad(GNT_BOX(box), 0);
+	plugins.tree = tree = gnt_tree_new();
+	gnt_tree_set_compare_func(GNT_TREE(tree), (GCompareFunc)plugin_compare);
+	GNT_WIDGET_SET_FLAGS(tree, GNT_WIDGET_NO_BORDER);
+	gnt_box_add_widget(GNT_BOX(box), tree);
+	gnt_box_add_widget(GNT_BOX(box), gnt_vline_new());
+
+	plugins.aboot = aboot = gnt_text_view_new();
+	gnt_widget_set_size(aboot, 40, 20);
+	gnt_box_add_widget(GNT_BOX(box), aboot);
+
+	for (iter = gaim_plugins_get_all(); iter; iter = iter->next)
+	{
+		GaimPlugin *plug = iter->data;
+
+		if (plug->info->type != GAIM_PLUGIN_STANDARD ||
+			(plug->info->flags & GAIM_PLUGIN_FLAG_INVISIBLE) ||
+			plug->error)
+			continue;
+
+		gnt_tree_add_choice(GNT_TREE(tree), plug,
+				gnt_tree_create_row(GNT_TREE(tree), plug->info->name), NULL, NULL);
+		gnt_tree_set_choice(GNT_TREE(tree), plug, gaim_plugin_is_loaded(plug));
+	}
+	gnt_tree_set_col_width(GNT_TREE(tree), 0, 30);
+	g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(plugin_toggled_cb), NULL);
+	g_signal_connect(G_OBJECT(tree), "selection_changed", G_CALLBACK(selection_changed), NULL);
+
+	box = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(window), box);
+
+	button = gnt_button_new(_("Close"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect_swapped(G_OBJECT(button), "activate",
+			G_CALLBACK(gnt_widget_destroy), window);
+
+	plugins.conf = button = gnt_button_new(_("Configure Plugin"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(configure_plugin_cb), NULL);
+
+	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(reset_plugin_window), NULL);
+
+	gnt_widget_show(window);
+
+	decide_conf_button(gnt_tree_get_selection_data(GNT_TREE(tree)));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntplugin.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,71 @@
+/**
+ * @file gntplugin.h GNT Plugins API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_PLUGIN_H
+#define _GNT_PLUGIN_H
+
+#include <gnt.h>
+
+#include <plugin.h>
+
+#include <string.h>
+
+#include "gntgaim.h"
+
+/**********************************************************************
+ * @name GNT Plugins API
+ **********************************************************************/
+/*@{*/
+
+typedef GntWidget* (*FinchPluginFrame) ();
+
+/* Guess where these came from */
+#define GAIM_GNT_PLUGIN_TYPE GAIM_GNT_UI
+
+/**
+ * Decide whether a plugin is a GNT-plugin.
+ */
+#define GAIM_IS_GNT_PLUGIN(plugin) \
+	((plugin)->info != NULL && (plugin)->info->ui_info != NULL && \
+	 !strcmp((plugin)->info->ui_requirement, GAIM_GNT_PLUGIN_TYPE))
+
+/**
+ * Get the ui-info from GNT-plugins.
+ */
+#define GAIM_GNT_PLUGIN_UI_INFO(plugin) \
+	(FinchPluginFrame)((plugin)->info->ui_info)
+
+/**
+ * Show a list of plugins.
+ */
+void finch_plugins_show_all(void);
+
+/**
+ * Save the list of loaded plugins.
+ */
+void finch_plugins_save_loaded(void);
+
+/*@}*/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntpounce.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,956 @@
+/**
+ * @file gntpounce.c GNT Buddy Pounce API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntcheckbox.h>
+#include <gntcombobox.h>
+#include <gntentry.h>
+#include <gntlabel.h>
+#include <gntline.h>
+#include <gnttree.h>
+#include "internal.h"
+#include "gntgaim.h"
+
+#include "account.h"
+#include "conversation.h"
+#include "debug.h"
+#include "notify.h"
+#include "prpl.h"
+#include "request.h"
+#include "server.h"
+#include "util.h"
+
+#include "gntpounce.h"
+
+
+typedef struct
+{
+	/* Pounce data */
+	GaimPounce  *pounce;
+	GaimAccount *account;
+
+	/* The window */
+	GntWidget *window;
+
+	/* Pounce on Whom */
+	GntWidget *account_menu;
+	GntWidget *buddy_entry;
+
+	/* Pounce options */
+	GntWidget *on_away;
+
+	/* Pounce When Buddy... */
+	GntWidget *signon;
+	GntWidget *signoff;
+	GntWidget *away;
+	GntWidget *away_return;
+	GntWidget *idle;
+	GntWidget *idle_return;
+	GntWidget *typing;
+	GntWidget *typed;
+	GntWidget *stop_typing;
+	GntWidget *message_recv;
+
+	/* Action */
+	GntWidget *open_win;
+	GntWidget *popup;
+	GntWidget *popup_entry;
+	GntWidget *send_msg;
+	GntWidget *send_msg_entry;
+	GntWidget *exec_cmd;
+	GntWidget *exec_cmd_entry;
+	GntWidget *play_sound;
+
+	GntWidget *save_pounce;
+
+	/* Buttons */
+	GntWidget *save_button;
+
+} GaimGntPounceDialog;
+
+typedef struct
+{
+	GntWidget *window;
+	GntWidget *tree;
+	GntWidget *modify_button;
+	GntWidget *delete_button;
+} PouncesManager;
+
+static PouncesManager *pounces_manager = NULL;
+
+/**************************************************************************
+ * Callbacks
+ **************************************************************************/
+static gint
+delete_win_cb(GntWidget *w, GaimGntPounceDialog *dialog)
+{
+	gnt_widget_destroy(dialog->window);
+	g_free(dialog);
+
+	return TRUE;
+}
+
+static void
+cancel_cb(GntWidget *w, GaimGntPounceDialog *dialog)
+{
+	gnt_widget_destroy(dialog->window);
+}
+
+static void
+add_pounce_to_treeview(GntTree *tree, GaimPounce *pounce)
+{
+	GaimAccount *account;
+	const char *pouncer;
+	const char *pouncee;
+
+	account = gaim_pounce_get_pouncer(pounce);
+	pouncer = gaim_account_get_username(account);
+	pouncee = gaim_pounce_get_pouncee(pounce);
+	gnt_tree_add_row_last(tree, pounce,
+		gnt_tree_create_row(tree, pouncer, pouncee), NULL);
+}
+
+static void
+populate_pounces_list(PouncesManager *dialog)
+{
+	const GList *pounces;
+
+	gnt_tree_remove_all(GNT_TREE(dialog->tree));
+
+	for (pounces = gaim_pounces_get_all(); pounces != NULL;
+			pounces = g_list_next(pounces))
+	{
+		add_pounce_to_treeview(GNT_TREE(dialog->tree), pounces->data);
+	}
+}
+
+static void
+update_pounces(void)
+{
+	/* Rebuild the pounces list if the pounces manager is open */
+	if (pounces_manager != NULL)
+	{
+		populate_pounces_list(pounces_manager);
+	}
+}
+
+static void
+signed_on_off_cb(GaimConnection *gc, gpointer user_data)
+{
+	update_pounces();
+}
+
+static void
+save_pounce_cb(GntWidget *w, GaimGntPounceDialog *dialog)
+{
+	const char *name;
+	const char *message, *command, *reason;
+	GaimPounceEvent events   = GAIM_POUNCE_NONE;
+	GaimPounceOption options = GAIM_POUNCE_OPTION_NONE;
+
+	name = gnt_entry_get_text(GNT_ENTRY(dialog->buddy_entry));
+
+	if (*name == '\0')
+	{
+		gaim_notify_error(NULL, NULL,
+						  _("Please enter a buddy to pounce."), NULL);
+		return;
+	}
+
+	/* Options */
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->on_away)))
+		options |= GAIM_POUNCE_OPTION_AWAY;
+
+	/* Events */
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->signon)))
+		events |= GAIM_POUNCE_SIGNON;
+
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->signoff)))
+		events |= GAIM_POUNCE_SIGNOFF;
+
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->away)))
+		events |= GAIM_POUNCE_AWAY;
+
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->away_return)))
+		events |= GAIM_POUNCE_AWAY_RETURN;
+
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->idle)))
+		events |= GAIM_POUNCE_IDLE;
+
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->idle_return)))
+		events |= GAIM_POUNCE_IDLE_RETURN;
+
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->typing)))
+		events |= GAIM_POUNCE_TYPING;
+
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->typed)))
+		events |= GAIM_POUNCE_TYPED;
+
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->stop_typing)))
+		events |= GAIM_POUNCE_TYPING_STOPPED;
+
+	if (gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->message_recv)))
+		events |= GAIM_POUNCE_MESSAGE_RECEIVED;
+
+	/* Data fields */
+	message = gnt_entry_get_text(GNT_ENTRY(dialog->send_msg_entry));
+	command = gnt_entry_get_text(GNT_ENTRY(dialog->exec_cmd_entry));
+	reason  = gnt_entry_get_text(GNT_ENTRY(dialog->popup_entry));
+
+	if (*reason == '\0') reason = NULL;
+	if (*message == '\0') message = NULL;
+	if (*command == '\0') command = NULL;
+
+	if (dialog->pounce == NULL) {
+		dialog->pounce = gaim_pounce_new(GAIM_GNT_UI, dialog->account,
+										 name, events, options);
+	} else {
+		gaim_pounce_set_events(dialog->pounce, events);
+		gaim_pounce_set_options(dialog->pounce, options);
+		gaim_pounce_set_pouncer(dialog->pounce, dialog->account);
+		gaim_pounce_set_pouncee(dialog->pounce, name);
+	}
+
+	/* Actions */
+	gaim_pounce_action_set_enabled(dialog->pounce, "open-window",
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->open_win)));
+	gaim_pounce_action_set_enabled(dialog->pounce, "popup-notify",
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->popup)));
+	gaim_pounce_action_set_enabled(dialog->pounce, "send-message",
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->send_msg)));
+	gaim_pounce_action_set_enabled(dialog->pounce, "execute-command",
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->exec_cmd)));
+	gaim_pounce_action_set_enabled(dialog->pounce, "play-beep",
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->play_sound)));
+
+	gaim_pounce_action_set_attribute(dialog->pounce, "send-message",
+									 "message", message);
+	gaim_pounce_action_set_attribute(dialog->pounce, "execute-command",
+									 "command", command);
+	gaim_pounce_action_set_attribute(dialog->pounce, "popup-notify",
+									 "reason", reason);
+
+	/* Set the defaults for next time. */
+	gaim_prefs_set_bool("/gaim/gnt/pounces/default_actions/open-window",
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->open_win)));
+	gaim_prefs_set_bool("/gaim/gnt/pounces/default_actions/popup-notify",
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->popup)));
+	gaim_prefs_set_bool("/gaim/gnt/pounces/default_actions/send-message",
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->send_msg)));
+	gaim_prefs_set_bool("/gaim/gnt/pounces/default_actions/execute-command",
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->exec_cmd)));
+	gaim_prefs_set_bool("/gaim/gnt/pounces/default_actions/play-beep",
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->play_sound)));
+
+	gaim_pounce_set_save(dialog->pounce,
+		gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->save_pounce)));
+
+	gaim_pounce_set_pouncer(dialog->pounce,
+		(GaimAccount *)gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->account_menu)));
+
+	update_pounces();
+
+	gnt_widget_destroy(dialog->window);
+}
+
+
+void
+finch_pounce_editor_show(GaimAccount *account, const char *name,
+							GaimPounce *cur_pounce)
+{
+	GaimGntPounceDialog *dialog;
+	GntWidget *window;
+	GntWidget *bbox;
+	GntWidget *hbox;
+	GntWidget *button;
+	GntWidget *combo;
+	GList *list;
+
+	g_return_if_fail((cur_pounce != NULL) ||
+	                 (account != NULL) ||
+	                 (gaim_accounts_get_all() != NULL));
+
+	dialog = g_new0(GaimGntPounceDialog, 1);
+
+	if (cur_pounce != NULL) {
+		dialog->pounce  = cur_pounce;
+		dialog->account = gaim_pounce_get_pouncer(cur_pounce);
+	} else if (account != NULL) {
+		dialog->pounce  = NULL;
+		dialog->account = account;
+	} else {
+		GList *connections = gaim_connections_get_all();
+		GaimConnection *gc;
+
+		if (connections != NULL) {
+			gc = (GaimConnection *)connections->data;
+			dialog->account = gaim_connection_get_account(gc);
+		} else
+			dialog->account = gaim_accounts_get_all()->data;
+
+		dialog->pounce  = NULL;
+	}
+
+	/* Create the window. */
+	dialog->window = window = gnt_vbox_new(FALSE);
+	gnt_box_set_pad(GNT_BOX(window), 0);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_LEFT);
+	gnt_box_set_title(GNT_BOX(window),
+						 (cur_pounce == NULL
+						  ? _("New Buddy Pounce") : _("Edit Buddy Pounce")));
+
+	g_signal_connect(G_OBJECT(window), "destroy",
+					 G_CALLBACK(delete_win_cb), dialog);
+
+	gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(_("Pounce Who"), GNT_TEXT_FLAG_BOLD));
+
+	/* Account: */
+	gnt_box_add_widget(GNT_BOX(window), gnt_label_new(_("Account:")));
+	dialog->account_menu = combo = gnt_combo_box_new();
+	list = gaim_accounts_get_all();
+	for (; list; list = list->next)
+	{
+		GaimAccount *account;
+		char *text;
+
+		account = list->data;
+		text = g_strdup_printf("%s (%s)",
+				gaim_account_get_username(account),
+				gaim_account_get_protocol_name(account));
+		gnt_combo_box_add_data(GNT_COMBO_BOX(combo), account, text);
+		g_free(text);
+	}
+	if (dialog->account)
+		gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), dialog->account);
+
+	gnt_box_add_widget(GNT_BOX(window), combo);
+
+	/* Buddy: */
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Buddy name:")));
+
+	dialog->buddy_entry = gnt_entry_new(NULL);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->buddy_entry);
+
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+
+	if (cur_pounce != NULL) {
+		gnt_entry_set_text(GNT_ENTRY(dialog->buddy_entry),
+						   gaim_pounce_get_pouncee(cur_pounce));
+	} else if (name != NULL) {
+		gnt_entry_set_text(GNT_ENTRY(dialog->buddy_entry), name);
+	}
+
+	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
+	gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(_("Pounce When Buddy..."), GNT_TEXT_FLAG_BOLD));
+
+	dialog->signon = gnt_check_box_new(_("Signs on"));
+	dialog->signoff = gnt_check_box_new(_("Signs off"));
+	dialog->away = gnt_check_box_new(_("Goes away"));
+	dialog->away_return = gnt_check_box_new(_("Returns from away"));
+	dialog->idle = gnt_check_box_new(_("Becomes idle"));
+	dialog->idle_return = gnt_check_box_new(_("Is no longer idle"));
+	dialog->typing = gnt_check_box_new(_("Starts typing"));
+	dialog->typed = gnt_check_box_new(_("Pauses while typing"));
+	dialog->stop_typing = gnt_check_box_new(_("Stops typing"));
+	dialog->message_recv = gnt_check_box_new(_("Sends a message"));
+
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_set_pad(GNT_BOX(hbox), 2);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->signon);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->signoff);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_set_pad(GNT_BOX(hbox), 2);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->away);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->away_return);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_set_pad(GNT_BOX(hbox), 2);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->idle);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->idle_return);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_set_pad(GNT_BOX(hbox), 2);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->typing);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->typed);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_set_pad(GNT_BOX(hbox), 2);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->stop_typing);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->message_recv);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+
+	/* Create the "Action" frame. */
+	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
+	gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(_("Action"), GNT_TEXT_FLAG_BOLD));
+
+	dialog->open_win = gnt_check_box_new(_("Open an IM window"));
+	dialog->popup = gnt_check_box_new(_("Pop up a notification"));
+	dialog->send_msg = gnt_check_box_new(_("Send a message"));
+	dialog->exec_cmd = gnt_check_box_new(_("Execute a command"));
+	dialog->play_sound = gnt_check_box_new(_("Play a sound"));
+
+	dialog->send_msg_entry    = gnt_entry_new(NULL);
+	dialog->exec_cmd_entry    = gnt_entry_new(NULL);
+	dialog->popup_entry       = gnt_entry_new(NULL);
+	dialog->exec_cmd_entry   = gnt_entry_new(NULL);
+
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->open_win);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->popup);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->popup_entry);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->send_msg);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->send_msg_entry);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->exec_cmd);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->exec_cmd_entry);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(hbox), dialog->play_sound);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+
+	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
+	gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(_("Options"), GNT_TEXT_FLAG_BOLD));
+	dialog->on_away = gnt_check_box_new(_("Pounce only when my status is not available"));
+	gnt_box_add_widget(GNT_BOX(window), dialog->on_away);
+	dialog->save_pounce = gnt_check_box_new(_("Recurring"));
+	gnt_box_add_widget(GNT_BOX(window), dialog->save_pounce);
+
+
+	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
+	/* Now the button box! */
+	bbox = gnt_hbox_new(TRUE);
+
+	/* Cancel button */
+	button = gnt_button_new(_("Cancel"));
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(cancel_cb), dialog);
+
+	/* Save button */
+	dialog->save_button = button = gnt_button_new(_("Save"));
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(save_pounce_cb), dialog);
+
+	gnt_box_add_widget(GNT_BOX(window), bbox);
+
+
+	/* Set the values of stuff. */
+	if (cur_pounce != NULL)
+	{
+		GaimPounceEvent events   = gaim_pounce_get_events(cur_pounce);
+		GaimPounceOption options = gaim_pounce_get_options(cur_pounce);
+		const char *value;
+
+		/* Options */
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->on_away),
+									(options & GAIM_POUNCE_OPTION_AWAY));
+
+		/* Events */
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->signon),
+									(events & GAIM_POUNCE_SIGNON));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->signoff),
+									(events & GAIM_POUNCE_SIGNOFF));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->away),
+									(events & GAIM_POUNCE_AWAY));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->away_return),
+									(events & GAIM_POUNCE_AWAY_RETURN));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->idle),
+									(events & GAIM_POUNCE_IDLE));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->idle_return),
+									(events & GAIM_POUNCE_IDLE_RETURN));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->typing),
+									(events & GAIM_POUNCE_TYPING));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->typed),
+									(events & GAIM_POUNCE_TYPED));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->stop_typing),
+									(events & GAIM_POUNCE_TYPING_STOPPED));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->message_recv),
+									(events & GAIM_POUNCE_MESSAGE_RECEIVED));
+
+		/* Actions */
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->open_win),
+			gaim_pounce_action_is_enabled(cur_pounce, "open-window"));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->popup),
+			gaim_pounce_action_is_enabled(cur_pounce, "popup-notify"));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->send_msg),
+			gaim_pounce_action_is_enabled(cur_pounce, "send-message"));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->exec_cmd),
+			gaim_pounce_action_is_enabled(cur_pounce, "execute-command"));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->play_sound),
+			gaim_pounce_action_is_enabled(cur_pounce, "play-beep"));
+
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->save_pounce),
+			gaim_pounce_get_save(cur_pounce));
+
+		if ((value = gaim_pounce_action_get_attribute(cur_pounce,
+		                                              "send-message",
+		                                              "message")) != NULL)
+		{
+			gnt_entry_set_text(GNT_ENTRY(dialog->send_msg_entry), value);
+		}
+
+		if ((value = gaim_pounce_action_get_attribute(cur_pounce,
+		                                              "popup-notify",
+		                                              "reason")) != NULL)
+		{
+			gnt_entry_set_text(GNT_ENTRY(dialog->popup_entry), value);
+		}
+
+		if ((value = gaim_pounce_action_get_attribute(cur_pounce,
+		                                              "execute-command",
+		                                              "command")) != NULL)
+		{
+			gnt_entry_set_text(GNT_ENTRY(dialog->exec_cmd_entry), value);
+		}
+	}
+	else
+	{
+		GaimBuddy *buddy = NULL;
+
+		if (name != NULL)
+			buddy = gaim_find_buddy(account, name);
+
+		/* Set some defaults */
+		if (buddy == NULL) {
+			gnt_check_box_set_checked(
+				GNT_CHECK_BOX(dialog->signon), TRUE);
+		} else {
+			if (!GAIM_BUDDY_IS_ONLINE(buddy)) {
+				gnt_check_box_set_checked(
+					GNT_CHECK_BOX(dialog->signon), TRUE);
+			} else {
+				gboolean default_set = FALSE;
+				GaimPresence *presence = gaim_buddy_get_presence(buddy);
+
+				if (gaim_presence_is_idle(presence))
+				{
+					gnt_check_box_set_checked(
+						GNT_CHECK_BOX(dialog->idle_return), TRUE);
+
+					default_set = TRUE;
+				}
+
+				if (!gaim_presence_is_available(presence))
+				{
+					gnt_check_box_set_checked(
+						GNT_CHECK_BOX(dialog->away_return), TRUE);
+
+					default_set = TRUE;
+				}
+
+				if (!default_set)
+				{
+					gnt_check_box_set_checked(
+						GNT_CHECK_BOX(dialog->signon), TRUE);
+				}
+			}
+		}
+
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->open_win),
+			gaim_prefs_get_bool("/gaim/gnt/pounces/default_actions/open-window"));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->popup),
+			gaim_prefs_get_bool("/gaim/gnt/pounces/default_actions/popup-notify"));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->send_msg),
+			gaim_prefs_get_bool("/gaim/gnt/pounces/default_actions/send-message"));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->exec_cmd),
+			gaim_prefs_get_bool("/gaim/gnt/pounces/default_actions/execute-command"));
+		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->play_sound),
+			gaim_prefs_get_bool("/gaim/gnt/pounces/default_actions/play-beep"));
+	}
+
+	gnt_widget_show(window);
+}
+
+
+
+static gboolean
+pounces_manager_destroy_cb(GntWidget *widget, gpointer user_data)
+{
+	PouncesManager *dialog = user_data;
+
+	dialog->window = NULL;
+	finch_pounces_manager_hide();
+
+	return FALSE;
+}
+
+
+static void
+pounces_manager_add_cb(GntButton *button, gpointer user_data)
+{
+	finch_pounce_editor_show(NULL, NULL, NULL);
+}
+
+
+static void
+pounces_manager_modify_cb(GntButton *button, gpointer user_data)
+{
+	PouncesManager *dialog = user_data;
+	GaimPounce *pounce = gnt_tree_get_selection_data(GNT_TREE(dialog->tree));
+	finch_pounce_editor_show(NULL, NULL, pounce);
+}
+
+static void
+pounces_manager_delete_confirm_cb(GaimPounce *pounce)
+{
+	gnt_tree_remove(GNT_TREE(pounces_manager->tree), pounce);
+
+	gaim_request_close_with_handle(pounce);
+	gaim_pounce_destroy(pounce);
+}
+
+
+static void
+pounces_manager_delete_cb(GntButton *button, gpointer user_data)
+{
+	PouncesManager *dialog = user_data;
+	GaimPounce *pounce;
+	GaimAccount *account;
+	const char *pouncer, *pouncee;
+	char *buf;
+
+	pounce = (GaimPounce *)gnt_tree_get_selection_data(GNT_TREE(dialog->tree));
+	account = gaim_pounce_get_pouncer(pounce);
+	pouncer = gaim_account_get_username(account);
+	pouncee = gaim_pounce_get_pouncee(pounce);
+	buf = g_strdup_printf(_("Are you sure you want to delete the pounce on %s for %s?"), pouncee, pouncer);
+	gaim_request_action(pounce, NULL, buf, NULL, 0, pounce, 2,
+						_("Delete"), pounces_manager_delete_confirm_cb,
+						_("Cancel"), NULL);
+	g_free(buf);
+}
+
+static void
+pounces_manager_close_cb(GntButton *button, gpointer user_data)
+{
+	finch_pounces_manager_hide();
+}
+
+
+void
+finch_pounces_manager_show(void)
+{
+	PouncesManager *dialog;
+	GntWidget *bbox;
+	GntWidget *button;
+	GntWidget *tree;
+	GntWidget *win;
+
+	if (pounces_manager != NULL) {
+		return;
+	}
+
+	pounces_manager = dialog = g_new0(PouncesManager, 1);
+
+	dialog->window = win = gnt_vbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(win), TRUE);
+	gnt_box_set_title(GNT_BOX(win), _("Buddy Pounces"));
+	gnt_box_set_pad(GNT_BOX(win), 0);
+
+	g_signal_connect(G_OBJECT(win), "destroy",
+					 G_CALLBACK(pounces_manager_destroy_cb), dialog);
+
+	/* List of saved buddy pounces */
+	dialog->tree = tree = GNT_WIDGET(gnt_tree_new_with_columns(2));
+	gnt_tree_set_column_titles(GNT_TREE(tree), "Account", "Pouncee", NULL);
+	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
+
+	gnt_box_add_widget(GNT_BOX(win), tree);
+
+	/* Button box. */
+	bbox = gnt_hbox_new(TRUE);
+
+	/* Add button */
+	button = gnt_button_new(_("Add"));
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(pounces_manager_add_cb), dialog);
+
+	/* Modify button */
+	button = gnt_button_new(_("Modify"));
+	dialog->modify_button = button;
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(pounces_manager_modify_cb), dialog);
+
+	/* Delete button */
+	button = gnt_button_new(_("Delete"));
+	dialog->delete_button = button;
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(pounces_manager_delete_cb), dialog);
+
+	/* Close button */
+	button = gnt_button_new(_("Close"));
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+	gnt_widget_show(button);
+
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(pounces_manager_close_cb), dialog);
+
+	gnt_box_add_widget(GNT_BOX(win), bbox);
+
+	gnt_widget_show(win);
+	populate_pounces_list(pounces_manager);
+}
+
+void
+finch_pounces_manager_hide(void)
+{
+	if (pounces_manager == NULL)
+		return;
+
+	if (pounces_manager->window != NULL)
+		gnt_widget_destroy(pounces_manager->window);
+
+	gaim_signals_disconnect_by_handle(pounces_manager);
+
+	g_free(pounces_manager);
+	pounces_manager = NULL;
+}
+
+static void
+pounce_cb(GaimPounce *pounce, GaimPounceEvent events, void *data)
+{
+	GaimConversation *conv;
+	GaimAccount *account;
+	GaimBuddy *buddy;
+	const char *pouncee;
+	const char *alias;
+
+	pouncee = gaim_pounce_get_pouncee(pounce);
+	account = gaim_pounce_get_pouncer(pounce);
+
+	buddy = gaim_find_buddy(account, pouncee);
+	if (buddy != NULL)
+	{
+		alias = gaim_buddy_get_alias(buddy);
+		if (alias == NULL)
+			alias = pouncee;
+	}
+	else
+		alias = pouncee;
+
+	if (gaim_pounce_action_is_enabled(pounce, "open-window"))
+	{
+		conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, pouncee, account);
+
+		if (conv == NULL)
+			conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, pouncee);
+	}
+
+	if (gaim_pounce_action_is_enabled(pounce, "popup-notify"))
+	{
+		char *tmp;
+		const char *name_shown;
+		const char *reason;
+		reason = gaim_pounce_action_get_attribute(pounce, "popup-notify",
+														  "reason");
+
+		/*
+		 * Here we place the protocol name in the pounce dialog to lessen
+		 * confusion about what protocol a pounce is for.
+		 */
+		tmp = g_strdup_printf(
+				   (events & GAIM_POUNCE_TYPING) ?
+				   _("%s has started typing to you (%s)") :
+				   (events & GAIM_POUNCE_TYPED) ?
+				   _("%s has paused while typing to you (%s)") :
+				   (events & GAIM_POUNCE_SIGNON) ?
+				   _("%s has signed on (%s)") :
+				   (events & GAIM_POUNCE_IDLE_RETURN) ?
+				   _("%s has returned from being idle (%s)") :
+				   (events & GAIM_POUNCE_AWAY_RETURN) ?
+				   _("%s has returned from being away (%s)") :
+				   (events & GAIM_POUNCE_TYPING_STOPPED) ?
+				   _("%s has stopped typing to you (%s)") :
+				   (events & GAIM_POUNCE_SIGNOFF) ?
+				   _("%s has signed off (%s)") :
+				   (events & GAIM_POUNCE_IDLE) ?
+				   _("%s has become idle (%s)") :
+				   (events & GAIM_POUNCE_AWAY) ?
+				   _("%s has gone away. (%s)") :
+				   (events & GAIM_POUNCE_MESSAGE_RECEIVED) ?
+				   _("%s has sent you a message. (%s)") :
+				   _("Unknown pounce event. Please report this!"),
+				   alias, gaim_account_get_protocol_name(account));
+
+		/*
+		 * Ok here is where I change the second argument, title, from
+		 * NULL to the account alias if we have it or the account
+		 * name if that's all we have
+		 */
+		if ((name_shown = gaim_account_get_alias(account)) == NULL)
+			name_shown = gaim_account_get_username(account);
+
+		if (reason == NULL)
+		{
+			gaim_notify_info(NULL, name_shown, tmp, gaim_date_format_full(NULL));
+		}
+		else
+		{
+			char *tmp2 = g_strdup_printf("%s\n\n%s", reason, gaim_date_format_full(NULL));
+			gaim_notify_info(NULL, name_shown, tmp, tmp2);
+			g_free(tmp2);
+		}
+		g_free(tmp);
+	}
+
+	if (gaim_pounce_action_is_enabled(pounce, "send-message"))
+	{
+		const char *message;
+
+		message = gaim_pounce_action_get_attribute(pounce, "send-message",
+												   "message");
+
+		if (message != NULL)
+		{
+			conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, pouncee, account);
+
+			if (conv == NULL)
+				conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, pouncee);
+
+			gaim_conversation_write(conv, NULL, message,
+									GAIM_MESSAGE_SEND, time(NULL));
+
+			serv_send_im(account->gc, (char *)pouncee, (char *)message, 0);
+		}
+	}
+
+	if (gaim_pounce_action_is_enabled(pounce, "execute-command"))
+	{
+		const char *command;
+
+		command = gaim_pounce_action_get_attribute(pounce,
+				"execute-command", "command");
+
+		if (command != NULL)
+		{
+			char *localecmd = g_locale_from_utf8(command, -1, NULL,
+					NULL, NULL);
+
+			if (localecmd != NULL)
+			{
+				int pid = fork();
+
+				if (pid == 0) {
+					char *args[4];
+
+					args[0] = "sh";
+					args[1] = "-c";
+					args[2] = (char *)localecmd;
+					args[3] = NULL;
+
+					execvp(args[0], args);
+
+					_exit(0);
+				}
+				g_free(localecmd);
+			}
+		}
+	}
+
+	if (gaim_pounce_action_is_enabled(pounce, "play-beep"))
+	{
+		beep();
+	}
+}
+
+static void
+free_pounce(GaimPounce *pounce)
+{
+	update_pounces();
+}
+
+static void
+new_pounce(GaimPounce *pounce)
+{
+	gaim_pounce_action_register(pounce, "open-window");
+	gaim_pounce_action_register(pounce, "popup-notify");
+	gaim_pounce_action_register(pounce, "send-message");
+	gaim_pounce_action_register(pounce, "execute-command");
+	gaim_pounce_action_register(pounce, "play-beep");
+
+	update_pounces();
+}
+
+void *
+finch_pounces_get_handle()
+{
+	static int handle;
+
+	return &handle;
+}
+
+void
+finch_pounces_init(void)
+{
+	gaim_pounces_register_handler(GAIM_GNT_UI, pounce_cb, new_pounce,
+								  free_pounce);
+
+	gaim_prefs_add_none("/gaim/gnt/pounces");
+	gaim_prefs_add_none("/gaim/gnt/pounces/default_actions");
+	gaim_prefs_add_bool("/gaim/gnt/pounces/default_actions/open-window",
+						FALSE);
+	gaim_prefs_add_bool("/gaim/gnt/pounces/default_actions/popup-notify",
+						TRUE);
+	gaim_prefs_add_bool("/gaim/gnt/pounces/default_actions/send-message",
+						FALSE);
+	gaim_prefs_add_bool("/gaim/gnt/pounces/default_actions/execute-command",
+						FALSE);
+	gaim_prefs_add_bool("/gaim/gnt/pounces/default_actions/play-beep",
+						FALSE);
+	gaim_prefs_add_none("/gaim/gnt/pounces/dialog");
+
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
+						finch_pounces_get_handle(),
+						GAIM_CALLBACK(signed_on_off_cb), NULL);
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
+						finch_pounces_get_handle(),
+						GAIM_CALLBACK(signed_on_off_cb), NULL);
+}
+
+/* XXX: There's no such thing in pidgin. Perhaps there should be? */
+void finch_pounces_uninit()
+{
+	gaim_pounces_register_handler(GAIM_GNT_UI, NULL, NULL, NULL);
+
+	gaim_signals_disconnect_by_handle(finch_pounces_get_handle());
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntpounce.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,67 @@
+/**
+ * @file gntpounce.h GNT Buddy Pounce API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GAIM_GNTPOUNCE_H_
+#define _GAIM_GNTPOUNCE_H_
+
+#include "pounce.h"
+
+/**
+ * Displays a New Buddy Pounce or Edit Buddy Pounce dialog.
+ *
+ * @param account    The optional account to use.
+ * @param name       The optional name to pounce on.
+ * @param cur_pounce The current buddy pounce, if editing an existing one.
+ */
+void finch_pounce_editor_show(GaimAccount *account, const char *name,
+								GaimPounce *cur_pounce);
+
+/**
+ * Shows the pounces manager window.
+ */
+void finch_pounces_manager_show(void);
+
+/**
+ * Hides the pounces manager window.
+ */
+void finch_pounces_manager_hide(void);
+
+/**
+ * Returns the gtkpounces handle
+ *
+ * @return The handle to the GTK+ pounces system
+ */
+void *finch_pounces_get_handle(void);
+
+/**
+ * Initializes the GNT pounces subsystem.
+ */
+void finch_pounces_init(void);
+
+/**
+ * Uninitializes the GNT pounces subsystem.
+ */
+void finch_pounces_uninit(void);
+
+#endif /* _GAIM_GTKPOUNCE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntprefs.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,286 @@
+/**
+ * @file gntprefs.c GNT Preferences API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <prefs.h>
+#include <savedstatuses.h>
+
+#include "gntgaim.h"
+#include "gntprefs.h"
+#include "gntrequest.h"
+
+#include <string.h>
+
+static GList *freestrings;  /* strings to be freed when the pref-window is closed */
+
+void finch_prefs_init()
+{
+	gaim_prefs_add_none("/gaim");
+	gaim_prefs_add_none("/gaim/gnt");
+
+	gaim_prefs_add_none("/gaim/gnt/plugins");
+	gaim_prefs_add_path_list("/gaim/gnt/plugins/loaded", NULL);
+
+	gaim_prefs_add_none("/gaim/gnt/conversations");
+	gaim_prefs_add_bool("/gaim/gnt/conversations/timestamps", TRUE);
+	gaim_prefs_add_bool("/gaim/gnt/conversations/notify_typing", FALSE); /* XXX: Not functional yet */
+}
+
+typedef struct
+{
+	GaimPrefType type;
+	const char *pref;
+	const char *label;
+	GList *(*lv)();   /* If the value is to be selected from a number of choices */
+} Prefs;
+
+static GList *
+get_log_options()
+{
+	return gaim_log_logger_get_options();
+}
+
+static GList *
+get_idle_options()
+{
+	GList *list = NULL;
+	list = g_list_append(list, "Based on keyboard use"); /* XXX: string freeze */
+	list = g_list_append(list, "system");
+	list = g_list_append(list, (char*)_("From last sent message"));
+	list = g_list_append(list, "gaim");
+	list = g_list_append(list, (char*)_("Never"));
+	list = g_list_append(list, "never");
+	return list;
+}
+
+static GList *
+get_status_titles()
+{
+	GList *list = NULL;
+	const GList *iter;
+	for (iter = gaim_savedstatuses_get_all(); iter; iter = iter->next) {
+		char *str;
+		if (gaim_savedstatus_is_transient(iter->data))
+			continue;
+		str = g_strdup_printf("%ld", gaim_savedstatus_get_creation_time(iter->data));
+		list = g_list_append(list, (char*)gaim_savedstatus_get_title(iter->data));
+		list = g_list_append(list, str);
+		freestrings = g_list_prepend(freestrings, str);
+	}
+	return list;
+}
+
+static GaimRequestField *
+get_pref_field(Prefs *prefs)
+{
+	GaimRequestField *field = NULL;
+
+	if (prefs->lv == NULL)
+	{
+		switch (prefs->type)
+		{
+			case GAIM_PREF_BOOLEAN:
+				field = gaim_request_field_bool_new(prefs->pref, _(prefs->label),
+						gaim_prefs_get_bool(prefs->pref));
+				break;
+			case GAIM_PREF_INT:
+				field = gaim_request_field_int_new(prefs->pref, _(prefs->label),
+						gaim_prefs_get_int(prefs->pref));
+				break;
+			case GAIM_PREF_STRING:
+				field = gaim_request_field_string_new(prefs->pref, _(prefs->label),
+						gaim_prefs_get_string(prefs->pref), FALSE);
+				break;
+			default:
+				break;
+		}
+	}
+	else
+	{
+		GList *list = prefs->lv(), *iter;
+		if (list)
+			field = gaim_request_field_list_new(prefs->pref, _(prefs->label));
+		for (iter = list; iter; iter = iter->next)
+		{
+			gboolean select = FALSE;
+			const char *data = iter->data;
+			int idata;
+			iter = iter->next;
+			switch (prefs->type)
+			{
+				case GAIM_PREF_BOOLEAN:
+					sscanf(iter->data, "%d", &idata);
+					if (gaim_prefs_get_bool(prefs->pref) == idata)
+						select = TRUE;
+					break;
+				case GAIM_PREF_INT:
+					sscanf(iter->data, "%d", &idata);
+					if (gaim_prefs_get_int(prefs->pref) == idata)
+						select = TRUE;
+					break;
+				case GAIM_PREF_STRING:
+					if (strcmp(gaim_prefs_get_string(prefs->pref), iter->data) == 0)
+						select = TRUE;
+					break;
+				default:
+					break;
+			}
+			gaim_request_field_list_add(field, data, iter->data);
+			if (select)
+				gaim_request_field_list_add_selected(field, data);
+		}
+		g_list_free(list);
+	}
+	return field;
+}
+
+static Prefs blist[] = 
+{
+	{GAIM_PREF_BOOLEAN, "/gaim/gnt/blist/idletime", N_("Show Idle Time"), NULL},
+	{GAIM_PREF_BOOLEAN, "/gaim/gnt/blist/showoffline", N_("Show Offline Buddies"), NULL},
+	{GAIM_PREF_NONE, NULL, NULL, NULL}
+};
+
+static Prefs convs[] = 
+{
+	{GAIM_PREF_BOOLEAN, "/gaim/gnt/conversations/timestamps", N_("Show Timestamps"), NULL},
+	{GAIM_PREF_BOOLEAN, "/gaim/gnt/conversations/notify_typing", N_("Notify buddies when you are typing"), NULL},
+	{GAIM_PREF_NONE, NULL, NULL, NULL}
+};
+
+static Prefs logging[] = 
+{
+	{GAIM_PREF_STRING, "/core/logging/format", N_("Log format"), get_log_options},
+	{GAIM_PREF_BOOLEAN, "/core/logging/log_ims", N_("Log IMs"), NULL},
+	{GAIM_PREF_BOOLEAN, "/core/logging/log_chats", N_("Log chats"), NULL},
+	{GAIM_PREF_BOOLEAN, "/core/logging/log_system", N_("Log status change events"), NULL},
+	{GAIM_PREF_NONE, NULL, NULL, NULL},
+};
+
+/* XXX: Translate after the freeze */
+static Prefs idle[] =
+{
+	{GAIM_PREF_STRING, "/core/away/idle_reporting", "Report Idle time", get_idle_options},
+	{GAIM_PREF_BOOLEAN, "/core/away/away_when_idle", "Change status when idle", NULL},
+	{GAIM_PREF_INT, "/core/away/mins_before_away", "Minutes before changing status", NULL},
+	{GAIM_PREF_INT, "/core/savedstatus/idleaway", "Change status to", get_status_titles},
+	{GAIM_PREF_NONE, NULL, NULL, NULL},
+};
+
+static void
+free_strings()
+{
+	g_list_foreach(freestrings, (GFunc)g_free, NULL);
+	g_list_free(freestrings);
+	freestrings = NULL;
+}
+
+static void
+save_cb(void *data, GaimRequestFields *allfields)
+{
+	GList *list;
+	for (list = gaim_request_fields_get_groups(allfields); list; list = list->next)
+	{
+		GaimRequestFieldGroup *group = list->data;
+		GList *fields = gaim_request_field_group_get_fields(group);
+		
+		for (; fields ; fields = fields->next)
+		{
+			GaimRequestField *field = fields->data;
+			GaimRequestFieldType type = gaim_request_field_get_type(field);
+			GaimPrefType pt;
+			gpointer val = NULL;
+			const char *id = gaim_request_field_get_id(field);
+
+			switch (type)
+			{
+				case GAIM_REQUEST_FIELD_LIST:
+					val = gaim_request_field_list_get_selected(field)->data;
+					break;
+				case GAIM_REQUEST_FIELD_BOOLEAN:
+					val = GINT_TO_POINTER(gaim_request_field_bool_get_value(field));
+					break;
+				case GAIM_REQUEST_FIELD_INTEGER:
+					val = GINT_TO_POINTER(gaim_request_field_int_get_value(field));
+					break;
+				case GAIM_REQUEST_FIELD_STRING:
+					val = (gpointer)gaim_request_field_string_get_value(field);
+					break;
+				default:
+					break;
+			}
+
+			pt = gaim_prefs_get_type(id);
+			switch (pt)
+			{
+				case GAIM_PREF_INT:
+					if (type == GAIM_REQUEST_FIELD_LIST) /* Lists always return string */
+						sscanf(val, "%ld", (long int *)&val);
+					gaim_prefs_set_int(id, GPOINTER_TO_INT(val));
+					break;
+				case GAIM_PREF_BOOLEAN:
+					gaim_prefs_set_bool(id, GPOINTER_TO_INT(val));
+					break;
+				case GAIM_PREF_STRING:
+					gaim_prefs_set_string(id, val);
+					break;
+				default:
+					break;
+			}
+		}
+	}
+	free_strings();
+}
+
+static void
+add_pref_group(GaimRequestFields *fields, const char *title, Prefs *prefs)
+{
+	GaimRequestField *field;
+	GaimRequestFieldGroup *group;
+	int i;
+
+	group = gaim_request_field_group_new(title);
+	gaim_request_fields_add_group(fields, group);
+	for (i = 0; prefs[i].pref; i++)
+	{
+		field = get_pref_field(prefs + i);
+		if (field)
+			gaim_request_field_group_add_field(group, field);
+	}
+}
+
+void finch_prefs_show_all()
+{
+	GaimRequestFields *fields;
+
+	fields = gaim_request_fields_new();
+
+	add_pref_group(fields, _("Buddy List"), blist);
+	add_pref_group(fields, _("Conversations"), convs);
+	add_pref_group(fields, _("Logging"), logging);
+	add_pref_group(fields, _("Idle"), idle);
+
+	gaim_request_fields(NULL, _("Preferences"), NULL, NULL, fields,
+			_("Save"), G_CALLBACK(save_cb), _("Cancel"), free_strings, NULL);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntprefs.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,45 @@
+/**
+ * @file gntprefs.h GNT Preferences API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_PREFS_H
+#define _GNT_PREFS_H
+
+/**********************************************************************
+ * @name GNT Preferences API
+ **********************************************************************/
+/*@{*/
+
+/**
+ * Perform necessary initializations.
+ */
+void finch_prefs_init(void);
+
+/**
+ * Show the preferences dialog.
+ */
+void finch_prefs_show_all(void);
+
+/*@}*/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntrequest.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,619 @@
+/**
+ * @file gntrequest.c GNT Request API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntcheckbox.h>
+#include <gntcombobox.h>
+#include <gntentry.h>
+#include <gntlabel.h>
+#include <gntline.h>
+#include <gnttree.h>
+
+#include "gntgaim.h"
+#include "gntrequest.h"
+#include "util.c"
+
+typedef struct
+{
+	void *user_data;
+	GntWidget *entry, *dialog;
+	GCallback *cbs;
+} GaimGntFileRequest;
+
+static GntWidget *
+setup_request_window(const char *title, const char *primary,
+		const char *secondary, GaimRequestType type)
+{
+	GntWidget *window;
+
+	window = gnt_vbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_title(GNT_BOX(window), title);
+	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
+
+	if (primary)
+		gnt_box_add_widget(GNT_BOX(window),
+				gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD));
+	if (secondary)
+		gnt_box_add_widget(GNT_BOX(window), gnt_label_new(secondary));
+
+	g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gaim_request_close),
+			GINT_TO_POINTER(type));
+
+	return window;
+}
+
+static GntWidget *
+setup_button_box(gpointer userdata, gpointer cb, gpointer data, ...)
+{
+	GntWidget *box, *button;
+	va_list list;
+	const char *text;
+	gpointer callback;
+
+	box = gnt_hbox_new(FALSE);
+
+	va_start(list, data);
+
+	while ((text = va_arg(list, const char *)))
+	{
+		callback = va_arg(list, gpointer);
+		button = gnt_button_new(text);
+		gnt_box_add_widget(GNT_BOX(box), button);
+		g_object_set_data(G_OBJECT(button), "activate-callback", callback);
+		g_object_set_data(G_OBJECT(button), "activate-userdata", userdata);
+		g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data);
+	}
+
+	va_end(list);
+	return box;
+}
+
+static void
+notify_input_cb(GntWidget *button, GntWidget *entry)
+{
+	GaimRequestInputCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
+	gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
+	const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
+
+	if (callback)
+		callback(data, text);
+
+	while (button->parent)
+		button = button->parent;
+
+	gaim_request_close(GAIM_REQUEST_INPUT, button);
+}
+
+static void *
+finch_request_input(const char *title, const char *primary,
+		const char *secondary, const char *default_value,
+		gboolean multiline, gboolean masked, gchar *hint,
+		const char *ok_text, GCallback ok_cb,
+		const char *cancel_text, GCallback cancel_cb,
+		void *user_data)
+{
+	GntWidget *window, *box, *entry;
+
+	window = setup_request_window(title, primary, secondary, GAIM_REQUEST_INPUT);
+
+	entry = gnt_entry_new(default_value);
+	if (masked)
+		gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
+	gnt_box_add_widget(GNT_BOX(window), entry);
+
+	box = setup_button_box(user_data, notify_input_cb, entry,
+			ok_text, ok_cb, cancel_text, cancel_cb, NULL);
+	gnt_box_add_widget(GNT_BOX(window), box);
+
+	gnt_widget_show(window);
+
+	return window;
+}
+
+static void
+finch_close_request(GaimRequestType type, gpointer ui_handle)
+{
+	GntWidget *widget = GNT_WIDGET(ui_handle);
+	while (widget->parent)
+		widget = widget->parent;
+	gnt_widget_destroy(widget);
+}
+
+static void
+request_choice_cb(GntWidget *button, GntComboBox *combo)
+{
+	GaimRequestChoiceCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
+	gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
+	int choice = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))) - 1;
+
+	if (callback)
+		callback(data, choice);
+
+	while (button->parent)
+		button = button->parent;
+
+	gaim_request_close(GAIM_REQUEST_INPUT, button);
+}
+
+static void *
+finch_request_choice(const char *title, const char *primary,
+		const char *secondary, unsigned int default_value,
+		const char *ok_text, GCallback ok_cb,
+		const char *cancel_text, GCallback cancel_cb,
+		void *user_data, va_list choices)
+{
+	GntWidget *window, *combo, *box;
+	const char *text;
+	int val;
+
+	window = setup_request_window(title, primary, secondary, GAIM_REQUEST_CHOICE);
+
+	combo = gnt_combo_box_new();
+	gnt_box_add_widget(GNT_BOX(window), combo);
+	while ((text = va_arg(choices, const char *)))
+	{
+		val = va_arg(choices, int);
+		gnt_combo_box_add_data(GNT_COMBO_BOX(combo), GINT_TO_POINTER(val + 1), text);
+	}
+	gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), GINT_TO_POINTER(default_value + 1));
+
+	box = setup_button_box(user_data, request_choice_cb, combo,
+			ok_text, ok_cb, cancel_text, cancel_cb, NULL);
+	gnt_box_add_widget(GNT_BOX(window), box);
+
+	gnt_widget_show(window);
+	
+	return window;
+}
+
+static void
+request_action_cb(GntWidget *button, GntWidget *window)
+{
+	GaimRequestActionCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
+	gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
+	int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "activate-id"));
+
+	if (callback)
+		callback(data, id);
+
+	gaim_request_close(GAIM_REQUEST_ACTION, window);
+}
+
+static void*
+finch_request_action(const char *title, const char *primary,
+		const char *secondary, unsigned int default_value,
+		void *user_data, size_t actioncount,
+		va_list actions)
+{
+	GntWidget *window, *box, *button;
+	int i;
+
+	window = setup_request_window(title, primary, secondary, GAIM_REQUEST_ACTION);
+
+	box = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(window), box);
+	for (i = 0; i < actioncount; i++)
+	{
+		const char *text = va_arg(actions, const char *);
+		GaimRequestActionCb callback = va_arg(actions, GaimRequestActionCb);
+
+		button = gnt_button_new(text);
+		gnt_box_add_widget(GNT_BOX(box), button);
+
+		g_object_set_data(G_OBJECT(button), "activate-callback", callback);
+		g_object_set_data(G_OBJECT(button), "activate-userdata", user_data);
+		g_object_set_data(G_OBJECT(button), "activate-id", GINT_TO_POINTER(i));
+		g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(request_action_cb), window);
+	}
+
+	gnt_widget_show(window);
+
+	return window;
+}
+
+static void
+request_fields_cb(GntWidget *button, GaimRequestFields *fields)
+{
+	GaimRequestFieldsCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
+	gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
+	GList *list;
+
+	/* Update the data of the fields. GtkGaim does this differently. Instead of
+	 * updating the fields at the end like here, it updates the appropriate field
+	 * instantly whenever a change is made. That allows it to make sure the
+	 * 'required' fields are entered before the user can hit OK. It's not the case
+	 * here, althought it can be done. I am not honouring the 'required' fields
+	 * for the moment. */
+	for (list = gaim_request_fields_get_groups(fields); list; list = list->next)
+	{
+		GaimRequestFieldGroup *group = list->data;
+		GList *fields = gaim_request_field_group_get_fields(group);
+		
+		for (; fields ; fields = fields->next)
+		{
+			GaimRequestField *field = fields->data;
+			GaimRequestFieldType type = gaim_request_field_get_type(field);
+			if (type == GAIM_REQUEST_FIELD_BOOLEAN)
+			{
+				GntWidget *check = field->ui_data;
+				gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check));
+				gaim_request_field_bool_set_value(field, value);
+			}
+			else if (type == GAIM_REQUEST_FIELD_STRING)
+			{
+				GntWidget *entry = field->ui_data;
+				const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
+				gaim_request_field_string_set_value(field, (text && *text) ? text : NULL);
+			}
+			else if (type == GAIM_REQUEST_FIELD_INTEGER)
+			{
+				GntWidget *entry = field->ui_data;
+				const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
+				int value = (text && *text) ? atoi(text) : 0;
+				gaim_request_field_int_set_value(field, value);
+			}
+			else if (type == GAIM_REQUEST_FIELD_CHOICE)
+			{
+				GntWidget *combo = field->ui_data;
+				int id;
+				id = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)));
+				gaim_request_field_choice_set_value(field, id);
+			}
+			else if (type == GAIM_REQUEST_FIELD_LIST)
+			{
+				GList *list = NULL;
+				if (gaim_request_field_list_get_multi_select(field))
+				{
+					const GList *iter;
+					GntWidget *tree = field->ui_data;
+
+					iter = gaim_request_field_list_get_items(field);
+					for (; iter; iter = iter->next)
+					{
+						const char *text = iter->data;
+						gpointer key = gaim_request_field_list_get_data(field, text);
+						if (gnt_tree_get_choice(GNT_TREE(tree), key))
+							list = g_list_prepend(list, key);
+					}
+				}
+				else
+				{
+					GntWidget *combo = field->ui_data;
+					gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
+					list = g_list_append(list, data);
+				}
+
+				gaim_request_field_list_set_selected(field, list);
+				g_list_free(list);
+			}
+			else if (type == GAIM_REQUEST_FIELD_ACCOUNT)
+			{
+				GntWidget *combo = field->ui_data;
+				GaimAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
+				gaim_request_field_account_set_value(field, acc);
+			}
+		}
+	}
+
+	if (callback)
+		callback(data, fields);
+
+	while (button->parent)
+		button = button->parent;
+
+	gaim_request_close(GAIM_REQUEST_FIELDS, button);
+}
+
+static void *
+finch_request_fields(const char *title, const char *primary,
+		const char *secondary, GaimRequestFields *allfields,
+		const char *ok, GCallback ok_cb,
+		const char *cancel, GCallback cancel_cb,
+		void *userdata)
+{
+	GntWidget *window, *box;
+	GList *grlist;
+
+	window = setup_request_window(title, primary, secondary, GAIM_REQUEST_FIELDS);
+
+	/* This is how it's going to work: the request-groups are going to be
+	 * stacked vertically one after the other. A GntLine will be separating
+	 * the groups. */
+	box = gnt_vbox_new(FALSE);
+	gnt_box_set_pad(GNT_BOX(box), 0);
+	gnt_box_set_fill(GNT_BOX(box), TRUE);
+	for (grlist = gaim_request_fields_get_groups(allfields); grlist; grlist = grlist->next)
+	{
+		GaimRequestFieldGroup *group = grlist->data;
+		GList *fields = gaim_request_field_group_get_fields(group);
+		GntWidget *hbox;
+		const char *title = gaim_request_field_group_get_title(group);
+
+		if (title)
+			gnt_box_add_widget(GNT_BOX(box),
+					gnt_label_new_with_format(title, GNT_TEXT_FLAG_BOLD));
+
+		for (; fields ; fields = fields->next)
+		{
+			/* XXX: Break each of the fields into a separate function? */
+			GaimRequestField *field = fields->data;
+			GaimRequestFieldType type = gaim_request_field_get_type(field);
+			const char *label = gaim_request_field_get_label(field);
+				
+			hbox = gnt_hbox_new(TRUE);   /* hrm */
+			gnt_box_add_widget(GNT_BOX(box), hbox);
+			
+			if (type != GAIM_REQUEST_FIELD_BOOLEAN && label)
+			{
+				GntWidget *l = gnt_label_new(label);
+				gnt_widget_set_size(l, 0, 1);
+				gnt_box_add_widget(GNT_BOX(hbox), l);
+			}
+
+			if (type == GAIM_REQUEST_FIELD_BOOLEAN)
+			{
+				GntWidget *check = gnt_check_box_new(label);
+				gnt_check_box_set_checked(GNT_CHECK_BOX(check),
+						gaim_request_field_bool_get_default_value(field));
+				gnt_box_add_widget(GNT_BOX(hbox), check);
+				field->ui_data = check;
+			}
+			else if (type == GAIM_REQUEST_FIELD_STRING)
+			{
+				GntWidget *entry = gnt_entry_new(
+							gaim_request_field_string_get_default_value(field));
+				gnt_entry_set_masked(GNT_ENTRY(entry),
+						gaim_request_field_string_is_masked(field));
+				gnt_box_add_widget(GNT_BOX(hbox), entry);
+				field->ui_data = entry;
+			}
+			else if (type == GAIM_REQUEST_FIELD_INTEGER)
+			{
+				char str[256];
+				int val = gaim_request_field_int_get_default_value(field);
+				GntWidget *entry;
+				
+				snprintf(str, sizeof(str), "%d", val);
+				entry = gnt_entry_new(str);
+				gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
+				gnt_box_add_widget(GNT_BOX(hbox), entry);
+				field->ui_data = entry;
+			}
+			else if (type == GAIM_REQUEST_FIELD_CHOICE)
+			{
+				int id;
+				const GList *list;
+				GntWidget *combo = gnt_combo_box_new();
+				gnt_box_add_widget(GNT_BOX(hbox), combo);
+				field->ui_data = combo;
+
+				list = gaim_request_field_choice_get_labels(field);
+				for (id = 1; list; list = list->next, id++)
+				{
+					gnt_combo_box_add_data(GNT_COMBO_BOX(combo),
+							GINT_TO_POINTER(id), list->data);
+				}
+				gnt_combo_box_set_selected(GNT_COMBO_BOX(combo),
+						GINT_TO_POINTER(gaim_request_field_choice_get_default_value(field)));
+			}
+			else if (type == GAIM_REQUEST_FIELD_LIST)
+			{
+				const GList *list;
+				gboolean multi = gaim_request_field_list_get_multi_select(field);
+				if (multi)
+				{
+					GntWidget *tree = gnt_tree_new();
+					gnt_box_add_widget(GNT_BOX(hbox), tree);
+					field->ui_data = tree;
+
+					list = gaim_request_field_list_get_items(field);
+					for (; list; list = list->next)
+					{
+						const char *text = list->data;
+						gpointer key = gaim_request_field_list_get_data(field, text);
+						gnt_tree_add_choice(GNT_TREE(tree), key,
+								gnt_tree_create_row(GNT_TREE(tree), text), NULL, NULL);
+						if (gaim_request_field_list_is_selected(field, text))
+							gnt_tree_set_choice(GNT_TREE(tree), key, TRUE);
+					}
+				}
+				else
+				{
+					GntWidget *combo = gnt_combo_box_new();
+					gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
+					gnt_box_add_widget(GNT_BOX(hbox), combo);
+					field->ui_data = combo;
+
+					list = gaim_request_field_list_get_items(field);
+					for (; list; list = list->next)
+					{
+						const char *text = list->data;
+						gpointer key = gaim_request_field_list_get_data(field, text);
+						gnt_combo_box_add_data(GNT_COMBO_BOX(combo), key, text);
+						if (gaim_request_field_list_is_selected(field, text))
+							gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), key);
+					}
+				}
+			}
+			else if (type == GAIM_REQUEST_FIELD_ACCOUNT)
+			{
+				gboolean all;
+				GaimAccount *def;
+				GList *list;
+				GntWidget *combo = gnt_combo_box_new();
+				gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
+				gnt_box_add_widget(GNT_BOX(hbox), combo);
+				field->ui_data = combo;
+
+				all = gaim_request_field_account_get_show_all(field);
+				def = gaim_request_field_account_get_default_value(field);
+
+				if (all)
+					list = gaim_accounts_get_all();
+				else
+					list = gaim_connections_get_all();
+
+				for (; list; list = list->next)
+				{
+					GaimAccount *account;
+					char *text;
+
+					if (all)
+						account = list->data;
+					else
+						account = gaim_connection_get_account(list->data);
+
+					text = g_strdup_printf("%s (%s)",
+							gaim_account_get_username(account),
+							gaim_account_get_protocol_name(account));
+					gnt_combo_box_add_data(GNT_COMBO_BOX(combo), account, text);
+					g_free(text);
+					if (account == def)
+						gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), account);
+				}
+				gnt_widget_set_size(combo, 20, 3); /* ew */
+			}
+			else
+			{
+				gnt_box_add_widget(GNT_BOX(hbox),
+						gnt_label_new_with_format(_("Not implemented yet."),
+							GNT_TEXT_FLAG_BOLD));
+			}
+		}
+		if (grlist->next)
+			gnt_box_add_widget(GNT_BOX(box), gnt_hline_new());
+	}
+	gnt_box_add_widget(GNT_BOX(window), box);
+
+	box = setup_button_box(userdata, request_fields_cb, allfields,
+			ok, ok_cb, cancel, cancel_cb, NULL);
+	gnt_box_add_widget(GNT_BOX(window), box);
+
+	gnt_widget_show(window);
+	
+	return window;
+}
+
+static void
+file_cancel_cb(GntWidget *wid, gpointer fq)
+{
+	GaimGntFileRequest *data = fq;
+	if (data->cbs[1] != NULL)
+		((GaimRequestFileCb)data->cbs[1])(data->user_data, NULL);
+
+	gaim_request_close(GAIM_REQUEST_FILE, data->dialog);
+}
+
+static void
+file_ok_cb(GntWidget *wid, gpointer fq)
+{
+	GaimGntFileRequest *data = fq;
+	if (data->cbs[0] != NULL)
+		((GaimRequestFileCb)data->cbs[0])(data->user_data, gnt_entry_get_text(GNT_ENTRY(data->entry)));
+
+	gaim_request_close(GAIM_REQUEST_FILE, data->dialog);
+}
+
+static void
+file_request_destroy(GaimGntFileRequest *data)
+{
+	g_free(data->cbs);
+	g_free(data);
+}
+
+static void *
+finch_request_file(const char *title, const char *filename,
+				gboolean savedialog,
+				GCallback ok_cb, GCallback cancel_cb,
+				void *user_data)
+{
+	GntWidget *window = gnt_vbox_new(FALSE);
+	GntWidget *entry, *hbox, *button;
+	GaimGntFileRequest *data = g_new0(GaimGntFileRequest, 1);
+
+	data->user_data = user_data;
+	data->cbs = g_new0(GCallback, 2);
+	data->cbs[0] = ok_cb;
+	data->cbs[1] = cancel_cb;
+	data->dialog = window;
+	data->entry = entry = gnt_entry_new(g_strconcat(gaim_home_dir(), G_DIR_SEPARATOR_S, filename, NULL));
+	gnt_widget_set_size(entry, 30, 1);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_title(GNT_BOX(window), title ? title : (savedialog ? _("Save File...") : _("Open File...")));
+#if 0
+	/* After the string freeze */
+	gnt_box_add_widget(GNT_BOX(window), gnt_label_new(_("Please enter a full path for a file")));
+#endif
+	gnt_box_add_widget(GNT_BOX(window), entry);
+
+	hbox = gnt_hbox_new(TRUE);
+	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
+
+	button = gnt_button_new(_("Cancel"));
+	g_signal_connect(G_OBJECT(button), "activate",
+		G_CALLBACK(file_cancel_cb), data);
+	gnt_box_add_widget(GNT_BOX(hbox), button);
+
+	button = gnt_button_new(_("OK"));
+	g_signal_connect(G_OBJECT(button), "activate",
+		G_CALLBACK(file_ok_cb), data);
+	gnt_box_add_widget(GNT_BOX(hbox), button);
+
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+
+	g_signal_connect_swapped(G_OBJECT(window), "destroy",
+			G_CALLBACK(file_request_destroy), data);
+
+	gnt_widget_show(window);
+
+	return window;
+}
+
+static GaimRequestUiOps uiops =
+{
+	.request_input = finch_request_input,
+	.close_request = finch_close_request,
+	.request_choice = finch_request_choice,
+	.request_action = finch_request_action,
+	.request_fields = finch_request_fields,
+	.request_file = finch_request_file,
+	.request_folder = NULL                        /* No plans for this */
+};
+
+GaimRequestUiOps *finch_request_get_ui_ops()
+{
+	return &uiops;
+}
+
+void finch_request_init()
+{
+}
+
+void finch_request_uninit()
+{
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntrequest.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,54 @@
+/**
+ * @file gntrequest.h GNT Request API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_REQUEST_H
+#define _GNT_REQUEST_H
+
+#include "request.h"
+
+/**********************************************************************
+ * @name GNT Request API
+ **********************************************************************/
+/*@{*/
+
+/**
+ * Get the ui-functions.
+ *
+ * @return The GaimRequestUiOps structure populated with the appropriate functions.
+ */
+GaimRequestUiOps *finch_request_get_ui_ops(void);
+
+/**
+ * Perform necessary initializations.
+ */
+void finch_request_init(void);
+
+/**
+ * Perform necessary uninitializations.
+ */
+void finch_request_uninit(void);
+
+/*@}*/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntstatus.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,606 @@
+/**
+ * @file gntstatus.c GNT Status API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntcombobox.h>
+#include <gntentry.h>
+#include <gntlabel.h>
+#include <gntline.h>
+#include <gnttree.h>
+
+#include <notify.h>
+#include <request.h>
+
+#include "gntgaim.h"
+#include "gntstatus.h"
+
+static struct
+{
+	GntWidget *window;
+	GntWidget *tree;
+} statuses;
+
+typedef struct
+{
+	GaimSavedStatus *saved;
+	GntWidget *window;
+	GntWidget *title;
+	GntWidget *type;
+	GntWidget *message;
+	GntWidget *tree;
+	GHashTable *hash;  /* list of windows for substatuses */
+} EditStatus;
+
+typedef struct
+{
+	GaimAccount *account;
+	const GaimStatusType *type;
+	char *message;
+} RowInfo;
+
+typedef struct
+{
+	GntWidget *window;
+	GntWidget *type;
+	GntWidget *message;
+
+	EditStatus *parent;
+	RowInfo *key;
+} EditSubStatus;
+
+static GList *edits;  /* List of opened edit-status dialogs */
+
+static void
+reset_status_window(GntWidget *widget, gpointer null)
+{
+	statuses.window = NULL;
+	statuses.tree = NULL;
+}
+
+static void
+populate_statuses(GntTree *tree)
+{
+	const GList *list;
+
+	for (list = gaim_savedstatuses_get_all(); list; list = list->next)
+	{
+		GaimSavedStatus *saved = list->data;
+		const char *title, *type, *message;
+
+		if (gaim_savedstatus_is_transient(saved))
+			continue;
+
+		title = gaim_savedstatus_get_title(saved);
+		type = gaim_primitive_get_name_from_type(gaim_savedstatus_get_type(saved));
+		message = gaim_savedstatus_get_message(saved);  /* XXX: Strip possible markups */
+
+		gnt_tree_add_row_last(tree, saved,
+				gnt_tree_create_row(tree, title, type, message), NULL);
+	}
+}
+
+static void
+really_delete_status(GaimSavedStatus *saved)
+{
+	GList *iter;
+
+	for (iter = edits; iter; iter = iter->next)
+	{
+		EditStatus *edit = iter->data;
+		if (edit->saved == saved)
+		{
+			gnt_widget_destroy(edit->window);
+			break;
+		}
+	}
+
+	if (statuses.tree)
+		gnt_tree_remove(GNT_TREE(statuses.tree), saved);
+
+	gaim_savedstatus_delete(gaim_savedstatus_get_title(saved));
+}
+
+static void
+ask_before_delete(GntWidget *button, gpointer null)
+{
+	char *ask;
+	GaimSavedStatus *saved;
+
+	g_return_if_fail(statuses.tree != NULL);
+
+	saved = gnt_tree_get_selection_data(GNT_TREE(statuses.tree));
+	ask = g_strdup_printf(_("Are you sure you want to delete \"%s\""),
+			gaim_savedstatus_get_title(saved));
+
+	gaim_request_action(saved, _("Delete Status"), ask, NULL, 0, saved, 2,
+			_("Delete"), really_delete_status, _("Cancel"), NULL);
+	g_free(ask);
+}
+
+static void
+use_savedstatus_cb(GntWidget *widget, gpointer null)
+{
+	g_return_if_fail(statuses.tree != NULL);
+
+	gaim_savedstatus_activate(gnt_tree_get_selection_data(GNT_TREE(statuses.tree)));
+}
+
+static void
+edit_savedstatus_cb(GntWidget *widget, gpointer null)
+{
+	g_return_if_fail(statuses.tree != NULL);
+
+	finch_savedstatus_edit(gnt_tree_get_selection_data(GNT_TREE(statuses.tree)));
+}
+
+void finch_savedstatus_show_all()
+{
+	GntWidget *window, *tree, *box, *button;
+	if (statuses.window)
+		return;
+
+	statuses.window = window = gnt_vbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_title(GNT_BOX(window), _("Saved Statuses"));
+	gnt_box_set_fill(GNT_BOX(window), FALSE);
+	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
+	gnt_box_set_pad(GNT_BOX(window), 0);
+
+	/* XXX: Add some sorting function to sort alphabetically, perhaps */
+	statuses.tree = tree = gnt_tree_new_with_columns(3);
+	gnt_tree_set_column_titles(GNT_TREE(tree), _("Title"), _("Type"), _("Message"));
+	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
+	gnt_tree_set_col_width(GNT_TREE(tree), 0, 25);
+	gnt_tree_set_col_width(GNT_TREE(tree), 1, 12);
+	gnt_tree_set_col_width(GNT_TREE(tree), 2, 35);
+	gnt_box_add_widget(GNT_BOX(window), tree);
+
+	populate_statuses(GNT_TREE(tree));
+
+	box = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(window), box);
+
+	button = gnt_button_new(_("Use"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect(G_OBJECT(button), "activate",
+			G_CALLBACK(use_savedstatus_cb), NULL);
+
+	button = gnt_button_new(_("Add"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect_swapped(G_OBJECT(button), "activate",
+			G_CALLBACK(finch_savedstatus_edit), NULL);
+
+	button = gnt_button_new(_("Edit"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect(G_OBJECT(button), "activate",
+			G_CALLBACK(edit_savedstatus_cb), NULL);
+
+	button = gnt_button_new(_("Delete"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect(G_OBJECT(button), "activate",
+			G_CALLBACK(ask_before_delete), NULL);
+
+	button = gnt_button_new(_("Close"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect_swapped(G_OBJECT(button), "activate",
+			G_CALLBACK(gnt_widget_destroy), window);
+
+	g_signal_connect(G_OBJECT(window), "destroy",
+			G_CALLBACK(reset_status_window), NULL);
+	gnt_widget_show(window);
+}
+
+static void
+destroy_substatus_win(GaimAccount *account, EditSubStatus *sub, gpointer null)
+{
+	gnt_widget_destroy(sub->window);   /* the "destroy" callback will remove entry from the hashtable */
+}
+
+static void
+free_key(gpointer key, gpointer n)
+{
+	RowInfo *row = key;
+	g_free(row->message);
+	g_free(key);
+}
+
+
+static void
+update_edit_list(GntWidget *widget, EditStatus *edit)
+{
+	edits = g_list_remove(edits, edit);
+	gaim_notify_close_with_handle(edit);
+	g_hash_table_foreach(edit->hash, (GHFunc)destroy_substatus_win, NULL);
+	g_list_foreach((GList*)gnt_tree_get_rows(GNT_TREE(edit->tree)), free_key, NULL);
+	g_free(edit);
+}
+
+static void
+set_substatuses(EditStatus *edit)
+{
+	const GList *iter;
+	for (iter = gnt_tree_get_rows(GNT_TREE(edit->tree)); iter; iter = iter->next) {
+		RowInfo *key = iter->data;
+		if (gnt_tree_get_choice(GNT_TREE(edit->tree), key)) {
+			gaim_savedstatus_set_substatus(edit->saved, key->account, key->type, key->message);
+		}
+	}
+}
+
+
+static void
+use_trans_status_cb(GntWidget *button, EditStatus *edit)
+{
+	const char *message;
+	GaimStatusPrimitive prim;
+	GaimSavedStatus *saved;
+
+	message = gnt_entry_get_text(GNT_ENTRY(edit->message));
+	prim = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(edit->type)));
+
+	saved = gaim_savedstatus_find_transient_by_type_and_message(prim, message);
+	if (saved == NULL) {
+		saved = gaim_savedstatus_new(NULL, prim);
+		edit->saved = saved;
+		set_substatuses(edit);
+	}
+	gaim_savedstatus_set_message(saved, message);
+	gaim_savedstatus_activate(saved);
+	gnt_widget_destroy(edit->window);
+}
+
+static void
+save_savedstatus_cb(GntWidget *button, EditStatus *edit)
+{
+	const char *title, *message;
+	GaimStatusPrimitive prim;
+	GaimSavedStatus *find;
+
+	title = gnt_entry_get_text(GNT_ENTRY(edit->title));
+	message = gnt_entry_get_text(GNT_ENTRY(edit->message));
+	if (!message || !*message)
+		message = NULL;
+
+	prim = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(edit->type)));
+
+	if (!title || !*title)
+	{
+		gaim_notify_error(edit, _("Error"), _("Invalid title"),
+				_("Please enter a non-empty title for the status."));
+		return;
+	}
+
+	find = gaim_savedstatus_find(title);
+	if (find && find != edit->saved)
+	{
+		gaim_notify_error(edit, _("Error"), _("Duplicate title"),
+				_("Please enter a different title for the status."));
+		return;
+	}
+	
+	if (edit->saved == NULL)
+	{
+		edit->saved = gaim_savedstatus_new(title, prim);
+		gaim_savedstatus_set_message(edit->saved, message);
+		set_substatuses(edit);
+		if (statuses.tree)
+			gnt_tree_add_row_last(GNT_TREE(statuses.tree), edit->saved,
+					gnt_tree_create_row(GNT_TREE(statuses.tree), title,
+						gaim_primitive_get_name_from_type(prim), message), NULL);
+	}
+	else
+	{
+		gaim_savedstatus_set_title(edit->saved, title);
+		gaim_savedstatus_set_type(edit->saved, prim);
+		gaim_savedstatus_set_message(edit->saved, message);
+		if (statuses.tree)
+		{
+			gnt_tree_change_text(GNT_TREE(statuses.tree), edit->saved, 0, title);
+			gnt_tree_change_text(GNT_TREE(statuses.tree), edit->saved, 1,
+						gaim_primitive_get_name_from_type(prim));
+			gnt_tree_change_text(GNT_TREE(statuses.tree), edit->saved, 2, message);
+		}
+	}
+
+	if (g_object_get_data(G_OBJECT(button), "use"))
+		gaim_savedstatus_activate(edit->saved);
+
+	gnt_widget_destroy(edit->window);
+}
+
+static void
+add_substatus(EditStatus *edit, GaimAccount *account)
+{
+	char *name;
+	const char *type = NULL, *message = NULL;
+	GaimSavedStatusSub *sub = NULL;
+	RowInfo *key;
+
+	if (!edit || !edit->tree)
+		return;
+
+	if (edit->saved)
+		sub = gaim_savedstatus_get_substatus(edit->saved, account);
+
+	key = g_new0(RowInfo, 1);
+	key->account = account;
+
+	if (sub)
+	{
+		key->type = gaim_savedstatus_substatus_get_type(sub);
+		type = gaim_status_type_get_name(key->type);
+		message = gaim_savedstatus_substatus_get_message(sub);
+		key->message = g_strdup(message);
+	}
+
+	name = g_strdup_printf("%s (%s)", gaim_account_get_username(account),
+			gaim_account_get_protocol_name(account));
+	gnt_tree_add_choice(GNT_TREE(edit->tree), key,
+			gnt_tree_create_row(GNT_TREE(edit->tree),
+				name, type ? type : "", message ? message : ""), NULL, NULL);
+
+	if (sub)
+		gnt_tree_set_choice(GNT_TREE(edit->tree), key, TRUE);
+	g_free(name);
+}
+
+static void
+substatus_window_destroy_cb(GntWidget *window, EditSubStatus *sub)
+{
+	g_hash_table_remove(sub->parent->hash, sub->key->account);
+	g_free(sub);
+}
+
+static void
+save_substatus_cb(GntWidget *widget, EditSubStatus *sub)
+{
+	GaimSavedStatus *saved = sub->parent->saved;
+	RowInfo *row = sub->key;
+	const char *message;
+	GaimStatusType *type;
+
+	type = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(sub->type));
+	message = gnt_entry_get_text(GNT_ENTRY(sub->message));
+
+	row->type = type;
+	row->message = g_strdup(message);
+
+	if (saved)    /* Save the substatus if the savedstatus actually exists. */
+		gaim_savedstatus_set_substatus(saved, row->account, type, message);
+
+	gnt_tree_set_choice(GNT_TREE(sub->parent->tree), row, TRUE);
+	gnt_tree_change_text(GNT_TREE(sub->parent->tree), row, 1,
+			gaim_status_type_get_name(type));
+	gnt_tree_change_text(GNT_TREE(sub->parent->tree), row, 2, message);
+	
+	gnt_widget_destroy(sub->window);
+}
+
+static gboolean
+popup_substatus(GntTree *tree, const char *key, EditStatus *edit)
+{
+	if (key[0] == ' ' && key[1] == 0)
+	{
+		EditSubStatus *sub;
+		GntWidget *window, *combo, *entry, *box, *button, *l;
+		GaimSavedStatusSub *substatus = NULL;
+		const GList *iter;
+		char *name;
+		RowInfo *selected = gnt_tree_get_selection_data(tree);
+		GaimAccount *account = selected->account;
+
+		if (gnt_tree_get_choice(tree, selected))
+		{
+			/* There was a savedstatus for this account. Now remove it. */
+			g_free(selected->message);
+			selected->type = NULL;
+			selected->message = NULL;
+			/* XXX: should we really be saving it right now? */
+			gaim_savedstatus_unset_substatus(edit->saved, account);
+			gnt_tree_change_text(tree, account, 1, NULL);
+			gnt_tree_change_text(tree, account, 2, NULL);
+			return FALSE;
+		}
+
+		if (g_hash_table_lookup(edit->hash, account))
+			return TRUE;
+
+		if (edit->saved)
+			substatus = gaim_savedstatus_get_substatus(edit->saved, account);
+
+		sub = g_new0(EditSubStatus, 1);
+		sub->parent = edit;
+		sub->key = selected;
+
+		sub->window = window = gnt_vbox_new(FALSE);
+		gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+		gnt_box_set_title(GNT_BOX(window), _("Substatus"));  /* XXX: a better title */
+
+		box = gnt_hbox_new(FALSE);
+		gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Account:")));
+		name = g_strdup_printf("%s (%s)", gaim_account_get_username(account),
+				gaim_account_get_protocol_name(account));
+		gnt_box_add_widget(GNT_BOX(box), gnt_label_new(name));
+		g_free(name);
+		gnt_box_add_widget(GNT_BOX(window), box);
+
+		box = gnt_hbox_new(FALSE);
+		gnt_box_add_widget(GNT_BOX(box), (l = gnt_label_new(_("Status:"))));
+		gnt_widget_set_size(l, 0, 1);   /* I don't like having to do this */
+		sub->type = combo = gnt_combo_box_new();
+		gnt_box_add_widget(GNT_BOX(box), combo);
+		gnt_box_add_widget(GNT_BOX(window), box);
+
+		for (iter = gaim_account_get_status_types(account); iter; iter = iter->next)
+		{
+			GaimStatusType *type = iter->data;
+			if (!gaim_status_type_is_user_settable(type))
+				continue;
+			gnt_combo_box_add_data(GNT_COMBO_BOX(combo), type, gaim_status_type_get_name(type));
+		}
+
+		box = gnt_hbox_new(FALSE);
+		gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Message:")));
+		sub->message = entry = gnt_entry_new(substatus ? gaim_savedstatus_substatus_get_message(substatus) : NULL);
+		gnt_box_add_widget(GNT_BOX(box), entry);
+		gnt_box_add_widget(GNT_BOX(window), box);
+
+		box  = gnt_hbox_new(FALSE);
+		button = gnt_button_new(_("Cancel"));
+		g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window);
+		gnt_box_add_widget(GNT_BOX(box), button);
+		button = gnt_button_new(_("Save"));
+		g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_substatus_cb), sub);
+		gnt_box_add_widget(GNT_BOX(box), button);
+		gnt_box_add_widget(GNT_BOX(window), box);
+
+		gnt_widget_show(window);
+
+		g_hash_table_insert(edit->hash, account, sub);
+
+		g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(substatus_window_destroy_cb), sub);
+
+		return TRUE;
+	}
+	return FALSE;
+}
+
+void finch_savedstatus_edit(GaimSavedStatus *saved)
+{
+	EditStatus *edit;
+	GntWidget *window, *box, *button, *entry, *combo, *label, *tree;
+	GaimStatusPrimitive prims[] = {GAIM_STATUS_AVAILABLE, GAIM_STATUS_AWAY,
+		GAIM_STATUS_INVISIBLE, GAIM_STATUS_OFFLINE, GAIM_STATUS_UNSET}, current;
+	GList *iter;
+	int i;
+
+	if (saved)
+	{
+		GList *iter;
+		for (iter = edits; iter; iter = iter->next)
+		{
+			edit = iter->data;
+			if (edit->saved == saved)
+				return;
+		}
+	}
+
+	edit = g_new0(EditStatus, 1);
+	edit->saved = saved;
+	edit->window = window = gnt_vbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_title(GNT_BOX(window), _("Edit Status"));
+	gnt_box_set_fill(GNT_BOX(window), TRUE);
+	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_LEFT);
+	gnt_box_set_pad(GNT_BOX(window), 0);
+
+	edits = g_list_append(edits, edit);
+
+	/* Title */
+	box = gnt_hbox_new(FALSE);
+	gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_LEFT);
+	gnt_box_add_widget(GNT_BOX(window), box);
+	gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Title")));
+
+	edit->title = entry = gnt_entry_new(saved ? gaim_savedstatus_get_title(saved) : NULL);
+	gnt_box_add_widget(GNT_BOX(box), entry);
+
+	/* Type */
+	box = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(window), box);
+	gnt_box_add_widget(GNT_BOX(box), label = gnt_label_new(_("Status")));
+	gnt_widget_set_size(label, 0, 1);
+
+	edit->type = combo = gnt_combo_box_new();
+	gnt_box_add_widget(GNT_BOX(box), combo);
+	current = saved ? gaim_savedstatus_get_type(saved) : GAIM_STATUS_UNSET;
+	for (i = 0; prims[i] != GAIM_STATUS_UNSET; i++)
+	{
+		gnt_combo_box_add_data(GNT_COMBO_BOX(combo), GINT_TO_POINTER(prims[i]),
+				gaim_primitive_get_name_from_type(prims[i]));
+		if (prims[i] == current)
+			gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), GINT_TO_POINTER(current));
+	}
+
+	/* Message */
+	box = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(window), box);
+	gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Message")));
+
+	edit->message = entry = gnt_entry_new(saved ? gaim_savedstatus_get_message(saved) : NULL);
+	gnt_box_add_widget(GNT_BOX(window), entry);
+
+	gnt_box_add_widget(GNT_BOX(window), gnt_hline_new());
+	gnt_box_add_widget(GNT_BOX(window), gnt_label_new(_("Use different status for following accounts")));
+
+	edit->hash = g_hash_table_new(g_direct_hash, g_direct_equal);
+	edit->tree = tree = gnt_tree_new_with_columns(3);
+	gnt_box_add_widget(GNT_BOX(window), tree);
+	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
+	gnt_tree_set_column_titles(GNT_TREE(tree), _("Account"), _("Status"), _("Message"));
+	gnt_tree_set_col_width(GNT_TREE(tree), 0, 30);
+	gnt_tree_set_col_width(GNT_TREE(tree), 1, 10);
+	gnt_tree_set_col_width(GNT_TREE(tree), 2, 30);
+
+	for (iter = gaim_accounts_get_all(); iter; iter = iter->next)
+	{
+		add_substatus(edit, iter->data);
+	}
+
+	g_signal_connect(G_OBJECT(tree), "key_pressed", G_CALLBACK(popup_substatus), edit);
+
+	/* The buttons */
+	box = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(window), box);
+
+	/* Use */
+	button = gnt_button_new(_("Use"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(use_trans_status_cb), edit);
+
+	/* Save */
+	button = gnt_button_new(_("Save"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_object_set_data(G_OBJECT(button), "use", NULL);
+	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_savedstatus_cb), edit);
+
+	/* Save & Use */
+	button = gnt_button_new(_("Save & Use"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_object_set_data(G_OBJECT(button), "use", GINT_TO_POINTER(TRUE));
+	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_savedstatus_cb), edit);
+
+	/* Cancel */
+	button = gnt_button_new(_("Cancel"));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect_swapped(G_OBJECT(button), "activate",
+			G_CALLBACK(gnt_widget_destroy), window);
+
+	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(update_edit_list), edit);
+
+	gnt_widget_show(window);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntstatus.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,50 @@
+/**
+ * @file gntstatus.h GNT Status API
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_STATUS_H
+#define _GNT_STATUS_H
+
+#include <status.h>
+#include <savedstatuses.h>
+
+/**********************************************************************
+ * @name GNT BuddyList API
+ **********************************************************************/
+/*@{*/
+
+/**
+ * Show a dialog with all the saved statuses.
+ */
+void finch_savedstatus_show_all(void);
+
+/**
+ * Show a dialog to edit a status.
+ *
+ * @param saved The saved status to edit. Set it to @c NULL to create a new status.
+ */
+void finch_savedstatus_edit(GaimSavedStatus *saved);
+
+/*@}*/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntui.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,118 @@
+/**
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "gntui.h"
+
+#include "gntaccount.h"
+#include "gntblist.h"
+#include "gntconn.h"
+#include "gntconv.h"
+#include "gntdebug.h"
+#include "gntft.h"
+#include "gntnotify.h"
+#include "gntplugin.h"
+#include "gntpounce.h"
+#include "gntprefs.h"
+#include "gntrequest.h"
+#include "gntstatus.h"
+#include "internal.h"
+
+#include <prefs.h>
+
+void gnt_ui_init()
+{
+#ifdef STANDALONE
+	gnt_init();
+#endif
+
+	gaim_prefs_add_none("/gaim/gnt");
+	
+	/* Accounts */
+	finch_accounts_init();
+	gaim_accounts_set_ui_ops(finch_accounts_get_ui_ops());
+
+	/* Connections */
+	finch_connections_init();
+	gaim_connections_set_ui_ops(finch_connections_get_ui_ops());
+
+	/* Initialize the buddy list */
+	finch_blist_init();
+	gaim_blist_set_ui_ops(finch_blist_get_ui_ops());
+
+	/* Now the conversations */
+	finch_conversation_init();
+	gaim_conversations_set_ui_ops(finch_conv_get_ui_ops());
+
+	/* Notify */
+	finch_notify_init();
+	gaim_notify_set_ui_ops(finch_notify_get_ui_ops());
+
+	finch_request_init();
+	gaim_request_set_ui_ops(finch_request_get_ui_ops());
+
+	finch_pounces_init();
+
+	finch_xfers_init();
+	gaim_xfers_set_ui_ops(finch_xfers_get_ui_ops());
+
+	gnt_register_action(_("Accounts"), finch_accounts_show_all);
+	gnt_register_action(_("Buddy List"), finch_blist_show);
+	gnt_register_action(_("Buddy Pounces"), finch_pounces_manager_show);
+	gnt_register_action(_("Debug Window"), finch_debug_window_show);
+	gnt_register_action(_("File Transfers"), finch_xfer_dialog_show);
+	gnt_register_action(_("Plugins"), finch_plugins_show_all);
+	gnt_register_action(_("Preferences"), finch_prefs_show_all);
+	gnt_register_action(_("Statuses"), finch_savedstatus_show_all);
+
+#ifdef STANDALONE
+
+	finch_plugins_save_loaded();
+}
+
+void gnt_ui_uninit()
+{
+	gaim_accounts_set_ui_ops(NULL);
+	finch_accounts_uninit();
+
+	gaim_connections_set_ui_ops(NULL);
+	finch_connections_uninit();
+
+	gaim_blist_set_ui_ops(NULL);
+	finch_blist_uninit();
+
+	gaim_conversations_set_ui_ops(NULL);
+	finch_conversation_uninit();
+
+	gaim_notify_set_ui_ops(NULL);
+	finch_notify_uninit();
+
+	gaim_request_set_ui_ops(NULL);
+	finch_request_uninit();
+
+	finch_pounces_uninit();
+
+	finch_xfers_uninit();
+	gaim_xfers_set_ui_ops(NULL);
+
+	gnt_quit();
+#endif
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntui.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,30 @@
+/**
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNT_UI_H
+#define _GNT_UI_H
+
+#include "gnt.h"
+
+void gnt_ui_init(void);
+void gnt_ui_uninit(void);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/COPYING	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/INSTALL	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,229 @@
+Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+   This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory.  After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/Makefile.am	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,83 @@
+EXTRA_DIST=genmarshal
+
+SUBDIRS = . wms
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = gnt.pc
+
+lib_LTLIBRARIES = libgnt.la
+
+libgnt_la_SOURCES = \
+	gntmarshal.c \
+	gntwidget.c \
+	gntbindable.c \
+	gntbox.c \
+	gntbutton.c \
+	gntcheckbox.c \
+	gntclipboard.c \
+	gntcolors.c \
+	gntcombobox.c \
+	gntentry.c \
+	gntkeys.c \
+	gntlabel.c \
+	gntline.c \
+	gntmenu.c \
+	gntmenuitem.c \
+	gntmenuitemcheck.c \
+	gntstyle.c \
+	gnttextview.c \
+	gnttree.c \
+	gntutils.c \
+	gntwindow.c \
+	gntwm.c \
+	gntmain.c
+
+libgnt_la_headers = \
+	gntwidget.h \
+	gntbindable.h \
+	gntbox.h \
+	gntbutton.h \
+	gntcheckbox.h \
+	gntclipboard.h \
+	gntcolors.h \
+	gntcombobox.h \
+	gntentry.h \
+	gntkeys.h \
+	gntlabel.h \
+	gntline.h \
+	gntmarshal.h \
+	gntmenu.h \
+	gntmenuitem.h \
+	gntmenuitemcheck.h \
+	gntstyle.h \
+	gnttextview.h \
+	gnttree.h \
+	gntutils.h \
+	gntwindow.h \
+	gntwm.h \
+	gnt.h
+
+CLEANFILES = \
+	gntmarshal.h \
+	gntmarshal.c
+
+gntmarshal.c: genmarshal gntmarshal.h
+	echo "#include \"gntmarshal.h\"" > $@
+	cat genmarshal | glib-genmarshal --prefix=gnt_closure_marshal --body >> $@
+
+gntmarshal.h: genmarshal
+	cat genmarshal | glib-genmarshal --prefix=gnt_closure_marshal --header > $@
+
+libgnt_laincludedir=$(includedir)/gnt
+libgnt_lainclude_HEADERS = \
+	$(libgnt_la_headers)
+
+libgnt_la_DEPENDENCIES = 
+libgnt_la_LDFLAGS = -export-dynamic
+libgnt_la_LIBADD = \
+	$(GLIB_LIBS) \
+	$(GNT_LIBS)
+
+AM_CPPFLAGS = \
+	$(GLIB_CFLAGS) \
+	$(GNT_CFLAGS) \
+	$(DEBUG_CFLAGS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/autogen.sh	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+(libtoolize --version) < /dev/null > /dev/null 2>&1 || {
+	echo;
+	echo "You must have libtool installed to compile LibGNT";
+	echo;
+	exit;
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+	echo;
+	echo "You must have automake installed to compile LibGNT";
+	echo;
+	exit;
+}
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+	echo;
+	echo "You must have autoconf installed to compile LibGNT";
+	echo;
+	exit;
+}
+
+echo "Generating configuration files for LibGNT, please wait...."
+echo;
+
+echo "Running libtoolize, please ignore non-fatal messages...."
+echo n | libtoolize --copy --force || exit;
+
+# Add other directories to this list if people continue to experience
+# brokennesses ...  Obviously the real answer is for them to fix it
+# themselves, but for Luke's sake we have this.
+for dir in "/usr/local/share/aclocal" \
+           "/opt/gnome-1.4/share/aclocal"
+do
+	if test -d $dir ; then
+		ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I $dir"
+	fi
+done
+
+libtoolize -c -f --automake
+aclocal $ACLOCAL_FLAGS || exit;
+autoheader || exit;
+automake --add-missing --copy;
+autoconf || exit;
+automake || exit;
+./configure $@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/configure.ac	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,257 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT([libgnt], [0.0.0dev], [gaim-devel@lists.sourceforge.net])
+AC_CANONICAL_SYSTEM
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
+
+AC_PREREQ([2.50])
+
+AC_PATH_PROG(sedpath, sed)
+
+dnl Storing configure arguments
+AC_DEFINE_UNQUOTED(CONFIG_ARGS, "$ac_configure_args", [configure arguments])
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_DISABLE_STATIC
+AM_PROG_LIBTOOL
+LIBTOOL="$LIBTOOL --silent"
+AC_PROG_INSTALL
+
+dnl we don't use autobreak on cygwin!!
+dnl AC_CYGWIN
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(arpa/nameser_compat.h fcntl.h sys/time.h unistd.h locale.h signal.h stdint.h regex.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_STRUCT_TM
+
+AC_C_BIGENDIAN
+
+dnl Checks for library functions.
+AC_TYPE_SIGNAL
+AC_FUNC_STRFTIME
+AC_CHECK_FUNCS(strdup strstr atexit setlocale)
+
+dnl to prevent the g_stat()/g_unlink() crash,
+dnl (09:50:07) Robot101: LSchiere2: it's easy. +LC_SYS_LARGEFILE somewhere in configure.ac
+AC_SYS_LARGEFILE
+
+dnl FreeBSD doesn't have libdl, dlopen is provided by libc
+AC_CHECK_FUNC(dlopen, LIBDL="", [AC_CHECK_LIB(dl, dlopen, LIBDL="-ldl")])
+
+AC_MSG_CHECKING(for the %z format string in strftime())
+AC_TRY_RUN([
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <time.h>
+#include <stdio.h>
+
+int main()
+{
+	char buf[6];
+	time_t t = time(NULL);
+
+	if (strftime(buf, sizeof(buf), "%z", localtime(&t)) != 5)
+		return 1;
+
+	fprintf(stderr, "strftime(\"%%z\") yields: \"%s\"\n", buf);
+
+	return !((buf[0] == '-' || buf[0] == '+') &&
+	         (buf[1] >= '0' && buf[1] <= '9') &&
+	         (buf[2] >= '0' && buf[2] <= '9') &&
+	         (buf[3] >= '0' && buf[3] <= '9') &&
+	         (buf[4] >= '0' && buf[4] <= '9')
+	        );
+}
+],
+[
+	AC_MSG_RESULT(yes)
+	AC_DEFINE([HAVE_STRFTIME_Z_FORMAT], [1],
+                                      [Define to 1 if you have a strftime() that supports the %z format string.])
+],
+[
+	AC_MSG_RESULT(no)
+],
+[
+	# Fallback for Cross Compiling...
+	# This will enable the compatibility code.
+	AC_MSG_RESULT(no)
+]
+)
+
+
+AC_CHECK_HEADER(sys/utsname.h)
+AC_CHECK_FUNC(uname)
+
+if test "x$enable_debug" = "xyes" ; then
+	AC_DEFINE(DEBUG, 1, [Define if debugging is enabled.])
+	enable_fatal_asserts="yes"
+fi
+
+if test "x$enable_fatal_asserts" = "xyes" ; then
+	AC_DEFINE(GAIM_FATAL_ASSERTS, 1, [Define to make assertions fatal (useful for debugging).])
+fi
+
+if test "x$enable_deprecated" = "xno"; then
+	DEBUG_CFLAGS="$DEBUG_CFLAGS -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED"
+fi
+
+if test "x$GCC" = "xyes"; then
+	dnl We enable -Wall later.
+	dnl If it's set after the warning CFLAGS in the compiler invocation, it counteracts the -Wno... flags.
+	dnl This leads to warnings we don't want.
+	CFLAGS=`echo $CFLAGS |$sedpath 's/-Wall//'`
+
+	dnl ENABLE WARNINGS SUPPORTED BY THE VERSION OF GCC IN USE
+	dnl
+	dnl Future Possibilities
+	dnl
+	dnl Consider adding -Wbad-function-cast.
+	dnl	This leads to spurious warnings using GPOINTER_TO_INT(), et al. directly on a function call.
+	dnl		We'd need an intermediate variable.
+	dnl
+	dnl Consider adding -Wfloat-equal.
+	dnl	This leads to warnings with Perl.
+	dnl 		Perhaps we could write ugly configure magic and pass -Wno-float-equal down to that subdirectory.
+	dnl		On the other hand, it's probably actually broken, so maybe the Perl folks should fix that?
+	dnl
+	dnl Consider removing -Wno-sign-compare (from the -Wextra set) and fixing all those cases.
+	dnl	This is likely non-trivial.
+	dnl
+	for newflag in \
+			"-Waggregate-return" \
+			"-Wcast-align" \
+			"-Wdeclaration-after-statement" \
+			"-Werror-implicit-function-declaration" \
+			"-Wextra -Wno-sign-compare -Wno-unused-parameter" \
+			"-Winit-self" \
+			"-Wmissing-declarations" \
+			"-Wmissing-prototypes" \
+			"-Wnested-externs" \
+			"-Wpointer-arith" \
+			"-Wundef" \
+	; do
+		orig_CFLAGS="$CFLAGS"
+		CFLAGS="$CFLAGS $newflag"
+		AC_MSG_CHECKING(for $newflag option to gcc)
+		AC_TRY_COMPILE([], [
+			int main() {return 0;}
+		], [
+			AC_MSG_RESULT(yes)
+			CFLAGS="$orig_CFLAGS"
+			DEBUG_CFLAGS="$DEBUG_CFLAGS $newflag"
+		], [
+			AC_MSG_RESULT(no)
+			CFLAGS="$orig_CFLAGS"
+		])
+	done
+
+	if test "x$enable_fortify" = "xyes"; then
+		AC_MSG_CHECKING(for FORTIFY_SOURCE support)
+		AC_TRY_COMPILE([#include <features.h>], [
+			int main() {
+			#if !(__GNUC_PREREQ (4, 1) \
+				|| (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (4, 0)) \
+				|| (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (3, 4) \
+					&& __GNUC_MINOR__ == 4 \
+					&& (__GNUC_PATCHLEVEL__ > 2 \
+						|| (__GNUC_PATCHLEVEL__ == 2 && __GNUC_RH_RELEASE__ >= 8))))
+			#error No FORTIFY_SOURCE support
+			#endif
+				return 0;
+			}
+		], [
+			AC_MSG_RESULT(yes)
+			DEBUG_CFLAGS="$DEBUG_CFLAGS -D_FORTIFY_SOURCE=2"
+		], [
+			AC_MSG_RESULT(no)
+		])
+	fi
+
+	DEBUG_CFLAGS="-Wall $DEBUG_CFLAGS"
+	CFLAGS="-g $CFLAGS"
+fi
+AC_SUBST(CFLAGS)
+
+PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.0.0 gobject-2.0 gmodule-2.0],,
+	[
+		AC_MSG_ERROR([
+*** GLib 2.0 is required to build LibGNT; please make sure you have the GLib
+*** development headers installed. The latest version of GLib is
+*** always available at http://www.gtk.org/.])
+	])
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+
+
+AC_MSG_CHECKING(for me pot o' gold)
+AC_MSG_RESULT(no)
+AC_CHECK_FUNCS(gethostid lrand48)
+AC_CHECK_FUNCS(memcpy memmove random strchr strerror vprintf)
+AC_CHECK_HEADERS(malloc.h paths.h sgtty.h stdarg.h sys/cdefs.h)
+AC_CHECK_HEADERS(sys/file.h sys/filio.h sys/ioctl.h sys/msgbuf.h)
+AC_CHECK_HEADERS(sys/select.h sys/uio.h sys/utsname.h sys/wait.h)
+AC_CHECK_HEADERS(termios.h)
+#AC_CHECK_FUNC(wcwidth, [AC_DEFINE([HAVE_WCWIDTH], [1], [Define to 1 if you have wcwidth function.])])
+#AC_VAR_TIMEZONE_EXTERNALS
+
+GNT_CFLAGS=
+GNT_LIBS=
+AC_CHECK_LIB(ncursesw, initscr, [GNT_LIBS="-lncursesw"], [enable_gnt=no])
+AC_CHECK_LIB(panelw, update_panels, [GNT_LIBS="$GNT_LIBS -lpanelw"], [enable_gnt=no])
+
+# If ncursesw is not found, look for plain old ncurses
+if test "x$enable_gnt" = "xno"; then
+	AC_CHECK_LIB(ncurses, initscr, [[GNT_LIBS="-lncurses"] [enable_gnt=yes]], [enable_gnt=no])
+	AC_CHECK_LIB(panel, update_panels, [[GNT_LIBS="$GNT_LIBS -lpanel"] [enable_gnt=yes]], [enable_gnt=no])
+	AC_DEFINE(NO_WIDECHAR, [1], [Define to 1 if you do not have ncursesw.])
+else
+	dnl # Some distros put the headers in ncursesw/, some don't
+	found_ncurses_h=no
+	for f in /usr/include/ncursesw/ncurses.h /usr/include/ncurses.h
+	do
+		AC_CHECK_HEADER($f,[
+			AC_MSG_CHECKING([if $f supports wide characters])
+			AC_TRY_COMPILE([
+				#define _XOPEN_SOURCE_EXTENDED
+				#include <$f>
+			], [
+				#ifndef get_wch
+				# error get_wch not found!
+				#endif
+			], [
+				dir=`dirname $f`
+				if test x"$dir" != x"." ; then
+					GNT_CFLAGS="-I$dir/"
+				else
+					GNT_CFLAGS=""
+				fi
+
+				found_ncurses_h=yes
+				AC_MSG_RESULT([yes])
+				break
+			], [
+				AC_MSG_RESULT([no])
+			])
+		])
+	done
+fi
+AC_SUBST(GNT_CFLAGS)
+AC_SUBST(GNT_LIBS)
+
+if test "x$enable_gnt" = "xno"; then
+	AC_MSG_ERROR([
+*** You need ncursesw or ncurses.])
+fi
+
+AC_OUTPUT([Makefile
+           gnt.pc
+           wms/Makefile
+		  ])
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/genmarshal	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,10 @@
+BOOLEAN:VOID
+BOOLEAN:STRING
+VOID:INT,INT,INT,INT
+VOID:INT,INT
+VOID:POINTER,POINTER
+BOOLEAN:INT,INT
+BOOLEAN:INT,INT,INT
+BOOLEAN:POINTER,POINTER,POINTER
+BOOLEAN:INT,INT,INT,POINTER
+VOID:STRING,STRING
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gnt-skel.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,106 @@
+#include "gnt-skel.h"
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntWidgetClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+
+static void
+gnt_skel_draw(GntWidget *widget)
+{
+	GNTDEBUG;
+}
+
+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);
+	GNTDEBUG;
+}
+
+static gboolean
+gnt_skel_key_pressed(GntWidget *widget, const char *text)
+{
+	return FALSE;
+}
+
+static void
+gnt_skel_destroy(GntWidget *widget)
+{
+}
+
+static void
+gnt_skel_class_init(GntSkelClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->destroy = gnt_skel_destroy;
+	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;
+
+	parent_class->actions = g_hash_table_duplicate(parent_class->actions, g_str_hash,
+				g_str_equal, NULL, (GDestroyNotify)gnt_widget_action_free);
+	parent_class->bindings = g_hash_table_duplicate(parent_class->bindings, g_str_hash,
+				g_str_equal, NULL, (GDestroyNotify)gnt_widget_action_param_free);
+
+	gnt_widget_actions_read(G_OBJECT_CLASS_TYPE(klass), klass);
+
+	GNTDEBUG;
+}
+
+static void
+gnt_skel_init(GTypeInstance *instance, gpointer class)
+{
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * 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/finch/libgnt/gnt-skel.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,47 @@
+#ifndef GNT_SKEL_H
+#define GNT_SKEL_H
+
+#include "gntwidget.h"
+#include "gnt.h"
+#include "gntcolors.h"
+#include "gntkeys.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/finch/libgnt/gnt.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,41 @@
+#include <glib.h>
+#include "gntwidget.h"
+#include "gntclipboard.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+
+void gnt_init(void);
+
+void gnt_main(void);
+
+gboolean gnt_ascii_only(void);
+
+void gnt_screen_occupy(GntWidget *widget);
+
+void gnt_screen_release(GntWidget *widget);
+
+void gnt_screen_update(GntWidget *widget);
+
+void gnt_screen_take_focus(GntWidget *widget);
+
+void gnt_screen_resize_widget(GntWidget *widget, int width, int height);
+
+void gnt_screen_move_widget(GntWidget *widget, int x, int y);
+
+void gnt_screen_rename_widget(GntWidget *widget, const char *text);
+
+gboolean gnt_widget_has_focus(GntWidget *widget);
+
+void gnt_widget_set_urgent(GntWidget *widget);
+
+void gnt_register_action(const char *label, void (*callback)());
+
+gboolean gnt_screen_menu_show(gpointer menu);
+
+void gnt_quit(void);
+
+GntClipboard *gnt_get_clipboard(void);
+
+gchar *gnt_get_clipboard_string(void);
+
+void gnt_set_clipboard_string(gchar *);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gnt.pc.in	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+ 
+Name: LibGNT
+Description: Glib Ncurses Toolkit is a collection of curses-widgets.
+Version: @VERSION@
+Requires: glib-2.0
+Cflags: -I${includedir}/gnt
+Libs: -L${libdir} -lgnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntbindable.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,232 @@
+#include "gntbindable.h"
+#include "gntstyle.h"
+#include "gnt.h"
+#include "gntutils.h"
+
+static GObjectClass *parent_class = NULL;
+
+static void
+gnt_bindable_class_init(GntBindableClass *klass)
+{
+	parent_class = g_type_class_peek_parent(klass);
+
+	klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+				(GDestroyNotify)gnt_bindable_action_free);
+	klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+				(GDestroyNotify)gnt_bindable_action_param_free);
+
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+	GNTDEBUG;
+}
+
+static gpointer
+bindable_clone(GntBindableAction *action)
+{
+	GntBindableAction *ret = g_new0(GntBindableAction, 1);
+	ret->name = g_strdup(action->name);
+	ret->u = action->u;
+	return ret;
+}
+
+static gpointer
+binding_clone(GntBindableActionParam *param)
+{
+	GntBindableActionParam *p = g_new0(GntBindableActionParam, 1);
+	p->list = g_list_copy(param->list);
+	p->action = param->action;
+	return p;
+}
+
+static void
+duplicate_hashes(GntBindableClass *klass)
+{
+	/* Duplicate the bindings from parent class */
+	if (klass->actions) {
+		klass->actions = g_hash_table_duplicate(klass->actions, g_str_hash,
+					g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_free,
+					(GDupFunc)g_strdup, (GDupFunc)bindable_clone);
+		klass->bindings = g_hash_table_duplicate(klass->bindings, g_str_hash,
+					g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_param_free,
+					(GDupFunc)g_strdup, (GDupFunc)binding_clone);
+	} else {
+		klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+					(GDestroyNotify)gnt_bindable_action_free);
+		klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+					(GDestroyNotify)gnt_bindable_action_param_free);
+	}
+
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntBindable API
+ *****************************************************************************/
+GType
+gnt_bindable_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(GntBindableClass),
+			(GBaseInitFunc)duplicate_hashes,	/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_bindable_class_init,
+			NULL,
+			NULL,					/* class_data		*/
+			sizeof(GntBindable),
+			0,						/* n_preallocs		*/
+			NULL,					/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(G_TYPE_OBJECT,
+									  "GntBindable",
+									  &info, G_TYPE_FLAG_ABSTRACT);
+	}
+
+	return type;
+}
+
+/**
+ * Key Remaps
+ */
+const char *
+gnt_bindable_remap_keys(GntBindable *bindable, const char *text)
+{
+	const char *remap = NULL;
+	GType type = G_OBJECT_TYPE(bindable);
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
+
+	if (klass->remaps == NULL)
+	{
+		klass->remaps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+		gnt_styles_get_keyremaps(type, klass->remaps);
+	}
+
+	remap = g_hash_table_lookup(klass->remaps, text);
+
+	return (remap ? remap : text);
+}
+
+/**
+ * Actions and Bindings
+ */
+gboolean
+gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...)
+{
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
+	GList *list = NULL;
+	va_list args;
+	GntBindableAction *action;
+	void *p;
+
+	va_start(args, name);
+	while ((p = va_arg(args, void *)) != NULL)
+		list = g_list_append(list, p);
+	va_end(args);
+	
+	action = g_hash_table_lookup(klass->actions, name);
+	if (action && action->u.action) {
+		return action->u.action(bindable, list);
+	}
+	return FALSE;
+}
+
+gboolean
+gnt_bindable_perform_action_key(GntBindable *bindable, const char *keys)
+{
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
+	GntBindableActionParam *param = g_hash_table_lookup(klass->bindings, keys);
+
+	if (param && param->action) {
+		if (param->list)
+			return param->action->u.action(bindable, param->list);
+		else
+			return param->action->u.action_noparam(bindable);
+	}
+	return FALSE;
+}
+
+static void
+register_binding(GntBindableClass *klass, const char *name, const char *trigger, GList *list)
+{
+	GntBindableActionParam *param;
+	GntBindableAction *action;
+
+	if (name == NULL || *name == '\0') {
+		g_hash_table_remove(klass->bindings, (char*)trigger);
+		gnt_keys_del_combination(trigger);
+		return;
+	}
+
+	action = g_hash_table_lookup(klass->actions, name);
+	if (!action) {
+		g_printerr("GntWidget: Invalid action name %s for %s\n",
+				name, g_type_name(G_OBJECT_CLASS_TYPE(klass)));
+		if (list)
+			g_list_free(list);
+		return;
+	}
+
+	param = g_new0(GntBindableActionParam, 1);
+	param->action = action;
+	param->list = list;
+	g_hash_table_replace(klass->bindings, g_strdup(trigger), param);
+	gnt_keys_add_combination(trigger);
+}
+
+void gnt_bindable_register_binding(GntBindableClass *klass, const char *name,
+			const char *trigger, ...)
+{
+	GList *list = NULL;
+	va_list args;
+	void *data;
+
+	va_start(args, trigger);
+	while ((data = va_arg(args, void *))) {
+		list = g_list_append(list, data);
+	}
+	va_end(args);
+
+	register_binding(klass, name, trigger, list);
+}
+
+void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name,
+			GntBindableActionCallback callback, const char *trigger, ...)
+{
+	void *data;
+	va_list args;
+	GntBindableAction *action = g_new0(GntBindableAction, 1);
+	GList *list;
+
+	action->name = g_strdup(name);
+	action->u.action = callback;
+
+	g_hash_table_replace(klass->actions, g_strdup(name), action);
+
+	if (trigger && *trigger) {
+		list = NULL;
+		va_start(args, trigger);
+		while ((data = va_arg(args, void *))) {
+			list = g_list_append(list, data);
+		}
+		va_end(args);
+
+		register_binding(klass, name, trigger, list);
+	}
+}
+
+void gnt_bindable_action_free(GntBindableAction *action)
+{
+	g_free(action->name);
+	g_free(action);
+}
+
+void gnt_bindable_action_param_free(GntBindableActionParam *param)
+{
+	g_list_free(param->list);   /* XXX: There may be a leak here for string parameters */
+	g_free(param);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntbindable.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,90 @@
+#ifndef GNT_BINDABLE_H
+#define GNT_BINDABLE_H
+
+#include <stdio.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <ncurses.h>
+
+#define GNT_TYPE_BINDABLE				(gnt_bindable_get_gtype())
+#define GNT_BINDABLE(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_BINDABLE, GntBindable))
+#define GNT_BINDABLE_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_BINDABLE, GntBindableClass))
+#define GNT_IS_BINDABLE(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_BINDABLE))
+#define GNT_IS_BINDABLE_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_BINDABLE))
+#define GNT_BINDABLE_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_BINDABLE, GntBindableClass))
+
+#define	GNTDEBUG	g_printerr("%s\n", __FUNCTION__)
+
+typedef struct _GnBindable			GntBindable;
+typedef struct _GnBindableClass		GntBindableClass;
+
+struct _GnBindable
+{
+	GObject inherit;
+};
+
+struct _GnBindableClass
+{
+	GObjectClass parent;
+
+	GHashTable *remaps;   /* Key remaps */
+	GHashTable *actions;  /* name -> Action */
+	GHashTable *bindings; /* key -> ActionParam */
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_bindable_get_gtype(void);
+
+/******************/
+/*   Key Remaps   */
+/******************/
+const char * gnt_bindable_remap_keys(GntBindable *bindable, const char *text);
+
+/******************/
+/* Bindable Actions */
+/******************/
+typedef gboolean (*GntBindableActionCallback) (GntBindable *bindable, GList *params);
+typedef gboolean (*GntBindableActionCallbackNoParam)(GntBindable *bindable);
+
+typedef struct _GnBindableAction GntBindableAction;
+typedef struct _GnBindableActionParam GntBindableActionParam;
+
+struct _GnBindableAction
+{
+	char *name;        /* The name of the action */
+	union {
+		gboolean (*action)(GntBindable *bindable, GList *params);
+		gboolean (*action_noparam)(GntBindable *bindable);
+	} u;
+};
+
+struct _GnBindableActionParam
+{
+	GntBindableAction *action;
+	GList *list;
+};
+
+
+/*GntBindableAction *gnt_bindable_action_parse(const char *name);*/
+
+void gnt_bindable_action_free(GntBindableAction *action);
+void gnt_bindable_action_param_free(GntBindableActionParam *param);
+
+void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name,
+			GntBindableActionCallback callback, const char *trigger, ...);
+void gnt_bindable_register_binding(GntBindableClass *klass, const char *name,
+			const char *trigger, ...);
+
+gboolean gnt_bindable_perform_action_key(GntBindable *bindable, const char *keys);
+gboolean gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...);
+
+G_END_DECLS
+
+#endif /* GNT_BINDABLE_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntbox.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,788 @@
+#include "gntbox.h"
+#include "gntutils.h"
+
+#include <string.h>
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntWidgetClass *parent_class = NULL;
+
+static GntWidget * find_focusable_widget(GntBox *box);
+
+static void
+add_to_focus(gpointer value, gpointer data)
+{
+	GntBox *box = GNT_BOX(data);
+	GntWidget *w = GNT_WIDGET(value);
+
+	if (GNT_IS_BOX(w))
+		g_list_foreach(GNT_BOX(w)->list, add_to_focus, box);
+	else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_CAN_TAKE_FOCUS))
+		box->focus = g_list_append(box->focus, w);
+}
+
+static void
+get_title_thingies(GntBox *box, char *title, int *p, int *r)
+{
+	GntWidget *widget = GNT_WIDGET(box);
+	int len;
+	char *end = (char*)gnt_util_onscreen_width_to_pointer(title, widget->priv.width - 4, &len);
+	
+	if (p)
+		*p = (widget->priv.width - len) / 2;
+	if (r)
+		*r = (widget->priv.width + len) / 2;
+	*end = '\0';
+}
+
+static void
+gnt_box_draw(GntWidget *widget)
+{
+	GntBox *box = GNT_BOX(widget);
+
+	if (box->focus == NULL && widget->parent == NULL)
+		g_list_foreach(box->list, add_to_focus, box);
+
+	g_list_foreach(box->list, (GFunc)gnt_widget_draw, NULL);
+
+	gnt_box_sync_children(box);
+
+	if (box->title && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
+	{
+		int pos, right;
+		char *title = g_strdup(box->title);
+		
+		get_title_thingies(box, title, &pos, &right);
+
+		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));
+		mvwaddch(widget->window, 0, pos-1, ACS_RTEE | COLOR_PAIR(GNT_COLOR_NORMAL));
+		mvwaddstr(widget->window, 0, pos, title);
+		mvwaddch(widget->window, 0, right, ACS_LTEE | COLOR_PAIR(GNT_COLOR_NORMAL));
+		g_free(title);
+	}
+	
+	GNTDEBUG;
+}
+
+static void
+reposition_children(GntWidget *widget)
+{
+	GList *iter;
+	GntBox *box = GNT_BOX(widget);
+	int w, h, curx, cury, max;
+	gboolean has_border = FALSE;
+
+	w = h = 0;
+	max = 0;
+	curx = widget->priv.x;
+	cury = widget->priv.y;
+	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER))
+	{
+		has_border = TRUE;
+		curx += 1;
+		cury += 1;
+	}
+
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(iter->data), GNT_WIDGET_INVISIBLE))
+			continue;
+		gnt_widget_set_position(GNT_WIDGET(iter->data), curx, cury);
+		gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h);
+		if (box->vertical)
+		{
+			if (h)
+			{
+				cury += h + box->pad;
+				if (max < w)
+					max = w;
+			}
+		}
+		else
+		{
+			if (w)
+			{
+				curx += w + box->pad;
+				if (max < h)
+					max = h;
+			}
+		}
+	}
+
+	if (has_border)
+	{
+		curx += 1;
+		cury += 1;
+		max += 2;
+	}
+
+	if (box->list)
+	{
+		if (box->vertical)
+			cury -= box->pad;
+		else
+			curx -= box->pad;
+	}
+
+	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)
+{
+	GList *iter;
+	int changex, changey;
+
+	changex = widget->priv.x - x;
+	changey = widget->priv.y - y;
+
+	for (iter = GNT_BOX(widget)->list; iter; iter = iter->next)
+	{
+		GntWidget *w = GNT_WIDGET(iter->data);
+		gnt_widget_set_position(w, w->priv.x - changex,
+				w->priv.y - changey);
+	}
+}
+
+static void
+gnt_box_size_request(GntWidget *widget)
+{
+	GntBox *box = GNT_BOX(widget);
+	GList *iter;
+	int maxw = 0, maxh = 0;
+	
+	g_list_foreach(box->list, (GFunc)gnt_widget_size_request, NULL);
+
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		int w, h;
+		gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h);
+		if (maxh < h)
+			maxh = h;
+		if (maxw < w)
+			maxw = w;
+	}
+
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		int w, h;
+		GntWidget *wid = GNT_WIDGET(iter->data);
+
+		gnt_widget_get_size(wid, &w, &h);
+
+		if (box->homogeneous)
+		{
+			if (box->vertical)
+				h = maxh;
+			else
+				w = maxw;
+		}
+		if (box->fill)
+		{
+			if (box->vertical)
+				w = maxw;
+			else
+				h = maxh;
+		}
+
+		gnt_widget_set_size(wid, w, 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);
+		find_focusable_widget(GNT_BOX(widget));
+	}
+	GNTDEBUG;
+}
+
+/* Ensures that the current widget can take focus */
+static GntWidget *
+find_focusable_widget(GntBox *box)
+{
+	/* XXX: Make sure the widget is visible? */
+	if (box->focus == NULL && GNT_WIDGET(box)->parent == NULL)
+		g_list_foreach(box->list, add_to_focus, box);
+
+	if (box->active == NULL && box->focus)
+		box->active = box->focus->data;
+
+	return box->active;
+}
+
+static void
+find_next_focus(GntBox *box)
+{
+	gpointer last = box->active;
+	do
+	{
+		GList *iter = g_list_find(box->focus, box->active);
+		if (iter && iter->next)
+			box->active = iter->next->data;
+		else if (box->focus)
+			box->active = box->focus->data;
+		if (!GNT_WIDGET_IS_FLAG_SET(box->active, GNT_WIDGET_INVISIBLE))
+			break;
+	} while (box->active != last);
+}
+
+static void
+find_prev_focus(GntBox *box)
+{
+	gpointer last = box->active;
+
+	if (!box->focus)
+		return;
+
+	do
+	{
+		GList *iter = g_list_find(box->focus, box->active);
+		if (!iter)
+			box->active = box->focus->data;
+		else if (!iter->prev)
+			box->active = g_list_last(box->focus)->data;
+		else
+			box->active = iter->prev->data;
+		if (!GNT_WIDGET_IS_FLAG_SET(box->active, GNT_WIDGET_INVISIBLE))
+			break;
+	} while (box->active != last);
+}
+
+static gboolean
+gnt_box_key_pressed(GntWidget *widget, const char *text)
+{
+	GntBox *box = GNT_BOX(widget);
+	GntWidget *now;
+
+	if (box->active == NULL && !find_focusable_widget(box))
+		return FALSE;
+
+	if (gnt_widget_key_pressed(box->active, text))
+		return TRUE;
+	
+	now = box->active;
+
+	if (text[0] == 27)
+	{
+		if (strcmp(text, GNT_KEY_LEFT) == 0)
+		{
+			find_prev_focus(box);
+		}
+		else if (strcmp(text, GNT_KEY_RIGHT) == 0)
+		{
+			find_next_focus(box);
+		}
+	}
+	else if (text[0] == '\t')
+	{
+		find_next_focus(box);
+	}
+
+	if (now && now != box->active)
+	{
+		gnt_widget_set_focus(now, FALSE);
+		gnt_widget_set_focus(box->active, TRUE);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void
+gnt_box_lost_focus(GntWidget *widget)
+{
+	GntWidget *w = GNT_BOX(widget)->active;
+	if (w)
+		gnt_widget_set_focus(w, FALSE);
+	gnt_widget_draw(widget);
+}
+
+static void
+gnt_box_gained_focus(GntWidget *widget)
+{
+	GntWidget *w = GNT_BOX(widget)->active;
+	if (w)
+		gnt_widget_set_focus(w, TRUE);
+	gnt_widget_draw(widget);
+}
+
+static void
+gnt_box_destroy(GntWidget *w)
+{
+	GntBox *box = GNT_BOX(w);
+
+	gnt_box_remove_all(box);
+	gnt_screen_release(w);
+}
+
+static void
+gnt_box_expose(GntWidget *widget, int x, int y, int width, int height)
+{
+	WINDOW *win = newwin(height, width, widget->priv.y + y, widget->priv.x + x);
+	copywin(widget->window, win, y, x, 0, 0, height - 1, width - 1, FALSE);
+	wrefresh(win);
+	delwin(win);
+}
+
+static gboolean
+gnt_box_confirm_size(GntWidget *widget, int width, int height)
+{
+	GList *iter;
+	GntBox *box = GNT_BOX(widget);
+	int wchange, hchange;
+
+	if (widget->priv.width != width && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_X))
+		return FALSE;
+	if (widget->priv.height != height && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_Y))
+		return FALSE;
+
+	if (!box->list)
+		return TRUE;
+
+	wchange = widget->priv.width - width;
+	hchange = widget->priv.height - height;
+
+	if (wchange == 0 && hchange == 0)
+		return TRUE;		/* Quit playing games */
+
+	/* XXX: Right now, I am trying to just apply all the changes to 
+	 * just one widget. It should be possible to distribute the
+	 * changes to all the widgets in the box. */
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		GntWidget *wid = iter->data;
+		int w, h;
+
+		gnt_widget_get_size(wid, &w, &h);
+
+		if (gnt_widget_confirm_size(wid, w - wchange, h - hchange))
+		{
+			GList *i;
+
+			for (i = box->list; i; i = i->next)
+			{
+				int tw, th;
+				if (i == iter) continue;
+				gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th);
+				if (box->vertical)
+				{
+					if (!gnt_widget_confirm_size(i->data, tw - wchange, th))
+						return FALSE;
+				}
+				else
+				{
+					if (!gnt_widget_confirm_size(i->data, tw, th - hchange))
+						return FALSE;
+				}
+			}
+#if 0
+			gnt_widget_set_size(wid, w - wchange, h - hchange);
+			if (box->vertical)
+				hchange = 0;
+			else
+				wchange = 0;
+
+			for (i = box->list; i; i = i->next)
+			{
+				int tw, th;
+				if (i == iter) continue;
+				gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th);
+				gnt_widget_set_size(i->data, tw - wchange, th - hchange);
+			}
+#endif
+			g_object_set_data(G_OBJECT(box), "size-queued", wid);
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+static void
+gnt_box_size_changed(GntWidget *widget, int oldw, int oldh)
+{
+	int wchange, hchange;
+	GList *i;
+	GntBox *box = GNT_BOX(widget);
+	GntWidget *wid;
+	int tw, th;
+		
+	wchange = widget->priv.width - oldw;
+	hchange = widget->priv.height - oldh;
+	
+	wid = g_object_get_data(G_OBJECT(box), "size-queued");
+	if (wid)
+	{
+		gnt_widget_get_size(wid, &tw, &th);
+		gnt_widget_set_size(wid, tw + wchange, th + hchange);
+		g_object_set_data(G_OBJECT(box), "size-queued", NULL);
+	}
+
+	if (box->vertical)
+		hchange = 0;
+	else
+		wchange = 0;
+
+	for (i = box->list; i; i = i->next)
+	{
+		if (wid != i->data)
+		{
+			gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th);
+			gnt_widget_set_size(i->data, tw + wchange, th + hchange);
+		}
+	}
+
+	reposition_children(widget);
+}
+
+static gboolean
+gnt_box_clicked(GntWidget *widget, GntMouseEvent event, int cx, int cy)
+{
+	GList *iter;
+	for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) {
+		int x, y, w, h;
+		GntWidget *wid = iter->data;
+
+		gnt_widget_get_position(wid, &x, &y);
+		gnt_widget_get_size(wid, &w, &h);
+
+		if (cx >= x && cx < x + w && cy >= y && cy < y + h) {
+			if (event <= GNT_MIDDLE_MOUSE_DOWN &&
+				GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_CAN_TAKE_FOCUS)) {
+				while (widget->parent)
+					widget = widget->parent;
+				gnt_box_give_focus_to_child(GNT_BOX(widget), wid);
+			}
+			return gnt_widget_clicked(wid, event, cx, cy);
+		}
+	}
+	return FALSE;
+}
+
+static void
+gnt_box_class_init(GntBoxClass *klass)
+{
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->destroy = gnt_box_destroy;
+	parent_class->draw = gnt_box_draw;
+	parent_class->expose = gnt_box_expose;
+	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->clicked = gnt_box_clicked;
+	parent_class->lost_focus = gnt_box_lost_focus;
+	parent_class->gained_focus = gnt_box_gained_focus;
+	parent_class->confirm_size = gnt_box_confirm_size;
+	parent_class->size_changed = gnt_box_size_changed;
+
+	GNTDEBUG;
+}
+
+static void
+gnt_box_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	GntBox *box = GNT_BOX(widget);
+	/* Initially make both the height and width resizable.
+	 * Update the flags as necessary when widgets are added to it. */
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+	box->pad = 1;
+	box->fill = TRUE;
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * 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	*/
+			NULL					/* value_table		*/
+		};
+
+		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;
+	box->alignment = vert ? GNT_ALIGN_LEFT : GNT_ALIGN_MID;
+
+	return widget;
+}
+
+void gnt_box_add_widget(GntBox *b, GntWidget *widget)
+{
+	b->list = g_list_append(b->list, widget);
+	widget->parent = GNT_WIDGET(b);
+
+	if (b->vertical)
+	{
+		if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_X))
+			GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(b), GNT_WIDGET_GROW_X);
+	}
+	else
+	{
+		if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_Y))
+			GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(b), GNT_WIDGET_GROW_Y);
+	}
+}
+
+void gnt_box_set_title(GntBox *b, const char *title)
+{
+	char *prev = b->title;
+	GntWidget *w = GNT_WIDGET(b);
+	b->title = g_strdup(title);
+	if (w->window && !GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_NO_BORDER)) {
+		/* Erase the old title */
+		int pos, right;
+		get_title_thingies(b, prev, &pos, &right);
+		mvwhline(w->window, 0, pos - 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL),
+				right - pos + 2);
+		g_free(prev);
+	}
+}
+
+void gnt_box_set_pad(GntBox *box, int pad)
+{
+	box->pad = pad;
+	/* XXX: Perhaps redraw if already showing? */
+}
+
+void gnt_box_set_toplevel(GntBox *box, gboolean set)
+{
+	GntWidget *widget = GNT_WIDGET(box);
+	if (set)
+	{
+		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
+	}
+	else
+	{
+		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
+	}
+}
+
+void gnt_box_sync_children(GntBox *box)
+{
+	GList *iter;
+	GntWidget *widget = GNT_WIDGET(box);
+	int pos = 1;
+
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
+		pos = 0;
+
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		GntWidget *w = GNT_WIDGET(iter->data);
+		int height, width;
+		int x, y;
+
+		if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_INVISIBLE))
+			continue;
+
+		if (GNT_IS_BOX(w))
+			gnt_box_sync_children(GNT_BOX(w));
+
+		gnt_widget_get_size(w, &width, &height);
+
+		x = w->priv.x - widget->priv.x;
+		y = w->priv.y - widget->priv.y;
+
+		if (box->vertical)
+		{
+			x = pos;
+			if (box->alignment == GNT_ALIGN_RIGHT)
+				x += widget->priv.width - width;
+			else if (box->alignment == GNT_ALIGN_MID)
+				x += (widget->priv.width - width)/2;
+			if (x + width > widget->priv.width - pos)
+				x -= x + width - (widget->priv.width - pos);
+		}
+		else
+		{
+			y = pos;
+			if (box->alignment == GNT_ALIGN_BOTTOM)
+				y += widget->priv.height - height;
+			else if (box->alignment == GNT_ALIGN_MID)
+				y += (widget->priv.height - height)/2;
+			if (y + height >= widget->priv.height - pos)
+				y = widget->priv.height - height - pos;
+		}
+
+		copywin(w->window, widget->window, 0, 0,
+				y, x, y + height - 1, x + width - 1, FALSE);
+		gnt_widget_set_position(w, x + widget->priv.x, y + widget->priv.y);
+	}
+}
+
+void gnt_box_set_alignment(GntBox *box, GntAlignment alignment)
+{
+	box->alignment = alignment;
+}
+
+void gnt_box_remove(GntBox *box, GntWidget *widget)
+{
+	box->list = g_list_remove(box->list, widget);
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS)
+			&& GNT_WIDGET(box)->parent == NULL && box->focus)
+	{
+		if (widget == box->active)
+		{
+			find_next_focus(box);
+			if (box->active == widget) /* There's only one widget */
+				box->active = NULL;
+		}
+		box->focus = g_list_remove(box->focus, widget);
+	}
+
+	if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(box), GNT_WIDGET_MAPPED))
+		gnt_widget_draw(GNT_WIDGET(box));
+}
+
+void gnt_box_remove_all(GntBox *box)
+{
+	g_list_foreach(box->list, (GFunc)gnt_widget_destroy, NULL);
+	g_list_free(box->list);
+	g_list_free(box->focus);
+	box->list = NULL;
+	box->focus = NULL;
+	GNT_WIDGET(box)->priv.width = 0;
+	GNT_WIDGET(box)->priv.height = 0;
+}
+
+void gnt_box_readjust(GntBox *box)
+{
+	GList *iter;
+	GntWidget *wid;
+	int width, height;
+
+	if (GNT_WIDGET(box)->parent != NULL)
+		return;
+
+	for (iter = box->list; iter; iter = iter->next)
+	{
+		GntWidget *w = iter->data;
+		if (GNT_IS_BOX(w))
+			gnt_box_readjust(GNT_BOX(w));
+		else
+		{
+			GNT_WIDGET_UNSET_FLAGS(w, GNT_WIDGET_MAPPED);
+			w->priv.width = 0;
+			w->priv.height = 0;
+		}
+	}
+
+	wid = GNT_WIDGET(box);
+	GNT_WIDGET_UNSET_FLAGS(wid, GNT_WIDGET_MAPPED);
+	wid->priv.width = 0;
+	wid->priv.height = 0;
+
+	if (wid->parent == NULL)
+	{
+		g_list_free(box->focus);
+		box->focus = NULL;
+		box->active = NULL;
+		gnt_widget_size_request(wid);
+		gnt_widget_get_size(wid, &width, &height);
+		gnt_screen_resize_widget(wid, width, height);
+		find_focusable_widget(box);
+	}
+}
+
+void gnt_box_set_fill(GntBox *box, gboolean fill)
+{
+	box->fill = fill;
+}
+
+void gnt_box_move_focus(GntBox *box, int dir)
+{
+	GntWidget *now;
+
+	if (box->active == NULL)
+	{
+		find_focusable_widget(box);
+		return;
+	}
+
+	now = box->active;
+
+	if (dir == 1)
+		find_next_focus(box);
+	else if (dir == -1)
+		find_prev_focus(box);
+
+	if (now && now != box->active)
+	{
+		gnt_widget_set_focus(now, FALSE);
+		gnt_widget_set_focus(box->active, TRUE);
+	}
+
+	if (GNT_WIDGET(box)->window)
+		gnt_widget_draw(GNT_WIDGET(box));
+}
+
+void gnt_box_give_focus_to_child(GntBox *box, GntWidget *widget)
+{
+	GList *find = g_list_find(box->focus, widget);
+	gpointer now = box->active;
+	if (find)
+		box->active = widget;
+	if (now && now != box->active)
+	{
+		gnt_widget_set_focus(now, FALSE);
+		gnt_widget_set_focus(box->active, TRUE);
+	}
+
+	if (GNT_WIDGET(box)->window)
+		gnt_widget_draw(GNT_WIDGET(box));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntbox.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,98 @@
+#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;
+
+typedef enum
+{
+	/* These for vertical boxes */
+	GNT_ALIGN_LEFT,
+	GNT_ALIGN_RIGHT,
+
+	GNT_ALIGN_MID,
+
+	/* These for horizontal boxes */
+	GNT_ALIGN_TOP,
+	GNT_ALIGN_BOTTOM
+} GntAlignment;
+
+struct _GnBox
+{
+	GntWidget parent;
+
+	gboolean vertical;
+	gboolean homogeneous;
+	gboolean fill;
+	GList *list;		/* List of widgets */
+
+	GntWidget *active;
+	int pad;			/* Number of spaces to use between widgets */
+	GntAlignment alignment;  /* How are the widgets going to be aligned? */
+
+	char *title;
+	GList *focus;		/* List of widgets to cycle focus (only valid for parent boxes) */
+
+    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);
+
+#define gnt_vbox_new(homo) gnt_box_new(homo, TRUE)
+#define gnt_hbox_new(homo) gnt_box_new(homo, FALSE)
+
+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);
+
+void gnt_box_set_pad(GntBox *box, int pad);
+
+void gnt_box_set_toplevel(GntBox *box, gboolean set);
+
+void gnt_box_sync_children(GntBox *box);
+
+void gnt_box_set_alignment(GntBox *box, GntAlignment alignment);
+
+void gnt_box_remove(GntBox *box, GntWidget *widget); /* XXX: does NOT destroy widget */
+
+void gnt_box_remove_all(GntBox *box);      /* Removes AND destroys all the widgets in it */
+
+void gnt_box_readjust(GntBox *box);
+
+void gnt_box_set_fill(GntBox *box, gboolean fill);
+
+void gnt_box_move_focus(GntBox *box, int dir);  /* +1 to move forward, -1 for backward */
+
+void gnt_box_give_focus_to_child(GntBox *box, GntWidget *widget);
+
+G_END_DECLS
+
+#endif /* GNT_BOX_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntbutton.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,136 @@
+#include <string.h>
+
+#include "gntbutton.h"
+#include "gntutils.h"
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntWidgetClass *parent_class = NULL;
+
+static void
+gnt_button_draw(GntWidget *widget)
+{
+	GntButton *button = GNT_BUTTON(widget);
+	GntColorType type;
+
+	if (gnt_widget_has_focus(widget))
+		type = GNT_COLOR_HIGHLIGHT;
+	else
+		type = GNT_COLOR_NORMAL;
+	
+	wbkgdset(widget->window, '\0' | COLOR_PAIR(type));
+	mvwaddstr(widget->window, 1, 2, button->priv->text);
+
+	GNTDEBUG;
+}
+
+static void
+gnt_button_size_request(GntWidget *widget)
+{
+	GntButton *button = GNT_BUTTON(widget);
+	gnt_util_get_text_bound(button->priv->text,
+			&widget->priv.width, &widget->priv.height);
+	widget->priv.width += 4;
+	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
+		widget->priv.height += 2;
+}
+
+static void
+gnt_button_map(GntWidget *widget)
+{
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+		gnt_widget_size_request(widget);
+	GNTDEBUG;
+}
+
+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 gboolean
+gnt_button_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
+{
+	if (event == GNT_LEFT_MOUSE_DOWN) {
+		gnt_widget_activate(widget);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static void
+gnt_button_class_init(GntWidgetClass *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;
+	parent_class->clicked = gnt_button_clicked;
+
+	GNTDEBUG;
+}
+
+static void
+gnt_button_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	GntButton *button = GNT_BUTTON(instance);
+	button->priv = g_new0(GntButtonPriv, 1);
+
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X);
+
+	widget->priv.minw = 4;
+	widget->priv.minh = 3;
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * 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	*/
+			NULL					/* value_table		*/
+		};
+
+		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 = gnt_util_onscreen_fit_string(text, -1);
+	gnt_widget_set_take_focus(widget, TRUE);
+
+	return widget;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntbutton.h	Sun Mar 18 19:38:15 2007 +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/finch/libgnt/gntcheckbox.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,156 @@
+#include "gntcheckbox.h"
+
+enum
+{
+	SIG_TOGGLED = 1,
+	SIGS,
+};
+
+static GntButtonClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+
+static void
+gnt_check_box_draw(GntWidget *widget)
+{
+	GntCheckBox *cb = GNT_CHECK_BOX(widget);
+	GntColorType type;
+	char *text;
+
+	if (gnt_widget_has_focus(widget))
+		type = GNT_COLOR_HIGHLIGHT;
+	else
+		type = GNT_COLOR_NORMAL;
+	
+	wbkgdset(widget->window, '\0' | COLOR_PAIR(type));
+
+	text = g_strdup_printf("[%c]", cb->checked ? 'X' : ' ');
+	mvwaddstr(widget->window, 0, 0, text);
+	g_free(text);
+
+	wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+	mvwaddstr(widget->window, 0, 4, GNT_BUTTON(cb)->priv->text);
+	
+	GNTDEBUG;
+}
+
+static void
+toggle_selection(GntWidget *widget)
+{
+	GNT_CHECK_BOX(widget)->checked = !GNT_CHECK_BOX(widget)->checked;
+	g_signal_emit(widget, signals[SIG_TOGGLED], 0);
+	gnt_widget_draw(widget);
+}
+
+static gboolean
+gnt_check_box_key_pressed(GntWidget *widget, const char *text)
+{
+	if (text[0] == ' ' && text[1] == '\0')
+	{
+		toggle_selection(widget);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+gnt_check_box_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
+{
+	if (event == GNT_LEFT_MOUSE_DOWN) {
+		toggle_selection(widget);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static void
+gnt_check_box_class_init(GntCheckBoxClass *klass)
+{
+	GntWidgetClass *wclass = GNT_WIDGET_CLASS(klass);
+
+	parent_class = GNT_BUTTON_CLASS(klass);
+	/*parent_class->destroy = gnt_check_box_destroy;*/
+	wclass->draw = gnt_check_box_draw;
+	/*parent_class->map = gnt_check_box_map;*/
+	/*parent_class->size_request = gnt_check_box_size_request;*/
+	wclass->key_pressed = gnt_check_box_key_pressed;
+	wclass->clicked = gnt_check_box_clicked;
+
+	signals[SIG_TOGGLED] = 
+		g_signal_new("toggled",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntCheckBoxClass, toggled),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__VOID,
+					 G_TYPE_NONE, 0);
+	GNTDEBUG;
+}
+
+static void
+gnt_check_box_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	widget->priv.minh = 1;
+	widget->priv.minw = 4;
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntCheckBox API
+ *****************************************************************************/
+GType
+gnt_check_box_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntCheckBoxClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_check_box_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntCheckBox),
+			0,						/* n_preallocs		*/
+			gnt_check_box_init,			/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_BUTTON,
+									  "GntCheckBox",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_check_box_new(const char *text)
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_CHECK_BOX, NULL);
+
+	GNT_BUTTON(widget)->priv->text = g_strdup(text);
+	gnt_widget_set_take_focus(widget, TRUE);
+
+	return widget;
+}
+
+void gnt_check_box_set_checked(GntCheckBox *box, gboolean set)
+{
+	if (set != box->checked)
+	{
+		box->checked = set;
+		g_signal_emit(box, signals[SIG_TOGGLED], 0);
+	}
+}
+
+gboolean gnt_check_box_get_checked(GntCheckBox *box)
+{
+	return box->checked;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntcheckbox.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,54 @@
+#ifndef GNT_CHECK_BOX_H
+#define GNT_CHECK_BOX_H
+
+#include "gntbutton.h"
+#include "gnt.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+
+#define GNT_TYPE_CHECK_BOX				(gnt_check_box_get_gtype())
+#define GNT_CHECK_BOX(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_CHECK_BOX, GntCheckBox))
+#define GNT_CHECK_BOX_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_CHECK_BOX, GntCheckBoxClass))
+#define GNT_IS_CHECK_BOX(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_CHECK_BOX))
+#define GNT_IS_CHECK_BOX_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_CHECK_BOX))
+#define GNT_CHECK_BOX_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_CHECK_BOX, GntCheckBoxClass))
+
+#define GNT_CHECK_BOX_FLAGS(obj)				(GNT_CHECK_BOX(obj)->priv.flags)
+#define GNT_CHECK_BOX_SET_FLAGS(obj, flags)		(GNT_CHECK_BOX_FLAGS(obj) |= flags)
+#define GNT_CHECK_BOX_UNSET_FLAGS(obj, flags)	(GNT_CHECK_BOX_FLAGS(obj) &= ~(flags))
+
+typedef struct _GnCheckBox			GntCheckBox;
+typedef struct _GnCheckBoxPriv		GntCheckBoxPriv;
+typedef struct _GnCheckBoxClass		GntCheckBoxClass;
+
+struct _GnCheckBox
+{
+	GntButton parent;
+	gboolean checked;
+};
+
+struct _GnCheckBoxClass
+{
+	GntButtonClass parent;
+
+	void (*toggled)(void);
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_check_box_get_gtype(void);
+
+GntWidget *gnt_check_box_new(const char *text);
+
+void gnt_check_box_set_checked(GntCheckBox *box, gboolean set);
+
+gboolean gnt_check_box_get_checked(GntCheckBox *box);
+
+G_END_DECLS
+
+#endif /* GNT_CHECK_BOX_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntclipboard.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,74 @@
+#include "gntclipboard.h"
+
+gchar *string;
+
+enum {
+	SIG_CLIPBOARD = 0,
+	SIGS
+};
+
+static guint signals[SIGS] = { 0 };
+
+static void
+gnt_clipboard_class_init(GntClipboardClass *klass)
+{
+	signals[SIG_CLIPBOARD] = 
+		g_signal_new("clipboard_changed",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 0,
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+}
+
+/******************************************************************************
+ * GntClipboard API
+ *****************************************************************************/
+
+void
+gnt_clipboard_set_string(GntClipboard *clipboard, gchar *string)
+{
+	g_free(clipboard->string);
+	clipboard->string = g_strdup(string);
+	g_signal_emit(clipboard, signals[SIG_CLIPBOARD], 0, clipboard->string);
+}
+
+gchar *
+gnt_clipboard_get_string(GntClipboard *clipboard)
+{
+	return g_strdup(clipboard->string);
+}
+
+static void gnt_clipboard_init(GTypeInstance *instance, gpointer class) {
+	GntClipboard *clipboard = GNT_CLIPBOARD(instance);
+	clipboard->string = g_strdup("");
+}
+
+GType
+gnt_clipboard_get_gtype(void)
+{
+	static GType type = 0;
+
+	if (type == 0) {
+		static const GTypeInfo info = {
+			sizeof(GntClipboardClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_clipboard_class_init,
+			NULL,
+			NULL,					/* class_data		*/
+			sizeof(GntClipboard),
+			0,						/* n_preallocs		*/
+			gnt_clipboard_init,		/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(G_TYPE_OBJECT,
+									  "GntClipboard",
+									  &info, 0);
+	}
+
+	return type;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntclipboard.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,46 @@
+#ifndef GNT_CLIPBOARD_H
+#define GNT_CLIPBOARD_H
+
+#include <stdio.h>
+#include <glib.h>
+#include <glib-object.h>
+
+#define GNT_TYPE_CLIPBOARD				(gnt_clipboard_get_gtype())
+#define GNT_CLIPBOARD(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_CLIPBOARD, GntClipboard))
+#define GNT_CLIPBOARD_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_CLIPBOARD, GntClipboardClass))
+#define GNT_IS_CLIPBOARD(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_CLIPBOARD))
+#define GNT_IS_CLIPBOARD_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_CLIPBOARD))
+#define GNT_CLIPBOARD_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_CLIPBOARD, GntClipboardClass))
+
+#define	GNTDEBUG	g_printerr("%s\n", __FUNCTION__)
+
+typedef struct _GnClipboard			GntClipboard;
+typedef struct _GnClipboardClass		GntClipboardClass;
+
+struct _GnClipboard
+{
+	GObject inherit;
+	gchar *string;
+};
+
+struct _GnClipboardClass
+{
+	GObjectClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_clipboard_get_gtype(void);
+
+gchar *gnt_clipboard_get_string(GntClipboard *);
+
+void gnt_clipboard_set_string(GntClipboard *, gchar *);
+
+G_END_DECLS
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntcolors.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,256 @@
+#include "config.h"
+
+#include <ncurses.h>
+
+#include "gntcolors.h"
+#include "gntstyle.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+static struct
+{
+	short r, g, b;
+} colors[GNT_TOTAL_COLORS];
+
+static void
+backup_colors()
+{
+	short i;
+	for (i = 0; i < GNT_TOTAL_COLORS; i++)
+	{
+		color_content(i, &colors[i].r,
+				&colors[i].g, &colors[i].b);
+	}
+}
+
+static gboolean
+can_use_custom_color()
+{
+	return (gnt_style_get_bool(GNT_STYLE_COLOR, FALSE) && can_change_color());
+}
+
+static void
+restore_colors()
+{
+	short i;
+	for (i = 0; i < GNT_TOTAL_COLORS; i++)
+	{
+		init_color(i, colors[i].r,
+				colors[i].g, colors[i].b);
+	}
+}
+
+void gnt_init_colors()
+{
+	static gboolean init = FALSE;
+	int defaults;
+
+	if (init)
+		return;
+	init = TRUE;
+
+	start_color();
+	defaults = use_default_colors();
+
+	if (can_use_custom_color())
+	{
+		backup_colors();
+
+		/* 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, 250, 250, 700);
+		init_color(GNT_COLOR_WHITE, 1000, 1000, 1000);
+		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_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_BLUE);
+		init_pair(GNT_COLOR_TITLE_D, GNT_COLOR_WHITE, 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);
+		init_pair(GNT_COLOR_URGENT, GNT_COLOR_WHITE, GNT_COLOR_RED);
+	}
+	else
+	{
+		int bg;
+
+		if (defaults == OK) {
+			init_pair(GNT_COLOR_NORMAL, -1, -1);
+			bg = -1;
+		} else {
+			init_pair(GNT_COLOR_NORMAL, COLOR_BLACK, COLOR_WHITE);
+			bg = COLOR_WHITE;
+		}
+		init_pair(GNT_COLOR_DISABLED, COLOR_YELLOW, bg);
+		init_pair(GNT_COLOR_URGENT, COLOR_GREEN, bg);
+
+		init_pair(GNT_COLOR_HIGHLIGHT, COLOR_WHITE, COLOR_BLUE);
+		init_pair(GNT_COLOR_SHADOW, COLOR_BLACK, COLOR_BLACK);
+		init_pair(GNT_COLOR_TITLE, COLOR_WHITE, COLOR_BLUE);
+		init_pair(GNT_COLOR_TITLE_D, COLOR_WHITE, COLOR_BLACK);
+		init_pair(GNT_COLOR_TEXT_NORMAL, COLOR_WHITE, COLOR_BLUE);
+		init_pair(GNT_COLOR_HIGHLIGHT_D, COLOR_CYAN, COLOR_BLACK);
+	}
+}
+
+void
+gnt_uninit_colors()
+{
+	if (can_use_custom_color())
+		restore_colors();
+}
+
+static int
+get_color(char *key)
+{
+	int color;
+	gboolean custom = can_use_custom_color();
+
+	key = g_strstrip(key);
+
+	if (strcmp(key, "black") == 0)
+		color = custom ? GNT_COLOR_BLACK : COLOR_BLACK;
+	else if (strcmp(key, "red") == 0)
+		color = custom ? GNT_COLOR_RED : COLOR_RED;
+	else if (strcmp(key, "green") == 0)
+		color = custom ? GNT_COLOR_GREEN : COLOR_GREEN;
+	else if (strcmp(key, "blue") == 0)
+		color = custom ? GNT_COLOR_BLUE : COLOR_BLUE;
+	else if (strcmp(key, "white") == 0)
+		color = custom ? GNT_COLOR_WHITE : COLOR_WHITE;
+	else if (strcmp(key, "gray") == 0)
+		color = custom ? GNT_COLOR_GRAY : COLOR_YELLOW;  /* eh? */
+	else if (strcmp(key, "darkgray") == 0)
+		color = custom ? GNT_COLOR_DARK_GRAY : COLOR_BLACK;
+	else if (strcmp(key, "magenta") == 0)
+		color = COLOR_MAGENTA;
+	else if (strcmp(key, "cyan") == 0)
+		color = COLOR_CYAN;
+	else
+		color = -1;
+	return color;
+}
+
+#if GLIB_CHECK_VERSION(2,6,0)
+void gnt_colors_parse(GKeyFile *kfile)
+{
+	GError *error = NULL;
+	gsize nkeys;
+	char **keys = g_key_file_get_keys(kfile, "colors", &nkeys, &error);
+
+	if (error)
+	{
+		g_printerr("GntColors: %s\n", error->message);
+		g_error_free(error);
+		error = NULL;
+	}
+	else if (nkeys)
+	{
+		gnt_init_colors();
+		while (nkeys--)
+		{
+			gsize len;
+			gchar *key = keys[nkeys];
+			char **list = g_key_file_get_string_list(kfile, "colors", key, &len, NULL);
+			if (len == 3)
+			{
+				int r = atoi(list[0]);
+				int g = atoi(list[1]);
+				int b = atoi(list[2]);
+				int color = -1;
+
+				key = g_ascii_strdown(key, -1);
+				color = get_color(key);
+				g_free(key);
+				if (color == -1)
+					continue;
+
+				init_color(color, r, g, b);
+			}
+			g_strfreev(list);
+		}
+
+		g_strfreev(keys);
+	}
+
+	gnt_color_pairs_parse(kfile);
+}
+
+void gnt_color_pairs_parse(GKeyFile *kfile)
+{
+	GError *error = NULL;
+	gsize nkeys;
+	char **keys = g_key_file_get_keys(kfile, "colorpairs", &nkeys, &error);
+
+	if (error)
+	{
+		g_printerr("GntColors: %s\n", error->message);
+		g_error_free(error);
+		return;
+	}
+	else if (nkeys)
+		gnt_init_colors();
+
+	while (nkeys--)
+	{
+		gsize len;
+		gchar *key = keys[nkeys];
+		char **list = g_key_file_get_string_list(kfile, "colorpairs", key, &len, NULL);
+		if (len == 2)
+		{
+			GntColorType type = 0;
+			gchar *fgc = g_ascii_strdown(list[0], -1);
+			gchar *bgc = g_ascii_strdown(list[1], -1);
+			int fg = get_color(fgc);
+			int bg = get_color(bgc);
+			g_free(fgc);
+			g_free(bgc);
+			if (fg == -1 || bg == -1)
+				continue;
+
+			key = g_ascii_strdown(key, -1);
+
+			if (strcmp(key, "normal") == 0)
+				type = GNT_COLOR_NORMAL;
+			else if (strcmp(key, "highlight") == 0)
+				type = GNT_COLOR_HIGHLIGHT;
+			else if (strcmp(key, "highlightd") == 0)
+				type = GNT_COLOR_HIGHLIGHT_D;
+			else if (strcmp(key, "shadow") == 0)
+				type = GNT_COLOR_SHADOW;
+			else if (strcmp(key, "title") == 0)
+				type = GNT_COLOR_TITLE;
+			else if (strcmp(key, "titled") == 0)
+				type = GNT_COLOR_TITLE_D;
+			else if (strcmp(key, "text") == 0)
+				type = GNT_COLOR_TEXT_NORMAL;
+			else if (strcmp(key, "disabled") == 0)
+				type = GNT_COLOR_DISABLED;
+			else if (strcmp(key, "urgent") == 0)
+				type = GNT_COLOR_URGENT;
+			else {
+				g_free(key);
+				continue;
+			}
+			g_free(key);
+
+			init_pair(type, fg, bg);
+		}
+		g_strfreev(list);
+	}
+
+	g_strfreev(keys);
+}
+
+#endif  /* GKeyFile */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntcolors.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,46 @@
+#ifndef GNT_COLORS_H
+#define GNT_COLORS_H
+
+#include <glib.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_COLOR_TITLE_D,
+	GNT_COLOR_URGENT,       /* this is for the 'urgent' windows */
+	GNT_COLORS
+} GntColorType;
+
+enum
+{
+	GNT_COLOR_BLACK = 0,
+	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(void);
+
+void gnt_uninit_colors(void);
+
+#if GLIB_CHECK_VERSION(2,6,0)
+void gnt_colors_parse(GKeyFile *kfile);
+
+void gnt_color_pairs_parse(GKeyFile *kfile);
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntcombobox.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,324 @@
+#include "gntbox.h"
+#include "gntcombobox.h"
+#include "gnttree.h"
+#include "gntmarshal.h"
+#include "gntutils.h"
+
+#include <string.h>
+
+enum
+{
+	SIG_SELECTION_CHANGED,
+	SIGS,
+};
+
+static GntWidgetClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+static void (*widget_lost_focus)(GntWidget *widget);
+
+static void
+set_selection(GntComboBox *box, gpointer key)
+{
+	if (box->selected != key)
+	{
+		/* XXX: make sure the key actually does exist */
+		gpointer old = box->selected;
+		box->selected = key;
+		if (GNT_WIDGET(box)->window)
+			gnt_widget_draw(GNT_WIDGET(box));
+		if (box->dropdown)
+			gnt_tree_set_selected(GNT_TREE(box->dropdown), key);
+		g_signal_emit(box, signals[SIG_SELECTION_CHANGED], 0, old, key);
+	}
+}
+
+static void
+hide_popup(GntComboBox *box, gboolean set)
+{
+	gnt_widget_set_size(box->dropdown,
+		box->dropdown->priv.width - 1, box->dropdown->priv.height);
+	if (set)
+		set_selection(box, gnt_tree_get_selection_data(GNT_TREE(box->dropdown)));
+	else
+		gnt_tree_set_selected(GNT_TREE(box->dropdown), box->selected);
+	gnt_widget_hide(box->dropdown->parent);
+}
+
+static void
+gnt_combo_box_draw(GntWidget *widget)
+{
+	GntComboBox *box = GNT_COMBO_BOX(widget);
+	char *text = NULL, *s;
+	GntColorType type;
+	int len;
+	
+	if (box->dropdown && box->selected)
+		text = gnt_tree_get_selection_text(GNT_TREE(box->dropdown));
+
+	if (text == NULL)
+		text = g_strdup("");
+
+	if (gnt_widget_has_focus(widget))
+		type = GNT_COLOR_HIGHLIGHT;
+	else
+		type = GNT_COLOR_NORMAL;
+
+	wbkgdset(widget->window, '\0' | COLOR_PAIR(type));
+
+	s = (char*)gnt_util_onscreen_width_to_pointer(text, widget->priv.width - 4, &len);
+	*s = '\0';
+
+	mvwaddstr(widget->window, 1, 1, text);
+	whline(widget->window, ' ' | COLOR_PAIR(type), widget->priv.width - 4 - len);
+	mvwaddch(widget->window, 1, widget->priv.width - 3, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL));
+	mvwaddch(widget->window, 1, widget->priv.width - 2, ACS_DARROW | COLOR_PAIR(GNT_COLOR_NORMAL));
+
+	g_free(text);
+	GNTDEBUG;
+}
+
+static void
+gnt_combo_box_size_request(GntWidget *widget)
+{
+	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
+	{
+		GntWidget *dd = GNT_COMBO_BOX(widget)->dropdown;
+		gnt_widget_size_request(dd);
+		widget->priv.height = 3;   /* For now, a combobox will have border */
+		widget->priv.width = MAX(10, dd->priv.width + 4);
+	}
+}
+
+static void
+gnt_combo_box_map(GntWidget *widget)
+{
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+		gnt_widget_size_request(widget);
+	GNTDEBUG;
+}
+
+static void
+popup_dropdown(GntComboBox *box)
+{
+	GntWidget *widget = GNT_WIDGET(box);
+	GntWidget *parent = box->dropdown->parent;
+	int height = g_list_length(GNT_TREE(box->dropdown)->list);
+	int y = widget->priv.y + widget->priv.height - 1;
+	gnt_widget_set_size(box->dropdown, widget->priv.width, height + 2);
+
+	if (y + height + 2 >= getmaxy(stdscr))
+		y = widget->priv.y - height - 1;
+	gnt_widget_set_position(parent, widget->priv.x, y);
+	if (parent->window)
+	{
+		mvwin(parent->window, y, widget->priv.x);
+		wresize(parent->window, height+2, widget->priv.width);
+	}
+	parent->priv.width = widget->priv.width;
+	parent->priv.height = height + 2;
+
+	GNT_WIDGET_UNSET_FLAGS(parent, GNT_WIDGET_INVISIBLE);
+	gnt_widget_draw(parent);
+}
+
+static gboolean
+gnt_combo_box_key_pressed(GntWidget *widget, const char *text)
+{
+	GntComboBox *box = GNT_COMBO_BOX(widget);
+	if (GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED))
+	{
+		if (text[1] == 0)
+		{
+			switch (text[0])
+			{
+				case '\r':
+				case '\t':
+					hide_popup(box, TRUE);
+					return TRUE;
+				case 27:
+					hide_popup(box, FALSE);
+					return TRUE;
+			}
+		}
+		if (gnt_widget_key_pressed(box->dropdown, text))
+			return TRUE;
+	}
+	else
+	{
+		if (text[0] == 27)
+		{
+			if (strcmp(text, GNT_KEY_UP) == 0 ||
+					strcmp(text, GNT_KEY_DOWN) == 0)
+			{
+				popup_dropdown(box);
+				return TRUE;
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+static void
+gnt_combo_box_destroy(GntWidget *widget)
+{
+	gnt_widget_destroy(GNT_COMBO_BOX(widget)->dropdown->parent);
+}
+
+static void
+gnt_combo_box_lost_focus(GntWidget *widget)
+{
+	GntComboBox *combo = GNT_COMBO_BOX(widget);
+	if (GNT_WIDGET_IS_FLAG_SET(combo->dropdown->parent, GNT_WIDGET_MAPPED))
+		hide_popup(combo, FALSE);
+	widget_lost_focus(widget);
+}
+
+static gboolean
+gnt_combo_box_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
+{
+	GntComboBox *box = GNT_COMBO_BOX(widget);
+	gboolean dshowing = GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED);
+
+	if (event == GNT_MOUSE_SCROLL_UP) {
+		if (dshowing)
+			gnt_widget_key_pressed(box->dropdown, GNT_KEY_UP);
+	} else if (event == GNT_MOUSE_SCROLL_DOWN) {
+		if (dshowing)
+			gnt_widget_key_pressed(box->dropdown, GNT_KEY_DOWN);
+	} else if (event == GNT_LEFT_MOUSE_DOWN) {
+		if (dshowing) {
+			hide_popup(box, TRUE);
+		} else {
+			popup_dropdown(GNT_COMBO_BOX(widget));
+		}
+	} else
+		return FALSE;
+	return TRUE;
+}
+
+static void
+gnt_combo_box_size_changed(GntWidget *widget, int oldw, int oldh)
+{
+	GntComboBox *box = GNT_COMBO_BOX(widget);
+	gnt_widget_set_size(box->dropdown, widget->priv.width - 1, box->dropdown->priv.height);
+}
+
+static void
+gnt_combo_box_class_init(GntComboBoxClass *klass)
+{
+	parent_class = GNT_WIDGET_CLASS(klass);
+
+	parent_class->destroy = gnt_combo_box_destroy;
+	parent_class->draw = gnt_combo_box_draw;
+	parent_class->map = gnt_combo_box_map;
+	parent_class->size_request = gnt_combo_box_size_request;
+	parent_class->key_pressed = gnt_combo_box_key_pressed;
+	parent_class->clicked = gnt_combo_box_clicked;
+	parent_class->size_changed = gnt_combo_box_size_changed;
+
+	widget_lost_focus = parent_class->lost_focus;
+	parent_class->lost_focus = gnt_combo_box_lost_focus;
+
+	signals[SIG_SELECTION_CHANGED] = 
+		g_signal_new("selection-changed",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 0,
+					 NULL, NULL,
+					 gnt_closure_marshal_VOID__POINTER_POINTER,
+					 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
+
+	GNTDEBUG;
+}
+
+static void
+gnt_combo_box_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *box;
+	GntWidget *widget = GNT_WIDGET(instance);
+	GntComboBox *combo = GNT_COMBO_BOX(instance);
+
+	GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance),
+			GNT_WIDGET_GROW_X | GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_NO_SHADOW);
+	combo->dropdown = gnt_tree_new();
+
+	box = gnt_box_new(FALSE, FALSE);
+	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER | GNT_WIDGET_TRANSIENT);
+	gnt_box_set_pad(GNT_BOX(box), 0);
+	gnt_box_add_widget(GNT_BOX(box), combo->dropdown);
+	
+	widget->priv.minw = 4;
+	widget->priv.minh = 3;
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntComboBox API
+ *****************************************************************************/
+GType
+gnt_combo_box_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntComboBoxClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_combo_box_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntComboBox),
+			0,						/* n_preallocs		*/
+			gnt_combo_box_init,			/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntComboBox",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_combo_box_new()
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_COMBO_BOX, NULL);
+
+	return widget;
+}
+
+void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text)
+{
+	gnt_tree_add_row_last(GNT_TREE(box->dropdown), key,
+			gnt_tree_create_row(GNT_TREE(box->dropdown), text), NULL);
+	if (box->selected == NULL)
+		set_selection(box, key);
+}
+
+gpointer gnt_combo_box_get_selected_data(GntComboBox *box)
+{
+	return box->selected;
+}
+
+void gnt_combo_box_set_selected(GntComboBox *box, gpointer key)
+{
+	set_selection(box, key);
+}
+
+void gnt_combo_box_remove(GntComboBox *box, gpointer key)
+{
+	gnt_tree_remove(GNT_TREE(box->dropdown), key);
+	if (box->selected == key)
+		set_selection(box, NULL);
+}
+
+void gnt_combo_box_remove_all(GntComboBox *box)
+{
+	gnt_tree_remove_all(GNT_TREE(box->dropdown));
+	set_selection(box, NULL);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntcombobox.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,61 @@
+#ifndef GNT_COMBO_BOX_H
+#define GNT_COMBO_BOX_H
+
+#include "gnt.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+#include "gntwidget.h"
+
+#define GNT_TYPE_COMBO_BOX				(gnt_combo_box_get_gtype())
+#define GNT_COMBO_BOX(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_COMBO_BOX, GntComboBox))
+#define GNT_COMBO_BOX_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_COMBO_BOX, GntComboBoxClass))
+#define GNT_IS_COMBO_BOX(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_COMBO_BOX))
+#define GNT_IS_COMBO_BOX_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_COMBO_BOX))
+#define GNT_COMBO_BOX_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_COMBO_BOX, GntComboBoxClass))
+
+#define GNT_COMBO_BOX_FLAGS(obj)				(GNT_COMBO_BOX(obj)->priv.flags)
+#define GNT_COMBO_BOX_SET_FLAGS(obj, flags)		(GNT_COMBO_BOX_FLAGS(obj) |= flags)
+#define GNT_COMBO_BOX_UNSET_FLAGS(obj, flags)	(GNT_COMBO_BOX_FLAGS(obj) &= ~(flags))
+
+typedef struct _GnComboBox			GntComboBox;
+typedef struct _GnComboBoxPriv		GntComboBoxPriv;
+typedef struct _GnComboBoxClass		GntComboBoxClass;
+
+struct _GnComboBox
+{
+	GntWidget parent;
+
+	GntWidget *dropdown;   /* This is a GntTree */
+
+	void *selected;        /* Currently selected key */
+};
+
+struct _GnComboBoxClass
+{
+	GntWidgetClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_combo_box_get_gtype(void);
+
+GntWidget *gnt_combo_box_new(void);
+
+void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text);
+
+void gnt_combo_box_remove(GntComboBox *box, gpointer key);
+
+void gnt_combo_box_remove_all(GntComboBox *box);
+
+gpointer gnt_combo_box_get_selected_data(GntComboBox *box);
+
+void gnt_combo_box_set_selected(GntComboBox *box, gpointer key);
+
+G_END_DECLS
+
+#endif /* GNT_COMBO_BOX_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntentry.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,932 @@
+#include <ctype.h>
+#include <string.h>
+
+#include "gntbox.h"
+#include "gntentry.h"
+#include "gntstyle.h"
+#include "gnttree.h"
+#include "gntutils.h"
+
+enum
+{
+	SIG_TEXT_CHANGED,
+	SIGS,
+};
+static guint signals[SIGS] = { 0 };
+
+static GntWidgetClass *parent_class = NULL;
+
+static void gnt_entry_set_text_internal(GntEntry *entry, const char *text);
+
+static void
+destroy_suggest(GntEntry *entry)
+{
+	if (entry->ddown)
+	{
+		gnt_widget_destroy(entry->ddown->parent);
+		entry->ddown = NULL;
+	}
+}
+
+static char *
+get_beginning_of_word(GntEntry *entry)
+{
+	char *s = entry->cursor;
+	while (s > entry->start)
+	{
+		char *t = g_utf8_find_prev_char(entry->start, s);
+		if (isspace(*t))
+			break;
+		s = t;
+	}
+	return s;
+}
+
+static gboolean
+show_suggest_dropdown(GntEntry *entry)
+{
+	char *suggest = NULL;
+	int len;
+	int offset = 0, x, y;
+	int count = 0;
+	GList *iter;
+
+	if (entry->word)
+	{
+		char *s = get_beginning_of_word(entry);
+		suggest = g_strndup(s, entry->cursor - s);
+		if (entry->scroll < s)
+			offset = gnt_util_onscreen_width(entry->scroll, s);
+	}
+	else
+		suggest = g_strdup(entry->start);
+	len = strlen(suggest);  /* Don't need to use the utf8-function here */
+	
+	if (entry->ddown == NULL)
+	{
+		GntWidget *box = gnt_vbox_new(FALSE);
+		entry->ddown = gnt_tree_new();
+		gnt_tree_set_compare_func(GNT_TREE(entry->ddown), (GCompareFunc)g_utf8_collate);
+		gnt_box_add_widget(GNT_BOX(box), entry->ddown);
+		/* XXX: Connect to the "activate" signal for the dropdown tree */
+
+		GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_TRANSIENT);
+
+		gnt_widget_get_position(GNT_WIDGET(entry), &x, &y);
+		x += offset;
+		y++;
+		if (y + 10 >= getmaxy(stdscr))
+			y -= 11;
+		gnt_widget_set_position(box, x, y);
+	}
+	else
+		gnt_tree_remove_all(GNT_TREE(entry->ddown));
+
+	for (count = 0, iter = entry->suggests; iter; iter = iter->next)
+	{
+		const char *text = iter->data;
+		if (g_ascii_strncasecmp(suggest, text, len) == 0 && strlen(text) >= len)
+		{
+			gnt_tree_add_row_after(GNT_TREE(entry->ddown), (gpointer)text,
+					gnt_tree_create_row(GNT_TREE(entry->ddown), text),
+					NULL, NULL);
+			count++;
+		}
+	}
+	g_free(suggest);
+
+	if (count == 0)
+	{
+		destroy_suggest(entry);
+		return FALSE;
+	}
+
+	gnt_widget_draw(entry->ddown->parent);
+	return TRUE;
+}
+
+static void
+gnt_entry_draw(GntWidget *widget)
+{
+	GntEntry *entry = GNT_ENTRY(widget);
+	int stop;
+	gboolean focus;
+
+	if ((focus = 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));
+
+	if (entry->masked)
+	{
+		mvwhline(widget->window, 0, 0, gnt_ascii_only() ? '*' : ACS_BULLET,
+				g_utf8_pointer_to_offset(entry->scroll, entry->end));
+	}
+	else
+		mvwprintw(widget->window, 0, 0, "%s", entry->scroll);
+
+	stop = gnt_util_onscreen_width(entry->scroll, entry->end);
+	if (stop < widget->priv.width)
+		whline(widget->window, ENTRY_CHAR, widget->priv.width - stop);
+
+	if (focus)
+		mvwchgat(widget->window, 0, gnt_util_onscreen_width(entry->scroll, entry->cursor),
+				1, A_REVERSE, GNT_COLOR_TEXT_NORMAL, NULL);
+
+	GNTDEBUG;
+}
+
+static void
+gnt_entry_size_request(GntWidget *widget)
+{
+	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
+	{
+		widget->priv.height = 1;
+		widget->priv.width = 20;
+	}
+}
+
+static void
+gnt_entry_map(GntWidget *widget)
+{
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+		gnt_widget_size_request(widget);
+	GNTDEBUG;
+}
+
+static void
+entry_redraw(GntWidget *widget)
+{
+	gnt_entry_draw(widget);
+	gnt_widget_queue_update(widget);
+}
+
+static void
+entry_text_changed(GntEntry *entry)
+{
+	g_signal_emit(entry, signals[SIG_TEXT_CHANGED], 0);
+}
+
+static gboolean
+move_back(GntBindable *bind, GList *null)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	if (entry->cursor <= entry->start)
+		return FALSE;
+	entry->cursor = g_utf8_find_prev_char(entry->start, entry->cursor);
+	if (entry->cursor < entry->scroll)
+		entry->scroll = entry->cursor;
+	entry_redraw(GNT_WIDGET(entry));
+	return TRUE;
+}
+
+static gboolean
+move_forward(GntBindable *bind, GList *list)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	if (entry->cursor >= entry->end)
+		return FALSE;
+	entry->cursor = g_utf8_find_next_char(entry->cursor, NULL);
+	while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width)
+		entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
+	entry_redraw(GNT_WIDGET(entry));
+	return TRUE;
+}
+
+static gboolean
+backspace(GntBindable *bind, GList *null)
+{
+	int len;
+	GntEntry *entry = GNT_ENTRY(bind);
+
+	if (entry->cursor <= entry->start)
+		return TRUE;
+	
+	len = entry->cursor - g_utf8_find_prev_char(entry->start, entry->cursor);
+	entry->cursor -= len;
+	memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor);
+	entry->end -= len;
+
+	if (entry->scroll > entry->start)
+		entry->scroll = g_utf8_find_prev_char(entry->start, entry->scroll);
+
+	entry_redraw(GNT_WIDGET(entry));
+	if (entry->ddown)
+		show_suggest_dropdown(entry);
+	entry_text_changed(entry);
+	return TRUE;
+}
+
+static gboolean
+delkey(GntBindable *bind, GList *null)
+{
+	int len;
+	GntEntry *entry = GNT_ENTRY(bind);
+
+	if (entry->cursor >= entry->end)
+		return FALSE;
+	
+	len = g_utf8_find_next_char(entry->cursor, NULL) - entry->cursor;
+	memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor - len + 1);
+	entry->end -= len;
+	entry_redraw(GNT_WIDGET(entry));
+
+	if (entry->ddown)
+		show_suggest_dropdown(entry);
+	entry_text_changed(entry);
+	return TRUE;
+}
+
+static gboolean
+move_start(GntBindable *bind, GList *null)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	entry->scroll = entry->cursor = entry->start;
+	entry_redraw(GNT_WIDGET(entry));
+	return TRUE;
+}
+
+static gboolean
+move_end(GntBindable *bind, GList *null)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	entry->cursor = entry->end;
+	/* This should be better than this */
+	while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width)
+		entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
+	entry_redraw(GNT_WIDGET(entry));
+	return TRUE;
+}
+
+static gboolean
+history_prev(GntBindable *bind, GList *null)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	if (entry->histlength && entry->history->prev)
+	{
+		entry->history = entry->history->prev;
+		gnt_entry_set_text_internal(entry, entry->history->data);
+		destroy_suggest(entry);
+		entry_text_changed(entry);
+
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+history_next(GntBindable *bind, GList *null)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	if (entry->histlength && entry->history->next)
+	{
+		if (entry->history->prev == NULL)
+		{
+			/* Save the current contents */
+			char *text = g_strdup(gnt_entry_get_text(entry));
+			g_free(entry->history->data);
+			entry->history->data = text;
+		}
+
+		entry->history = entry->history->next;
+		gnt_entry_set_text_internal(entry, entry->history->data);
+		destroy_suggest(entry);
+		entry_text_changed(entry);
+
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+clipboard_paste(GntBindable *bind, GList *n)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	gchar *i, *text, *a, *all;
+	text = i = gnt_get_clipboard_string();
+	while (*i != '\0') {
+		i = g_utf8_next_char(i);
+		if (*i == '\r' || *i == '\n')
+			*i = ' ';
+	}
+	a = g_strndup(entry->start, entry->cursor - entry->start);
+	all = g_strconcat(a, text, entry->cursor, NULL);
+	gnt_entry_set_text_internal(entry, all);
+	g_free(a);
+	g_free(text);
+	g_free(all);
+	return TRUE;
+}
+
+static gboolean
+suggest_show(GntBindable *bind, GList *null)
+{
+	return show_suggest_dropdown(GNT_ENTRY(bind));
+}
+
+static gboolean
+suggest_next(GntBindable *bind, GList *null)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	if (entry->ddown) {
+		gnt_bindable_perform_action_named(GNT_BINDABLE(entry->ddown), "move-down", NULL);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+suggest_prev(GntBindable *bind, GList *null)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	if (entry->ddown) {
+		gnt_bindable_perform_action_named(GNT_BINDABLE(entry->ddown), "move-up", NULL);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+del_to_home(GntBindable *bind, GList *null)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	if (entry->cursor <= entry->start)
+		return TRUE;
+	memmove(entry->start, entry->cursor, entry->end - entry->cursor);
+	entry->end -= (entry->cursor - entry->start);
+	entry->cursor = entry->scroll = entry->start;
+	memset(entry->end, '\0', entry->buffer - (entry->end - entry->start));
+	entry_redraw(GNT_WIDGET(bind));
+	entry_text_changed(entry);
+	return TRUE;
+}
+
+static gboolean
+del_to_end(GntBindable *bind, GList *null)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	if (entry->end <= entry->cursor)
+		return TRUE;
+	entry->end = entry->cursor;
+	memset(entry->end, '\0', entry->buffer - (entry->end - entry->start));
+	entry_redraw(GNT_WIDGET(bind));
+	entry_text_changed(entry);
+	return TRUE;
+}
+
+#define SAME(a,b)    ((g_unichar_isalpha(a) && g_unichar_isalpha(b)) || \
+				(g_unichar_isdigit(a) && g_unichar_isdigit(b)) || \
+				(g_unichar_isspace(a) && g_unichar_isspace(b)) || \
+				(g_unichar_iswide(a) && g_unichar_iswide(b)))
+
+static const char *
+begin_word(const char *text, const char *begin)
+{
+	gunichar ch = 0;
+	while (text > begin && (!*text || g_unichar_isspace(g_utf8_get_char(text))))
+		text = g_utf8_find_prev_char(begin, text);
+	ch = g_utf8_get_char(text);
+	while ((text = g_utf8_find_prev_char(begin, text)) >= begin) {
+		gunichar cur = g_utf8_get_char(text);
+		if (!SAME(ch, cur))
+			break;
+	}
+
+	return (text ? g_utf8_find_next_char(text, NULL) : begin);
+}
+
+static const char *
+next_begin_word(const char *text, const char *end)
+{
+	gunichar ch = 0;
+	ch = g_utf8_get_char(text);
+	while ((text = g_utf8_find_next_char(text, end)) != NULL && text <= end) {
+		gunichar cur = g_utf8_get_char(text);
+		if (!SAME(ch, cur))
+			break;
+	}
+
+	while (text && text < end && g_unichar_isspace(g_utf8_get_char(text)))
+		text = g_utf8_find_next_char(text, end);
+	return (text ? text : end);
+}
+
+#undef SAME
+static gboolean
+move_back_word(GntBindable *bind, GList *null)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	const char *iter = g_utf8_find_prev_char(entry->start, entry->cursor);
+
+	if (iter < entry->start)
+		return TRUE;
+	iter = begin_word(iter, entry->start);
+	entry->cursor = (char*)iter;
+	if (entry->cursor < entry->scroll)
+		entry->scroll = entry->cursor;
+	entry_redraw(GNT_WIDGET(bind));
+	return TRUE;
+}
+
+static gboolean
+del_prev_word(GntBindable *bind, GList *null)
+{
+	GntWidget *widget = GNT_WIDGET(bind);
+	GntEntry *entry = GNT_ENTRY(bind);
+	char *iter = g_utf8_find_prev_char(entry->start, entry->cursor);
+	int count;
+
+	if (iter < entry->start)
+		return TRUE;
+	iter = (char*)begin_word(iter, entry->start);
+	count = entry->cursor - iter;
+	memmove(iter, entry->cursor, entry->end - entry->cursor);
+	entry->end -= count;
+	entry->cursor = iter;
+	if (entry->cursor <= entry->scroll) {
+		entry->scroll = entry->cursor - widget->priv.width + 2;
+		if (entry->scroll < entry->start)
+			entry->scroll = entry->start;
+	}
+	memset(entry->end, '\0', entry->buffer - (entry->end - entry->start));
+	entry_redraw(widget);
+	entry_text_changed(entry);
+
+	return TRUE;
+}
+
+static gboolean
+move_forward_word(GntBindable *bind, GList *list)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	GntWidget *widget = GNT_WIDGET(bind);
+	entry->cursor = (char *)next_begin_word(entry->cursor, entry->end);
+	while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width) {
+		entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
+	}
+	entry_redraw(widget);
+	return TRUE;
+}
+
+static gboolean
+delete_forward_word(GntBindable *bind, GList *list)
+{
+	GntEntry *entry = GNT_ENTRY(bind);
+	GntWidget *widget = GNT_WIDGET(bind);
+	char *iter = (char *)next_begin_word(entry->cursor, entry->end);
+	int len = entry->end - iter + 1;
+	if (len <= 0)
+		return TRUE;
+	memmove(entry->cursor, iter, len);
+	len = iter - entry->cursor;
+	entry->end -= len;
+	memset(entry->end, '\0', len);
+	entry_redraw(widget);
+	entry_text_changed(entry);
+	return TRUE;
+}
+
+static gboolean
+gnt_entry_key_pressed(GntWidget *widget, const char *text)
+{
+	GntEntry *entry = GNT_ENTRY(widget);
+
+	if (text[0] == 27)
+	{
+		if (text[1] == 0)
+		{
+			destroy_suggest(entry);
+			return TRUE;
+		}
+
+		return FALSE;
+	}
+	else
+	{
+		if (text[0] == '\t')
+		{
+			if (entry->ddown)
+				destroy_suggest(entry);
+			else if (entry->suggests)
+				return show_suggest_dropdown(entry);
+
+			return FALSE;
+		}
+		else if (text[0] == '\r' && entry->ddown)
+		{
+			char *text = g_strdup(gnt_tree_get_selection_data(GNT_TREE(entry->ddown)));
+			destroy_suggest(entry);
+			if (entry->word)
+			{
+				char *s = get_beginning_of_word(entry);
+				char *iter = text;
+				while (*iter && toupper(*s) == toupper(*iter))
+				{
+					*s++ = *iter++;
+				}
+				gnt_entry_key_pressed(widget, iter);
+			}
+			else
+			{
+				gnt_entry_set_text_internal(entry, text);
+			}
+			g_free(text);
+			entry_text_changed(entry);
+			return TRUE;
+		}
+
+		if (!iscntrl(text[0]))
+		{
+			const char *str, *next;
+
+			for (str = text; *str; str = next)
+			{
+				int len;
+				next = g_utf8_find_next_char(str, NULL);
+				len = next - str;
+
+				/* Valid input? */
+				/* XXX: Is it necessary to use _unichar_ variants here? */
+				if (ispunct(*str) && (entry->flag & GNT_ENTRY_FLAG_NO_PUNCT))
+					continue;
+				if (isspace(*str) && (entry->flag & GNT_ENTRY_FLAG_NO_SPACE))
+					continue;
+				if (isalpha(*str) && !(entry->flag & GNT_ENTRY_FLAG_ALPHA))
+					continue;
+				if (isdigit(*str) && !(entry->flag & GNT_ENTRY_FLAG_INT))
+					continue;
+
+				/* Reached the max? */
+				if (entry->max && g_utf8_pointer_to_offset(entry->start, entry->end) >= entry->max)
+					continue;
+
+				if (entry->end + len - entry->start >= entry->buffer)
+				{
+					/* This will cause the buffer to grow */
+					char *tmp = g_strdup(entry->start);
+					gnt_entry_set_text_internal(entry, tmp);
+					g_free(tmp);
+				}
+
+				memmove(entry->cursor + len, entry->cursor, entry->end - entry->cursor + 1);
+				entry->end += len;
+
+				while (str < next)
+				{
+					if (*str == '\r' || *str == '\n')
+						*entry->cursor = ' ';
+					else
+						*entry->cursor = *str;
+					entry->cursor++;
+					str++;
+				}
+
+				while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width)
+					entry->scroll = g_utf8_find_next_char(entry->scroll, NULL);
+
+				if (entry->ddown)
+					show_suggest_dropdown(entry);
+			}
+			entry_redraw(widget);
+			entry_text_changed(entry);
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+static void
+gnt_entry_destroy(GntWidget *widget)
+{
+	GntEntry *entry = GNT_ENTRY(widget);
+	g_free(entry->start);
+
+	if (entry->history)
+	{
+		entry->history = g_list_first(entry->history);
+		g_list_foreach(entry->history, (GFunc)g_free, NULL);
+		g_list_free(entry->history);
+	}
+
+	if (entry->suggests)
+	{
+		g_list_foreach(entry->suggests, (GFunc)g_free, NULL);
+		g_list_free(entry->suggests);
+	}
+
+	if (entry->ddown)
+	{
+		gnt_widget_destroy(entry->ddown->parent);
+	}
+}
+
+static void
+gnt_entry_lost_focus(GntWidget *widget)
+{
+	GntEntry *entry = GNT_ENTRY(widget);
+	destroy_suggest(entry);
+	entry_redraw(widget);
+}
+
+static void
+gnt_entry_class_init(GntEntryClass *klass)
+{
+	GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass);
+	char s[2] = {erasechar(), 0};
+
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->destroy = gnt_entry_destroy;
+	parent_class->draw = gnt_entry_draw;
+	parent_class->map = gnt_entry_map;
+	parent_class->size_request = gnt_entry_size_request;
+	parent_class->key_pressed = gnt_entry_key_pressed;
+	parent_class->lost_focus = gnt_entry_lost_focus;
+
+	signals[SIG_TEXT_CHANGED] =
+		g_signal_new("text_changed",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntEntryClass, text_changed),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__VOID,
+					 G_TYPE_NONE, 0);
+
+	gnt_bindable_class_register_action(bindable, "cursor-home", move_start,
+				GNT_KEY_CTRL_A, NULL);
+	gnt_bindable_register_binding(bindable, "cursor-home", GNT_KEY_HOME, NULL);
+	gnt_bindable_class_register_action(bindable, "cursor-end", move_end,
+				GNT_KEY_CTRL_E, NULL);
+	gnt_bindable_register_binding(bindable, "cursor-end", GNT_KEY_END, NULL);
+	gnt_bindable_class_register_action(bindable, "delete-prev", backspace,
+				GNT_KEY_BACKSPACE, NULL);
+	gnt_bindable_register_binding(bindable, "delete-prev", s, NULL);
+	gnt_bindable_register_binding(bindable, "delete-prev", GNT_KEY_CTRL_H, NULL);
+	gnt_bindable_class_register_action(bindable, "delete-next", delkey,
+				GNT_KEY_DEL, NULL);
+	gnt_bindable_register_binding(bindable, "delete-next", GNT_KEY_CTRL_D, NULL);
+	gnt_bindable_class_register_action(bindable, "delete-start", del_to_home,
+				GNT_KEY_CTRL_U, NULL);
+	gnt_bindable_class_register_action(bindable, "delete-end", del_to_end,
+				GNT_KEY_CTRL_K, NULL);
+	gnt_bindable_class_register_action(bindable, "delete-prev-word", del_prev_word,
+				GNT_KEY_CTRL_W, NULL);
+	gnt_bindable_class_register_action(bindable, "cursor-prev-word", move_back_word,
+				"\033" "b", NULL);
+	gnt_bindable_class_register_action(bindable, "cursor-prev", move_back,
+				GNT_KEY_LEFT, NULL);
+	gnt_bindable_register_binding(bindable, "cursor-prev", GNT_KEY_CTRL_B, NULL);
+	gnt_bindable_class_register_action(bindable, "cursor-next", move_forward,
+				GNT_KEY_RIGHT, NULL);
+	gnt_bindable_register_binding(bindable, "cursor-next", GNT_KEY_CTRL_F, NULL);
+	gnt_bindable_class_register_action(bindable, "cursor-next-word", move_forward_word,
+				"\033" "f", NULL);
+	gnt_bindable_class_register_action(bindable, "delete-next-word", delete_forward_word,
+				"\033" "d", NULL);
+	gnt_bindable_class_register_action(bindable, "suggest-show", suggest_show,
+				"\t", NULL);
+	gnt_bindable_class_register_action(bindable, "suggest-next", suggest_next,
+				GNT_KEY_DOWN, NULL);
+	gnt_bindable_class_register_action(bindable, "suggest-prev", suggest_prev,
+				GNT_KEY_UP, NULL);
+	gnt_bindable_class_register_action(bindable, "history-prev", history_prev,
+				GNT_KEY_CTRL_DOWN, NULL);
+	gnt_bindable_class_register_action(bindable, "history-next", history_next,
+				GNT_KEY_CTRL_UP, NULL);
+	gnt_bindable_class_register_action(bindable, "clipboard-paste", clipboard_paste,
+				GNT_KEY_CTRL_V, NULL);
+
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+	GNTDEBUG;
+}
+
+static void
+gnt_entry_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	GntEntry *entry = GNT_ENTRY(instance);
+
+	entry->flag = GNT_ENTRY_FLAG_ALL;
+	entry->max = 0;
+	
+	entry->histlength = 0;
+	entry->history = NULL;
+
+	entry->word = TRUE;
+	entry->always = FALSE;
+	entry->suggests = NULL;
+
+	GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry),
+			GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW | GNT_WIDGET_CAN_TAKE_FOCUS);
+	GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry), GNT_WIDGET_GROW_X);
+
+	widget->priv.minw = 3;
+	widget->priv.minh = 1;
+	
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntEntry API
+ *****************************************************************************/
+GType
+gnt_entry_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntEntryClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_entry_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntEntry),
+			0,						/* n_preallocs		*/
+			gnt_entry_init,			/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntEntry",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_entry_new(const char *text)
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_ENTRY, NULL);
+	GntEntry *entry = GNT_ENTRY(widget);
+
+	gnt_entry_set_text_internal(entry, text);
+
+	return widget;
+}
+
+static void
+gnt_entry_set_text_internal(GntEntry *entry, const char *text)
+{
+	int len;
+	int scroll, cursor;
+
+	g_free(entry->start);
+
+	if (text && text[0])
+	{
+		len = strlen(text);
+	}
+	else
+	{
+		len = 0;
+	}
+
+	entry->buffer = len + 128;
+
+	scroll = entry->scroll - entry->start;
+	cursor = entry->end - entry->cursor;
+
+	entry->start = g_new0(char, entry->buffer);
+	if (text)
+		snprintf(entry->start, len + 1, "%s", text);
+	entry->end = entry->start + len;
+
+	entry->scroll = entry->start + scroll;
+	entry->cursor = entry->end - cursor;
+
+	if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(entry), GNT_WIDGET_MAPPED))
+		entry_redraw(GNT_WIDGET(entry));
+}
+
+void gnt_entry_set_text(GntEntry *entry, const char *text)
+{
+	gboolean changed = TRUE;
+	if (text == NULL && entry->start == NULL)
+		changed = FALSE;
+	if (text && entry->start && g_utf8_collate(text, entry->start) == 0)
+		changed = FALSE;
+	gnt_entry_set_text_internal(entry, text);
+	if (changed)
+		entry_text_changed(entry);
+}
+
+void gnt_entry_set_max(GntEntry *entry, int max)
+{
+	entry->max = max;
+}
+
+void gnt_entry_set_flag(GntEntry *entry, GntEntryFlag flag)
+{
+	entry->flag = flag;
+	/* XXX: Check the existing string to make sure the flags are respected? */
+}
+
+const char *gnt_entry_get_text(GntEntry *entry)
+{
+	return entry->start;
+}
+
+void gnt_entry_clear(GntEntry *entry)
+{
+	gnt_entry_set_text_internal(entry, NULL);
+	entry->scroll = entry->cursor = entry->end = entry->start;
+	entry_redraw(GNT_WIDGET(entry));
+	destroy_suggest(entry);
+	entry_text_changed(entry);
+}
+
+void gnt_entry_set_masked(GntEntry *entry, gboolean set)
+{
+	entry->masked = set;
+}
+
+void gnt_entry_add_to_history(GntEntry *entry, const char *text)
+{
+	g_return_if_fail(entry->history != NULL);   /* Need to set_history_length first */
+
+	if (g_list_length(entry->history) >= entry->histlength)
+		return;
+
+	entry->history = g_list_first(entry->history);
+	g_free(entry->history->data);
+	entry->history->data = g_strdup(text);
+	entry->history = g_list_prepend(entry->history, NULL);
+}
+
+void gnt_entry_set_history_length(GntEntry *entry, int num)
+{
+	if (num == 0)
+	{
+		entry->histlength = num;
+		if (entry->history)
+		{
+			entry->history = g_list_first(entry->history);
+			g_list_foreach(entry->history, (GFunc)g_free, NULL);
+			g_list_free(entry->history);
+			entry->history = NULL;
+		}
+		return;
+	}
+
+	if (entry->histlength == 0)
+	{
+		entry->histlength = num;
+		entry->history = g_list_append(NULL, NULL);
+		return;
+	}
+
+	if (num > 0 && num < entry->histlength)
+	{
+		GList *first, *iter;
+		int index = 0;
+		for (first = entry->history, index = 0; first->prev; first = first->prev, index++);
+		while ((iter = g_list_nth(first, num)) != NULL)
+		{
+			g_free(iter->data);
+			first = g_list_delete_link(first, iter);
+		}
+		entry->histlength = num;
+		if (index >= num)
+			entry->history = g_list_last(first);
+		return;
+	}
+
+	entry->histlength = num;
+}
+
+void gnt_entry_set_word_suggest(GntEntry *entry, gboolean word)
+{
+	entry->word = word;
+}
+
+void gnt_entry_set_always_suggest(GntEntry *entry, gboolean always)
+{
+	entry->always = always;
+}
+
+void gnt_entry_add_suggest(GntEntry *entry, const char *text)
+{
+	GList *find;
+
+	if (!text || !*text)
+		return;
+	
+	find = g_list_find_custom(entry->suggests, text, (GCompareFunc)g_utf8_collate);
+	if (find)
+		return;
+	entry->suggests = g_list_append(entry->suggests, g_strdup(text));
+}
+
+void gnt_entry_remove_suggest(GntEntry *entry, const char *text)
+{
+	GList *find = g_list_find_custom(entry->suggests, text, (GCompareFunc)g_utf8_collate);
+	if (find)
+	{
+		g_free(find->data);
+		entry->suggests = g_list_delete_link(entry->suggests, find);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntentry.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,106 @@
+#ifndef GNT_ENTRY_H
+#define GNT_ENTRY_H
+
+#include "gntwidget.h"
+#include "gnt.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+
+#define GNT_TYPE_ENTRY				(gnt_entry_get_gtype())
+#define GNT_ENTRY(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_ENTRY, GntEntry))
+#define GNT_ENTRY_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_ENTRY, GntEntryClass))
+#define GNT_IS_ENTRY(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_ENTRY))
+#define GNT_IS_ENTRY_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_ENTRY))
+#define GNT_ENTRY_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_ENTRY, GntEntryClass))
+
+#define GNT_ENTRY_FLAGS(obj)				(GNT_ENTRY(obj)->priv.flags)
+#define GNT_ENTRY_SET_FLAGS(obj, flags)		(GNT_ENTRY_FLAGS(obj) |= flags)
+#define GNT_ENTRY_UNSET_FLAGS(obj, flags)	(GNT_ENTRY_FLAGS(obj) &= ~(flags))
+
+#define	ENTRY_CHAR		'_'			/* The character to use to fill in the blank places */
+
+typedef struct _GnEntry			GntEntry;
+typedef struct _GnEntryPriv		GntEntryPriv;
+typedef struct _GnEntryClass	GntEntryClass;
+
+typedef enum
+{
+	GNT_ENTRY_FLAG_ALPHA    = 1 << 0,  /* Only alpha */
+	GNT_ENTRY_FLAG_INT      = 1 << 1,  /* Only integer */
+	GNT_ENTRY_FLAG_NO_SPACE = 1 << 2,  /* No blank space is allowed */
+	GNT_ENTRY_FLAG_NO_PUNCT = 1 << 3,  /* No punctuations */
+	GNT_ENTRY_FLAG_MASK     = 1 << 4,  /* Mask the inputs */
+} GntEntryFlag;
+
+#define GNT_ENTRY_FLAG_ALL    (GNT_ENTRY_FLAG_ALPHA | GNT_ENTRY_FLAG_INT)
+
+struct _GnEntry
+{
+	GntWidget parent;
+
+	GntEntryFlag flag;
+
+	char *start;
+	char *end;
+	char *scroll;   /* Current scrolling position */
+	char *cursor;   /* Cursor location */
+	                /* 0 <= cursor - scroll < widget-width */
+	
+	size_t buffer;  /* Size of the buffer */
+	
+	int max;        /* 0 means infinite */
+	gboolean masked;
+
+	GList *history; /* History of the strings. User can use this by pressing ctrl+up/down */
+	int histlength; /* How long can the history be? */
+
+	GList *suggests;    /* List of suggestions */
+	gboolean word;      /* Are the suggestions for only a word, or for the whole thing? */
+	gboolean always;    /* Should the list of suggestions show at all times, or only on tab-press? */
+	GntWidget *ddown;   /* The dropdown with the suggested list */
+};
+
+struct _GnEntryClass
+{
+	GntWidgetClass parent;
+
+	void (*text_changed)(GntEntry *entry);
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_entry_get_gtype(void);
+
+GntWidget *gnt_entry_new(const char *text);
+
+void gnt_entry_set_max(GntEntry *entry, int max);
+
+void gnt_entry_set_text(GntEntry *entry, const char *text);
+
+void gnt_entry_set_flag(GntEntry *entry, GntEntryFlag flag);
+
+const char *gnt_entry_get_text(GntEntry *entry);
+
+void gnt_entry_clear(GntEntry *entry);
+
+void gnt_entry_set_masked(GntEntry *entry, gboolean set);
+
+void gnt_entry_add_to_history(GntEntry *entry, const char *text);
+
+void gnt_entry_set_history_length(GntEntry *entry, int num);
+
+void gnt_entry_set_word_suggest(GntEntry *entry, gboolean word);
+
+void gnt_entry_set_always_suggest(GntEntry *entry, gboolean always);
+
+void gnt_entry_add_suggest(GntEntry *entry, const char *text);
+
+void gnt_entry_remove_suggest(GntEntry *entry, const char *text);
+
+G_END_DECLS
+
+#endif /* GNT_ENTRY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntkeys.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,243 @@
+#include "gntkeys.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *gnt_key_cup;
+char *gnt_key_cdown;
+char *gnt_key_cleft;
+char *gnt_key_cright;
+
+static const char *term;
+static GHashTable *specials;
+
+void gnt_init_keys()
+{
+	const char *controls[] = {"", "c-", "ctrl-", "ctr-", "ctl-", NULL};
+	const char *alts[] = {"", "alt-", "a-", "m-", "meta-", NULL};
+	int c, a, ch;
+	char key[32];
+
+	if (term == NULL) {
+		term = getenv("TERM");
+		if (!term)
+			term = "";  /* Just in case */
+	}
+
+	if (strcmp(term, "xterm") == 0 || strcmp(term, "rxvt") == 0) {
+		gnt_key_cup    = "\033" "[1;5A";
+		gnt_key_cdown  = "\033" "[1;5B";
+		gnt_key_cright = "\033" "[1;5C";
+		gnt_key_cleft  = "\033" "[1;5D";
+	} else if (strcmp(term, "screen") == 0 || strcmp(term, "rxvt-unicode") == 0) {
+		gnt_key_cup    = "\033" "Oa";
+		gnt_key_cdown  = "\033" "Ob";
+		gnt_key_cright = "\033" "Oc";
+		gnt_key_cleft  = "\033" "Od";
+	}
+
+	specials = g_hash_table_new(g_str_hash, g_str_equal);
+
+#define INSERT_KEY(k, code) do { \
+		g_hash_table_insert(specials, g_strdup(k), g_strdup(code)); \
+		gnt_keys_add_combination(code); \
+	} while (0)
+
+	INSERT_KEY("home",     GNT_KEY_HOME);
+	INSERT_KEY("end",      GNT_KEY_END);
+	INSERT_KEY("pageup",   GNT_KEY_PGUP);
+	INSERT_KEY("pagedown", GNT_KEY_PGDOWN);
+	INSERT_KEY("insert",   GNT_KEY_INS);
+	INSERT_KEY("delete",   GNT_KEY_DEL);
+
+	INSERT_KEY("left",   GNT_KEY_LEFT);
+	INSERT_KEY("right",  GNT_KEY_RIGHT);
+	INSERT_KEY("up",     GNT_KEY_UP);
+	INSERT_KEY("down",   GNT_KEY_DOWN);
+
+	INSERT_KEY("tab",    "\t");
+	INSERT_KEY("menu",   GNT_KEY_POPUP);
+
+	INSERT_KEY("f1",   GNT_KEY_F1);
+	INSERT_KEY("f2",   GNT_KEY_F2);
+	INSERT_KEY("f3",   GNT_KEY_F3);
+	INSERT_KEY("f4",   GNT_KEY_F4);
+	INSERT_KEY("f5",   GNT_KEY_F5);
+	INSERT_KEY("f6",   GNT_KEY_F6);
+	INSERT_KEY("f7",   GNT_KEY_F7);
+	INSERT_KEY("f8",   GNT_KEY_F8);
+	INSERT_KEY("f9",   GNT_KEY_F9);
+	INSERT_KEY("f10",  GNT_KEY_F10);
+	INSERT_KEY("f11",  GNT_KEY_F11);
+	INSERT_KEY("f12",  GNT_KEY_F12);
+
+#define REM_LENGTH  (sizeof(key) - (cur - key))
+#define INSERT_COMB(k, code) do { \
+		snprintf(key, sizeof(key), "%s%s%s", controls[c], alts[a], k);  \
+		INSERT_KEY(key, code);  \
+	} while (0);
+
+	/* Lower-case alphabets */
+	for (a = 0, c = 0; controls[c]; c++, a = 0) {
+		if (c) {
+			INSERT_COMB("up",    gnt_key_cup);
+			INSERT_COMB("down",  gnt_key_cdown);
+			INSERT_COMB("left",  gnt_key_cleft);
+			INSERT_COMB("right", gnt_key_cright);
+		}
+
+		for (a = 0; alts[a]; a++) {
+			for (ch = 0; ch < 26; ch++) {
+				char str[2] = {'a' + ch, 0}, code[4] = "\0\0\0\0";
+				int ind = 0;
+				if (a)
+					code[ind++] = '\033';
+				code[ind] = (c ? 1 : 'a') + ch;
+				INSERT_COMB(str, code);
+			}
+		}
+	}
+	c = 0;
+	for (a = 0; alts[a]; a++) {
+		/* Upper-case alphabets */
+		for (ch = 0; ch < 26; ch++) {
+			char str[2] = {'A' + ch, 0}, code[] = {'\033', 'A' + ch, 0};
+			INSERT_COMB(str, code);
+		}
+		/* Digits */
+		for (ch = 0; ch < 10; ch++) {
+			char str[2] = {'0' + ch, 0}, code[] = {'\033', '0' + ch, 0};
+			INSERT_COMB(str, code);
+		}
+	}
+}
+
+void gnt_keys_refine(char *text)
+{
+	if (*text == 27 && *(text + 1) == '[' &&
+			(*(text + 2) >= 'A' && *(text + 2) <= 'D')) {
+		/* Apparently this is necessary for urxvt and screen and xterm */
+		if (strcmp(term, "screen") == 0 || strcmp(term, "rxvt-unicode") == 0 ||
+				strcmp(term, "xterm") == 0)
+			*(text + 1) = 'O';
+	} else if (*(unsigned char*)text == 195) {
+		if (*(text + 2) == 0 && strcmp(term, "xterm") == 0) {
+			*(text) = 27;
+			*(text + 1) -= 64;  /* Say wha? */
+		}
+	}
+}
+
+const char *gnt_key_translate(const char *name)
+{
+	return g_hash_table_lookup(specials, name);
+}
+
+/**
+ * The key-bindings will be saved in a tree. When a keystroke happens, GNT will
+ * find the sequence that matches a binding and return the length.
+ * A sequence should not be a prefix of another sequence. If it is, then only
+ * the shortest one will be processed. If we want to change that, we will need
+ * to allow getting the k-th prefix that matches the input, and pay attention
+ * to the return value of gnt_wm_process_input in gntmain.c.
+ */
+#define SIZE 256
+
+#define IS_END         1 << 0
+struct _node
+{
+	struct _node *next[SIZE];
+	int ref;
+	int flags;
+};
+
+static struct _node root = {.ref = 1, .flags = 0};
+
+static void add_path(struct _node *node, const char *path)
+{
+	struct _node *n = NULL;
+	if (!path || !*path) {
+		node->flags |= IS_END;
+		return;
+	}
+	while (*path && node->next[*path]) {
+		node = node->next[*path];
+		node->ref++;
+		path++;
+	}
+	if (!*path)
+		return;
+	n = g_new0(struct _node, 1);
+	n->ref = 1;
+	node->next[*path++] = n;
+	add_path(n, path);
+}
+
+void gnt_keys_add_combination(const char *path)
+{
+	add_path(&root, path);
+}
+
+static void del_path(struct _node *node, const char *path)
+{
+	struct _node *next = NULL;
+
+	if (!*path)
+		return;
+	next = node->next[*path];
+	if (!next)
+		return;
+	del_path(next, path + 1);
+	next->ref--;
+	if (next->ref == 0) {
+		node->next[*path] = NULL;
+		g_free(next);
+	}
+}
+
+void gnt_keys_del_combination(const char *path)
+{
+	del_path(&root, path);
+}
+
+int gnt_keys_find_combination(const char *path)
+{
+	int depth = 0;
+	struct _node *n = &root;
+
+	root.flags &= ~IS_END;
+	while (*path && n->next[*path] && !(n->flags & IS_END)) {
+		if (g_utf8_find_next_char(path, NULL) - path > 1)
+			return 0;
+		n = n->next[*path++];
+		depth++;
+	}
+
+	if (!(n->flags & IS_END))
+		depth = 0;
+	return depth;
+}
+
+static void
+print_path(struct _node *node, int depth)
+{
+	int i;
+	for (i = 0; i < SIZE; i++) {
+		if (node->next[i]) {
+			g_printerr("%*c (%d:%d)\n", depth * 4, i, node->next[i]->ref,
+						node->next[i]->flags);
+			print_path(node->next[i], depth + 1);
+		}
+	}
+}
+
+/* this is purely for debugging purposes. */
+void gnt_keys_print_combinations(void);
+void gnt_keys_print_combinations()
+{
+	g_printerr("--------\n");
+	print_path(&root, 1);
+	g_printerr("--------\n");
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntkeys.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,99 @@
+#ifndef GNT_KEYS_H
+#define GNT_KEYS_H
+
+#include <curses.h>
+#include <term.h>
+
+/**
+ * terminfo/termcap doesn't provide all the information that I want to use, eg.
+ * ctrl-up, ctrl-down etc. So I am going to hard-code some of the information
+ * for some popular $TERMs
+ */
+extern char *gnt_key_cup;
+extern char *gnt_key_cdown;
+extern char *gnt_key_cleft;
+extern char *gnt_key_cright;
+
+#define SAFE(x)   ((x) ? (x) : "")
+
+#define GNT_KEY_POPUP   SAFE(key_f16)   /* Apparently */
+
+/* Arrow keys */
+#define GNT_KEY_LEFT   SAFE(key_left)
+#define GNT_KEY_RIGHT  SAFE(key_right)
+#define GNT_KEY_UP     SAFE(key_up)
+#define GNT_KEY_DOWN   SAFE(key_down)
+
+#define GNT_KEY_CTRL_UP     SAFE(gnt_key_cup)
+#define GNT_KEY_CTRL_DOWN   SAFE(gnt_key_cdown)
+#define GNT_KEY_CTRL_RIGHT  SAFE(gnt_key_cright)
+#define GNT_KEY_CTRL_LEFT   SAFE(gnt_key_cleft)
+
+#define GNT_KEY_PGUP   SAFE(key_ppage)
+#define GNT_KEY_PGDOWN SAFE(key_npage)
+#define GNT_KEY_HOME   SAFE(key_home)
+#define GNT_KEY_END    SAFE(key_end)
+
+#define GNT_KEY_ENTER  carriage_return
+
+#define GNT_KEY_BACKSPACE SAFE(key_backspace)
+#define GNT_KEY_DEL    SAFE(key_dc)
+#define GNT_KEY_INS    SAFE(key_ic)
+
+#define GNT_KEY_CTRL_A     "\001"
+#define GNT_KEY_CTRL_B     "\002"
+#define GNT_KEY_CTRL_D     "\004"
+#define GNT_KEY_CTRL_E     "\005"
+#define GNT_KEY_CTRL_F     "\006"
+#define GNT_KEY_CTRL_G     "\007"
+#define GNT_KEY_CTRL_H     "\010"
+#define GNT_KEY_CTRL_I     "\011"
+#define GNT_KEY_CTRL_J     "\012"
+#define GNT_KEY_CTRL_K     "\013"
+#define GNT_KEY_CTRL_L     "\014"
+#define GNT_KEY_CTRL_M     "\012"
+#define GNT_KEY_CTRL_N     "\016"
+#define GNT_KEY_CTRL_O     "\017"
+#define GNT_KEY_CTRL_P     "\020"
+#define GNT_KEY_CTRL_R     "\022"
+#define GNT_KEY_CTRL_T     "\024"
+#define GNT_KEY_CTRL_U     "\025"
+#define GNT_KEY_CTRL_V     "\026"
+#define GNT_KEY_CTRL_W     "\027"
+#define GNT_KEY_CTRL_X     "\030"
+#define GNT_KEY_CTRL_Y     "\031"
+
+#define GNT_KEY_F1         SAFE(key_f1)
+#define GNT_KEY_F2         SAFE(key_f2)
+#define GNT_KEY_F3         SAFE(key_f3)
+#define GNT_KEY_F4         SAFE(key_f4)
+#define GNT_KEY_F5         SAFE(key_f5)
+#define GNT_KEY_F6         SAFE(key_f6)
+#define GNT_KEY_F7         SAFE(key_f7)
+#define GNT_KEY_F8         SAFE(key_f8)
+#define GNT_KEY_F9         SAFE(key_f9)
+#define GNT_KEY_F10        SAFE(key_f10)
+#define GNT_KEY_F11        SAFE(key_f11)
+#define GNT_KEY_F12        SAFE(key_f12)
+
+/**
+ * This will do stuff with the terminal settings and stuff.
+ */
+void gnt_init_keys(void);
+void gnt_keys_refine(char *text);
+const char *gnt_key_translate(const char *name);
+
+void gnt_keys_add_combination(const char *path);
+void gnt_keys_del_combination(const char *path);
+int gnt_keys_find_combination(const char *path);
+
+
+/* A lot of commonly used variable names are defined in <term.h>. 
+ * #undef them to make life easier for everyone. */
+
+#undef columns
+#undef lines
+#undef buttons
+#undef newline
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntlabel.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,124 @@
+#include "gntlabel.h"
+#include "gntutils.h"
+
+#include <string.h>
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntWidgetClass *parent_class = NULL;
+
+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);
+	chtype flag = gnt_text_format_flag_to_chtype(label->flags);
+
+	wbkgdset(widget->window, '\0' | flag);
+	mvwaddstr(widget->window, 0, 0, label->text);
+
+	GNTDEBUG;
+}
+
+static void
+gnt_label_size_request(GntWidget *widget)
+{
+	GntLabel *label = GNT_LABEL(widget);
+
+	gnt_util_get_text_bound(label->text,
+			&widget->priv.width, &widget->priv.height);
+}
+
+static void
+gnt_label_class_init(GntLabelClass *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;
+
+	GNTDEBUG;
+}
+
+static void
+gnt_label_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X);
+	widget->priv.minw = 3;
+	widget->priv.minh = 1;
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * 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	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntLabel",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_label_new(const char *text)
+{
+	return gnt_label_new_with_format(text, 0);
+}
+
+GntWidget *gnt_label_new_with_format(const char *text, GntTextFormatFlags flags)
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_LABEL, NULL);
+	GntLabel *label = GNT_LABEL(widget);
+
+	label->text = gnt_util_onscreen_fit_string(text, -1);
+	label->flags = flags;
+	gnt_widget_set_take_focus(widget, FALSE);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+
+	return widget;
+}
+
+void gnt_label_set_text(GntLabel *label, const char *text)
+{
+	g_free(label->text);
+	label->text = gnt_util_onscreen_fit_string(text, -1);
+
+	if (GNT_WIDGET(label)->window)
+	{
+		gnt_widget_hide(GNT_WIDGET(label));
+		gnt_label_size_request(GNT_WIDGET(label));
+		gnt_widget_draw(GNT_WIDGET(label));
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntlabel.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,54 @@
+#ifndef GNT_LABEL_H
+#define GNT_LABEL_H
+
+#include "gnt.h"
+#include "gntwidget.h"
+#include "gnttextview.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;
+	GntTextFormatFlags flags;
+
+    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);
+
+GntWidget *gnt_label_new_with_format(const char *text, GntTextFormatFlags flags);
+
+void gnt_label_set_text(GntLabel *label, const char *text);
+
+G_END_DECLS
+
+#endif /* GNT_LABEL_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntline.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,115 @@
+#include "gntline.h"
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntWidgetClass *parent_class = NULL;
+
+static void
+gnt_line_draw(GntWidget *widget)
+{
+	GntLine *line = GNT_LINE(widget);
+	if (line->vertical)
+		mvwvline(widget->window, 1, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL),
+				widget->priv.height - 2);
+	else
+		mvwhline(widget->window, 0, 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL),
+				widget->priv.width - 2);
+}
+
+static void
+gnt_line_size_request(GntWidget *widget)
+{
+	if (GNT_LINE(widget)->vertical)
+	{
+		widget->priv.width = 1;
+		widget->priv.height = 5;
+	}
+	else
+	{
+		widget->priv.width = 5;
+		widget->priv.height = 1;
+	}
+}
+
+static void
+gnt_line_map(GntWidget *widget)
+{
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+		gnt_widget_size_request(widget);
+	GNTDEBUG;
+}
+
+static void
+gnt_line_class_init(GntLineClass *klass)
+{
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->draw = gnt_line_draw;
+	parent_class->map = gnt_line_map;
+	parent_class->size_request = gnt_line_size_request;
+
+	GNTDEBUG;
+}
+
+static void
+gnt_line_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER);
+	widget->priv.minw = 1;
+	widget->priv.minh = 1;
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntLine API
+ *****************************************************************************/
+GType
+gnt_line_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntLineClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_line_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntLine),
+			0,						/* n_preallocs		*/
+			gnt_line_init,			/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntLine",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_line_new(gboolean vertical)
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_LINE, NULL);
+	GntLine *line = GNT_LINE(widget);
+
+	line->vertical = vertical;
+
+	if (vertical)
+	{
+		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_Y);
+	}
+	else
+	{
+		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X);
+	}
+
+	return widget;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntline.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,52 @@
+#ifndef GNT_LINE_H
+#define GNT_LINE_H
+
+#include "gntwidget.h"
+#include "gnt.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+
+#define GNT_TYPE_LINE				(gnt_line_get_gtype())
+#define GNT_LINE(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_LINE, GntLine))
+#define GNT_LINE_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_LINE, GntLineClass))
+#define GNT_IS_LINE(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_LINE))
+#define GNT_IS_LINE_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_LINE))
+#define GNT_LINE_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_LINE, GntLineClass))
+
+#define GNT_LINE_FLAGS(obj)				(GNT_LINE(obj)->priv.flags)
+#define GNT_LINE_SET_FLAGS(obj, flags)		(GNT_LINE_FLAGS(obj) |= flags)
+#define GNT_LINE_UNSET_FLAGS(obj, flags)	(GNT_LINE_FLAGS(obj) &= ~(flags))
+
+typedef struct _GnLine			GntLine;
+typedef struct _GnLinePriv		GntLinePriv;
+typedef struct _GnLineClass		GntLineClass;
+
+struct _GnLine
+{
+	GntWidget parent;
+
+	gboolean vertical;
+};
+
+struct _GnLineClass
+{
+	GntWidgetClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_line_get_gtype(void);
+
+#define gnt_hline_new() gnt_line_new(FALSE)
+#define gnt_vline_new() gnt_line_new(TRUE)
+
+GntWidget *gnt_line_new(gboolean vertical);
+
+G_END_DECLS
+
+#endif /* GNT_LINE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntmain.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,535 @@
+#define _GNU_SOURCE
+#if defined(__APPLE__)
+#define _XOPEN_SOURCE_EXTENDED
+#endif
+
+#include "config.h"
+
+#include <gmodule.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "gnt.h"
+#include "gntbox.h"
+#include "gntcolors.h"
+#include "gntclipboard.h"
+#include "gntkeys.h"
+#include "gntmenu.h"
+#include "gntstyle.h"
+#include "gnttree.h"
+#include "gntutils.h"
+#include "gntwm.h"
+
+#include <panel.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+/**
+ * Notes: Interesting functions to look at:
+ * 	scr_dump, scr_init, scr_restore: for workspaces
+ *
+ * 	Need to wattrset for colors to use with PDCurses.
+ */
+
+static GIOChannel *channel = NULL;
+
+static gboolean ascii_only;
+static gboolean mouse_enabled;
+
+static void setup_io(void);
+
+static gboolean refresh_screen();
+
+GntWM *wm;
+static GntClipboard *clipboard;
+
+#define HOLDING_ESCAPE  (escape_stuff.timer != 0)
+
+static struct {
+	int timer;
+} escape_stuff;
+
+static gboolean
+escape_timeout(gpointer data)
+{
+	gnt_wm_process_input(wm, "\033");
+	escape_stuff.timer = 0;
+	return FALSE;
+}
+
+/**
+ * Mouse support:
+ *  - bring a window on top if you click on its taskbar
+ *  - click on the top-bar of the active window and drag+drop to move a window
+ *  - click on a window to bring it to focus
+ *   - allow scrolling in tree/textview on wheel-scroll event
+ *   - click to activate button or select a row in tree
+ *  wishlist:
+ *   - have a little [X] on the windows, and clicking it will close that window.
+ */
+static gboolean
+detect_mouse_action(const char *buffer)
+{
+	int x, y;
+	static enum {
+		MOUSE_NONE,
+		MOUSE_LEFT,
+		MOUSE_RIGHT,
+		MOUSE_MIDDLE
+	} button = MOUSE_NONE;
+	static GntWidget *remember = NULL;
+	static int offset = 0;
+	GntMouseEvent event;
+	GntWidget *widget = NULL;
+	PANEL *p = NULL;
+
+	if (!wm->ordered || buffer[0] != 27)
+		return FALSE;
+	
+	buffer++;
+	if (strlen(buffer) < 5)
+		return FALSE;
+
+	x = buffer[3];
+	y = buffer[4];
+	if (x < 0)	x += 256;
+	if (y < 0)	y += 256;
+	x -= 33;
+	y -= 33;
+
+	while ((p = panel_below(p)) != NULL) {
+		const GntNode *node = panel_userptr(p);
+		GntWidget *wid;
+		if (!node)
+			continue;
+		wid = node->me;
+		if (x >= wid->priv.x && x < wid->priv.x + wid->priv.width) {
+			if (y >= wid->priv.y && y < wid->priv.y + wid->priv.height) {
+				widget = wid;
+				break;
+			}
+		}
+	}
+
+	if (strncmp(buffer, "[M ", 3) == 0) {
+		/* left button down */
+		/* Bring the window you clicked on to front */
+		/* If you click on the topbar, then you can drag to move the window */
+		event = GNT_LEFT_MOUSE_DOWN;
+	} else if (strncmp(buffer, "[M\"", 3) == 0) {
+		/* right button down */
+		event = GNT_RIGHT_MOUSE_DOWN;
+	} else if (strncmp(buffer, "[M!", 3) == 0) {
+		/* middle button down */
+		event = GNT_MIDDLE_MOUSE_DOWN;
+	} else if (strncmp(buffer, "[M`", 3) == 0) {
+		/* wheel up*/
+		event = GNT_MOUSE_SCROLL_UP;
+	} else if (strncmp(buffer, "[Ma", 3) == 0) {
+		/* wheel down */
+		event = GNT_MOUSE_SCROLL_DOWN;
+	} else if (strncmp(buffer, "[M#", 3) == 0) {
+		/* button up */
+		event = GNT_MOUSE_UP;
+	} else
+		return FALSE;
+	
+	if (gnt_wm_process_click(wm, event, x, y, widget))
+		return TRUE;
+	
+	if (event == GNT_LEFT_MOUSE_DOWN && widget && widget != wm->_list.window &&
+			!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) {
+		if (widget != wm->ordered->data) {
+			gnt_wm_raise_window(wm, widget);
+		}
+		if (y == widget->priv.y) {
+			offset = x - widget->priv.x;
+			remember = widget;
+			button = MOUSE_LEFT;
+		}
+	} else if (event == GNT_MOUSE_UP) {
+		if (button == MOUSE_NONE && y == getmaxy(stdscr) - 1) {
+			/* Clicked on the taskbar */
+			int n = g_list_length(wm->list);
+			if (n) {
+				int width = getmaxx(stdscr) / n;
+				gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "switch-window-n", x/width, NULL);
+			}
+		} else if (button == MOUSE_LEFT && remember) {
+			x -= offset;
+			if (x < 0)	x = 0;
+			if (y < 0)	y = 0;
+			gnt_screen_move_widget(remember, x, y);
+		}
+		button = MOUSE_NONE;
+		remember = NULL;
+		offset = 0;
+	}
+
+	gnt_widget_clicked(widget, event, x, y);
+	return TRUE;
+}
+
+static gboolean
+io_invoke_error(GIOChannel *source, GIOCondition cond, gpointer data)
+{
+	int id = GPOINTER_TO_INT(data);
+	g_source_remove(id);
+	g_io_channel_unref(source);
+
+	channel = NULL;
+	setup_io();
+	return TRUE;
+}
+
+static gboolean
+io_invoke(GIOChannel *source, GIOCondition cond, gpointer null)
+{
+	char keys[256];
+	int rd = read(STDIN_FILENO, keys + HOLDING_ESCAPE, sizeof(keys) - 1 - HOLDING_ESCAPE);
+	char *k;
+	if (rd < 0)
+	{
+		int ch = getch(); /* This should return ERR, but let's see what it really returns */
+		endwin();
+		printf("ERROR: %s\n", strerror(errno));
+		printf("File descriptor is: %d\n\nGIOChannel is: %p\ngetch() = %d\n", STDIN_FILENO, source, ch);
+		raise(SIGABRT);
+	}
+	else if (rd == 0)
+	{
+		endwin();
+		printf("EOF\n");
+		raise(SIGABRT);
+	}
+
+	rd += HOLDING_ESCAPE;
+	keys[rd] = 0;
+	if (mouse_enabled && detect_mouse_action(keys))
+		return TRUE;
+
+	if (HOLDING_ESCAPE)
+		keys[0] = '\033';
+	k = keys;
+	while (rd) {
+		char back;
+		int p;
+
+		if (k[0] == '\033' && rd == 1) {
+			if (escape_stuff.timer) {
+				gnt_wm_process_input(wm, "\033\033");
+				g_source_remove(escape_stuff.timer);
+				escape_stuff.timer = 0;
+				break;
+			}
+			escape_stuff.timer = g_timeout_add(250, escape_timeout, NULL);
+			break;
+		}
+
+		gnt_keys_refine(k);
+		p = MAX(1, gnt_keys_find_combination(k));
+		back = k[p];
+		k[p] = '\0';
+		gnt_wm_process_input(wm, k);     /* XXX: */
+		k[p] = back;
+		rd -= p;
+		k += p;
+	}
+
+	return TRUE;
+}
+
+static void
+setup_io()
+{
+	int result;
+	channel = g_io_channel_unix_new(STDIN_FILENO);
+	g_io_channel_set_close_on_unref(channel, TRUE);
+
+#if 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 );
+#endif
+
+	result = g_io_add_watch_full(channel,  G_PRIORITY_HIGH,
+					(G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
+					io_invoke, NULL, NULL);
+	
+	g_io_add_watch_full(channel,  G_PRIORITY_HIGH,
+					(G_IO_NVAL),
+					io_invoke_error, GINT_TO_POINTER(result), NULL);
+	
+	g_io_channel_unref(channel);  /* Apparently this caused crashes for some people.
+	                                 But irssi does this, so I am going to assume the
+	                                 crashes were caused by some other stuff. */
+
+	g_printerr("gntmain: setting up IO\n");
+}
+
+static gboolean
+refresh_screen()
+{
+	gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "refresh-screen", NULL);
+	return FALSE;
+}
+
+/* Xerox */
+static void
+clean_pid(void)
+{
+	int status;
+	pid_t pid;
+
+	do {
+		pid = waitpid(-1, &status, WNOHANG);
+	} while (pid != 0 && pid != (pid_t)-1);
+
+	if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
+		char errmsg[BUFSIZ];
+		g_snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
+		perror(errmsg);
+	}
+}
+
+static void
+sighandler(int sig)
+{
+	switch (sig) {
+#ifdef SIGWINCH
+	case SIGWINCH:
+		werase(stdscr);
+		wrefresh(stdscr);
+		g_idle_add(refresh_screen, NULL);
+		signal(SIGWINCH, sighandler);
+		break;
+#endif
+	case SIGCHLD:
+		clean_pid();
+		signal(SIGCHLD, sighandler);
+		break;
+	}
+}
+
+static void
+init_wm()
+{
+	const char *name = gnt_style_get(GNT_STYLE_WM);
+	gpointer handle;
+	
+	if (name && *name) {
+		handle = g_module_open(name, G_MODULE_BIND_LAZY);
+		if (handle) {
+			gboolean (*init)(GntWM **);
+			if (g_module_symbol(handle, "gntwm_init", (gpointer)&init)) {
+				init(&wm);
+			}
+		}
+	}
+	if (wm == NULL)
+		wm = g_object_new(GNT_TYPE_WM, NULL);
+}
+
+void gnt_init()
+{
+	char *filename;
+	const char *locale;
+
+	if (channel)
+		return;
+	
+	locale = setlocale(LC_ALL, "");
+
+	setup_io();
+
+	if (locale && (strstr(locale, "UTF") || strstr(locale, "utf")))
+		ascii_only = FALSE;
+	else
+		ascii_only = TRUE;
+
+	initscr();
+	typeahead(-1);
+	noecho();
+	curs_set(0);
+
+	gnt_init_keys();
+	gnt_init_styles();
+
+	filename = g_build_filename(g_get_home_dir(), ".gntrc", NULL);
+	gnt_style_read_configure_file(filename);
+	g_free(filename);
+
+	gnt_init_colors();
+
+	wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+	refresh();
+
+#ifdef ALL_MOUSE_EVENTS
+	if ((mouse_enabled = gnt_style_get_bool(GNT_STYLE_MOUSE, FALSE)))
+		mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
+#endif
+
+	wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+	werase(stdscr);
+	wrefresh(stdscr);
+
+#ifdef SIGWINCH
+	signal(SIGWINCH, sighandler);
+#endif
+	signal(SIGCHLD, sighandler);
+	signal(SIGPIPE, SIG_IGN);
+
+	g_type_init();
+
+	init_wm();
+
+	clipboard = g_object_new(GNT_TYPE_CLIPBOARD, NULL);
+}
+
+void gnt_main()
+{
+	wm->loop = g_main_loop_new(NULL, FALSE);
+	g_main_loop_run(wm->loop);
+}
+
+/*********************************
+ * Stuff for 'window management' *
+ *********************************/
+
+void gnt_screen_occupy(GntWidget *widget)
+{
+	gnt_wm_new_window(wm, widget);
+}
+
+void gnt_screen_release(GntWidget *widget)
+{
+	gnt_wm_window_close(wm, widget);
+}
+
+void gnt_screen_update(GntWidget *widget)
+{
+	gnt_wm_update_window(wm, widget);
+}
+
+gboolean gnt_widget_has_focus(GntWidget *widget)
+{
+	GntWidget *w;
+	if (!widget)
+		return FALSE;
+	
+	if (GNT_IS_MENU(widget))
+		return TRUE;
+
+	w = widget;
+
+	while (widget->parent)
+		widget = widget->parent;
+
+	if (widget == wm->_list.window)
+		return TRUE;
+	if (wm->ordered && wm->ordered->data == widget) {
+		if (GNT_IS_BOX(widget) &&
+				(GNT_BOX(widget)->active == w || widget == w))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+void gnt_widget_set_urgent(GntWidget *widget)
+{
+	while (widget->parent)
+		widget = widget->parent;
+
+	if (wm->ordered && wm->ordered->data == widget)
+		return;
+
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_URGENT);
+
+	gnt_wm_update_window(wm, widget);
+}
+
+void gnt_quit()
+{
+	g_hash_table_destroy(wm->nodes); /* XXX: */
+	update_panels();
+	doupdate();
+	gnt_uninit_colors();
+	gnt_uninit_styles();
+	endwin();
+}
+
+gboolean gnt_ascii_only()
+{
+	return ascii_only;
+}
+
+void gnt_screen_resize_widget(GntWidget *widget, int width, int height)
+{
+	gnt_wm_resize_window(wm, widget, width, height);
+}
+
+void gnt_screen_move_widget(GntWidget *widget, int x, int y)
+{
+	gnt_wm_move_window(wm, widget, x, y);
+}
+
+void gnt_screen_rename_widget(GntWidget *widget, const char *text)
+{
+	gnt_box_set_title(GNT_BOX(widget), text);
+	gnt_widget_draw(widget);
+	gnt_wm_update_window(wm, widget);
+}
+
+void gnt_register_action(const char *label, void (*callback)())
+{
+	GntAction *action = g_new0(GntAction, 1);
+	action->label = g_strdup(label);
+	action->callback = callback;
+
+	wm->acts = g_list_append(wm->acts, action);
+}
+
+static void
+reset_menu(GntWidget *widget, gpointer null)
+{
+	wm->menu = NULL;
+}
+
+gboolean gnt_screen_menu_show(gpointer newmenu)
+{
+	if (wm->menu) {
+		/* For now, if a menu is being displayed, then another menu
+		 * can NOT take over. */
+		return FALSE;
+	}
+
+	wm->menu = newmenu;
+	GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(wm->menu), GNT_WIDGET_INVISIBLE);
+	gnt_widget_draw(GNT_WIDGET(wm->menu));
+
+	g_signal_connect(G_OBJECT(wm->menu), "hide", G_CALLBACK(reset_menu), NULL);
+
+	return TRUE;
+}
+
+void gnt_set_clipboard_string(gchar *string)
+{
+	gnt_clipboard_set_string(clipboard, string);
+}
+
+GntClipboard *gnt_get_clipboard()
+{
+	return clipboard;
+}
+gchar *gnt_get_clipboard_string()
+{
+	return gnt_clipboard_get_string(clipboard);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntmenu.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,317 @@
+#include "gntmenu.h"
+#include "gntmenuitemcheck.h"
+
+#include <string.h>
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntTreeClass *parent_class = NULL;
+
+static void (*org_draw)(GntWidget *wid);
+static void (*org_destroy)(GntWidget *wid);
+static void (*org_map)(GntWidget *wid);
+static gboolean (*org_key_pressed)(GntWidget *w, const char *t);
+
+static void
+gnt_menu_draw(GntWidget *widget)
+{
+	GntMenu *menu = GNT_MENU(widget);
+	GList *iter;
+	chtype type;
+	int i;
+
+	if (menu->type == GNT_MENU_TOPLEVEL) {
+		wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT));
+		werase(widget->window);
+
+		for (i = 0, iter = menu->list; iter; iter = iter->next, i++) {
+			GntMenuItem *item = GNT_MENUITEM(iter->data);
+			type = ' ' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT);
+			if (i == menu->selected)
+				type |= A_REVERSE;
+			item->priv.x = getcurx(widget->window) + widget->priv.x;
+			item->priv.y = getcury(widget->window) + widget->priv.y + 1;
+			wbkgdset(widget->window, type);
+			wprintw(widget->window, " %s   ", item->text);
+		}
+	} else {
+		org_draw(widget);
+	}
+
+	GNTDEBUG;
+}
+
+static void
+gnt_menu_size_request(GntWidget *widget)
+{
+	GntMenu *menu = GNT_MENU(widget);
+
+	if (menu->type == GNT_MENU_TOPLEVEL) {
+		widget->priv.height = 1;
+		widget->priv.width = getmaxx(stdscr);
+	} else {
+		widget->priv.height = g_list_length(menu->list) + 2;
+		widget->priv.width = 25;  /* XXX: */
+	}
+}
+
+static void
+menu_tree_add(GntMenu *menu, GntMenuItem *item, GntMenuItem *parent)
+{
+	if (GNT_IS_MENUITEM_CHECK(item)) {
+		gnt_tree_add_choice(GNT_TREE(menu), item,
+			gnt_tree_create_row(GNT_TREE(menu), item->text, " "), parent, NULL);
+		gnt_tree_set_choice(GNT_TREE(menu), item, gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item)));
+	} else
+		gnt_tree_add_row_last(GNT_TREE(menu), item,
+			gnt_tree_create_row(GNT_TREE(menu), item->text, item->submenu ? ">" : " "), parent);
+
+	if (0 && item->submenu) {
+		GntMenu *sub = GNT_MENU(item->submenu);
+		GList *iter;
+		for (iter = sub->list; iter; iter = iter->next) {
+			GntMenuItem *it = GNT_MENUITEM(iter->data);
+			menu_tree_add(menu, it, item);
+		}
+	}
+}
+
+static void
+gnt_menu_map(GntWidget *widget)
+{
+	GntMenu *menu = GNT_MENU(widget);
+
+	if (menu->type == GNT_MENU_TOPLEVEL) {
+		gnt_widget_size_request(widget);
+	} else {
+		/* Populate the tree */
+		GList *iter;
+		gnt_tree_remove_all(GNT_TREE(widget));
+		for (iter = menu->list; iter; iter = iter->next) {
+			GntMenuItem *item = GNT_MENUITEM(iter->data);
+			menu_tree_add(menu, item, NULL);
+		}
+		org_map(widget);
+		gnt_tree_adjust_columns(GNT_TREE(widget));
+	}
+	GNTDEBUG;
+}
+
+static void
+menuitem_activate(GntMenu *menu, GntMenuItem *item)
+{
+	if (item) {
+		if (item->submenu) {
+			GntMenu *sub = GNT_MENU(item->submenu);
+			menu->submenu = sub;
+			sub->type = GNT_MENU_POPUP;	/* Submenus are *never* toplevel */
+			sub->parentmenu = menu;
+			if (menu->type != GNT_MENU_TOPLEVEL) {
+				GntWidget *widget = GNT_WIDGET(menu);
+				item->priv.x = widget->priv.x + widget->priv.width - 1;
+				item->priv.y = widget->priv.y + gnt_tree_get_selection_visible_line(GNT_TREE(menu));
+			}
+			gnt_widget_set_position(GNT_WIDGET(sub), item->priv.x, item->priv.y);
+			GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(sub), GNT_WIDGET_INVISIBLE);
+			gnt_widget_draw(GNT_WIDGET(sub));
+		} else if (item->callback) {
+			item->callback(item, item->callbackdata);
+			while (menu) {
+				gnt_widget_hide(GNT_WIDGET(menu));
+				menu = menu->parentmenu;
+			}
+		}
+	}
+}
+
+static gboolean
+gnt_menu_key_pressed(GntWidget *widget, const char *text)
+{
+	GntMenu *menu = GNT_MENU(widget);
+	int current = menu->selected;
+
+	if (menu->submenu) {
+		do menu = menu->submenu; while (menu->submenu);
+		return (gnt_widget_key_pressed(GNT_WIDGET(menu), text));
+	}
+
+	if (text[0] == 27 && text[1] == 0) {
+		/* Escape closes menu */
+		GntMenu *par = menu->parentmenu;
+		if (par != NULL) {
+			par->submenu = NULL;
+			gnt_widget_hide(widget);
+		} else
+			gnt_widget_hide(widget);
+		return TRUE;
+	}
+
+	if (menu->type == GNT_MENU_TOPLEVEL) {
+		if (strcmp(text, GNT_KEY_LEFT) == 0) {
+			menu->selected--;
+			if (menu->selected < 0)
+				menu->selected = g_list_length(menu->list) - 1;
+		} else if (strcmp(text, GNT_KEY_RIGHT) == 0) {
+			menu->selected++;
+			if (menu->selected >= g_list_length(menu->list))
+				menu->selected = 0;
+		} else if (strcmp(text, GNT_KEY_ENTER) == 0) {
+			gnt_widget_activate(widget);
+		}
+
+		if (current != menu->selected) {
+			gnt_widget_draw(widget);
+			return TRUE;
+		}
+	} else {
+		return org_key_pressed(widget, text);
+	}
+
+	return FALSE;
+}
+
+static void
+gnt_menu_destroy(GntWidget *widget)
+{
+	GntMenu *menu = GNT_MENU(widget);
+	g_list_foreach(menu->list, (GFunc)g_object_unref, NULL);
+	g_list_free(menu->list);
+	org_destroy(widget);
+}
+
+static void
+gnt_menu_toggled(GntTree *tree, gpointer key)
+{
+	GntMenuItem *item = GNT_MENUITEM(key);
+	GntMenu *menu = GNT_MENU(tree);
+	gboolean check = gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item));
+	gnt_menuitem_check_set_checked(GNT_MENUITEM_CHECK(item), !check);
+	if (item->callback)
+		item->callback(item, item->callbackdata);
+	while (menu) {
+		gnt_widget_hide(GNT_WIDGET(menu));
+		menu = menu->parentmenu;
+	}
+}
+
+static void
+gnt_menu_activate(GntWidget *widget)
+{
+	GntMenu *menu = GNT_MENU(widget);
+	GntMenuItem *item;
+
+	if (menu->type == GNT_MENU_TOPLEVEL) {
+		item = g_list_nth_data(menu->list, menu->selected);
+	} else {
+		item = gnt_tree_get_selection_data(GNT_TREE(menu));
+	}
+
+	if (item) {
+		if (GNT_IS_MENUITEM_CHECK(item))
+			gnt_menu_toggled(GNT_TREE(widget), item);
+		else
+			menuitem_activate(menu, item);
+	}
+}
+
+static void
+gnt_menu_hide(GntWidget *widget)
+{
+	GntMenu *menu = GNT_MENU(widget);
+	if (menu->parentmenu)
+		menu->parentmenu->submenu = NULL;
+}
+
+static void
+gnt_menu_class_init(GntMenuClass *klass)
+{
+	GntWidgetClass *wid_class = GNT_WIDGET_CLASS(klass);
+	parent_class = GNT_TREE_CLASS(klass);
+
+	org_destroy = wid_class->destroy;
+	org_map = wid_class->map;
+	org_draw = wid_class->draw;
+	org_key_pressed = wid_class->key_pressed;
+
+	wid_class->destroy = gnt_menu_destroy;
+	wid_class->draw = gnt_menu_draw;
+	wid_class->map = gnt_menu_map;
+	wid_class->size_request = gnt_menu_size_request;
+	wid_class->key_pressed = gnt_menu_key_pressed;
+	wid_class->activate = gnt_menu_activate;
+	wid_class->hide = gnt_menu_hide;
+
+	parent_class->toggled = gnt_menu_toggled;
+
+	GNTDEBUG;
+}
+
+static void
+gnt_menu_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER |
+			GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_TRANSIENT);
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntMenu API
+ *****************************************************************************/
+GType
+gnt_menu_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntMenuClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_menu_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntMenu),
+			0,						/* n_preallocs		*/
+			gnt_menu_init,			/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_TREE,
+									  "GntMenu",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_menu_new(GntMenuType type)
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_MENU, NULL);
+	GntMenu *menu = GNT_MENU(widget);
+	menu->list = NULL;
+	menu->selected = 0;
+	menu->type = type;
+
+	if (type == GNT_MENU_TOPLEVEL) {
+		widget->priv.x = 0;
+		widget->priv.y = 0;
+	} else {
+		GNT_TREE(widget)->show_separator = FALSE;
+		_gnt_tree_init_internals(GNT_TREE(widget), 2);
+		gnt_tree_set_col_width(GNT_TREE(widget), 1, 1);  /* The second column is to indicate that it has a submenu */
+		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
+	}
+
+	return widget;
+}
+
+void gnt_menu_add_item(GntMenu *menu, GntMenuItem *item)
+{
+	menu->list = g_list_append(menu->list, item);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntmenu.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,70 @@
+#ifndef GNT_MENU_H
+#define GNT_MENU_H
+
+#include "gnttree.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+
+#define GNT_TYPE_MENU				(gnt_menu_get_gtype())
+#define GNT_MENU(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_MENU, GntMenu))
+#define GNT_MENU_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_MENU, GntMenuClass))
+#define GNT_IS_MENU(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_MENU))
+#define GNT_IS_MENU_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_MENU))
+#define GNT_MENU_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_MENU, GntMenuClass))
+
+#define GNT_MENU_FLAGS(obj)				(GNT_MENU(obj)->priv.flags)
+#define GNT_MENU_SET_FLAGS(obj, flags)		(GNT_MENU_FLAGS(obj) |= flags)
+#define GNT_MENU_UNSET_FLAGS(obj, flags)	(GNT_MENU_FLAGS(obj) &= ~(flags))
+
+typedef struct _GnMenu			GntMenu;
+typedef struct _GnMenuPriv		GntMenuPriv;
+typedef struct _GnMenuClass		GntMenuClass;
+
+#include "gntmenuitem.h"
+
+/**
+ * A toplevel-menu is displayed at the top of the screen, and it spans accross
+ * the entire width of the screen.
+ * A popup-menu could be displayed, for example, as a context menu for widgets.
+ */
+typedef enum
+{
+	GNT_MENU_TOPLEVEL = 1,  /* Menu for a toplevel window */
+	GNT_MENU_POPUP,         /* A popup menu */
+} GntMenuType;
+
+struct _GnMenu
+{
+	GntTree parent;
+	GntMenuType type;
+	
+	GList *list;
+	int selected;
+
+	/* This will keep track of its immediate submenu which is visible so that
+	 * keystrokes can be passed to it. */
+	GntMenu *submenu;
+	GntMenu *parentmenu;
+};
+
+struct _GnMenuClass
+{
+	GntTreeClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_menu_get_gtype(void);
+
+GntWidget *gnt_menu_new(GntMenuType type);
+
+void gnt_menu_add_item(GntMenu *menu, GntMenuItem *item);
+
+G_END_DECLS
+
+#endif /* GNT_MENU_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntmenuitem.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,84 @@
+#include "gntmenu.h"
+#include "gntmenuitem.h"
+
+static GObjectClass *parent_class = NULL;
+
+static void
+gnt_menuitem_destroy(GObject *obj)
+{
+	GntMenuItem *item = GNT_MENUITEM(obj);
+	g_free(item->text);
+	item->text = NULL;
+	if (item->submenu)
+		gnt_widget_destroy(GNT_WIDGET(item->submenu));
+	parent_class->dispose(obj);
+}
+
+static void
+gnt_menuitem_class_init(GntMenuItemClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	parent_class = g_type_class_peek_parent(klass);
+
+	obj_class->dispose = gnt_menuitem_destroy;
+}
+
+static void
+gnt_menuitem_init(GTypeInstance *instance, gpointer class)
+{
+}
+
+/******************************************************************************
+ * GntMenuItem API
+ *****************************************************************************/
+GType
+gnt_menuitem_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntMenuItemClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_menuitem_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntMenuItem),
+			0,						/* n_preallocs		*/
+			gnt_menuitem_init,			/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(G_TYPE_OBJECT,
+									  "GntMenuItem",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntMenuItem *gnt_menuitem_new(const char *text)
+{
+	GObject *item = g_object_new(GNT_TYPE_MENUITEM, NULL);
+	GntMenuItem *menuitem = GNT_MENUITEM(item);
+
+	menuitem->text = g_strdup(text);
+
+	return menuitem;
+}
+
+void gnt_menuitem_set_callback(GntMenuItem *item, GntMenuItemCallback callback, gpointer data)
+{
+	item->callback = callback;
+	item->callbackdata = data;
+}
+
+void gnt_menuitem_set_submenu(GntMenuItem *item, GntMenu *menu)
+{
+	if (item->submenu)
+		gnt_widget_destroy(GNT_WIDGET(item->submenu));
+	item->submenu = menu;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntmenuitem.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,71 @@
+#ifndef GNT_MENUITEM_H
+#define GNT_MENUITEM_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#define GNT_TYPE_MENUITEM				(gnt_menuitem_get_gtype())
+#define GNT_MENUITEM(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_MENUITEM, GntMenuItem))
+#define GNT_MENUITEM_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_MENUITEM, GntMenuItemClass))
+#define GNT_IS_MENUITEM(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_MENUITEM))
+#define GNT_IS_MENUITEM_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_MENUITEM))
+#define GNT_MENUITEM_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_MENUITEM, GntMenuItemClass))
+
+#define GNT_MENUITEM_FLAGS(obj)				(GNT_MENUITEM(obj)->priv.flags)
+#define GNT_MENUITEM_SET_FLAGS(obj, flags)		(GNT_MENUITEM_FLAGS(obj) |= flags)
+#define GNT_MENUITEM_UNSET_FLAGS(obj, flags)	(GNT_MENUITEM_FLAGS(obj) &= ~(flags))
+
+typedef struct _GnMenuItem			GntMenuItem;
+typedef struct _GnMenuItemPriv		GntMenuItemPriv;
+typedef struct _GnMenuItemClass		GntMenuItemClass;
+
+#include "gntmenu.h"
+
+struct _GnMenuItemPriv
+{
+	/* These will be used to determine the position of the submenu */
+	int x;
+	int y;
+};
+
+typedef void (*GntMenuItemCallback)(GntMenuItem *item, gpointer data);
+
+struct _GnMenuItem
+{
+	GObject parent;
+	GntMenuItemPriv priv;
+
+	char *text;
+
+	/* A GntMenuItem can have a callback associated with it.
+	 * The callback will be activated whenever the suer selects it and presses enter (or clicks).
+	 * However, if the GntMenuItem has some child, then the callback and callbackdata will be ignored. */
+	gpointer callbackdata;
+	GntMenuItemCallback callback;
+
+	GntMenu *submenu;
+};
+
+struct _GnMenuItemClass
+{
+	GObjectClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_menuitem_get_gtype(void);
+
+GntMenuItem *gnt_menuitem_new(const char *text);
+
+void gnt_menuitem_set_callback(GntMenuItem *item, GntMenuItemCallback callback, gpointer data);
+
+void gnt_menuitem_set_submenu(GntMenuItem *item, GntMenu *menu);
+
+G_END_DECLS
+
+#endif /* GNT_MENUITEM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntmenuitemcheck.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,68 @@
+#include "gntmenuitemcheck.h"
+
+static GntMenuItemClass *parent_class = NULL;
+
+static void
+gnt_menuitem_check_class_init(GntMenuItemCheckClass *klass)
+{
+	parent_class = GNT_MENUITEM_CLASS(klass);
+
+	GNTDEBUG;
+}
+
+static void
+gnt_menuitem_check_init(GTypeInstance *instance, gpointer class)
+{
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntMenuItemCheck API
+ *****************************************************************************/
+GType
+gnt_menuitem_check_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntMenuItemCheckClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_menuitem_check_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntMenuItemCheck),
+			0,						/* n_preallocs		*/
+			gnt_menuitem_check_init,			/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_MENUITEM,
+									  "GntMenuItemCheck",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntMenuItem *gnt_menuitem_check_new(const char *text)
+{
+	GntMenuItem *item = g_object_new(GNT_TYPE_MENUITEM_CHECK, NULL);
+	GntMenuItem *menuitem = GNT_MENUITEM(item);
+
+	menuitem->text = g_strdup(text);
+	return item;
+}
+
+gboolean gnt_menuitem_check_get_checked(GntMenuItemCheck *item)
+{
+		return item->checked;
+}
+
+void gnt_menuitem_check_set_checked(GntMenuItemCheck *item, gboolean set)
+{
+		item->checked = set;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntmenuitemcheck.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,52 @@
+#ifndef GNT_MENUITEM_CHECK_H
+#define GNT_MENUITEM_CHECK_H
+
+#include "gnt.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+#include "gntmenuitem.h"
+
+#define GNT_TYPE_MENUITEM_CHECK				(gnt_menuitem_check_get_gtype())
+#define GNT_MENUITEM_CHECK(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_MENUITEM_CHECK, GntMenuItemCheck))
+#define GNT_MENUITEM_CHECK_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_MENUITEM_CHECK, GntMenuItemCheckClass))
+#define GNT_IS_MENUITEM_CHECK(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_MENUITEM_CHECK))
+#define GNT_IS_MENUITEM_CHECK_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_MENUITEM_CHECK))
+#define GNT_MENUITEM_CHECK_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_MENUITEM_CHECK, GntMenuItemCheckClass))
+
+#define GNT_MENUITEM_CHECK_FLAGS(obj)				(GNT_MENUITEM_CHECK(obj)->priv.flags)
+#define GNT_MENUITEM_CHECK_SET_FLAGS(obj, flags)		(GNT_MENUITEM_CHECK_FLAGS(obj) |= flags)
+#define GNT_MENUITEM_CHECK_UNSET_FLAGS(obj, flags)	(GNT_MENUITEM_CHECK_FLAGS(obj) &= ~(flags))
+
+typedef struct _GnMenuItemCheck			GntMenuItemCheck;
+typedef struct _GnMenuItemCheckPriv		GntMenuItemCheckPriv;
+typedef struct _GnMenuItemCheckClass		GntMenuItemCheckClass;
+
+struct _GnMenuItemCheck
+{
+	GntMenuItem parent;
+	gboolean checked;
+};
+
+struct _GnMenuItemCheckClass
+{
+	GntMenuItemClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_menuitem_check_get_gtype(void);
+
+GntMenuItem *gnt_menuitem_check_new(const char *text);
+
+gboolean gnt_menuitem_check_get_checked(GntMenuItemCheck *item);
+
+void gnt_menuitem_check_set_checked(GntMenuItemCheck *item, gboolean set);
+
+G_END_DECLS
+
+#endif /* GNT_MENUITEM_CHECK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntrc.sample	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,21 @@
+[general]
+shadow = 0
+
+[colors]
+black = 0; 0; 0
+red = 1000; 0; 0
+green = 0; 1000; 0
+blue = 250; 250; 700
+white = 1000; 1000; 1000
+gray = 700; 700; 700
+darkgray = 256; 256; 256
+
+[colorpairs]
+normal = black; white
+highlight = white; blue
+highlightd = black; gray
+shadow = black; darkgray
+title = white; blue
+titled = white; gray
+text = white; blue
+disabled = gray; white
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntstyle.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,268 @@
+#include "gntstyle.h"
+#include "gntcolors.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#if GLIB_CHECK_VERSION(2,6,0)
+static GKeyFile *gkfile;
+#endif
+
+static char * str_styles[GNT_STYLES];
+static int int_styles[GNT_STYLES];
+static int bool_styles[GNT_STYLES];
+
+const char *gnt_style_get(GntStyle style)
+{
+	return str_styles[style];
+}
+
+gboolean gnt_style_get_bool(GntStyle style, gboolean def)
+{
+	int i;
+	const char * str;
+
+	if (bool_styles[style] != -1)
+		return bool_styles[style];
+	
+	str = gnt_style_get(style);
+
+	if (str)
+	{
+		if (strcmp(str, "false") == 0)
+			def = FALSE;
+		else if (strcmp(str, "true") == 0)
+			def = TRUE;
+		else if (sscanf(str, "%d", &i) == 1)
+		{
+			if (i)
+				def = TRUE;
+			else
+				def = FALSE;
+		}
+	}
+
+	bool_styles[style] = def;
+	return bool_styles[style];
+}
+
+static void
+refine(char *text)
+{
+	char *s = text, *t = text;
+
+	while (*s)
+	{
+		if (*s == '^' && *(s + 1) == '[')
+		{
+			*t = '\033';  /* escape */
+			s++;
+		}
+		else if (*s == '\\')
+		{
+			if (*(s + 1) == '\0')
+				*t = ' ';
+			else
+			{
+				s++;
+				if (*s == 'r' || *s == 'n')
+					*t = '\r';
+				else if (*s == 't')
+					*t = '\t';
+				else
+					*t = *s;
+			}
+		}
+		else
+			*t = *s;
+		t++;
+		s++;
+	}
+	*t = '\0';
+}
+
+static char *
+parse_key(const char *key)
+{
+	return (char *)gnt_key_translate(key);
+}
+
+void gnt_style_read_actions(GType type, GntBindableClass *klass)
+{
+#if GLIB_CHECK_VERSION(2,6,0)
+	char *name;
+	GError *error = NULL;
+
+	name = g_strdup_printf("%s::binding", g_type_name(type));
+
+	if (g_key_file_has_group(gkfile, name))
+	{
+		gsize len = 0;
+		char **keys;
+		
+		keys = g_key_file_get_keys(gkfile, name, &len, &error);
+		if (error)
+		{
+			g_printerr("GntStyle: %s\n", error->message);
+			g_error_free(error);
+			g_free(name);
+			return;
+		}
+
+		while (len--)
+		{
+			char *key, *action;
+
+			key = g_strdup(keys[len]);
+			action = g_key_file_get_string(gkfile, name, keys[len], &error);
+
+			if (error)
+			{
+				g_printerr("GntStyle: %s\n", error->message);
+				g_error_free(error);
+				error = NULL;
+			}
+			else
+			{
+				const char *keycode = parse_key(key);
+				if (keycode == NULL) {
+					g_printerr("GntStyle: Invalid key-binding %s\n", key);
+				} else {
+					gnt_bindable_register_binding(klass, action, keycode, NULL);
+				}
+			}
+			g_free(key);
+			g_free(action);
+		}
+		g_strfreev(keys);
+	}
+	g_free(name);
+#endif
+}
+
+void gnt_styles_get_keyremaps(GType type, GHashTable *hash)
+{
+#if GLIB_CHECK_VERSION(2,6,0)
+	char *name;
+	GError *error = NULL;
+	
+	name = g_strdup_printf("%s::remap", g_type_name(type));
+
+	if (g_key_file_has_group(gkfile, name))
+	{
+		gsize len = 0;
+		char **keys;
+		
+		keys = g_key_file_get_keys(gkfile, name, &len, &error);
+		if (error)
+		{
+			g_printerr("GntStyle: %s\n", error->message);
+			g_error_free(error);
+			g_free(name);
+			return;
+		}
+
+		while (len--)
+		{
+			char *key, *replace;
+
+			key = g_strdup(keys[len]);
+			replace = g_key_file_get_string(gkfile, name, keys[len], &error);
+
+			if (error)
+			{
+				g_printerr("GntStyle: %s\n", error->message);
+				g_error_free(error);
+				error = NULL;
+				g_free(key);
+			}
+			else
+			{
+				refine(key);
+				refine(replace);
+				g_hash_table_insert(hash, key, replace);
+			}
+		}
+		g_strfreev(keys);
+	}
+
+	g_free(name);
+#endif
+}
+
+#if GLIB_CHECK_VERSION(2,6,0)
+static void
+read_general_style(GKeyFile *kfile)
+{
+	GError *error = NULL;
+	gsize nkeys;
+	char **keys = g_key_file_get_keys(kfile, "general", &nkeys, &error);
+	int i;
+	struct
+	{
+		const char *style;
+		GntStyle en;
+	} styles[] = {{"shadow", GNT_STYLE_SHADOW},
+	              {"customcolor", GNT_STYLE_COLOR},
+	              {"mouse", GNT_STYLE_MOUSE},
+	              {"wm", GNT_STYLE_WM},
+	              {"remember_position", GNT_STYLE_REMPOS},
+	              {NULL, 0}};
+
+	if (error)
+	{
+		g_printerr("GntStyle: %s\n", error->message);
+		g_error_free(error);
+	}
+	else
+	{
+		for (i = 0; styles[i].style; i++)
+		{
+			error = NULL;
+			str_styles[styles[i].en] =
+					g_key_file_get_string(kfile, "general", styles[i].style, &error);
+		}
+	}
+	g_strfreev(keys);
+}
+#endif
+
+void gnt_style_read_configure_file(const char *filename)
+{
+#if GLIB_CHECK_VERSION(2,6,0)
+	GError *error = NULL;
+	gkfile = g_key_file_new();
+
+	if (!g_key_file_load_from_file(gkfile, filename, G_KEY_FILE_NONE, &error))
+	{
+		g_printerr("GntStyle: %s\n", error->message);
+		g_error_free(error);
+		return;
+	}
+	gnt_colors_parse(gkfile);
+	read_general_style(gkfile);
+#endif
+}
+
+void gnt_init_styles()
+{
+	int i;
+	for (i = 0; i < GNT_STYLES; i++)
+	{
+		str_styles[i] = NULL;
+		int_styles[i] = -1;
+		bool_styles[i] = -1;
+	}
+}
+
+void gnt_uninit_styles()
+{
+	int i;
+	for (i = 0; i < GNT_STYLES; i++)
+		g_free(str_styles[i]);
+
+#if GLIB_CHECK_VERSION(2,6,0)
+	g_key_file_free(gkfile);
+#endif
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntstyle.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,27 @@
+#include "gnt.h"
+
+typedef enum
+{
+	GNT_STYLE_SHADOW = 0,
+	GNT_STYLE_COLOR = 1,
+	GNT_STYLE_MOUSE = 2,
+	GNT_STYLE_WM = 3,
+	GNT_STYLE_REMPOS = 4,
+	GNT_STYLES
+} GntStyle;
+
+void gnt_style_read_configure_file(const char *filename);
+
+const char *gnt_style_get(GntStyle style);
+
+gboolean gnt_style_get_bool(GntStyle style, gboolean def);
+
+/* This should be called only once for the each type */
+void gnt_styles_get_keyremaps(GType type, GHashTable *hash);
+
+void gnt_style_read_actions(GType type, GntBindableClass *klass);
+
+void gnt_init_styles(void);
+
+void gnt_uninit_styles(void);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gnttextview.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,727 @@
+#include "gnttextview.h"
+#include "gntutils.h"
+
+#include <string.h>
+
+enum
+{
+	SIGS = 1,
+};
+
+typedef struct
+{
+	GntTextFormatFlags tvflag;
+	chtype flags;
+	int start;
+	int end;     /* This is the next byte of the last character of this segment */
+} GntTextSegment;
+
+typedef struct
+{
+	GList *segments;         /* A list of GntTextSegments */
+	int length;              /* The current length of the line so far (ie. onscreen width) */
+	gboolean soft;           /* TRUE if it's an overflow from prev. line */
+} GntTextLine;
+
+typedef struct
+{
+	char *name;
+	int start;
+	int end;
+} GntTextTag;
+
+static GntWidgetClass *parent_class = NULL;
+
+static gchar *select_start;
+static gchar *select_end;
+static gboolean double_click;
+
+static void
+gnt_text_view_draw(GntWidget *widget)
+{
+	GntTextView *view = GNT_TEXT_VIEW(widget);
+	int i = 0;
+	GList *lines;
+	int rows, scrcol;
+
+	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;
+			char *end = view->string->str + seg->end;
+			char back = *end;
+			chtype fl = seg->flags;
+			*end = '\0';
+			if (select_start < view->string->str + seg->start && select_end > view->string->str + seg->end) {
+				fl |= A_REVERSE;
+				wattrset(widget->window, fl);
+				wprintw(widget->window, "%s", (view->string->str + seg->start));
+			} else if (select_start && select_end &&
+				((select_start >= view->string->str + seg->start && select_start <= view->string->str + seg->end) ||
+				(select_end <= view->string->str + seg->end && select_start <= view->string->str + seg->start))) {
+				char *cur = view->string->str + seg->start;
+				while (*cur != '\0') {
+					gchar *last = g_utf8_next_char(cur);
+					gchar *str;
+					if (cur >= select_start && cur <= select_end)
+						fl |= A_REVERSE;
+					else
+						fl = seg->flags;
+					str = g_strndup(cur, last - cur);
+					wattrset(widget->window, fl);
+					waddstr(widget->window, str);
+					g_free(str);
+					cur = g_utf8_next_char(cur);
+				}
+			} else {
+				wattrset(widget->window, fl);
+				wprintw(widget->window, "%s", (view->string->str + seg->start));
+			}
+			*end = back;
+		}
+		wattroff(widget->window, A_UNDERLINE | A_BLINK | A_REVERSE);
+		whline(widget->window, ' ', widget->priv.width - line->length - 1);
+	}
+
+	scrcol = widget->priv.width - 1;
+	rows = widget->priv.height - 2;
+	if (rows > 0)
+	{
+		int total = g_list_length(g_list_first(view->list));
+		int showing, position, up, down;
+
+		showing = rows * rows / total + 1;
+		showing = MIN(rows, showing);
+
+		total -= rows;
+		up = g_list_length(lines);
+		down = total - up;
+
+		position = (rows - showing) * up / MAX(1, up + down);
+		position = MAX((lines != NULL), position);
+
+		if (showing + position > rows)
+			position = rows - showing;
+		
+		if (showing + position == rows && view->list && view->list->prev)
+			position = MAX(1, rows - 1 - showing);
+		else if (showing + position < rows && view->list && !view->list->prev)
+			position = rows - showing;
+
+		mvwvline(widget->window, position + 1, scrcol,
+				ACS_CKBOARD | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D), showing);
+	}
+
+	mvwaddch(widget->window, 0, scrcol,
+			(lines ? ACS_UARROW : ' ') | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
+	mvwaddch(widget->window, widget->priv.height - 1, scrcol,
+			((view->list && view->list->prev) ? ACS_DARROW : ' ') |
+				COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
+
+	GNTDEBUG;
+}
+
+static void
+gnt_text_view_size_request(GntWidget *widget)
+{
+	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
+	{
+		gnt_widget_set_size(widget, 64, 20);
+	}
+}
+
+static void
+gnt_text_view_map(GntWidget *widget)
+{
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+		gnt_widget_size_request(widget);
+	GNTDEBUG;
+}
+
+static gboolean
+gnt_text_view_key_pressed(GntWidget *widget, const char *text)
+{
+	return FALSE;
+}
+
+static void
+free_text_segment(gpointer data, gpointer null)
+{
+	GntTextSegment *seg = data;
+	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
+free_tag(gpointer data, gpointer null)
+{
+	GntTextTag *tag = data;
+	g_free(tag->name);
+	g_free(tag);
+}
+
+static void
+gnt_text_view_destroy(GntWidget *widget)
+{
+	GntTextView *view = GNT_TEXT_VIEW(widget);
+	view->list = g_list_first(view->list);
+	g_list_foreach(view->list, free_text_line, NULL);
+	g_list_free(view->list);
+	g_list_foreach(view->tags, free_tag, NULL);
+	g_list_free(view->tags);
+	g_string_free(view->string, TRUE);
+}
+
+static char *
+gnt_text_view_get_p(GntTextView *view, int x, int y)
+{
+	int i = 0;
+	GntWidget *wid = GNT_WIDGET(view);
+	GntTextLine *line;
+	GList *lines;
+	GList *segs;
+	GntTextSegment *seg;
+	gchar *pos;
+
+	y = wid->priv.height - y;
+	if (g_list_length(view->list) < y) {
+		x = 0;
+		y = g_list_length(view->list) - 1;
+	}
+
+	lines = g_list_nth(view->list, y - 1);
+	if (!lines)
+		return NULL;
+	do {
+		line = lines->data;
+		lines = lines->next;
+	} while (line && !line->segments && lines);
+
+	if (!line || !line->segments) /* no valid line */
+		return NULL;
+	segs = line->segments;
+	seg = (GntTextSegment *)segs->data;
+	pos = view->string->str + seg->start;
+	x = MIN(x, line->length);
+	while (++i <= x) {
+		gunichar *u;
+		pos = g_utf8_next_char(pos);
+		u = g_utf8_to_ucs4(pos, -1, NULL, NULL, NULL);
+		if (u && g_unichar_iswide(*u))
+			i++;
+		g_free(u);
+	}
+	return pos;
+}
+
+static GString *
+select_word_text(GntTextView *view, gchar *c)
+{
+	gchar *start = c;
+	gchar *end = c;
+	gchar *t, *endsize;
+	while ((t = g_utf8_prev_char(start))) {
+		if (!g_ascii_isspace(*t)) {
+			if (start == view->string->str)
+				break;
+			start = t;
+		} else
+			break;
+	}
+	while ((t = g_utf8_next_char(end))) {
+		if (!g_ascii_isspace(*t))
+			end = t;
+		else
+			break;
+	}
+	select_start = start;
+	select_end = end;
+	endsize = g_utf8_next_char(select_end); /* End at the correct byte */
+	return g_string_new_len(start, endsize - start);
+}
+
+static gboolean too_slow(gpointer n)
+{
+	double_click = FALSE;
+	return FALSE;
+}
+
+static gboolean
+gnt_text_view_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
+{
+	if (event == GNT_MOUSE_SCROLL_UP) {
+		gnt_text_view_scroll(GNT_TEXT_VIEW(widget), -1);
+	} else if (event == GNT_MOUSE_SCROLL_DOWN) {
+		gnt_text_view_scroll(GNT_TEXT_VIEW(widget), 1);
+	} else if (event == GNT_LEFT_MOUSE_DOWN) {
+		select_start = gnt_text_view_get_p(GNT_TEXT_VIEW(widget), x - widget->priv.x, y - widget->priv.y);
+		g_timeout_add(500, too_slow, NULL);
+	} else if (event == GNT_MOUSE_UP) {
+		if (select_start) {
+			GString *clip;
+			select_end = gnt_text_view_get_p(GNT_TEXT_VIEW(widget), x - widget->priv.x, y - widget->priv.y);
+			if (select_end < select_start) {
+				gchar *t = select_start;
+				select_start = select_end;
+				select_end = t;
+			}
+			if (select_start == select_end) {
+				if (double_click) {
+					clip = select_word_text(GNT_TEXT_VIEW(widget), select_start);
+					double_click = FALSE;
+				} else {
+					double_click = TRUE;
+					select_start = 0;
+					select_end = 0;
+					gnt_widget_draw(widget);
+					return TRUE;
+				}
+			} else {
+				gchar *endsize = g_utf8_next_char(select_end); /* End at the correct byte */
+				clip = g_string_new_len(select_start, endsize - select_start);
+			}
+			gnt_widget_draw(widget);
+			gnt_set_clipboard_string(clip->str);
+			g_string_free(clip, TRUE);
+		}
+	} else
+		return FALSE;
+	return TRUE;
+}
+
+static void
+gnt_text_view_reflow(GntTextView *view)
+{
+	/* This is pretty ugly, and inefficient. Someone do something about it. */
+	GntTextLine *line;
+	GList *back, *iter, *list;
+	GString *string;
+	int pos = 0;    /* no. of 'real' lines */
+
+	list = view->list;
+	while (list->prev) {
+		line = list->data;
+		if (!line->soft)
+			pos++;
+		list = list->prev;
+	}
+
+	back = g_list_last(view->list);
+	view->list = NULL;
+
+	string = view->string;
+	view->string = NULL;
+	gnt_text_view_clear(view);
+
+	view->string = g_string_set_size(view->string, string->len);
+	view->string->len = 0;
+	GNT_WIDGET_SET_FLAGS(GNT_WIDGET(view), GNT_WIDGET_DRAWING);
+
+	for (; back; back = back->prev) {
+		line = back->data;
+		if (back->next && !line->soft) {
+			gnt_text_view_append_text_with_flags(view, "\n", GNT_TEXT_FLAG_NORMAL);
+		}
+
+		for (iter = line->segments; iter; iter = iter->next) {
+			GntTextSegment *seg = iter->data;
+			char *start = string->str + seg->start;
+			char *end = string->str + seg->end;
+			char back = *end;
+			*end = '\0';
+			gnt_text_view_append_text_with_flags(view, start, seg->tvflag);
+			*end = back;
+		}
+		free_text_line(line, NULL);
+	}
+	g_list_free(list);
+
+	list = view->list = g_list_first(view->list);
+	/* Go back to the line that was in view before resizing started */
+	while (pos--) {
+		while (((GntTextLine*)list->data)->soft)
+			list = list->next;
+		list = list->next;
+	}
+	view->list = list;
+	GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(view), GNT_WIDGET_DRAWING);
+	if (GNT_WIDGET(view)->window)
+		gnt_widget_draw(GNT_WIDGET(view));
+	g_string_free(string, TRUE);
+}
+
+static void
+gnt_text_view_size_changed(GntWidget *widget, int w, int h)
+{
+	if (w != widget->priv.width) {
+		gnt_text_view_reflow(GNT_TEXT_VIEW(widget));
+	}
+}
+
+static void
+gnt_text_view_class_init(GntTextViewClass *klass)
+{
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->destroy = gnt_text_view_destroy;
+	parent_class->draw = gnt_text_view_draw;
+	parent_class->map = gnt_text_view_map;
+	parent_class->size_request = gnt_text_view_size_request;
+	parent_class->key_pressed = gnt_text_view_key_pressed;
+	parent_class->clicked = gnt_text_view_clicked;
+	parent_class->size_changed = gnt_text_view_size_changed;
+
+	GNTDEBUG;
+}
+
+static void
+gnt_text_view_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	
+	GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), GNT_WIDGET_GROW_Y | GNT_WIDGET_GROW_X);
+
+	widget->priv.minw = 5;
+	widget->priv.minh = 2;
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntTextView API
+ *****************************************************************************/
+GType
+gnt_text_view_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntTextViewClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_text_view_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntTextView),
+			0,						/* n_preallocs		*/
+			gnt_text_view_init,			/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntTextView",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_text_view_new()
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_TEXTVIEW, NULL);
+	GntTextView *view = GNT_TEXT_VIEW(widget);
+	GntTextLine *line = g_new0(GntTextLine, 1);
+
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+
+	view->string = g_string_new(NULL);
+	view->list = g_list_append(view->list, line);
+
+	return widget;
+}
+
+void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags)
+{
+	gnt_text_view_append_text_with_tag(view, text, flags, NULL);
+}
+
+void gnt_text_view_append_text_with_tag(GntTextView *view, const char *text,
+			GntTextFormatFlags flags, const char *tagname)
+{
+	GntWidget *widget = GNT_WIDGET(view);
+	int fl = 0;
+	const char *start, *end;
+	GList *list = view->list;
+	GntTextLine *line;
+	int len;
+
+	if (text == NULL || *text == '\0')
+		return;
+
+	fl = gnt_text_format_flag_to_chtype(flags);
+
+	len = view->string->len;
+	view->string = g_string_append(view->string, text);
+
+	if (tagname) {
+		GntTextTag *tag = g_new0(GntTextTag, 1);
+		tag->name = g_strdup(tagname);
+		tag->start = len;
+		tag->end = view->string->len;
+		view->tags = g_list_append(view->tags, tag);
+	}
+
+	view->list = g_list_first(view->list);
+
+	start = end = view->string->str + len;
+
+	while (*start) {
+		GntTextSegment *seg = NULL;
+
+		if (*end == '\n' || *end == '\r') {
+			end++;
+			start = end;
+			gnt_text_view_next_line(view);
+			view->list = g_list_first(view->list);
+			continue;
+		}
+
+		line = view->list->data;
+		if (line->length == widget->priv.width - 1) {
+			/* The last added line was exactly the same width as the widget */
+			line = g_new0(GntTextLine, 1);
+			line->soft = TRUE;
+			view->list = g_list_prepend(view->list, line);
+		}
+
+		if ((end = strchr(start, '\n')) != NULL ||
+			(end = strchr(start, '\r')) != NULL) {
+			len = gnt_util_onscreen_width(start, end - 1);
+			if (len >= widget->priv.width - line->length - 1) {
+				end = NULL;
+			}
+		}
+
+		if (end == NULL)
+			end = gnt_util_onscreen_width_to_pointer(start,
+					widget->priv.width - line->length - 1, &len);
+
+		/* Try to append to the previous segment if possible */
+		if (line->segments) {
+			seg = g_list_last(line->segments)->data;
+			if (seg->flags != fl)
+				seg = NULL;
+		}
+
+		if (seg == NULL) {
+			seg = g_new0(GntTextSegment, 1);
+			seg->start = start - view->string->str;
+			seg->tvflag = flags;
+			seg->flags = fl;
+			line->segments = g_list_append(line->segments, seg);
+		}
+		seg->end = end - view->string->str;
+		line->length += len;
+
+		start = end;
+		if (*end && *end != '\n' && *end != '\r') {
+			line = g_new0(GntTextLine, 1);
+			line->soft = TRUE;
+			view->list = g_list_prepend(view->list, line);
+		}
+	}
+
+	view->list = list;
+
+	gnt_widget_draw(widget);
+}
+
+void gnt_text_view_scroll(GntTextView *view, int scroll)
+{
+	if (scroll == 0)
+	{
+		view->list = g_list_first(view->list);
+	}
+	else if (scroll > 0)
+	{
+		GList *list = g_list_nth_prev(view->list, scroll);
+		if (list == NULL)
+			list = g_list_first(view->list);
+		view->list = list;
+	}
+	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)
+{
+	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));
+}
+
+chtype gnt_text_format_flag_to_chtype(GntTextFormatFlags flags)
+{
+	chtype fl = 0;
+
+	if (flags & GNT_TEXT_FLAG_BOLD)
+		fl |= A_BOLD;
+	if (flags & GNT_TEXT_FLAG_UNDERLINE)
+		fl |= A_UNDERLINE;
+	if (flags & GNT_TEXT_FLAG_BLINK)
+		fl |= A_BLINK;
+
+	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);
+
+	return fl;
+}
+
+void gnt_text_view_clear(GntTextView *view)
+{
+	GntTextLine *line;
+
+	g_list_foreach(view->list, free_text_line, NULL);
+	g_list_free(view->list);
+	view->list = NULL;
+
+	line = g_new0(GntTextLine, 1);
+	view->list = g_list_append(view->list, line);
+	if (view->string)
+		g_string_free(view->string, TRUE);
+	view->string = g_string_new(NULL);
+
+	if (GNT_WIDGET(view)->window)
+		gnt_widget_draw(GNT_WIDGET(view));
+}
+
+int gnt_text_view_get_lines_below(GntTextView *view)
+{
+	int below = 0;
+	GList *list = view->list;
+	while ((list = list->prev))
+		++below;
+	return below;
+}
+
+int gnt_text_view_get_lines_above(GntTextView *view)
+{
+	int above = 0;
+	GList *list = view->list;
+	list = g_list_nth(view->list, GNT_WIDGET(view)->priv.height);
+	if (!list)
+		return 0;
+	while ((list = list->next))
+		++above;
+	return above;
+}
+
+/**
+ * XXX: There are quite possibly more than a few bugs here.
+ */
+int gnt_text_view_tag_change(GntTextView *view, const char *name, const char *text, gboolean all)
+{
+	GList *alllines = g_list_first(view->list);
+	GList *list, *next, *iter, *inext;
+	const int text_length = text ? strlen(text) : 0;
+	int count = 0;
+	for (list = view->tags; list; list = next) {
+		GntTextTag *tag = list->data;
+		next = list->next;
+		if (strcmp(tag->name, name) == 0) {
+			int change;
+			char *before, *after;
+
+			count++;
+
+			before = g_strndup(view->string->str, tag->start);
+			after = g_strdup(view->string->str + tag->end);
+			change = (tag->end - tag->start) - text_length;
+
+			g_string_printf(view->string, "%s%s%s", before, text ? text : "", after);
+			g_free(before);
+			g_free(after);
+
+			/* Update the offsets of the next tags */
+			for (iter = next; iter; iter = iter->next) {
+				GntTextTag *t = iter->data;
+				t->start -= change;
+				t->end -= change;
+			}
+
+			/* Update the offsets of the segments */
+			for (iter = alllines; iter; iter = inext) {
+				GList *segs, *snext;
+				GntTextLine *line = iter->data;
+				inext = iter->next;
+				for (segs = line->segments; segs; segs = snext) {
+					GntTextSegment *seg = segs->data;
+					snext = segs->next;
+					if (seg->start >= tag->end) {
+						/* The segment is somewhere after the tag */
+						seg->start -= change;
+						seg->end -= change;
+					} else if (seg->end <= tag->start) {
+						/* This segment is somewhere in front of the tag */
+					} else if (seg->start >= tag->start) {
+						/* This segment starts in the middle of the tag */
+						if (text == NULL) {
+							free_text_segment(seg, NULL);
+							line->segments = g_list_delete_link(line->segments, segs);
+							if (line->segments == NULL) {
+								free_text_line(line, NULL);
+								if (view->list == iter) {
+									if (inext)
+										view->list = inext;
+									else
+										view->list = iter->prev;
+								}
+								alllines = g_list_delete_link(alllines, iter);
+							}
+						} else {
+							/* XXX: (null) */
+							seg->start = tag->start;
+							seg->end = tag->end - change;
+						}
+						line->length -= change;
+						/* XXX: Make things work if the tagged text spans over several lines. */
+					} else {
+						/* XXX: handle the rest of the conditions */
+						g_printerr("WTF! This needs to be handled properly!!\n");
+					}
+				}
+			}
+			if (text == NULL) {
+				/* Remove the tag */
+				view->tags = g_list_delete_link(view->tags, list);
+				free_tag(tag, NULL);
+			} else {
+				tag->end -= change;
+			}
+			if (!all)
+				break;
+		}
+	}
+	return count;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gnttextview.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,86 @@
+#ifndef GNT_TEXT_VIEW_H
+#define GNT_TEXT_VIEW_H
+
+#include "gntwidget.h"
+#include "gnt.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+
+#define GNT_TYPE_TEXTVIEW				(gnt_text_view_get_gtype())
+#define GNT_TEXT_VIEW(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_TEXTVIEW, GntTextView))
+#define GNT_TEXT_VIEW_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_TEXTVIEW, GntTextViewClass))
+#define GNT_IS_TEXTVIEW(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_TEXTVIEW))
+#define GNT_IS_TEXTVIEW_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_TEXTVIEW))
+#define GNT_TEXT_VIEW_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_TEXTVIEW, GntTextViewClass))
+
+#define GNT_TEXT_VIEW_FLAGS(obj)				(GNT_TEXT_VIEW(obj)->priv.flags)
+#define GNT_TEXT_VIEW_SET_FLAGS(obj, flags)		(GNT_TEXT_VIEW_FLAGS(obj) |= flags)
+#define GNT_TEXT_VIEW_UNSET_FLAGS(obj, flags)	(GNT_TEXT_VIEW_FLAGS(obj) &= ~(flags))
+
+typedef struct _GnTextView			GntTextView;
+typedef struct _GnTextViewPriv		GntTextViewPriv;
+typedef struct _GnTextViewClass		GntTextViewClass;
+
+struct _GnTextView
+{
+	GntWidget parent;
+
+	GString *string;
+	GList *list;        /* List of GntTextLine */
+
+	GList *tags;       /* A list of tags */
+};
+
+typedef enum
+{
+	GNT_TEXT_FLAG_NORMAL      = 0,
+	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,
+} GntTextFormatFlags;
+
+struct _GnTextViewClass
+{
+	GntWidgetClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_text_view_get_gtype(void);
+
+/* XXX: For now, don't set a textview to have any border.
+ *      If you want borders real bad, put it in a box. */
+GntWidget *gnt_text_view_new(void);
+
+/* scroll > 0 means scroll up, < 0 means scroll down, == 0 means scroll to the end */
+void gnt_text_view_scroll(GntTextView *view, int scroll);
+
+void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags);
+
+void gnt_text_view_append_text_with_tag(GntTextView *view, const char *text, GntTextFormatFlags flags, const char *tag);
+
+/* Move the cursor to the beginning of the next line and resets text-attributes.
+ * It first completes the current line with the current text-attributes. */
+void gnt_text_view_next_line(GntTextView *view);
+
+chtype gnt_text_format_flag_to_chtype(GntTextFormatFlags flags);
+
+void gnt_text_view_clear(GntTextView *view);
+
+int gnt_text_view_get_lines_below(GntTextView *view);
+
+int gnt_text_view_get_lines_above(GntTextView *view);
+
+/* If text is NULL, then the tag is removed. */
+int gnt_text_view_tag_change(GntTextView *view, const char *name, const char *text, gboolean all);
+
+G_END_DECLS
+
+#endif /* GNT_TEXT_VIEW_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gnttree.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,1499 @@
+#include "gntmarshal.h"
+#include "gntstyle.h"
+#include "gnttree.h"
+#include "gntutils.h"
+
+#include <string.h>
+#include <ctype.h>
+
+#define SEARCH_TIMEOUT 4000   /* 4 secs */
+
+enum
+{
+	SIG_SELECTION_CHANGED,
+	SIG_SCROLLED,
+	SIG_TOGGLED,
+	SIGS,
+};
+
+#define	TAB_SIZE 3
+
+/* XXX: Make this one into a GObject?
+ * 		 ... Probably not */
+struct _GnTreeRow
+{
+	void *key;
+	void *data;		/* XXX: unused */
+
+	gboolean collapsed;
+	gboolean choice;            /* Is this a choice-box?
+	                               If choice is true, then child will be NULL */
+	gboolean isselected;
+	GntTextFormatFlags flags;
+
+	GntTreeRow *parent;
+	GntTreeRow *child;
+	GntTreeRow *next;
+	GntTreeRow *prev;
+
+	GList *columns;
+	GntTree *tree;
+};
+
+struct _GnTreeCol
+{
+	char *text;
+	int span;       /* How many columns does it span? */
+};
+
+static GntWidgetClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+
+/* Move the item at position old to position new */
+static GList *
+g_list_reposition_child(GList *list, int old, int new)
+{
+	gpointer item = g_list_nth_data(list, old);
+	list = g_list_remove(list, item);
+	if (old < new)
+		new--;   /* because the positions would have shifted after removing the item */
+	list = g_list_insert(list, item, new);
+	return list;
+}
+
+static GntTreeRow *
+_get_next(GntTreeRow *row, gboolean godeep)
+{
+	if (row == NULL)
+		return NULL;
+	if (godeep && row->child)
+		return row->child;
+	if (row->next)
+		return row->next;
+	return _get_next(row->parent, FALSE);
+}
+
+static gboolean
+row_matches_search(GntTreeRow *row)
+{
+	GntTree *t = row->tree;
+	if (t->search && t->search->len > 0) {
+		char *one = g_utf8_casefold(((GntTreeCol*)row->columns->data)->text, -1);
+		char *two = g_utf8_casefold(t->search->str, -1);
+		char *z = strstr(one, two);
+		g_free(one);
+		g_free(two);
+		if (z == NULL)
+			return FALSE;
+	}
+	return TRUE;
+}
+
+static GntTreeRow *
+get_next(GntTreeRow *row)
+{
+	if (row == NULL)
+		return NULL;
+	while ((row = _get_next(row, !row->collapsed)) != NULL) {
+		if (row_matches_search(row))
+			break;
+	}
+	return row;
+}
+
+/* Returns the n-th next row. If it doesn't exist, returns NULL */
+static GntTreeRow *
+get_next_n(GntTreeRow *row, int n)
+{
+	while (row && n--)
+		row = get_next(row);
+	return row;
+}
+
+/* Returns the n-th next row. If it doesn't exist, then the last non-NULL node */
+static GntTreeRow *
+get_next_n_opt(GntTreeRow *row, int n, int *pos)
+{
+	GntTreeRow *next = row;
+	int r = 0;
+
+	if (row == NULL)
+		return NULL;
+
+	while (row && n--)
+	{
+		row = get_next(row);
+		if (row)
+		{
+			next = row;
+			r++;
+		}
+	}
+
+	if (pos)
+		*pos = r;
+
+	return next;
+}
+
+static GntTreeRow *
+get_last_child(GntTreeRow *row)
+{
+	if (row == NULL)
+		return NULL;
+	if (!row->collapsed && row->child)
+		row = row->child;
+	else
+		return row;
+
+	while(row->next)
+		row = row->next;
+	if (!row->collapsed && row->child)
+		row = get_last_child(row->child);
+	return row;
+}
+
+static GntTreeRow *
+get_prev(GntTreeRow *row)
+{
+	if (row == NULL)
+		return NULL;
+	while (row) {
+		if (row->prev)
+			row = get_last_child(row->prev);
+		else
+			row = row->parent;
+		if (!row || row_matches_search(row))
+			break;
+	}
+	return row;
+}
+
+static GntTreeRow *
+get_prev_n(GntTreeRow *row, int n)
+{
+	while (row && n--)
+		row = get_prev(row);
+	return row;
+}
+
+/* Distance of row from the root */
+/* XXX: This is uber-inefficient */
+static int
+get_root_distance(GntTreeRow *row)
+{
+	if (row == NULL)
+		return -1;
+	return get_root_distance(get_prev(row)) + 1;
+}
+
+/* Returns the distance between a and b. 
+ * If a is 'above' b, then the distance is positive */
+static int
+get_distance(GntTreeRow *a, GntTreeRow *b)
+{
+	/* First get the distance from a to the root.
+	 * Then the distance from b to the root.
+	 * Subtract.
+	 * It's not that good, but it works. */
+	int ha = get_root_distance(a);
+	int hb = get_root_distance(b);
+
+	return (hb - ha);
+}
+
+static int
+find_depth(GntTreeRow *row)
+{
+	int dep = -1;
+
+	while (row)
+	{
+		dep++;
+		row = row->parent;
+	}
+
+	return dep;
+}
+
+static char *
+update_row_text(GntTree *tree, GntTreeRow *row)
+{
+	GString *string = g_string_new(NULL);
+	GList *iter;
+	int i;
+
+	for (i = 0, iter = row->columns; i < tree->ncol && iter; i++, iter = iter->next)
+	{
+		GntTreeCol *col = iter->data;
+		const char *text;
+		int len = gnt_util_onscreen_width(col->text, NULL);
+		int fl = 0;
+		gboolean cut = FALSE;
+
+		if (i == 0)
+		{
+			if (row->choice)
+			{
+				g_string_append_printf(string, "[%c] ",
+						row->isselected ? 'X' : ' ');
+				fl = 4;
+			}
+			else if (row->parent == NULL && row->child)
+			{
+				if (row->collapsed)
+				{
+					string = g_string_append(string, "+ ");
+				}
+				else
+				{
+					string = g_string_append(string, "- ");
+				}
+				fl = 2;
+			}
+			else
+			{
+				fl = TAB_SIZE * find_depth(row);
+				g_string_append_printf(string, "%*s", fl, "");
+			}
+			len += fl;
+		}
+		else
+			g_string_append_c(string, '|');
+
+		if (len > tree->columns[i].width) {
+			len = tree->columns[i].width - 1;
+			cut = TRUE;
+		}
+		text = gnt_util_onscreen_width_to_pointer(col->text, len - fl, NULL);
+		string = g_string_append_len(string, col->text, text - col->text);
+		if (cut) { /* ellipsis */
+			if (gnt_ascii_only())
+				g_string_append_c(string, '~');
+			else
+				string = g_string_append(string, "\342\200\246");
+			len++;
+		}
+
+		if (len < tree->columns[i].width && iter->next)
+			g_string_append_printf(string, "%*s", tree->columns[i].width - len, "");
+	}
+	return g_string_free(string, FALSE);
+}
+
+static void
+tree_mark_columns(GntTree *tree, int pos, int y, chtype type)
+{
+	GntWidget *widget = GNT_WIDGET(tree);
+	int i;
+	int x = pos;
+
+	for (i = 0; i < tree->ncol - 1; i++)
+	{
+		x += tree->columns[i].width;
+		mvwaddch(widget->window, y, x + i, type);
+	}
+}
+
+static void
+redraw_tree(GntTree *tree)
+{
+	int start, i;
+	GntWidget *widget = GNT_WIDGET(tree);
+	GntTreeRow *row;
+	int pos, up, down;
+	int rows, scrcol;
+
+	if (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_MAPPED))
+		return;
+
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
+		pos = 0;
+	else
+		pos = 1;
+
+	if (tree->top == NULL)
+		tree->top = tree->root;
+	if (tree->current == NULL)
+		tree->current = tree->root;
+
+	wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL));
+
+	start = 0;
+	if (tree->show_title)
+	{
+		int i;
+		int x = pos;
+
+		mvwhline(widget->window, pos + 1, pos, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL),
+				widget->priv.width - pos - 1);
+		
+		for (i = 0; i < tree->ncol; i++)
+		{
+			mvwaddstr(widget->window, pos, x + i, tree->columns[i].title);
+			x += tree->columns[i].width;
+		}
+		if (pos)
+		{
+			tree_mark_columns(tree, pos, 0, ACS_TTEE | COLOR_PAIR(GNT_COLOR_NORMAL));
+			tree_mark_columns(tree, pos, widget->priv.height - pos,
+					ACS_BTEE | COLOR_PAIR(GNT_COLOR_NORMAL));
+		}
+		tree_mark_columns(tree, pos, pos + 1,
+			(tree->show_separator ? ACS_PLUS : ACS_HLINE) | COLOR_PAIR(GNT_COLOR_NORMAL));
+		tree_mark_columns(tree, pos, pos,
+			(tree->show_separator ? ACS_VLINE : ' ') | COLOR_PAIR(GNT_COLOR_NORMAL));
+		start = 2;
+	}
+
+	rows = widget->priv.height - pos * 2 - start - 1;
+	tree->bottom = get_next_n_opt(tree->top, rows, &down);
+	if (down < rows)
+	{
+		tree->top = get_prev_n(tree->bottom, rows);
+		if (tree->top == NULL)
+			tree->top = tree->root;
+	}
+
+	up = get_distance(tree->top, tree->current);
+	if (up < 0)
+		tree->top = tree->current;
+	else if (up >= widget->priv.height - pos)
+		tree->top = get_prev_n(tree->current, rows);
+
+	if (tree->top && !row_matches_search(tree->top))
+		tree->top = get_next(tree->top);
+	row = tree->top;
+	scrcol = widget->priv.width - 1 - 2 * pos;  /* exclude the borders and the scrollbar */
+	for (i = start + pos; row && i < widget->priv.height - pos;
+				i++, row = get_next(row))
+	{
+		char *str;
+		int wr;
+
+		GntTextFormatFlags flags = row->flags;
+		int attr = 0;
+
+		if (!row_matches_search(row))
+			continue;
+		str = update_row_text(tree, row);
+
+		if ((wr = gnt_util_onscreen_width(str, NULL)) > scrcol)
+		{
+			char *s = (char*)gnt_util_onscreen_width_to_pointer(str, scrcol, &wr);
+			*s = '\0';
+		}
+
+		if (flags & GNT_TEXT_FLAG_BOLD)
+			attr |= A_BOLD;
+		if (flags & GNT_TEXT_FLAG_UNDERLINE)
+			attr |= A_UNDERLINE;
+		if (flags & GNT_TEXT_FLAG_BLINK)
+			attr |= A_BLINK;
+
+		if (row == tree->current)
+		{
+			if (gnt_widget_has_focus(widget))
+				attr |= COLOR_PAIR(GNT_COLOR_HIGHLIGHT);
+			else
+				attr |= COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D);
+		}
+		else
+		{
+			if (flags & GNT_TEXT_FLAG_DIM)
+				attr |= (A_DIM | COLOR_PAIR(GNT_COLOR_DISABLED));
+			else if (flags & GNT_TEXT_FLAG_HIGHLIGHT)
+				attr |= (A_DIM | COLOR_PAIR(GNT_COLOR_HIGHLIGHT));
+			else
+				attr |= COLOR_PAIR(GNT_COLOR_NORMAL);
+		}
+
+		wbkgdset(widget->window, '\0' | attr);
+		mvwaddstr(widget->window, i, pos, str);
+		whline(widget->window, ' ', scrcol - wr);
+		tree->bottom = row;
+		g_free(str);
+		tree_mark_columns(tree, pos, i,
+			(tree->show_separator ? ACS_VLINE : ' ') | attr);
+	}
+
+	wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+	while (i < widget->priv.height - pos)
+	{
+		mvwhline(widget->window, i, pos, ' ',
+				widget->priv.width - pos * 2 - 1);
+		tree_mark_columns(tree, pos, i,
+			(tree->show_separator ? ACS_VLINE : ' '));
+		i++;
+	}
+
+	scrcol = widget->priv.width - pos - 1;  /* position of the scrollbar */
+	rows--;
+	if (rows > 0)
+	{
+		int total;
+		int showing, position;
+
+		get_next_n_opt(tree->root, g_list_length(tree->list), &total);
+		showing = rows * rows / MAX(total, 1) + 1;
+		showing = MIN(rows, showing);
+
+		total -= rows;
+		up = get_distance(tree->root, tree->top);
+		down = total - up;
+
+		position = (rows - showing) * up / MAX(1, up + down);
+		position = MAX((tree->top != tree->root), position);
+
+		if (showing + position > rows)
+			position = rows - showing;
+
+		if (showing + position == rows  && row)
+			position = MAX(0, rows - 1 - showing);
+		else if (showing + position < rows && !row)
+			position = rows - showing;
+
+		position += pos + start + 1;
+
+		mvwvline(widget->window, pos + start + 1, scrcol,
+				' ' | COLOR_PAIR(GNT_COLOR_NORMAL), rows);
+		mvwvline(widget->window, position, scrcol,
+				ACS_CKBOARD | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D), showing);
+	}
+
+	mvwaddch(widget->window, start + pos, scrcol,
+			((tree->top != tree->root) ?  ACS_UARROW : ' ') |
+				COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
+
+	mvwaddch(widget->window, widget->priv.height - pos - 1, scrcol,
+			(row ?  ACS_DARROW : ' ') | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
+
+	gnt_widget_queue_update(widget);
+}
+
+static void
+gnt_tree_draw(GntWidget *widget)
+{
+	GntTree *tree = GNT_TREE(widget);
+
+	redraw_tree(tree);
+	
+	GNTDEBUG;
+}
+
+static void
+gnt_tree_size_request(GntWidget *widget)
+{
+	if (widget->priv.height == 0)
+		widget->priv.height = 10;	/* XXX: Why?! */
+	if (widget->priv.width == 0)
+	{
+		GntTree *tree = GNT_TREE(widget);
+		int i, width = 0;
+		for (i = 0; i < tree->ncol; i++)
+			width += tree->columns[i].width;
+		widget->priv.width = width + i;
+	}
+}
+
+static void
+gnt_tree_map(GntWidget *widget)
+{
+	GntTree *tree = GNT_TREE(widget);
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+	{
+		gnt_widget_size_request(widget);
+	}
+	tree->top = tree->root;
+	tree->current = tree->root;
+	GNTDEBUG;
+}
+
+static void
+tree_selection_changed(GntTree *tree, GntTreeRow *old, GntTreeRow *current)
+{
+	g_signal_emit(tree, signals[SIG_SELECTION_CHANGED], 0, old ? old->key : NULL,
+				current ? current->key : NULL);
+}
+
+static gboolean
+action_down(GntBindable *bind, GList *null)
+{
+	int dist;
+	GntTree *tree = GNT_TREE(bind);
+	GntTreeRow *old = tree->current;
+	GntTreeRow *row = get_next(tree->current);
+	if (row == NULL)
+		return FALSE;
+	tree->current = row;
+	if ((dist = get_distance(tree->current, tree->bottom)) < 0)
+		gnt_tree_scroll(tree, -dist);
+	else
+		redraw_tree(tree);
+	if (old != tree->current)
+		tree_selection_changed(tree, old, tree->current);
+	return TRUE;
+}
+
+static gboolean
+action_up(GntBindable *bind, GList *list)
+{
+	int dist;
+	GntTree *tree = GNT_TREE(bind);
+	GntTreeRow *old = tree->current;
+	GntTreeRow *row = get_prev(tree->current);
+	if (!row)
+		return FALSE;
+	tree->current = row;
+	if ((dist = get_distance(tree->current, tree->top)) > 0)
+		gnt_tree_scroll(tree, -dist);
+	else
+		redraw_tree(tree);
+	if (old != tree->current)
+		tree_selection_changed(tree, old, tree->current);
+
+	return TRUE;
+}
+
+static gboolean
+action_page_down(GntBindable *bind, GList *null)
+{
+	GntTree *tree = GNT_TREE(bind);
+	GntTreeRow *old = tree->current;
+	GntTreeRow *row = get_next(tree->bottom);
+	if (row)
+	{
+		int dist = get_distance(tree->top, tree->current);
+		tree->top = tree->bottom;
+		tree->current = get_next_n_opt(tree->top, dist, NULL);
+		redraw_tree(tree);
+	}
+	else if (tree->current != tree->bottom)
+	{
+		tree->current = tree->bottom;
+		redraw_tree(tree);
+	}
+
+	if (old != tree->current)
+		tree_selection_changed(tree, old, tree->current);
+	return TRUE;
+}
+
+static gboolean
+action_page_up(GntBindable *bind, GList *null)
+{
+	GntWidget *widget = GNT_WIDGET(bind);
+	GntTree *tree = GNT_TREE(bind);
+	GntTreeRow *row;
+	GntTreeRow *old = tree->current;
+
+	if (tree->top != tree->root)
+	{
+		int dist = get_distance(tree->top, tree->current);
+		row = get_prev_n(tree->top, widget->priv.height - 1 -
+			tree->show_title * 2 - 2 * (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER) == 0));
+		if (row == NULL)
+			row = tree->root;
+		tree->top = row;
+		tree->current = get_next_n_opt(tree->top, dist, NULL);
+		redraw_tree(tree);
+	}
+	else if (tree->current != tree->top)
+	{
+		tree->current = tree->top;
+		redraw_tree(tree);
+	}
+	if (old != tree->current)
+		tree_selection_changed(tree, old, tree->current);
+	return TRUE;
+}
+
+static void
+end_search(GntTree *tree)
+{
+	if (tree->search) {
+		g_source_remove(tree->search_timeout);
+		g_string_free(tree->search, TRUE);
+		tree->search = NULL;
+		tree->search_timeout = 0;
+	}
+}
+
+static gboolean
+search_timeout(gpointer data)
+{
+	GntTree *tree = data;
+
+	end_search(tree);
+	redraw_tree(tree);
+
+	return FALSE;
+}
+
+static gboolean
+gnt_tree_key_pressed(GntWidget *widget, const char *text)
+{
+	GntTree *tree = GNT_TREE(widget);
+	GntTreeRow *old = tree->current;
+
+	if (text[0] == '\r') {
+		end_search(tree);
+		gnt_widget_activate(widget);
+	} else if (tree->search) {
+		if (isalnum(*text)) {
+			tree->search = g_string_append_c(tree->search, *text);
+			redraw_tree(tree);
+			g_source_remove(tree->search_timeout);
+			tree->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree);
+		}
+		return TRUE;
+	} else if (text[0] == ' ' && text[1] == 0) {
+		/* Space pressed */
+		GntTreeRow *row = tree->current;
+		if (row && row->child)
+		{
+			row->collapsed = !row->collapsed;
+			redraw_tree(tree);
+		}
+		else if (row && row->choice)
+		{
+			row->isselected = !row->isselected;
+			g_signal_emit(tree, signals[SIG_TOGGLED], 0, row->key);
+			redraw_tree(tree);
+		}
+	}
+
+	if (old != tree->current)
+	{
+		tree_selection_changed(tree, old, tree->current);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void
+gnt_tree_destroy(GntWidget *widget)
+{
+	GntTree *tree = GNT_TREE(widget);
+	int i;
+
+	end_search(tree);
+	if (tree->hash)
+		g_hash_table_destroy(tree->hash);
+	g_list_free(tree->list);
+
+	for (i = 0; i < tree->ncol; i++)
+	{
+		g_free(tree->columns[i].title);
+	}
+	g_free(tree->columns);
+}
+
+static gboolean
+gnt_tree_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
+{
+	GntTree *tree = GNT_TREE(widget);
+	GntTreeRow *old = tree->current;
+	if (event == GNT_MOUSE_SCROLL_UP) {
+		action_up(GNT_BINDABLE(widget), NULL);
+	} else if (event == GNT_MOUSE_SCROLL_DOWN) {
+		action_down(GNT_BINDABLE(widget), NULL);
+	} else if (event == GNT_LEFT_MOUSE_DOWN) {
+		GntTreeRow *row;
+		GntTree *tree = GNT_TREE(widget);
+		int pos = 1;
+		if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
+			pos = 0;
+		if (tree->show_title)
+			pos += 2;
+		pos = y - widget->priv.y - pos;
+		row = get_next_n(tree->top, pos);
+		if (row && tree->current != row) {
+			GntTreeRow *old = tree->current;
+			tree->current = row;
+			redraw_tree(tree);
+			tree_selection_changed(tree, old, tree->current);
+		} else if (row && row == tree->current) {
+			if (row->choice) {
+				row->isselected = !row->isselected;
+				g_signal_emit(tree, signals[SIG_TOGGLED], 0, row->key);
+				redraw_tree(tree);
+			} else {
+				gnt_widget_activate(widget);
+			}
+		}
+	} else {
+		return FALSE;
+	}
+	if (old != tree->current) {
+		tree_selection_changed(tree, old, tree->current);
+	}
+	return TRUE;
+}
+
+static void
+gnt_tree_size_changed(GntWidget *widget, int w, int h)
+{
+	GntTree *tree = GNT_TREE(widget);
+	int i;
+	int n = 0;
+	if (widget->priv.width <= 0)
+		return;
+	for (i = 0; i < tree->ncol; ++i)
+		n += tree->columns[i].width;
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
+		tree->columns[tree->ncol - 1].width += widget->priv.width - n - 1 * tree->ncol;
+	else
+		tree->columns[tree->ncol - 1].width += widget->priv.width - n - 2 - 1 * tree->ncol;
+}
+
+static gboolean
+start_search(GntBindable *bindable, GList *list)
+{
+	GntTree *tree = GNT_TREE(bindable);
+	if (tree->search)
+		return FALSE;
+	tree->search = g_string_new(NULL);
+	tree->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree);
+	return TRUE;
+}
+
+static gboolean
+end_search_action(GntBindable *bindable, GList *list)
+{
+	GntTree *tree = GNT_TREE(bindable);
+	if (tree->search == NULL)
+		return FALSE;
+	end_search(tree);
+	redraw_tree(tree);
+	return TRUE;
+}
+
+static void
+gnt_tree_class_init(GntTreeClass *klass)
+{
+	GntBindableClass *bindable = GNT_BINDABLE_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;
+	parent_class->clicked = gnt_tree_clicked;
+	parent_class->size_changed = gnt_tree_size_changed;
+
+	signals[SIG_SELECTION_CHANGED] = 
+		g_signal_new("selection-changed",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntTreeClass, selection_changed),
+					 NULL, NULL,
+					 gnt_closure_marshal_VOID__POINTER_POINTER,
+					 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
+	signals[SIG_SCROLLED] = 
+		g_signal_new("scrolled",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 0,
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__INT,
+					 G_TYPE_NONE, 1, G_TYPE_INT);
+	signals[SIG_TOGGLED] = 
+		g_signal_new("toggled",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntTreeClass, toggled),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+	gnt_bindable_class_register_action(bindable, "move-up", action_up,
+				GNT_KEY_UP, NULL);
+	gnt_bindable_register_binding(bindable, "move-up", GNT_KEY_CTRL_P, NULL);
+	gnt_bindable_class_register_action(bindable, "move-down", action_down,
+				GNT_KEY_DOWN, NULL);
+	gnt_bindable_register_binding(bindable, "move-down", GNT_KEY_CTRL_N, NULL);
+	gnt_bindable_class_register_action(bindable, "page-up", action_page_up,
+				GNT_KEY_PGUP, NULL);
+	gnt_bindable_class_register_action(bindable, "page-down", action_page_down,
+				GNT_KEY_PGDOWN, NULL);
+	gnt_bindable_class_register_action(bindable, "start-search", start_search,
+				"/", NULL);
+	gnt_bindable_class_register_action(bindable, "end-search", end_search_action,
+				"\033", NULL);
+
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), bindable);
+	GNTDEBUG;
+}
+
+static void
+gnt_tree_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	GntTree *tree = GNT_TREE(widget);
+	tree->show_separator = TRUE;
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y);
+	widget->priv.minw = 4;
+	widget->priv.minh = 1;
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * 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	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+									  "GntTree",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+static void
+free_tree_col(gpointer data)
+{
+	GntTreeCol *col = data;
+
+	g_free(col->text);
+	g_free(col);
+}
+
+static void
+free_tree_row(gpointer data)
+{
+	GntTreeRow *row = data;
+
+	if (!row)
+		return;
+
+	g_list_foreach(row->columns, (GFunc)free_tree_col, NULL);
+	g_list_free(row->columns);
+	g_free(row);
+}
+
+GntWidget *gnt_tree_new()
+{
+	return gnt_tree_new_with_columns(1);
+}
+
+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))
+		ret -= 2;
+	return ret;
+}
+
+const GList *gnt_tree_get_rows(GntTree *tree)
+{
+	return tree->list;
+}
+
+void gnt_tree_scroll(GntTree *tree, int count)
+{
+	GntTreeRow *row;
+
+	if (count < 0)
+	{
+		if (get_root_distance(tree->top) == 0)
+			return;
+		row = get_prev_n(tree->top, -count);
+		if (row == NULL)
+			row = tree->root;
+		tree->top = row;
+	}
+	else
+	{
+		get_next_n_opt(tree->bottom, count, &count);
+		tree->top = get_next_n(tree->top, count);
+	}
+
+	redraw_tree(tree);
+	g_signal_emit(tree, signals[SIG_SCROLLED], 0, count);
+}
+
+static gpointer
+find_position(GntTree *tree, gpointer key, gpointer parent)
+{
+	GntTreeRow *row;
+
+	if (tree->compare == NULL)
+		return NULL;
+
+	if (parent == NULL)
+		row = tree->root;
+	else
+		row = g_hash_table_lookup(tree->hash, parent);
+
+	if (!row)
+		return NULL;
+
+	if (parent)
+		row = row->child;
+
+	while (row)
+	{
+		if (tree->compare(key, row->key) < 0)
+			return (row->prev ? row->prev->key : NULL);
+		if (row->next)
+			row = row->next;
+		else
+			return row->key;
+	}
+	return NULL;
+}
+
+void gnt_tree_sort_row(GntTree *tree, gpointer key)
+{
+	GntTreeRow *row, *q, *s;
+	int current, newp;
+
+	if (!tree->compare)
+		return;
+
+	row = g_hash_table_lookup(tree->hash, key);
+	g_return_if_fail(row != NULL);
+
+	current = g_list_index(tree->list, key);
+
+	if (row->parent)
+		s = row->parent->child;
+	else
+		s = tree->root;
+
+	q = NULL;
+	while (s) {
+		if (tree->compare(row->key, s->key) < 0)
+			break;
+		q = s;
+		s = s->next;
+	}
+
+	/* Move row between q and s */
+	if (row == q || row == s)
+		return;
+
+	if (q == NULL) {
+		/* row becomes the first child of its parent */
+		row->prev->next = row->next;  /* row->prev cannot be NULL at this point */
+		if (row->next)
+			row->next->prev = row->prev;
+		if (row->parent)
+			row->parent->child = row;
+		else
+			tree->root = row;
+		row->next = s;
+		s->prev = row;  /* s cannot be NULL */
+		row->prev = NULL;
+		newp = g_list_index(tree->list, s) - 1;
+	} else {
+		if (row->prev) {
+			row->prev->next = row->next;
+		} else {
+			/* row was the first child of its parent */
+			if (row->parent)
+				row->parent->child = row->next;
+			else
+				tree->top = row->next;
+		}
+
+		if (row->next)
+			row->next->prev = row->prev;
+
+		q->next = row;
+		row->prev = q;
+		if (s)
+			s->prev = row;
+		row->next = s;
+		newp = g_list_index(tree->list, q) + 1;
+	}
+	tree->list = g_list_reposition_child(tree->list, current, newp);
+
+	redraw_tree(tree);
+}
+
+GntTreeRow *gnt_tree_add_row_after(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro)
+{
+	GntTreeRow *pr = NULL;
+
+	g_hash_table_replace(tree->hash, key, row);
+	row->tree = tree;
+
+	if (bigbro == NULL && tree->compare)
+	{
+		bigbro = find_position(tree, key, parent);
+	}
+
+	if (tree->root == NULL)
+	{
+		tree->root = row;
+		tree->list = g_list_prepend(tree->list, key);
+	}
+	else
+	{
+		int position = 0;
+
+		if (bigbro)
+		{
+			pr = g_hash_table_lookup(tree->hash, bigbro);
+			if (pr)
+			{
+				if (pr->next)	pr->next->prev = row;
+				row->next = pr->next;
+				row->prev = pr;
+				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)
+			{
+				if (pr->child)	pr->child->prev = row;
+				row->next = pr->child;
+				pr->child = row;
+				row->parent = pr;
+
+				position = g_list_index(tree->list, parent);
+			}
+		}
+
+		if (pr == NULL)
+		{
+			GntTreeRow *r = tree->root;
+			row->next = r;
+			if (r) r->prev = row;
+			if (tree->current == tree->root)
+				tree->current = row;
+			tree->root = row;
+			tree->list = g_list_prepend(tree->list, key);
+		}
+		else
+		{
+			tree->list = g_list_insert(tree->list, key, position + 1);
+		}
+	}
+
+	row->key = key;
+	row->data = NULL;
+
+	redraw_tree(tree);
+
+	return row;
+}
+
+GntTreeRow *gnt_tree_add_row_last(GntTree *tree, void *key, GntTreeRow *row, void *parent)
+{
+	GntTreeRow *pr = NULL, *br = NULL;
+
+	if (parent)
+		pr = g_hash_table_lookup(tree->hash, parent);
+
+	if (pr)
+		br = pr->child;
+	else
+		br = tree->root;
+
+	if (br)
+	{
+		while (br->next)
+			br = br->next;
+	}
+
+	return gnt_tree_add_row_after(tree, key, row, parent, br ? br->key : NULL);
+}
+
+gpointer gnt_tree_get_selection_data(GntTree *tree)
+{
+	if (tree->current)
+		return tree->current->key;	/* XXX: perhaps we should just get rid of 'data' */
+	return NULL;
+}
+
+char *gnt_tree_get_selection_text(GntTree *tree)
+{
+	if (tree->current)
+		return update_row_text(tree, tree->current);
+	return NULL;
+}
+
+GList *gnt_tree_get_selection_text_list(GntTree *tree)
+{
+	GList *list = NULL, *iter;
+	int i;
+
+	if (!tree->current)
+		return NULL;
+
+	for (i = 0, iter = tree->current->columns; i < tree->ncol && iter;
+			i++, iter = iter->next)
+	{
+		GntTreeCol *col = iter->data;
+		list = g_list_append(list, g_strdup(col->text));
+	}
+
+	return list;
+}
+
+void gnt_tree_remove(GntTree *tree, gpointer key)
+{
+	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
+	static int depth = 0; /* Only redraw after all child nodes are removed */
+	if (row)
+	{
+		gboolean redraw = FALSE;
+
+		if (row->child) {
+			depth++;
+			while (row->child) {
+				gnt_tree_remove(tree, row->child->key);
+			}
+			depth--;
+		}
+
+		if (get_distance(tree->top, row) >= 0 && get_distance(row, tree->bottom) >= 0)
+			redraw = TRUE;
+
+		/* Update root/top/current/bottom if necessary */
+		if (tree->root == row)
+			tree->root = get_next(row);
+		if (tree->top == row)
+		{
+			if (tree->top != tree->root)
+				tree->top = get_prev(row);
+			else
+				tree->top = get_next(row);
+		}
+		if (tree->current == row)
+		{
+			if (tree->current != tree->root)
+				tree->current = get_prev(row);
+			else
+				tree->current = get_next(row);
+			tree_selection_changed(tree, row, tree->current);
+		}
+		if (tree->bottom == row)
+		{
+			tree->bottom = get_prev(row);
+		}
+
+		/* Fix the links */
+		if (row->next)
+			row->next->prev = row->prev;
+		if (row->parent && row->parent->child == row)
+			row->parent->child = row->next;
+		if (row->prev)
+			row->prev->next = row->next;
+
+		g_hash_table_remove(tree->hash, key);
+		tree->list = g_list_remove(tree->list, key);
+
+		if (redraw && depth == 0)
+		{
+			redraw_tree(tree);
+		}
+	}
+}
+
+static gboolean
+return_true(gpointer key, gpointer data, gpointer null)
+{
+	return TRUE;
+}
+
+void gnt_tree_remove_all(GntTree *tree)
+{
+	tree->root = NULL;
+	g_hash_table_foreach_remove(tree->hash, (GHRFunc)return_true, tree);
+	g_list_free(tree->list);
+	tree->list = NULL;
+	tree->current = tree->top = tree->bottom = NULL;
+}
+
+int gnt_tree_get_selection_visible_line(GntTree *tree)
+{
+	return get_distance(tree->top, tree->current) +
+			!!(GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER));
+}
+
+void gnt_tree_change_text(GntTree *tree, gpointer key, int colno, const char *text)
+{
+	GntTreeRow *row;
+	GntTreeCol *col;
+
+	g_return_if_fail(colno < tree->ncol);
+	
+	row = g_hash_table_lookup(tree->hash, key);
+	if (row)
+	{
+		col = g_list_nth_data(row->columns, colno);
+		g_free(col->text);
+		col->text = g_strdup(text);
+
+		if (get_distance(tree->top, row) >= 0 && get_distance(row, tree->bottom) >= 0)
+			redraw_tree(tree);
+	}
+}
+
+GntTreeRow *gnt_tree_add_choice(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro)
+{
+	GntTreeRow *r;
+	r = g_hash_table_lookup(tree->hash, key);
+	g_return_val_if_fail(!r || !r->choice, NULL);
+
+	if (bigbro == NULL) {
+		if (tree->compare)
+			bigbro = find_position(tree, key, parent);
+		else {
+			r = g_hash_table_lookup(tree->hash, parent);
+			if (!r)
+				r = tree->root;
+			else
+				r = r->child;
+			if (r) {
+				while (r->next)
+					r = r->next;
+				bigbro = r->key;
+			} 
+		}
+	}
+	row = gnt_tree_add_row_after(tree, key, row, parent, bigbro);
+	row->choice = TRUE;
+
+	return row;
+}
+
+void gnt_tree_set_choice(GntTree *tree, void *key, gboolean set)
+{
+	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
+
+	if (!row)
+		return;
+	g_return_if_fail(row->choice);
+
+	row->isselected = set;
+	redraw_tree(tree);
+}
+
+gboolean gnt_tree_get_choice(GntTree *tree, void *key)
+{
+	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
+
+	if (!row)
+		return FALSE;
+	g_return_val_if_fail(row->choice, FALSE);
+
+	return row->isselected;
+}
+
+void gnt_tree_set_row_flags(GntTree *tree, void *key, GntTextFormatFlags flags)
+{
+	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
+	if (!row || row->flags == flags)
+		return;
+
+	row->flags = flags;
+	redraw_tree(tree);	/* XXX: It shouldn't be necessary to redraw the whole darned tree */
+}
+
+void gnt_tree_set_selected(GntTree *tree , void *key)
+{
+	int dist;
+	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
+	if (!row)
+		return;
+
+	if (tree->top == NULL)
+		tree->top = row;
+	if (tree->bottom == NULL)
+		tree->bottom = row;
+
+	tree->current = row;
+	if ((dist = get_distance(tree->current, tree->bottom)) < 0)
+		gnt_tree_scroll(tree, -dist);
+	else if ((dist = get_distance(tree->current, tree->top)) > 0)
+		gnt_tree_scroll(tree, -dist);
+	else
+		redraw_tree(tree);
+}
+
+void _gnt_tree_init_internals(GntTree *tree, int col)
+{
+	tree->ncol = col;
+	tree->hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_tree_row);
+	tree->columns = g_new0(struct _GntTreeColInfo, col);
+	while (col--)
+	{
+		tree->columns[col].width = 15;
+	}
+	tree->list = NULL;
+	tree->show_title = FALSE;
+}
+
+GntWidget *gnt_tree_new_with_columns(int col)
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_TREE, NULL);
+	GntTree *tree = GNT_TREE(widget);
+
+	_gnt_tree_init_internals(tree, col);
+	
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW);
+	gnt_widget_set_take_focus(widget, TRUE);
+
+	return widget;
+}
+
+GntTreeRow *gnt_tree_create_row_from_list(GntTree *tree, GList *list)
+{
+	GList *iter;
+	int i;
+	GntTreeRow *row = g_new0(GntTreeRow, 1);
+
+	for (i = 0, iter = list; i < tree->ncol && iter; iter = iter->next, i++)
+	{
+		GntTreeCol *col = g_new0(GntTreeCol, 1);
+		col->span = 1;
+		col->text = g_strdup(iter->data ? iter->data : "");
+
+		row->columns = g_list_append(row->columns, col);
+	}
+
+	return row;
+}
+
+GntTreeRow *gnt_tree_create_row(GntTree *tree, ...)
+{
+	int i;
+	va_list args;
+	GList *list = NULL;
+	GntTreeRow *row;
+
+	va_start(args, tree);
+	for (i = 0; i < tree->ncol; i++)
+	{
+		list = g_list_append(list, va_arg(args, char *));
+	}
+	va_end(args);
+
+	row = gnt_tree_create_row_from_list(tree, list);
+	g_list_free(list);
+
+	return row;
+}
+
+void gnt_tree_set_col_width(GntTree *tree, int col, int width)
+{
+	g_return_if_fail(col < tree->ncol);
+
+	tree->columns[col].width = width;
+}
+
+void gnt_tree_set_column_titles(GntTree *tree, ...)
+{
+	int i;
+	va_list args;
+
+	va_start(args, tree);
+	for (i = 0; i < tree->ncol; i++)
+	{
+		const char *title = va_arg(args, const char *);
+		tree->columns[i].title = g_strdup(title);
+	}
+	va_end(args);
+}
+
+void gnt_tree_set_show_title(GntTree *tree, gboolean set)
+{
+	tree->show_title = set;
+	GNT_WIDGET(tree)->priv.minh = (set ? 6 : 4);
+}
+
+void gnt_tree_set_compare_func(GntTree *tree, GCompareFunc func)
+{
+	tree->compare = func;
+}
+
+void gnt_tree_set_expanded(GntTree *tree, void *key, gboolean expanded)
+{
+	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
+	if (row) {
+		row->collapsed = !expanded;
+		if (GNT_WIDGET(tree)->window)
+			gnt_widget_draw(GNT_WIDGET(tree));
+	}
+}
+
+void gnt_tree_set_show_separator(GntTree *tree, gboolean set)
+{
+	tree->show_separator = set;
+}
+
+void gnt_tree_adjust_columns(GntTree *tree)
+{
+	GntTreeRow *row = tree->root;
+	int *widths, i, twidth, height;
+
+	widths = g_new0(int, tree->ncol);
+	while (row) {
+		GList *iter;
+		for (i = 0, iter = row->columns; iter; iter = iter->next, i++) {
+			GntTreeCol *col = iter->data;
+			int w = gnt_util_onscreen_width(col->text, NULL);
+			if (widths[i] < w)
+				widths[i] = w;
+		}
+		row = row->next;
+	}
+
+	twidth = 1 + 2 * (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER));
+	for (i = 0; i < tree->ncol; i++) {
+		gnt_tree_set_col_width(tree, i, widths[i]);
+		twidth += widths[i] + (tree->show_separator ? 1 : 0) + 1;
+	}
+	g_free(widths);
+
+	gnt_widget_get_size(GNT_WIDGET(tree), NULL, &height);
+	gnt_widget_set_size(GNT_WIDGET(tree), twidth, height);
+}
+
+void gnt_tree_set_hash_fns(GntTree *tree, gpointer hash, gpointer eq, gpointer kd)
+{
+	g_hash_table_foreach_remove(tree->hash, return_true, NULL);
+	g_hash_table_destroy(tree->hash);
+	tree->hash = g_hash_table_new_full(hash, eq, kd, free_tree_row);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gnttree.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,150 @@
+#ifndef GNT_TREE_H
+#define GNT_TREE_H
+
+#include "gntwidget.h"
+#include "gnt.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+#include "gnttextview.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;
+typedef struct _GnTreeCol		GntTreeCol;
+
+struct _GnTree
+{
+	GntWidget parent;
+
+	GntTreeRow *current;    /* current selection */
+
+	GntTreeRow *top;        /* The topmost visible item */
+	GntTreeRow *bottom;     /* The bottommost visible item */
+	
+	GntTreeRow *root;       /* The root of all evil */
+	
+	GList *list;            /* List of GntTreeRow s */
+	GHashTable *hash;       /* We need this for quickly referencing the rows */
+	guint (*hash_func)(gconstpointer);
+	gboolean (*hash_eq_func)(gconstpointer, gconstpointer);
+	GDestroyNotify key_destroy;
+	GDestroyNotify value_destroy;
+
+	int ncol;               /* No. of columns */
+	struct _GntTreeColInfo
+	{
+		int width;
+		char *title;
+	} *columns;             /* Would a GList be better? */
+	gboolean show_title;
+	gboolean show_separator; /* Whether to show column separators */
+
+	GString *search;
+	int search_timeout;
+
+	GCompareFunc compare;
+};
+
+struct _GnTreeClass
+{
+	GntWidgetClass parent;
+
+	void (*selection_changed)(GntTreeRow *old, GntTreeRow * current);
+	void (*toggled)(GntTree *tree, gpointer key);
+
+	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);      /* A tree with just one column */
+
+GntWidget *gnt_tree_new_with_columns(int columns);
+
+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);
+
+GntTreeRow *gnt_tree_add_row_after(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro);
+
+GntTreeRow *gnt_tree_add_row_last(GntTree *tree, void *key, GntTreeRow *row, void *parent);
+
+gpointer gnt_tree_get_selection_data(GntTree *tree);
+
+/* Returned string needs to be freed */
+char *gnt_tree_get_selection_text(GntTree *tree);
+
+GList *gnt_tree_get_selection_text_list(GntTree *tree);
+
+const GList *gnt_tree_get_rows(GntTree *tree);
+
+void gnt_tree_remove(GntTree *tree, gpointer key);
+
+void gnt_tree_remove_all(GntTree *tree);
+
+/* Returns the visible line number of the selected row */
+int gnt_tree_get_selection_visible_line(GntTree *tree);
+
+void gnt_tree_change_text(GntTree *tree, gpointer key, int colno, const char *text);
+
+GntTreeRow *gnt_tree_add_choice(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro);
+
+void gnt_tree_set_choice(GntTree *tree, void *key, gboolean set);
+
+gboolean gnt_tree_get_choice(GntTree *tree, void *key);
+
+void gnt_tree_set_row_flags(GntTree *tree, void *key, GntTextFormatFlags flags);
+
+void gnt_tree_set_selected(GntTree *tree , void *key);
+
+GntTreeRow *gnt_tree_create_row(GntTree *tree, ...);
+
+GntTreeRow *gnt_tree_create_row_from_list(GntTree *tree, GList *list);
+
+void gnt_tree_set_col_width(GntTree *tree, int col, int width);
+
+void gnt_tree_set_column_titles(GntTree *tree, ...);
+
+void gnt_tree_set_show_title(GntTree *tree, gboolean set);
+
+void gnt_tree_set_compare_func(GntTree *tree, GCompareFunc func);
+
+void gnt_tree_set_expanded(GntTree *tree, void *key, gboolean expanded);
+
+void gnt_tree_set_show_separator(GntTree *tree, gboolean set);
+
+void gnt_tree_sort_row(GntTree *tree, void *row);
+
+/* This will try to automatically adjust the width of the columns in the tree */
+void gnt_tree_adjust_columns(GntTree *tree);
+
+void gnt_tree_set_hash_fns(GntTree *tree, gpointer hash, gpointer eq, gpointer kd);
+
+G_END_DECLS
+
+/* The following functions should NOT be used by applications. */
+
+/* This should be called by the subclasses of GntTree's in their _new function */
+void _gnt_tree_init_internals(GntTree *tree, int col);
+
+#endif /* GNT_TREE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntutils.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,147 @@
+#include "gntutils.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+
+void gnt_util_get_text_bound(const char *text, int *width, int *height)
+{
+	const char *s = text, *last;
+	int count = 1, max = 0;
+	int len;
+
+	/* XXX: ew ... everyone look away */
+	last = s;
+	if (s)
+	{
+		while (*s)
+		{
+			if (*s == '\n' || *s == '\r')
+			{
+				count++;
+				len = gnt_util_onscreen_width(last, s);
+				if (max < len)
+					max = len;
+				last = s + 1;
+			}
+			s = g_utf8_next_char(s);
+		}
+
+		len = gnt_util_onscreen_width(last, s);
+		if (max < len)
+			max = len;
+	}
+
+	if (height)
+		*height = count;
+	if (width)
+		*width = max + (count > 1);
+}
+
+int gnt_util_onscreen_width(const char *start, const char *end)
+{
+	int width = 0;
+
+	if (end == NULL)
+		end = start + strlen(start);
+
+	while (start < end) {
+		width += g_unichar_iswide(g_utf8_get_char(start)) ? 2 : 1;
+		start = g_utf8_next_char(start);
+	}
+	return width;
+}
+
+const char *gnt_util_onscreen_width_to_pointer(const char *string, int len, int *w)
+{
+	int size;
+	int width = 0;
+	const char *str = string;
+
+	if (len <= 0) {
+		len = gnt_util_onscreen_width(string, NULL);
+	}
+
+	while (width < len && *str) {
+		size = g_unichar_iswide(g_utf8_get_char(str)) ? 2 : 1;
+		if (width + size > len)
+			break;
+		str = g_utf8_next_char(str);
+		width += size;
+	}
+	if (w)
+		*w = width;
+	return str;
+}
+
+char *gnt_util_onscreen_fit_string(const char *string, int maxw)
+{
+	const char *start, *end;
+	GString *str;
+
+	if (maxw <= 0)
+		maxw = getmaxx(stdscr) - 4;
+
+	start = string;
+	str = g_string_new(NULL);
+
+	while (*start) {
+		if ((end = strchr(start, '\n')) != NULL ||
+			(end = strchr(start, '\r')) != NULL) {
+			if (gnt_util_onscreen_width(start, end) > maxw)
+				end = NULL;
+		}
+		if (end == NULL)
+			end = gnt_util_onscreen_width_to_pointer(start, maxw, NULL);
+		str = g_string_append_len(str, start, end - start);
+		if (*end) {
+			str = g_string_append_c(str, '\n');
+			if (*end == '\n' || *end == '\r')
+				end++;
+		}
+		start = end;
+	}
+	return g_string_free(str, FALSE);
+}
+
+struct duplicate_fns
+{
+	GDupFunc key_dup;
+	GDupFunc value_dup;
+	GHashTable *table;
+};
+
+static void
+duplicate_values(gpointer key, gpointer value, gpointer data)
+{
+	struct duplicate_fns *fns = data;
+	g_hash_table_insert(fns->table, fns->key_dup ? fns->key_dup(key) : key,
+			fns->value_dup ? fns->value_dup(value) : value);
+}
+
+GHashTable *g_hash_table_duplicate(GHashTable *src, GHashFunc hash,
+		GEqualFunc equal, GDestroyNotify key_d, GDestroyNotify value_d,
+		GDupFunc key_dup, GDupFunc value_dup)
+{
+	GHashTable *dest = g_hash_table_new_full(hash, equal, key_d, value_d);
+	struct duplicate_fns fns = {key_dup, value_dup, dest};
+	g_hash_table_foreach(src, duplicate_values, &fns);
+	return dest;
+}
+
+gboolean gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint,
+				  GValue                *return_accu,
+				  const GValue          *handler_return,
+				  gpointer               dummy)
+{
+	gboolean continue_emission;
+	gboolean signal_handled;
+
+	signal_handled = g_value_get_boolean (handler_return);
+	g_value_set_boolean (return_accu, signal_handled);
+	continue_emission = !signal_handled;
+
+	return continue_emission;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntutils.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,36 @@
+#include <glib.h>
+
+#include "gnt.h"
+#include "gntwidget.h"
+
+typedef gpointer (*GDupFunc)(gconstpointer data);
+
+void gnt_util_get_text_bound(const char *text, int *width, int *height);
+
+/* excluding *end */
+int gnt_util_onscreen_width(const char *start, const char *end);
+
+const char *gnt_util_onscreen_width_to_pointer(const char *str, int len, int *w);
+
+/* Inserts newlines in 'string' where necessary so that its onscreen width is
+ * no more than 'maxw'.
+ * 'maxw' can be <= 0, in which case the maximum screen width is considered.
+ *
+ * Returns a newly allocated string.
+ */
+char *gnt_util_onscreen_fit_string(const char *string, int maxw);
+
+GHashTable *g_hash_table_duplicate(GHashTable *src, GHashFunc hash,
+		GEqualFunc equal, GDestroyNotify key_d, GDestroyNotify value_d,
+		GDupFunc key_dup, GDupFunc value_dup);
+
+
+/**
+ * To be used with g_signal_new. Look in the key_pressed signal-definition in
+ * gntwidget.c for usage.
+ */
+gboolean gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint,
+				  GValue                *return_accu,
+				  const GValue          *handler_return,
+				  gpointer               dummy);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntwidget.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,630 @@
+/* Stuff brutally ripped from Gflib */
+
+#include "gntwidget.h"
+#include "gntstyle.h"
+#include "gntmarshal.h"
+#include "gntutils.h"
+#include "gnt.h"
+
+enum
+{
+	SIG_DESTROY,
+	SIG_DRAW,
+	SIG_HIDE,
+	SIG_GIVE_FOCUS,
+	SIG_LOST_FOCUS,
+	SIG_KEY_PRESSED,
+	SIG_MAP,
+	SIG_ACTIVATE,
+	SIG_EXPOSE,
+	SIG_SIZE_REQUEST,
+	SIG_CONFIRM_SIZE,
+	SIG_SIZE_CHANGED,
+	SIG_POSITION,
+	SIG_CLICKED,
+	SIG_CONTEXT_MENU,
+	SIGS
+};
+
+static GObjectClass *parent_class = NULL;
+static guint signals[SIGS] = { 0 };
+
+static void init_widget(GntWidget *widget);
+
+static void
+gnt_widget_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	widget->priv.name = NULL;
+	GNTDEBUG;
+}
+
+static void
+gnt_widget_map(GntWidget *widget)
+{
+	/* Get some default size for the widget */
+	GNTDEBUG;
+	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);
+	GNTDEBUG;
+}
+
+static void
+gnt_widget_focus_change(GntWidget *widget)
+{
+	if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED)
+		gnt_widget_draw(widget);
+}
+
+static gboolean
+gnt_widget_dummy_confirm_size(GntWidget *widget, int width, int height)
+{
+	if (width < widget->priv.minw || height < widget->priv.minh)
+		return FALSE;
+	if (widget->priv.width != width && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_X))
+		return FALSE;
+	if (widget->priv.height != height && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_GROW_Y))
+		return FALSE;
+	return TRUE;
+}
+
+static gboolean
+context_menu(GntBindable *bind, GList *null)
+{
+	gboolean ret = FALSE;
+	g_signal_emit(bind, signals[SIG_CONTEXT_MENU], 0, &ret);
+	return ret;
+}
+
+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->confirm_size = gnt_widget_dummy_confirm_size;
+	
+	klass->key_pressed = NULL;
+	klass->activate = NULL;
+	klass->clicked = 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_HIDE] = 
+		g_signal_new("hide",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, hide),
+					 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_SIZE_CHANGED] = 
+		g_signal_new("size_changed",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, size_changed),
+					 NULL, NULL,
+					 gnt_closure_marshal_VOID__INT_INT,
+					 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+	signals[SIG_CONFIRM_SIZE] = 
+		g_signal_new("confirm_size",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, confirm_size),
+					 NULL, NULL,
+					 gnt_closure_marshal_BOOLEAN__INT_INT,
+					 G_TYPE_BOOLEAN, 2, G_TYPE_INT, G_TYPE_INT);
+	signals[SIG_KEY_PRESSED] = 
+		g_signal_new("key_pressed",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, key_pressed),
+					 gnt_boolean_handled_accumulator, NULL,
+					 gnt_closure_marshal_BOOLEAN__STRING,
+					 G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
+
+	signals[SIG_CLICKED] = 
+		g_signal_new("clicked",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWidgetClass, clicked),
+					 gnt_boolean_handled_accumulator, NULL,
+					 gnt_closure_marshal_BOOLEAN__INT_INT_INT,
+					 G_TYPE_BOOLEAN, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
+
+	signals[SIG_CONTEXT_MENU] = 
+		g_signal_new("context-menu",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 0,
+					 gnt_boolean_handled_accumulator, NULL,
+					 gnt_closure_marshal_BOOLEAN__VOID,
+					 G_TYPE_BOOLEAN, 0);
+
+	/* This is relevant for all widgets */
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "context-menu", context_menu,
+				GNT_KEY_POPUP, NULL);
+	gnt_bindable_register_binding(GNT_BINDABLE_CLASS(klass), "context-menu", GNT_KEY_F11, NULL);
+
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * 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,
+			NULL,					/* class_data		*/
+			sizeof(GntWidget),
+			0,						/* n_preallocs		*/
+			gnt_widget_init,					/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_BINDABLE,
+									  "GntWidget",
+									  &info, G_TYPE_FLAG_ABSTRACT);
+	}
+
+	return type;
+}
+
+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));
+
+	gnt_widget_hide(obj);
+	delwin(obj->window);
+	if(!(GNT_WIDGET_FLAGS(obj) & GNT_WIDGET_DESTROYING))
+		g_object_run_dispose(G_OBJECT(obj));
+	GNTDEBUG;
+}
+
+void
+gnt_widget_show(GntWidget *widget)
+{
+	gnt_widget_draw(widget);
+	gnt_screen_occupy(widget);
+}
+
+void
+gnt_widget_draw(GntWidget *widget)
+{
+	/* Draw the widget */
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_DRAWING))
+		return;
+
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_DRAWING);
+	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED)) {
+		gnt_widget_map(widget);
+	}
+
+	if (widget->window == NULL)
+	{
+#if 0
+		int x, y, maxx, maxy, w, h;
+		int oldw, oldh;
+		gboolean shadow = TRUE;
+
+		if (!gnt_widget_has_shadow(widget))
+			shadow = FALSE;
+
+		x = widget->priv.x;
+		y = widget->priv.y;
+		w = oldw = widget->priv.width + shadow;
+		h = oldh = widget->priv.height + shadow;
+
+		getmaxyx(stdscr, maxy, maxx);
+		maxy -= 1;		/* room for the taskbar */
+
+		x = MAX(0, x);
+		y = MAX(0, y);
+		if (x + w >= maxx)
+			x = MAX(0, maxx - w);
+		if (y + h >= maxy)
+			y = MAX(0, maxy - h);
+
+		w = MIN(w, maxx);
+		h = MIN(h, maxy);
+
+		widget->priv.x = x;
+		widget->priv.y = y;
+		if (w != oldw || h != oldh) {
+			widget->priv.width = w - shadow;
+			widget->priv.height = h - shadow;
+			g_signal_emit(widget, signals[SIG_SIZE_CHANGED], 0, oldw, oldh);
+		}
+#else
+		widget->window = newpad(widget->priv.height + 20, widget->priv.width + 20);  /* XXX: */
+#endif
+		init_widget(widget);
+	}
+
+	g_signal_emit(widget, signals[SIG_DRAW], 0);
+	gnt_widget_queue_update(widget);
+	GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_DRAWING);
+}
+
+gboolean
+gnt_widget_key_pressed(GntWidget *widget, const char *keys)
+{
+	gboolean ret;
+	if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS))
+		return FALSE;
+
+	if (gnt_bindable_perform_action_key(GNT_BINDABLE(widget), keys))
+		return TRUE;
+
+	keys = gnt_bindable_remap_keys(GNT_BINDABLE(widget), keys);
+	g_signal_emit(widget, signals[SIG_KEY_PRESSED], 0, keys, &ret);
+	return ret;
+}
+
+gboolean
+gnt_widget_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
+{
+	gboolean ret;
+	g_signal_emit(widget, signals[SIG_CLICKED], 0, event, x, y, &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)
+{
+	g_signal_emit(widget, signals[SIG_HIDE], 0);
+	wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+#if 0
+	/* XXX: I have no clue why, but this seemed to be necessary. */
+	if (gnt_widget_has_shadow(widget))
+		mvwvline(widget->window, 1, widget->priv.width, ' ', widget->priv.height);
+#endif
+	gnt_screen_release(widget);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_INVISIBLE);
+	GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_MAPPED);
+}
+
+void
+gnt_widget_set_position(GntWidget *wid, int x, int y)
+{
+	g_signal_emit(wid, signals[SIG_POSITION], 0, x, y);
+	/* XXX: Need to install properties for these and g_object_notify */
+	wid->priv.x = x;
+	wid->priv.y = 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)
+{
+	gboolean shadow = TRUE;
+	if (!gnt_widget_has_shadow(wid))
+		shadow = FALSE;
+
+	if (width)
+		*width = wid->priv.width + shadow;
+	if (height)
+		*height = wid->priv.height + shadow;
+	
+}
+
+static void
+init_widget(GntWidget *widget)
+{
+	gboolean shadow = TRUE;
+
+	if (!gnt_widget_has_shadow(widget))
+		shadow = FALSE;
+
+	wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL));
+	werase(widget->window);
+
+	if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER))
+	{
+		/* - This is ugly. */
+		/* - What's your point? */
+		mvwvline(widget->window, 0, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.height);
+		mvwvline(widget->window, 0, widget->priv.width - 1,
+				ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.height);
+		mvwhline(widget->window, widget->priv.height - 1, 0,
+				ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.width);
+		mvwhline(widget->window, 0, 0, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.width);
+		mvwaddch(widget->window, 0, 0, ACS_ULCORNER | COLOR_PAIR(GNT_COLOR_NORMAL));
+		mvwaddch(widget->window, 0, widget->priv.width - 1,
+				ACS_URCORNER | COLOR_PAIR(GNT_COLOR_NORMAL));
+		mvwaddch(widget->window, widget->priv.height - 1, 0,
+				ACS_LLCORNER | COLOR_PAIR(GNT_COLOR_NORMAL));
+		mvwaddch(widget->window, widget->priv.height - 1, widget->priv.width - 1,
+				ACS_LRCORNER | COLOR_PAIR(GNT_COLOR_NORMAL));
+	}
+
+	if (shadow)
+	{
+		wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_SHADOW));
+		mvwvline(widget->window, 1, widget->priv.width, ' ', widget->priv.height);
+		mvwhline(widget->window, widget->priv.height, 1, ' ', widget->priv.width);
+	}
+}
+
+gboolean
+gnt_widget_set_size(GntWidget *widget, int width, int height)
+{
+	gboolean ret = TRUE;
+
+	if (gnt_widget_has_shadow(widget))
+	{
+		width--;
+		height--;
+	}
+	if (width <= 0)
+		width = widget->priv.width;
+	if (height <= 0)
+		height = widget->priv.height;
+
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
+	{
+		ret = gnt_widget_confirm_size(widget, width, height);
+	}
+
+	if (ret)
+	{
+		gboolean shadow = TRUE;
+		int oldw, oldh;
+
+		if (!gnt_widget_has_shadow(widget))
+			shadow = FALSE;
+
+		oldw = widget->priv.width;
+		oldh = widget->priv.height;
+
+		widget->priv.width = width;
+		widget->priv.height = height;
+		if (width >= getmaxx(widget->window) || height >= getmaxy(widget->window)) {
+			delwin(widget->window);
+			widget->window = newpad(height + 20, width + 20);
+		}
+
+		g_signal_emit(widget, signals[SIG_SIZE_CHANGED], 0, oldw, oldh);
+
+		if (widget->window)
+		{
+			init_widget(widget);
+		}
+		if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
+			init_widget(widget);
+		else
+			GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_MAPPED);
+	}
+
+	return ret;
+}
+
+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))
+	{
+		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);
+}
+
+const char *gnt_widget_get_name(GntWidget *widget)
+{
+	return widget->priv.name;
+}
+
+void gnt_widget_activate(GntWidget *widget)
+{
+	g_signal_emit(widget, signals[SIG_ACTIVATE], 0);
+}
+
+static gboolean
+update_queue_callback(gpointer data)
+{
+	GntWidget *widget = GNT_WIDGET(data);
+
+	if (!g_object_get_data(G_OBJECT(widget), "gnt:queue_update"))
+		return FALSE;
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
+		gnt_screen_update(widget);
+	g_object_set_data(G_OBJECT(widget), "gnt:queue_update", NULL);
+	return FALSE;
+}
+
+void gnt_widget_queue_update(GntWidget *widget)
+{
+	if (widget->window == NULL)
+		return;
+	while (widget->parent)
+		widget = widget->parent;
+	
+	if (!g_object_get_data(G_OBJECT(widget), "gnt:queue_update"))
+	{
+		int id = g_timeout_add(0, update_queue_callback, widget);
+		g_object_set_data_full(G_OBJECT(widget), "gnt:queue_update", GINT_TO_POINTER(id),
+				(GDestroyNotify)g_source_remove);
+	}
+}
+
+gboolean gnt_widget_confirm_size(GntWidget *widget, int width, int height)
+{
+	gboolean ret = FALSE;
+	g_signal_emit(widget, signals[SIG_CONFIRM_SIZE], 0, width, height, &ret);
+	return ret;
+}
+
+void gnt_widget_set_visible(GntWidget *widget, gboolean set)
+{
+	if (set)
+		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_INVISIBLE);
+	else
+		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_INVISIBLE);
+}
+
+gboolean gnt_widget_has_shadow(GntWidget *widget)
+{
+	return (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_SHADOW) &&
+			gnt_style_get_bool(GNT_STYLE_SHADOW, FALSE));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntwidget.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,152 @@
+#ifndef GNT_WIDGET_H
+#define GNT_WIDGET_H
+
+#include <stdio.h>
+#include <glib.h>
+#include <ncurses.h>
+
+#include "gntbindable.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_WIDGET_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))
+
+typedef struct _GnWidget			GntWidget;
+typedef struct _GnWidgetPriv		GntWidgetPriv;
+typedef struct _GnWidgetClass		GntWidgetClass;
+
+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,
+	GNT_WIDGET_DRAWING        = 1 << 6,
+	GNT_WIDGET_URGENT         = 1 << 7,
+	GNT_WIDGET_GROW_X         = 1 << 8,
+	GNT_WIDGET_GROW_Y         = 1 << 9,
+	GNT_WIDGET_INVISIBLE      = 1 << 10,
+	GNT_WIDGET_TRANSIENT      = 1 << 11,
+} GntWidgetFlags;
+
+/* XXX: This will probably move elsewhere */
+typedef enum _GnMouseEvent
+{
+	GNT_LEFT_MOUSE_DOWN = 1,
+	GNT_RIGHT_MOUSE_DOWN,
+	GNT_MIDDLE_MOUSE_DOWN,
+	GNT_MOUSE_UP,
+	GNT_MOUSE_SCROLL_UP,
+	GNT_MOUSE_SCROLL_DOWN
+} GntMouseEvent;
+
+/* XXX: I'll have to ask grim what he's using this for in guifications. */
+typedef enum _GnParamFlags
+{
+	GNT_PARAM_SERIALIZABLE	= 1 << G_PARAM_USER_SHIFT
+} GntParamFlags;
+
+struct _GnWidgetPriv
+{
+	int x, y;
+	int width, height;
+	GntWidgetFlags flags;
+	char *name;
+
+	int minw, minh;    /* Minimum size for the widget */
+};
+
+struct _GnWidget
+{
+	GntBindable inherit;
+
+	GntWidget *parent;
+
+	GntWidgetPriv priv;
+	WINDOW *window;
+
+    void (*gnt_reserved1)(void);
+    void (*gnt_reserved2)(void);
+    void (*gnt_reserved3)(void);
+    void (*gnt_reserved4)(void);
+};
+
+struct _GnWidgetClass
+{
+	GntBindableClass 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 (*hide)(GntWidget *obj);
+	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);
+	gboolean (*confirm_size)(GntWidget *widget, int x, int y);
+	void (*size_changed)(GntWidget *widget, int w, int h);
+	void (*set_position)(GntWidget *widget, int x, int y);
+	gboolean (*key_pressed)(GntWidget *widget, const char *key);
+	void (*activate)(GntWidget *widget);
+	gboolean (*clicked)(GntWidget *widget, GntMouseEvent event, int x, int y);
+
+	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);
+gboolean gnt_widget_set_size(GntWidget *widget, int width, int height);
+gboolean gnt_widget_confirm_size(GntWidget *widget, int width, int height);
+
+gboolean gnt_widget_key_pressed(GntWidget *widget, const char *keys);
+
+gboolean gnt_widget_clicked(GntWidget *widget, GntMouseEvent event, int x, int y);
+
+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);
+
+const char *gnt_widget_get_name(GntWidget *widget);
+
+/* Widget-subclasses should call this from the draw-callback.
+ * Applications should just call gnt_widget_draw instead of this. */
+void gnt_widget_queue_update(GntWidget *widget);
+
+void gnt_widget_set_take_focus(GntWidget *widget, gboolean set);
+
+void gnt_widget_set_visible(GntWidget *widget, gboolean set);
+
+gboolean gnt_widget_has_shadow(GntWidget *widget);
+
+G_END_DECLS
+
+#endif /* GNT_WIDGET_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntwindow.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,119 @@
+#include "gntstyle.h"
+#include "gntwindow.h"
+
+#include <string.h>
+
+enum
+{
+	SIGS = 1,
+};
+
+static GntBoxClass *parent_class = NULL;
+
+static void (*org_destroy)(GntWidget *widget);
+
+static gboolean
+show_menu(GntBindable *bind, GList *null)
+{
+	GntWindow *win = GNT_WINDOW(bind);
+	if (win->menu) {
+		gnt_screen_menu_show(win->menu);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static void
+gnt_window_destroy(GntWidget *widget)
+{
+	GntWindow *window = GNT_WINDOW(widget);
+	if (window->menu)
+		gnt_widget_destroy(GNT_WIDGET(window->menu));
+	org_destroy(widget);
+}
+
+static void
+gnt_window_class_init(GntWindowClass *klass)
+{
+	GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass);
+	GntWidgetClass *wid_class = GNT_WIDGET_CLASS(klass);
+	parent_class = GNT_BOX_CLASS(klass);
+
+	org_destroy = wid_class->destroy;
+	wid_class->destroy = gnt_window_destroy;
+
+	gnt_bindable_class_register_action(bindable, "show-menu", show_menu,
+				GNT_KEY_CTRL_O, NULL);
+	gnt_bindable_register_binding(bindable, "show-menu", GNT_KEY_F10, NULL);
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), bindable);
+
+	GNTDEBUG;
+}
+
+static void
+gnt_window_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntWindow API
+ *****************************************************************************/
+GType
+gnt_window_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntWindowClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_window_class_init,
+			NULL,					/* class_finalize	*/
+			NULL,					/* class_data		*/
+			sizeof(GntWindow),
+			0,						/* n_preallocs		*/
+			gnt_window_init,			/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_BOX,
+									  "GntWindow",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_window_new()
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_WINDOW, NULL);
+
+	return widget;
+}
+
+GntWidget *gnt_window_box_new(gboolean homo, gboolean vert)
+{
+	GntWidget *wid = gnt_window_new();
+	GntBox *box = GNT_BOX(wid);
+
+	box->homogeneous = homo;
+	box->vertical = vert;
+	box->alignment = vert ? GNT_ALIGN_LEFT : GNT_ALIGN_MID;
+
+	return wid;
+}
+
+void gnt_window_set_menu(GntWindow *window, GntMenu *menu)
+{
+	/* If a menu already existed, then destroy that first. */
+	if (window->menu)
+		gnt_widget_destroy(GNT_WIDGET(window->menu));
+	window->menu = menu;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntwindow.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,56 @@
+#ifndef GNT_WINDOW_H
+#define GNT_WINDOW_H
+
+#include "gnt.h"
+#include "gntbox.h"
+#include "gntcolors.h"
+#include "gntkeys.h"
+#include "gntmenu.h"
+
+#define GNT_TYPE_WINDOW				(gnt_window_get_gtype())
+#define GNT_WINDOW(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_WINDOW, GntWindow))
+#define GNT_WINDOW_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_WINDOW, GntWindowClass))
+#define GNT_IS_WINDOW(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_WINDOW))
+#define GNT_IS_WINDOW_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WINDOW))
+#define GNT_WINDOW_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WINDOW, GntWindowClass))
+
+#define GNT_WINDOW_FLAGS(obj)				(GNT_WINDOW(obj)->priv.flags)
+#define GNT_WINDOW_SET_FLAGS(obj, flags)		(GNT_WINDOW_FLAGS(obj) |= flags)
+#define GNT_WINDOW_UNSET_FLAGS(obj, flags)	(GNT_WINDOW_FLAGS(obj) &= ~(flags))
+
+typedef struct _GnWindow			GntWindow;
+typedef struct _GnWindowPriv		GntWindowPriv;
+typedef struct _GnWindowClass		GntWindowClass;
+
+struct _GnWindow
+{
+	GntBox parent;
+	GntMenu *menu;
+};
+
+struct _GnWindowClass
+{
+	GntBoxClass parent;
+
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_window_get_gtype(void);
+
+#define gnt_vwindow_new(homo) gnt_window_box_new(homo, TRUE)
+#define gnt_hwindow_new(homo) gnt_window_box_new(homo, FALSE)
+
+GntWidget *gnt_window_new(void);
+
+GntWidget *gnt_window_box_new(gboolean homo, gboolean vert);
+
+void gnt_window_set_menu(GntWindow *window, GntMenu *menu);
+
+G_END_DECLS
+
+#endif /* GNT_WINDOW_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntwm.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,1504 @@
+#define _GNU_SOURCE
+#if defined(__APPLE__)
+#define _XOPEN_SOURCE_EXTENDED
+#endif
+
+#include "config.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "gntwm.h"
+#include "gntstyle.h"
+#include "gntmarshal.h"
+#include "gnt.h"
+#include "gntbox.h"
+#include "gntmenu.h"
+#include "gnttextview.h"
+#include "gnttree.h"
+#include "gntutils.h"
+
+#define IDLE_CHECK_INTERVAL 5 /* 5 seconds */
+
+enum
+{
+	SIG_NEW_WIN,
+	SIG_DECORATE_WIN,
+	SIG_CLOSE_WIN,
+	SIG_CONFIRM_RESIZE,
+	SIG_RESIZED,
+	SIG_CONFIRM_MOVE,
+	SIG_MOVED,
+	SIG_UPDATE_WIN,
+	SIG_GIVE_FOCUS,
+	SIG_KEY_PRESS,
+	SIG_MOUSE_CLICK,
+	SIGS
+};
+
+static guint signals[SIGS] = { 0 };
+static void gnt_wm_new_window_real(GntWM *wm, GntWidget *widget);
+static void gnt_wm_win_resized(GntWM *wm, GntNode *node);
+static void gnt_wm_win_moved(GntWM *wm, GntNode *node);
+static void gnt_wm_give_focus(GntWM *wm, GntWidget *widget);
+static void update_window_in_list(GntWM *wm, GntWidget *wid);
+static void shift_window(GntWM *wm, GntWidget *widget, int dir);
+
+static gboolean write_already(gpointer data);
+static int write_timeout;
+static time_t last_active_time;
+static gboolean idle_update;
+
+static GList *
+g_list_bring_to_front(GList *list, gpointer data)
+{
+	list = g_list_remove(list, data);
+	list = g_list_prepend(list, data);
+	return list;
+}
+
+static void
+free_node(gpointer data)
+{
+	GntNode *node = data;
+	hide_panel(node->panel);
+	del_panel(node->panel);
+	g_free(node);
+}
+
+static void
+draw_taskbar(GntWM *wm, gboolean reposition)
+{
+	static WINDOW *taskbar = NULL;
+	GList *iter;
+	int n, width = 0;
+	int i;
+
+	if (taskbar == NULL) {
+		taskbar = newwin(1, getmaxx(stdscr), getmaxy(stdscr) - 1, 0);
+	} else if (reposition) {
+		int Y_MAX = getmaxy(stdscr) - 1;
+		mvwin(taskbar, Y_MAX, 0);
+	}
+
+	wbkgdset(taskbar, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
+	werase(taskbar);
+
+	n = g_list_length(wm->list);
+	if (n)
+		width = getmaxx(stdscr) / n;
+
+	for (i = 0, iter = wm->list; iter; iter = iter->next, i++)
+	{
+		GntWidget *w = iter->data;
+		int color;
+		const char *title;
+
+		if (w == wm->ordered->data) {
+			/* This is the current window in focus */
+			color = GNT_COLOR_TITLE;
+		} else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_URGENT)) {
+			/* This is a window with the URGENT hint set */
+			color = GNT_COLOR_URGENT;
+		} else {
+			color = GNT_COLOR_NORMAL;
+		}
+		wbkgdset(taskbar, '\0' | COLOR_PAIR(color));
+		if (iter->next)
+			mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), width);
+		else
+			mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), getmaxx(stdscr) - width * i);
+		title = GNT_BOX(w)->title;
+		mvwprintw(taskbar, 0, width * i, "%s", title ? title : "<gnt>");
+		if (i)
+			mvwaddch(taskbar, 0, width *i - 1, ACS_VLINE | A_STANDOUT | COLOR_PAIR(GNT_COLOR_NORMAL));
+
+		update_window_in_list(wm, w);
+	}
+
+	wrefresh(taskbar);
+}
+
+static void
+copy_win(GntWidget *widget, GntNode *node)
+{
+	WINDOW *src, *dst;
+	int shadow;
+	if (!node)
+		return;
+	src = widget->window;
+	dst = node->window;
+	shadow = gnt_widget_has_shadow(widget) ? 1 : 0;
+	copywin(src, dst, node->scroll, 0, 0, 0, getmaxy(dst) - 1, getmaxx(dst) - 1, 0);
+}
+
+static gboolean
+update_screen(GntWM *wm)
+{
+	if (wm->menu) {
+		GntMenu *top = wm->menu;
+		while (top) {
+			GntNode *node = g_hash_table_lookup(wm->nodes, top);
+			if (node)
+				top_panel(node->panel);
+			top = top->submenu;
+		}
+	}
+	update_panels();
+	doupdate();
+	return TRUE;
+}
+
+static gboolean
+sanitize_position(GntWidget *widget, int *x, int *y)
+{
+	int X_MAX = getmaxx(stdscr);
+	int Y_MAX = getmaxy(stdscr) - 1;
+	int w, h;
+	int nx, ny;
+	gboolean changed = FALSE;
+
+	gnt_widget_get_size(widget, &w, &h);
+	if (x) {
+		if (*x + w > X_MAX) {
+			nx = MAX(0, X_MAX - w);
+			if (nx != *x) {
+				*x = nx;
+				changed = TRUE;
+			}
+		}
+	}
+	if (y) {
+		if (*y + h > Y_MAX) {
+			ny = MAX(0, Y_MAX - h);
+			if (ny != *y) {
+				*y = ny;
+				changed = TRUE;
+			}
+		}
+	}
+	return changed;
+}
+
+static void
+refresh_node(GntWidget *widget, GntNode *node, gpointer null)
+{
+	int x, y, w, h;
+	int nw, nh;
+
+	int X_MAX = getmaxx(stdscr);
+	int Y_MAX = getmaxy(stdscr) - 1;
+
+	gnt_widget_get_position(widget, &x, &y);
+	gnt_widget_get_size(widget, &w, &h);
+
+	if (sanitize_position(widget, &x, &y))
+		gnt_screen_move_widget(widget, x, y);
+
+	nw = MIN(w, X_MAX);
+	nh = MIN(h, Y_MAX);
+	if (nw != w || nh != h)
+		gnt_screen_resize_widget(widget, nw, nh);
+}
+
+static void
+read_window_positions(GntWM *wm)
+{
+#if GLIB_CHECK_VERSION(2,6,0)
+	GKeyFile *gfile = g_key_file_new();
+	char *filename = g_build_filename(g_get_home_dir(), ".gntpositions", NULL);
+	GError *error = NULL;
+	char **keys;
+	gsize nk;
+
+	if (!g_key_file_load_from_file(gfile, filename, G_KEY_FILE_NONE, &error)) {
+		g_printerr("GntWM: %s\n", error->message);
+		g_error_free(error);
+		g_free(filename);
+		return;
+	}
+
+	keys = g_key_file_get_keys(gfile, "positions", &nk, &error);
+	if (error) {
+		g_printerr("GntWM: %s\n", error->message);
+		g_error_free(error);
+		error = NULL;
+	} else {
+		while (nk--) {
+			char *title = keys[nk];
+			gsize l;
+			char **coords = g_key_file_get_string_list(gfile, "positions", title, &l, NULL);
+			if (l == 2) {
+				int x = atoi(coords[0]);
+				int y = atoi(coords[1]);
+				GntPosition *p = g_new0(GntPosition, 1);
+				p->x = x;
+				p->y = y;
+				g_hash_table_replace(wm->positions, g_strdup(title + 1), p);
+			} else {
+				g_printerr("GntWM: Invalid number of arguments for positioing a window.\n");
+			}
+			g_strfreev(coords);
+		}
+		g_strfreev(keys);
+	}
+
+	g_free(filename);
+#endif
+}
+
+static gboolean check_idle(gpointer n)
+{
+	if (idle_update) {
+		time(&last_active_time);
+		idle_update = FALSE;
+	}
+	return TRUE;
+}
+
+static void
+gnt_wm_init(GTypeInstance *instance, gpointer class)
+{
+	GntWM *wm = GNT_WM(instance);
+	wm->list = NULL;
+	wm->ordered = NULL;
+	wm->event_stack = FALSE;
+	wm->windows = NULL;
+	wm->actions = NULL;
+	wm->nodes = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_node);
+	wm->positions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+	if (gnt_style_get_bool(GNT_STYLE_REMPOS, TRUE))
+		read_window_positions(wm);
+	g_timeout_add(IDLE_CHECK_INTERVAL * 1000, check_idle, NULL);
+	time(&last_active_time);
+}
+
+static void
+switch_window(GntWM *wm, int direction)
+{
+	GntWidget *w = NULL, *wid = NULL;
+	int pos;
+
+	if (wm->_list.window || wm->menu)
+		return;
+
+	if (!wm->ordered || !wm->ordered->next)
+		return;
+
+	w = wm->ordered->data;
+	pos = g_list_index(wm->list, w);
+	pos += direction;
+
+	if (pos < 0)
+		wid = g_list_last(wm->list)->data;
+	else if (pos >= g_list_length(wm->list))
+		wid = wm->list->data;
+	else if (pos >= 0)
+		wid = g_list_nth_data(wm->list, pos);
+
+	wm->ordered = g_list_bring_to_front(wm->ordered, wid);
+
+	gnt_wm_raise_window(wm, wm->ordered->data);
+
+	if (w != wid) {
+		gnt_widget_set_focus(w, FALSE);
+	}
+}
+
+static gboolean
+window_next(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	switch_window(wm, 1);
+	return TRUE;
+}
+
+static gboolean
+window_prev(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	switch_window(wm, -1);
+	return TRUE;
+}
+
+static gboolean
+switch_window_n(GntBindable *bind, GList *list)
+{
+	GntWM *wm = GNT_WM(bind);
+	GntWidget *w = NULL;
+	GList *l;
+	int n;
+
+	if (!wm->ordered)
+		return TRUE;
+
+	if (list)
+		n = GPOINTER_TO_INT(list->data);
+	else
+		n = 0;
+
+	w = wm->ordered->data;
+
+	if ((l = g_list_nth(wm->list, n)) != NULL)
+	{
+		gnt_wm_raise_window(wm, l->data);
+	}
+
+	if (l && w != l->data)
+	{
+		gnt_widget_set_focus(w, FALSE);
+	}
+	return TRUE;
+}
+
+static gboolean
+window_scroll_up(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	GntWidget *window;
+	GntNode *node;
+
+	if (!wm->ordered)
+		return TRUE;
+
+	window = wm->ordered->data;
+	node = g_hash_table_lookup(wm->nodes, window);
+	if (!node)
+		return TRUE;
+
+	if (node->scroll) {
+		node->scroll--;
+		copy_win(window, node);
+		update_screen(wm);
+	}
+	return TRUE;
+}
+
+static gboolean
+window_scroll_down(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	GntWidget *window;
+	GntNode *node;
+	int w, h;
+
+	if (!wm->ordered)
+		return TRUE;
+
+	window = wm->ordered->data;
+	node = g_hash_table_lookup(wm->nodes, window);
+	if (!node)
+		return TRUE;
+
+	gnt_widget_get_size(window, &w, &h);
+	if (h - node->scroll > getmaxy(node->window)) {
+		node->scroll++;
+		copy_win(window, node);
+		update_screen(wm);
+	}
+	return TRUE;
+}
+
+static gboolean
+window_close(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+
+	if (wm->_list.window)
+		return TRUE;
+
+	if (wm->ordered) {
+		gnt_widget_destroy(wm->ordered->data);
+	}
+
+	return TRUE;
+}
+
+static void
+destroy__list(GntWidget *widget, GntWM *wm)
+{
+	wm->_list.window = NULL;
+	wm->_list.tree = NULL;
+	wm->windows = NULL;
+	wm->actions = NULL;
+	update_screen(wm);
+}
+
+static void
+setup__list(GntWM *wm)
+{
+	GntWidget *tree, *win;
+	win = wm->_list.window = gnt_box_new(FALSE, FALSE);
+	gnt_box_set_toplevel(GNT_BOX(win), TRUE);
+	gnt_box_set_pad(GNT_BOX(win), 0);
+	GNT_WIDGET_SET_FLAGS(win, GNT_WIDGET_TRANSIENT);
+
+	tree = wm->_list.tree = gnt_tree_new();
+	gnt_box_add_widget(GNT_BOX(win), tree);
+
+	g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(destroy__list), wm);
+}
+
+static void
+window_list_activate(GntTree *tree, GntWM *wm)
+{
+	GntWidget *widget = gnt_tree_get_selection_data(GNT_TREE(tree));
+
+	if (!wm->ordered || !widget)
+		return;
+
+	gnt_widget_destroy(wm->_list.window);
+	gnt_wm_raise_window(wm, widget);
+}
+
+static void
+populate_window_list(GntWM *wm)
+{
+	GList *iter;
+	GntTree *tree = GNT_TREE(wm->windows->tree);
+	for (iter = wm->list; iter; iter = iter->next) {
+		GntBox *box = GNT_BOX(iter->data);
+
+		gnt_tree_add_row_last(tree, box,
+				gnt_tree_create_row(tree, box->title), NULL);
+		update_window_in_list(wm, GNT_WIDGET(box));
+	}
+}
+
+static gboolean
+window_list_key_pressed(GntWidget *widget, const char *text, GntWM *wm)
+{
+	if (text[1] == 0 && wm->ordered) {
+		GntWidget *sel = gnt_tree_get_selection_data(GNT_TREE(widget));
+		switch (text[0]) {
+			case '-':
+			case '<':
+				shift_window(wm, sel, -1);
+				break;
+			case '+':
+			case '>':
+				shift_window(wm, sel, 1);
+				break;
+			default:
+				return FALSE;
+		}
+		gnt_tree_remove_all(GNT_TREE(widget));
+		populate_window_list(wm);
+		gnt_tree_set_selected(GNT_TREE(widget), sel);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+window_list(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	GntWidget *tree, *win;
+
+	if (wm->_list.window || wm->menu)
+		return TRUE;
+
+	if (!wm->ordered)
+		return TRUE;
+
+	setup__list(wm);
+	wm->windows = &wm->_list;
+
+	win = wm->windows->window;
+	tree = wm->windows->tree;
+
+	gnt_box_set_title(GNT_BOX(win), "Window List");
+	
+	populate_window_list(wm);
+
+	gnt_tree_set_selected(GNT_TREE(tree), wm->ordered->data);
+	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(window_list_activate), wm);
+	g_signal_connect(G_OBJECT(tree), "key_pressed", G_CALLBACK(window_list_key_pressed), wm);
+
+	gnt_tree_set_col_width(GNT_TREE(tree), 0, getmaxx(stdscr) / 3);
+	gnt_widget_set_size(tree, 0, getmaxy(stdscr) / 2);
+	gnt_widget_set_position(win, getmaxx(stdscr) / 3, getmaxy(stdscr) / 4);
+
+	gnt_widget_show(win);
+	return TRUE;
+}
+
+static gboolean
+dump_screen(GntBindable *bindable, GList *null)
+{
+	int x, y;
+	chtype old = 0, now = 0;
+	FILE *file = fopen("dump.html", "w");
+
+	fprintf(file, "<pre>");
+	for (y = 0; y < getmaxy(stdscr); y++) {
+		for (x = 0; x < getmaxx(stdscr); x++) {
+			char ch;
+			now = mvwinch(curscr, y, x);
+			ch = now & A_CHARTEXT;
+			now ^= ch;
+
+#define CHECK(attr, start, end) \
+			do \
+			{  \
+				if (now & attr)  \
+				{  \
+					if (!(old & attr))  \
+						fprintf(file, "%s", start);  \
+				}  \
+				else if (old & attr)  \
+				{  \
+					fprintf(file, "%s", end);  \
+				}  \
+			} while (0) 
+
+			CHECK(A_BOLD, "<b>", "</b>");
+			CHECK(A_UNDERLINE, "<u>", "</u>");
+			CHECK(A_BLINK, "<blink>", "</blink>");
+
+			if ((now & A_COLOR) != (old & A_COLOR) ||
+				(now & A_REVERSE) != (old & A_REVERSE))
+			{
+				int ret;
+				short fgp, bgp, r, g, b;
+				struct
+				{
+					int r, g, b;
+				} fg, bg;
+
+				ret = pair_content(PAIR_NUMBER(now & A_COLOR), &fgp, &bgp);
+				if (fgp == -1)
+					fgp = COLOR_BLACK;
+				if (bgp == -1)
+					bgp = COLOR_WHITE;
+				if (now & A_REVERSE)
+					fgp ^= bgp ^= fgp ^= bgp;  /* *wink* */
+				ret = color_content(fgp, &r, &g, &b);
+				fg.r = r; fg.b = b; fg.g = g;
+				ret = color_content(bgp, &r, &g, &b);
+				bg.r = r; bg.b = b; bg.g = g;
+#define ADJUST(x) (x = x * 255 / 1000)
+				ADJUST(fg.r);
+				ADJUST(fg.g);
+				ADJUST(fg.b);
+				ADJUST(bg.r);
+				ADJUST(bg.b);
+				ADJUST(bg.g);
+				
+				if (x) fprintf(file, "</span>");
+				fprintf(file, "<span style=\"background:#%02x%02x%02x;color:#%02x%02x%02x\">",
+						bg.r, bg.g, bg.b, fg.r, fg.g, fg.b);
+			}
+			if (now & A_ALTCHARSET)
+			{
+				switch (ch)
+				{
+					case 'q':
+						ch = '-'; break;
+					case 't':
+					case 'u':
+					case 'x':
+						ch = '|'; break;
+					case 'v':
+					case 'w':
+					case 'l':
+					case 'm':
+					case 'k':
+					case 'j':
+					case 'n':
+						ch = '+'; break;
+					case '-':
+						ch = '^'; break;
+					case '.':
+						ch = 'v'; break;
+					case 'a':
+						ch = '#'; break;
+					default:
+						ch = ' '; break;
+				}
+			}
+			if (ch == '&')
+				fprintf(file, "&amp;");
+			else if (ch == '<')
+				fprintf(file, "&lt;");
+			else if (ch == '>')
+				fprintf(file, "&gt;");
+			else
+				fprintf(file, "%c", ch);
+			old = now;
+		}
+		fprintf(file, "</span>\n");
+		old = 0;
+	}
+	fprintf(file, "</pre>");
+	fclose(file);
+	return TRUE;
+}
+
+static void
+shift_window(GntWM *wm, GntWidget *widget, int dir)
+{
+	GList *all = wm->list;
+	GList *list = g_list_find(all, widget);
+	int length, pos;
+	if (!list)
+		return;
+
+	length = g_list_length(all);
+	pos = g_list_position(all, list);
+
+	pos += dir;
+	if (dir > 0)
+		pos++;
+
+	if (pos < 0)
+		pos = length;
+	else if (pos > length)
+		pos = 0;
+
+	all = g_list_insert(all, widget, pos);
+	all = g_list_delete_link(all, list);
+	wm->list = all;
+	draw_taskbar(wm, FALSE);
+}
+
+static gboolean
+shift_left(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	if (wm->_list.window)
+		return TRUE;
+
+	shift_window(wm, wm->ordered->data, -1);
+	return TRUE;
+}
+
+static gboolean
+shift_right(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	if (wm->_list.window)
+		return TRUE;
+
+	shift_window(wm, wm->ordered->data, 1);
+	return TRUE;
+}
+
+static void
+action_list_activate(GntTree *tree, GntWM *wm)
+{
+	GntAction *action = gnt_tree_get_selection_data(tree);
+	action->callback();
+	gnt_widget_destroy(wm->_list.window);
+}
+
+static int
+compare_action(gconstpointer p1, gconstpointer p2)
+{
+	const GntAction *a1 = p1;
+	const GntAction *a2 = p2;
+
+	return g_utf8_collate(a1->label, a2->label);
+}
+
+static gboolean
+list_actions(GntBindable *bindable, GList *null)
+{
+	GntWidget *tree, *win;
+	GList *iter;
+	GntWM *wm = GNT_WM(bindable);
+	if (wm->_list.window || wm->menu)
+		return TRUE;
+
+	if (wm->acts == NULL)
+		return TRUE;
+
+	setup__list(wm);
+	wm->actions = &wm->_list;
+
+	win = wm->actions->window;
+	tree = wm->actions->tree;
+
+	gnt_box_set_title(GNT_BOX(win), "Actions");
+	GNT_WIDGET_SET_FLAGS(tree, GNT_WIDGET_NO_BORDER);
+	/* XXX: Do we really want this? */
+	gnt_tree_set_compare_func(GNT_TREE(tree), compare_action);
+
+	for (iter = wm->acts; iter; iter = iter->next) {
+		GntAction *action = iter->data;
+		gnt_tree_add_row_last(GNT_TREE(tree), action,
+				gnt_tree_create_row(GNT_TREE(tree), action->label), NULL);
+	}
+	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(action_list_activate), wm);
+	gnt_widget_set_size(tree, 0, g_list_length(wm->acts));
+	gnt_widget_set_position(win, 0, getmaxy(stdscr) - 3 - g_list_length(wm->acts));
+
+	gnt_widget_show(win);
+	return TRUE;
+}
+
+#ifndef NO_WIDECHAR
+static int
+widestringwidth(wchar_t *wide)
+{
+	int len, ret;
+	char *string;
+
+	len = wcstombs(NULL, wide, 0) + 1;
+	string = g_new0(char, len);
+	wcstombs(string, wide, len);
+	ret = gnt_util_onscreen_width(string, NULL);
+	g_free(string);
+	return ret;
+}
+#endif
+
+/* Returns the onscreen width of the character at the position */
+static int
+reverse_char(WINDOW *d, int y, int x, gboolean set)
+{
+#define DECIDE(ch) (set ? ((ch) | A_REVERSE) : ((ch) & ~A_REVERSE))
+
+#ifdef NO_WIDECHAR
+	chtype ch;
+	ch = mvwinch(d, y, x);
+	mvwaddch(d, y, x, DECIDE(ch));
+	return 1;
+#else
+	cchar_t ch;
+	int wc = 1;
+	if (mvwin_wch(d, y, x, &ch) == OK) {
+		wc = widestringwidth(ch.chars);
+		ch.attr = DECIDE(ch.attr);
+		ch.attr &= WA_ATTRIBUTES;   /* XXX: This is a workaround for a bug */
+		mvwadd_wch(d, y, x, &ch);
+	}
+
+	return wc;
+#endif
+}
+
+static void
+window_reverse(GntWidget *win, gboolean set, GntWM *wm)
+{
+	int i;
+	int w, h;
+	WINDOW *d;
+
+	if (GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_NO_BORDER))
+		return;
+	
+	d = win->window;
+	gnt_widget_get_size(win, &w, &h);
+
+	if (gnt_widget_has_shadow(win)) {
+		--w;
+		--h;
+	}
+
+	/* the top and bottom */
+	for (i = 0; i < w; i += reverse_char(d, 0, i, set));
+	for (i = 0; i < w; i += reverse_char(d, h-1, i, set));
+
+	/* the left and right */
+	for (i = 0; i < h; i += reverse_char(d, i, 0, set));
+	for (i = 0; i < h; i += reverse_char(d, i, w-1, set));
+
+	copy_win(win, g_hash_table_lookup(wm->nodes, win));
+	update_screen(wm);
+}
+
+static gboolean
+start_move(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	if (wm->_list.window || wm->menu)
+		return TRUE;
+	if (!wm->ordered)
+		return TRUE;
+
+	wm->mode = GNT_KP_MODE_MOVE;
+	window_reverse(GNT_WIDGET(wm->ordered->data), TRUE, wm);
+
+	return TRUE;
+}
+
+static gboolean
+start_resize(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	if (wm->_list.window || wm->menu)
+		return TRUE;
+	if (!wm->ordered)
+		return TRUE;
+
+	wm->mode = GNT_KP_MODE_RESIZE;
+	window_reverse(GNT_WIDGET(wm->ordered->data), TRUE, wm);
+
+	return TRUE;
+}
+
+static gboolean
+wm_quit(GntBindable *bindable, GList *list)
+{
+	GntWM *wm = GNT_WM(bindable);
+	if (write_timeout)
+		write_already(wm);
+	g_main_loop_quit(wm->loop);
+	return TRUE;
+}
+
+static gboolean
+return_true(GntWM *wm, GntWidget *w, int *a, int *b)
+{
+	return TRUE;
+}
+
+static gboolean
+refresh_screen(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+
+	endwin();
+	refresh();
+	curs_set(0);   /* endwin resets the cursor to normal */
+
+	g_hash_table_foreach(wm->nodes, (GHFunc)refresh_node, NULL);
+	update_screen(wm);
+	draw_taskbar(wm, TRUE);
+
+	return FALSE;
+}
+
+static void
+gnt_wm_class_init(GntWMClass *klass)
+{
+	int i;
+
+	klass->new_window = gnt_wm_new_window_real;
+	klass->decorate_window = NULL;
+	klass->close_window = NULL;
+	klass->window_resize_confirm = return_true;
+	klass->window_resized = gnt_wm_win_resized;
+	klass->window_move_confirm = return_true;
+	klass->window_moved = gnt_wm_win_moved;
+	klass->window_update = NULL;
+	klass->key_pressed  = NULL;
+	klass->mouse_clicked = NULL;
+	klass->give_focus = gnt_wm_give_focus;
+	
+	signals[SIG_NEW_WIN] = 
+		g_signal_new("new_win",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, new_window),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals[SIG_DECORATE_WIN] = 
+		g_signal_new("decorate_win",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, decorate_window),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals[SIG_CLOSE_WIN] = 
+		g_signal_new("close_win",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, close_window),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals[SIG_CONFIRM_RESIZE] = 
+		g_signal_new("confirm_resize",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, window_resize_confirm),
+					 gnt_boolean_handled_accumulator, NULL,
+					 gnt_closure_marshal_BOOLEAN__POINTER_POINTER_POINTER,
+					 G_TYPE_BOOLEAN, 3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER);
+
+	signals[SIG_CONFIRM_MOVE] = 
+		g_signal_new("confirm_move",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, window_move_confirm),
+					 gnt_boolean_handled_accumulator, NULL,
+					 gnt_closure_marshal_BOOLEAN__POINTER_POINTER_POINTER,
+					 G_TYPE_BOOLEAN, 3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER);
+
+	signals[SIG_RESIZED] = 
+		g_signal_new("window_resized",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, window_resized),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals[SIG_MOVED] = 
+		g_signal_new("window_moved",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, window_moved),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals[SIG_UPDATE_WIN] = 
+		g_signal_new("window_update",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, window_update),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+	signals[SIG_GIVE_FOCUS] = 
+		g_signal_new("give_focus",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, give_focus),
+					 NULL, NULL,
+					 g_cclosure_marshal_VOID__POINTER,
+					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+	signals[SIG_MOUSE_CLICK] = 
+		g_signal_new("mouse_clicked",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntWMClass, mouse_clicked),
+					 gnt_boolean_handled_accumulator, NULL,
+					 gnt_closure_marshal_BOOLEAN__INT_INT_INT_POINTER,
+					 G_TYPE_BOOLEAN, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_POINTER);
+
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-next", window_next,
+				"\033" "n", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-prev", window_prev,
+				"\033" "p", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-close", window_close,
+				"\033" "c", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-list", window_list,
+				"\033" "w", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "dump-screen", dump_screen,
+				"\033" "d", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "shift-left", shift_left,
+				"\033" ",", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "shift-right", shift_right,
+				"\033" ".", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "action-list", list_actions,
+				"\033" "a", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "start-move", start_move,
+				"\033" "m", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "start-resize", start_resize,
+				"\033" "r", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "wm-quit", wm_quit,
+				"\033" "q", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "refresh-screen", refresh_screen,
+				"\033" "l", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "switch-window-n", switch_window_n,
+				NULL, NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-scroll-down", window_scroll_down,
+				"\033" GNT_KEY_CTRL_J, NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-scroll-up", window_scroll_up,
+				"\033" GNT_KEY_CTRL_K, NULL);
+
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+
+	/* Make sure Alt+x are detected properly. */
+	for (i = '0'; i <= '9'; i++) {
+		char str[] = "\033X";
+		str[1] = i;
+		gnt_keys_add_combination(str);
+	}
+
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntWM API
+ *****************************************************************************/
+GType
+gnt_wm_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(GntWMClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_wm_class_init,
+			NULL,
+			NULL,					/* class_data		*/
+			sizeof(GntWM),
+			0,						/* n_preallocs		*/
+			gnt_wm_init,			/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(GNT_TYPE_BINDABLE,
+									  "GntWM",
+									  &info, 0);
+	}
+
+	return type;
+}
+static void
+update_window_in_list(GntWM *wm, GntWidget *wid)
+{
+	GntTextFormatFlags flag = 0;
+
+	if (wm->windows == NULL)
+		return;
+
+	if (wid == wm->ordered->data)
+		flag |= GNT_TEXT_FLAG_DIM;
+	else if (GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_URGENT))
+		flag |= GNT_TEXT_FLAG_BOLD;
+
+	gnt_tree_set_row_flags(GNT_TREE(wm->windows->tree), wid, flag);
+}
+
+static void
+gnt_wm_new_window_real(GntWM *wm, GntWidget *widget)
+{
+	GntNode *node;
+	gboolean transient = FALSE;
+
+	if (widget->window == NULL)
+		return;
+
+	node = g_new0(GntNode, 1);
+	node->me = widget;
+	node->scroll = 0;
+
+	g_hash_table_replace(wm->nodes, widget, node);
+
+	refresh_node(widget, node, NULL);
+
+	transient = !!GNT_WIDGET_IS_FLAG_SET(node->me, GNT_WIDGET_TRANSIENT);
+
+#if 1
+	{
+		int x, y, w, h, maxx, maxy;
+		gboolean shadow = TRUE;
+
+		if (!gnt_widget_has_shadow(widget))
+			shadow = FALSE;
+		x = widget->priv.x;
+		y = widget->priv.y;
+		w = widget->priv.width;
+		h = widget->priv.height;
+
+		getmaxyx(stdscr, maxy, maxx);
+		maxy -= 1;              /* room for the taskbar */
+		maxy -= shadow;
+		maxx -= shadow;
+
+		x = MAX(0, x);
+		y = MAX(0, y);
+		if (x + w >= maxx)
+			x = MAX(0, maxx - w);
+		if (y + h >= maxy)
+			y = MAX(0, maxy - h);
+
+		w = MIN(w, maxx);
+		h = MIN(h, maxy);
+		node->window = newwin(h + shadow, w + shadow, y, x);
+		copy_win(widget, node);
+	}
+#endif
+
+	node->panel = new_panel(node->window);
+	set_panel_userptr(node->panel, node);
+
+	if (!transient) {
+		if (node->me != wm->_list.window) {
+			GntWidget *w = NULL;
+
+			if (wm->ordered)
+				w = wm->ordered->data;
+
+			wm->list = g_list_append(wm->list, widget);
+
+			if (wm->event_stack)
+				wm->ordered = g_list_prepend(wm->ordered, widget);
+			else
+				wm->ordered = g_list_append(wm->ordered, widget);
+
+			gnt_widget_set_focus(widget, TRUE);
+			if (w)
+				gnt_widget_set_focus(w, FALSE);
+		}
+
+		if (wm->event_stack || node->me == wm->_list.window) {
+			gnt_wm_raise_window(wm, node->me);
+		} else {
+			bottom_panel(node->panel);     /* New windows should not grab focus */
+			gnt_widget_set_urgent(node->me);
+		}
+	}
+}
+
+void gnt_wm_new_window(GntWM *wm, GntWidget *widget)
+{
+	while (widget->parent)
+		widget = widget->parent;
+	
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_INVISIBLE) ||
+			g_hash_table_lookup(wm->nodes, widget)) {
+		update_screen(wm);
+		return;
+	}
+
+	if (GNT_IS_BOX(widget)) {
+		const char *title = GNT_BOX(widget)->title;
+		GntPosition *p = NULL;
+		if (title && (p = g_hash_table_lookup(wm->positions, title)) != NULL) {
+			sanitize_position(widget, &p->x, &p->y);
+			gnt_widget_set_position(widget, p->x, p->y);
+			mvwin(widget->window, p->y, p->x);
+		}
+	}
+
+	g_signal_emit(wm, signals[SIG_NEW_WIN], 0, widget);
+	g_signal_emit(wm, signals[SIG_DECORATE_WIN], 0, widget);
+
+	if (wm->windows && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) {
+		if ((GNT_IS_BOX(widget) && GNT_BOX(widget)->title) && wm->_list.window != widget
+				&& GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS)) {
+			gnt_tree_add_row_last(GNT_TREE(wm->windows->tree), widget,
+					gnt_tree_create_row(GNT_TREE(wm->windows->tree), GNT_BOX(widget)->title),
+					NULL);
+			update_window_in_list(wm, widget);
+		}
+	}
+
+	update_screen(wm);
+	draw_taskbar(wm, FALSE);
+}
+
+void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget)
+{
+	g_signal_emit(wm, signals[SIG_DECORATE_WIN], 0, widget);
+}
+
+void gnt_wm_window_close(GntWM *wm, GntWidget *widget)
+{
+	GntNode *node;
+	int pos;
+
+	if ((node = g_hash_table_lookup(wm->nodes, widget)) == NULL)
+		return;
+
+	g_signal_emit(wm, signals[SIG_CLOSE_WIN], 0, widget);
+	g_hash_table_remove(wm->nodes, widget);
+
+	if (wm->windows) {
+		gnt_tree_remove(GNT_TREE(wm->windows->tree), widget);
+	}
+
+	pos = g_list_index(wm->list, widget);
+
+	if (pos != -1) {
+		wm->list = g_list_remove(wm->list, widget);
+		wm->ordered = g_list_remove(wm->ordered, widget);
+
+		if (wm->ordered)
+			gnt_wm_raise_window(wm, wm->ordered->data);
+	}
+
+	update_screen(wm);
+	draw_taskbar(wm, FALSE);
+}
+
+time_t gnt_wm_get_idle_time()
+{
+	return time(NULL) - last_active_time;
+}
+
+gboolean gnt_wm_process_input(GntWM *wm, const char *keys)
+{
+	gboolean ret = FALSE;
+
+	keys = gnt_bindable_remap_keys(GNT_BINDABLE(wm), keys);
+
+	idle_update = TRUE;
+
+	if (gnt_bindable_perform_action_key(GNT_BINDABLE(wm), keys))
+		return TRUE;
+
+	/* Do some manual checking */
+	if (wm->ordered && wm->mode != GNT_KP_MODE_NORMAL) {
+		int xmin = 0, ymin = 0, xmax = getmaxx(stdscr), ymax = getmaxy(stdscr) - 1;
+		int x, y, w, h;
+		GntWidget *widget = GNT_WIDGET(wm->ordered->data);
+		int ox, oy, ow, oh;
+
+		gnt_widget_get_position(widget, &x, &y);
+		gnt_widget_get_size(widget, &w, &h);
+		ox = x;	oy = y;
+		ow = w;	oh = h;
+
+		if (wm->mode == GNT_KP_MODE_MOVE) {
+			if (strcmp(keys, GNT_KEY_LEFT) == 0) {
+				if (x > xmin)
+					x--;
+			} else if (strcmp(keys, GNT_KEY_RIGHT) == 0) {
+				if (x + w < xmax)
+					x++;
+			} else if (strcmp(keys, GNT_KEY_UP) == 0) {
+				if (y > ymin)
+					y--;
+			} else if (strcmp(keys, GNT_KEY_DOWN) == 0) {
+				if (y + h < ymax)
+					y++;
+			}
+			if (ox != x || oy != y) {
+				gnt_screen_move_widget(widget, x, y);
+				window_reverse(widget, TRUE, wm);
+				return TRUE;
+			}
+		} else if (wm->mode == GNT_KP_MODE_RESIZE) {
+			if (strcmp(keys, GNT_KEY_LEFT) == 0) {
+				w--;
+			} else if (strcmp(keys, GNT_KEY_RIGHT) == 0) {
+				if (x + w < xmax)
+					w++;
+			} else if (strcmp(keys, GNT_KEY_UP) == 0) {
+				h--;
+			} else if (strcmp(keys, GNT_KEY_DOWN) == 0) {
+				if (y + h < ymax)
+					h++;
+			}
+			if (oh != h || ow != w) {
+				gnt_screen_resize_widget(widget, w, h);
+				window_reverse(widget, TRUE, wm);
+				return TRUE;
+			}
+		}
+		if (strcmp(keys, "\r") == 0 || strcmp(keys, "\033") == 0) {
+			window_reverse(widget, FALSE, wm);
+			wm->mode = GNT_KP_MODE_NORMAL;
+		}
+		return TRUE;
+	}
+
+	wm->event_stack = TRUE;
+
+	/* Escape to close the window-list or action-list window */
+	if (strcmp(keys, "\033") == 0) {
+		if (wm->_list.window) {
+			gnt_widget_destroy(wm->_list.window);
+			wm->event_stack = FALSE;
+			return TRUE;
+		}
+	} else if (keys[0] == '\033' && isdigit(keys[1]) && keys[2] == '\0') {
+		/* Alt+x for quick switch */
+		int n = *(keys + 1) - '0';
+		GList *list = NULL;
+
+		if (n == 0)
+			n = 10;
+
+		list = g_list_append(list, GINT_TO_POINTER(n - 1));
+		switch_window_n(GNT_BINDABLE(wm), list);
+		g_list_free(list);
+		return TRUE;
+	}
+
+	if (wm->menu)
+		ret = gnt_widget_key_pressed(GNT_WIDGET(wm->menu), keys);
+	else if (wm->_list.window)
+		ret = gnt_widget_key_pressed(wm->_list.window, keys);
+	else if (wm->ordered)
+		ret = gnt_widget_key_pressed(GNT_WIDGET(wm->ordered->data), keys);
+	wm->event_stack = FALSE;
+	return ret;
+}
+
+static void
+gnt_wm_win_resized(GntWM *wm, GntNode *node)
+{
+	/*refresh_node(node->me, node, NULL);*/
+}
+
+static void
+gnt_wm_win_moved(GntWM *wm, GntNode *node)
+{
+	refresh_node(node->me, node, NULL);
+}
+
+void gnt_wm_resize_window(GntWM *wm, GntWidget *widget, int width, int height)
+{
+	gboolean ret = TRUE;
+	GntNode *node;
+	int shadow;
+	int maxx, maxy;
+	
+	while (widget->parent)
+		widget = widget->parent;
+	node = g_hash_table_lookup(wm->nodes, widget);
+	if (!node)
+		return;
+
+	g_signal_emit(wm, signals[SIG_CONFIRM_RESIZE], 0, widget, &width, &height, &ret);
+	if (!ret)
+		return;    /* resize is not permitted */
+	hide_panel(node->panel);
+	gnt_widget_set_size(widget, width, height);
+	gnt_widget_draw(widget);
+
+	shadow = gnt_widget_has_shadow(widget) ? 1 : 0;
+	maxx = getmaxx(stdscr) - shadow;
+	maxy = getmaxy(stdscr) - 1 - shadow;
+	height = MIN(height, maxy);
+	width = MIN(width, maxx);
+	wresize(node->window, height + shadow, width + shadow);
+	replace_panel(node->panel, node->window);
+
+	g_signal_emit(wm, signals[SIG_RESIZED], 0, node);
+
+	show_panel(node->panel);
+	update_screen(wm);
+}
+
+static void
+write_gdi(gpointer key, gpointer value, gpointer data)
+{
+	GntPosition *p = value;
+	fprintf(data, ".%s = %d;%d\n", (char *)key, p->x, p->y);
+}
+
+static gboolean
+write_already(gpointer data)
+{
+	GntWM *wm = data;
+	FILE *file;
+	char *filename;
+
+	filename = g_build_filename(g_get_home_dir(), ".gntpositions", NULL);
+
+	file = fopen(filename, "wb");
+	if (file == NULL) {
+		g_printerr("GntWM: error opening file to save positions\n");
+	} else {
+		fprintf(file, "[positions]\n");
+		g_hash_table_foreach(wm->positions, write_gdi, file);
+		fclose(file);
+	}
+
+	g_free(filename);
+	g_source_remove(write_timeout);
+	write_timeout = 0;
+	return FALSE;
+}
+
+static void
+write_positions_to_file(GntWM *wm)
+{
+	if (write_timeout) {
+		g_source_remove(write_timeout);
+	}
+	write_timeout = g_timeout_add(10000, write_already, wm);
+}
+
+void gnt_wm_move_window(GntWM *wm, GntWidget *widget, int x, int y)
+{
+	gboolean ret = TRUE;
+	GntNode *node;
+
+	while (widget->parent)
+		widget = widget->parent;
+	node = g_hash_table_lookup(wm->nodes, widget);
+	if (!node)
+		return;
+
+	g_signal_emit(wm, signals[SIG_CONFIRM_MOVE], 0, widget, &x, &y, &ret);
+	if (!ret)
+		return;    /* resize is not permitted */
+
+	gnt_widget_set_position(widget, x, y);
+	move_panel(node->panel, y, x);
+
+	g_signal_emit(wm, signals[SIG_MOVED], 0, node);
+	if (gnt_style_get_bool(GNT_STYLE_REMPOS, TRUE) && GNT_IS_BOX(widget)) {
+		const char *title = GNT_BOX(widget)->title;
+		if (title) {
+			GntPosition *p = g_new0(GntPosition, 1);
+			GntWidget *wid = node->me;
+			p->x = wid->priv.x;
+			p->y = wid->priv.y;
+			g_hash_table_replace(wm->positions, g_strdup(title), p);
+			write_positions_to_file(wm);
+		}
+	}
+
+	update_screen(wm);
+}
+
+static void
+gnt_wm_give_focus(GntWM *wm, GntWidget *widget)
+{
+	GntNode *node = g_hash_table_lookup(wm->nodes, widget);
+
+	if (!node)
+		return;
+	
+	if (widget != wm->_list.window && !GNT_IS_MENU(widget) &&
+				wm->ordered->data != widget) {
+		GntWidget *w = wm->ordered->data;
+		wm->ordered = g_list_bring_to_front(wm->ordered, widget);
+		gnt_widget_set_focus(w, FALSE);
+	}
+
+	gnt_widget_set_focus(widget, TRUE);
+	GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_URGENT);
+	gnt_widget_draw(widget);
+	top_panel(node->panel);
+
+	if (wm->_list.window) {
+		GntNode *nd = g_hash_table_lookup(wm->nodes, wm->_list.window);
+		top_panel(nd->panel);
+	}
+	update_screen(wm);
+	draw_taskbar(wm, FALSE);
+}
+
+void gnt_wm_update_window(GntWM *wm, GntWidget *widget)
+{
+	GntNode *node;
+
+	while (widget->parent)
+		widget = widget->parent;
+	if (!GNT_IS_MENU(widget))
+		gnt_box_sync_children(GNT_BOX(widget));
+
+	node = g_hash_table_lookup(wm->nodes, widget);
+	if (node == NULL) {
+		gnt_wm_new_window(wm, widget);
+	} else
+		g_signal_emit(wm, signals[SIG_UPDATE_WIN], 0, node);
+
+	copy_win(widget, node);
+	update_screen(wm);
+	draw_taskbar(wm, FALSE);
+}
+
+gboolean gnt_wm_process_click(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget)
+{
+	gboolean ret = TRUE;
+	idle_update = TRUE;
+	g_signal_emit(wm, signals[SIG_MOUSE_CLICK], 0, event, x, y, widget, &ret);
+	return ret;
+}
+
+void gnt_wm_raise_window(GntWM *wm, GntWidget *widget)
+{
+	g_signal_emit(wm, signals[SIG_GIVE_FOCUS], 0, widget);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntwm.h	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,168 @@
+
+#include "gntwidget.h"
+#include "gntmenu.h"
+
+#include <panel.h>
+
+#define GNT_TYPE_WM				(gnt_wm_get_gtype())
+#define GNT_WM(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_WM, GntWM))
+#define GNT_WM_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_WM, GntWMClass))
+#define GNT_IS_WM(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_WM))
+#define GNT_IS_WM_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WM))
+#define GNT_WM_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WM, GntWMClass))
+
+typedef enum
+{
+	GNT_KP_MODE_NORMAL,
+	GNT_KP_MODE_RESIZE,
+	GNT_KP_MODE_MOVE,
+} GntKeyPressMode;
+
+typedef struct
+{
+	GntWidget *me;
+
+	WINDOW *window;
+	int scroll;
+	PANEL *panel;
+} GntNode;
+
+typedef struct _GntWM GntWM;
+
+typedef struct _GnPosition
+{
+	int x;
+	int y;
+} GntPosition;
+
+/**
+ * An application can register actions which will show up in a 'start-menu' like popup
+ */
+typedef struct _GnAction
+{
+	const char *label;
+	void (*callback)();
+} GntAction;
+
+struct _GntWM
+{
+	GntBindable inherit;
+
+	GMainLoop *loop;
+
+	GList *list;      /* List of windows ordered on their creation time */
+	GList *ordered;   /* List of windows ordered on their focus */
+
+	struct {
+		GntWidget *window;
+		GntWidget *tree;
+	} _list,
+		*windows,         /* Window-list window */
+		*actions;         /* Action-list window */
+
+	GHashTable *nodes;    /* GntWidget -> GntNode */
+
+	GList *acts;          /* List of actions */
+
+	/**
+	 * There can be at most one menu at a time on the screen.
+	 * If there is a menu being displayed, then all the keystrokes will be sent to
+	 * the menu until it is closed, either when the user activates a menuitem, or
+	 * presses Escape to cancel the menu.
+	 */
+	GntMenu *menu;        /* Currently active menu */
+
+	/**
+	 * 'event_stack' will be set to TRUE when a user-event, ie. a mouse-click
+	 * or a key-press is being processed. This variable will be used to determine
+	 * whether to give focus to a new window.
+	 */
+	gboolean event_stack;
+	
+	GntKeyPressMode mode;
+
+	GHashTable *positions;
+
+	void *res1;
+	void *res2;
+	void *res3;
+	void *res4;
+};
+
+typedef struct _GnWMClass GntWMClass;
+
+struct _GnWMClass
+{
+	GntBindableClass parent;
+
+	/* This is called when a new window is shown */
+	void (*new_window)(GntWM *wm, GntWidget *win);
+
+	void (*decorate_window)(GntWM *wm, GntWidget *win);
+	/* This is called when a window is being closed */
+	gboolean (*close_window)(GntWM *wm, GntWidget *win);
+
+	/* The WM may want to confirm a size for a window first */
+	gboolean (*window_resize_confirm)(GntWM *wm, GntWidget *win, int *w, int *h);
+
+	void (*window_resized)(GntWM *wm, GntNode *node);
+
+	/* The WM may want to confirm the position of a window */
+	gboolean (*window_move_confirm)(GntWM *wm, GntWidget *win, int *x, int *y);
+
+	void (*window_moved)(GntWM *wm, GntNode *node);
+
+	/* This gets called when:
+	 * 	 - the title of the window changes
+	 * 	 - the 'urgency' of the window changes
+	 */
+	void (*window_update)(GntWM *wm, GntNode *node);
+
+	/* This should usually return NULL if the keys were processed by the WM.
+	 * If not, the WM can simply return the original string, which will be
+	 * processed by the default WM. The custom WM can also return a different
+	 * static string for the default WM to process.
+	 */
+	gboolean (*key_pressed)(GntWM *wm, const char *key);
+
+	gboolean (*mouse_clicked)(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget);
+
+	/* Whatever the WM wants to do when a window is given focus */
+	void (*give_focus)(GntWM *wm, GntWidget *widget);
+
+	/* List of windows. Although the WM can keep a list of its own for the windows,
+	 * it'd be better if there was a way to share between the 'core' and the WM.
+	 */
+	/*const GList *(*window_list)();*/
+
+	void (*res1)(void);
+	void (*res2)(void);
+	void (*res3)(void);
+	void (*res4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType gnt_wm_get_gtype(void);
+
+void gnt_wm_new_window(GntWM *wm, GntWidget *widget);
+
+void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget);
+
+void gnt_wm_window_close(GntWM *wm, GntWidget *widget);
+
+gboolean gnt_wm_process_input(GntWM *wm, const char *string);
+
+gboolean gnt_wm_process_click(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget);
+
+void gnt_wm_resize_window(GntWM *wm, GntWidget *widget, int width, int height);
+
+void gnt_wm_move_window(GntWM *wm, GntWidget *widget, int x, int y);
+
+void gnt_wm_update_window(GntWM *wm, GntWidget *widget);
+
+void gnt_wm_raise_window(GntWM *wm, GntWidget *widget);
+
+time_t gnt_wm_get_idle_time(void);
+
+G_END_DECLS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,125 @@
+#include "gntbutton.h"
+#include "gnt.h"
+#include "gntkeys.h"
+#include "gnttree.h"
+#include "gntbox.h"
+
+static gboolean
+key_pressed(GntWidget *widget, const char *text, gpointer null)
+{
+	GntWidget *w = null;
+	GntWidget *box = gnt_box_new(FALSE, FALSE);
+	GntWidget *label = gnt_label_new("so wassup!!");
+
+	gnt_box_add_widget(GNT_BOX(box), label);
+	GNT_WIDGET_UNSET_FLAGS(box, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+	gnt_box_set_title(GNT_BOX(box), "This is a test");
+
+	gnt_widget_show(box);
+#if 0
+
+	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);
+#endif
+
+	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(GNT_BOX(vbox), widget);
+	gnt_box_add_widget(GNT_BOX(vbox), widget2);
+
+	gnt_box_add_widget(GNT_BOX(hbox), label);
+	/*gnt_box_add_widget(GNT_BOX(hbox), vbox);*/
+
+	gnt_box_add_widget(GNT_BOX(hbox), gnt_entry_new("a"));
+
+	tree = gnt_tree_new();
+	gnt_box_add_widget(GNT_BOX(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(GNT_BOX(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), tree);
+	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;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test/Makefile	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,16 @@
+CC=gcc
+CFLAGS=`pkg-config --cflags gobject-2.0 gmodule-2.0` -g -I../ -DSTANDALONE
+LDFLAGS=`pkg-config --libs gobject-2.0 gmodule-2.0 gnt` -pg
+
+EXAMPLES=combo focus tv multiwin keys menu
+
+all:
+	make examples
+
+clean:
+	rm -f $(EXAMPLES) *.so wm
+
+WM: wm
+	for i in $(EXAMPLES); do gcc -shared $(CFLAGS) -USTANDALONE $(LDFLAGS) $${i}.c -o $${i}.so ; done
+
+examples: $(EXAMPLES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test/combo.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,82 @@
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntcheckbox.h>
+#include <gntcombobox.h>
+#include <gntlabel.h>
+
+static void
+button_activated(GntWidget *b, GntComboBox *combo)
+{
+	GntWidget *w = b->parent;
+
+	gnt_box_add_widget(GNT_BOX(w),
+			gnt_label_new(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))));
+	fprintf(stderr, "%s\n", gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)));
+	gnt_box_readjust(GNT_BOX(w->parent));
+}
+
+int main()
+{
+	GntWidget *box, *combo, *button;
+	GntWidget *hbox;
+
+#ifdef STANDALONE
+	freopen(".error", "w", stderr);
+	gnt_init();
+#endif
+	
+	box = gnt_box_new(FALSE, TRUE);
+	gnt_widget_set_name(box, "box");
+	gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID);
+	gnt_box_set_pad(GNT_BOX(box), 0);
+
+	gnt_box_set_toplevel(GNT_BOX(box), TRUE);
+	gnt_box_set_title(GNT_BOX(box), "Checkbox");
+
+	hbox = gnt_box_new(FALSE, FALSE);
+	gnt_box_set_pad(GNT_BOX(hbox), 0);
+	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
+	gnt_widget_set_name(hbox, "upper");
+
+	combo = gnt_combo_box_new();
+	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "1", "1");
+	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "2", "2");
+	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "3", "3abcdefghijklmnopqrstuvwxyz");
+	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "4", "4");
+	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "5", "5");
+	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "6", "6");
+	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "7", "7");
+	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "8", "8");
+	gnt_combo_box_add_data(GNT_COMBO_BOX(combo), "9", "9");
+
+	GntWidget *l = gnt_label_new("Select");
+	gnt_box_add_widget(GNT_BOX(hbox), l);
+	gnt_widget_set_size(l, 0, 1);
+	gnt_box_add_widget(GNT_BOX(hbox), combo);
+
+	gnt_box_add_widget(GNT_BOX(box), hbox);
+
+	hbox = gnt_box_new(TRUE, FALSE);
+	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
+	gnt_widget_set_name(hbox, "lower");
+
+	button = gnt_button_new("OK");
+	gnt_box_add_widget(GNT_BOX(hbox), button);
+	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(button_activated), combo);
+
+	gnt_box_add_widget(GNT_BOX(box), hbox);
+
+	gnt_box_add_widget(GNT_BOX(box), gnt_check_box_new("check box"));
+
+	gnt_widget_show(box);
+
+#ifdef STANDALONE
+	gnt_main();
+
+	gnt_quit();
+#endif
+
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test/focus.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,92 @@
+#include "gntbutton.h"
+#include "gnt.h"
+#include "gntkeys.h"
+#include "gnttree.h"
+#include "gntbox.h"
+#include "gntentry.h"
+#include "gntlabel.h"
+
+static void
+toggled(GntWidget *tree, gpointer key, gpointer null)
+{
+	GntWidget *w = gnt_box_new(FALSE, FALSE);
+
+	gnt_box_set_toplevel(GNT_BOX(w), TRUE);
+
+	gnt_box_add_widget(GNT_BOX(w),
+			gnt_label_new(gnt_tree_get_choice(GNT_TREE(tree), key) ? "Selected" : "NOT"));
+	gnt_widget_show(w);
+}
+
+int main()
+{
+#ifdef STANDALONE
+	freopen(".error", "w", stderr);
+	gnt_init();
+#endif
+	
+	GntWidget *label = gnt_label_new("So wassup dudes and dudettes!!\u4e0a1\u6d772\u67003\u4f4e4\u67085\nSo this is, like,\nthe third line!! \\o/");
+	GntWidget *vbox, *hbox, *tree, *box, *button;
+	WINDOW *test;
+
+	vbox = gnt_box_new(FALSE, FALSE);
+	hbox = gnt_box_new(FALSE, TRUE);
+	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
+
+	gnt_widget_set_name(vbox, "vbox");
+	gnt_widget_set_name(hbox, "hbox");
+
+	gnt_box_add_widget(GNT_BOX(hbox), label);
+
+	GntWidget *entry = gnt_entry_new("a");
+	gnt_widget_set_name(entry, "entry");
+	gnt_box_add_widget(GNT_BOX(hbox), entry);
+
+	box = gnt_box_new(FALSE, FALSE);
+	tree = gnt_tree_new();
+	gnt_tree_set_compare_func(GNT_TREE(tree), g_utf8_collate);
+	gnt_widget_set_name(tree, "tree");
+	gnt_box_add_widget(GNT_BOX(box), tree);
+	gnt_box_add_widget(GNT_BOX(hbox), box);
+
+	gnt_tree_add_row_after(GNT_TREE(tree), "c", gnt_tree_create_row(GNT_TREE(tree), "c"), NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "a", gnt_tree_create_row(GNT_TREE(tree), "a"), NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "z", gnt_tree_create_row(GNT_TREE(tree), "z"), "a", NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "y", gnt_tree_create_row(GNT_TREE(tree), "y"), "a", NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "g", gnt_tree_create_row(GNT_TREE(tree), "g"), "a", NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "d", gnt_tree_create_row(GNT_TREE(tree), "d"), NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "x", gnt_tree_create_row(GNT_TREE(tree), "x"), "a", NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "k", gnt_tree_create_row(GNT_TREE(tree), "k"), "a", NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "e", gnt_tree_create_row(GNT_TREE(tree), "e"), "a", NULL);
+	gnt_tree_add_choice(GNT_TREE(tree), "b", gnt_tree_create_row(GNT_TREE(tree), "b"), "d", NULL);
+
+	GNT_WIDGET_UNSET_FLAGS(hbox, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+	gnt_box_set_title(GNT_BOX(hbox), "\u4e0a\u6d77\u6700\u4f4e\u6708\u5de5 \u4e0a\u6d77\u6700\u4f4e\u6708\u5de5 ……\u4e0a\u6d77\u6700\u4f4e\u6708\u5de5 …");
+
+	g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(toggled), NULL);
+
+	button = gnt_button_new("one");
+	gnt_widget_set_name(button, "one");
+	gnt_box_add_widget(GNT_BOX(vbox), button);
+
+	button = gnt_button_new("two");
+	gnt_widget_set_name(button, "two");
+	gnt_box_add_widget(GNT_BOX(vbox), button);
+
+	button = gnt_button_new("three");
+	gnt_widget_set_name(button, "three");
+	gnt_box_add_widget(GNT_BOX(vbox), button);
+
+	gnt_box_add_widget(GNT_BOX(hbox), vbox);
+	
+	gnt_widget_show(hbox);
+
+#ifdef STANDALONE
+	gnt_main();
+
+	gnt_quit();
+#endif
+
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test/key.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,18 @@
+#include <ncurses.h>
+
+int main()
+{
+	int ch;
+	initscr();
+
+	noecho();
+
+	while ((ch = getch())) {
+		printw("%d ", ch);
+		refresh();
+	}
+
+	endwin();
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test/keys.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,60 @@
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntentry.h>
+#include <gntlabel.h>
+
+static gboolean
+print_keycode(GntEntry *entry, const char *text, gpointer null)
+{
+	char *s = g_strdup_printf("%s ", text);
+	gnt_entry_set_text(entry, s);
+	g_free(s);
+	if (text[0] == 27)
+	{
+		if (strncmp(text + 1, "[M ", 3) == 0)
+		{
+			int x = (unsigned)text[4];
+			int y = (unsigned)text[5];
+			if (x < 0)	x += 256;
+			if (y < 0)	y += 256;
+			x -= 33;
+			y -= 33;
+			s = g_strdup_printf("ldown %d %d", x, y);
+			gnt_entry_set_text(entry, s);
+			g_free(s);
+		}
+		else if (strncmp(text + 1, "[M#", 3) == 0)
+			gnt_entry_set_text(entry, "up");
+		else
+			return FALSE;
+		return TRUE;
+	}
+	else
+		return TRUE;
+}
+
+int main()
+{
+	GntWidget *window, *entry;
+
+	gnt_init();
+
+	freopen(".error", "w", stderr);
+
+	window = gnt_hbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+
+	gnt_box_add_widget(GNT_BOX(window), gnt_label_new("Press any key: "));
+
+	entry = gnt_entry_new(NULL);
+	gnt_box_add_widget(GNT_BOX(window), entry);
+	g_signal_connect(G_OBJECT(entry), "key_pressed", G_CALLBACK(print_keycode), NULL);
+
+	gnt_widget_set_position(window, getmaxx(stdscr) / 2 - 12, getmaxy(stdscr) / 2 - 3);
+	gnt_widget_show(window);
+
+	gnt_main();
+	gnt_quit();
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test/menu.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,64 @@
+#include "gnt.h"
+#include "gntbox.h"
+#include "gntlabel.h"
+#include "gntmenu.h"
+#include "gntmenuitem.h"
+#include "gntwindow.h"
+
+void dothis(GntMenuItem *item, gpointer null)
+{
+	GntWidget *w = gnt_vbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(w), TRUE);
+	gnt_box_add_widget(GNT_BOX(w),
+			gnt_label_new("Callback to a menuitem"));
+	gnt_widget_show(w);
+}
+
+int main()
+{
+	freopen(".error", "w", stderr);
+	gnt_init();
+
+	GntWidget *menu = gnt_menu_new(GNT_MENU_TOPLEVEL);
+	GObject *item = gnt_menuitem_new("File");
+
+	gnt_menu_add_item(GNT_MENU(menu), GNT_MENUITEM(item));
+
+	item = gnt_menuitem_new("Edit");
+	gnt_menu_add_item(GNT_MENU(menu), GNT_MENUITEM(item));
+
+	item = gnt_menuitem_new("Help");
+	gnt_menu_add_item(GNT_MENU(menu), GNT_MENUITEM(item));
+
+	GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
+	gnt_menuitem_set_submenu(GNT_MENUITEM(item), GNT_MENU(sub));
+
+	item = gnt_menuitem_new("Online Help");
+	gnt_menu_add_item(GNT_MENU(sub), GNT_MENUITEM(item));
+
+	item = gnt_menuitem_new("About");
+	gnt_menu_add_item(GNT_MENU(sub), GNT_MENUITEM(item));
+
+	sub = gnt_menu_new(GNT_MENU_POPUP);
+	gnt_menuitem_set_submenu(GNT_MENUITEM(item), GNT_MENU(sub));
+
+	item = gnt_menuitem_new("Online Help");
+	gnt_menu_add_item(GNT_MENU(sub), GNT_MENUITEM(item));
+	gnt_menuitem_set_callback(GNT_MENUITEM(item), dothis, NULL);
+
+	gnt_screen_menu_show(menu);
+
+	GntWidget *win = gnt_window_new();
+	gnt_box_add_widget(GNT_BOX(win),
+		gnt_label_new("..."));
+	gnt_box_set_title(GNT_BOX(win), "Title");
+	gnt_window_set_menu(GNT_WINDOW(win), GNT_MENU(menu));
+	gnt_widget_show(win);
+
+	gnt_main();
+
+	gnt_quit();
+
+	return  0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test/multiwin.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,87 @@
+#include "gnt.h"
+#include "gntbutton.h"
+#include "gntentry.h"
+#include "gntkeys.h"
+#include "gntlabel.h"
+#include "gnttree.h"
+#include "gntbox.h"
+
+gboolean show(GntWidget *w)
+{
+	return FALSE;
+}
+
+int main()
+{
+#ifdef STANDALONE
+	freopen(".error", "w", stderr);
+	gnt_init();
+#endif
+
+	GntWidget *hbox, *tree, *box2;
+
+	hbox = gnt_box_new(FALSE, TRUE);
+	box2 = gnt_box_new(FALSE, TRUE);
+
+	gnt_widget_set_name(hbox, "hbox");
+	gnt_widget_set_name(box2, "box2");
+
+	tree = gnt_tree_new_with_columns(3);
+	GNT_WIDGET_SET_FLAGS(tree, GNT_WIDGET_NO_BORDER);
+	gnt_tree_set_column_titles(GNT_TREE(tree), "12345678901234567890", "column 2", "column3");
+	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
+	gnt_widget_set_name(tree, "tree");
+	gnt_box_add_widget(GNT_BOX(hbox), tree);
+
+	gnt_box_set_toplevel(GNT_BOX(hbox), TRUE);
+	gnt_box_set_title(GNT_BOX(hbox), "Testing the tree widget");
+
+	gnt_box_set_toplevel(GNT_BOX(box2), TRUE);
+	gnt_box_set_title(GNT_BOX(box2), "On top");
+
+	gnt_box_add_widget(GNT_BOX(box2), gnt_label_new("asdasd"));
+	gnt_box_add_widget(GNT_BOX(box2), gnt_entry_new(NULL));
+
+	gnt_widget_show(hbox);
+	gnt_widget_set_position(box2, 80, 40);
+	gnt_widget_show(box2);
+
+	gnt_tree_add_row_after(GNT_TREE(tree), "a",
+			gnt_tree_create_row(GNT_TREE(tree), "alaskdjfkashfashfah kfalkdhflsiafhlasf", " long text", "a2"), NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "c",
+			gnt_tree_create_row(GNT_TREE(tree), "casdgertqhyeqgasfeytwfga fg arf  agfwa ", " long text", "a2"), NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "d", gnt_tree_create_row(GNT_TREE(tree), "d", " long text", "a2"), NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "e", gnt_tree_create_row(GNT_TREE(tree), "e", " long text", "a2"), "a", NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "b", gnt_tree_create_row(GNT_TREE(tree), "b", "this is", "a2"), "d", NULL);
+
+	gnt_tree_add_choice(GNT_TREE(tree), "1", gnt_tree_create_row(GNT_TREE(tree), "1", " long text", "a2"), NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "2", gnt_tree_create_row(GNT_TREE(tree), "2", " long text", "a2"), NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "3", gnt_tree_create_row(GNT_TREE(tree), "3", " long text", "a2"), NULL, NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "4", gnt_tree_create_row(GNT_TREE(tree), "4", " long text", "a2"), "a", NULL);
+	gnt_tree_add_row_after(GNT_TREE(tree), "5", gnt_tree_create_row(GNT_TREE(tree), "5", " long text", "a2"), "d", NULL);
+
+	gnt_tree_add_row_after(GNT_TREE(tree), "6", gnt_tree_create_row(GNT_TREE(tree), "6", " long text", "a2"), "4", NULL);
+
+	int i;
+	for (i = 110; i < 430; i++)
+	{
+		char *s;
+		s = g_strdup_printf("%d", i); /* XXX: yes, leaking */
+		gnt_tree_add_row_after(GNT_TREE(tree), s, gnt_tree_create_row(GNT_TREE(tree), s, " long text", "a2"), "4", NULL);
+	}
+
+	gnt_tree_set_row_flags(GNT_TREE(tree), "e", GNT_TEXT_FLAG_DIM);
+
+	gnt_tree_set_selected(GNT_TREE(tree), "2");
+
+	g_timeout_add(5000, (GSourceFunc)show, box2);
+
+#ifdef STANDALONE
+	gnt_main();
+
+	gnt_quit();
+#endif
+
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test/tv.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,107 @@
+#include "gntbutton.h"
+#include "gnt.h"
+#include "gntkeys.h"
+#include "gnttree.h"
+#include "gntbox.h"
+#include "gntentry.h"
+#include "gnttextview.h"
+
+static gboolean
+key_pressed(GntWidget *w, const char *key, GntWidget *view)
+{
+	if (key[0] == '\r' && key[1] == 0)
+	{
+		gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view),
+				gnt_entry_get_text(GNT_ENTRY(w)),
+				GNT_TEXT_FLAG_UNDERLINE | GNT_TEXT_FLAG_HIGHLIGHT);
+		gnt_entry_add_to_history(GNT_ENTRY(w), gnt_entry_get_text(GNT_ENTRY(w)));
+		gnt_text_view_next_line(GNT_TEXT_VIEW(view));
+		gnt_entry_clear(GNT_ENTRY(w));
+		if (gnt_text_view_get_lines_below(GNT_TEXT_VIEW(view)) <= 1)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(view), 0);
+		gnt_entry_remove_suggest(GNT_ENTRY(w), "acb");
+
+		return TRUE;
+	}
+	else if (key[0] == 27)
+	{
+		if (strcmp(key, GNT_KEY_UP) == 0)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(view), -1);
+		else if (strcmp(key, GNT_KEY_DOWN) == 0)
+			gnt_text_view_scroll(GNT_TEXT_VIEW(view), 1);
+		else
+			return FALSE;
+		return TRUE;
+	}
+		
+	return FALSE;
+}
+
+int main()
+{
+	GntWidget *hbox, *entry, *view;
+
+#ifdef STANDALONE
+	freopen(".error", "w", stderr);
+
+	gnt_init();
+#endif
+
+	hbox = gnt_box_new(FALSE, TRUE);
+	gnt_widget_set_name(hbox, "hbox");
+	gnt_box_set_toplevel(GNT_BOX(hbox), TRUE);
+	gnt_box_set_fill(GNT_BOX(hbox), FALSE);
+	gnt_box_set_title(GNT_BOX(hbox), "Textview test");
+	gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
+
+	entry = gnt_entry_new(NULL);
+	gnt_widget_set_name(entry, "entry");
+	GNT_WIDGET_SET_FLAGS(entry, GNT_WIDGET_CAN_TAKE_FOCUS);
+
+	gnt_entry_set_word_suggest(GNT_ENTRY(entry), TRUE);
+	gnt_entry_set_always_suggest(GNT_ENTRY(entry), FALSE);
+	gnt_entry_add_suggest(GNT_ENTRY(entry), "a");
+	gnt_entry_add_suggest(GNT_ENTRY(entry), "ab");
+	gnt_entry_add_suggest(GNT_ENTRY(entry), "abe");
+	gnt_entry_add_suggest(GNT_ENTRY(entry), "abc");
+	gnt_entry_add_suggest(GNT_ENTRY(entry), "abcde");
+	gnt_entry_add_suggest(GNT_ENTRY(entry), "abcd");
+	gnt_entry_add_suggest(GNT_ENTRY(entry), "acb");
+
+	view = gnt_text_view_new();
+	gnt_widget_set_name(view, "view");
+
+	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);
+	gnt_box_add_widget(GNT_BOX(hbox), gnt_button_new("OK"));
+
+	gnt_widget_show(hbox);
+
+	gnt_entry_set_history_length(GNT_ENTRY(entry), -1);
+	g_signal_connect_after(G_OBJECT(entry), "key_pressed", G_CALLBACK(key_pressed), view);
+
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "\n", GNT_TEXT_FLAG_NORMAL);
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "plugins: ", GNT_TEXT_FLAG_BOLD);
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "this is the 1st line\n", GNT_TEXT_FLAG_NORMAL);
+
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "plugins: ", GNT_TEXT_FLAG_BOLD);
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "this is the 2nd line\n", GNT_TEXT_FLAG_NORMAL);
+
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "plugins: ", GNT_TEXT_FLAG_BOLD);
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "this is the 3rd line\n", GNT_TEXT_FLAG_NORMAL);
+
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "plugins: ", GNT_TEXT_FLAG_BOLD);
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "this is the 4th line\n", GNT_TEXT_FLAG_NORMAL);
+
+#ifdef STANDALONE
+	gnt_main();
+
+	gnt_quit();
+#endif
+
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test/wm.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,67 @@
+#include <gmodule.h>
+
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntentry.h>
+#include <gntlabel.h>
+
+static gboolean
+key_pressed(GntEntry *entry, const char *text, gpointer null)
+{
+	if (*text != '\r')
+		return FALSE;
+
+	{
+		const char *cmd;
+		void *handle;
+		void (*func)();
+
+		cmd = gnt_entry_get_text(entry);
+		handle = g_module_open(cmd, G_MODULE_BIND_LOCAL);
+		if (handle && g_module_symbol(handle, "main", (gpointer)&func))
+		{
+			char *argv[] = {cmd, NULL};
+			gnt_entry_clear(entry);
+			func(1, argv);
+		}
+		else
+		{
+			GntWidget *widget = gnt_vbox_new(FALSE);
+			gnt_box_set_toplevel(GNT_BOX(widget), TRUE);
+			gnt_box_set_title(GNT_BOX(widget), "Error");
+			gnt_box_add_widget(GNT_BOX(widget), gnt_label_new("Could not execute."));
+			gnt_box_add_widget(GNT_BOX(widget), gnt_label_new(g_module_error()));
+
+			gnt_widget_show(widget);
+		}
+	}
+	
+	return TRUE;
+}
+
+int main()
+{
+	GntWidget *window, *entry;
+
+	freopen(".error", "w", stderr);
+
+	gnt_init();
+
+	window = gnt_hbox_new(FALSE);
+
+	gnt_box_add_widget(GNT_BOX(window), gnt_label_new("Command"));
+
+	entry = gnt_entry_new(NULL);
+	g_signal_connect(G_OBJECT(entry), "key_pressed", G_CALLBACK(key_pressed), NULL);
+	gnt_box_add_widget(GNT_BOX(window), entry);
+
+	gnt_widget_set_position(window, 0, getmaxy(stdscr) - 2);
+	gnt_widget_show(window);
+
+	gnt_main();
+
+	gnt_quit();
+	
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/wms/Makefile.am	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,26 @@
+s_la_LDFLAGS             = -module -avoid-version
+
+plugin_LTLIBRARIES = \
+	s.la
+
+plugindir = $(libdir)/gaim
+
+s_la_SOURCES = s.c
+s_la_LIBADD =  \
+  $(GLIB_LIBS) \
+  $(top_builddir)/finch/libgnt/libgnt.la \
+  $(top_builddir)/libpurple/libpurple.la
+
+EXTRA_DIST = 
+
+AM_CPPFLAGS = \
+	-DDATADIR=\"$(datadir)\" \
+	-DVERSION=\"$(VERSION)\" \
+	-I$(top_srcdir)/libpurple \
+	-I$(top_srcdir)/finch \
+	-I$(top_srcdir)/finch/libgnt \
+	$(DEBUG_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	$(GNT_CFLAGS) \
+	$(PLUGIN_CFLAGS)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/wms/s.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,247 @@
+#include <string.h>
+#include <sys/types.h>
+
+#include "gnt.h"
+#include "gntbox.h"
+#include "gntmenu.h"
+#include "gntstyle.h"
+#include "gntwm.h"
+#include "gntwindow.h"
+#include "gntlabel.h"
+
+#include "blist.h"
+
+#define TYPE_S				(s_get_gtype())
+
+typedef struct _S
+{
+	GntWM inherit;
+} S;
+
+typedef struct _SClass
+{
+	GntWMClass inherit;
+} SClass;
+
+GType s_get_gtype(void);
+void gntwm_init(GntWM **wm);
+
+static void (*org_new_window)(GntWM *wm, GntWidget *win);
+
+static void
+envelope_buddylist(GntWidget *win)
+{
+	int w, h;
+	gnt_widget_get_size(win, &w, &h);
+	wresize(win->window, h, w + 1);
+	mvwvline(win->window, 0, w, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), h);
+	touchwin(win->window);
+}
+
+static void
+envelope_normal_window(GntWidget *win)
+{
+	int w, h;
+
+	if (GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_NO_BORDER | GNT_WIDGET_TRANSIENT))
+		return;
+
+	gnt_widget_get_size(win, &w, &h);
+	wbkgdset(win->window, ' ' | COLOR_PAIR(GNT_COLOR_NORMAL));
+	mvwprintw(win->window, 0, w - 4, "[X]");
+}
+
+static void
+s_decorate_window(GntWM *wm, GntWidget *win)
+{
+	const char *name;
+
+	name = gnt_widget_get_name(win);
+	if (name && strcmp(name, "buddylist") == 0) {
+		envelope_buddylist(win);
+	} else {
+		envelope_normal_window(win);
+	}
+}
+
+static void
+s_window_update(GntWM *wm, GntNode *node)
+{
+	s_decorate_window(wm, node->me);
+}
+
+static void
+s_new_window(GntWM *wm, GntWidget *win)
+{
+	int x, y, w, h;
+	int maxx, maxy;
+	const char *name;
+	gboolean blist = FALSE;
+
+	if (!GNT_IS_MENU(win)) {
+		getmaxyx(stdscr, maxy, maxx);
+
+		gnt_widget_get_position(win, &x, &y);
+		gnt_widget_get_size(win, &w, &h);
+
+		name = gnt_widget_get_name(win);
+
+		if (name && strcmp(name, "buddylist") == 0) {
+			/* The buddylist doesn't have no border nor nothing! */
+			x = 0;
+			y = 0;
+			h = maxy - 1;
+			blist = TRUE;
+
+			gnt_box_set_toplevel(GNT_BOX(win), FALSE);
+			GNT_WIDGET_SET_FLAGS(win, GNT_WIDGET_CAN_TAKE_FOCUS);
+
+			gnt_widget_set_position(win, x, y);
+			mvwin(win->window, y, x);
+
+			gnt_widget_set_size(win, -1, h + 2);  /* XXX: Why is the +2 needed here? -- sadrul */
+		} else if (!GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_TRANSIENT)) {
+			const char *title = GNT_BOX(win)->title;
+			if (title == NULL || !g_hash_table_lookup(wm->positions, title)) {
+				/* In the middle of the screen */
+				x = (maxx - w) / 2;
+				y = (maxy - h) / 2;
+
+				gnt_widget_set_position(win, x, y);
+				mvwin(win->window, y, x);
+			}
+		}
+	}
+	org_new_window(wm, win);
+
+	if (blist)
+		gnt_wm_raise_window(wm, win);
+}
+
+static GntWidget *
+find_widget(GntWM *wm, const char *wname)
+{
+	const GList *iter = wm->list;
+	for (; iter; iter = iter->next) {
+		GntWidget *widget = iter->data;
+		const char *name = gnt_widget_get_name(widget);
+		if (name && strcmp(name, wname) == 0) {
+			return widget;
+		}
+	}
+	return NULL;
+}
+
+static gboolean
+s_mouse_clicked(GntWM *wm, GntMouseEvent event, int cx, int cy, GntWidget *widget)
+{
+	int x, y, w, h;
+
+	if (!widget)
+		return FALSE;
+		/* This might be a place to bring up a context menu */
+	
+	if (event != GNT_LEFT_MOUSE_DOWN ||
+			GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER))
+		return FALSE;
+	
+	gnt_widget_get_position(widget, &x, &y);
+	gnt_widget_get_size(widget, &w, &h);
+
+	if (cy == y && cx == x + w - 3) {
+		gnt_widget_destroy(widget);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+toggle_buddylist(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	GntWidget *blist = find_widget(wm, "buddylist");
+	if (blist)
+		gnt_widget_destroy(blist);
+	else
+		gaim_blist_show();
+	return TRUE;
+}
+
+static gboolean
+toggle_clipboard(GntBindable *bindable, GList *n)
+{
+	static GntWidget *clip;
+	gchar *text;
+	int maxx, maxy;
+	if (clip) {
+		gnt_widget_destroy(clip);
+		clip = NULL;
+		return TRUE;
+	}
+	getmaxyx(stdscr, maxy, maxx);
+	text = gnt_get_clipboard_string();
+	clip = gnt_hwindow_new(FALSE);
+	GNT_WIDGET_SET_FLAGS(clip, GNT_WIDGET_TRANSIENT);
+	GNT_WIDGET_SET_FLAGS(clip, GNT_WIDGET_NO_BORDER);
+	gnt_box_set_pad(GNT_BOX(clip), 0);
+	gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(" "));
+	gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(text));
+	gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(" "));
+	gnt_widget_set_position(clip, 0, 0);
+	gnt_widget_draw(clip);
+	g_free(text);
+	return TRUE;
+}
+
+static void
+s_class_init(SClass *klass)
+{
+	GntWMClass *pclass = GNT_WM_CLASS(klass);
+
+	org_new_window = pclass->new_window;
+
+	pclass->new_window = s_new_window;
+	pclass->decorate_window = s_decorate_window;
+	pclass->window_update = s_window_update;
+	pclass->mouse_clicked = s_mouse_clicked;
+
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-buddylist",
+				toggle_buddylist, "\033" "b", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-clipboard",
+				toggle_clipboard, "\033" "C", NULL);
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+	GNTDEBUG;
+}
+
+void gntwm_init(GntWM **wm)
+{
+	*wm = g_object_new(TYPE_S, NULL);
+}
+
+GType s_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(SClass),
+			NULL,					/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)s_class_init,
+			NULL,
+			NULL,                   /* class_data		*/
+			sizeof(S),
+			0,                      /* n_preallocs		*/
+			NULL,	            /* instance_init	*/
+			NULL
+		};
+
+		type = g_type_register_static(GNT_TYPE_WM,
+									  "GntS",
+									  &info, 0);
+	}
+
+	return type;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/plugins/Makefile.am	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,51 @@
+gntgf_la_LDFLAGS      = -module -avoid-version
+gnthistory_la_LDFLAGS = -module -avoid-version
+gntlastlog_la_LDFLAGS    = -module -avoid-version
+
+if PLUGINS
+
+plugin_LTLIBRARIES = \
+	gntgf.la \
+	gnthistory.la \
+	gntlastlog.la
+
+plugindir = $(libdir)/gaim
+
+gntgf_la_SOURCES      = gntgf.c
+gnthistory_la_SOURCES = gnthistory.c
+gntlastlog_la_SOURCES = lastlog.c
+
+gntgf_la_CFLAGS = $(X11_CFLAGS)
+
+gntgf_la_LIBADD       = $(GLIB_LIBS) $(X11_LIBS) $(top_builddir)/finch/libgnt/libgnt.la
+gnthistory_la_LIBADD  = $(GLIB_LIBS)
+gntlastlog_la_LIBADD  = $(GLIB_LIBS)
+
+endif # PLUGINS
+
+EXTRA_DIST = 
+
+AM_CPPFLAGS = \
+	-DDATADIR=\"$(datadir)\" \
+	-DVERSION=\"$(VERSION)\" \
+	-I$(top_builddir)/libpurple \
+	-I$(top_srcdir)/libpurple \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/finch \
+	-I$(top_srcdir)/finch/libgnt \
+	$(DEBUG_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	$(GNT_CFLAGS) \
+	$(PLUGIN_CFLAGS)
+
+#
+# This part allows people to build their own plugins in here.
+# Yes, it's a mess.
+#
+SUFFIXES = .c .so
+.c.so:
+	$(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_srcdir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS)
+	$(LIBTOOL) --mode=link    $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS)
+	@rm -f tmp$@.lo tmp$@.o libtmp$@.la
+	@cp .libs/libtmp$@.so* $@
+	@rm -f .libs/libtmp$@.*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/plugins/gntclipboard.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,168 @@
+/**
+ * @file gntclipboard.c
+ *
+ * Copyright (C) 2007 Richard Nelson <wabz@whatsbeef.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "internal.h"
+#include <glib.h>
+
+#define PLUGIN_STATIC_NAME	"GntClipboard"
+
+#ifdef HAVE_X11
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#endif
+
+#include <sys/types.h>
+#include <signal.h>
+
+#include <glib.h>
+
+#include <plugin.h>
+#include <version.h>
+#include <debug.h>
+#include <gntwm.h>
+
+#include <gntplugin.h>
+
+static pid_t child = 0;
+
+static gulong sig_handle;
+
+static void
+set_clip(gchar *string)
+{
+#ifdef HAVE_X11
+	Window w;
+	XEvent e, respond;
+	XSelectionRequestEvent *req;
+	const char *ids;
+	Display *dpy = XOpenDisplay(NULL);
+
+	if (!dpy)
+		return;
+	ids = getenv("WINDOWID");
+	if (ids == NULL)
+		return;
+	w = atoi(ids);
+	XSetSelectionOwner(dpy, XA_PRIMARY, w, CurrentTime);
+	XFlush(dpy);
+	XSelectInput(dpy, w, StructureNotifyMask);
+	while (TRUE) {
+		XNextEvent(dpy, &e); /* this blocks. */
+		req = &e.xselectionrequest;
+		if (e.type == SelectionRequest) {
+			XChangeProperty(dpy,
+				req->requestor,
+				req->property,
+				XA_STRING,
+				8, PropModeReplace,
+				(unsigned char *)string,
+				strlen(string));
+			respond.xselection.property = req->property;
+			respond.xselection.type = SelectionNotify;
+			respond.xselection.display = req->display;
+			respond.xselection.requestor = req->requestor;
+			respond.xselection.selection = req->selection;
+			respond.xselection.target= req->target;
+			respond.xselection.time = req->time;
+			XSendEvent(dpy, req->requestor, 0, 0, &respond);
+			XFlush (dpy);
+		} else if (e.type == SelectionClear) {
+			return;
+		}
+	}
+#endif
+	return;
+}
+
+static void
+clipboard_changed(GntWM *wm, gchar *string)
+{
+#ifdef HAVE_X11
+	if (child) {
+		kill(child, SIGTERM);
+	}
+	if ((child = fork() == 0)) {
+		set_clip(string);
+		_exit(0);
+	}
+#endif
+}
+
+static gboolean
+plugin_load(GaimPlugin *plugin)
+{
+	if (!XOpenDisplay(NULL)) {
+		gaim_debug_warning("gntclipboard", "Couldn't find X display\n");
+		return FALSE;
+	}
+	if (!getenv("WINDOWID")) {
+		gaim_debug_warning("gntclipboard", "Couldn't find window\n");
+		return FALSE;
+	}
+	sig_handle = g_signal_connect(G_OBJECT(gnt_get_clipboard()), "clipboard_changed", G_CALLBACK(clipboard_changed), NULL);
+	return TRUE;
+}
+
+static gboolean
+plugin_unload(GaimPlugin *plugin)
+{
+	if (child) {
+		kill(child, SIGTERM);
+		child = 0;
+	}
+	g_signal_handler_disconnect(G_OBJECT(gnt_get_clipboard()), sig_handle);
+	return TRUE;
+}
+
+static GaimPluginInfo info =
+{
+	GAIM_PLUGIN_MAGIC,
+	GAIM_MAJOR_VERSION,
+	GAIM_MINOR_VERSION,
+	GAIM_PLUGIN_STANDARD,
+	GAIM_GNT_PLUGIN_TYPE,
+	0,
+	NULL,
+	GAIM_PRIORITY_DEFAULT,
+	"gntclipboard",
+	N_("GntClipboard"),
+	VERSION,
+	N_("Clipboard plugin"),
+	N_("When the gnt clipboard contents change, "
+		"the contents are made available to X, if possible."),
+	"Richard Nelson <wabz@whatsbeef.net>",
+	"http://gaim.sourceforge.net",
+	plugin_load,
+	plugin_unload,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static void
+init_plugin(GaimPlugin *plugin)
+{
+}
+
+GAIM_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/plugins/gntgf.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,390 @@
+/**
+ * @file gntgf.c Minimal toaster plugin in Gnt.
+ *
+ * Copyright (C) 2006 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "internal.h"
+
+#define PLUGIN_STATIC_NAME	"GntGf"
+
+#define PREFS_PREFIX          "/plugins/gnt/gntgf"
+#define PREFS_EVENT           PREFS_PREFIX "/events"
+#define PREFS_EVENT_SIGNONF   PREFS_EVENT "/signonf"
+#define PREFS_EVENT_IM_MSG    PREFS_EVENT "/immsg"
+#define PREFS_EVENT_CHAT_MSG  PREFS_EVENT "/chatmsg"
+#define PREFS_EVENT_CHAT_NICK PREFS_EVENT "/chatnick"
+#define PREFS_BEEP            PREFS_PREFIX "/beep"
+
+#define MAX_COLS	3
+
+#ifdef HAVE_X11
+#define PREFS_URGENT          PREFS_PREFIX "/urgent"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif
+
+#include <glib.h>
+
+#include <plugin.h>
+#include <version.h>
+#include <blist.h>
+#include <conversation.h>
+#include <debug.h>
+#include <util.h>
+
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntcheckbox.h>
+#include <gntlabel.h>
+#include <gnttree.h>
+
+#include <gntplugin.h>
+
+typedef struct
+{
+	GntWidget *window;
+	int timer;
+	int column;
+} GntToast;
+
+static GList *toasters;
+static int gpsy[MAX_COLS];
+static int gpsw[MAX_COLS];
+
+static void
+destroy_toaster(GntToast *toast)
+{
+	toasters = g_list_remove(toasters, toast);
+	gnt_widget_destroy(toast->window);
+	g_source_remove(toast->timer);
+	g_free(toast);
+}
+
+static gboolean
+remove_toaster(GntToast *toast)
+{
+	GList *iter;
+	int h;
+	int col;
+	int nwin[MAX_COLS];
+
+	gnt_widget_get_size(toast->window, NULL, &h);
+	gpsy[toast->column] -= h;
+	col = toast->column;
+
+	memset(&nwin, 0, sizeof(nwin));
+	destroy_toaster(toast);
+
+	for (iter = toasters; iter; iter = iter->next)
+	{
+		int x, y;
+		toast = iter->data;
+		nwin[toast->column]++;
+		if (toast->column != col) continue;
+		gnt_widget_get_position(toast->window, &x, &y);
+		y += h;
+		gnt_screen_move_widget(toast->window, x, y);
+	}
+
+	if (nwin[col] == 0)
+		gpsw[col] = 0;
+
+	return FALSE;
+}
+
+#ifdef HAVE_X11
+static void
+urgent()
+{
+	/* This is from deryni/tuomov's urgent_test.c */
+	Display *dpy;
+	Window id;
+	const char *ids;
+	XWMHints *hints;
+
+	ids = getenv("WINDOWID");
+	if (ids == NULL)
+		return;
+	
+	id = atoi(ids);
+
+	dpy = XOpenDisplay(NULL);
+	if (dpy == NULL)
+		return;
+
+	hints = XGetWMHints(dpy, id);
+	hints->flags|=XUrgencyHint;
+	XSetWMHints(dpy, id, hints);
+
+	XFlush(dpy);
+	XCloseDisplay(dpy);
+}
+#endif
+
+static void
+notify(const char *fmt, ...)
+{
+	GntWidget *window;
+	GntToast *toast;
+	char *str;
+	int h, w, i;
+	va_list args;
+
+	if (gaim_prefs_get_bool(PREFS_BEEP))
+		beep();
+#ifdef HAVE_X11
+	if (gaim_prefs_get_bool(PREFS_URGENT))
+		urgent();
+#endif
+
+	window = gnt_vbox_new(FALSE);
+	GNT_WIDGET_SET_FLAGS(window, GNT_WIDGET_TRANSIENT);
+	GNT_WIDGET_UNSET_FLAGS(window, GNT_WIDGET_NO_BORDER);
+
+	va_start(args, fmt);
+	str = g_strdup_vprintf(fmt, args);
+	va_end(args);
+
+	gnt_box_add_widget(GNT_BOX(window),
+			gnt_label_new_with_format(str, GNT_TEXT_FLAG_HIGHLIGHT));
+
+	g_free(str);
+	gnt_widget_size_request(window);
+	gnt_widget_get_size(window, &w, &h);
+	for (i = 0; i < MAX_COLS && gpsy[i] + h >= getmaxy(stdscr) ; ++i)
+		;
+	if (i >= MAX_COLS) {
+		gaim_debug_warning("GntGf", "Dude, that's way too many popups\n");
+		gnt_widget_destroy(window);
+		return;
+	}
+
+	toast = g_new0(GntToast, 1);
+	toast->window = window;
+	toast->column = i;
+	gpsy[i] += h;
+	if (w > gpsw[i]) {
+		if (i == 0)
+			gpsw[i] = w;
+		else
+			gpsw[i] = gpsw[i - 1] + w + 1;
+	}
+
+	if (i == 0 || (w + gpsw[i - 1] >= getmaxx(stdscr))) {
+		/* if it's going to be too far left, overlap. */
+		gnt_widget_set_position(window, getmaxx(stdscr) - w - 1,
+				getmaxy(stdscr) - gpsy[i] - 1);
+	} else {
+		gnt_widget_set_position(window, getmaxx(stdscr) - gpsw[i - 1] - w - 1,
+				getmaxy(stdscr) - gpsy[i] - 1);
+	}
+	gnt_widget_draw(window);
+
+	toast->timer = g_timeout_add(4000, (GSourceFunc)remove_toaster, toast);
+	toasters = g_list_prepend(toasters, toast);
+}
+
+static void
+buddy_signed_on(GaimBuddy *buddy, gpointer null)
+{
+	if (gaim_prefs_get_bool(PREFS_EVENT_SIGNONF))
+		notify(_("%s just signed on"), gaim_buddy_get_alias(buddy));
+}
+
+static void
+buddy_signed_off(GaimBuddy *buddy, gpointer null)
+{
+	if (gaim_prefs_get_bool(PREFS_EVENT_SIGNONF))
+		notify(_("%s just signed off"), gaim_buddy_get_alias(buddy));
+}
+
+static void
+received_im_msg(GaimAccount *account, const char *sender, const char *msg,
+		GaimConversation *conv, GaimMessageFlags flags, gpointer null)
+{
+	if (gaim_prefs_get_bool(PREFS_EVENT_IM_MSG))
+		notify(_("%s sent you a message"), sender);
+}
+
+static void
+received_chat_msg(GaimAccount *account, const char *sender, const char *msg,
+		GaimConversation *conv, GaimMessageFlags flags, gpointer null)
+{
+	const char *nick;
+
+	if (flags & GAIM_MESSAGE_WHISPER)
+		return;
+	
+	nick = GAIM_CONV_CHAT(conv)->nick;
+
+	if (g_utf8_collate(sender, nick) == 0)
+		return;
+
+	if (gaim_prefs_get_bool(PREFS_EVENT_CHAT_NICK) &&
+			(gaim_utf8_has_word(msg, nick)))
+		notify(_("%s said your nick in %s"), sender, gaim_conversation_get_name(conv));
+	else if (gaim_prefs_get_bool(PREFS_EVENT_CHAT_MSG))
+		notify(_("%s sent a message in %s"), sender, gaim_conversation_get_name(conv));
+}
+
+static gboolean
+plugin_load(GaimPlugin *plugin)
+{
+	gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-on", plugin,
+			GAIM_CALLBACK(buddy_signed_on), NULL);
+	gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-off", plugin,
+			GAIM_CALLBACK(buddy_signed_off), NULL);
+	gaim_signal_connect(gaim_conversations_get_handle(), "received-im-msg", plugin,
+			GAIM_CALLBACK(received_im_msg), NULL);
+	gaim_signal_connect(gaim_conversations_get_handle(), "received-chat-msg", plugin,
+			GAIM_CALLBACK(received_chat_msg), NULL);
+
+	memset(&gpsy, 0, sizeof(gpsy));
+	memset(&gpsw, 0, sizeof(gpsw));
+
+	return TRUE;
+}
+
+static gboolean
+plugin_unload(GaimPlugin *plugin)
+{
+	while (toasters)
+	{
+		GntToast *toast = toasters->data;
+		destroy_toaster(toast);
+	}
+	return TRUE;
+}
+
+static struct
+{
+	char *pref;
+	char *display;
+} prefs[] =
+{
+	{PREFS_EVENT_SIGNONF, N_("Buddy signs on/off")},
+	{PREFS_EVENT_IM_MSG, N_("You receive an IM")},
+	{PREFS_EVENT_CHAT_MSG, N_("Someone speaks in a chat")},
+	{PREFS_EVENT_CHAT_NICK, N_("Someone says your name in a chat")},
+	{NULL, NULL}
+};
+
+static void
+pref_toggled(GntTree *tree, char *key, gpointer null)
+{
+	gaim_prefs_set_bool(key, gnt_tree_get_choice(tree, key));
+}
+
+static void
+toggle_option(GntCheckBox *check, gpointer str)
+{
+	gaim_prefs_set_bool(str, gnt_check_box_get_checked(check));
+}
+
+static GntWidget *
+config_frame()
+{
+	GntWidget *window, *tree, *check;
+	int i;
+
+	window = gnt_vbox_new(FALSE);
+	gnt_box_set_pad(GNT_BOX(window), 0);
+	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
+	gnt_box_set_fill(GNT_BOX(window), TRUE);
+
+	gnt_box_add_widget(GNT_BOX(window),
+			gnt_label_new(_("Notify with a toaster when")));
+
+	tree = gnt_tree_new();
+	gnt_box_add_widget(GNT_BOX(window), tree);
+
+	for (i = 0; prefs[i].pref; i++)
+	{
+		gnt_tree_add_choice(GNT_TREE(tree), prefs[i].pref,
+				gnt_tree_create_row(GNT_TREE(tree), prefs[i].display), NULL, NULL);
+		gnt_tree_set_choice(GNT_TREE(tree), prefs[i].pref,
+				gaim_prefs_get_bool(prefs[i].pref));
+	}
+	gnt_tree_set_col_width(GNT_TREE(tree), 0, 40);
+	g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(pref_toggled), NULL);
+
+	check = gnt_check_box_new(_("Beep too!"));
+	gnt_check_box_set_checked(GNT_CHECK_BOX(check), gaim_prefs_get_bool(PREFS_BEEP));
+	g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(toggle_option), PREFS_BEEP);
+	gnt_box_add_widget(GNT_BOX(window), check);
+
+#ifdef HAVE_X11
+	check = gnt_check_box_new(_("Set URGENT for the terminal window."));
+	gnt_check_box_set_checked(GNT_CHECK_BOX(check), gaim_prefs_get_bool(PREFS_URGENT));
+	g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(toggle_option), PREFS_URGENT);
+	gnt_box_add_widget(GNT_BOX(window), check);
+#endif
+
+	return window;
+}
+
+static GaimPluginInfo info =
+{
+	GAIM_PLUGIN_MAGIC,
+	GAIM_MAJOR_VERSION,
+	GAIM_MINOR_VERSION,
+	GAIM_PLUGIN_STANDARD,
+	GAIM_GNT_PLUGIN_TYPE,
+	0,
+	NULL,
+	GAIM_PRIORITY_DEFAULT,
+	"gntgf",
+	N_("GntGf"),
+	VERSION,
+	N_("Toaster plugin"),
+	N_("Toaster plugin"),
+	"Sadrul H Chowdhury <sadrul@users.sourceforge.net>",
+	"http://gaim.sourceforge.net",
+	plugin_load,
+	plugin_unload,
+	NULL,
+	config_frame,
+	NULL,
+	NULL,
+	NULL
+};
+
+static void
+init_plugin(GaimPlugin *plugin)
+{
+	gaim_prefs_add_none("/plugins");
+	gaim_prefs_add_none("/plugins/gnt");
+	
+	gaim_prefs_add_none("/plugins/gnt/gntgf");
+	gaim_prefs_add_none(PREFS_EVENT);
+
+	gaim_prefs_add_bool(PREFS_EVENT_SIGNONF, TRUE);
+	gaim_prefs_add_bool(PREFS_EVENT_IM_MSG, TRUE);
+	gaim_prefs_add_bool(PREFS_EVENT_CHAT_MSG, TRUE);
+	gaim_prefs_add_bool(PREFS_EVENT_CHAT_NICK, TRUE);
+
+	gaim_prefs_add_bool(PREFS_BEEP, TRUE);
+#ifdef HAVE_X11
+	gaim_prefs_add_bool(PREFS_URGENT, FALSE);
+#endif
+}
+
+GAIM_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/plugins/gnthistory.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,202 @@
+/**
+ * @file gnthistory.c Show log from previous conversation
+ *
+ * Copyright (C) 2006 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Ripped from gtk/plugins/history.c */
+
+#include "internal.h"
+
+#include "conversation.h"
+#include "debug.h"
+#include "log.h"
+#include "notify.h"
+#include "prefs.h"
+#include "signals.h"
+#include "util.h"
+#include "version.h"
+
+#include "gntplugin.h"
+
+#define HISTORY_PLUGIN_ID "gnt-history"
+
+#define HISTORY_SIZE (4 * 1024)
+
+static void historize(GaimConversation *c)
+{
+	GaimAccount *account = gaim_conversation_get_account(c);
+	const char *name = gaim_conversation_get_name(c);
+	GaimConversationType convtype;
+	GList *logs = NULL;
+	const char *alias = name;
+	GaimLogReadFlags flags;
+	char *history;
+	char *header;
+	GaimMessageFlags mflag;
+
+	convtype = gaim_conversation_get_type(c);
+	if (convtype == GAIM_CONV_TYPE_IM)
+	{
+		GSList *buddies;
+		GSList *cur;
+
+		/* If we're not logging, don't show anything.
+		 * Otherwise, we might show a very old log. */
+		if (!gaim_prefs_get_bool("/core/logging/log_ims"))
+			return;
+
+		/* Find buddies for this conversation. */
+	        buddies = gaim_find_buddies(account, name);
+
+		/* If we found at least one buddy, save the first buddy's alias. */
+		if (buddies != NULL)
+			alias = gaim_buddy_get_contact_alias((GaimBuddy *)buddies->data);
+
+	        for (cur = buddies; cur != NULL; cur = cur->next)
+	        {
+	                GaimBlistNode *node = cur->data;
+	                if ((node != NULL) && ((node->prev != NULL) || (node->next != NULL)))
+	                {
+				GaimBlistNode *node2;
+
+				alias = gaim_buddy_get_contact_alias((GaimBuddy *)node);
+
+				/* We've found a buddy that matches this conversation.  It's part of a
+				 * GaimContact with more than one GaimBuddy.  Loop through the GaimBuddies
+				 * in the contact and get all the logs. */
+				for (node2 = node->parent->child ; node2 != NULL ; node2 = node2->next)
+				{
+					logs = g_list_concat(
+						gaim_log_get_logs(GAIM_LOG_IM,
+							gaim_buddy_get_name((GaimBuddy *)node2),
+							gaim_buddy_get_account((GaimBuddy *)node2)),
+						logs);
+				}
+				break;
+	                }
+	        }
+	        g_slist_free(buddies);
+
+		if (logs == NULL)
+			logs = gaim_log_get_logs(GAIM_LOG_IM, name, account);
+		else
+			logs = g_list_sort(logs, gaim_log_compare);
+	}
+	else if (convtype == GAIM_CONV_TYPE_CHAT)
+	{
+		/* If we're not logging, don't show anything.
+		 * Otherwise, we might show a very old log. */
+		if (!gaim_prefs_get_bool("/core/logging/log_chats"))
+			return;
+
+		logs = gaim_log_get_logs(GAIM_LOG_CHAT, name, account);
+	}
+
+	if (logs == NULL)
+		return;
+
+	mflag = GAIM_MESSAGE_NO_LOG | GAIM_MESSAGE_SYSTEM | GAIM_MESSAGE_DELAYED;
+	history = gaim_log_read((GaimLog*)logs->data, &flags);
+
+	header = g_strdup_printf(_("<b>Conversation with %s on %s:</b><br>"), alias,
+							 gaim_date_format_full(localtime(&((GaimLog *)logs->data)->time)));
+	gaim_conversation_write(c, "", header, mflag, time(NULL));
+	g_free(header);
+
+	if (flags & GAIM_LOG_READ_NO_NEWLINE)
+		gaim_str_strip_char(history, '\n');
+	gaim_conversation_write(c, "", history, mflag, time(NULL));
+	g_free(history);
+
+	gaim_conversation_write(c, "", "<hr>", mflag, time(NULL));
+
+	g_list_foreach(logs, (GFunc)gaim_log_free, NULL);
+	g_list_free(logs);
+}
+
+static void
+history_prefs_check(GaimPlugin *plugin)
+{
+	if (!gaim_prefs_get_bool("/core/logging/log_ims") &&
+	    !gaim_prefs_get_bool("/core/logging/log_chats"))
+	{
+		gaim_notify_warning(plugin, NULL, _("History Plugin Requires Logging"),
+							_("Logging can be enabled from Tools -> Preferences -> Logging.\n\n"
+							  "Enabling logs for instant messages and/or chats will activate "
+							  "history for the same conversation type(s)."));
+	}
+}
+
+static void history_prefs_cb(const char *name, GaimPrefType type,
+							 gconstpointer val, gpointer data)
+{
+	history_prefs_check((GaimPlugin *)data);
+}
+
+static gboolean
+plugin_load(GaimPlugin *plugin)
+{
+	gaim_signal_connect(gaim_conversations_get_handle(),
+						"conversation-created",
+						plugin, GAIM_CALLBACK(historize), NULL);
+
+	gaim_prefs_connect_callback(plugin, "/core/logging/log_ims",
+								history_prefs_cb, plugin);
+	gaim_prefs_connect_callback(plugin, "/core/logging/log_chats",
+								history_prefs_cb, plugin);
+
+	history_prefs_check(plugin);
+
+	return TRUE;
+}
+
+static GaimPluginInfo info =
+{
+	GAIM_PLUGIN_MAGIC,
+	GAIM_MAJOR_VERSION,
+	GAIM_MINOR_VERSION,
+	GAIM_PLUGIN_STANDARD,
+	NULL,
+	0,
+	NULL,
+	GAIM_PRIORITY_DEFAULT,
+	HISTORY_PLUGIN_ID,
+	N_("GntHistory"),
+	VERSION,
+	N_("Shows recently logged conversations in new conversations."),
+	N_("When a new conversation is opened this plugin will insert "
+	   "the last conversation into the current conversation."),
+	"Sean Egan <seanegan@gmail.com>\n"
+	"Sadrul H Chowdhury <sadrul@users.sourceforge.net>",
+	GAIM_WEBSITE,
+	plugin_load,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static void
+init_plugin(GaimPlugin *plugin)
+{
+}
+
+GAIM_INIT_PLUGIN(gnthistory, init_plugin, info)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/plugins/lastlog.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,142 @@
+/**
+ * @file lastlog.c Lastlog plugin for gaim-text.
+ *
+ * Copyright (C) 2006 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#define PLUGIN_STATIC_NAME	"GntLastlog"
+
+#include "internal.h"
+
+#include <plugin.h>
+#include <version.h>
+
+#include <cmds.h>
+
+#include <gnt.h>
+#include <gnttextview.h>
+#include <gntwindow.h>
+
+#include <gntconv.h>
+#include <gntplugin.h>
+
+static GaimCmdId cmd;
+
+static gboolean
+window_kpress_cb(GntWidget *wid, const char *key, GntTextView *view)
+{
+	if (key[0] == 27)
+	{
+		if (strcmp(key, GNT_KEY_DOWN) == 0)
+			gnt_text_view_scroll(view, 1);
+		else if (strcmp(key, GNT_KEY_UP) == 0)
+			gnt_text_view_scroll(view, -1);
+		else if (strcmp(key, GNT_KEY_PGDOWN) == 0)
+			gnt_text_view_scroll(view, wid->priv.height - 2);
+		else if (strcmp(key, GNT_KEY_PGUP) == 0)
+			gnt_text_view_scroll(view, -(wid->priv.height - 2));
+		else
+			return FALSE;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static GaimCmdRet
+lastlog_cb(GaimConversation *conv, const char *cmd, char **args, char **error, gpointer null)
+{
+	FinchConv *ggconv = conv->ui_data;
+	char **strings = g_strsplit(GNT_TEXT_VIEW(ggconv->tv)->string->str, "\n", 0);
+	GntWidget *win, *tv;
+	int i, j;
+
+	win = gnt_window_new();
+	gnt_box_set_title(GNT_BOX(win), _("Lastlog"));
+
+	tv = gnt_text_view_new();
+	gnt_box_add_widget(GNT_BOX(win), tv);
+
+	gnt_widget_show(win);
+
+	for (i = 0; strings[i]; i++) {
+		if (strstr(strings[i], args[0]) != NULL) {
+			char **finds = g_strsplit(strings[i], args[0], 0);
+			for (j = 0; finds[j]; j++) {
+				if (j)
+					gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(tv), args[0], GNT_TEXT_FLAG_BOLD);
+				gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(tv), finds[j], GNT_TEXT_FLAG_NORMAL);
+			}
+			g_strfreev(finds);
+			gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(tv), "\n", GNT_TEXT_FLAG_NORMAL);
+		}
+	}
+
+	g_signal_connect(G_OBJECT(win), "key_pressed", G_CALLBACK(window_kpress_cb), tv);
+	g_strfreev(strings);
+	return GAIM_CMD_STATUS_OK;
+}
+
+static gboolean
+plugin_load(GaimPlugin *plugin)
+{
+	cmd = gaim_cmd_register("lastlog", "s", GAIM_CMD_P_DEFAULT,
+			GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM, NULL,
+			lastlog_cb, _("lastlog: Searches for a substring in the backlog."), NULL);
+	return TRUE;
+}
+
+static gboolean
+plugin_unload(GaimPlugin *plugin)
+{
+	gaim_cmd_unregister(cmd);
+	return TRUE;
+}
+
+static GaimPluginInfo info =
+{
+	GAIM_PLUGIN_MAGIC,
+	GAIM_MAJOR_VERSION,
+	GAIM_MINOR_VERSION,
+	GAIM_PLUGIN_STANDARD,
+	GAIM_GNT_PLUGIN_TYPE,
+	0,
+	NULL,
+	GAIM_PRIORITY_DEFAULT,
+	"gntlastlog",
+	N_("GntLastlog"),
+	VERSION,
+	N_("Lastlog plugin."),
+	N_("Lastlog plugin."),
+	"Sadrul H Chowdhury <sadrul@users.sourceforge.net>",
+	"http://gaim.sourceforge.net",
+	plugin_load,
+	plugin_unload,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static void
+init_plugin(GaimPlugin *plugin)
+{
+}
+
+GAIM_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
+
--- a/po/ta.po	Sun Mar 18 18:17:14 2007 +0000
+++ b/po/ta.po	Sun Mar 18 19:38:15 2007 +0000
@@ -8981,10 +8981,10 @@
 
 #: ../src/protocols/oscar/oscar.c:4793
 #, c-format
-msgid ""
-"The user %u wants to add %s to their buddy list for the following reason:\n"
-"%s"
-msgstr "பயனர் %u %s ஐ தன் நண்பர் பட்டியலில் பின்வரும் காரணத்திற்காக சேர்க்க விரும்புகிறார்.:\n"
+#msgid ""
+#"The user %u wants to add %s to their buddy list for the following reason:\n"
+#"%s"
+#msgstr "பயனர் %u %s ஐ தன் நண்பர் பட்டியலில் பின்வரும் காரணத்திற்காக சேர்க்க விரும்புகிறார்.:\n"
 
 #: ../src/protocols/oscar/oscar.c:4803
 #: ../src/protocols/oscar/oscar.c:7480