summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorBerke Viktor <bviktor@hexchat.org>2012-07-11 19:46:46 +0200
committerBerke Viktor <bviktor@hexchat.org>2012-07-11 19:46:46 +0200
commit1ea726a91809340451c7a05ede34e7be00ba7863 (patch)
tree936bb6fce5c26b3876a7324ec82ee0bb232875d7 /src
parentd81619cca95831e2fd444d71cd078201f3db0e39 (diff)
parent9d9c24c8d347aa44efbd63e8f8c8dfb5b3cddedb (diff)
Merge branch 'wdk'
Diffstat (limited to 'src')
-rw-r--r--src/common/cfgfiles.c107
-rw-r--r--src/common/chanopt.c13
-rw-r--r--src/common/common.vcxproj157
-rw-r--r--src/common/common.vcxproj.filters194
-rw-r--r--src/common/common.vcxproj.user3
-rw-r--r--src/common/ctcp.c22
-rw-r--r--src/common/dcc.c22
-rw-r--r--src/common/identd.c100
-rw-r--r--src/common/identd.h1
-rw-r--r--src/common/ignore.c5
-rw-r--r--src/common/inbound.c7
-rw-r--r--src/common/inet.h4
-rw-r--r--src/common/makefile.mak45
-rw-r--r--src/common/modes.c10
-rw-r--r--src/common/msproxy.c5
-rw-r--r--src/common/network.c5
-rw-r--r--src/common/notify.c5
-rw-r--r--src/common/outbound.c110
-rw-r--r--src/common/plugin-timer.c10
-rw-r--r--src/common/plugin.c273
-rw-r--r--src/common/plugin.h15
-rw-r--r--src/common/proto-irc.c15
-rw-r--r--src/common/server.c75
-rw-r--r--src/common/servlist.c13
-rw-r--r--src/common/ssl.c2
-rw-r--r--src/common/text.c104
-rw-r--r--src/common/text.h3
-rw-r--r--src/common/thread.c33
-rw-r--r--src/common/thread.h10
-rw-r--r--src/common/url.c8
-rw-r--r--src/common/util.c195
-rw-r--r--src/common/util.h9
-rw-r--r--src/common/xchat-plugin.h47
-rw-r--r--src/common/xchat.c86
-rw-r--r--src/common/xchat.h33
-rw-r--r--src/dirent/dirent-win32.c199
-rw-r--r--src/dirent/dirent-win32.h28
-rw-r--r--src/dirent/dirent.vcxproj100
-rw-r--r--src/dirent/dirent.vcxproj.filters23
-rw-r--r--src/dirent/dirent.vcxproj.user3
-rw-r--r--src/fe-gtk/Makefile.am9
-rw-r--r--src/fe-gtk/about.c55
-rw-r--r--src/fe-gtk/banlist.c10
-rw-r--r--src/fe-gtk/chanlist.c5
-rw-r--r--src/fe-gtk/chanview-tabs.c8
-rw-r--r--src/fe-gtk/custom-list.c2
-rw-r--r--src/fe-gtk/editlist.c6
-rw-r--r--src/fe-gtk/fe-gtk.c95
-rw-r--r--src/fe-gtk/fe-gtk.h9
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj177
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj.filters216
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj.user3
-rw-r--r--src/fe-gtk/fkeys.c13
-rw-r--r--src/fe-gtk/gtkutil.c252
-rw-r--r--src/fe-gtk/joind.c5
-rw-r--r--src/fe-gtk/maingui.c100
-rw-r--r--src/fe-gtk/makefile.mak62
-rw-r--r--src/fe-gtk/menu.c94
-rw-r--r--src/fe-gtk/notifygui.c2
-rw-r--r--src/fe-gtk/palette.c8
-rw-r--r--src/fe-gtk/palette.h1
-rw-r--r--src/fe-gtk/plugin-tray.c50
-rw-r--r--src/fe-gtk/plugingui.c15
-rw-r--r--src/fe-gtk/rawlog.c5
-rw-r--r--src/fe-gtk/search.c122
-rw-r--r--src/fe-gtk/servlistgui.c22
-rw-r--r--src/fe-gtk/setup.c134
-rw-r--r--src/fe-gtk/sexy-iso-codes.c305
-rw-r--r--src/fe-gtk/sexy-iso-codes.h37
-rw-r--r--src/fe-gtk/sexy-marshal.c129
-rw-r--r--src/fe-gtk/sexy-marshal.h28
-rw-r--r--src/fe-gtk/sexy-spell-entry.c112
-rw-r--r--src/fe-gtk/typedef.h11
-rw-r--r--src/fe-gtk/xchat.exe.manifest22
-rw-r--r--src/fe-gtk/xchat.rc26
-rw-r--r--src/fe-gtk/xtext.c840
-rw-r--r--src/fe-gtk/xtext.h20
-rw-r--r--src/fe-text/fe-text.c473
-rw-r--r--src/fe-text/fe-text.h30
-rw-r--r--src/fe-text/fe-text.vcxproj108
-rw-r--r--src/fe-text/fe-text.vcxproj.filters23
-rw-r--r--src/fe-text/fe-text.vcxproj.user3
-rw-r--r--src/fe-text/makefile.mak20
-rw-r--r--src/gtk2-prefs/callbacks.cpp224
-rw-r--r--src/gtk2-prefs/callbacks.h71
-rw-r--r--src/gtk2-prefs/config.h59
-rw-r--r--src/gtk2-prefs/interface.cpp836
-rw-r--r--src/gtk2-prefs/interface.h5
-rw-r--r--src/gtk2-prefs/main.cpp616
-rw-r--r--src/gtk2-prefs/main.h32
-rw-r--r--src/gtk2-prefs/makefile.mak24
-rw-r--r--src/gtk2-prefs/support.cpp146
-rw-r--r--src/gtk2-prefs/support.h44
-rw-r--r--src/gtk2-prefs/sys_win32.h28
-rw-r--r--src/gtk2-prefs/win32util.cpp80
-rw-r--r--src/gtk2-prefs/win32util.h26
-rw-r--r--src/makefile.mak23
-rw-r--r--src/makeinc.skel.mak45
-rw-r--r--src/pixmaps/makefile.mak18
-rw-r--r--src/pixmaps/pixmaps.vcxproj110
-rw-r--r--src/pixmaps/pixmaps.vcxproj.filters41
-rw-r--r--src/pixmaps/pixmaps.vcxproj.user3
-rw-r--r--src/version-script6
-rw-r--r--src/version/version.c143
-rw-r--r--src/version/version.vcxproj103
-rw-r--r--src/version/version.vcxproj.filters14
-rw-r--r--src/version/version.vcxproj.user3
-rw-r--r--src/xtm/Main.Designer.cs316
-rw-r--r--src/xtm/Main.cs327
-rw-r--r--src/xtm/Main.resx287
-rw-r--r--src/xtm/Program.cs21
-rw-r--r--src/xtm/Properties/AssemblyInfo.cs38
-rw-r--r--src/xtm/Properties/Resources.Designer.cs63
-rw-r--r--src/xtm/Properties/Resources.resourcesbin0 -> 180 bytes
-rw-r--r--src/xtm/Properties/Resources.resx120
-rw-r--r--src/xtm/Properties/Settings.Designer.cs26
-rw-r--r--src/xtm/Properties/Settings.settings7
-rw-r--r--src/xtm/README.md7
-rw-r--r--src/xtm/Resources/xtm.icobin0 -> 9662 bytes
-rw-r--r--src/xtm/app.config3
-rw-r--r--src/xtm/xtm.csproj163
-rw-r--r--src/xtm/xtm.csproj.user13
122 files changed, 9027 insertions, 830 deletions
diff --git a/src/common/cfgfiles.c b/src/common/cfgfiles.c
index 83f50e37..111234e9 100644
--- a/src/common/cfgfiles.c
+++ b/src/common/cfgfiles.c
@@ -17,7 +17,6 @@
  */
 
 #include <fcntl.h>
-#include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -31,12 +30,15 @@
 #include "text.h"
 #include "xchatc.h"
 
-#ifdef WIN32
-#define XCHAT_DIR "X-Chat 2"
-#else
+#ifndef WIN32
+#include <unistd.h>
 #define XCHAT_DIR ".xchat2"
 #endif
+
 #define DEF_FONT "Monospace 9"
+#ifdef WIN32
+#define DEF_FONT_ALTER "Arial Unicode MS,Lucida Sans Unicode"
+#endif
 
 void
 list_addentry (GSList ** list, char *cmd, char *name)
@@ -82,11 +84,11 @@ list_load_from_data (GSList ** list, char *ibuf, int size)
 	{
 		if (*buf != '#')
 		{
-			if (!strncasecmp (buf, "NAME ", 5))
+			if (!g_ascii_strncasecmp (buf, "NAME ", 5))
 			{
 				safe_strcpy (name, buf + 5, sizeof (name));
 			}
-			else if (!strncasecmp (buf, "CMD ", 4))
+			else if (!g_ascii_strncasecmp (buf, "CMD ", 4))
 			{
 				safe_strcpy (cmd, buf + 4, sizeof (cmd));
 				if (*name)
@@ -152,7 +154,7 @@ list_delentry (GSList ** list, char *name)
 	while (alist)
 	{
 		pop = (struct popup *) alist->data;
-		if (!strcasecmp (name, pop->name))
+		if (!g_ascii_strcasecmp (name, pop->name))
 		{
 			*list = g_slist_remove (*list, pop);
 			free (pop);
@@ -166,9 +168,13 @@ list_delentry (GSList ** list, char *name)
 char *
 cfg_get_str (char *cfg, char *var, char *dest, int dest_len)
 {
+	char buffer[128];	/* should be plenty for a variable name */
+
+	sprintf (buffer, "%s ", var);	/* add one space, this way it works against var - var2 checks too */
+
 	while (1)
 	{
-		if (!strncasecmp (var, cfg, strlen (var)))
+		if (!g_ascii_strncasecmp (buffer, cfg, strlen (var) + 1))
 		{
 			char *value, t;
 			cfg += strlen (var);
@@ -308,12 +314,19 @@ get_xdir_fs (void)
 {
 	if (!xdir_fs)
 	{
-		char out[256];
+		if (portable_mode ())
+		{
+			xdir_fs = ".\\config";
+		}
+		else
+		{
+			char out[256];
 
-		if (!get_reg_str ("Software\\Microsoft\\Windows\\CurrentVersion\\"
-				"Explorer\\Shell Folders", "AppData", out, sizeof (out)))
-			return "./config";
-		xdir_fs = g_strdup_printf ("%s\\" XCHAT_DIR, out);
+			if (!get_reg_str ("Software\\Microsoft\\Windows\\CurrentVersion\\"
+					"Explorer\\Shell Folders", "AppData", out, sizeof (out)))
+				return "./config";
+			xdir_fs = g_strdup_printf ("%s\\" "X-Chat 2", out);
+		}
 	}
 	return xdir_fs;
 }
@@ -393,7 +406,9 @@ const struct prefs vars[] = {
 	{"dcc_blocksize", P_OFFINT (dcc_blocksize), TYPE_INT},
 	{"dcc_completed_dir", P_OFFSET (dcc_completed_dir), TYPE_STR},
 	{"dcc_dir", P_OFFSET (dccdir), TYPE_STR},
+#ifndef WIN32
 	{"dcc_fast_send", P_OFFINT (fastdccsend), TYPE_BOOL},
+#endif
 	{"dcc_global_max_get_cps", P_OFFINT (dcc_global_max_get_cps), TYPE_INT},
 	{"dcc_global_max_send_cps", P_OFFINT (dcc_global_max_send_cps), TYPE_INT},
 	{"dcc_ip", P_OFFSET (dcc_ip_str), TYPE_STR},
@@ -429,9 +444,14 @@ const struct prefs vars[] = {
 	{"gui_input_style", P_OFFINT (style_inputbox), TYPE_BOOL},
 	{"gui_join_dialog", P_OFFINT (gui_join_dialog), TYPE_BOOL},
 	{"gui_lagometer", P_OFFINT (lagometer), TYPE_INT},
+	{"gui_license", P_OFFSET (gui_license), TYPE_STR},
 	{"gui_mode_buttons", P_OFFINT (chanmodebuttons), TYPE_BOOL},
+#ifdef WIN32
+	{"gui_one_instance", P_OFFINT (gui_one_instance), TYPE_BOOL},
+#endif
 	{"gui_pane_left_size", P_OFFINT (gui_pane_left_size), TYPE_INT},
 	{"gui_pane_right_size", P_OFFINT (gui_pane_right_size), TYPE_INT},
+	{"gui_pane_right_size_min", P_OFFINT (gui_pane_right_size_min), TYPE_INT},
 	{"gui_quit_dialog", P_OFFINT (gui_quit_dialog), TYPE_BOOL},
 	{"gui_slist_fav", P_OFFINT (slist_fav), TYPE_INT},
 	{"gui_slist_select", P_OFFINT (slist_select), TYPE_INT},
@@ -536,6 +556,9 @@ const struct prefs vars[] = {
 
 	{"tab_chans", P_OFFINT (tabchannels), TYPE_BOOL},
 	{"tab_dialogs", P_OFFINT (privmsgtab), TYPE_BOOL},
+#ifdef WIN32
+	{"tab_icons", P_OFFINT (tab_icons), TYPE_BOOL},
+#endif
 	{"tab_layout", P_OFFINT (tab_layout), TYPE_INT},
 	{"tab_new_to_front", P_OFFINT (newtabstofront), TYPE_INT},
 	{"tab_notices", P_OFFINT (notices_tabs), TYPE_BOOL},
@@ -546,16 +569,35 @@ const struct prefs vars[] = {
 	{"tab_sort", P_OFFINT (tab_sort), TYPE_BOOL},
 	{"tab_trunc", P_OFFINT (truncchans), TYPE_INT},
 	{"tab_utils", P_OFFINT (windows_as_tabs), TYPE_BOOL},
+#ifdef WIN32
+	{"tab_xp", P_OFFINT (tab_xp), TYPE_BOOL},
+#endif
 
+	{"text_auto_copy_color", P_OFFINT (autocopy_color), TYPE_BOOL},	
+	{"text_auto_copy_stamp", P_OFFINT (autocopy_stamp), TYPE_BOOL},
+	{"text_auto_copy_text", P_OFFINT (autocopy_text), TYPE_BOOL},
 	{"text_background", P_OFFSET (background), TYPE_STR},
 	{"text_color_nicks", P_OFFINT (colorednicks), TYPE_BOOL},
+#ifdef WIN32
+	{"text_emoticons", P_OFFINT (emoticons), TYPE_BOOL},
+#endif
 	{"text_font", P_OFFSET (font_normal), TYPE_STR},
+#ifdef WIN32
+	{"text_font_main", P_OFFSET (font_main), TYPE_STR},
+	{"text_font_alternative", P_OFFSET (font_alternative), TYPE_STR},
+#endif
 	{"text_indent", P_OFFINT (indent_nicks), TYPE_BOOL},
 	{"text_max_indent", P_OFFINT (max_auto_indent), TYPE_INT},
 	{"text_max_lines", P_OFFINT (max_lines), TYPE_INT},
 	{"text_replay", P_OFFINT (text_replay), TYPE_BOOL},
+	{"text_search_case_match", P_OFFINT (text_search_case_match), TYPE_BOOL},
+	{"text_search_backward", P_OFFINT (text_search_backward), TYPE_BOOL},
+	{"text_search_highlight_all", P_OFFINT (text_search_highlight_all), TYPE_BOOL},
+	{"text_search_follow", P_OFFINT (text_search_follow), TYPE_BOOL},
+	{"text_search_regexp", P_OFFINT (text_search_regexp), TYPE_BOOL},
 	{"text_show_marker", P_OFFINT (show_marker), TYPE_BOOL},
 	{"text_show_sep", P_OFFINT (show_separator), TYPE_BOOL},
+	{"text_spell_langs", P_OFFSET (spell_langs), TYPE_STR},
 	{"text_stripcolor", P_OFFINT (stripcolor), TYPE_BOOL},
 	{"text_thin_sep", P_OFFINT (thin_separator), TYPE_BOOL},
 	{"text_tint_blue", P_OFFINT (tint_blue), TYPE_INT},
@@ -601,9 +643,11 @@ load_config (void)
 	if (!username)
 		username = "root";
 
-	realname = g_get_real_name ();
+	/* We hid Real name from the Network List, so don't use the user's name unnoticeably */
+	/* realname = g_get_real_name ();
 	if ((realname && realname[0] == 0) || !realname)
-		realname = username;
+		realname = username; */
+	realname = "realname";
 
 	username = convert_with_fallback (username, "username");
 	realname = convert_with_fallback (realname, "realname");
@@ -626,13 +670,16 @@ load_config (void)
 	prefs.indent_nicks = 1;
 	prefs.thin_separator = 1;
 	prefs._tabs_position = 2; /* 2 = left */
+#ifndef WIN32
 	prefs.fastdccsend = 1;
+#endif
 	prefs.wordwrap = 1;
 	prefs.autosave = 1;
 	prefs.autodialog = 1;
 	prefs.gui_input_spell = 1;
 	prefs.autoreconnect = 1;
 	prefs.recon_delay = 10;
+	prefs.autocopy_text = 1;
 	prefs.text_replay = 1;
 	prefs.tabchannels = 1;
 	prefs.tab_layout = 2;	/* 0=Tabs 1=Reserved 2=Tree */
@@ -676,6 +723,7 @@ load_config (void)
 	prefs.gui_tray = 1;
 	prefs.gui_pane_left_size = 100;
 	prefs.gui_pane_right_size = 100;
+	prefs.gui_pane_right_size_min = 80;
 	prefs.mainwindow_save = 1;
 	prefs.bantype = 2;
 	prefs.input_balloon_time = 20;
@@ -684,9 +732,12 @@ load_config (void)
 	prefs.autodccsend = 2;	/* browse mode */
 	prefs.url_grabber = 1;
 	prefs.url_grabber_limit = 0; /* 0 means unlimited for backcompat */
+	prefs.text_search_follow = 1;
 #ifdef WIN32
 	prefs.identd = 1;
 #endif
+	strcpy (prefs.gui_license, "");
+	strcpy (prefs.spell_langs, g_getenv ("LC_ALL") ? g_getenv ("LC_ALL") : "en_US");
 	strcpy (prefs.stamp_format, "[%H:%M] ");
 	strcpy (prefs.timestamp_log_format, "%b %d %H:%M:%S ");
 	strcpy (prefs.logmask, "%n-%c.log");
@@ -719,6 +770,10 @@ load_config (void)
 	strcpy (prefs.quitreason, _("Leaving"));
 	strcpy (prefs.partreason, prefs.quitreason);
 	strcpy (prefs.font_normal, DEF_FONT);
+#ifdef WIN32
+	strcpy (prefs.font_main, DEF_FONT);
+	strcpy (prefs.font_alternative, DEF_FONT_ALTER);
+#endif
 	strcpy (prefs.dnsprogram, "host");
 	strcpy (prefs.irc_no_hilight, "NickServ,ChanServ");
 
@@ -945,7 +1000,7 @@ cfg_get_bool (char *var)
 
 	do
 	{
-		if (!strcasecmp (var, vars[i].name))
+		if (!g_ascii_strcasecmp (var, vars[i].name))
 		{
 			return *((int *) &prefs + vars[i].offset);
 		}
@@ -968,27 +1023,27 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	int idx = 2;
 	char *var, *val;
 
-	if (strcasecmp (word[2], "-e") == 0)
+	if (g_ascii_strcasecmp (word[2], "-e") == 0)
 	{
 		idx++;
 		erase = TRUE;
 	}
 
 	/* turn a bit OFF */
-	if (strcasecmp (word[idx], "-off") == 0)
+	if (g_ascii_strcasecmp (word[idx], "-off") == 0)
 	{
 		idx++;
 		off = TRUE;
 	}
 
 	/* turn a bit ON */
-	if (strcasecmp (word[idx], "-or") == 0 || strcasecmp (word[idx], "-on") == 0)
+	if (g_ascii_strcasecmp (word[idx], "-or") == 0 || g_ascii_strcasecmp (word[idx], "-on") == 0)
 	{
 		idx++;
 		or = TRUE;
 	}
 
-	if (strcasecmp (word[idx], "-quiet") == 0)
+	if (g_ascii_strcasecmp (word[idx], "-quiet") == 0)
 	{
 		idx++;
 		quiet = TRUE;
@@ -1014,7 +1069,7 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		if (wild)
 			found = !match (var, vars[i].name);
 		else
-			found = strcasecmp (var, vars[i].name);
+			found = g_ascii_strcasecmp (var, vars[i].name);
 
 		if (found == 0)
 		{
@@ -1043,9 +1098,9 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 							*((int *) &prefs + vars[i].offset) = 1;
 						else
 							*((int *) &prefs + vars[i].offset) = 0;
-						if (!strcasecmp (val, "YES") || !strcasecmp (val, "ON"))
+						if (!g_ascii_strcasecmp (val, "YES") || !g_ascii_strcasecmp (val, "ON"))
 							*((int *) &prefs + vars[i].offset) = 1;
-						if (!strcasecmp (val, "NO") || !strcasecmp (val, "OFF"))
+						if (!g_ascii_strcasecmp (val, "NO") || !g_ascii_strcasecmp (val, "OFF"))
 							*((int *) &prefs + vars[i].offset) = 0;
 					} else
 					{
@@ -1071,7 +1126,13 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	while (vars[i].name);
 
 	if (!finds && !quiet)
+	{
 		PrintText (sess, "No such variable.\n");
+	}
+	else if (prefs.autosave && !save_config ())
+	{
+		PrintText (sess, "Error saving changes to disk.\n");
+	}
 
 	return TRUE;
 }
diff --git a/src/common/chanopt.c b/src/common/chanopt.c
index a4fd8faa..198ebe6c 100644
--- a/src/common/chanopt.c
+++ b/src/common/chanopt.c
@@ -3,12 +3,15 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "xchat.h"
 
 #include "cfgfiles.h"
@@ -81,9 +84,9 @@ chanopt_command (session *sess, char *tbuf, char *word[], char *word_eol[])
 
 	if (word[offset][0])
 	{
-		if (!strcasecmp (word[offset], "ON"))
+		if (!g_ascii_strcasecmp (word[offset], "ON"))
 			newval = 1;
-		else if (!strcasecmp (word[offset], "OFF"))
+		else if (!g_ascii_strcasecmp (word[offset], "OFF"))
 			newval = 0;
 		else if (word[offset][0] == 'u')
 			newval = SET_DEFAULT;
@@ -183,8 +186,8 @@ chanopt_find (char *network, char *channel, gboolean add_new)
 	for (list = chanopt_list; list; list = list->next)
 	{
 		co = list->data;
-		if (!strcasecmp (co->channel, channel) &&
-			 !strcasecmp (co->network, network))
+		if (!g_ascii_strcasecmp (co->channel, channel) &&
+			 !g_ascii_strcasecmp (co->network, network))
 			return co;
 	}
 
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
new file mode 100644
index 00000000..4e95c929
--- /dev/null
+++ b/src/common/common.vcxproj
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="..\..\config.h" />

+    <ClInclude Include="cfgfiles.h" />

+    <ClInclude Include="chanopt.h" />

+    <ClInclude Include="ctcp.h" />

+    <ClInclude Include="dcc.h" />

+    <ClInclude Include="fe.h" />

+    <ClInclude Include="history.h" />

+    <ClInclude Include="identd.h" />

+    <ClInclude Include="ignore.h" />

+    <ClInclude Include="inbound.h" />

+    <ClInclude Include="inet.h" />

+    <ClInclude Include="modes.h" />

+    <ClInclude Include="msproxy.h" />

+    <ClInclude Include="network.h" />

+    <ClInclude Include="notify.h" />

+    <ClInclude Include="outbound.h" />

+    <ClInclude Include="plugin-timer.h" />

+    <ClInclude Include="plugin.h" />

+    <ClInclude Include="proto-irc.h" />

+    <ClInclude Include="server.h" />

+    <ClInclude Include="servlist.h" />

+    <ClInclude Include="ssl.h" />

+    <ClInclude Include="text.h" />

+    <ClInclude Include="textenums.h" />

+    <ClInclude Include="textevents.h" />

+    <ClInclude Include="thread.h" />

+    <ClInclude Include="tree.h" />

+    <ClInclude Include="url.h" />

+    <ClInclude Include="userlist.h" />

+    <ClInclude Include="util.h" />

+    <ClInclude Include="xchat-plugin.h" />

+    <ClInclude Include="xchat.h" />

+    <ClInclude Include="xchatc.h" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="cfgfiles.c" />

+    <ClCompile Include="chanopt.c" />

+    <ClCompile Include="ctcp.c" />

+    <ClCompile Include="dcc.c" />

+    <ClCompile Include="history.c" />

+    <ClCompile Include="identd.c" />

+    <ClCompile Include="ignore.c" />

+    <ClCompile Include="inbound.c" />

+    <ClCompile Include="modes.c" />

+    <ClCompile Include="msproxy.c" />

+    <ClCompile Include="network.c" />

+    <ClCompile Include="notify.c" />

+    <ClCompile Include="outbound.c" />

+    <ClCompile Include="plugin-timer.c" />

+    <ClCompile Include="plugin.c" />

+    <ClCompile Include="proto-irc.c" />

+    <ClCompile Include="server.c" />

+    <ClCompile Include="servlist.c" />

+    <ClCompile Include="ssl.c" />

+    <ClCompile Include="text.c" />

+    <ClCompile Include="thread.c" />

+    <ClCompile Include="tree.c" />

+    <ClCompile Include="url.c" />

+    <ClCompile Include="userlist.c" />

+    <ClCompile Include="util.c" />

+    <ClCompile Include="xchat.c" />

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{87554B59-006C-4D94-9714-897B27067BA3}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>common</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level1</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level1</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;_WIN64;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters
new file mode 100644
index 00000000..afb66e63
--- /dev/null
+++ b/src/common/common.vcxproj.filters
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="cfgfiles.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="chanopt.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ctcp.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="dcc.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="fe.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="history.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="identd.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ignore.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="inbound.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="inet.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="modes.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="msproxy.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="network.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="notify.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="outbound.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="plugin.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="plugin-timer.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="proto-irc.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="server.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="servlist.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ssl.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="text.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="textenums.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="textevents.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="thread.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="tree.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="url.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="userlist.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="util.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="xchat.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="xchatc.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="xchat-plugin.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\..\config.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="cfgfiles.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="chanopt.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ctcp.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="dcc.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="history.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="identd.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ignore.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="inbound.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="modes.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="msproxy.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="network.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="notify.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="outbound.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="plugin.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="plugin-timer.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="proto-irc.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="server.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="servlist.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ssl.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="text.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="thread.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="tree.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="url.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="userlist.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="util.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="xchat.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/common/common.vcxproj.user b/src/common/common.vcxproj.user
new file mode 100644
index 00000000..695b5c78
--- /dev/null
+++ b/src/common/common.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+</Project>
\ No newline at end of file
diff --git a/src/common/ctcp.c b/src/common/ctcp.c
index 574cda79..36952db7 100644
--- a/src/common/ctcp.c
+++ b/src/common/ctcp.c
@@ -18,9 +18,12 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <unistd.h>
 #include <stdlib.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "xchat.h"
 #include "cfgfiles.h"
 #include "util.h"
@@ -70,7 +73,7 @@ ctcp_check (session *sess, char *nick, char *word[], char *word_eol[],
 	while (list)
 	{
 		pop = (struct popup *) list->data;
-		if (!strcasecmp (ctcp, pop->name))
+		if (!g_ascii_strcasecmp (ctcp, pop->name))
 		{
 			ctcp_reply (sess, nick, word, word_eol, pop->cmd);
 			ret = 1;
@@ -94,7 +97,7 @@ ctcp_handle (session *sess, char *to, char *nick, char *ip,
 			ctcp_offset = 3;
 
 	/* consider DCC to be different from other CTCPs */
-	if (!strncasecmp (msg, "DCC", 3))
+	if (!g_ascii_strncasecmp (msg, "DCC", 3))
 	{
 		/* but still let CTCP replies override it */
 		if (!ctcp_check (sess, nick, word, word_eol, word[4] + ctcp_offset))
@@ -107,7 +110,7 @@ ctcp_handle (session *sess, char *to, char *nick, char *ip,
 
 	/* consider ACTION to be different from other CTCPs. Check
       ignore as if it was a PRIV/CHAN. */
-	if (!strncasecmp (msg, "ACTION ", 7))
+	if (!g_ascii_strncasecmp (msg, "ACTION ", 7))
 	{
 		if (is_channel (serv, to))
 		{
@@ -132,16 +135,21 @@ ctcp_handle (session *sess, char *to, char *nick, char *ip,
 	if (ignore_check (word[1], IG_CTCP))
 		return;
 
-	if (!strcasecmp (msg, "VERSION") && !prefs.hidever)
+	if (!g_ascii_strcasecmp (msg, "VERSION") && !prefs.hidever)
 	{
-		snprintf (outbuf, sizeof (outbuf), "VERSION xchat "PACKAGE_VERSION" %s",
+#ifdef WIN32
+		snprintf (outbuf, sizeof (outbuf), "VERSION XChat-WDK "PACKAGE_VERSION" [x%d] / %s",
+					 get_cpu_arch (), get_cpu_str ());
+#else
+		snprintf (outbuf, sizeof (outbuf), "VERSION XChat-WDK "PACKAGE_VERSION" %s",
 					 get_cpu_str ());
+#endif
 		serv->p_nctcp (serv, nick, outbuf);
 	}
 
 	if (!ctcp_check (sess, nick, word, word_eol, word[4] + ctcp_offset))
 	{
-		if (!strncasecmp (msg, "SOUND", 5))
+		if (!g_ascii_strncasecmp (msg, "SOUND", 5))
 		{
 			po = strchr (word[5], '\001');
 			if (po)
diff --git a/src/common/dcc.c b/src/common/dcc.c
index 8f289342..4c8724d9 100644
--- a/src/common/dcc.c
+++ b/src/common/dcc.c
@@ -31,7 +31,6 @@
 #include <time.h>
 #include <errno.h>
 #include <sys/stat.h>
-#include <unistd.h>
 #include <fcntl.h>
 
 #define WANTSOCKET
@@ -41,6 +40,8 @@
 
 #ifdef WIN32
 #include <windows.h>
+#else
+#include <unistd.h>
 #endif
 
 #include "xchat.h"
@@ -57,6 +58,9 @@
 
 #ifdef USE_DCC64
 #define BIG_STR_TO_INT(x) strtoull(x,NULL,10)
+#ifdef WIN32
+#define stat _stat64
+#endif
 #else
 #define BIG_STR_TO_INT(x) strtoul(x,NULL,10)
 #endif
@@ -568,7 +572,7 @@ dcc_chat_line (struct DCC *dcc, char *line)
 
 	url_check_line (line, len);
 
-	if (line[0] == 1 && !strncasecmp (line + 1, "ACTION", 6))
+	if (line[0] == 1 && !g_ascii_strncasecmp (line + 1, "ACTION", 6))
 	{
 		po = strchr (line + 8, '\001');
 		if (po)
@@ -1936,9 +1940,9 @@ find_dcc (char *nick, char *file, int type)
 			{
 				if (!file[0])
 					return dcc;
-				if (!strcasecmp (file, file_part (dcc->file)))
+				if (!g_ascii_strcasecmp (file, file_part (dcc->file)))
 					return dcc;
-				if (!strcasecmp (file, dcc->file))
+				if (!g_ascii_strcasecmp (file, dcc->file))
 					return dcc;
 			}
 		}
@@ -1984,7 +1988,7 @@ is_same_file (struct DCC *dcc, struct DCC *new_dcc)
 
 	/* now handle case-insensitive Filesystems: HFS+, FAT */
 #ifdef WIN32
-#warning no win32 implementation - behaviour may be unreliable
+	/* warning no win32 implementation - behaviour may be unreliable */
 #else
 	/* this fstat() shouldn't really fail */
 	if ((dcc->fp == -1 ? stat (dcc->destfile_fs, &st_a) : fstat (dcc->fp, &st_a)) == -1)
@@ -2402,7 +2406,7 @@ handle_dcc (struct session *sess, char *nick, char *word[],
 	DCC_SIZE size;
 	int psend = 0;
 
-	if (!strcasecmp (type, "CHAT"))
+	if (!g_ascii_strcasecmp (type, "CHAT"))
 	{
 		port = atoi (word[8]);
 		addr = strtoul (word[7], NULL, 10);
@@ -2449,7 +2453,7 @@ handle_dcc (struct session *sess, char *nick, char *word[],
 		return;
 	}
 
-	if (!strcasecmp (type, "Resume"))
+	if (!g_ascii_strcasecmp (type, "Resume"))
 	{
 		port = atoi (word[7]);
 
@@ -2493,7 +2497,7 @@ handle_dcc (struct session *sess, char *nick, char *word[],
 		}
 		return;
 	}
-	if (!strcasecmp (type, "Accept"))
+	if (!g_ascii_strcasecmp (type, "Accept"))
 	{
 		port = atoi (word[7]);
 		dcc = find_dcc_from_port (port, TYPE_RECV);
@@ -2503,7 +2507,7 @@ handle_dcc (struct session *sess, char *nick, char *word[],
 		}
 		return;
 	}
-	if (!strcasecmp (type, "SEND"))
+	if (!g_ascii_strcasecmp (type, "SEND"))
 	{
 		char *file = file_part (word[6]);
 
diff --git a/src/common/identd.c b/src/common/identd.c
index 919282ea..430c7e8f 100644
--- a/src/common/identd.c
+++ b/src/common/identd.c
@@ -1,8 +1,13 @@
 /* simple identd server for xchat under win32 */
 
+#include "inet.h"
+#include "xchat.h"
+#include "xchatc.h"
 
 static int identd_is_running = FALSE;
-
+#ifdef USE_IPV6
+static int identd_ipv6_is_running = FALSE;
+#endif
 
 static int
 identd (char *username)
@@ -75,11 +80,102 @@ identd (char *username)
 	return 0;
 }
 
-static void
+#ifdef USE_IPV6
+static int
+identd_ipv6 (char *username)
+{
+	int sok, read_sok, len;
+	char *p;
+	char buf[256];
+	char outbuf[256];
+	char ipv6buf[60];
+	DWORD ipv6buflen = sizeof (ipv6buf);
+	struct sockaddr_in6 addr;
+
+	sok = socket (AF_INET6, SOCK_STREAM, 0);
+
+	if (sok == INVALID_SOCKET)
+	{
+		free (username);
+		return 0;
+	}
+
+	len = 1;
+	setsockopt (sok, SOL_SOCKET, SO_REUSEADDR, (char *) &len, sizeof (len));
+
+	memset (&addr, 0, sizeof (addr));
+	addr.sin6_family = AF_INET6;
+	addr.sin6_port = htons (113);
+
+	if (bind (sok, (struct sockaddr *) &addr, sizeof (addr)) == SOCKET_ERROR)
+	{
+		closesocket (sok);
+		free (username);
+		return 0;
+	}
+
+	if (listen (sok, 1) == SOCKET_ERROR)
+	{
+		closesocket (sok);
+		free (username);
+		return 0;
+	}
+
+	len = sizeof (addr);
+	read_sok = accept (sok, (struct sockaddr *) &addr, &len);
+	closesocket (sok);
+
+	if (read_sok == INVALID_SOCKET)
+	{
+		free (username);
+		return 0;
+	}
+
+	identd_ipv6_is_running = FALSE;
+
+	if (WSAAddressToString ((struct sockaddr *) &addr, sizeof (addr), NULL, &ipv6buf, &ipv6buflen) == SOCKET_ERROR)
+	{
+		snprintf (ipv6buf, sizeof (ipv6buf) - 1, "[SOCKET ERROR: 0x%X]", WSAGetLastError ());
+	}
+
+	snprintf (outbuf, sizeof (outbuf), "%%\tServicing ident request from %s\n", ipv6buf);
+	PrintText (current_sess, outbuf);
+
+	recv (read_sok, buf, sizeof (buf) - 1, 0);
+	buf[sizeof (buf) - 1] = 0;	  /* ensure null termination */
+
+	p = strchr (buf, ',');
+
+	if (p)
+	{
+		snprintf (outbuf, sizeof (outbuf) - 1, "%d, %d : USERID : UNIX : %s\r\n", atoi (buf), atoi (p + 1), username);
+		outbuf[sizeof (outbuf) - 1] = 0;	/* ensure null termination */
+		send (read_sok, outbuf, strlen (outbuf), 0);
+	}
+
+	sleep (1);
+	closesocket (read_sok);
+	free (username);
+
+	return 0;
+}
+#endif
+
+void
 identd_start (char *username)
 {
 	DWORD tid;
 
+#ifdef USE_IPV6
+	DWORD tidv6;
+	if (identd_ipv6_is_running == FALSE)
+	{
+		identd_ipv6_is_running = TRUE;
+		CloseHandle (CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) identd_ipv6,
+						 strdup (username), 0, &tidv6));
+	}
+#endif
+
 	if (identd_is_running == FALSE)
 	{
 		identd_is_running = TRUE;
diff --git a/src/common/identd.h b/src/common/identd.h
new file mode 100644
index 00000000..636f9641
--- /dev/null
+++ b/src/common/identd.h
@@ -0,0 +1 @@
+void identd_start (char *username);
diff --git a/src/common/ignore.c b/src/common/ignore.c
index c3544f30..0ed23daa 100644
--- a/src/common/ignore.c
+++ b/src/common/ignore.c
@@ -19,11 +19,14 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "xchat.h"
 #include "ignore.h"
 #include "cfgfiles.h"
diff --git a/src/common/inbound.c b/src/common/inbound.c
index 719bbe60..89899655 100644
--- a/src/common/inbound.c
+++ b/src/common/inbound.c
@@ -21,9 +21,12 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
-#include <unistd.h>
 #include <time.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #define WANTARPA
 #define WANTDNS
 #include "inet.h"
@@ -883,7 +886,7 @@ inbound_notice (server *serv, char *to, char *nick, char *msg, char *ip, int id)
 			if (msg[0] == '[' && (!serv->have_idmsg || id))
 			{
 				/* guess where chanserv meant to post this -sigh- */
-				if (!strcasecmp (nick, "ChanServ") && !find_dialog (serv, nick))
+				if (!g_ascii_strcasecmp (nick, "ChanServ") && !find_dialog (serv, nick))
 				{
 					char *dest = strdup (msg + 1);
 					char *end = strchr (dest, ']');
diff --git a/src/common/inet.h b/src/common/inet.h
index b420c9c6..8995569c 100644
--- a/src/common/inet.h
+++ b/src/common/inet.h
@@ -21,12 +21,12 @@
 
 #else
 
+#include "../../config.h"
 #ifdef USE_IPV6
 #include <winsock2.h>
 #include <ws2tcpip.h>
-#include <tpipv6.h>
 #else
-#include <winsock.h>
+#include <winsock2.h>
 #endif
 
 #define set_blocking(sok)	{ \
diff --git a/src/common/makefile.mak b/src/common/makefile.mak
new file mode 100644
index 00000000..d6df2608
--- /dev/null
+++ b/src/common/makefile.mak
@@ -0,0 +1,45 @@
+include "..\makeinc.mak"
+
+COMMON_OBJECTS = \
+cfgfiles.obj \
+chanopt.obj \
+ctcp.obj \
+dcc.obj \
+dirent-win32.obj \
+history.obj \
+identd.obj \
+ignore.obj \
+inbound.obj \
+modes.obj \
+network.obj \
+notify.obj \
+outbound.obj \
+plugin.obj \
+plugin-timer.obj \
+proto-irc.obj \
+server.obj \
+servlist.obj \
+ssl.obj \
+text.obj \
+thread.obj \
+tree.obj \
+url.obj \
+userlist.obj \
+util.obj \
+xchat.obj
+
+all: $(COMMON_OBJECTS) xchatcommon.lib dirent-win32.lib
+
+xchatcommon.lib: $(COMMON_OBJECTS)
+	lib /nologo /out:xchatcommon.lib $(COMMON_OBJECTS)
+
+dirent-win32.lib: dirent-win32.obj
+	lib /nologo /out:dirent-win32.lib dirent-win32.obj
+
+.c.obj::
+	$(CC) $(CFLAGS) $(GLIB) $<
+
+clean:
+	@del *.obj
+	@del xchatcommon.lib
+	@del dirent-win32.lib
diff --git a/src/common/modes.c b/src/common/modes.c
index 1acf7f54..6eb63f3b 100644
--- a/src/common/modes.c
+++ b/src/common/modes.c
@@ -789,20 +789,20 @@ inbound_005 (server * serv, char *word[])
 			}
 
 			/* use /NICKSERV */
-			if (strcasecmp (word[w] + 8, "RusNet") == 0)
+			if (g_ascii_strcasecmp (word[w] + 8, "RusNet") == 0)
 				serv->nickservtype = 1;
-			else if (strcasecmp (word[w] + 8, "UniBG") == 0)
+			else if (g_ascii_strcasecmp (word[w] + 8, "UniBG") == 0)
 				serv->nickservtype = 3;
-			else if (strcasecmp (word[w] + 8, "QuakeNet") == 0)
+			else if (g_ascii_strcasecmp (word[w] + 8, "QuakeNet") == 0)
 				serv->nickservtype = 4;
 
 		} else if (strncmp (word[w], "CASEMAPPING=", 12) == 0)
 		{
 			if (strcmp (word[w] + 12, "ascii") == 0)	/* bahamut */
-				serv->p_cmp = (void *)strcasecmp;
+				serv->p_cmp = (void *)g_ascii_strcasecmp;
 		} else if (strncmp (word[w], "CHARSET=", 8) == 0)
 		{
-			if (strcasecmp (word[w] + 8, "UTF-8") == 0)
+			if (g_ascii_strcasecmp (word[w] + 8, "UTF-8") == 0)
 			{
 				server_set_encoding (serv, "UTF-8");
 			}
diff --git a/src/common/msproxy.c b/src/common/msproxy.c
index 9c85394d..5103233a 100644
--- a/src/common/msproxy.c
+++ b/src/common/msproxy.c
@@ -26,9 +26,12 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <fcntl.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #define WANTSOCKET
 #define WANTARPA
 #include "inet.h"
diff --git a/src/common/network.c b/src/common/network.c
index 0c409506..eba24b05 100644
--- a/src/common/network.c
+++ b/src/common/network.c
@@ -21,9 +21,12 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
-#include <unistd.h>
 #include <glib.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "../../config.h"				  /* grab USE_IPV6 and LOOKUPD defines */
 
 #define WANTSOCKET
diff --git a/src/common/notify.c b/src/common/notify.c
index 04795849..9c6e54de 100644
--- a/src/common/notify.c
+++ b/src/common/notify.c
@@ -22,9 +22,12 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include <unistd.h>
 #include <time.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "xchat.h"
 #include "notify.h"
 #include "cfgfiles.h"
diff --git a/src/common/outbound.c b/src/common/outbound.c
index 2add05fd..872ef50b 100644
--- a/src/common/outbound.c
+++ b/src/common/outbound.c
@@ -30,9 +30,9 @@
 
 #ifndef WIN32
 #include <sys/wait.h>
+#include <unistd.h>
 #endif
 
-#include <unistd.h>
 #include <time.h>
 #include <signal.h>
 #include <sys/stat.h>
@@ -617,13 +617,13 @@ cmd_clear (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	GSList *list = sess_list;
 	char *reason = word_eol[2];
 
-	if (strcasecmp (reason, "HISTORY") == 0)
+	if (g_ascii_strcasecmp (reason, "HISTORY") == 0)
 	{
 		history_free (&sess->history);
 		return TRUE;
 	}
 
-	if (strncasecmp (reason, "all", 3) == 0)
+	if (g_ascii_strncasecmp (reason, "all", 3) == 0)
 	{
 		while (list)
 		{
@@ -750,26 +750,26 @@ cmd_dcc (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	char *type = word[2];
 	if (*type)
 	{
-		if (!strcasecmp (type, "HELP"))
+		if (!g_ascii_strcasecmp (type, "HELP"))
 			return FALSE;
-		if (!strcasecmp (type, "CLOSE"))
+		if (!g_ascii_strcasecmp (type, "CLOSE"))
 		{
 			if (*word[3] && *word[4])
 			{
 				goodtype = 0;
-				if (!strcasecmp (word[3], "SEND"))
+				if (!g_ascii_strcasecmp (word[3], "SEND"))
 				{
 					dcc = find_dcc (word[4], word[5], TYPE_SEND);
 					dcc_abort (sess, dcc);
 					goodtype = TRUE;
 				}
-				if (!strcasecmp (word[3], "GET"))
+				if (!g_ascii_strcasecmp (word[3], "GET"))
 				{
 					dcc = find_dcc (word[4], word[5], TYPE_RECV);
 					dcc_abort (sess, dcc);
 					goodtype = TRUE;
 				}
-				if (!strcasecmp (word[3], "CHAT"))
+				if (!g_ascii_strcasecmp (word[3], "CHAT"))
 				{
 					dcc = find_dcc (word[4], "", TYPE_CHATRECV);
 					if (!dcc)
@@ -789,20 +789,20 @@ cmd_dcc (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			}
 			return FALSE;
 		}
-		if ((!strcasecmp (type, "CHAT")) || (!strcasecmp (type, "PCHAT")))
+		if ((!g_ascii_strcasecmp (type, "CHAT")) || (!g_ascii_strcasecmp (type, "PCHAT")))
 		{
 			char *nick = word[3];
-			int passive = (!strcasecmp(type, "PCHAT")) ? 1 : 0;
+			int passive = (!g_ascii_strcasecmp(type, "PCHAT")) ? 1 : 0;
 			if (*nick)
 				dcc_chat (sess, nick, passive);
 			return TRUE;
 		}
-		if (!strcasecmp (type, "LIST"))
+		if (!g_ascii_strcasecmp (type, "LIST"))
 		{
 			dcc_show_list (sess);
 			return TRUE;
 		}
-		if (!strcasecmp (type, "GET"))
+		if (!g_ascii_strcasecmp (type, "GET"))
 		{
 			char *nick = word[3];
 			char *file = word[4];
@@ -820,18 +820,18 @@ cmd_dcc (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			}
 			return TRUE;
 		}
-		if ((!strcasecmp (type, "SEND")) || (!strcasecmp (type, "PSEND")))
+		if ((!g_ascii_strcasecmp (type, "SEND")) || (!g_ascii_strcasecmp (type, "PSEND")))
 		{
 			int i = 3, maxcps;
 			char *nick, *file;
-			int passive = (!strcasecmp(type, "PSEND")) ? 1 : 0;
+			int passive = (!g_ascii_strcasecmp(type, "PSEND")) ? 1 : 0;
 
 			nick = word[i];
 			if (!*nick)
 				return FALSE;
 
 			maxcps = prefs.dcc_max_send_cps;
-			if (!strncasecmp(nick, "-maxcps=", 8))
+			if (!g_ascii_strncasecmp(nick, "-maxcps=", 8))
 			{
 				maxcps = atoi(nick + 8);
 				i++;
@@ -1312,7 +1312,7 @@ cmd_menu (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 				*p = '/';
 	}
 
-	if (!strcasecmp (word[idx], "ADD"))
+	if (!g_ascii_strcasecmp (word[idx], "ADD"))
 	{
 		if (toggle)
 		{
@@ -1327,7 +1327,7 @@ cmd_menu (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		return TRUE;
 	}
 
-	if (!strcasecmp (word[idx], "DEL"))
+	if (!g_ascii_strcasecmp (word[idx], "DEL"))
 	{
 		menu_del (tbuf, label);
 		return TRUE;
@@ -2045,7 +2045,7 @@ cmd_gui (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	case 0xc0851aaa: fe_message (word[3], FE_MSG_INFO|FE_MSG_MARKUP); break; /* MSGBOX */
 	case 0x0035dafd: fe_ctrl_gui (sess, 1, 0); break; /* SHOW */
 	case 0x0033155f: /* MENU */
-		if (!strcasecmp (word[3], "TOGGLE"))
+		if (!g_ascii_strcasecmp (word[3], "TOGGLE"))
 			fe_ctrl_gui (sess, 6, 0);
 		else
 			return FALSE;
@@ -2247,25 +2247,25 @@ cmd_ignore (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			}
 			return TRUE;
 		}
-		if (!strcasecmp (word[i], "UNIGNORE"))
+		if (!g_ascii_strcasecmp (word[i], "UNIGNORE"))
 			type |= IG_UNIG;
-		else if (!strcasecmp (word[i], "ALL"))
+		else if (!g_ascii_strcasecmp (word[i], "ALL"))
 			type |= IG_PRIV | IG_NOTI | IG_CHAN | IG_CTCP | IG_INVI | IG_DCC;
-		else if (!strcasecmp (word[i], "PRIV"))
+		else if (!g_ascii_strcasecmp (word[i], "PRIV"))
 			type |= IG_PRIV;
-		else if (!strcasecmp (word[i], "NOTI"))
+		else if (!g_ascii_strcasecmp (word[i], "NOTI"))
 			type |= IG_NOTI;
-		else if (!strcasecmp (word[i], "CHAN"))
+		else if (!g_ascii_strcasecmp (word[i], "CHAN"))
 			type |= IG_CHAN;
-		else if (!strcasecmp (word[i], "CTCP"))
+		else if (!g_ascii_strcasecmp (word[i], "CTCP"))
 			type |= IG_CTCP;
-		else if (!strcasecmp (word[i], "INVI"))
+		else if (!g_ascii_strcasecmp (word[i], "INVI"))
 			type |= IG_INVI;
-		else if (!strcasecmp (word[i], "QUIET"))
+		else if (!g_ascii_strcasecmp (word[i], "QUIET"))
 			quiet = 1;
-		else if (!strcasecmp (word[i], "NOSAVE"))
+		else if (!g_ascii_strcasecmp (word[i], "NOSAVE"))
 			type |= IG_NOSAVE;
-		else if (!strcasecmp (word[i], "DCC"))
+		else if (!g_ascii_strcasecmp (word[i], "DCC"))
 			type |= IG_DCC;
 		else
 		{
@@ -2456,12 +2456,12 @@ cmd_load (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 #ifdef USE_PLUGIN
 	len = strlen (word[2]);
 #ifdef WIN32
-	if (len > 4 && strcasecmp (".dll", word[2] + len - 4) == 0)
+	if (len > 4 && g_ascii_strcasecmp (".dll", word[2] + len - 4) == 0)
 #else
 #if defined(__hpux)
-	if (len > 3 && strcasecmp (".sl", word[2] + len - 3) == 0)
+	if (len > 3 && g_ascii_strcasecmp (".sl", word[2] + len - 3) == 0)
 #else
-	if (len > 3 && strcasecmp (".so", word[2] + len - 3) == 0)
+	if (len > 3 && g_ascii_strcasecmp (".so", word[2] + len - 3) == 0)
 #endif
 #endif
 	{
@@ -2613,8 +2613,8 @@ cmd_msg (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			else
 			{
 				/* mask out passwords */
-				if (strcasecmp (nick, "nickserv") == 0 &&
-					 strncasecmp (msg, "identify ", 9) == 0)
+				if (g_ascii_strcasecmp (nick, "nickserv") == 0 &&
+					 g_ascii_strncasecmp (msg, "identify ", 9) == 0)
 					msg = "identify ****";
 				EMIT_SIGNAL (XP_TE_MSGSEND, sess, nick, msg, NULL, NULL, 0);
 			}
@@ -2825,7 +2825,7 @@ cmd_reconnect (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 
 	prefs.recon_delay = 0;
 
-	if (!strcasecmp (word[2], "ALL"))
+	if (!g_ascii_strcasecmp (word[2], "ALL"))
 	{
 		list = serv_list;
 		while (list)
@@ -2881,6 +2881,23 @@ cmd_recv (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	return FALSE;
 }
 
+#if 0 /* manual command for flushing prefs to disk, but we use an autosave-upon-set approach instead */
+static int
+cmd_saveconf (struct session *sess, char *tbuf, char *word[], char *word_eol[])
+{
+	if (save_config ())
+	{
+		PrintText (sess, "Settings have been saved successfully.\n");
+	}
+	else
+	{
+		PrintText (sess, "Error saving settings.\n");
+	}
+
+	return TRUE;
+}
+#endif
+
 static int
 cmd_say (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
@@ -2980,7 +2997,7 @@ parse_irc_url (char *url, char *server_name[], char *port[], char *channel[], in
 {
 	char *co;
 #ifdef USE_OPENSSL
-	if (strncasecmp ("ircs://", url, 7) == 0)
+	if (g_ascii_strncasecmp ("ircs://", url, 7) == 0)
 	{
 		*use_ssl = TRUE;
 		*server_name = url + 7;
@@ -2988,7 +3005,7 @@ parse_irc_url (char *url, char *server_name[], char *port[], char *channel[], in
 	}
 #endif
 
-	if (strncasecmp ("irc://", url, 6) == 0)
+	if (g_ascii_strncasecmp ("irc://", url, 6) == 0)
 	{
 		*server_name = url + 6;
 #ifdef USE_OPENSSL
@@ -3059,7 +3076,7 @@ cmd_server (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	sess->server->network = NULL;
 
 	/* dont clear it for /servchan */
-	if (strncasecmp (word_eol[1], "SERVCHAN ", 9))
+	if (g_ascii_strncasecmp (word_eol[1], "SERVCHAN ", 9))
 		sess->willjoinchannel[0] = 0;
 
 	if (channel)
@@ -3189,7 +3206,7 @@ cmd_unignore (struct session *sess, char *tbuf, char *word[],
 	{
 		if (ignore_del (mask, NULL))
 		{
-			if (strcasecmp (arg, "QUIET"))
+			if (g_ascii_strcasecmp (arg, "QUIET"))
 				EMIT_SIGNAL (XP_TE_IGNOREREMOVE, sess, mask, NULL, NULL, NULL, 0);
 		}
 		return TRUE;
@@ -3205,12 +3222,12 @@ cmd_unload (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 
 	len = strlen (word[2]);
 #ifdef WIN32
-	if (len > 4 && strcasecmp (word[2] + len - 4, ".dll") == 0)
+	if (len > 4 && g_ascii_strcasecmp (word[2] + len - 4, ".dll") == 0)
 #else
 #if defined(__hpux)
-	if (len > 3 && strcasecmp (word[2] + len - 3, ".sl") == 0)
+	if (len > 3 && g_ascii_strcasecmp (word[2] + len - 3, ".sl") == 0)
 #else
-	if (len > 3 && strcasecmp (word[2] + len - 3, ".so") == 0)
+	if (len > 3 && g_ascii_strcasecmp (word[2] + len - 3, ".so") == 0)
 #endif
 #endif
 		by_file = TRUE;
@@ -3240,7 +3257,7 @@ find_server_from_hostname (char *hostname)
 	while (list)
 	{
 		serv = list->data;
-		if (!strcasecmp (hostname, serv->hostname) && serv->connected)
+		if (!g_ascii_strcasecmp (hostname, serv->hostname) && serv->connected)
 			return serv;
 		list = list->next;
 	}
@@ -3293,7 +3310,7 @@ cmd_url (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			/* maybe we're already connected to this net */
 
 			/* check for "FreeNode" */
-			net = servlist_net_find (server_name, NULL, strcasecmp);
+			net = servlist_net_find (server_name, NULL, g_ascii_strcasecmp);
 			/* check for "irc.eu.freenode.net" */
 			if (!net)
 				net = servlist_net_find_from_server (server_name);
@@ -3633,6 +3650,9 @@ const struct commands xc_cmds[] = {
 #endif
 	{"RECV", cmd_recv, 1, 0, 1, N_("RECV <text>, send raw data to xchat, as if it was received from the irc server")},
 
+#if 0
+	{"SAVECONF", cmd_saveconf, 0, 0, 1, N_("SAVECONF, saves the current settings to disk")},
+#endif
 	{"SAY", cmd_say, 0, 0, 1,
 	 N_("SAY <text>, sends the text to the object in the current window")},
 	{"SEND", cmd_send, 0, 0, 1, N_("SEND <nick> [<file>]")},
@@ -3685,7 +3705,7 @@ const struct commands xc_cmds[] = {
 static int
 command_compare (const void *a, const void *b)
 {
-	return strcasecmp (a, ((struct commands *)b)->name);
+	return g_ascii_strcasecmp (a, ((struct commands *)b)->name);
 }
 
 static struct commands *
@@ -4257,7 +4277,7 @@ handle_command (session *sess, char *cmd, int check_spch)
 	while (list)
 	{
 		pop = (struct popup *) list->data;
-		if (!strcasecmp (pop->name, word[1]))
+		if (!g_ascii_strcasecmp (pop->name, word[1]))
 		{
 			user_command (sess, tbuf, pop->cmd, word, word_eol);
 			user_cmd = TRUE;
diff --git a/src/common/plugin-timer.c b/src/common/plugin-timer.c
index f09074a8..431ce8ab 100644
--- a/src/common/plugin-timer.c
+++ b/src/common/plugin-timer.c
@@ -4,7 +4,7 @@
 #include "xchat-plugin.h"
 
 #ifdef WIN32
-#define strcasecmp stricmp
+#define g_ascii_strcasecmp stricmp
 #endif
 
 static xchat_plugin *ph;	/* plugin handle */
@@ -151,25 +151,25 @@ timer_cb (char *word[], char *word_eol[], void *userdata)
 		return XCHAT_EAT_XCHAT;
 	}
 
-	if (strcasecmp (word[2], "-quiet") == 0)
+	if (g_ascii_strcasecmp (word[2], "-quiet") == 0)
 	{
 		quiet = TRUE;
 		offset++;
 	}
 
-	if (strcasecmp (word[2 + offset], "-delete") == 0)
+	if (g_ascii_strcasecmp (word[2 + offset], "-delete") == 0)
 	{
 		timer_del_ref (atoi (word[3 + offset]), quiet);
 		return XCHAT_EAT_XCHAT;
 	}
 
-	if (strcasecmp (word[2 + offset], "-refnum") == 0)
+	if (g_ascii_strcasecmp (word[2 + offset], "-refnum") == 0)
 	{
 		ref = atoi (word[3 + offset]);
 		offset += 2;
 	}
 
-	if (strcasecmp (word[2 + offset], "-repeat") == 0)
+	if (g_ascii_strcasecmp (word[2 + offset], "-repeat") == 0)
 	{
 		repeat = atoi (word[3 + offset]);
 		offset += 2;
diff --git a/src/common/plugin.c b/src/common/plugin.c
index ada4d3be..0a265d16 100644
--- a/src/common/plugin.c
+++ b/src/common/plugin.c
@@ -20,6 +20,14 @@
 #include <string.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#ifdef WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
 
 #include "xchat.h"
 #include "fe.h"
@@ -262,6 +270,12 @@ plugin_add (session *sess, char *filename, void *handle, void *init_func,
 		pl->xchat_send_modes = xchat_send_modes;
 		pl->xchat_strip = xchat_strip;
 		pl->xchat_free = xchat_free;
+		pl->xchat_pluginpref_set_str = xchat_pluginpref_set_str;
+		pl->xchat_pluginpref_get_str = xchat_pluginpref_get_str;
+		pl->xchat_pluginpref_set_int = xchat_pluginpref_set_int;
+		pl->xchat_pluginpref_get_int = xchat_pluginpref_get_int;
+		pl->xchat_pluginpref_delete = xchat_pluginpref_delete;
+		pl->xchat_pluginpref_list = xchat_pluginpref_list;
 
 		/* incase new plugins are loaded on older xchat */
 		pl->xchat_dummy4 = xchat_dummy;
@@ -295,9 +309,9 @@ plugin_kill (char *name, int by_filename)
 	{
 		pl = list->data;
 		/* static-plugins (plugin-timer.c) have a NULL filename */
-		if ((by_filename && pl->filename && strcasecmp (name, pl->filename) == 0) ||
-			 (by_filename && pl->filename && strcasecmp (name, file_part (pl->filename)) == 0) ||
-			(!by_filename && strcasecmp (name, pl->name) == 0))
+		if ((by_filename && pl->filename && g_ascii_strcasecmp (name, pl->filename) == 0) ||
+			 (by_filename && pl->filename && g_ascii_strcasecmp (name, file_part (pl->filename)) == 0) ||
+			(!by_filename && g_ascii_strcasecmp (name, pl->name) == 0))
 		{
 			/* statically linked plugins have a NULL filename */
 			if (pl->filename != NULL && !pl->fake)
@@ -458,12 +472,12 @@ plugin_hook_find (GSList *list, int type, char *name)
 		hook = list->data;
 		if (hook->type == type)
 		{
-			if (strcasecmp (hook->name, name) == 0)
+			if (g_ascii_strcasecmp (hook->name, name) == 0)
 				return list;
 
 			if (type == HOOK_SERVER)
 			{
-				if (strcasecmp (hook->name, "RAW LINE") == 0)
+				if (g_ascii_strcasecmp (hook->name, "RAW LINE") == 0)
 					return list;
 			}
 		}
@@ -933,8 +947,8 @@ xchat_find_context (xchat_plugin *ph, const char *servname, const char *channel)
 
 		if (servname == NULL ||
 			 rfc_casecmp (servname, serv->servername) == 0 ||
-			 strcasecmp (servname, serv->hostname) == 0 ||
-			 strcasecmp (servname, netname) == 0)
+			 g_ascii_strcasecmp (servname, serv->hostname) == 0 ||
+			 g_ascii_strcasecmp (servname, netname) == 0)
 		{
 			if (channel == NULL)
 				return serv->front_session;
@@ -996,13 +1010,20 @@ xchat_get_info (xchat_plugin *ph, const char *id)
 		return XCHATLIBDIR;
 
 	case 0x14f51cd8: /* version */
+#ifdef WIN32
+		return XCHAT_RELEASE;
+#else
 		return PACKAGE_VERSION;
+#endif
 
 	case 0xdd9b1abd:	/* xchatdir */
 		return get_xdir_utf8 ();
 
 	case 0xe33f6c4a:	/* xchatdirfs */
 		return get_xdir_fs ();
+
+	case 0x3d1e70d7:	/* wdk_version */
+		return PACKAGE_VERSION;
 	}
 
 	sess = ph->context;
@@ -1100,7 +1121,7 @@ xchat_get_prefs (xchat_plugin *ph, const char *name, const char **string, int *i
 	
 	do
 	{
-		if (!strcasecmp (name, vars[i].name))
+		if (!g_ascii_strcasecmp (name, vars[i].name))
 		{
 			switch (vars[i].type)
 			{
@@ -1567,3 +1588,239 @@ xchat_free (xchat_plugin *ph, void *ptr)
 {
 	g_free (ptr);
 }
+
+static int
+xchat_pluginpref_set_str_real (xchat_plugin *pl, const char *var, const char *value, int mode) /* mode: 0 = delete, 1 = save */
+{
+	FILE *fpIn;
+	int fhOut;
+	int prevSetting;
+	char confname[64];
+	char confname_tmp[69];
+	char buffer[512];		/* the same as in cfg_put_str */
+	char buffer_tmp[512];
+	char *canon;
+
+	canon = g_strdup (pl->name);
+	canonalize_key (canon);
+	sprintf (confname, "plugin_%s.conf", canon);
+	g_free (canon);
+	sprintf (confname_tmp, "%s.new", confname);
+
+	fhOut = xchat_open_file (confname_tmp, O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
+	fpIn = xchat_fopen_file (confname, "r", 0);
+
+	if (fhOut == -1)		/* unable to save, abort */
+	{
+		return 0;
+	}
+	else if (fpIn == NULL)	/* no previous config file, no parsing */
+	{
+		if (mode)
+		{
+			sprintf (buffer, "%s = %s\n", var, value);
+			write (fhOut, buffer, strlen (buffer));
+			close (fhOut);
+
+			sprintf (buffer, "%s/%s", get_xdir_fs (), confname);
+			sprintf (buffer_tmp, "%s/%s", get_xdir_fs (), confname_tmp);
+
+#ifdef WIN32
+			unlink (buffer);
+#endif
+
+			if (rename (buffer_tmp, buffer) == 0)
+			{
+				return 1;
+			}
+			else
+			{
+				return 0;
+			}
+		}
+		else
+		{
+			/* mode = 0, we want to delete but the config file and thus the given setting does not exist, we're ready */
+			close (fhOut);
+			return 1;
+		}
+	}
+	else	/* existing config file, preserve settings and find & replace current var value if any */
+	{
+		prevSetting = 0;
+
+		while (fscanf (fpIn, " %[^\n]", &buffer) != EOF)	/* read whole lines including whitespaces */
+		{
+			sprintf (buffer_tmp, "%s ", var);				/* add one space, this way it works against var - var2 checks too */
+
+			if (strncmp (buffer_tmp, buffer, strlen (var) + 1) == 0)	/* given setting already exists */
+			{
+				if (mode)									/* overwrite the existing matching setting if we are in save mode */
+				{
+					sprintf (buffer, "%s = %s\n", var, value);
+				}
+				else										/* erase the setting in delete mode */
+				{
+					strcpy (buffer, "");
+				}
+
+				prevSetting = 1;
+			}
+			else
+			{
+				strcat (buffer, "\n");						/* preserve the existing different settings */
+			}
+
+			write (fhOut, buffer, strlen (buffer));
+		}
+
+		fclose (fpIn);
+
+		if (!prevSetting && mode)	/* var doesn't exist currently, append if we're in save mode */
+		{
+			sprintf (buffer, "%s = %s\n", var, value);
+			write (fhOut, buffer, strlen (buffer));
+		}
+
+		close (fhOut);
+
+		sprintf (buffer, "%s/%s", get_xdir_fs (), confname);
+		sprintf (buffer_tmp, "%s/%s", get_xdir_fs (), confname_tmp);
+
+#ifdef WIN32
+		unlink (buffer);
+#endif
+
+		if (rename (buffer_tmp, buffer) == 0)
+		{
+			return 1;
+		}
+		else
+		{
+			return 0;
+		}
+	}
+}
+
+int
+xchat_pluginpref_set_str (xchat_plugin *pl, const char *var, const char *value)
+{
+	return xchat_pluginpref_set_str_real (pl, var, value, 1);
+}
+
+int
+xchat_pluginpref_get_str (xchat_plugin *pl, const char *var, char *dest)
+{
+	int fh;
+	int l;
+	char confname[64];
+	char *canon;
+	char *cfg;
+	struct stat st;
+
+	canon = g_strdup (pl->name);
+	canonalize_key (canon);
+	sprintf (confname, "plugin_%s.conf", canon);
+	g_free (canon);
+
+	/* partly borrowed from palette.c */
+	fh = xchat_open_file (confname, O_RDONLY, 0, 0);
+
+	if (fh == -1)
+	{
+		return 0;
+	}
+
+	fstat (fh, &st);
+	cfg = malloc (st.st_size + 1);
+
+	if (!cfg)
+	{
+		close (fh);
+		return 0;
+	}
+
+	cfg[0] = '\0';
+	l = read (fh, cfg, st.st_size);
+
+	if (l >= 0)
+	{
+		cfg[l] = '\0';
+	}
+
+	if (!cfg_get_str (cfg, var, dest, 512)) /* dest_len is the same as buffer size in set */
+	{
+		free (cfg);
+		close (fh);
+		return 0;
+	}
+
+	free (cfg);
+	close (fh);
+	return 1;
+}
+
+int
+xchat_pluginpref_set_int (xchat_plugin *pl, const char *var, int value)
+{
+	char buffer[12];
+
+	sprintf (buffer, "%d", value);
+	return xchat_pluginpref_set_str_real (pl, var, buffer, 1);
+}
+
+int
+xchat_pluginpref_get_int (xchat_plugin *pl, const char *var)
+{
+	char buffer[12];
+
+	if (xchat_pluginpref_get_str (pl, var, buffer))
+	{
+		return atoi (buffer);
+	}
+	else
+	{
+		return -1;
+	}
+}
+
+int
+xchat_pluginpref_delete (xchat_plugin *pl, const char *var)
+{
+	return xchat_pluginpref_set_str_real (pl, var, 0, 0);
+}
+
+int
+xchat_pluginpref_list (xchat_plugin *pl, char* dest)
+{
+	FILE *fpIn;
+	char confname[64];
+	char buffer[512];										/* the same as in cfg_put_str */
+	char *token;
+
+	token = g_strdup (pl->name);
+	canonalize_key (token);
+	sprintf (confname, "plugin_%s.conf", token);
+	g_free (token);
+
+	fpIn = xchat_fopen_file (confname, "r", 0);
+
+	if (fpIn == NULL)										/* no existing config file, no parsing */
+	{
+		return 0;
+	}
+	else													/* existing config file, get list of settings */
+	{
+		strcpy (dest, "");									/* clean up garbage */
+		while (fscanf (fpIn, " %[^\n]", &buffer) != EOF)	/* read whole lines including whitespaces */
+		{
+			token = strtok (buffer, "=");
+			strncat (dest, token, strlen (token) - 1);
+			strcat (dest, ",");
+		}
+
+		fclose (fpIn);
+	}
+
+	return 1;
+}
diff --git a/src/common/plugin.h b/src/common/plugin.h
index b0c89d1b..8c347d51 100644
--- a/src/common/plugin.h
+++ b/src/common/plugin.h
@@ -98,6 +98,21 @@ struct _xchat_plugin
 	     int flags);
 	void (*xchat_free) (xchat_plugin *ph,
 	    void *ptr);
+	int (*xchat_pluginpref_set_str) (xchat_plugin *ph,
+		const char *var,
+		const char *value);
+	int (*xchat_pluginpref_get_str) (xchat_plugin *ph,
+		const char *var,
+		char *dest);
+	int (*xchat_pluginpref_set_int) (xchat_plugin *ph,
+		const char *var,
+		int value);
+	int (*xchat_pluginpref_get_int) (xchat_plugin *ph,
+		const char *var);
+	int (*xchat_pluginpref_delete) (xchat_plugin *ph,
+		const char *var);
+	int (*xchat_pluginpref_list) (xchat_plugin *ph,
+		char *dest);
 	void *(*xchat_dummy4) (xchat_plugin *ph);
 	void *(*xchat_dummy3) (xchat_plugin *ph);
 	void *(*xchat_dummy2) (xchat_plugin *ph);
diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c
index 338a3b18..d8a6be7c 100644
--- a/src/common/proto-irc.c
+++ b/src/common/proto-irc.c
@@ -18,13 +18,16 @@
 
 /* IRC RFC1459(+commonly used extensions) protocol implementation */
 
-#include <unistd.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <stdarg.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "xchat.h"
 #include "ctcp.h"
 #include "fe.h"
@@ -472,12 +475,12 @@ process_numeric (session * sess, int n,
 		}
 
 		/* use /NICKSERV */
-		if (strcasecmp (word[7], "DALnet") == 0 ||
-			 strcasecmp (word[7], "BRASnet") == 0)
+		if (g_ascii_strcasecmp (word[7], "DALnet") == 0 ||
+			 g_ascii_strcasecmp (word[7], "BRASnet") == 0)
 			serv->nickservtype = 1;
 
 		/* use /NS */
-		else if (strcasecmp (word[7], "FreeNode") == 0)
+		else if (g_ascii_strcasecmp (word[7], "FreeNode") == 0)
 			serv->nickservtype = 2;
 
 		goto def;
@@ -1072,9 +1075,9 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
 					{
 						text[len - 1] = 0;
 						text++;
-						if (strncasecmp (text, "ACTION", 6) != 0)
+						if (g_ascii_strncasecmp (text, "ACTION", 6) != 0)
 							flood_check (nick, ip, serv, sess, 0);
-						if (strncasecmp (text, "DCC ", 4) == 0)
+						if (g_ascii_strncasecmp (text, "DCC ", 4) == 0)
 							/* redo this with handle_quotes TRUE */
 							process_data_init (word[1], word_eol[1], word, word_eol, TRUE, FALSE);
 						ctcp_handle (sess, to, nick, ip, text, word, word_eol, id);
diff --git a/src/common/server.c b/src/common/server.c
index db0af9ca..c8cc59e0 100644
--- a/src/common/server.c
+++ b/src/common/server.c
@@ -26,7 +26,6 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
 
@@ -37,6 +36,7 @@
 #ifndef WIN32
 #include <signal.h>
 #include <sys/wait.h>
+#include <unistd.h>
 #else
 #include <winbase.h>
 #endif
@@ -67,7 +67,7 @@
 #endif
 
 #ifdef WIN32
-#include "identd.c"
+#include "identd.h"
 #endif
 
 #ifdef USE_LIBPROXY
@@ -238,17 +238,17 @@ tcp_send_len (server *serv, char *buf, int len)
 	dbuf[len + 1] = 0;
 
 	/* privmsg and notice get a lower priority */
-	if (strncasecmp (dbuf + 1, "PRIVMSG", 7) == 0 ||
-		 strncasecmp (dbuf + 1, "NOTICE", 6) == 0)
+	if (g_ascii_strncasecmp (dbuf + 1, "PRIVMSG", 7) == 0 ||
+		 g_ascii_strncasecmp (dbuf + 1, "NOTICE", 6) == 0)
 	{
 		dbuf[0] = 1;
 	}
 	else
 	{
 		/* WHO/MODE get the lowest priority */
-		if (strncasecmp (dbuf + 1, "WHO ", 4) == 0 ||
+		if (g_ascii_strncasecmp (dbuf + 1, "WHO ", 4) == 0 ||
 		/* but only MODE queries, not changes */
-			(strncasecmp (dbuf + 1, "MODE", 4) == 0 &&
+			(g_ascii_strncasecmp (dbuf + 1, "MODE", 4) == 0 &&
 			 strchr (dbuf, '-') == NULL &&
 			 strchr (dbuf, '+') == NULL))
 			dbuf[0] = 0;
@@ -310,12 +310,17 @@ server_inline (server *serv, char *line, int len)
 {
 	char *utf_line_allocated = NULL;
 
+#ifdef WIN32
+	char *cleaned_line;
+	int cleaned_len;
+#endif
+
 	/* Checks whether we're set to use UTF-8 charset */
 	if (serv->using_irc ||				/* 1. using CP1252/UTF-8 Hybrid */
 		(serv->encoding == NULL && prefs.utf8_locale) || /* OR 2. using system default->UTF-8 */
 	    (serv->encoding != NULL &&				/* OR 3. explicitly set to UTF-8 */
-		 (strcasecmp (serv->encoding, "UTF8") == 0 ||
-		  strcasecmp (serv->encoding, "UTF-8") == 0)))
+		 (g_ascii_strcasecmp (serv->encoding, "UTF8") == 0 ||
+		  g_ascii_strcasecmp (serv->encoding, "UTF-8") == 0)))
 	{
 		/* The user has the UTF-8 charset set, either via /charset
 		command or from his UTF-8 locale. Thus, we first try the
@@ -396,11 +401,23 @@ server_inline (server *serv, char *line, int len)
 		}
 	}
 
+#ifdef WIN32
+	cleaned_line = text_replace_non_bmp (line, len, &cleaned_len);
+	if (cleaned_line != NULL ) {
+		line = cleaned_line;
+		len = cleaned_len;
+	}
+#endif
+
 	fe_add_rawlog (serv, line, len, FALSE);
 
 	/* let proto-irc.c handle it */
 	serv->p_inline (serv, line, len);
 
+#ifdef WIN32
+	g_free (cleaned_line);
+#endif
+
 	if (utf_line_allocated != NULL) /* only if a special copy was allocated */
 		g_free (utf_line_allocated);
 }
@@ -844,33 +861,6 @@ server_flush_queue (server *serv)
 	fe_set_throttle (serv);
 }
 
-#ifdef WIN32
-
-static int
-waitline2 (GIOChannel *source, char *buf, int bufsize)
-{
-	int i = 0;
-	int len;
-
-	while (1)
-	{
-		if (g_io_channel_read (source, &buf[i], 1, &len) != G_IO_ERROR_NONE)
-			return -1;
-		if (buf[i] == '\n' || bufsize == i + 1)
-		{
-			buf[i] = 0;
-			return i;
-		}
-		i++;
-	}
-}
-
-#else
-
-#define waitline2(source,buf,size) waitline(serv->childread,buf,size,0)
-
-#endif
-
 /* connect() successed */
 
 static void
@@ -1394,12 +1384,7 @@ base64_encode (char *to, char *from, unsigned int len)
 static int
 http_read_line (int print_fd, int sok, char *buf, int len)
 {
-#ifdef WIN32
-	/* make sure waitline() uses recv() or it'll fail on win32 */
-	len = waitline (sok, buf, len, FALSE);
-#else
 	len = waitline (sok, buf, len, TRUE);
-#endif
 	if (len >= 1)
 	{
 		/* print the message out (send it to the parent process) */
@@ -1795,7 +1780,11 @@ server_connect (server *serv, char *hostname, int port, int no_login)
 	}
 #endif
 	serv->childpid = pid;
+#ifdef WIN32
+	serv->iotag = fe_input_add (serv->childread, FIA_READ|FIA_FD, server_read_child,
+#else
 	serv->iotag = fe_input_add (serv->childread, FIA_READ, server_read_child,
+#endif
 										 serv);
 }
 
@@ -1835,10 +1824,10 @@ server_set_encoding (server *serv, char *new_encoding)
 			space[0] = 0;
 
 		/* server_inline() uses these flags */
-		if (!strcasecmp (serv->encoding, "CP1255") ||
-			 !strcasecmp (serv->encoding, "WINDOWS-1255"))
+		if (!g_ascii_strcasecmp (serv->encoding, "CP1255") ||
+			 !g_ascii_strcasecmp (serv->encoding, "WINDOWS-1255"))
 			serv->using_cp1255 = TRUE;
-		else if (!strcasecmp (serv->encoding, "IRC"))
+		else if (!g_ascii_strcasecmp (serv->encoding, "IRC"))
 			serv->using_irc = TRUE;
 	}
 }
diff --git a/src/common/servlist.c b/src/common/servlist.c
index 66bc8115..aa32aa4d 100644
--- a/src/common/servlist.c
+++ b/src/common/servlist.c
@@ -21,7 +21,10 @@
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+
+#ifndef WIN32
 #include <unistd.h>
+#endif
 
 #include "xchat.h"
 #include <glib.h>
@@ -585,7 +588,7 @@ servlist_connect_by_netname (session *sess, char *network, gboolean join)
 	{
 		net = list->data;
 
-		if (strcasecmp (net->name, network) == 0)
+		if (g_ascii_strcasecmp (net->name, network) == 0)
 		{
 			servlist_connect (sess, net, join);
 			return 1;
@@ -730,7 +733,7 @@ servlist_net_find_from_server (char *server_name)
 		while (slist)
 		{
 			serv = slist->data;
-			if (strcasecmp (serv->hostname, server_name) == 0)
+			if (g_ascii_strcasecmp (serv->hostname, server_name) == 0)
 				return net;
 			slist = slist->next;
 		}
@@ -1015,7 +1018,7 @@ servlist_check_encoding (char *charset)
 	if (c)
 		c[0] = 0;
 
-	if (!strcasecmp (charset, "IRC")) /* special case */
+	if (!g_ascii_strcasecmp (charset, "IRC")) /* special case */
 	{
 		if (c)
 			c[0] = ' ';
@@ -1090,8 +1093,8 @@ servlist_save (void)
 			fprintf (fp, "J=%s\n", net->autojoin);
 		if (net->nickserv)
 			fprintf (fp, "B=%s\n", net->nickserv);
-		if (net->encoding && strcasecmp (net->encoding, "System") &&
-			 strcasecmp (net->encoding, "System default"))
+		if (net->encoding && g_ascii_strcasecmp (net->encoding, "System") &&
+			 g_ascii_strcasecmp (net->encoding, "System default"))
 		{
 			fprintf (fp, "E=%s\n", net->encoding);
 			if (!servlist_check_encoding (net->encoding))
diff --git a/src/common/ssl.c b/src/common/ssl.c
index a18ad47c..daa7416b 100644
--- a/src/common/ssl.c
+++ b/src/common/ssl.c
@@ -17,12 +17,12 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
+#include "inet.h"				  /* make it first to avoid macro redefinitions */
 #include <openssl/ssl.h>		  /* SSL_() */
 #include <openssl/err.h>		  /* ERR_() */
 #include <time.h>					  /* asctime() */
 #include <string.h>				  /* strncpy() */
 #include "ssl.h"					  /* struct cert_info */
-#include "inet.h"
 #include "../../config.h"		  /* HAVE_SNPRINTF */
 
 #ifndef HAVE_SNPRINTF
diff --git a/src/common/text.c b/src/common/text.c
index 6b111742..f8afc4b3 100644
--- a/src/common/text.c
+++ b/src/common/text.c
@@ -19,13 +19,16 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <unistd.h>
 #include <ctype.h>
 #include <time.h>
 #include <sys/types.h>
 #include <fcntl.h>
 #include <sys/stat.h>
+
+#ifndef WIN32
+#include <unistd.h>
 #include <sys/mman.h>
+#endif
 
 #include "xchat.h"
 #include <glib.h>
@@ -271,9 +274,15 @@ scrollback_load (session *sess)
 	char *text;
 	time_t stamp;
 	int lines;
+
+#ifdef WIN32
+	char *cleaned_text;
+	int cleaned_len;
+#else
 	char *map, *end_map;
 	struct stat statbuf;
 	const char *begin, *eol;
+#endif
 
 	if (sess->text_scrollback == SET_DEFAULT)
 	{
@@ -293,6 +302,7 @@ scrollback_load (session *sess)
 	if (fh == -1)
 		return;
 
+#ifndef WIN32
 	if (fstat (fh, &statbuf) < 0)
 		return;
 
@@ -301,7 +311,7 @@ scrollback_load (session *sess)
 		return;
 
 	end_map = map + statbuf.st_size;
-	
+
 	lines = 0;
 	begin = map;
 	while (begin < end_map)
@@ -314,11 +324,11 @@ scrollback_load (session *sess)
 			eol = end_map;
 
 		n_bytes = MIN (eol - begin, sizeof (buf) - 1);
-		
+
 		strncpy (buf, begin, n_bytes);
 
 		buf[n_bytes] = 0;
-		
+
 		if (buf[0] == 'T')
 		{
 			if (sizeof (time_t) == 4)
@@ -350,6 +360,45 @@ scrollback_load (session *sess)
 	}
 
 	munmap (map, statbuf.st_size);
+#else
+	lines = 0;
+	while (waitline (fh, buf, sizeof buf, FALSE) != -1)
+	{
+		if (buf[0] == 'T')
+		{
+			if (sizeof (time_t) == 4)
+				stamp = strtoul (buf + 2, NULL, 10);
+			else
+				stamp = strtoull (buf + 2, NULL, 10); /* just incase time_t is 64 bits */
+			text = strchr (buf + 3, ' ');
+			if (text)
+			{
+				text = strip_color (text + 1, -1, STRIP_COLOR);
+				cleaned_text = text_replace_non_bmp (text, -1, &cleaned_len);
+				if (cleaned_text != NULL)
+				{
+					g_free (text);
+					text = cleaned_text;
+				}
+				fe_print_text (sess, text, stamp);
+				g_free (text);
+			}
+			lines++;
+		}
+	}
+
+	sess->scrollwritten = lines;
+
+	if (lines)
+	{
+		text = ctime (&stamp);
+		text[24] = 0;	/* get rid of the \n */
+		snprintf (buf, sizeof (buf), "\n*\t%s %s\n\n", _("Loaded log from"), text);
+		fe_print_text (sess, buf, 0);
+		/*EMIT_SIGNAL (XP_TE_GENMSG, sess, "*", buf, NULL, NULL, NULL, 0);*/
+	}
+#endif
+
 	close (fh);
 }
 
@@ -637,6 +686,13 @@ get_stamp_str (char *fmt, time_t tim, char **ret)
 	}
 
 	len = strftime (dest, sizeof (dest), fmt, localtime (&tim));
+#ifdef WIN32
+	if (!len)
+	{
+		/* use failsafe format until a correct one is specified */
+		len = strftime (dest, sizeof (dest), "[%H:%M]", localtime (&tim));
+	}
+#endif
 	if (len)
 	{
 		if (prefs.utf8_locale)
@@ -812,6 +868,46 @@ iso_8859_1_to_utf8 (unsigned char *text, int len, gsize *bytes_written)
 	return res;
 }
 
+#ifdef WIN32
+/* replace characters outside of the Basic Multilingual Plane with
+ * replacement characters (0xFFFD) */
+char *
+text_replace_non_bmp (char *utf8_input, int input_length, glong *output_length)
+{
+	gunichar *ucs4_text;
+	gunichar suspect;
+	gchar *utf8_text;
+	glong ucs4_length;
+	glong index;
+
+	ucs4_text = g_utf8_to_ucs4_fast (utf8_input, input_length, &ucs4_length);
+
+	/* replace anything not in the Basic Multilingual Plane
+	 * (code points above 0xFFFF) with the replacement
+	 * character */
+	for (index = 0; index < ucs4_length; index++)
+	{
+		suspect = ucs4_text[index];
+		if ((suspect >= 0x1D173 && suspect <= 0x1D17A)
+			|| (suspect >= 0xE0001 && suspect <= 0xE007F))
+		{
+			ucs4_text[index] = 0xFFFD; /* replacement character */
+		}
+	}
+
+	utf8_text = g_ucs4_to_utf8 (
+		ucs4_text,
+		ucs4_length,
+		NULL,
+		output_length,
+		NULL
+	);
+	g_free (ucs4_text);
+
+	return utf8_text;
+}
+#endif
+
 char *
 text_validate (char **text, int *len)
 {
diff --git a/src/common/text.h b/src/common/text.h
index 150821ae..6d5ac03e 100644
--- a/src/common/text.h
+++ b/src/common/text.h
@@ -28,6 +28,9 @@ int pevent_load (char *filename);
 void pevent_make_pntevts (void);
 void text_emit (int index, session *sess, char *a, char *b, char *c, char *d);
 int text_emit_by_name (char *name, session *sess, char *a, char *b, char *c, char *d);
+#ifdef WIN32
+char *text_replace_non_bmp (char *utf8_input, int input_length, glong *output_length);
+#endif
 char *text_validate (char **text, int *len);
 int get_stamp_str (char *fmt, time_t tim, char **ret);
 void format_event (session *sess, int index, char **args, char *o, int sizeofo, unsigned int stripcolor_args);
diff --git a/src/common/thread.c b/src/common/thread.c
new file mode 100644
index 00000000..02b17cfb
--- /dev/null
+++ b/src/common/thread.c
@@ -0,0 +1,33 @@
+#include <fcntl.h>
+#include "thread.h"
+
+thread *
+thread_new (void)
+{
+	thread *th;
+
+	th = calloc (1, sizeof (*th));
+	if (!th)
+	{
+		return NULL;
+	}
+
+	if (_pipe (th->pipe_fd, 4096, _O_BINARY) == -1)
+	{
+		free (th);
+		return NULL;
+	}
+
+	return th;
+}
+
+int
+thread_start (thread *th, void *(*start_routine)(void *), void *arg)
+{
+	DWORD id;
+
+	CloseHandle (CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, (DWORD *)&id));
+	th->threadid = id;
+
+	return 1;
+}
diff --git a/src/common/thread.h b/src/common/thread.h
new file mode 100644
index 00000000..7ca0f937
--- /dev/null
+++ b/src/common/thread.h
@@ -0,0 +1,10 @@
+#include <windows.h>
+
+typedef struct
+{
+	DWORD threadid;
+	int pipe_fd[2];
+} thread;
+
+thread *thread_new (void);
+int thread_start (thread *th, void *(*start_routine)(void *), void *arg);
diff --git a/src/common/url.c b/src/common/url.c
index b83732d1..9fa2d75c 100644
--- a/src/common/url.c
+++ b/src/common/url.c
@@ -82,7 +82,7 @@ url_find (char *urltext)
 {
 	int pos;
 
-	if (tree_find (url_tree, urltext, (tree_cmp_func *)strcasecmp, NULL, &pos))
+	if (tree_find (url_tree, urltext, (tree_cmp_func *)g_ascii_strcasecmp, NULL, &pos))
 		return 1;
 	return 0;
 }
@@ -117,7 +117,7 @@ url_add (char *urltext, int len)
 	}
 
 	if (!url_tree)
-		url_tree = tree_new ((tree_cmp_func *)strcasecmp, NULL);
+		url_tree = tree_new ((tree_cmp_func *)g_ascii_strcasecmp, NULL);
 
 	size = tree_size (url_tree);
 	/* 0 is unlimited */
@@ -186,7 +186,7 @@ url_check_word (char *word, int len)
 		{
 			int j;
 
-			/* This is pretty much strncasecmp(). */
+			/* This is pretty much g_ascii_strncasecmp(). */
 			for (j = 0; j < l; j++)
 			{
 				unsigned char c = word[j];
@@ -238,7 +238,7 @@ url_check_word (char *word, int len)
 				const unsigned char *p = &word[len - l];
 				int j;
 
-				/* This is pretty much strncasecmp(). */
+				/* This is pretty much g_ascii_strncasecmp(). */
 				for (j = 0; j < l; j++)
 				{
 					if (tolower(p[j]) != suffix[i].s[j])
diff --git a/src/common/util.c b/src/common/util.c
index 5a0ab6c5..fb4cd23e 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -16,26 +16,32 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
+#define WANTSOCKET
+#include "inet.h"				/* make it first to avoid macro redefinitions */
+
 #define __APPLE_API_STRICT_CONFORMANCE
 
 #define _FILE_OFFSET_BITS 64
 #include <stdio.h>
-#include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+
 #ifdef WIN32
 #include <sys/timeb.h>
 #include <process.h>
+#include <io.h>
+#include "../dirent/dirent-win32.h"
 #else
-#include <sys/types.h>
+#include <unistd.h>
 #include <pwd.h>
 #include <sys/time.h>
 #include <sys/utsname.h>
+#include <dirent.h>
 #endif
+
 #include <fcntl.h>
-#include <dirent.h>
 #include <errno.h>
 #include "xchat.h"
 #include "xchatc.h"
@@ -44,9 +50,6 @@
 #include "util.h"
 #include "../../config.h"
 
-#define WANTSOCKET
-#include "inet.h"
-
 #if defined (USING_FREEBSD) || defined (__APPLE__)
 #include <sys/sysctl.h>
 #endif
@@ -280,7 +283,7 @@ nocasestrstr (const char *s, const char *wanted)
 
 	if (len == 0)
 		return (char *)s;
-	while (rfc_tolower(*s) != rfc_tolower(*wanted) || strncasecmp (s, wanted, len))
+	while (rfc_tolower(*s) != rfc_tolower(*wanted) || g_ascii_strncasecmp (s, wanted, len))
 		if (*s++ == '\0')
 			return (char *)NULL;
 	return (char *)s;
@@ -383,6 +386,28 @@ waitline (int sok, char *buf, int bufsize, int use_recv)
 	}
 }
 
+#ifdef WIN32
+/* waitline2 using win32 file descriptor and glib instead of _read. win32 can't _read() sok! */
+int
+waitline2 (GIOChannel *source, char *buf, int bufsize)
+{
+	int i = 0;
+	int len;
+
+	while (1)
+	{
+		if (g_io_channel_read (source, &buf[i], 1, &len) != G_IO_ERROR_NONE)
+			return -1;
+		if (buf[i] == '\n' || bufsize == i + 1)
+		{
+			buf[i] = 0;
+			return i;
+		}
+		i++;
+	}
+}
+#endif
+
 /* checks for "~" in a file and expands */
 
 char *
@@ -624,30 +649,110 @@ get_mhz (void)
 	return 0;	/* fails on Win9x */
 }
 
+int
+get_cpu_arch (void)
+{
+	SYSTEM_INFO si;
+
+	GetSystemInfo (&si);
+
+	if (si.wProcessorArchitecture == 9)
+	{
+		return 64;
+	}
+	else
+	{
+		return 86;
+	}
+}
+
 char *
 get_cpu_str (void)
 {
 	static char verbuf[64];
-	OSVERSIONINFO osvi;
-	SYSTEM_INFO si;
+	static char winver[20];
+	OSVERSIONINFOEX osvi;
 	double mhz;
 
-	osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+	osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
 	GetVersionEx (&osvi);
-	GetSystemInfo (&si);
+
+	switch (osvi.dwMajorVersion)
+	{
+		case 5:
+			switch (osvi.dwMinorVersion)
+			{
+				case 1:
+					strcpy (winver, "XP");
+					break;
+				case 2:
+					if (osvi.wProductType == VER_NT_WORKSTATION)
+					{
+						strcpy (winver, "XP x64 Edition");
+					}
+					else
+					{
+						if (GetSystemMetrics(SM_SERVERR2) == 0)
+						{
+							strcpy (winver, "Server 2003");
+						}
+						else
+						{
+							strcpy (winver, "Server 2003 R2");
+						}
+					}
+					break;
+			}
+			break;
+		case 6:
+			switch (osvi.dwMinorVersion)
+			{
+				case 0:
+					if (osvi.wProductType == VER_NT_WORKSTATION)
+					{
+						strcpy (winver, "Vista");
+					}
+					else
+					{
+						strcpy (winver, "Server 2008");
+					}
+					break;
+				case 1:
+					if (osvi.wProductType == VER_NT_WORKSTATION)
+					{
+						strcpy (winver, "7");
+					}
+					else
+					{
+						strcpy (winver, "Server 2008 R2");
+					}
+					break;
+				case 2:
+					if (osvi.wProductType == VER_NT_WORKSTATION)
+					{
+						strcpy (winver, "8");
+					}
+					else
+					{
+						strcpy (winver, "8 Server");
+					}
+					break;
+			}
+			break;
+	}
 
 	mhz = get_mhz ();
 	if (mhz)
 	{
 		double cpuspeed = ( mhz > 1000 ) ? mhz / 1000 : mhz;
 		const char *cpuspeedstr = ( mhz > 1000 ) ? "GHz" : "MHz";
-		sprintf (verbuf, "Windows %ld.%ld [i%d86/%.2f%s]",
-					osvi.dwMajorVersion, osvi.dwMinorVersion, si.wProcessorLevel, 
-					cpuspeed, cpuspeedstr);
-	} else
-		sprintf (verbuf, "Windows %ld.%ld [i%d86]",
-			osvi.dwMajorVersion, osvi.dwMinorVersion, si.wProcessorLevel);
-
+		sprintf (verbuf, "Windows %s [%.2f%s]",	winver, cpuspeed, cpuspeedstr);
+	}
+	else
+	{
+		sprintf (verbuf, "Windows %s", winver);
+	}
+	
 	return verbuf;
 }
 
@@ -840,7 +945,7 @@ typedef struct
 static int
 country_compare (const void *a, const void *b)
 {
-	return strcasecmp (a, ((domain_t *)b)->code);
+	return g_ascii_strcasecmp (a, ((domain_t *)b)->code);
 }
 
 static const domain_t domain[] =
@@ -1727,3 +1832,55 @@ safe_strcpy (char *dest, const char *src, int bytes_left)
 		}
 	}
 }
+
+void
+canonalize_key (char *key)
+{
+	char *pos, token;
+
+	for (pos = key; (token = *pos) != 0; pos++)
+	{
+		if (token != '_' && (token < '0' || token > '9') && (token < 'A' || token > 'Z') && (token < 'a' || token > 'z'))
+		{
+			*pos = '_';
+		}
+		else
+		{
+			*pos = tolower(token);
+		}
+	}
+}
+
+int
+portable_mode ()
+{
+#ifdef WIN32
+	if ((_access( "portable-mode", 0 )) != -1)
+	{
+		return 1;
+	}
+	else
+	{
+		return 0;
+	}
+#else
+	return 0;
+#endif
+}
+
+int
+xtray_mode ()
+{
+#ifdef WIN32
+	if ((_access( "plugins/xtray.dll", 0 )) != -1)
+	{
+		return 1;
+	}
+	else
+	{
+		return 0;
+	}
+#else
+	return 0;
+#endif
+}
diff --git a/src/common/util.h b/src/common/util.h
index fce45def..82d74366 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -43,6 +43,12 @@ int strip_color2 (const char *src, int len, char *dst, int flags);
 int strip_hidden_attribute (char *src, char *dst);
 char *errorstring (int err);
 int waitline (int sok, char *buf, int bufsize, int);
+#ifdef WIN32
+int waitline2 (GIOChannel *source, char *buf, int bufsize);
+int get_cpu_arch (void);
+#else
+#define waitline2(source,buf,size) waitline(serv->childread,buf,size,0)
+#endif
 unsigned long make_ping_time (void);
 void move_file_utf8 (char *src_dir, char *dst_dir, char *fname, int dccpermissions);
 int mkdir_utf8 (char *dir);
@@ -50,5 +56,8 @@ int token_foreach (char *str, char sep, int (*callback) (char *str, void *ud), v
 guint32 str_hash (const char *key);
 guint32 str_ihash (const unsigned char *key);
 void safe_strcpy (char *dest, const char *src, int bytes_left);
+void canonalize_key (char *key);
+int portable_mode ();
+int xtray_mode ();
 
 #endif
diff --git a/src/common/xchat-plugin.h b/src/common/xchat-plugin.h
index 30b19295..1b7da8fb 100644
--- a/src/common/xchat-plugin.h
+++ b/src/common/xchat-plugin.h
@@ -137,6 +137,21 @@ struct _xchat_plugin
 	     int flags);
 	void (*xchat_free) (xchat_plugin *ph,
 	    void *ptr);
+	int (*xchat_pluginpref_set_str) (xchat_plugin *ph,
+		const char *var,
+		const char *value);
+	int (*xchat_pluginpref_get_str) (xchat_plugin *ph,
+		const char *var,
+		char *dest);
+	int (*xchat_pluginpref_set_int) (xchat_plugin *ph,
+		const char *var,
+		int value);
+	int (*xchat_pluginpref_get_int) (xchat_plugin *ph,
+		const char *var);
+	int (*xchat_pluginpref_delete) (xchat_plugin *ph,
+		const char *var);
+	int (*xchat_pluginpref_list) (xchat_plugin *ph,
+		char *dest);
 };
 #endif
 
@@ -292,6 +307,32 @@ void
 xchat_free (xchat_plugin *ph,
 	    void *ptr);
 
+int
+xchat_pluginpref_set_str (xchat_plugin *ph,
+		const char *var,
+		const char *value);
+
+int
+xchat_pluginpref_get_str (xchat_plugin *ph,
+		const char *var,
+		char *dest);
+
+int
+xchat_pluginpref_set_int (xchat_plugin *ph,
+		const char *var,
+		int value);
+int
+xchat_pluginpref_get_int (xchat_plugin *ph,
+		const char *var);
+
+int
+xchat_pluginpref_delete (xchat_plugin *ph,
+		const char *var);
+
+int
+xchat_pluginpref_list (xchat_plugin *ph,
+		char *dest);
+
 #if !defined(PLUGIN_C) && defined(WIN32)
 #ifndef XCHAT_PLUGIN_HANDLE
 #define XCHAT_PLUGIN_HANDLE (ph)
@@ -326,6 +367,12 @@ xchat_free (xchat_plugin *ph,
 #define xchat_send_modes ((XCHAT_PLUGIN_HANDLE)->xchat_send_modes)
 #define xchat_strip ((XCHAT_PLUGIN_HANDLE)->xchat_strip)
 #define xchat_free ((XCHAT_PLUGIN_HANDLE)->xchat_free)
+#define xchat_pluginpref_set_str ((XCHAT_PLUGIN_HANDLE)->xchat_pluginpref_set_str)
+#define xchat_pluginpref_get_str ((XCHAT_PLUGIN_HANDLE)->xchat_pluginpref_get_str)
+#define xchat_pluginpref_set_int ((XCHAT_PLUGIN_HANDLE)->xchat_pluginpref_set_int)
+#define xchat_pluginpref_get_int ((XCHAT_PLUGIN_HANDLE)->xchat_pluginpref_get_int)
+#define xchat_pluginpref_delete ((XCHAT_PLUGIN_HANDLE)->xchat_pluginpref_delete)
+#define xchat_pluginpref_list ((XCHAT_PLUGIN_HANDLE)->xchat_pluginpref_list)
 #endif
 
 #ifdef __cplusplus
diff --git a/src/common/xchat.c b/src/common/xchat.c
index afac9a0e..845f262b 100644
--- a/src/common/xchat.c
+++ b/src/common/xchat.c
@@ -22,14 +22,16 @@
 #include <time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
 
 #define WANTSOCKET
 #include "inet.h"
 
-#ifndef WIN32
+#ifdef WIN32
+#include <windows.h>
+#else
 #include <sys/wait.h>
 #include <signal.h>
+#include <unistd.h>
 #endif
 
 #include "xchat.h"
@@ -590,6 +592,7 @@ static char defaultconf_commands[] =
 	"NAME DMSG\n"			"CMD msg =%2 &3\n\n"\
 	"NAME EXIT\n"			"CMD quit\n\n"\
 	"NAME GREP\n"			"CMD lastlog -r &2\n\n"\
+	"NAME IGNALL\n"			"CMD ignore %2!*@* ALL\n\n"\
 	"NAME J\n"				"CMD join &2\n\n"\
 	"NAME KILL\n"			"CMD quote KILL %2 :&3\n\n"\
 	"NAME LEAVE\n"			"CMD part &2\n\n"\
@@ -899,11 +902,55 @@ xchat_execv (char * const argv[])
 #endif
 }
 
+#ifdef WIN32
+static void
+xchat_restore_window (HWND xchat_window)
+{
+	/* ShowWindow (xchat_window, SW_RESTORE); another way, but works worse */
+	SendMessage (xchat_window, WM_SYSCOMMAND, SC_RESTORE, 0);
+	SetForegroundWindow (xchat_window);
+}
+
+BOOL CALLBACK
+enum_windows_impl (HWND current_window, LPARAM lParam)
+{
+	TCHAR window_name[10];
+	TCHAR module_path[1024];
+	ZeroMemory (&window_name, sizeof (window_name));
+
+	if (!current_window)
+	{
+		return TRUE;
+	}
+
+	GetWindowText (current_window, window_name, 10);
+	if (stricmp (window_name, "xchat-wdk") == 0)
+	{
+		/* use a separate if block, this way we don't have to call GetWindowModuleFileName() for each hit */
+		ZeroMemory (&module_path, sizeof (module_path));
+		GetWindowModuleFileName (current_window, module_path, sizeof (module_path));
+
+		if (strstr (module_path, "xchat.exe"))	/* We've found it, stop */
+		{
+			xchat_restore_window (current_window);
+			return FALSE;
+		}
+	}
+
+	return TRUE;								/* Keep searching */
+
+}
+#endif
+
 int
 main (int argc, char *argv[])
 {
 	int ret;
-	
+
+#ifdef WIN32
+	HANDLE mutex;
+#endif
+
 	srand (time (0));	/* CL: do this only once! */
 
 #ifdef SOCKS
@@ -920,6 +967,34 @@ main (int argc, char *argv[])
 
 	load_config ();
 
+#ifdef WIN32
+	if (prefs.gui_one_instance && !portable_mode ())
+	{
+		DWORD error;
+
+		mutex = CreateMutex (NULL, TRUE, "Local\xchat");
+		error = GetLastError ();
+
+		if (error == ERROR_ALREADY_EXISTS || mutex == NULL)
+		{
+			/* restoring the XChat window from the tray via the taskbar icon
+			 * only works correctly when X-Tray is used, but it's not a big deal
+			 * since you can only minimize XChat to tray via the taskbar if you
+			 * use X-Tray*/
+			if (xtray_mode ())
+			{
+				/* FindWindow() doesn't support wildcards so we check all the open windows */
+				EnumWindows (enum_windows_impl, NULL);
+				return 0;
+			}
+			else
+			{
+				return 1;
+			}
+		}
+	}
+#endif
+
 #ifdef USE_LIBPROXY
 	libproxy_factory = px_proxy_factory_new();
 #endif
@@ -945,6 +1020,11 @@ main (int argc, char *argv[])
 
 #ifdef WIN32
 	WSACleanup ();
+
+	if (prefs.gui_one_instance && !portable_mode ())
+	{
+		CloseHandle (mutex);
+	}
 #endif
 
 	return 0;
diff --git a/src/common/xchat.h b/src/common/xchat.h
index 6e31d7c5..85c20186 100644
--- a/src/common/xchat.h
+++ b/src/common/xchat.h
@@ -13,7 +13,7 @@
 #endif
 
 #ifndef HAVE_VSNPRINTF
-#define vsnprintf g_vsnprintf
+#define vsnprintf _vsnprintf
 #endif
 
 #ifdef USE_DEBUG
@@ -41,8 +41,8 @@ void *xchat_realloc (char *old, int len, char *file, int line);
 
 #ifdef __EMX__						  /* for o/s 2 */
 #define OFLAGS O_BINARY
-#define strcasecmp stricmp
-#define strncasecmp strnicmp
+#define g_ascii_strcasecmp stricmp
+#define g_ascii_strncasecmp strnicmp
 #define PATH_MAX MAXPATHLEN
 #define FILEPATH_LEN_MAX MAXPATHLEN
 #endif
@@ -54,7 +54,7 @@ void *xchat_realloc (char *old, int len, char *file, int line);
 
 #ifdef WIN32						/* for win32 */
 #define OFLAGS O_BINARY
-#define sleep(t) _sleep(t*1000)
+#define sleep(t) Sleep(t*1000)
 #include <direct.h>
 #define	F_OK	0
 #define	X_OK	1
@@ -113,8 +113,16 @@ struct xchatprefs
 	char awayreason[256];
 	char quitreason[256];
 	char partreason[256];
+#ifdef WIN32
+	char font_normal[4 * FONTNAMELEN + 1];
+	char font_main[FONTNAMELEN + 1];
+	char font_alternative[3 * FONTNAMELEN + 1];
+#else
 	char font_normal[FONTNAMELEN + 1];
+#endif
 	char doubleclickuser[256];
+	char gui_license[64];
+	char spell_langs[64];
 	char sounddir[PATHLEN + 1];
 	char soundcmd[PATHLEN + 1];
 	char background[PATHLEN + 1];
@@ -152,6 +160,7 @@ struct xchatprefs
 
 	int gui_pane_left_size;
 	int gui_pane_right_size;
+	int gui_pane_right_size_min;
 
 	int gui_ulist_pos;
 	int tab_pos;
@@ -178,6 +187,9 @@ struct xchatprefs
 	int gui_usermenu;
 	int gui_join_dialog;
 	int gui_quit_dialog;
+#ifdef WIN32
+	int gui_one_instance;
+#endif
 	int dialog_left;
 	int dialog_top;
 	int dialog_width;
@@ -205,6 +217,9 @@ struct xchatprefs
 	unsigned int wallops;
 	unsigned int skipmotd;
 	unsigned int autorejoin;
+	unsigned int autocopy_text;
+	unsigned int autocopy_stamp;
+	unsigned int autocopy_color;
 	unsigned int colorednicks;
 	unsigned int chanmodebuttons;
 	unsigned int userlistbuttons;
@@ -292,7 +307,12 @@ struct xchatprefs
 	unsigned int wait_on_exit;
 	unsigned int confmode;
 	unsigned int utf8_locale;
+#ifdef WIN32
 	unsigned int identd;
+	unsigned int emoticons;
+	unsigned int tab_icons;
+	unsigned int tab_xp;
+#endif
 
 	unsigned int ctcp_number_limit;	/*flood */
 	unsigned int ctcp_time_limit;	/*seconds of floods */
@@ -306,6 +326,11 @@ struct xchatprefs
 		This is so that we continue using internal defaults (which can
 		change in the next release) until the user edits them. */
 	unsigned int save_pevents:1;
+	unsigned int text_search_case_match;
+	unsigned int text_search_backward;
+	unsigned int text_search_highlight_all;
+	unsigned int text_search_follow;
+	unsigned int text_search_regexp;
 };
 
 /* Session types */
diff --git a/src/dirent/dirent-win32.c b/src/dirent/dirent-win32.c
new file mode 100644
index 00000000..273c6732
--- /dev/null
+++ b/src/dirent/dirent-win32.c
@@ -0,0 +1,199 @@
+/*****************************************************************************
+ * dirent.h - dirent API for Microsoft Visual Studio
+ *
+ * Copyright (C) 2006 Toni Ronkko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * ``Software''), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Dec 15, 2009, John Cunningham
+ * Added rewinddir member function
+ *
+ * Jan 18, 2008, Toni Ronkko
+ * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
+ * between multi-byte and unicode representations.  This makes the
+ * code simpler and also allows the code to be compiled under MingW.  Thanks
+ * to Azriel Fasten for the suggestion.
+ *
+ * Mar 4, 2007, Toni Ronkko
+ * Bug fix: due to the strncpy_s() function this file only compiled in
+ * Visual Studio 2005.  Using the new string functions only when the
+ * compiler version allows.
+ *
+ * Nov  2, 2006, Toni Ronkko
+ * Major update: removed support for Watcom C, MS-DOS and Turbo C to
+ * simplify the file, updated the code to compile cleanly on Visual
+ * Studio 2005 with both unicode and multi-byte character strings,
+ * removed rewinddir() as it had a bug.
+ *
+ * Aug 20, 2006, Toni Ronkko
+ * Removed all remarks about MSVC 1.0, which is antiqued now.  Simplified
+ * comments by removing SGML tags.
+ *
+ * May 14 2002, Toni Ronkko
+ * Embedded the function definitions directly to the header so that no
+ * source modules need to be included in the Visual Studio project.  Removed
+ * all the dependencies to other projects so that this very header can be
+ * used independently.
+ *
+ * May 28 1998, Toni Ronkko
+ * First version.
+ *****************************************************************************/
+
+#include "dirent-win32.h"
+
+/* Use the new safe string functions introduced in Visual Studio 2005 */
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+# define STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE)
+#else
+# define STRNCPY(dest,src,size) strncpy((dest),(src),(size))
+#endif
+
+
+/*****************************************************************************
+ * Open directory stream DIRNAME for read and return a pointer to the
+ * internal working area that is used to retrieve individual directory
+ * entries.
+ */
+DIR *opendir(const char *dirname)
+{
+   DIR *dirp;
+   assert (dirname != NULL);
+   assert (strlen (dirname) < MAX_PATH);
+
+   /* construct new DIR structure */
+   dirp = (DIR*) malloc (sizeof (struct DIR));
+   if (dirp != NULL) {
+      char *p;
+
+      /* take directory name... */
+      STRNCPY (dirp->patt, dirname, sizeof(dirp->patt));
+      dirp->patt[MAX_PATH] = '\0';
+
+      /* ... and append search pattern to it */
+      p = strchr (dirp->patt, '\0');
+      if (dirp->patt < p  &&  *(p-1) != '\\'  &&  *(p-1) != ':') {
+         *p++ = '\\';
+      }
+      *p++ = '*';
+      *p = '\0';
+
+      /* open stream and retrieve first file */
+      dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->current.data);
+      if (dirp->search_handle == INVALID_HANDLE_VALUE) {
+         /* invalid search pattern? */
+         free (dirp);
+         return NULL;
+      }
+
+      /* there is an un-processed directory entry in memory now */
+      dirp->cached = 1;
+   }
+
+   return dirp;
+}
+
+
+/*****************************************************************************
+ * Read a directory entry, and return a pointer to a dirent structure
+ * containing the name of the entry in d_name field.  Individual directory
+ * entries returned by this very function include regular files,
+ * sub-directories, pseudo-directories "." and "..", but also volume labels,
+ * hidden files and system files may be returned.
+ */
+struct dirent *readdir(DIR *dirp)
+{
+   assert (dirp != NULL);
+
+   if (dirp->search_handle == INVALID_HANDLE_VALUE) {
+      /* directory stream was opened/rewound incorrectly or ended normally */
+      return NULL;
+   }
+
+   /* get next directory entry */
+   if (dirp->cached != 0) {
+      /* a valid directory entry already in memory */
+      dirp->cached = 0;
+   } else {
+      /* read next directory entry from disk */
+      if (FindNextFileA (dirp->search_handle, &dirp->current.data) == FALSE) {
+         /* the very last file has been processed or an error occured */
+         FindClose (dirp->search_handle);
+         dirp->search_handle = INVALID_HANDLE_VALUE;
+         return NULL;
+      }
+   }
+
+   /* copy as a multibyte character string */
+   STRNCPY ( dirp->current.d_name,
+             dirp->current.data.cFileName,
+             sizeof(dirp->current.d_name) );
+   dirp->current.d_name[MAX_PATH] = '\0';
+
+   return &dirp->current;
+}
+
+
+/*****************************************************************************
+ * Close directory stream opened by opendir() function.  Close of the
+ * directory stream invalidates the DIR structure as well as any previously
+ * read directory entry.
+ */
+int closedir(DIR *dirp)
+{
+   assert (dirp != NULL);
+
+   /* release search handle */
+   if (dirp->search_handle != INVALID_HANDLE_VALUE) {
+      FindClose (dirp->search_handle);
+      dirp->search_handle = INVALID_HANDLE_VALUE;
+   }
+
+   /* release directory handle */
+   free (dirp);
+   return 0;
+}
+
+
+/*****************************************************************************
+ * Resets the position of the directory stream to which dirp refers to the
+ * beginning of the directory. It also causes the directory stream to refer
+ * to the current state of the corresponding directory, as a call to opendir()
+ * would have done. If dirp does not refer to a directory stream, the effect
+ * is undefined.
+ */
+void rewinddir(DIR* dirp)
+{
+   /* release search handle */
+   if (dirp->search_handle != INVALID_HANDLE_VALUE) {
+      FindClose (dirp->search_handle);
+      dirp->search_handle = INVALID_HANDLE_VALUE;
+   }
+
+   /* open new search handle and retrieve first file */
+   dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->current.data);
+   if (dirp->search_handle == INVALID_HANDLE_VALUE) {
+      /* invalid search pattern? */
+      free (dirp);
+      return;
+   }
+
+   /* there is an un-processed directory entry in memory now */
+   dirp->cached = 1;
+}
diff --git a/src/dirent/dirent-win32.h b/src/dirent/dirent-win32.h
new file mode 100644
index 00000000..cbb753e6
--- /dev/null
+++ b/src/dirent/dirent-win32.h
@@ -0,0 +1,28 @@
+#ifndef DIRENT_H
+#define DIRENT_H
+
+#include <windows.h>
+#include <string.h>
+#include <assert.h>
+
+typedef struct dirent
+{
+   char d_name[MAX_PATH + 1]; /* current dir entry (multi-byte char string) */
+   WIN32_FIND_DATAA data;     /* file attributes */
+}  dirent;
+
+typedef struct DIR
+{
+   dirent current;            /* Current directory entry */
+   int    cached;             /* Indicates un-processed entry in memory */
+   HANDLE search_handle;      /* File search handle */
+   char   patt[MAX_PATH + 3]; /* search pattern (3 = pattern + "\\*\0") */
+} DIR;
+
+/* Forward declarations */
+DIR *opendir (const char *dirname);
+struct dirent *readdir (DIR *dirp);
+int closedir (DIR *dirp);
+void rewinddir(DIR* dirp);
+
+#endif /*DIRENT_H*/
diff --git a/src/dirent/dirent.vcxproj b/src/dirent/dirent.vcxproj
new file mode 100644
index 00000000..5ae75f57
--- /dev/null
+++ b/src/dirent/dirent.vcxproj
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="dirent-win32.h" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="dirent-win32.c" />

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{98B56DF9-E4F1-4696-A565-5F7823CF214D}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>dirent</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <TargetName>$(ProjectName)-win32</TargetName>

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <TargetName>$(ProjectName)-win32</TargetName>

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level1</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level1</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;_WIN64;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/dirent/dirent.vcxproj.filters b/src/dirent/dirent.vcxproj.filters
new file mode 100644
index 00000000..d889015d
--- /dev/null
+++ b/src/dirent/dirent.vcxproj.filters
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="dirent-win32.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="dirent-win32.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/dirent/dirent.vcxproj.user b/src/dirent/dirent.vcxproj.user
new file mode 100644
index 00000000..695b5c78
--- /dev/null
+++ b/src/dirent/dirent.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+</Project>
\ No newline at end of file
diff --git a/src/fe-gtk/Makefile.am b/src/fe-gtk/Makefile.am
index 7db38096..da36ed57 100644
--- a/src/fe-gtk/Makefile.am
+++ b/src/fe-gtk/Makefile.am
@@ -10,8 +10,8 @@ EXTRA_DIST = \
 	about.h ascii.h banlist.h chanlist.h chanview.h chanview-tabs.c \
 	chanview-tree.c custom-list.h editlist.h fe-gtk.h fkeys.h gtkutil.h joind.h \
 	maingui.h menu.h mmx_cmod.S mmx_cmod.h notifygui.h palette.h pixmaps.h \
-	plugin-tray.h plugingui.c plugingui.h rawlog.h search.h sexy-spell-entry.h \
-   textgui.h urlgrab.h userlistgui.h xtext.h
+	plugin-tray.h plugingui.c plugingui.h rawlog.h search.h sexy-iso-codes.h \
+	sexy-spell-entry.h sexy-marshal.h textgui.h urlgrab.h userlistgui.h xtext.h
 
 if USE_MMX
 mmx_cmod_S = mmx_cmod.S
@@ -22,11 +22,12 @@ plugingui_c = plugingui.c
 endif
 
 if USE_LIBSEXY
-sexy_spell_entry_c = sexy-spell-entry.c
+sexy_spell = \
+	sexy-iso-codes.c sexy-marshal.c sexy-spell-entry.c
 endif
 
 xchat_SOURCES = about.c ascii.c banlist.c chanlist.c chanview.c custom-list.c \
 	dccgui.c editlist.c fe-gtk.c fkeys.c gtkutil.c ignoregui.c joind.c menu.c \
 	maingui.c $(mmx_cmod_S) notifygui.c palette.c pixmaps.c plugin-tray.c $(plugingui_c) \
-	rawlog.c search.c servlistgui.c setup.c $(sexy_spell_entry_c) textgui.c \
+	rawlog.c search.c servlistgui.c setup.c $(sexy_spell) textgui.c \
 	urlgrab.c userlistgui.c xtext.c
diff --git a/src/fe-gtk/about.c b/src/fe-gtk/about.c
index 60700aec..dc1cbf08 100644
--- a/src/fe-gtk/about.c
+++ b/src/fe-gtk/about.c
@@ -39,6 +39,7 @@
 
 #include "../common/xchat.h"
 #include "../common/util.h"
+#include "../common/xchatc.h"
 #include "palette.h"
 #include "pixmaps.h"
 #include "gtkutil.h"
@@ -69,7 +70,7 @@ menu_about (GtkWidget * wid, gpointer sess)
 							"(C) 1998-2005 Peter Zelezny", author, buf, 0));
 }
 
-#else
+#endif
 
 static GtkWidget *about = 0;
 
@@ -95,7 +96,7 @@ menu_about (GtkWidget * wid, gpointer sess)
 	}
 
 	about = gtk_dialog_new ();
-	gtk_window_set_position (GTK_WINDOW (about), GTK_WIN_POS_CENTER);
+	gtk_window_set_position (GTK_WINDOW (about), GTK_WIN_POS_CENTER_ON_PARENT);
 	gtk_window_set_resizable (GTK_WINDOW (about), FALSE);
 	gtk_window_set_title (GTK_WINDOW (about), _("About "DISPLAY_NAME));
 	if (parent_window)
@@ -113,36 +114,47 @@ menu_about (GtkWidget * wid, gpointer sess)
 	gtk_container_add (GTK_CONTAINER (vbox), label);
 	g_get_charset (&locale);
 	(snprintf) (buf, sizeof (buf),
-				"<span size=\"x-large\"><b>"DISPLAY_NAME" "PACKAGE_VERSION"</b></span>\n\n"
-				"%s\n\n"
+				"<span size=\"x-large\"><b>"DISPLAY_NAME" "PACKAGE_VERSION"</b></span>\n"
 #ifdef WIN32
-				/* leave this message to avoid time wasting bug reports! */
-				"This version is unofficial and comes with no support.\n\n"
-#endif
-				"%s\n"
+				"%s%s%s"
+				"\n<b>XChat Release</b>: "XCHAT_RELEASE"\n\n"
+				"<b>OS</b>: %s\n"
 				"<b>Charset</b>: %s "
-#ifdef WIN32 
 				"<b>GTK+</b>: %i.%i.%i\n"
+				"<b>Compiled</b>: "__DATE__"\n"
+				"<b>Portable Mode</b>: %s\n"
+				"<b>Build Type</b>: x%d\n\n"
+				"<small>This version is unofficial and comes with no support.\n"
+				"\302\251 1998-2010 Peter \305\275elezn\303\275 &lt;zed@xchat.org>"
+				/* "\n<a href=\"http://code.google.com/p/xchat-wdk/\">http://code.google.com/p/xchat-wdk/</a>" this is broken in gtk ATM */
+				"</small>",
+				(strcmp (prefs.gui_license, "") ? "<span size=\"x-large\">" : ""),
+				(strcmp (prefs.gui_license, "") ? prefs.gui_license : ""),
+				(strcmp (prefs.gui_license, "") ? "</span>\n" : ""),
+				get_cpu_str (),
+				locale,
+				gtk_major_version,
+				gtk_minor_version,
+				gtk_micro_version,
+				(portable_mode () ? "Yes" : "No"),
+				get_cpu_arch ()
 #else
+				"\n%s\n\n"
+				"%s\n"
+				"<b>Charset</b>: %s "
 				"<b>Renderer</b>: %s\n"
-#endif
 				"<b>Compiled</b>: "__DATE__"\n\n"
 				"<small>\302\251 1998-2010 Peter \305\275elezn\303\275 &lt;zed@xchat.org></small>",
-					_("A multiplatform IRC Client"),
-					get_cpu_str(),
-					locale,
-#ifdef WIN32
-					gtk_major_version,
-					gtk_minor_version,
-					gtk_micro_version
-#else
+				_("A multiplatform IRC Client"),
+				get_cpu_str (),
+				locale,
 #ifdef USE_XFT
-					"Xft"
+				"Xft"
 #else
-					"Pango"
+				"Pango"
 #endif
 #endif
-					);
+				);
 	gtk_label_set_markup (GTK_LABEL (label), buf);
 	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
 
@@ -158,4 +170,3 @@ menu_about (GtkWidget * wid, gpointer sess)
 
 	gtk_widget_show_all (about);
 }
-#endif
diff --git a/src/fe-gtk/banlist.c b/src/fe-gtk/banlist.c
index afaa7eb4..fecb62a5 100644
--- a/src/fe-gtk/banlist.c
+++ b/src/fe-gtk/banlist.c
@@ -19,10 +19,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #include <fcntl.h>
 #include <time.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "fe-gtk.h"
 
 #include <gtk/gtkhbox.h>
@@ -134,11 +137,8 @@ banlist_do_refresh (struct session *sess)
 		gtk_list_store_clear (store);
 
 		handle_command (sess, "ban", FALSE);
-#ifdef WIN32
-		if (0)
-#else
+
 		if (supports_exempt (sess->server))
-#endif
 		{
 			snprintf (tbuf, sizeof (tbuf), "quote mode %s +e", sess->channel);
 			handle_command (sess, tbuf, FALSE);
diff --git a/src/fe-gtk/chanlist.c b/src/fe-gtk/chanlist.c
index 2f65b518..4dca935b 100644
--- a/src/fe-gtk/chanlist.c
+++ b/src/fe-gtk/chanlist.c
@@ -19,10 +19,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #include <fcntl.h>
 #include <time.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "fe-gtk.h"
 
 #include <gtk/gtkalignment.h>
diff --git a/src/fe-gtk/chanview-tabs.c b/src/fe-gtk/chanview-tabs.c
index 8e3da8e6..f99e61f1 100644
--- a/src/fe-gtk/chanview-tabs.c
+++ b/src/fe-gtk/chanview-tabs.c
@@ -144,8 +144,8 @@ tab_scroll_left_up_clicked (GtkWidget *widget, chanview *cv)
 		for (i = adj->value; ((i > new_value) && (tab_left_is_moving)); i -= 0.1)
 		{
 			gtk_adjustment_set_value (adj, i);
-			while (g_main_pending ())
-				g_main_iteration (TRUE);
+			while (g_main_context_pending (NULL))
+				g_main_context_iteration (NULL, TRUE);
 		}
 
 		gtk_adjustment_set_value (adj, new_value);
@@ -191,8 +191,8 @@ tab_scroll_right_down_clicked (GtkWidget *widget, chanview *cv)
 		for (i = adj->value; ((i < new_value) && (tab_right_is_moving)); i += 0.1)
 		{
 			gtk_adjustment_set_value (adj, i);
-			while (g_main_pending ())
-				g_main_iteration (TRUE);
+			while (g_main_context_pending (NULL))
+				g_main_context_iteration (NULL, TRUE);
 		}
 
 		gtk_adjustment_set_value (adj, new_value);
diff --git a/src/fe-gtk/custom-list.c b/src/fe-gtk/custom-list.c
index ac20e0ff..0c3c40b5 100644
--- a/src/fe-gtk/custom-list.c
+++ b/src/fe-gtk/custom-list.c
@@ -106,7 +106,7 @@ custom_list_sortable_init (GtkTreeSortableIface * iface)
  *
  *****************************************************************************/
 
-static GType
+GType
 custom_list_get_type (void)
 {
 	static GType custom_list_type = 0;
diff --git a/src/fe-gtk/editlist.c b/src/fe-gtk/editlist.c
index 5af67e32..d374d064 100644
--- a/src/fe-gtk/editlist.c
+++ b/src/fe-gtk/editlist.c
@@ -19,10 +19,14 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "fe-gtk.h"
 
 #include <gtk/gtkstock.h>
diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c
index 5efcaeec..88a1138c 100644
--- a/src/fe-gtk/fe-gtk.c
+++ b/src/fe-gtk/fe-gtk.c
@@ -19,7 +19,6 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <unistd.h>
 
 #include "fe-gtk.h"
 
@@ -32,6 +31,12 @@
 #include <gtk/gtkmessagedialog.h>
 #include <gtk/gtkversion.h>
 
+#ifdef WIN32
+#include <gdk/gdkwin32.h>
+#else
+#include <unistd.h>
+#endif
+
 #include "../common/xchat.h"
 #include "../common/fe.h"
 #include "../common/util.h"
@@ -39,6 +44,7 @@
 #include "../common/cfgfiles.h"
 #include "../common/xchatc.h"
 #include "../common/plugin.h"
+#include "../common/server.h"
 #include "gtkutil.h"
 #include "maingui.h"
 #include "pixmaps.h"
@@ -136,11 +142,26 @@ static const GOptionEntry gopt_entries[] =
  {NULL}
 };
 
+#ifdef WIN32
+static void
+create_msg_dialog (gchar *title, gchar *message)
+{
+	GtkWidget *dialog;
+	dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, message);
+	gtk_window_set_title (GTK_WINDOW (dialog), title);
+	gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
+}
+#endif
+
 int
 fe_args (int argc, char *argv[])
 {
 	GError *error = NULL;
 	GOptionContext *context;
+#ifdef WIN32
+	char *buffer[2048];
+#endif
 
 #ifdef ENABLE_NLS
 	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
@@ -149,22 +170,67 @@ fe_args (int argc, char *argv[])
 #endif
 
 	context = g_option_context_new (NULL);
+#ifdef WIN32
+	g_option_context_set_help_enabled (context, FALSE);	/* disable stdout help as stdout is unavailable for subsystem:windows */
+#endif
 	g_option_context_add_main_entries (context, gopt_entries, GETTEXT_PACKAGE);
 	g_option_context_add_group (context, gtk_get_option_group (FALSE));
 	g_option_context_parse (context, &argc, &argv, &error);
 
+#ifdef WIN32
+	if (error)											/* workaround for argv not being available when using subsystem:windows */
+	{
+		if (error->message)								/* the error message contains argv so search for patterns in that */
+		{
+			if (strstr (error->message, "--help-all") != NULL)
+			{
+				if (snprintf (buffer, 2048, g_option_context_get_help (context, FALSE, NULL)))
+				{
+					gtk_init (&argc, &argv);
+					create_msg_dialog ("Long Help", buffer);
+				}
+				return 0;
+			} else if (strstr (error->message, "--help") != NULL || strstr (error->message, "-?") != NULL)
+			{
+				if (snprintf (buffer, 2048, g_option_context_get_help (context, TRUE, NULL)))
+				{
+					gtk_init (&argc, &argv);
+					create_msg_dialog ("Help", buffer);
+				}
+				return 0;
+			} else 
+			{
+				if (snprintf (buffer, 2048, "%s\n", error->message))
+				{
+					gtk_init (&argc, &argv);
+					create_msg_dialog ("Error", buffer);
+				}
+				return 1;
+			}
+		}
+	}
+#else
 	if (error)
 	{
 		if (error->message)
 			printf ("%s\n", error->message);
 		return 1;
 	}
+#endif
 
 	g_option_context_free (context);
 
 	if (arg_show_version)
 	{
+#ifdef WIN32
+		if (snprintf (buffer, 2048, DISPLAY_NAME" "PACKAGE_VERSION"\n"))
+		{
+			gtk_init (&argc, &argv);
+			create_msg_dialog ("Version Information", buffer);
+		}
+#else
 		printf (PACKAGE_TARNAME" "PACKAGE_VERSION"\n");
+#endif
 		return 0;
 	}
 
@@ -177,7 +243,18 @@ fe_args (int argc, char *argv[])
 		if (sl)
 		{
 			*sl = 0;
-			printf ("%s\\plugins\n", exe);
+			if (snprintf (buffer, 2048, "%s\\plugins\n", exe))
+			{
+				gtk_init (&argc, &argv);
+				create_msg_dialog ("Plugin Auto-load Directory", buffer);
+			}
+		} else
+		{
+			if (snprintf (buffer, 2048, ".\\plugins\n"))
+			{
+				gtk_init (&argc, &argv);
+				create_msg_dialog ("Plugin Auto-load Directory", buffer);
+			}
 		}
 #else
 		printf ("%s\n", XCHATLIBDIR"/plugins");
@@ -187,7 +264,15 @@ fe_args (int argc, char *argv[])
 
 	if (arg_show_config)
 	{
+#ifdef WIN32
+		if (snprintf (buffer, 2048, "%s\n", get_xdir_fs ()))
+		{
+			gtk_init (&argc, &argv);
+			create_msg_dialog ("User Config Directory", buffer);
+		}
+#else
 		printf ("%s\n", get_xdir_fs ());
+#endif
 		return 0;
 	}
 
@@ -330,7 +415,7 @@ log_handler (const gchar   *log_domain,
 {
 	session *sess;
 
-	if (getenv ("XCHAT_WARNING_IGNORE"))
+	/* if (getenv ("XCHAT_WARNING_IGNORE")) this gets ignored sometimes, so simply just disable all warnings */
 		return;
 
 	sess = find_dialog (serv_list->data, "(warnings)");
@@ -845,7 +930,11 @@ fe_gui_info_ptr (session *sess, int info_type)
 	{
 	case 0:	/* native window pointer (for plugins) */
 #ifdef WIN32
+#if GTK_CHECK_VERSION(2,24,8)
+		return gdk_win32_window_get_impl_hwnd (sess->gui->window->window);
+#else
 		return GDK_WINDOW_HWND (sess->gui->window->window);
+#endif
 #else
 		return sess->gui->window;
 #endif
diff --git a/src/fe-gtk/fe-gtk.h b/src/fe-gtk/fe-gtk.h
index 12516259..8fffb3cc 100644
--- a/src/fe-gtk/fe-gtk.h
+++ b/src/fe-gtk/fe-gtk.h
@@ -1,13 +1,6 @@
 #include "../../config.h"
 
-#ifdef WIN32
-/* If you're compiling this for Windows, your release is un-official
- * and not condoned. Please don't use the XChat name. Make up your
- * own name! */
-#define DISPLAY_NAME "XChat-Unofficial"
-#else
-#define DISPLAY_NAME "XChat"
-#endif
+#define DISPLAY_NAME "XChat-WDK"
 
 #ifndef WIN32
 #include <sys/types.h>
diff --git a/src/fe-gtk/fe-gtk.vcxproj b/src/fe-gtk/fe-gtk.vcxproj
new file mode 100644
index 00000000..cb102012
--- /dev/null
+++ b/src/fe-gtk/fe-gtk.vcxproj
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{E4BDB4C8-2335-415A-ACEE-BA88B19BFE82}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>fegtk</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <TargetName>xchat</TargetName>

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <TargetName>xchat</TargetName>

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level1</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(DepLibs);common.lib;dirent-win32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <EntryPointSymbol>mainCRTStartup</EntryPointSymbol>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level1</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;_WIN64;NDEBUG;_WINDOWS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(DepLibs);common.lib;dirent-win32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <EntryPointSymbol>mainCRTStartup</EntryPointSymbol>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClInclude Include="about.h" />

+    <ClInclude Include="ascii.h" />

+    <ClInclude Include="banlist.h" />

+    <ClInclude Include="chanlist.h" />

+    <ClInclude Include="chanview.h" />

+    <ClInclude Include="custom-list.h" />

+    <ClInclude Include="editlist.h" />

+    <ClInclude Include="fe-gtk.h" />

+    <ClInclude Include="fkeys.h" />

+    <ClInclude Include="gtkutil.h" />

+    <ClInclude Include="joind.h" />

+    <ClInclude Include="maingui.h" />

+    <ClInclude Include="menu.h" />

+    <ClInclude Include="mmx_cmod.h" />

+    <ClInclude Include="notifygui.h" />

+    <ClInclude Include="palette.h" />

+    <ClInclude Include="pixmaps.h" />

+    <ClInclude Include="plugin-tray.h" />

+    <ClInclude Include="plugingui.h" />

+    <ClInclude Include="rawlog.h" />

+    <ClInclude Include="search.h" />

+    <ClInclude Include="sexy-iso-codes.h" />

+    <ClInclude Include="sexy-marshal.h" />

+    <ClInclude Include="sexy-spell-entry.h" />

+    <ClInclude Include="textgui.h" />

+    <ClInclude Include="typedef.h" />

+    <ClInclude Include="urlgrab.h" />

+    <ClInclude Include="userlistgui.h" />

+    <ClInclude Include="xtext.h" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="about.c" />

+    <ClCompile Include="ascii.c" />

+    <ClCompile Include="banlist.c" />

+    <ClCompile Include="chanlist.c" />

+    <ClCompile Include="chanview.c" />

+    <ClCompile Include="custom-list.c" />

+    <ClCompile Include="dccgui.c" />

+    <ClCompile Include="editlist.c" />

+    <ClCompile Include="fe-gtk.c" />

+    <ClCompile Include="fkeys.c" />

+    <ClCompile Include="gtkutil.c" />

+    <ClCompile Include="ignoregui.c" />

+    <ClCompile Include="joind.c" />

+    <ClCompile Include="maingui.c" />

+    <ClCompile Include="menu.c" />

+    <ClCompile Include="notifygui.c" />

+    <ClCompile Include="palette.c" />

+    <ClCompile Include="pixmaps.c" />

+    <ClCompile Include="plugin-tray.c" />

+    <ClCompile Include="plugingui.c" />

+    <ClCompile Include="rawlog.c" />

+    <ClCompile Include="search.c" />

+    <ClCompile Include="servlistgui.c" />

+    <ClCompile Include="setup.c" />

+    <ClCompile Include="sexy-iso-codes.c" />

+    <ClCompile Include="sexy-marshal.c" />

+    <ClCompile Include="sexy-spell-entry.c" />

+    <ClCompile Include="textgui.c" />

+    <ClCompile Include="urlgrab.c" />

+    <ClCompile Include="userlistgui.c" />

+    <ClCompile Include="xtext.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <Manifest Include="xchat.exe.manifest" />

+  </ItemGroup>

+  <ItemGroup>

+    <ResourceCompile Include="xchat.rc" />

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="..\..\xchat.ico" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/fe-gtk/fe-gtk.vcxproj.filters b/src/fe-gtk/fe-gtk.vcxproj.filters
new file mode 100644
index 00000000..0e2e830b
--- /dev/null
+++ b/src/fe-gtk/fe-gtk.vcxproj.filters
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

+    </Filter>

+    <Filter Include="Resource Files">

+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>

+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="about.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ascii.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="banlist.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="chanlist.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="chanview.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="custom-list.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="editlist.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="fe-gtk.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="fkeys.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="gtkutil.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="joind.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="maingui.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="menu.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="mmx_cmod.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="notifygui.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="palette.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="pixmaps.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="plugingui.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="plugin-tray.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="rawlog.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="search.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="sexy-iso-codes.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="sexy-marshal.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="sexy-spell-entry.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="textgui.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="typedef.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="urlgrab.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="userlistgui.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="xtext.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="about.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ascii.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="banlist.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="chanlist.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="chanview.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="custom-list.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="dccgui.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="editlist.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="fe-gtk.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="fkeys.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="gtkutil.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ignoregui.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="joind.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="maingui.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="menu.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="notifygui.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="palette.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="pixmaps.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="plugingui.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="plugin-tray.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="rawlog.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="search.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="servlistgui.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="setup.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="sexy-iso-codes.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="sexy-marshal.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="sexy-spell-entry.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="textgui.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="urlgrab.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="userlistgui.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="xtext.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <Manifest Include="xchat.exe.manifest">

+      <Filter>Resource Files</Filter>

+    </Manifest>

+  </ItemGroup>

+  <ItemGroup>

+    <ResourceCompile Include="xchat.rc">

+      <Filter>Resource Files</Filter>

+    </ResourceCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="..\..\xchat.ico">

+      <Filter>Resource Files</Filter>

+    </None>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/fe-gtk/fe-gtk.vcxproj.user b/src/fe-gtk/fe-gtk.vcxproj.user
new file mode 100644
index 00000000..695b5c78
--- /dev/null
+++ b/src/fe-gtk/fe-gtk.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+</Project>
\ No newline at end of file
diff --git a/src/fe-gtk/fkeys.c b/src/fe-gtk/fkeys.c
index 014b5cc3..4fbbebf6 100644
--- a/src/fe-gtk/fkeys.c
+++ b/src/fe-gtk/fkeys.c
@@ -20,11 +20,14 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
 #include <string.h>
 #include <fcntl.h>
 #include <ctype.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "fe-gtk.h"
 
 #include <gtk/gtklabel.h>
@@ -315,7 +318,7 @@ key_handle_key_press (GtkWidget *wid, GdkEventKey *evt, session *sess)
 		key_action_tab_clean ();
 		break;
 
-#if defined(USE_GTKSPELL) && !defined(WIN32)
+#if defined(USE_GTKSPELL)/* && !defined(WIN32) */
 	/* gtktextview has no 'activate' event, so we trap ENTER here */
 	case GDK_Return:
 	case GDK_KP_Enter:
@@ -1257,11 +1260,11 @@ key_action_scroll_page (GtkWidget * wid, GdkEventKey * evt, char *d1,
 
 	if (d1)
 	{
-		if (!strcasecmp (d1, "up"))
+		if (!g_ascii_strcasecmp (d1, "up"))
 			type = PAGE_UP;
-		else if (!strcasecmp (d1, "+1"))
+		else if (!g_ascii_strcasecmp (d1, "+1"))
 			type = LINE_DOWN;
-		else if (!strcasecmp (d1, "-1"))
+		else if (!g_ascii_strcasecmp (d1, "-1"))
 			type = LINE_UP;
 	}
 
diff --git a/src/fe-gtk/gtkutil.c b/src/fe-gtk/gtkutil.c
index 63ab491b..fe4e1737 100644
--- a/src/fe-gtk/gtkutil.c
+++ b/src/fe-gtk/gtkutil.c
@@ -22,8 +22,8 @@
 #include <stdarg.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
 #include <fcntl.h>
+
 #include "fe-gtk.h"
 
 #include <gtk/gtkbutton.h>
@@ -52,6 +52,13 @@
 #include "gtkutil.h"
 #include "pixmaps.h"
 
+#ifdef WIN32
+#include "../common/fe.h"
+#include "../common/thread.h"
+#else
+#include <unistd.h>
+#endif
+
 /* gtkutil.c, just some gtk wrappers */
 
 extern void path_part (char *file, char *path, int pathlen);
@@ -63,6 +70,13 @@ struct file_req
 	void *userdata;
 	filereqcallback callback;
 	int flags;		/* FRF_* flags */
+
+#ifdef WIN32
+	int multiple;
+	thread *th;
+	char *title;	/* native locale */
+	char *filter;
+#endif
 };
 
 static char last_dir[256] = "";
@@ -164,6 +178,190 @@ gtkutil_file_req_response (GtkWidget *dialog, gint res, struct file_req *freq)
 	}
 }
 
+#ifdef WIN32
+static int
+win32_openfile (char *file_buf, int file_buf_len, char *title_text, char *filter,
+			   int multiple)
+{
+	OPENFILENAME o;
+
+	memset (&o, 0, sizeof (o));
+
+	o.lStructSize = sizeof (o);
+	o.lpstrFilter = filter;
+	o.lpstrFile = file_buf;
+	o.nMaxFile = file_buf_len;
+	o.lpstrTitle = title_text;
+	o.Flags = 0x02000000 | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
+				OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_LONGNAMES | OFN_NONETWORKBUTTON;
+	if (multiple)
+	{
+		o.Flags |= OFN_ALLOWMULTISELECT;
+	}
+
+	return GetOpenFileName (&o);
+}
+
+static int
+win32_savefile (char *file_buf, int file_buf_len, char *title_text, char *filter,
+               int multiple)
+{
+	/* we need the filter to get the default filename. it is from fe-gtk.c (fe_confirm);
+	 * but that filter is actually the whole filename, so apply an empty filter and all good.
+	 * in win32_thread2 we copy the filter ( = the filename) after the last dir into our
+	 * LPTSTR file buffer to make it actually work. the docs for this amazingly retard api:
+	 *
+	 * http://msdn.microsoft.com/en-us/library/ms646839%28VS.85%29.aspx
+	 */
+
+	OPENFILENAME o;
+
+	memset (&o, 0, sizeof (o));
+
+	o.lStructSize = sizeof (o);
+	o.lpstrFilter = "All files\0*.*\0\0";
+	o.lpstrFile = file_buf;
+	o.nMaxFile = file_buf_len;
+	o.lpstrTitle = title_text;
+	o.Flags = 0x02000000 | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
+				OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_LONGNAMES | OFN_NONETWORKBUTTON;
+	if (multiple)
+	{
+		o.Flags |= OFN_ALLOWMULTISELECT;
+	}
+
+	return GetSaveFileName (&o);
+}
+
+static void *
+win32_thread (struct file_req *freq)
+{
+	char buf[1024 + 32];
+	char file[1024];
+
+	memset (file, 0, sizeof (file));
+	safe_strcpy (file, last_dir, sizeof (file));
+
+	if (win32_openfile (file, sizeof (file), freq->title, freq->filter, freq->multiple))
+	{
+		if (freq->multiple)
+		{
+			char *f = file;
+
+			if (f[strlen (f) + 1] == 0)	/* only selected one file */
+			{
+				snprintf (buf, sizeof (buf), "1\n%s\n", file);
+				write (freq->th->pipe_fd[1], buf, strlen (buf));
+			} else
+			{
+				f += strlen (f) + 1; /* skip first, it's only the dir */
+				while (f[0])
+				{
+					snprintf (buf, sizeof (buf), "1\n%s\\%s\n", /*dir!*/file, f);
+					write (freq->th->pipe_fd[1], buf, strlen (buf));
+					f += strlen (f) + 1;
+				}
+			}
+
+		} else
+		{
+			snprintf (buf, sizeof (buf), "1\n%s\n", file);
+			write (freq->th->pipe_fd[1], buf, strlen (buf));
+		}
+	}
+
+	write (freq->th->pipe_fd[1], "0\n", 2);
+	Sleep (2000);
+
+	return NULL;
+}
+
+static void *
+win32_thread2 (struct file_req *freq)
+{
+	char buf[1024 + 32];
+	char file[1024];
+
+	memset (file, 0, sizeof (file));
+	safe_strcpy (file, last_dir, sizeof (file));
+	safe_strcpy (file, freq->filter, sizeof (file));
+
+	if (win32_savefile (file, sizeof (file), freq->title, NULL, freq->multiple))
+	{
+		if (freq->multiple)
+		{
+			char *f = file;
+
+			if (f[strlen (f) + 1] == 0)    /* only selected one file */
+			{
+				snprintf (buf, sizeof (buf), "1\n%s\n", file);
+				write (freq->th->pipe_fd[1], buf, strlen (buf));
+			} else
+			{
+				f += strlen (f) + 1; /* skip first, it's only the dir */
+				while (f[0])
+				{
+					snprintf (buf, sizeof (buf), "1\n%s\\%s\n", /*dir!*/file, f);
+					write (freq->th->pipe_fd[1], buf, strlen (buf));
+					f += strlen (f) + 1;
+				}
+			}
+
+		} else
+		{
+			snprintf (buf, sizeof (buf), "1\n%s\n", file);
+			write (freq->th->pipe_fd[1], buf, strlen (buf));
+		}
+	}
+
+	write (freq->th->pipe_fd[1], "0\n", 2);
+	Sleep (2000);
+
+	return NULL;
+}
+
+static gboolean
+win32_close_pipe (int fd)
+{
+	close (fd);
+	return 0;
+}
+
+static gboolean
+win32_read_thread (GIOChannel *source, GIOCondition cond, struct file_req *freq)
+{
+	char buf[512];
+	char *file;
+
+	waitline2 (source, buf, sizeof buf);
+
+	switch (buf[0])
+	{
+	case '0':	/* filedialog has closed */
+		freq->callback (freq->userdata, NULL);
+		break;
+
+	case '1':	/* got a filename! */
+		waitline2 (source, buf, sizeof buf);
+		file = g_filename_to_utf8 (buf, -1, 0, 0, 0);
+		freq->callback (freq->userdata, file);
+		g_free (file);
+		return TRUE;
+	}
+
+	/* it doesn't work to close them here, because of the weird
+		way giowin32 works. We must _return_ before closing them */
+	g_timeout_add(3000, (GSourceFunc)win32_close_pipe, freq->th->pipe_fd[0]);
+	g_timeout_add(2000, (GSourceFunc)win32_close_pipe, freq->th->pipe_fd[1]);
+
+	g_free (freq->title);
+	free (freq->th);
+	free (freq);
+
+	return FALSE;
+}
+#endif
+
 void
 gtkutil_file_req (const char *title, void *callback, void *userdata, char *filter,
 						int flags)
@@ -172,6 +370,58 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
 	GtkWidget *dialog;
 	extern char *get_xdir_fs (void);
 
+#ifdef WIN32
+	if (!(flags & FRF_WRITE))
+	{
+		freq = malloc (sizeof (struct file_req));
+		freq->th = thread_new ();
+		freq->flags = 0;
+		freq->multiple = (flags & FRF_MULTIPLE);
+		freq->callback = callback;
+		freq->userdata = userdata;
+		freq->title = g_locale_from_utf8 (title, -1, 0, 0, 0);
+		if (!filter)
+		{
+			freq->filter =	"All files\0*.*\0"
+							"Executables\0*.exe\0"
+							"ZIP files\0*.zip\0\0";
+		}
+		else
+		{
+			freq->filter = filter;
+		}
+
+		thread_start (freq->th, win32_thread, freq);
+		fe_input_add (freq->th->pipe_fd[0], FIA_FD|FIA_READ, win32_read_thread, freq);
+
+		return;
+
+	}
+	
+	else {
+		freq = malloc (sizeof (struct file_req));
+		freq->th = thread_new ();
+		freq->flags = 0;
+		freq->multiple = (flags & FRF_MULTIPLE);
+		freq->callback = callback;
+		freq->userdata = userdata;
+		freq->title = g_locale_from_utf8 (title, -1, 0, 0, 0);
+		if (!filter)
+		{
+			freq->filter = "All files\0*.*\0\0";
+		}
+		else
+		{
+			freq->filter = filter;
+		}
+
+		thread_start (freq->th, win32_thread2, freq);
+		fe_input_add (freq->th->pipe_fd[0], FIA_FD|FIA_READ, win32_read_thread, freq);
+
+	return;
+	}
+#endif
+
 	if (flags & FRF_WRITE)
 	{
 		dialog = gtk_file_chooser_dialog_new (title, NULL,
diff --git a/src/fe-gtk/joind.c b/src/fe-gtk/joind.c
index ee5c56d1..e645f0bc 100644
--- a/src/fe-gtk/joind.c
+++ b/src/fe-gtk/joind.c
@@ -9,10 +9,13 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
 #include <string.h>
 #include <stdio.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include <gtk/gtkbbox.h>
 #include <gtk/gtkbutton.h>
 #include <gtk/gtkdialog.h>
diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c
index 8e6873a2..1ff59354 100644
--- a/src/fe-gtk/maingui.c
+++ b/src/fe-gtk/maingui.c
@@ -53,6 +53,8 @@
 #include "../common/plugin.h"
 #include "../common/modes.h"
 #include "../common/url.h"
+#include "../common/util.h"
+
 #include "fe-gtk.h"
 #include "banlist.h"
 #include "gtkutil.h"
@@ -214,60 +216,10 @@ mg_create_tab_colors (void)
 	away_list = mg_attr_list_create (&colors[COL_AWAY], FALSE);
 }
 
-#ifdef WIN32
-#define WINVER 0x0501	/* needed for vc6? */
-#include <windows.h>
-#include <gdk/gdkwin32.h>
-
-/* Flash the taskbar button on Windows when there's a highlight event. */
-
-static void
-flash_window (GtkWidget *win)
-{
-	FLASHWINFO fi;
-	static HMODULE user = NULL;
-	static BOOL (*flash) (PFLASHWINFO) = NULL;
-
-	if (!user)
-	{
-		user = GetModuleHandleA ("USER32");
-		if (!user)
-			return;	/* this should never fail */
-	}
-
-	if (!flash)
-	{
-		flash = (void *)GetProcAddress (user, "FlashWindowEx");
-		if (!flash)
-			return;	/* this fails on NT4.0 and Win95 */
-	}
-
-	fi.cbSize = sizeof (fi);
-	fi.hwnd = GDK_WINDOW_HWND (win->window);
-	fi.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG;
-	fi.uCount = 0;
-	fi.dwTimeout = 500;
-	flash (&fi);
-	/*FlashWindowEx (&fi);*/
-}
-#else
-
-#ifdef USE_XLIB
-#include <gdk/gdkx.h>
-
 static void
 set_window_urgency (GtkWidget *win, gboolean set)
 {
-	XWMHints *hints;
-
-	hints = XGetWMHints(GDK_WINDOW_XDISPLAY(win->window), GDK_WINDOW_XWINDOW(win->window));
-	if (set)
-		hints->flags |= XUrgencyHint;
-	else
-		hints->flags &= ~XUrgencyHint;
-	XSetWMHints(GDK_WINDOW_XDISPLAY(win->window),
-	            GDK_WINDOW_XWINDOW(win->window), hints);
-	XFree(hints);
+	gtk_window_set_urgency_hint (GTK_WINDOW (win), set);
 }
 
 static void
@@ -281,18 +233,14 @@ unflash_window (GtkWidget *win)
 {
 	set_window_urgency (win, FALSE);
 }
-#endif
-#endif
 
 /* flash the taskbar button */
 
 void
 fe_flash_window (session *sess)
 {
-#if defined(WIN32) || defined(USE_XLIB)
 	if (fe_gui_info (sess, 0) != 1)	/* only do it if not focused */
 		flash_window (sess->gui->window);
-#endif
 }
 
 /* set a tab plain, red, light-red, or blue */
@@ -530,10 +478,22 @@ fe_set_title (session *sess)
 		break;
 	default:
 	def:
-		gtk_window_set_title (GTK_WINDOW (sess->gui->window), DISPLAY_NAME);
+		snprintf (tbuf, sizeof (tbuf), DISPLAY_NAME);
+		if (strcmp (prefs.gui_license, ""))		/* zero means gui_license is empty */
+		{
+			strcat (tbuf, " - ");
+			strcat (tbuf, prefs.gui_license);
+		}
+		gtk_window_set_title (GTK_WINDOW (sess->gui->window), tbuf);
 		return;
 	}
 
+	if (strcmp (prefs.gui_license, ""))			/* zero means gui_license is empty */
+	{
+		strcat (tbuf, " - ");
+		strcat (tbuf, prefs.gui_license);
+	}
+
 	gtk_window_set_title (GTK_WINDOW (sess->gui->window), tbuf);
 }
 
@@ -840,6 +800,9 @@ mg_userlist_showhide (session *sess, int show)
 {
 	session_gui *gui = sess->gui;
 	int handle_size;
+	int right_size;
+
+	right_size = MAX (prefs.gui_pane_right_size, prefs.gui_pane_right_size_min);
 
 	if (show)
 	{
@@ -847,7 +810,7 @@ mg_userlist_showhide (session *sess, int show)
 		gui->ul_hidden = 0;
 
 		gtk_widget_style_get (GTK_WIDGET (gui->hpane_right), "handle-size", &handle_size, NULL);
-		gtk_paned_set_position (GTK_PANED (gui->hpane_right), GTK_WIDGET (gui->hpane_right)->allocation.width - (prefs.gui_pane_right_size + handle_size));
+		gtk_paned_set_position (GTK_PANED (gui->hpane_right), GTK_WIDGET (gui->hpane_right)->allocation.width - (right_size + handle_size));
 	}
 	else
 	{
@@ -1335,7 +1298,7 @@ mg_open_quit_dialog (gboolean minimize_button)
 	gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1),
 										GTK_BUTTONBOX_END);
 
-	if (minimize_button)
+	if (minimize_button && !xtray_mode ())
 	{
 		button = gtk_button_new_with_mnemonic (_("_Minimize to Tray"));
 		gtk_widget_show (button);
@@ -1633,7 +1596,12 @@ mg_create_alertmenu (session *sess, GtkWidget *menu)
 	submenu = menu_quick_sub (_("_Extra Alerts"), menu, NULL, XCMENU_MNEMONIC, -1);
 
 	mg_perchan_menu_item (_("Beep on _Message"), submenu, &sess->alert_beep, prefs.input_beep_chans);
-	mg_perchan_menu_item (_("Blink Tray _Icon"), submenu, &sess->alert_tray, prefs.input_tray_chans);
+
+	if (!xtray_mode ())		/*disable this context menu item when xtray is loaded */
+	{
+		mg_perchan_menu_item (_("Blink Tray _Icon"), submenu, &sess->alert_tray, prefs.input_tray_chans);
+	}
+
 	mg_perchan_menu_item (_("Blink Task _Bar"), submenu, &sess->alert_taskbar, prefs.input_flash_chans);
 }
 
@@ -1720,7 +1688,7 @@ mg_dnd_drop_file (session *sess, char *target, char *uri)
 	while (*p)
 	{
 		next = strchr (p, '\r');
-		if (strncasecmp ("file:", p, 5) == 0)
+		if (g_ascii_strncasecmp ("file:", p, 5) == 0)
 		{
 			if (next)
 				*next = 0;
@@ -2883,7 +2851,7 @@ mg_create_entry (session *sess, GtkWidget *box)
 #else
 	gui->input_box = entry = gtk_entry_new ();
 #endif
-	gtk_entry_set_max_length (GTK_ENTRY (gui->input_box), 2048);
+	gtk_entry_set_max_length (GTK_ENTRY (gui->input_box), 0);
 	g_signal_connect (G_OBJECT (entry), "activate",
 							G_CALLBACK (mg_inputbox_cb), gui);
 	gtk_container_add (GTK_CONTAINER (hbox), entry);
@@ -2943,7 +2911,7 @@ mg_tabs_compare (session *a, session *b)
 	if (a->type != SESS_CHANNEL && b->type == SESS_CHANNEL)
 		return 1;
 
-	return strcasecmp (a->channel, b->channel);
+	return g_ascii_strcasecmp (a->channel, b->channel);
 }
 
 static void
@@ -2973,11 +2941,7 @@ mg_tabwin_focus_cb (GtkWindow * win, GdkEventFocus *event, gpointer userdata)
 		gtk_xtext_check_marker_visibility (GTK_XTEXT (current_sess->gui->xtext));
 		plugin_emit_dummy_print (current_sess, "Focus Window");
 	}
-#ifndef WIN32
-#ifdef USE_XLIB
 	unflash_window (GTK_WIDGET (win));
-#endif
-#endif
 	return FALSE;
 }
 
@@ -2988,11 +2952,7 @@ mg_topwin_focus_cb (GtkWindow * win, GdkEventFocus *event, session *sess)
 	if (!sess->server->server_session)
 		sess->server->server_session = sess;
 	gtk_xtext_check_marker_visibility(GTK_XTEXT (current_sess->gui->xtext));
-#ifndef WIN32
-#ifdef USE_XLIB
 	unflash_window (GTK_WIDGET (win));
-#endif
-#endif
 	plugin_emit_dummy_print (sess, "Focus Window");
 	return FALSE;
 }
diff --git a/src/fe-gtk/makefile.mak b/src/fe-gtk/makefile.mak
new file mode 100644
index 00000000..27922405
--- /dev/null
+++ b/src/fe-gtk/makefile.mak
@@ -0,0 +1,62 @@
+include "..\makeinc.mak"
+
+FEGTK_OBJECTS = \
+about.obj \
+ascii.obj \
+banlist.obj \
+chanlist.obj \
+chanview.obj \
+custom-list.obj \
+dccgui.obj \
+editlist.obj \
+fe-gtk.obj \
+fkeys.obj \
+gtkutil.obj \
+ignoregui.obj \
+joind.obj \
+maingui.obj \
+menu.obj \
+notifygui.obj \
+palette.obj \
+pixmaps.obj \
+plugingui.obj \
+plugin-tray.obj \
+rawlog.obj \
+search.obj \
+servlistgui.obj \
+setup.obj \
+sexy-iso-codes.obj \
+sexy-marshal.obj \
+sexy-spell-entry.obj \
+textgui.obj \
+urlgrab.obj \
+userlistgui.obj \
+xtext.obj
+
+!ifdef X64
+MACHINE_FLAG = /MACHINE:X64
+!else
+MACHINE_FLAG = /MACHINE:X86
+!endif
+
+COMLIB = ..\common\xchatcommon.lib
+PROG = xchat.exe
+
+all: $(PROG)
+
+.c.obj::
+	$(CC) $(CFLAGS) -I..\..\plugins $(GLIB) $(GTK) $<
+
+$(PROG): $(FEGTK_OBJECTS) $(COMLIB) xchat-icon.obj
+	$(LINK) /out:$(PROG) /entry:mainCRTStartup $(LDFLAGS) $(LIBS) $(FEGTK_OBJECTS) $(COMLIB) xchat-icon.obj
+
+xchat.res: xchat.rc ../../xchat.ico
+	rc /nologo /r xchat.rc
+
+xchat-icon.obj: xchat.res
+	cvtres /nologo $(MACHINE_FLAG) /OUT:xchat-icon.obj xchat.res
+
+clean:
+	@del *.obj
+	@del $(PROG)
+	@del xchat.res
diff --git a/src/fe-gtk/menu.c b/src/fe-gtk/menu.c
index d04be222..2a683604 100644
--- a/src/fe-gtk/menu.c
+++ b/src/fe-gtk/menu.c
@@ -20,10 +20,11 @@
 #include <stdlib.h>
 #include <fcntl.h>
 #include <string.h>
-#include <unistd.h>
 
 #ifdef WIN32
 #include <windows.h>
+#else
+#include <unistd.h>
 #endif
 
 #include "fe-gtk.h"
@@ -483,18 +484,18 @@ menu_create (GtkWidget *menu, GSList *list, char *target, int check_path)
 	{
 		pop = (struct popup *) list->data;
 
-		if (!strncasecmp (pop->name, "SUB", 3))
+		if (!g_ascii_strncasecmp (pop->name, "SUB", 3))
 		{
 			childcount = 0;
 			tempmenu = menu_quick_sub (pop->cmd, tempmenu, &subitem, XCMENU_DOLIST|XCMENU_MNEMONIC, -1);
 
-		} else if (!strncasecmp (pop->name, "TOGGLE", 6))
+		} else if (!g_ascii_strncasecmp (pop->name, "TOGGLE", 6))
 		{
 			childcount++;
 			menu_toggle_item (pop->name + 7, tempmenu, toggle_cb, pop->cmd,
 									cfg_get_bool (pop->cmd));
 
-		} else if (!strncasecmp (pop->name, "ENDSUB", 6))
+		} else if (!g_ascii_strncasecmp (pop->name, "ENDSUB", 6))
 		{
 			/* empty sub menu due to no programs in PATH? */
 			if (check_path && childcount < 1)
@@ -505,7 +506,7 @@ menu_create (GtkWidget *menu, GSList *list, char *target, int check_path)
 				tempmenu = menu_quick_endsub ();
 			/* If we get here and tempmenu equals menu that means we havent got any submenus to exit from */
 
-		} else if (!strncasecmp (pop->name, "SEP", 3))
+		} else if (!g_ascii_strncasecmp (pop->name, "SEP", 3))
 		{
 			menu_quick_item (0, 0, tempmenu, XCMENU_SHADED, 0, 0);
 
@@ -1122,6 +1123,23 @@ usermenu_update (void)
 	}
 }
 
+#if 0
+static void
+menu_saveconf (void)
+{
+	session *sess = current_sess;
+
+	if (save_config ())
+	{
+		PrintText (sess, "Settings have been saved successfully.\n");
+	}
+	else
+	{
+		PrintText (sess, "Error saving settings.\n");
+	}
+}
+#endif
+
 static void
 menu_newserver_window (GtkWidget * wid, gpointer none)
 {
@@ -1198,12 +1216,53 @@ menu_search ()
 }
 
 static void
+menu_search_next ()
+{
+	GtkXText *xtext = GTK_XTEXT (current_sess->gui->xtext);
+	xtext_buffer *buf = xtext->buffer;
+
+	if (!gtk_xtext_search (xtext, buf->search_text,
+		(buf->search_flags & (case_match | follow | regexp)), NULL))
+	{
+		fe_message (_("Search hit end, not found."), FE_MSG_ERROR);
+	}
+}
+
+static void
+menu_search_prev ()
+{
+	GtkXText *xtext = GTK_XTEXT (current_sess->gui->xtext);
+	xtext_buffer *buf = xtext->buffer;
+
+	if (!gtk_xtext_search(xtext, buf->search_text,
+		(buf->search_flags & (case_match | follow | regexp) | backward), NULL))
+	{
+		fe_message (_("Search hit end, not found."), FE_MSG_ERROR);
+	}
+}
+
+static void
+menu_search_reset ()
+{
+	GtkXText *xtext = GTK_XTEXT (current_sess->gui->xtext);
+	xtext_buffer *buf = xtext->buffer;
+
+	gtk_xtext_search (xtext, "", 0, NULL);
+}
+
+static void
 menu_resetmarker (GtkWidget * wid, gpointer none)
 {
 	gtk_xtext_reset_marker_pos (GTK_XTEXT (current_sess->gui->xtext));
 }
 
 static void
+menu_copy_selection (GtkWidget * wid, gpointer none)
+{
+	gtk_xtext_copy_selection (GTK_XTEXT (current_sess->gui->xtext));
+}
+
+static void
 menu_flushbuffer (GtkWidget * wid, gpointer none)
 {
 	fe_text_clear (current_sess, 0);
@@ -1580,7 +1639,7 @@ static struct mymenu mymenu[] = {
 #endif
 	{0, 0, 0, M_SEP, 0, 0, 0},	/* 11 */
 #define DETACH_OFFSET (12)
-	{0, menu_detach, GTK_STOCK_REDO, M_MENUSTOCK, 0, 0, 1, GDK_I},	/* 12 */
+	{0, menu_detach, GTK_STOCK_REDO, M_MENUSTOCK, 0, 0, 1, GDK_i},	/* 12 */
 #define CLOSE_OFFSET (13)
 	{0, menu_close, GTK_STOCK_CLOSE, M_MENUSTOCK, 0, 0, 1, GDK_w},
 	{0, 0, 0, M_SEP, 0, 0, 0},
@@ -1633,6 +1692,10 @@ static struct mymenu mymenu[] = {
 		{N_("Userlist Popup..."), menu_ulpopup, 0, M_MENUITEM, 0, 0, 1},
 		{0, 0, 0, M_END, 0, 0, 0},		/* 53 */
 
+#if 0
+	{N_("Save Settings to Disk"), menu_saveconf, GTK_STOCK_SAVE, M_MENUSTOCK, 0, 0, 1}, /* don't use this, a /set auto-save approach will be added instead */
+#endif
+
 	{N_("_Window"), 0, 0, M_NEWMENU, 0, 0, 1},
 	{N_("Ban List..."), menu_banlist, 0, M_MENUITEM, 0, 0, 1},
 	{N_("Character Chart..."), ascii_open, 0, M_MENUITEM, 0, 0, 1},
@@ -1645,12 +1708,19 @@ static struct mymenu mymenu[] = {
 	{N_("URL Grabber..."), url_opengui, 0, M_MENUITEM, 0, 0, 1},
 	{0, 0, 0, M_SEP, 0, 0, 0},
 	{N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_m},
+	{N_("_Copy Selection"), menu_copy_selection, 0, M_MENUITEM, 0, 0, 1, GDK_C},
 	{N_("C_lear Text"), menu_flushbuffer, GTK_STOCK_CLEAR, M_MENUSTOCK, 0, 0, 1, GDK_l},
-#define SEARCH_OFFSET 67
-	{N_("Search Text..."), menu_search, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_f},
 	{N_("Save Text..."), menu_savebuffer, GTK_STOCK_SAVE, M_MENUSTOCK, 0, 0, 1},
+#define SEARCH_OFFSET 70
+	{N_("Search"), 0, GTK_STOCK_JUSTIFY_LEFT, M_MENUSUB, 0, 0, 1},
+		{N_("Search Text..."), menu_search, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_f},
+		{N_("Reset Search"), menu_search_reset, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_F},
+		{N_("Search Next"   ), menu_search_next, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_g},
+		{N_("Search Previous"   ), menu_search_prev, GTK_STOCK_FIND, M_MENUSTOCK, 0, 0, 1, GDK_G},
+		{0, 0, 0, M_END, 0, 0, 0},
+
+	{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1},	/* 74 */
 
-	{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1},	/* 69 */
 	{N_("_Contents"), menu_docs, GTK_STOCK_HELP, M_MENUSTOCK, 0, 0, 1, GDK_F1},
 #if 0
 	{N_("Check for updates"), menu_update, 0, M_MENUITEM, 0, 1},
@@ -2120,7 +2190,7 @@ menu_create_main (void *accel_group, int bar, int away, int toplevel,
 		g_object_get (settings, "gtk-key-theme-name", &key_theme, NULL);
 		if (key_theme)
 		{
-			if (!strcasecmp (key_theme, "Emacs"))
+			if (!g_ascii_strcasecmp (key_theme, "Emacs"))
 			{
 				close_mask = GDK_SHIFT_MASK | GDK_CONTROL_MASK;
 				mymenu[SEARCH_OFFSET].key = 0;
@@ -2188,7 +2258,9 @@ normalitem:
 										mymenu[i].key,
 										mymenu[i].key == GDK_F1 ? 0 :
 										mymenu[i].key == GDK_w ? close_mask :
-										GDK_CONTROL_MASK,
+										(g_ascii_isupper (mymenu[i].key)) ?
+											GDK_SHIFT_MASK | GDK_CONTROL_MASK :
+											GDK_CONTROL_MASK,
 										GTK_ACCEL_VISIBLE);
 			if (mymenu[i].callback)
 				g_signal_connect (G_OBJECT (item), "activate",
diff --git a/src/fe-gtk/notifygui.c b/src/fe-gtk/notifygui.c
index 5acb683a..135a548d 100644
--- a/src/fe-gtk/notifygui.c
+++ b/src/fe-gtk/notifygui.c
@@ -321,7 +321,7 @@ notifygui_add_cb (GtkDialog *dialog, gint response, gpointer entry)
 	if (text[0] && response == GTK_RESPONSE_ACCEPT)
 	{
 		networks = GTK_ENTRY (g_object_get_data (G_OBJECT (entry), "net"))->text;
-		if (strcasecmp (networks, "ALL") == 0 || networks[0] == 0)
+		if (g_ascii_strcasecmp (networks, "ALL") == 0 || networks[0] == 0)
 			notify_adduser (text, NULL);
 		else
 			notify_adduser (text, networks);
diff --git a/src/fe-gtk/palette.c b/src/fe-gtk/palette.c
index ebae92ff..104700c2 100644
--- a/src/fe-gtk/palette.c
+++ b/src/fe-gtk/palette.c
@@ -18,11 +18,14 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "fe-gtk.h"
 #include "palette.h"
 
@@ -78,8 +81,9 @@ GdkColor colors[] = {
 	{0, 0x0000, 0x0000, 0xffff}, /* 38 tab Nick Mentioned (blue) */
 	{0, 0xffff, 0x0000, 0x0000}, /* 39 tab New Message (red) */
 	{0, 0x9595, 0x9595, 0x9595}, /* 40 away user (grey) */
+	{0, 0xffff, 0x0000, 0x0000}, /* 41 spell checker color (red) */
 };
-#define MAX_COL 40
+#define MAX_COL 41
 
 
 void
diff --git a/src/fe-gtk/palette.h b/src/fe-gtk/palette.h
index c97693bb..627c6963 100644
--- a/src/fe-gtk/palette.h
+++ b/src/fe-gtk/palette.h
@@ -9,6 +9,7 @@ extern GdkColor colors[];
 #define COL_HILIGHT 38
 #define COL_NEW_MSG 39
 #define COL_AWAY 40
+#define COL_SPELL 41
 
 void palette_alloc (GtkWidget * widget);
 void palette_load (void);
diff --git a/src/fe-gtk/plugin-tray.c b/src/fe-gtk/plugin-tray.c
index e46d9570..b9f60f8d 100644
--- a/src/fe-gtk/plugin-tray.c
+++ b/src/fe-gtk/plugin-tray.c
@@ -1,7 +1,6 @@
 /* Copyright (C) 2006-2007 Peter Zelezny. */
 
 #include <string.h>
-#include <unistd.h>
 #include "../common/xchat-plugin.h"
 #include "../common/xchat.h"
 #include "../common/xchatc.h"
@@ -15,6 +14,10 @@
 #include "menu.h"
 #include <gtk/gtk.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #ifdef USE_LIBNOTIFY
 #include <libnotify/notify.h>
 #ifndef NOTIFY_CHECK_VERSION
@@ -217,10 +220,10 @@ tray_stop_flash (void)
 		nets = tray_count_networks ();
 		chans = tray_count_channels ();
 		if (nets)
-			tray_set_tipf (_("XChat: Connected to %u networks and %u channels"),
+			tray_set_tipf (_("XChat-WDK: Connected to %u networks and %u channels"),
 								nets, chans);
 		else
-			tray_set_tipf ("XChat: %s", _("Not connected."));
+			tray_set_tipf ("XChat-WDK: %s", _("Not connected."));
 	}
 
 	if (custom_icon1)
@@ -370,7 +373,7 @@ tray_toggle_visibility (gboolean force_hide)
 	/* ph may have an invalid context now */
 	xchat_set_context (ph, xchat_find_context (ph, NULL, NULL));
 
-	win = (GtkWindow *)xchat_get_info (ph, "win_ptr");
+	win = xchat_get_info (ph, "gtkwin_ptr");
 
 	tray_stop_flash ();
 	tray_reset_counts ();
@@ -505,11 +508,12 @@ tray_menu_cb (GtkWidget *widget, guint button, guint time, gpointer userdata)
 	/*gtk_menu_set_screen (GTK_MENU (menu), gtk_widget_get_screen (widget));*/
 
 	if (tray_get_window_status () == WS_HIDDEN)
-		tray_make_item (menu, _("_Restore"), tray_menu_restore_cb, NULL);
+		tray_make_item (menu, _("_Restore Window"), tray_menu_restore_cb, NULL);
 	else
-		tray_make_item (menu, _("_Hide"), tray_menu_restore_cb, NULL);
+		tray_make_item (menu, _("_Hide Window"), tray_menu_restore_cb, NULL);
 	tray_make_item (menu, NULL, tray_menu_quit_cb, NULL);
 
+#ifndef WIN32 /* somehow this is broken on win32 */
 	submenu = mg_submenu (menu, _("_Blink on"));
 	blink_item (&prefs.input_tray_chans, submenu, _("Channel Message"));
 	blink_item (&prefs.input_tray_priv, submenu, _("Private Message"));
@@ -526,6 +530,8 @@ tray_menu_cb (GtkWidget *widget, guint button, guint time, gpointer userdata)
 		gtk_widget_set_sensitive (item, FALSE);
 
 	tray_make_item (menu, NULL, tray_menu_quit_cb, NULL);
+#endif
+
 	mg_create_icon_item (_("_Quit"), GTK_STOCK_QUIT, menu, tray_menu_quit_cb, NULL);
 
 	menu_add_plugin_items (menu, "\x5$TRAY", NULL);
@@ -551,8 +557,12 @@ tray_init (void)
 	sticon = gtk_status_icon_new_from_pixbuf (ICON_NORMAL);
 	if (!sticon)
 		return;
+
+#ifndef WIN32
 	g_signal_connect (G_OBJECT (sticon), "popup-menu",
 							G_CALLBACK (tray_menu_cb), sticon);
+#endif
+
 	g_signal_connect (G_OBJECT (sticon), "activate",
 							G_CALLBACK (tray_menu_restore_cb), NULL);
 }
@@ -570,15 +580,15 @@ tray_hilight_cb (char *word[], void *userdata)
 		/* FIXME: hides any previous private messages */
 		tray_hilight_count++;
 		if (tray_hilight_count == 1)
-			tray_set_tipf (_("XChat: Highlighted message from: %s (%s)"),
+			tray_set_tipf (_("XChat-WDK: Highlighted message from: %s (%s)"),
 								word[1], xchat_get_info (ph, "channel"));
 		else
-			tray_set_tipf (_("XChat: %u highlighted messages, latest from: %s (%s)"),
+			tray_set_tipf (_("XChat-WDK: %u highlighted messages, latest from: %s (%s)"),
 								tray_hilight_count, word[1], xchat_get_info (ph, "channel"));
 	}
 
 	if (prefs.input_balloon_hilight)
-		tray_set_balloonf (word[2], _("XChat: Highlighted message from: %s (%s)"),
+		tray_set_balloonf (word[2], _("XChat-WDK: Highlighted message from: %s (%s)"),
 								 word[1], xchat_get_info (ph, "channel"));
 
 	return XCHAT_EAT_NONE;
@@ -596,14 +606,14 @@ tray_message_cb (char *word[], void *userdata)
 
 		tray_pub_count++;
 		if (tray_pub_count == 1)
-			tray_set_tipf (_("XChat: New public message from: %s (%s)"),
+			tray_set_tipf (_("XChat-WDK: New public message from: %s (%s)"),
 								word[1], xchat_get_info (ph, "channel"));
 		else
-			tray_set_tipf (_("XChat: %u new public messages."), tray_pub_count);
+			tray_set_tipf (_("XChat-WDK: %u new public messages."), tray_pub_count);
 	}
 
 	if (prefs.input_balloon_chans)
-		tray_set_balloonf (word[2], _("XChat: New public message from: %s (%s)"),
+		tray_set_balloonf (word[2], _("XChat-WDK: New public message from: %s (%s)"),
 								 word[1], xchat_get_info (ph, "channel"));
 
 	return XCHAT_EAT_NONE;
@@ -625,14 +635,14 @@ tray_priv (char *from, char *text)
 
 	tray_priv_count++;
 	if (tray_priv_count == 1)
-		tray_set_tipf (_("XChat: Private message from: %s (%s)"),
+		tray_set_tipf (_("XChat-WDK: Private message from: %s (%s)"),
 							from, network);
 	else
-		tray_set_tipf (_("XChat: %u private messages, latest from: %s (%s)"),
+		tray_set_tipf (_("XChat-WDK: %u private messages, latest from: %s (%s)"),
 							tray_priv_count, from, network);
 
 	if (prefs.input_balloon_priv)
-		tray_set_balloonf (text, _("XChat: Private message from: %s (%s)"),
+		tray_set_balloonf (text, _("XChat-WDK: Private message from: %s (%s)"),
 								 from, network);
 }
 
@@ -678,15 +688,15 @@ tray_dcc_cb (char *word[], void *userdata)
 
 		tray_file_count++;
 		if (tray_file_count == 1)
-			tray_set_tipf (_("XChat: File offer from: %s (%s)"),
+			tray_set_tipf (_("XChat-WDK: File offer from: %s (%s)"),
 								word[1], network);
 		else
-			tray_set_tipf (_("XChat: %u file offers, latest from: %s (%s)"),
+			tray_set_tipf (_("XChat-WDK: %u file offers, latest from: %s (%s)"),
 								tray_file_count, word[1], network);
 	}
 
 	if (prefs.input_balloon_priv)
-		tray_set_balloonf ("", _("XChat: File offer from: %s (%s)"),
+		tray_set_balloonf ("", _("XChat-WDK: File offer from: %s (%s)"),
 								word[1], network);
 
 	return XCHAT_EAT_NONE;
@@ -722,7 +732,7 @@ tray_apply_setup (void)
 	}
 	else
 	{
-		if (prefs.gui_tray)
+		if (prefs.gui_tray && !xtray_mode ())
 			tray_init ();
 	}
 }
@@ -754,7 +764,7 @@ tray_plugin_init (xchat_plugin *plugin_handle, char **plugin_name,
 
 	xchat_hook_print (ph, "Focus Window", -1, tray_focus_cb, NULL);
 
-	if (prefs.gui_tray)
+	if (prefs.gui_tray && !xtray_mode ())
 		tray_init ();
 
 	return 1;       /* return 1 for success */
diff --git a/src/fe-gtk/plugingui.c b/src/fe-gtk/plugingui.c
index de59e649..7d2dc85d 100644
--- a/src/fe-gtk/plugingui.c
+++ b/src/fe-gtk/plugingui.c
@@ -146,8 +146,13 @@ plugingui_load_cb (session *sess, char *file)
 void
 plugingui_load (void)
 {
-	gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb,
-							current_sess, NULL, FRF_ADDFOLDER);
+	gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess,
+#ifdef WIN32
+							"Plugins and Scripts\0*.dll;*.lua;*.pl;*.py;*.tcl\0"
+							"All files\0*.*\0\0", 0);
+#else
+							NULL, FRF_ADDFOLDER);
+#endif
 }
 
 static void
@@ -171,12 +176,12 @@ plugingui_unload (GtkWidget * wid, gpointer unused)
 
 	len = strlen (file);
 #ifdef WIN32
-	if (len > 4 && strcasecmp (file + len - 4, ".dll") == 0)
+	if (len > 4 && g_ascii_strcasecmp (file + len - 4, ".dll") == 0)
 #else
 #if defined(__hpux)
-	if (len > 3 && strcasecmp (file + len - 3, ".sl") == 0)
+	if (len > 3 && g_ascii_strcasecmp (file + len - 3, ".sl") == 0)
 #else
-	if (len > 3 && strcasecmp (file + len - 3, ".so") == 0)
+	if (len > 3 && g_ascii_strcasecmp (file + len - 3, ".so") == 0)
 #endif
 #endif
 	{
diff --git a/src/fe-gtk/rawlog.c b/src/fe-gtk/rawlog.c
index 56ca0510..593468c1 100644
--- a/src/fe-gtk/rawlog.c
+++ b/src/fe-gtk/rawlog.c
@@ -19,9 +19,12 @@
 #include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
-#include <unistd.h>
 #include <stdlib.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "fe-gtk.h"
 
 #include <gtk/gtkbutton.h>
diff --git a/src/fe-gtk/search.c b/src/fe-gtk/search.c
index d62e79c7..30ef266f 100644
--- a/src/fe-gtk/search.c
+++ b/src/fe-gtk/search.c
@@ -42,15 +42,20 @@
 #include "xtext.h"
 #include "maingui.h"
 
-
-static textentry *last;	/* our last search pos */
-static int case_match = 0;
-static int search_backward = 0;
-
+GtkWidget *searchwin;
 
 static void
 search_search (session * sess, const gchar *text)
 {
+	gtk_xtext_search_flags flags;
+	textentry *last;
+	GError *err = NULL;
+
+	flags = ((prefs.text_search_case_match == 1? case_match: 0) |
+				(prefs.text_search_backward == 1? backward: 0) |
+				(prefs.text_search_highlight_all == 1? highlight: 0) |
+				(prefs.text_search_follow == 1? follow: 0) |
+				(prefs.text_search_regexp == 1? regexp: 0));
 	if (!is_session (sess))
 	{
 		fe_message (_("The window you opened this Search "
@@ -58,10 +63,20 @@ search_search (session * sess, const gchar *text)
 		return;
 	}
 
-	last = gtk_xtext_search (GTK_XTEXT (sess->gui->xtext), text,
-									 last, case_match, search_backward);
-	if (!last)
+	last = gtk_xtext_search (GTK_XTEXT (sess->gui->xtext), text, flags, &err);
+	if (text == NULL || text[0] == 0)
+	{
+		return;
+	}
+	if (err)
+	{
+		fe_message (_(err->message), FE_MSG_ERROR);
+		g_error_free (err);
+	}
+	else if (!last)
+	{
 		fe_message (_("Search hit end, not found."), FE_MSG_ERROR);
+	}
 }
 
 static void
@@ -79,6 +94,23 @@ static void
 search_close_cb (GtkWidget * button, GtkWidget * win)
 {
 	gtk_widget_destroy (win);
+	searchwin = NULL;
+}
+
+static void
+search_reset_cb (GtkWidget * button, session * sess)
+{
+	search_search (sess, "");
+	if (searchwin)
+	{
+		search_close_cb (button, searchwin);
+	}
+}
+
+static void
+search_cleanup_cb (GtkWidget * button, GtkWidget * win)
+{
+	searchwin = NULL;
 }
 
 static void
@@ -98,13 +130,26 @@ search_key_cb (GtkWidget * window, GdkEventKey * key, gpointer userdata)
 static void
 search_caseign_cb (GtkToggleButton * but, session * sess)
 {
-	case_match = (but->active)? 1: 0;
+	prefs.text_search_case_match = (but->active)? 1: 0;
 }
 
 static void
 search_dirbwd_cb (GtkToggleButton * but, session * sess)
 {
-	search_backward = (but->active)? 1: 0;
+	prefs.text_search_backward = (but->active)? 1: 0;
+}
+
+static void
+search_regexp_cb (GtkToggleButton * but, session * sess)
+{
+	prefs.text_search_regexp = (but->active)? 1: 0;
+}
+
+static void
+search_highlight_cb (GtkToggleButton * but, session * sess)
+{
+	prefs.text_search_highlight_all = (but->active)? 1: 0;
+	search_search (sess, NULL);
 }
 
 void
@@ -112,18 +157,21 @@ search_open (session * sess)
 {
 	GtkWidget *win, *hbox, *vbox, *entry, *wid;
 
-	last = NULL;
+	if (searchwin)
+	{
+		gtk_widget_destroy (searchwin);
+		searchwin = NULL;
+	}
 	win = mg_create_generic_tab ("search", _("XChat: Search"), TRUE, FALSE,
-								 NULL, NULL, 0, 0, &vbox, 0);
+								 search_cleanup_cb, NULL, 0, 0, &vbox, 0);
 	gtk_container_set_border_width (GTK_CONTAINER (win), 12);
 	gtk_box_set_spacing (GTK_BOX (vbox), 4);
 
+	/* First line:  _____________________   _Find */
 	hbox = gtk_hbox_new (0, 10);
 	gtk_container_add (GTK_CONTAINER (vbox), hbox);
 	gtk_widget_show (hbox);
 
-	gtkutil_label_new (_("Find:"), hbox);
-
 	entry = gtk_entry_new ();
 	g_signal_connect (G_OBJECT (entry), "activate",
 							G_CALLBACK (search_entry_cb), sess);
@@ -131,29 +179,61 @@ search_open (session * sess)
 	gtk_widget_show (entry);
 	gtk_widget_grab_focus (entry);
 
+	wid = gtk_hbutton_box_new ();
+	gtk_container_add (GTK_CONTAINER (hbox), wid);
+	gtk_widget_show (wid);
+	wid = gtkutil_button (wid, GTK_STOCK_FIND, 0, search_find_cb, sess,
+								 _("_Find"));
+	g_object_set_data (G_OBJECT (wid), "e", entry);
+
+	/* Second line:  X Match case */
 	wid = gtk_check_button_new_with_mnemonic (_("_Match case"));
-	GTK_TOGGLE_BUTTON (wid)->active = case_match;
+	GTK_TOGGLE_BUTTON (wid)->active = prefs.text_search_case_match;
 	g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (search_caseign_cb), sess);
 	gtk_container_add (GTK_CONTAINER (vbox), wid);
+	add_tip (wid, "Perform a case-sensitive search.");
 	gtk_widget_show (wid);
 
+	/* Third line:  X Search backwards */
 	wid = gtk_check_button_new_with_mnemonic (_("Search _backwards"));
-	GTK_TOGGLE_BUTTON (wid)->active = search_backward;
+	GTK_TOGGLE_BUTTON (wid)->active = prefs.text_search_backward;
 	g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (search_dirbwd_cb), sess);
 	gtk_container_add (GTK_CONTAINER (vbox), wid);
+	add_tip (wid, "Search from the newest text line to the oldest.");
+	gtk_widget_show (wid);
+
+	/* Fourth line:  X Highlight all */
+	wid = gtk_check_button_new_with_mnemonic (_("_Highlight all"));
+	GTK_TOGGLE_BUTTON (wid)->active = prefs.text_search_highlight_all;
+	g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (search_highlight_cb), sess);
+	gtk_container_add (GTK_CONTAINER (vbox), wid);
+	add_tip (wid, "Highlight all occurrences, and underline the current occurrence.");
 	gtk_widget_show (wid);
 
+	/* Fifth line:  X Regular expression */
+	wid = gtk_check_button_new_with_mnemonic (_("R_egular expression"));
+	GTK_TOGGLE_BUTTON (wid)->active = prefs.text_search_regexp;
+	g_signal_connect (G_OBJECT (wid), "toggled", G_CALLBACK (search_regexp_cb), sess);
+	gtk_container_add (GTK_CONTAINER (vbox), wid);
+	add_tip (wid, "Regard search string as a regular expression.");
+	gtk_widget_show (wid);
+
+	/* Sixth line:  _Close    Close and _Reset */
 	hbox = gtk_hbutton_box_new ();
 	gtk_box_pack_start (GTK_BOX (vbox), hbox, 0, 0, 4);
 	gtk_widget_show (hbox);
 
-	gtkutil_button (hbox, GTK_STOCK_CLOSE, 0, search_close_cb, win,
+	wid = gtkutil_button (hbox, GTK_STOCK_CLOSE, 0, search_close_cb, win,
 						_("_Close"));
-	wid = gtkutil_button (hbox, GTK_STOCK_FIND, 0, search_find_cb, sess,
-								_("_Find"));
-	g_object_set_data (G_OBJECT (wid), "e", entry);
+	add_tip (wid, "Close this box, but continue searching new lines.");
+	wid = gtkutil_button (hbox, "gtk-reset", 0, search_reset_cb, sess,
+						_("Close and _Reset"));
+	add_tip (wid, "Close this box, reset highlighted search items, and stop searching new lines.");
 
-	g_signal_connect (G_OBJECT (win), "key-press-event", G_CALLBACK (search_key_cb), win);
+	/* Add recognition of the ESC key to close the box */
+	g_signal_connect (G_OBJECT (win), "key_press_event", G_CALLBACK (search_key_cb), win);
 
+	/* That's all, folks */
+	searchwin = win;
 	gtk_widget_show (win);
 }
diff --git a/src/fe-gtk/servlistgui.c b/src/fe-gtk/servlistgui.c
index 2ac0e6c9..96feb5f4 100644
--- a/src/fe-gtk/servlistgui.c
+++ b/src/fe-gtk/servlistgui.c
@@ -61,7 +61,7 @@ static GtkWidget *entry_nick1;
 static GtkWidget *entry_nick2;
 static GtkWidget *entry_nick3;
 static GtkWidget *entry_guser;
-static GtkWidget *entry_greal;
+/* static GtkWidget *entry_greal; */
 
 /* edit area */
 static GtkWidget *edit_win;
@@ -649,8 +649,8 @@ servlist_savegui (void)
 	if (GTK_ENTRY (entry_guser)->text[0] == 0)
 		return 1;
 
-	if (GTK_ENTRY (entry_greal)->text[0] == 0)
-		return 1;
+	/* if (GTK_ENTRY (entry_greal)->text[0] == 0)
+		return 1; */
 
 	strcpy (prefs.nick1, GTK_ENTRY (entry_nick1)->text);
 	strcpy (prefs.nick2, GTK_ENTRY (entry_nick2)->text);
@@ -659,7 +659,7 @@ servlist_savegui (void)
 	sp = strchr (prefs.username, ' ');
 	if (sp)
 		sp[0] = 0;	/* spaces will break the login */
-	strcpy (prefs.realname, GTK_ENTRY (entry_greal)->text);
+	/* strcpy (prefs.realname, GTK_ENTRY (entry_greal)->text); */
 	servlist_save ();
 
 	return 0;
@@ -1624,12 +1624,12 @@ servlist_open_networks (void)
 	GtkWidget *label4;
 	GtkWidget *label5;
 	GtkWidget *label6;
-	GtkWidget *label7;
+	/* GtkWidget *label7; */
 	GtkWidget *entry1;
 	GtkWidget *entry2;
 	GtkWidget *entry3;
 	GtkWidget *entry4;
-	GtkWidget *entry5;
+	/* GtkWidget *entry5; */
 	GtkWidget *vbox2;
 	GtkWidget *label1;
 	GtkWidget *table4;
@@ -1703,12 +1703,12 @@ servlist_open_networks (void)
 							(GtkAttachOptions) (0), 0, 0);
 	gtk_misc_set_alignment (GTK_MISC (label6), 0, 0.5);
 
-	label7 = gtk_label_new_with_mnemonic (_("Rea_l name:"));
+	/* label7 = gtk_label_new_with_mnemonic (_("Rea_l name:"));
 	gtk_widget_show (label7);
 	gtk_table_attach (GTK_TABLE (table1), label7, 0, 1, 4, 5,
 							(GtkAttachOptions) (GTK_FILL),
 							(GtkAttachOptions) (0), 0, 0);
-	gtk_misc_set_alignment (GTK_MISC (label7), 0, 0.5);
+	gtk_misc_set_alignment (GTK_MISC (label7), 0, 0.5);*/
 
 	entry_nick1 = entry1 = gtk_entry_new ();
 	gtk_entry_set_text (GTK_ENTRY (entry1), prefs.nick1);
@@ -1738,12 +1738,12 @@ servlist_open_networks (void)
 							(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
 							(GtkAttachOptions) (0), 0, 0);
 
-	entry_greal = entry5 = gtk_entry_new ();
+	/* entry_greal = entry5 = gtk_entry_new ();
 	gtk_entry_set_text (GTK_ENTRY (entry5), prefs.realname);
 	gtk_widget_show (entry5);
 	gtk_table_attach (GTK_TABLE (table1), entry5, 1, 2, 4, 5,
 							(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-							(GtkAttachOptions) (0), 0, 0);
+							(GtkAttachOptions) (0), 0, 0); */
 
 	vbox2 = gtk_vbox_new (FALSE, 0);
 	gtk_widget_show (vbox2);
@@ -1882,7 +1882,7 @@ servlist_open_networks (void)
 
 	gtk_label_set_mnemonic_widget (GTK_LABEL (label3), entry1);
 	gtk_label_set_mnemonic_widget (GTK_LABEL (label6), entry4);
-	gtk_label_set_mnemonic_widget (GTK_LABEL (label7), entry5);
+	/* gtk_label_set_mnemonic_widget (GTK_LABEL (label7), entry5); */
 
 	gtk_widget_grab_focus (networks_tree);
 	gtk_widget_grab_default (button_close);
diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c
index 517e0944..cec06b25 100644
--- a/src/fe-gtk/setup.c
+++ b/src/fe-gtk/setup.c
@@ -102,7 +102,12 @@ typedef struct
 static const setting textbox_settings[] =
 {
 	{ST_HEADER,	N_("Text Box Appearance"),0,0,0},
+#ifdef WIN32
+	{ST_EFONT,  N_("Main font:"), P_OFFSETNL(font_main), 0, 0, sizeof prefs.font_main},
+	{ST_ENTRY,  N_("Alternative fonts:"), P_OFFSETNL(font_alternative), "Separate multiple entries with commas without spaces before or after.", 0, sizeof prefs.font_alternative},
+#else
 	{ST_EFONT,  N_("Font:"), P_OFFSETNL(font_normal), 0, 0, sizeof prefs.font_normal},
+#endif
 	{ST_EFILE,  N_("Background image:"), P_OFFSETNL(background), 0, 0, sizeof prefs.background},
 	{ST_NUMBER,	N_("Scrollback lines:"), P_OFFINTNL(max_lines),0,0,100000},
 	{ST_TOGGLE, N_("Colored nick names"), P_OFFINTNL(colorednicks),
@@ -120,7 +125,24 @@ static const setting textbox_settings[] =
 	{ST_HEADER,	N_("Time Stamps"),0,0,0},
 	{ST_TOGGLE, N_("Enable time stamps"), P_OFFINTNL(timestamp),0,0,2},
 	{ST_ENTRY,  N_("Time stamp format:"), P_OFFSETNL(stamp_format),
-					N_("See strftime manpage for details."),0,sizeof prefs.stamp_format},
+#ifdef WIN32
+					N_("See the strftime MSDN article for details."),0,sizeof prefs.stamp_format},
+#else
+					N_("See the strftime manpage for details."),0,sizeof prefs.stamp_format},
+#endif
+
+	{ST_HEADER,	N_("Auto-Copy Behavior"),0,0,0},
+	{ST_TOGGLE, N_("Automatically copy selected text"), P_OFFINTNL(autocopy_text),
+					N_("Copy selected text to clipboard when left mouse button is released. "
+						"Otherwise, CONTROL-SHIFT-C will copy the "
+						"selected text to the clipboard."), 0, 0},
+	{ST_TOGGLE, N_("Automatically include time stamps"), P_OFFINTNL(autocopy_stamp),
+					N_("Automatically include time stamps in copied lines of text. Otherwise, "
+						"include time stamps if the SHIFT key is held down while selecting."), 0, 0},
+	{ST_TOGGLE, N_("Automatically include color information"), P_OFFINTNL(autocopy_color),
+					N_("Automatically include color information in copied lines of text.  "
+						"Otherwise, include color information if the CONTROL key is held down "
+						"while selecting."), 0, 0},
 
 	{ST_END, 0, 0, 0, 0, 0}
 };
@@ -138,6 +160,12 @@ static const setting inputbox_settings[] =
 	{ST_TOGGLE, N_("Use the Text box font and colors"), P_OFFINTNL(style_inputbox),0,0,0},
 #if defined(USE_GTKSPELL) || defined(USE_LIBSEXY)
 	{ST_TOGGLE, N_("Spell checking"), P_OFFINTNL(gui_input_spell),0,0,0},
+	{ST_ENTRY,	N_("Dictionaries to use:"), P_OFFSETNL(spell_langs),0,0,sizeof prefs.spell_langs},
+#ifdef WIN32
+	{ST_LABEL,	N_("Use language codes (as in \"share\\myspell\\dicts\").\nSeparate multiple entries with commas.")},
+#else
+	{ST_LABEL,	N_("Use language codes. Separate multiple entries with commas.")},
+#endif
 #endif
 
 	{ST_HEADER, N_("Nick Completion"),0,0,0},
@@ -348,6 +376,24 @@ static const setting alert_settings[] =
 	{ST_END, 0, 0, 0, 0, 0}
 };
 
+static const setting alert_settings_xtray[] =
+{
+	{ST_HEADER,	N_("Alerts"),0,0,0},
+
+	{ST_ALERTHEAD},
+	{ST_3OGGLE, N_("Blink task bar on:"), 0, 0, (void *)taskbarlist, 0},
+	{ST_3OGGLE, N_("Make a beep sound on:"), 0, 0, (void *)beeplist, 0},
+
+	{ST_HEADER,	N_("Highlighted Messages"),0,0,0},
+	{ST_LABEL,	N_("Highlighted messages are ones where your nickname is mentioned, but also:"), 0, 0, 0, 1},
+
+	{ST_ENTRY,	N_("Extra words to highlight:"), P_OFFSETNL(irc_extra_hilight), 0, 0, sizeof prefs.irc_extra_hilight},
+	{ST_ENTRY,	N_("Nick names not to highlight:"), P_OFFSETNL(irc_no_hilight), 0, 0, sizeof prefs.irc_no_hilight},
+	{ST_ENTRY,	N_("Nick names to always highlight:"), P_OFFSETNL(irc_nick_hilight), 0, 0, sizeof prefs.irc_nick_hilight},
+	{ST_LABEL,	N_("Separate multiple words with commas.\nWildcards are accepted.")},
+	{ST_END, 0, 0, 0, 0, 0}
+};
+
 static const setting general_settings[] =
 {
 	{ST_HEADER,	N_("Default Messages"),0,0,0},
@@ -363,7 +409,6 @@ static const setting general_settings[] =
 	{ST_END, 0, 0, 0, 0, 0}
 };
 
-#if 0
 static const setting advanced_settings[] =
 {
 	{ST_HEADER,	N_("Advanced Settings"),0,0,0},
@@ -371,6 +416,25 @@ static const setting advanced_settings[] =
 	{ST_TOGGLE,	N_("Display MODEs in raw form"), P_OFFINTNL(raw_modes), 0, 0, 0},
 	{ST_TOGGLE,	N_("Whois on notify"), P_OFFINTNL(whois_on_notifyonline), N_("Sends a /WHOIS when a user comes online in your notify list"), 0, 0},
 	{ST_TOGGLE,	N_("Hide join and part messages"), P_OFFINTNL(confmode), N_("Hide channel join/part messages by default"), 0, 0},
+	{ST_ENTRY,	N_("License Text:"), P_OFFSETNL(gui_license), 0, 0, sizeof prefs.gui_license},
+	{ST_HEADER,	N_("Auto Open DCC Windows"),0,0,0},
+	{ST_TOGGLE, N_("Send window"), P_OFFINTNL(autoopendccsendwindow), 0, 0, 0},
+	{ST_TOGGLE, N_("Receive window"), P_OFFINTNL(autoopendccrecvwindow), 0, 0, 0},
+	{ST_TOGGLE, N_("Chat window"), P_OFFINTNL(autoopendccchatwindow), 0, 0, 0},
+
+	{ST_END, 0, 0, 0, 0, 0}
+};
+
+#ifdef WIN32
+static const setting advanced_settings_oneinstance[] =
+{
+	{ST_HEADER,	N_("Advanced Settings"),0,0,0},
+	{ST_NUMBER,	N_("Auto reconnect delay:"), P_OFFINTNL(recon_delay), 0, 0, 9999},
+	{ST_TOGGLE,	N_("Display MODEs in raw form"), P_OFFINTNL(raw_modes), 0, 0, 0},
+	{ST_TOGGLE,	N_("Whois on notify"), P_OFFINTNL(whois_on_notifyonline), N_("Sends a /WHOIS when a user comes online in your notify list"), 0, 0},
+	{ST_TOGGLE,	N_("Hide join and part messages"), P_OFFINTNL(confmode), N_("Hide channel join/part messages by default"), 0, 0},
+	{ST_TOGGLE,	N_("Allow only one instance of XChat to run"), P_OFFINTNL(gui_one_instance), 0, 0, 0},
+	{ST_ENTRY,	N_("License Text:"), P_OFFSETNL(gui_license), 0, 0, sizeof prefs.gui_license},
 	{ST_HEADER,	N_("Auto Open DCC Windows"),0,0,0},
 	{ST_TOGGLE, N_("Send window"), P_OFFINTNL(autoopendccsendwindow), 0, 0, 0},
 	{ST_TOGGLE, N_("Receive window"), P_OFFINTNL(autoopendccrecvwindow), 0, 0, 0},
@@ -391,7 +455,11 @@ static const setting logging_settings[] =
 	{ST_HEADER,	N_("Time Stamps"),0,0,0},
 	{ST_TOGGLE,	N_("Insert timestamps in logs"), P_OFFINTNL(timestamp_logs), 0, 0, 2},
 	{ST_ENTRY,	N_("Log timestamp format:"), P_OFFSETNL(timestamp_log_format), 0, 0, sizeof prefs.timestamp_log_format},
-	{ST_LABEL,	N_("See strftime manpage for details.")},
+#ifdef WIN32
+	{ST_LABEL,	N_("See the strftime MSDN article for details.")},
+#else
+	{ST_LABEL,	N_("See the strftime manpage for details.")},
+#endif
 
 	{ST_END, 0, 0, 0, 0, 0}
 };
@@ -1328,6 +1396,9 @@ setup_create_color_page (void)
 	setup_create_other_color (_("New message:"), COL_NEW_MSG, 10, tab);
 	setup_create_other_colorR (_("Away user:"), COL_AWAY, 10, tab);
 	setup_create_other_color (_("Highlight:"), COL_HILIGHT, 11, tab);
+#if defined(USE_GTKSPELL) || defined(USE_LIBSEXY)
+	setup_create_other_colorR (_("Spell checker:"), COL_SPELL, 11, tab);
+#endif
 
 	return box;
 }
@@ -1711,7 +1782,7 @@ static const char *const cata[] =
 		N_("General"),
 		N_("Logging"),
 		N_("Sound"),
-/*		N_("Advanced"),*/
+		N_("Advanced"),
 		NULL,
 	N_("Network"),
 		N_("Network setup"),
@@ -1732,10 +1803,33 @@ setup_create_pages (GtkWidget *box)
 	setup_add_page (cata[3], book, setup_create_page (userlist_settings));
 	setup_add_page (cata[4], book, setup_create_page (tabs_settings));
 	setup_add_page (cata[5], book, setup_create_color_page ());
-	setup_add_page (cata[8], book, setup_create_page (alert_settings));
+
+	if (xtray_mode ())
+	{
+		setup_add_page (cata[8], book, setup_create_page (alert_settings_xtray));
+	}
+	else
+	{
+		setup_add_page (cata[8], book, setup_create_page (alert_settings));
+	}
+
 	setup_add_page (cata[9], book, setup_create_page (general_settings));
 	setup_add_page (cata[10], book, setup_create_page (logging_settings));
 	setup_add_page (cata[11], book, setup_create_sound_page ());
+
+#ifdef WIN32
+	if (portable_mode ())
+	{
+		setup_add_page (cata[12], book, setup_create_page (advanced_settings));
+	}
+	else
+	{
+		setup_add_page (cata[12], book, setup_create_page (advanced_settings_oneinstance));
+	}
+#else
+	setup_add_page (cata[12], book, setup_create_page (advanced_settings));
+#endif
+
 	setup_add_page (cata[14], book, setup_create_page (network_settings));
 	setup_add_page (cata[15], book, setup_create_page (filexfer_settings));
 
@@ -1971,6 +2065,12 @@ setup_apply_real (int new_pix, int do_ulist, int do_layout)
 static void
 setup_apply (struct xchatprefs *pr)
 {
+#ifdef WIN32
+	PangoFontDescription *old_desc;
+	PangoFontDescription *new_desc;
+	char buffer[4 * FONTNAMELEN + 1];
+	time_t rawtime;
+#endif
 	int new_pix = FALSE;
 	int noapply = FALSE;
 	int do_ulist = FALSE;
@@ -2014,6 +2114,30 @@ setup_apply (struct xchatprefs *pr)
 
 	memcpy (&prefs, pr, sizeof (prefs));
 
+#ifdef WIN32
+	/* merge font_main and font_alternative into font_normal */
+	old_desc = pango_font_description_from_string (prefs.font_main);
+	sprintf (buffer, "%s,%s", pango_font_description_get_family (old_desc), prefs.font_alternative);
+	new_desc = pango_font_description_from_string (buffer);
+	pango_font_description_set_weight (new_desc, pango_font_description_get_weight (old_desc));
+	pango_font_description_set_style (new_desc, pango_font_description_get_style (old_desc));
+	pango_font_description_set_size (new_desc, pango_font_description_get_size (old_desc));
+	sprintf (prefs.font_normal, "%s", pango_font_description_to_string (new_desc));
+
+	/* FIXME this is not required after pango_font_description_from_string()
+	g_free (old_desc);
+	g_free (new_desc);
+	*/
+
+	/* workaround for strftime differences between POSIX and MSVC */
+	time (&rawtime);
+
+	if (!strftime (buffer, sizeof (buffer), prefs.stamp_format, localtime (&rawtime)) || !strftime (buffer, sizeof (buffer), prefs.timestamp_log_format, localtime (&rawtime)))
+	{
+		fe_message (_("Invalid time stamp format! See the strftime MSDN article for details."), FE_MSG_ERROR);
+	}
+#endif
+
 	setup_apply_real (new_pix, do_ulist, do_layout);
 
 	if (noapply)
diff --git a/src/fe-gtk/sexy-iso-codes.c b/src/fe-gtk/sexy-iso-codes.c
new file mode 100644
index 00000000..4b637c9f
--- /dev/null
+++ b/src/fe-gtk/sexy-iso-codes.c
@@ -0,0 +1,305 @@
+/*
+ *  Copyright (C) 2005 Nathan Fredrickson
+ *  Borrowed from Galeon, renamed, and simplified to only use iso-codes with no
+ *  fallback method.
+ *
+ *  Copyright (C) 2004 Christian Persch
+ *  Copyright (C) 2004 Crispin Flowerday
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include "../../config.h"
+
+#include "sexy-iso-codes.h"
+
+#include <glib/gi18n.h>
+
+#include <string.h>
+
+#include <libxml/xmlreader.h>
+
+static GHashTable *iso_639_table = NULL;
+static GHashTable *iso_3166_table = NULL;
+
+#define ISO_639_DOMAIN	"iso_639"
+#define ISO_3166_DOMAIN	"iso_3166"
+
+#ifdef HAVE_ISO_CODES
+
+#define ISOCODESLOCALEDIR "/share/locale"
+
+static void
+read_iso_639_entry (xmlTextReaderPtr reader,
+		    GHashTable *table)
+{
+	xmlChar *code, *name;
+
+	code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_1_code");
+	name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");
+
+	/* Get iso-639-2 code */
+	if (code == NULL || code[0] == '\0')
+	{
+		xmlFree (code);
+		/* FIXME: use the 2T or 2B code? */
+		code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_2T_code");
+	}
+
+	if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0')
+	{
+		g_hash_table_insert (table, code, name);
+	}
+	else
+	{
+		xmlFree (code);
+		xmlFree (name);
+	}
+}
+
+static void
+read_iso_3166_entry (xmlTextReaderPtr reader,
+		     GHashTable *table)
+{
+	xmlChar *code, *name;
+
+	code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "alpha_2_code");
+	name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");
+
+	if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0')
+	{
+		char *lcode;
+
+		lcode = g_ascii_strdown ((char *) code, -1);
+		xmlFree (code);
+
+		g_hash_table_insert (table, lcode, name);
+	}
+	else
+	{
+		xmlFree (code);
+		xmlFree (name);
+	}
+
+}
+
+typedef enum
+{
+	STATE_START,
+	STATE_STOP,
+	STATE_ENTRIES,
+} ParserState;
+
+static gboolean
+load_iso_entries (int iso,
+		  GFunc read_entry_func,
+		  gpointer user_data)
+{
+	xmlTextReaderPtr reader;
+	ParserState state = STATE_START;
+	xmlChar iso_entries[32], iso_entry[32];
+	char *filename;
+	int ret = -1;
+
+#ifdef WIN32
+	filename = g_strdup_printf (".\\share\\xml\\iso-codes\\iso_%d.xml", iso);
+#else
+	filename = g_strdup_printf ("/usr/share/xml/iso-codes/iso_%d.xml", iso);
+#endif
+	reader = xmlNewTextReaderFilename (filename);
+	if (reader == NULL) goto out;
+
+	xmlStrPrintf (iso_entries, sizeof (iso_entries),
+				  (xmlChar *)"iso_%d_entries", iso);
+	xmlStrPrintf (iso_entry, sizeof (iso_entry),
+				  (xmlChar *)"iso_%d_entry", iso);
+
+	ret = xmlTextReaderRead (reader);
+
+	while (ret == 1)
+	{
+		const xmlChar *tag;
+		xmlReaderTypes type;
+
+		tag = xmlTextReaderConstName (reader);
+		type = xmlTextReaderNodeType (reader);
+
+		if (state == STATE_ENTRIES &&
+		    type == XML_READER_TYPE_ELEMENT &&
+		    xmlStrEqual (tag, iso_entry))
+		{
+			read_entry_func (reader, user_data);
+		}
+		else if (state == STATE_START &&
+			 type == XML_READER_TYPE_ELEMENT &&
+			 xmlStrEqual (tag, iso_entries))
+		{
+			state = STATE_ENTRIES;
+		}
+		else if (state == STATE_ENTRIES &&
+			 type == XML_READER_TYPE_END_ELEMENT &&
+			 xmlStrEqual (tag, iso_entries))
+		{
+			state = STATE_STOP;
+		}
+		else if (type == XML_READER_TYPE_SIGNIFICANT_WHITESPACE ||
+			 type == XML_READER_TYPE_WHITESPACE ||
+			 type == XML_READER_TYPE_TEXT ||
+			 type == XML_READER_TYPE_COMMENT)
+		{
+			/* eat it */
+		}
+		else
+		{
+			/* ignore it */
+		}
+
+		ret = xmlTextReaderRead (reader);
+	}
+
+	xmlFreeTextReader (reader);
+
+out:
+	if (ret < 0 || state != STATE_STOP)
+	{
+		/* This is not critical, we will fallback to our own code */
+		g_free (filename);
+		return FALSE;
+	}
+
+	g_free (filename);
+
+	return TRUE;
+}
+
+#endif /* HAVE_ISO_CODES */
+
+
+static void
+ensure_iso_codes_initialised (void)
+{
+	static gboolean initialised = FALSE;
+
+	if (initialised == TRUE)
+	{
+		return;
+	}
+	initialised = TRUE;
+
+#if defined (ENABLE_NLS) && defined (HAVE_ISO_CODES)
+	bindtextdomain (ISO_639_DOMAIN, ISOCODESLOCALEDIR);
+	bind_textdomain_codeset (ISO_639_DOMAIN, "UTF-8");
+
+	bindtextdomain(ISO_3166_DOMAIN, ISOCODESLOCALEDIR);
+	bind_textdomain_codeset (ISO_3166_DOMAIN, "UTF-8");
+#endif
+
+	iso_639_table = g_hash_table_new_full (g_str_hash, g_str_equal,
+					       (GDestroyNotify) xmlFree,
+					       (GDestroyNotify) xmlFree);
+
+	iso_3166_table = g_hash_table_new_full (g_str_hash, g_str_equal,
+						(GDestroyNotify) g_free,
+						(GDestroyNotify) xmlFree);
+	
+#ifdef HAVE_ISO_CODES
+	load_iso_entries (639, (GFunc) read_iso_639_entry, iso_639_table);
+	load_iso_entries (3166, (GFunc) read_iso_3166_entry, iso_3166_table);
+#endif
+}
+
+
+static char *
+get_iso_name_for_lang_code (const char *code)
+{
+	char **str;
+	char *name = NULL;
+	const char *langname, *localename;
+	int len;
+
+	str = g_strsplit (code, "_", -1);
+
+	/* count the entries */
+	for (len = 0; str[len]; len++ ) /* empty */;
+
+	g_return_val_if_fail (len != 0, NULL);
+
+	langname = (const char *) g_hash_table_lookup (iso_639_table, str[0]);
+
+	if (len == 1 && langname != NULL)
+	{
+		name = g_strdup (dgettext (ISO_639_DOMAIN, langname));
+	}
+	else if (len == 2 && langname != NULL)
+	{
+		localename = (const char *) g_hash_table_lookup (iso_3166_table, str[1]);
+
+		if (localename != NULL)
+		{
+			/* translators: the first %s is the language name, and the
+			 * second %s is the locale name. Example:
+			 * "French (France)
+			 *
+			 * Also: The text before the "|" is context to help you decide on
+                         * the correct translation. You MUST OMIT it in the translated string.
+			 */
+			name = g_strdup_printf (Q_("language|%s (%s)"),
+						dgettext (ISO_639_DOMAIN, langname),
+						dgettext (ISO_3166_DOMAIN, localename));
+		}
+		else
+		{
+			name = g_strdup_printf (Q_("language|%s (%s)"),
+						dgettext (ISO_639_DOMAIN, langname), str[1]);
+		}
+	}
+
+	g_strfreev (str);
+
+	return name;
+}
+
+/**
+ * gtkspell_iso_codes_lookup_name_for_code:
+ * @code: A language code, e.g. en_CA
+ *
+ * Looks up a name to display to the user for a language code,
+ * this might use the iso-codes package if support was compiled
+ * in, and it is available
+ *
+ * Returns: the UTF-8 string to display to the user, or NULL if 
+ * a name for the code could not be found
+ */
+char *
+gtkspell_iso_codes_lookup_name_for_code (const char *code)
+{
+	char * lcode;
+	char * ret;
+
+	g_return_val_if_fail (code != NULL, NULL);
+
+	ensure_iso_codes_initialised ();
+
+	lcode = g_ascii_strdown (code, -1);
+
+	ret = get_iso_name_for_lang_code (lcode);
+
+	g_free (lcode);
+
+	return ret;
+}
+
diff --git a/src/fe-gtk/sexy-iso-codes.h b/src/fe-gtk/sexy-iso-codes.h
new file mode 100644
index 00000000..e5f37162
--- /dev/null
+++ b/src/fe-gtk/sexy-iso-codes.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (C) 2005 Nathan Fredrickson
+ *  Borrowed from Galeon, renamed, and simplified to only use iso-codes with no
+ *  fallback method.
+ *
+ *  Copyright (C) 2004 Christian Persch
+ *  Copyright (C) 2004 Crispin Flowerday
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ *
+ */
+
+#ifndef GTKSPELL_ISO_CODES_H
+#define GTKSPELL_ISO_CODES_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+char *  gtkspell_iso_codes_lookup_name_for_code (const char *code);
+
+G_END_DECLS
+
+#endif
diff --git a/src/fe-gtk/sexy-marshal.c b/src/fe-gtk/sexy-marshal.c
new file mode 100644
index 00000000..10a629f2
--- /dev/null
+++ b/src/fe-gtk/sexy-marshal.c
@@ -0,0 +1,129 @@
+
+#include	<glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* BOOLEAN:STRING (./marshal.list:1) */
+void
+sexy_marshal_BOOLEAN__STRING (GClosure     *closure,
+                              GValue       *return_value,
+                              guint         n_param_values,
+                              const GValue *param_values,
+                              gpointer      invocation_hint,
+                              gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__STRING) (gpointer     data1,
+                                                    gpointer     arg_1,
+                                                    gpointer     data2);
+  register GMarshalFunc_BOOLEAN__STRING callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__STRING) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_string (param_values + 1),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+/* OBJECT:OBJECT,OBJECT (./marshal.list:2) */
+void
+sexy_marshal_OBJECT__OBJECT_OBJECT (GClosure     *closure,
+                                    GValue       *return_value,
+                                    guint         n_param_values,
+                                    const GValue *param_values,
+                                    gpointer      invocation_hint,
+                                    gpointer      marshal_data)
+{
+  typedef GObject* (*GMarshalFunc_OBJECT__OBJECT_OBJECT) (gpointer     data1,
+                                                          gpointer     arg_1,
+                                                          gpointer     arg_2,
+                                                          gpointer     data2);
+  register GMarshalFunc_OBJECT__OBJECT_OBJECT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  GObject* v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_OBJECT__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_object (param_values + 1),
+                       g_marshal_value_peek_object (param_values + 2),
+                       data2);
+
+  g_value_take_object (return_value, v_return);
+}
+
diff --git a/src/fe-gtk/sexy-marshal.h b/src/fe-gtk/sexy-marshal.h
new file mode 100644
index 00000000..f41eccbe
--- /dev/null
+++ b/src/fe-gtk/sexy-marshal.h
@@ -0,0 +1,28 @@
+
+#ifndef __sexy_marshal_MARSHAL_H__
+#define __sexy_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+/* BOOLEAN:STRING (./marshal.list:1) */
+extern void sexy_marshal_BOOLEAN__STRING (GClosure     *closure,
+                                          GValue       *return_value,
+                                          guint         n_param_values,
+                                          const GValue *param_values,
+                                          gpointer      invocation_hint,
+                                          gpointer      marshal_data);
+
+/* OBJECT:OBJECT,OBJECT (./marshal.list:2) */
+extern void sexy_marshal_OBJECT__OBJECT_OBJECT (GClosure     *closure,
+                                                GValue       *return_value,
+                                                guint         n_param_values,
+                                                const GValue *param_values,
+                                                gpointer      invocation_hint,
+                                                gpointer      marshal_data);
+
+G_END_DECLS
+
+#endif /* __sexy_marshal_MARSHAL_H__ */
+
diff --git a/src/fe-gtk/sexy-spell-entry.c b/src/fe-gtk/sexy-spell-entry.c
index d67ffe2d..d6f4ad63 100644
--- a/src/fe-gtk/sexy-spell-entry.c
+++ b/src/fe-gtk/sexy-spell-entry.c
@@ -26,10 +26,19 @@
 #include <gtk/gtk.h>
 #include "sexy-spell-entry.h"
 #include <string.h>
+#include <fcntl.h>
 #include <glib/gi18n.h>
 #include <sys/types.h>
-/*#include "gtkspell-iso-codes.h"
-#include "sexy-marshal.h"*/
+#include <sys/stat.h>
+#include "sexy-iso-codes.h"
+#include "sexy-marshal.h"
+
+#ifdef WIN32
+#include "typedef.h"
+#endif
+
+#include "../common/cfgfiles.h"
+#include "../common/xchatc.h"
 
 /*
  * Bunch of poop to make enchant into a runtime dependency rather than a
@@ -134,12 +143,19 @@ initialize_enchant ()
 	GModule *enchant;
 	gpointer funcptr;
 
+#ifdef WIN32
+	enchant = g_module_open("libenchant.dll", 0);
+#else
 	enchant = g_module_open("libenchant", 0);
+#endif
 	if (enchant == NULL)
 	{
+#ifndef WIN32
 		enchant = g_module_open("libenchant.so.1", 0);
-		if (enchant == NULL)
-			return;
+				if (enchant == NULL)
+					return;
+#endif
+		return;
 	}
 
 	have_enchant = TRUE;
@@ -207,14 +223,14 @@ sexy_spell_entry_class_init(SexySpellEntryClass *klass)
 	 * Returns: %FALSE to indicate that the word should be marked as
 	 * correct.
 	 */
-/*	signals[WORD_CHECK] = g_signal_new("word_check",
+	signals[WORD_CHECK] = g_signal_new("word_check",
 					   G_TYPE_FROM_CLASS(object_class),
 					   G_SIGNAL_RUN_LAST,
 					   G_STRUCT_OFFSET(SexySpellEntryClass, word_check),
 					   (GSignalAccumulator) spell_accumulator, NULL,
 					   sexy_marshal_BOOLEAN__STRING,
 					   G_TYPE_BOOLEAN,
-					   1, G_TYPE_STRING);*/
+					   1, G_TYPE_STRING);
 }
 
 static void
@@ -260,8 +276,42 @@ gtk_entry_find_position (GtkEntry *entry, gint x)
 static void
 insert_underline(SexySpellEntry *entry, guint start, guint end)
 {
-	PangoAttribute *ucolor = pango_attr_underline_color_new (65535, 0, 0);
-	PangoAttribute *unline = pango_attr_underline_new (PANGO_UNDERLINE_ERROR);
+	int fh, l;
+	int red, green, blue;
+	struct stat st;
+	char *cfg;
+	PangoAttribute *ucolor;
+	PangoAttribute *unline;
+
+	fh = xchat_open_file ("colors.conf", O_RDONLY, 0, 0);
+
+	if (fh != -1)
+	{
+		fstat (fh, &st);
+		cfg = malloc (st.st_size + 1);
+
+		if (cfg)
+		{
+			cfg[0] = '\0';
+			l = read (fh, cfg, st.st_size);
+			if (l >= 0)
+			{
+				cfg[l] = '\0';
+			}
+
+			cfg_get_color (cfg, "color_265", &red, &green, &blue);
+			free (cfg);
+		}
+
+		close (fh);
+	} else
+	{
+		red = 65535;
+		green = blue = 0;
+	}
+
+	ucolor = pango_attr_underline_color_new (red, green, blue);
+	unline = pango_attr_underline_new (PANGO_UNDERLINE_ERROR);
 
 	ucolor->start_index = start;
 	unline->start_index = start;
@@ -457,10 +507,6 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word)
 	if (entry->priv->dict_list == NULL)
 		return topmenu;
 
-#if 1
-	dict = (struct EnchantDict *) entry->priv->dict_list->data;
-	build_suggestion_menu(entry, topmenu, dict, word);
-#else
 	/* Suggestions */
 	if (g_slist_length(entry->priv->dict_list) == 1) {
 		dict = (struct EnchantDict *) entry->priv->dict_list->data;
@@ -489,7 +535,6 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word)
 			build_suggestion_menu(entry, menu, dict, word);
 		}
 	}
-#endif
 
 	/* Separator */
 	mi = gtk_separator_menu_item_new ();
@@ -503,11 +548,6 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word)
 
 	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
 
-#if 1
-	dict = (struct EnchantDict *) entry->priv->dict_list->data;
-	g_object_set_data(G_OBJECT(mi), "enchant-dict", dict);
-	g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(add_to_dictionary), entry);
-#else
 	if (g_slist_length(entry->priv->dict_list) == 1) {
 		dict = (struct EnchantDict *) entry->priv->dict_list->data;
 		g_object_set_data(G_OBJECT(mi), "enchant-dict", dict);
@@ -539,7 +579,6 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word)
 			gtk_menu_shell_append(GTK_MENU_SHELL(menu), submi);
 		}
 	}
-#endif
 
 	gtk_widget_show_all(mi);
 	gtk_menu_shell_append(GTK_MENU_SHELL(topmenu), mi);
@@ -721,11 +760,7 @@ word_misspelled(SexySpellEntry *entry, int start, int end)
 
 	g_strlcpy(word, text + start, end - start + 1);
 
-#if 0
 	g_signal_emit(entry, signals[WORD_CHECK], 0, word, &ret);
-#else
-	ret = default_word_check (entry, word);
-#endif
 
 	g_free(word);
 	return ret;
@@ -921,10 +956,10 @@ void
 sexy_spell_entry_activate_default_languages(SexySpellEntry *entry)
 {
 #if GLIB_CHECK_VERSION (2, 6, 0)
-	const gchar* const *langs;
+	/*const gchar* const *langs;
 	int i;
-	gchar *lastprefix = NULL;
-	GSList *enchant_langs;
+	gchar *lastprefix = NULL;*/
+	GSList *enchant_langs, *i;
 
 	if (!have_enchant)
 		return;
@@ -933,15 +968,15 @@ sexy_spell_entry_activate_default_languages(SexySpellEntry *entry)
 		entry->priv->broker = enchant_broker_init();
 
 
-	langs = g_get_language_names ();
+	/*langs = g_get_language_names ();
 
 	if (langs == NULL)
-		return;
+		return;*/
 
 	enchant_langs = sexy_spell_entry_get_languages(entry);
 
-	for (i = 0; langs[i]; i++) {
-		if ((g_strncasecmp(langs[i], "C", 1) != 0) &&
+	/*for (i = 0; langs[i]; i++) {
+		if ((g_ascii_strncasecmp(langs[i], "C", 1) != 0) &&
 		    (strlen(langs[i]) >= 2) &&
 		    enchant_has_lang(langs[i], enchant_langs)) {
 			if ((lastprefix == NULL) || (g_str_has_prefix(langs[i], lastprefix) == FALSE))
@@ -952,10 +987,19 @@ sexy_spell_entry_activate_default_languages(SexySpellEntry *entry)
 		}
 	}
 	if (lastprefix != NULL)
-		g_free(lastprefix);
+		g_free(lastprefix);*/
+
+	for (i = enchant_langs; i; i = g_slist_next (i))
+	{
+		if (strstr (prefs.spell_langs, i->data) != NULL)
+		{
+			sexy_spell_entry_activate_language_internal (entry, i->data, NULL);
+		}
+	}
 
 	g_slist_foreach(enchant_langs, (GFunc) g_free, NULL);
 	g_slist_free(enchant_langs);
+	g_slist_free (i);
 
 	/* If we don't have any languages activated, use "en" */
 	if (entry->priv->dict_list == NULL)
@@ -969,7 +1013,7 @@ sexy_spell_entry_activate_default_languages(SexySpellEntry *entry)
 	lang = (gchar *) g_getenv("LANG");
 
 	if (lang != NULL) {
-		if (g_strncasecmp(lang, "C", 1) == 0)
+		if (g_ascii_strncasecmp(lang, "C", 1) == 0)
 			lang = NULL;
 		else if (lang[0] == '\0')
 			lang = NULL;
@@ -1083,8 +1127,8 @@ gchar *
 sexy_spell_entry_get_language_name(const SexySpellEntry *entry,
 								   const gchar *lang)
 {
-	/*if (have_enchant)
-		return gtkspell_iso_codes_lookup_name_for_code(lang);*/
+	if (have_enchant)
+		return gtkspell_iso_codes_lookup_name_for_code(lang);
 	return NULL;
 }
 
diff --git a/src/fe-gtk/typedef.h b/src/fe-gtk/typedef.h
new file mode 100644
index 00000000..b20612ea
--- /dev/null
+++ b/src/fe-gtk/typedef.h
@@ -0,0 +1,11 @@
+#ifndef SSIZE_T_DEFINED
+#ifdef ssize_t
+#undef ssize_t
+#endif
+#ifdef _WIN64
+typedef __int64          ssize_t;
+#else
+typedef _W64 int         ssize_t;
+#endif
+#define SSIZE_T_DEFINED
+#endif
diff --git a/src/fe-gtk/xchat.exe.manifest b/src/fe-gtk/xchat.exe.manifest
new file mode 100644
index 00000000..13685d98
--- /dev/null
+++ b/src/fe-gtk/xchat.exe.manifest
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <assemblyIdentity
+    name="XChat"
+    processorArchitecture="*"
+    version="1.0.0.0"
+    type="win32"
+  />
+  <description>XChat IRC client</description>
+  <dependency>
+    <dependentAssembly>
+      <assemblyIdentity
+        type="win32"
+        name="Microsoft.Windows.Common-Controls"
+        version="6.0.0.0"
+        processorArchitecture="*"
+        publicKeyToken="6595b64144ccf1df"
+        language="*"
+      />
+    </dependentAssembly>
+  </dependency>
+</assembly>
diff --git a/src/fe-gtk/xchat.rc b/src/fe-gtk/xchat.rc
new file mode 100644
index 00000000..f63b70e7
--- /dev/null
+++ b/src/fe-gtk/xchat.rc
@@ -0,0 +1,26 @@
+#include <winver.h>

+#include "../../config.h"

+#include "../../resource.h"

+

+XC_ICON ICON "../../xchat.ico" 

+

+VS_VERSION_INFO VERSIONINFO

+	FILEVERSION    COMMA_VERSION

+	PRODUCTVERSION COMMA_VERSION

+	BEGIN

+		BLOCK "StringFileInfo"

+		BEGIN

+			BLOCK "040904B0"

+			BEGIN

+				

+				VALUE "FileDescription", "XChat-WDK IRC Client"

+				VALUE "ProductName", "XChat-WDK" 

+				VALUE "ProductVersion", PACKAGE_VERSION

+				VALUE "FileVersion", PACKAGE_VERSION

+			END

+		END

+		BLOCK "VarFileInfo"

+		BEGIN

+			VALUE "Translation", 0x0409, 0x04B0

+		END

+	END

diff --git a/src/fe-gtk/xtext.c b/src/fe-gtk/xtext.c
index fa9803c7..547affee 100644
--- a/src/fe-gtk/xtext.c
+++ b/src/fe-gtk/xtext.c
@@ -42,7 +42,6 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <time.h>
-#include <unistd.h>
 #include <gtk/gtkmain.h>
 #include <gtk/gtksignal.h>
 #include <gtk/gtkselection.h>
@@ -66,6 +65,11 @@
 #include "mmx_cmod.h"
 #endif
 
+#include "../common/xchat.h"
+#include "../common/fe.h"
+#include "../common/util.h"
+#include "../common/xchatc.h"
+#include "fe-gtk.h"
 #include "xtext.h"
 
 #define charlen(str) g_utf8_skip[*(guchar *)(str)]
@@ -73,6 +77,8 @@
 #ifdef WIN32
 #include <windows.h>
 #include <gdk/gdkwin32.h>
+#else
+#include <unistd.h>
 #endif
 
 /* is delimiter */
@@ -89,6 +95,20 @@
 
 static GtkWidgetClass *parent_class = NULL;
 
+/*
+ * offsets_t is used for retaining search information.
+ * It is stored in the 'data' member of a GList,
+ * as chained from ent->marks.  It saves starting and
+ * ending+1 offset of a found occurrence.
+ */
+typedef union offsets_u {
+	struct offsets_s {
+		guint16	start;
+		guint16	end;
+	} o;
+	guint32 u;
+} offsets_t;
+
 struct textentry
 {
 	struct textentry *next;
@@ -108,6 +128,7 @@ struct textentry
 	guchar tag;
 	guchar pad1;
 	guchar pad2;	/* 32-bit align : 44 bytes total */
+	GList *marks;	/* List of found strings */
 };
 
 enum
@@ -146,11 +167,25 @@ static void gtk_xtext_recalc_widths (xtext_buffer *buf, int);
 static void gtk_xtext_fix_indent (xtext_buffer *buf);
 static int gtk_xtext_find_subline (GtkXText *xtext, textentry *ent, int line);
 static char *gtk_xtext_conv_color (unsigned char *text, int len, int *newlen);
+/* For use by gtk_xtext_strip_color() and its callers -- */
+typedef union offlen_u {
+   struct offlen_s {
+      guint16  off;
+      guint16  len;
+   } o;
+   guint32 u;
+} offlen_t;
 static unsigned char *
 gtk_xtext_strip_color (unsigned char *text, int len, unsigned char *outbuf,
-							  int *newlen, int *mb_ret, int strip_hidden);
+							  int *newlen, int *mb_ret, GSList **slp, int strip_hidden);
 static gboolean gtk_xtext_check_ent_visibility (GtkXText * xtext, textentry *find_ent, int add);
 static int gtk_xtext_render_page_timeout (GtkXText * xtext);
+static int gtk_xtext_search_offset (xtext_buffer *buf, textentry *ent, unsigned int off);
+static void gtk_xtext_search_textentry (xtext_buffer *, textentry *, int);
+static void gtk_xtext_search_textentry_del (xtext_buffer *, textentry *);
+static void gtk_xtext_search_textentry_fini (gpointer, gpointer);
+static void gtk_xtext_search_fini (xtext_buffer *);
+static gboolean gtk_xtext_search_init (xtext_buffer *buf, const gchar *text, gtk_xtext_search_flags flags, GError **perr);
 
 /* some utility functions first */
 
@@ -163,7 +198,7 @@ nocasestrstr (const char *s, const char *tofind)
 
    if (len == 0)
      return (char *)s;
-   while (toupper(*s) != toupper(*tofind) || strncasecmp (s, tofind, len))
+   while (toupper(*s) != toupper(*tofind) || g_ascii_strncasecmp (s, tofind, len))
      if (*s++ == '\0')
        return (char *)NULL;
    return (char *)s;   
@@ -767,9 +802,8 @@ gtk_xtext_adjustment_set (xtext_buffer *buf, int fire_signal)
 		if (adj->upper == 0)
 			adj->upper = 1;
 
-		adj->page_size =
-			(GTK_WIDGET (buf->xtext)->allocation.height -
-			 buf->xtext->font->descent) / buf->xtext->fontsize;
+		adj->page_size = GTK_WIDGET (buf->xtext)->allocation.height /
+							  buf->xtext->fontsize;
 		adj->page_increment = adj->page_size;
 
 		if (adj->value > adj->upper - adj->page_size)
@@ -998,7 +1032,11 @@ gtk_xtext_realize (GtkWidget * widget)
 
 	gdk_window_set_user_data (widget->window, widget);
 
+#if GTK_CHECK_VERSION(2,24,0)
+	xtext->depth = gdk_window_get_visual (widget->window)->depth;
+#else
 	xtext->depth = gdk_drawable_get_visual (widget->window)->depth;
+#endif
 
 	val.subwindow_mode = GDK_INCLUDE_INFERIORS;
 	val.graphics_exposures = 0;
@@ -1122,18 +1160,6 @@ gtk_xtext_size_allocate (GtkWidget * widget, GtkAllocation * allocation)
 	}
 }
 
-static void
-gtk_xtext_selection_clear_full (xtext_buffer *buf)
-{
-	textentry *ent = buf->text_first;
-	while (ent)
-	{
-		ent->mark_start = -1;
-		ent->mark_end = -1;
-		ent = ent->next;
-	}
-}
-
 static int
 gtk_xtext_selection_clear (xtext_buffer *buf)
 {
@@ -1717,13 +1743,6 @@ gtk_xtext_selection_draw (GtkXText * xtext, GdkEventMotion * event, gboolean ren
 		offset_end = tmp;
 	}
 
-	/* has the selection changed? Dont render unless necessary */
-	if (xtext->buffer->last_ent_start == ent_start &&
-		 xtext->buffer->last_ent_end == ent_end &&
-		 xtext->buffer->last_offset_start == offset_start &&
-		 xtext->buffer->last_offset_end == offset_end)
-		return;
-
 	/* set all the old mark_ fields to -1 */
 	gtk_xtext_selection_clear (xtext->buffer);
 
@@ -1753,10 +1772,24 @@ gtk_xtext_selection_draw (GtkXText * xtext, GdkEventMotion * event, gboolean ren
 		gtk_xtext_selection_render (xtext, ent_start, offset_start, ent_end, offset_end);
 }
 
+static int
+gtk_xtext_timeout_ms (GtkXText *xtext, int pixes)
+{
+	int apixes = abs(pixes);
+
+	if (apixes < 6) return 100;
+	if (apixes < 12) return 50;
+	if (apixes < 20) return 20;
+	return 10;
+}
+
 static gint
 gtk_xtext_scrolldown_timeout (GtkXText * xtext)
 {
 	int p_y, win_height;
+	xtext_buffer *buf = xtext->buffer;
+	GtkAdjustment *adj = xtext->adj;
+	textentry *ent;
 
 	gdk_window_get_pointer (GTK_WIDGET (xtext)->window, 0, &p_y, 0);
 	gdk_drawable_get_size (GTK_WIDGET (xtext)->window, 0, &win_height);
@@ -1764,13 +1797,30 @@ gtk_xtext_scrolldown_timeout (GtkXText * xtext)
 	if (p_y > win_height &&
 		 xtext->adj->value < (xtext->adj->upper - xtext->adj->page_size))
 	{
-		xtext->adj->value++;
-		gtk_adjustment_changed (xtext->adj);
-		gtk_xtext_render_page (xtext);
-		return 1;
+		xtext->adj->value += buf->pagetop_ent->lines_taken;
+		ent = buf->last_ent_end->next;
+		if (ent)
+		{
+			gtk_adjustment_value_changed (xtext->adj);
+		}
+		else
+		{
+			buf->scrollbar_down = TRUE;
+		}
+		xtext->scroll_tag = g_timeout_add (gtk_xtext_timeout_ms (xtext, p_y - win_height),
+														(GSourceFunc)
+														gtk_xtext_scrolldown_timeout,
+														xtext);
+		xtext->select_start_y -= (adj->value - xtext->select_start_adj) * xtext->fontsize;
+		xtext->select_start_adj = adj->value;
+		gtk_xtext_selection_draw (xtext, NULL, TRUE);
+		gtk_xtext_render_ents (xtext, ent, buf->last_ent_end);
+	}
+	else
+	{
+		xtext->scroll_tag = 0;
 	}
 
-	xtext->scroll_tag = 0;
 	return 0;
 }
 
@@ -1778,18 +1828,35 @@ static gint
 gtk_xtext_scrollup_timeout (GtkXText * xtext)
 {
 	int p_y;
+	xtext_buffer *buf = xtext->buffer;
+	GtkAdjustment *adj = xtext->adj;
+	textentry *ent;
 
 	gdk_window_get_pointer (GTK_WIDGET (xtext)->window, 0, &p_y, 0);
 
-	if (p_y < 0 && xtext->adj->value > 0.0)
+	if (p_y < 0 && adj->value >= 0)
 	{
-		xtext->adj->value--;
-		gtk_adjustment_changed (xtext->adj);
-		gtk_xtext_render_page (xtext);
-		return 1;
+		buf->scrollbar_down = FALSE;
+		ent = buf->last_ent_start->prev;
+		if (ent)
+		{
+			adj->value -= ent->lines_taken;
+			gtk_adjustment_value_changed (adj);
+		}
+		xtext->select_start_y -= (adj->value - xtext->select_start_adj) * xtext->fontsize;
+		xtext->select_start_adj = adj->value;
+		gtk_xtext_selection_draw (xtext, NULL, TRUE);
+		gtk_xtext_render_ents (xtext, ent, buf->last_ent_end);
+		xtext->scroll_tag = g_timeout_add (gtk_xtext_timeout_ms (xtext, p_y),
+														(GSourceFunc)
+														gtk_xtext_scrollup_timeout,
+														xtext);
+	}
+	else
+	{
+		xtext->scroll_tag = 0;
 	}
 
-	xtext->scroll_tag = 0;
 	return 0;
 }
 
@@ -1799,35 +1866,32 @@ gtk_xtext_selection_update (GtkXText * xtext, GdkEventMotion * event, int p_y, g
 	int win_height;
 	int moved;
 
+	if (xtext->scroll_tag)
+	{
+		return;
+	}
+
 	gdk_drawable_get_size (GTK_WIDGET (xtext)->window, 0, &win_height);
 
 	/* selecting past top of window, scroll up! */
 	if (p_y < 0 && xtext->adj->value >= 0)
 	{
-		if (!xtext->scroll_tag)
-			xtext->scroll_tag = g_timeout_add (100,
-															(GSourceFunc)
-														 	gtk_xtext_scrollup_timeout,
-															xtext);
-		return;
+		gtk_xtext_scrollup_timeout (xtext);
 	}
 
 	/* selecting past bottom of window, scroll down! */
-	if (p_y > win_height &&
+	else if (p_y > win_height &&
 		 xtext->adj->value < (xtext->adj->upper - xtext->adj->page_size))
 	{
-		if (!xtext->scroll_tag)
-			xtext->scroll_tag = g_timeout_add (100,
-															(GSourceFunc)
-															gtk_xtext_scrolldown_timeout,
-															xtext);
-		return;
+		gtk_xtext_scrolldown_timeout (xtext);
+	}
+	else
+	{
+		moved = (int)xtext->adj->value - xtext->select_start_adj;
+		xtext->select_start_y -= (moved * xtext->fontsize);
+		xtext->select_start_adj = xtext->adj->value;
+		gtk_xtext_selection_draw (xtext, event, render);
 	}
-
-	moved = (int)xtext->adj->value - xtext->select_start_adj;
-	xtext->select_start_y -= (moved * xtext->fontsize);
-	xtext->select_start_adj = xtext->adj->value;
-	gtk_xtext_selection_draw (xtext, event, render);
 }
 
 static char *
@@ -1883,7 +1947,7 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
 	if (ret_len)
 		*ret_len = str - word;
 
-	return gtk_xtext_strip_color (word, len, xtext->scratch_buffer, NULL, NULL, FALSE);
+	return gtk_xtext_strip_color (word, len, xtext->scratch_buffer, NULL, NULL, NULL, FALSE);
 }
 
 #ifdef MOTION_MONITOR
@@ -1941,7 +2005,7 @@ gtk_xtext_check_mark_stamp (GtkXText *xtext, GdkModifierType mask)
 {
 	gboolean redraw = FALSE;
 
-	if ((mask & GDK_SHIFT_MASK))
+	if (mask & GDK_SHIFT_MASK || prefs.autocopy_stamp)
 	{
 		if (!xtext->mark_stamp)
 		{
@@ -2106,7 +2170,16 @@ gtk_xtext_set_clip_owner (GtkWidget * xtext, GdkEventButton * event)
 		free (str);
 	}
 
-	gtk_selection_owner_set (xtext, GDK_SELECTION_PRIMARY, event->time);
+	if (event)
+	{
+		gtk_selection_owner_set (xtext, GDK_SELECTION_PRIMARY, event->time);
+	}
+}
+
+void
+gtk_xtext_copy_selection (GtkXText *xtext)
+{
+	gtk_xtext_set_clip_owner (xtext, NULL);
 }
 
 static void
@@ -2174,6 +2247,11 @@ gtk_xtext_button_release (GtkWidget * widget, GdkEventButton * event)
 	if (event->button == 1)
 	{
 		xtext->button_down = FALSE;
+		if (xtext->scroll_tag)
+		{
+			g_source_remove (xtext->scroll_tag);
+			xtext->scroll_tag = 0;
+		}
 
 		gtk_grab_remove (widget);
 		/*gdk_pointer_ungrab (0);*/
@@ -2182,9 +2260,12 @@ gtk_xtext_button_release (GtkWidget * widget, GdkEventButton * event)
 		if (xtext->buffer->last_ent_start)
 		{
 			xtext->color_paste = FALSE;
-			if (event->state & GDK_CONTROL_MASK)
+			if (event->state & GDK_CONTROL_MASK || prefs.autocopy_color)
 				xtext->color_paste = TRUE;
-			gtk_xtext_set_clip_owner (GTK_WIDGET (xtext), event);
+			if (prefs.autocopy_text)
+			{
+				gtk_xtext_set_clip_owner (GTK_WIDGET (xtext), event);
+			}
 		}
 
 		if (xtext->select_start_x == event->x &&
@@ -2249,7 +2330,10 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event)
 			ent->mark_end = offset + len;
 			gtk_xtext_selection_render (xtext, ent, offset, ent, offset + len);
 			xtext->word_or_line_select = TRUE;
-			gtk_xtext_set_clip_owner (GTK_WIDGET (xtext), event);
+			if (prefs.autocopy_text)
+			{
+				gtk_xtext_set_clip_owner (GTK_WIDGET (xtext), event);
+			}
 		}
 
 		return FALSE;
@@ -2265,7 +2349,10 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event)
 			ent->mark_end = ent->str_len;
 			gtk_xtext_selection_render (xtext, ent, 0, ent, ent->str_len);
 			xtext->word_or_line_select = TRUE;
-			gtk_xtext_set_clip_owner (GTK_WIDGET (xtext), event);
+			if (prefs.autocopy_text)
+			{
+				gtk_xtext_set_clip_owner (GTK_WIDGET (xtext), event);
+			}
 		}
 
 		return FALSE;
@@ -2391,7 +2478,7 @@ gtk_xtext_selection_get_text (GtkXText *xtext, int *len_ret)
 		len = strlen (txt);
 	} else
 	{
-		stripped = gtk_xtext_strip_color (txt, strlen (txt), NULL, &len, 0, FALSE);
+		stripped = gtk_xtext_strip_color (txt, strlen (txt), NULL, &len, NULL, NULL, FALSE);
 		free (txt);
 	}
 
@@ -2431,12 +2518,14 @@ gtk_xtext_selection_get (GtkWidget * widget,
 
 #if (GTK_MAJOR_VERSION == 2) && (GTK_MINOR_VERSION == 0)
 			gdk_string_to_compound_text (
+												stripped, &encoding, &format, &new_text,
+												&new_length);
 #else
 			gdk_string_to_compound_text_for_display (
 												gdk_drawable_get_display (widget->window),
-#endif
 												stripped, &encoding, &format, &new_text,
 												&new_length);
+#endif
 			gtk_selection_data_set (selection_data_ptr, encoding, format,
 											new_text, new_length);
 			gdk_free_compound_text (new_text);
@@ -2551,19 +2640,26 @@ gtk_xtext_get_type (void)
 
 static unsigned char *
 gtk_xtext_strip_color (unsigned char *text, int len, unsigned char *outbuf,
-							  int *newlen, int *mb_ret, int strip_hidden)
+							  int *newlen, int *mb_ret, GSList **slp, int strip_hidden)
 {
 	int i = 0;
 	int rcol = 0, bgcol = 0;
 	int hidden = FALSE;
 	unsigned char *new_str;
 	int mb = FALSE;
+	GSList *sl = NULL;
+	unsigned char *text0 = text;
+	int off1, len1;
+	offlen_t data;
 
 	if (outbuf == NULL)
 		new_str = malloc (len + 2);
 	else
 		new_str = outbuf;
 
+	off1 = 0;
+	len1 = 0;
+	data.u = 0;
 	while (len > 0)
 	{
 		if (*text >= 128)
@@ -2597,12 +2693,32 @@ gtk_xtext_strip_color (unsigned char *text, int len, unsigned char *outbuf,
 				break;
 			default:
 				if (!(hidden && strip_hidden))
+				{
+					if (text - text0 - off1 != len1)
+					{
+						if (len1)
+						{
+							data.o.off = off1;
+							data.o.len = len1;
+							sl = g_slist_append (sl, GUINT_TO_POINTER (data.u));
+							len1 = 0;
+						}
+						off1 = text - text0;
+					}
+					len1++;
 					new_str[i++] = *text;
+				}
 			}
 		}
 		text++;
 		len--;
 	}
+	if (len1)
+	{
+		data.o.off = off1;
+		data.o.len = len1;
+		sl = g_slist_append (sl, GUINT_TO_POINTER (data.u));
+	}
 
 	new_str[i] = 0;
 
@@ -2612,9 +2728,15 @@ gtk_xtext_strip_color (unsigned char *text, int len, unsigned char *outbuf,
 	if (mb_ret != NULL)
 		*mb_ret = mb;
 
+	if (slp)
+		*slp = sl;
+	else
+		g_slist_free (sl);
+
 	return new_str;
 }
 
+
 /* GeEkMaN: converts mIRC control codes to literal control codes */
 
 static char *
@@ -2718,7 +2840,7 @@ gtk_xtext_text_width (GtkXText *xtext, unsigned char *text, int len,
 	int new_len, mb;
 
 	new_buf = gtk_xtext_strip_color (text, len, xtext->scratch_buffer,
-												&new_len, &mb, !xtext->ignore_hidden);
+												&new_len, &mb, NULL, !xtext->ignore_hidden);
 
 	if (mb_ret)
 		*mb_ret = mb;
@@ -2884,6 +3006,63 @@ gtk_xtext_reset (GtkXText * xtext, int mark, int attribs)
 	xtext->nc = 0;
 }
 
+/*
+ * gtk_xtext_search_offset (buf, ent, off) --
+ * Look for arg offset in arg textentry
+ * Return one or more flags:
+ * 	GTK_MATCH_MID if we are in a match
+ * 	GTK_MATCH_START if we're at the first byte of it
+ * 	GTK_MATCH_END if we're at the first byte past it
+ * 	GTK_MATCH_CUR if it is the current match
+ */
+#define GTK_MATCH_START	1
+#define GTK_MATCH_MID	2
+#define GTK_MATCH_END	4
+#define GTK_MATCH_CUR	8
+static int
+gtk_xtext_search_offset (xtext_buffer *buf, textentry *ent, unsigned int off)
+{
+	GList *gl;
+	offsets_t o;
+	int flags = 0;
+
+	for (gl = g_list_first (ent->marks); gl; gl = g_list_next (gl))
+	{
+		o.u = GPOINTER_TO_UINT (gl->data);
+		if (off < o.o.start || off > o.o.end)
+			continue;
+		flags = GTK_MATCH_MID;
+		if (off == o.o.start)
+			flags |= GTK_MATCH_START;
+		if (off == o.o.end)
+		{
+			gl = g_list_next (gl);
+			if (gl)
+			{
+				o.u = GPOINTER_TO_UINT (gl->data);
+				if (off ==  o.o.start)	/* If subseq match is adjacent */
+				{
+					flags |= (gl == buf->curmark)? GTK_MATCH_CUR: 0;
+				}
+				else		/* If subseq match is not adjacent */
+				{
+					flags |= GTK_MATCH_END;
+				}
+			}
+			else		/* If there is no subseq match */
+			{
+				flags |= GTK_MATCH_END;
+			}
+		}
+		else if (gl == buf->curmark)	/* If not yet at the end of this match */
+		{
+			flags |= GTK_MATCH_CUR;
+		}
+		break;
+	}
+	return flags;
+}
+
 /* render a single line, which WONT wrap, and parse mIRC colors */
 
 static int
@@ -2898,6 +3077,9 @@ gtk_xtext_render_str (GtkXText * xtext, int y, textentry * ent,
 	int offset;
 	int mark = FALSE;
 	int ret = 1;
+	int k;
+	int srch_underline = FALSE;
+	int srch_mark = FALSE;
 
 	xtext->in_hilight = FALSE;
 
@@ -3049,6 +3231,50 @@ gtk_xtext_render_str (GtkXText * xtext, int y, textentry * ent,
 				}
 			}
 
+			if (!left_only && !mark &&
+				 (k = gtk_xtext_search_offset (xtext->buffer, ent, offset + i)))
+			{
+				x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc, ent->mb);
+				pstr += j;
+				j = 0;
+				if (!(xtext->buffer->search_flags & highlight))
+				{
+					if (k & GTK_MATCH_CUR)
+					{
+						xtext_set_bg (xtext, gc, XTEXT_MARK_BG);
+						xtext_set_fg (xtext, gc, XTEXT_MARK_FG);
+						xtext->backcolor = TRUE;
+						srch_mark = TRUE;
+					} else
+					{
+						xtext_set_bg (xtext, gc, xtext->col_back);
+						xtext_set_fg (xtext, gc, xtext->col_fore);
+						xtext->backcolor = (xtext->col_back != XTEXT_BG)? TRUE: FALSE;
+						srch_mark = FALSE;
+					}
+				}
+				else
+				{
+					xtext->underline = (k & GTK_MATCH_CUR)? TRUE: FALSE;
+					if (k & (GTK_MATCH_START | GTK_MATCH_MID))
+					{
+						xtext_set_bg (xtext, gc, XTEXT_MARK_BG);
+						xtext_set_fg (xtext, gc, XTEXT_MARK_FG);
+						xtext->backcolor = TRUE;
+						srch_mark = TRUE;
+					}
+					if (k & GTK_MATCH_END)
+					{
+						xtext_set_bg (xtext, gc, xtext->col_back);
+						xtext_set_fg (xtext, gc, xtext->col_fore);
+						xtext->backcolor = (xtext->col_back != XTEXT_BG)? TRUE: FALSE;
+						srch_mark = FALSE;
+						xtext->underline = FALSE;
+					}
+					srch_underline = xtext->underline;
+				}
+			}
+
 			switch (str[i])
 			{
 			case '\n':
@@ -3198,6 +3424,11 @@ gtk_xtext_render_str (GtkXText * xtext, int y, textentry * ent,
 			xtext_set_bg (xtext, gc, XTEXT_MARK_BG);
 			xtext_set_fg (xtext, gc, XTEXT_MARK_FG);
 			xtext->backcolor = TRUE;
+			if (srch_underline)
+			{
+				xtext->underline = FALSE;
+				srch_underline = FALSE;
+			}
 			mark = TRUE;
 		}
 
@@ -3220,7 +3451,7 @@ gtk_xtext_render_str (GtkXText * xtext, int y, textentry * ent,
 	if (j)
 		x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc, ent->mb);
 
-	if (mark)
+	if (mark || srch_mark)
 	{
 		xtext_set_bg (xtext, gc, xtext->col_back);
 		xtext_set_fg (xtext, gc, xtext->col_fore);
@@ -3836,7 +4067,7 @@ gtk_xtext_load_trans (GtkXText * xtext)
 	PaintDesktop (hdc);
 	ReleaseDC (hwnd, hdc);
 
-	gdk_window_get_size (GTK_WIDGET (xtext)->window, &width, &height);
+	gdk_drawable_get_size (GTK_WIDGET (xtext)->window, &width, &height);
 	img = gdk_image_get (GTK_WIDGET (xtext)->window, 0, 0, width+128, height);
 	xtext->pixmap = win32_tint (xtext, img, img->width, img->height);
 
@@ -4388,7 +4619,7 @@ gtk_xtext_save (GtkXText * xtext, int fh)
 	while (ent)
 	{
 		buf = gtk_xtext_strip_color (ent->str, ent->str_len, NULL,
-											  &newlen, NULL, FALSE);
+											  &newlen, NULL, NULL, FALSE);
 		write (fh, buf, newlen);
 		write (fh, "\n", 1);
 		free (buf);
@@ -4775,6 +5006,11 @@ gtk_xtext_kill_ent (xtext_buffer *buffer, textentry *ent)
 
 	if (buffer->marker_pos == ent) buffer->marker_pos = NULL;
 
+	if (ent->marks)
+	{
+		gtk_xtext_search_textentry_del (buffer, ent);
+	}
+
 	free (ent);
 	return visible;
 }
@@ -4839,7 +5075,23 @@ gtk_xtext_remove_bottom (xtext_buffer *buffer)
 	else
 		buffer->text_first = NULL;
 
-	gtk_xtext_kill_ent (buffer, ent);
+	if (gtk_xtext_kill_ent (buffer, ent))
+	{
+		if (!buffer->xtext->add_io_tag)
+		{
+			/* remove scrolling events */
+			if (buffer->xtext->io_tag)
+			{
+				g_source_remove (buffer->xtext->io_tag);
+				buffer->xtext->io_tag = 0;
+			}
+			buffer->xtext->force_render = TRUE;
+			buffer->xtext->add_io_tag = g_timeout_add (REFRESH_TIMEOUT * 2,
+														(GSourceFunc)
+														gtk_xtext_render_page_timeout,
+														buffer->xtext);
+		}
+	}
 }
 
 /* If lines=0 => clear all */
@@ -4874,6 +5126,8 @@ gtk_xtext_clear (xtext_buffer *buf, int lines)
 	else
 	{
 		/* delete all */
+		if (buf->search_found)
+			gtk_xtext_search_fini (buf);
 		if (buf->xtext->auto_indent)
 			buf->indent = MARGIN;
 		buf->scrollbar_down = TRUE;
@@ -4905,21 +5159,37 @@ static gboolean
 gtk_xtext_check_ent_visibility (GtkXText * xtext, textentry *find_ent, int add)
 {
 	textentry *ent;
-	int lines_max;
-	int line = 0;
+	int lines;
+	xtext_buffer *buf = xtext->buffer;
 	int width;
 	int height;
 
-	gdk_drawable_get_size (GTK_WIDGET (xtext)->window, &width, &height);
+	if (find_ent == NULL)
+	{
+		return FALSE;
+	}
 
-	lines_max = ((height + xtext->pixel_offset) / xtext->fontsize) + add;
-	ent = xtext->buffer->pagetop_ent;
+	gdk_drawable_get_size (GTK_WIDGET (xtext)->window, &width, &height);
 
-	while (ent && line < lines_max)
+	ent = buf->pagetop_ent;
+	/* If top line not completely displayed return FALSE */
+	if (ent == find_ent && buf->pagetop_subline > 0)
 	{
-		if (find_ent == ent)
+		return FALSE;
+	}
+	/* Loop through line positions looking for find_ent */
+	lines = ((height + xtext->pixel_offset) / xtext->fontsize) + buf->pagetop_subline + add;
+	while (ent)	
+	{
+		lines -= ent->lines_taken;
+		if (lines <= 0)
+		{
+			return FALSE;
+		}
+		if (ent == find_ent)
+		{
 			return TRUE;
-		line += ent->lines_taken;
+		}
 		ent = ent->next;
 	}
 
@@ -4933,90 +5203,369 @@ gtk_xtext_check_marker_visibility (GtkXText * xtext)
 		xtext->buffer->marker_seen = TRUE;
 }
 
-textentry *
-gtk_xtext_search (GtkXText * xtext, const gchar *text, textentry *start, gboolean case_match, gboolean backward)
+static void
+gtk_xtext_unstrip_color (gint start, gint end, GSList *slp, GList **gl, gint maxo)
 {
-	textentry *ent, *fent;
-	int line;
-	gchar *str, *nee, *hay;	/* needle in haystack */
-
-	gtk_xtext_selection_clear_full (xtext->buffer);
-	xtext->buffer->last_ent_start = NULL;
-	xtext->buffer->last_ent_end = NULL;
+	gint off1, off2, curlen;
+	GSList *cursl;
+	offsets_t marks;
 
-	/* set up text comparand for Case Match or Ignore */
-	if (case_match)
-		nee = g_strdup (text);
-	else
-		nee = g_utf8_casefold (text, strlen (text));
+	off1 = 0;
+	curlen = 0;
+	cursl = slp;
+	while (cursl)
+	{
+		offlen_t ol;
+		ol.u = GPOINTER_TO_UINT(cursl->data);
+		if (start < ol.o.len)
+		{
+			off1 = ol.o.off + start;
+			break;
+		}
+		curlen += ol.o.len;
+		start -= ol.o.len;
+		end -= ol.o.len;
+		cursl = g_slist_next (cursl);
+	}
 
-	/* Validate that start gives a currently valid ent pointer */
-	ent = xtext->buffer->text_first;
-	while (ent)
+	off2 = off1;
+	while (cursl)
 	{
-		if (ent == start)
+		offlen_t ol;
+		ol.u = GPOINTER_TO_UINT(cursl->data);
+		if (end < ol.o.len)
+		{
+			off2 = ol.o.off + end;
 			break;
-		ent = ent->next;
+		}
+		curlen += ol.o.len;
+		end -= ol.o.len;
+		cursl = g_slist_next (cursl);
+	}
+	if (!cursl)
+	{
+		off2 = maxo;
 	}
-	if (!ent)
-		start = NULL;
 
-	/* Choose first ent to look at */
-	if (start)
-		ent = backward? start->prev: start->next;
-	else
-		ent = backward? xtext->buffer->text_last: xtext->buffer->text_first;
+	marks.o.start = off1;
+	marks.o.end = off2;
+	*gl = g_list_append (*gl, GUINT_TO_POINTER (marks.u));
+}
 
-	/* Search from there to one end or the other until found */
-	while (ent)
+/* Search a single textentry for occurrence(s) of search arg string */
+static void
+gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent, int pre)
+{
+	gchar *str;								/* text string to be searched */
+	GList *gl = NULL;
+	GSList *slp;
+	gint lstr;
+
+	if (buf->search_text == NULL)
 	{
-		/* If Case Ignore, fold before & free after calling strstr */
-		if (case_match)
-			hay = g_strdup (ent->str);
-		else
-			hay = g_utf8_casefold (ent->str, strlen (ent->str));
-		/* Try to find the needle in this haystack */
-		str = g_strstr_len (hay, strlen (hay), nee);
+		return;
+	}
+
+	str = gtk_xtext_strip_color (ent->str, ent->str_len, buf->xtext->scratch_buffer,
+										  &lstr, NULL, &slp, !buf->xtext->ignore_hidden);
+
+	/* Regular-expression matching --- */
+	if (buf->search_flags & regexp)
+	{
+		GMatchInfo *gmi;
+		gint start, end;
+
+		if (buf->search_re == NULL)
+		{
+			return;
+		}
+		g_regex_match (buf->search_re, str, 0, &gmi);
+		while (g_match_info_matches (gmi))
+		{
+			g_match_info_fetch_pos (gmi, 0,  &start, &end);
+			gtk_xtext_unstrip_color (start, end, slp, &gl, ent->str_len);
+			g_match_info_next (gmi, NULL);
+		}
+		g_match_info_free (gmi);
+
+	/* Non-regular-expression matching --- */
+	} else {
+		gchar *hay, *pos;
+		gint lhay, off, len;
+		gint match = buf->search_flags & case_match;
+
+		hay = match? g_strdup (str): g_utf8_casefold (str, lstr);
+		lhay = strlen (hay);
+		off = 0;
+
+		for (pos = hay, len = lhay; len;
+			  off += buf->search_lnee, pos = hay + off, len = lhay - off)
+		{
+			str = g_strstr_len (pos, len, buf->search_nee);
+			if (str == NULL)
+			{
+				break;
+			}
+			off = str - hay;
+			gtk_xtext_unstrip_color (off, off + buf->search_lnee,
+											 slp, &gl, ent->str_len);
+		}
+
 		g_free (hay);
-		if (str)
-			break;
-		ent = backward? ent->prev: ent->next;
 	}
-	fent = ent;
 
-	/* Save distance to start, end of found string */
-	if (ent)
+	/* Common processing --- */
+	g_slist_free (slp);
+	ent->marks = gl;
+	if (gl)
+	{
+		buf->search_found = (pre? g_list_prepend: g_list_append) (buf->search_found, ent);
+		if (pre == FALSE && buf->hintsearch == NULL)
+		{
+			buf->hintsearch = ent;
+		}
+	}
+	return;
+}
+
+/* Free all search information for a textentry */
+static void
+gtk_xtext_search_textentry_del (xtext_buffer *buf, textentry *ent)
+{
+	g_list_free (ent->marks);
+	ent->marks = NULL;
+	if (buf->cursearch && buf->cursearch->data == ent)
+	{
+		buf->cursearch = NULL;
+		buf->curmark = NULL;
+	}
+	if (buf->pagetop_ent == ent)
+	{
+		buf->pagetop_ent = NULL;
+	}
+	if (buf->hintsearch == ent)
+	{
+		buf->hintsearch = NULL;
+	}
+	buf->search_found = g_list_remove (buf->search_found, ent);
+}
+
+/* Used only by glist_foreach */
+static void
+gtk_xtext_search_textentry_fini (gpointer entp, gpointer dummy)
+{
+	textentry *ent = entp;
+
+	g_list_free (ent->marks);
+	ent->marks = NULL;
+}
+
+/* Free all search information for all textentrys and the xtext_buffer */
+static void
+gtk_xtext_search_fini (xtext_buffer *buf)
+{
+	g_list_foreach (buf->search_found, gtk_xtext_search_textentry_fini, 0);
+	g_list_free (buf->search_found);
+	buf->search_found = NULL;
+	g_free (buf->search_text);
+	buf->search_text = NULL;
+	g_free (buf->search_nee);
+	buf->search_nee = NULL;
+	buf->search_flags = 0;
+	buf->cursearch = NULL;
+	buf->curmark = NULL;
+	if (buf->search_re)
+	{
+		g_regex_unref (buf->search_re);
+		buf->search_re = NULL;
+	}
+}
+
+/* Returns TRUE if the base search information exists and is still okay to use */
+static gboolean
+gtk_xtext_search_init (xtext_buffer *buf, const gchar *text, gtk_xtext_search_flags flags, GError **perr)
+{
+	/* Of the five flags, backward and highlight_all do not need a new search */
+	if (buf->search_found &&
+		 strcmp (buf->search_text, text) == 0 &&
+		 (buf->search_flags & case_match) == (flags & case_match) &&
+		 (buf->search_flags & follow) == (flags & follow) &&
+		 (buf->search_flags & regexp) == (flags & regexp))
+	{
+		return TRUE;
+	}
+	buf->hintsearch = buf->cursearch? buf->cursearch->data: NULL;
+	gtk_xtext_search_fini (buf);
+	buf->search_text = g_strdup (text);
+	if (flags & regexp)
+	{
+		buf->search_re = g_regex_new (text, (flags & case_match)? 0: G_REGEX_CASELESS, 0, perr);
+		if (perr && *perr)
+		{
+			return FALSE;
+		}
+	}
+	else
+	{
+		if (flags & case_match)
+		{
+			buf->search_nee = g_strdup (text);
+		}
+		else
+		{
+			buf->search_nee = g_utf8_casefold (text, strlen (text));
+		}
+		buf->search_lnee = strlen (buf->search_nee);
+	}
+	buf->search_flags = flags;
+	buf->cursearch = NULL;
+	buf->curmark = NULL;
+	return FALSE;
+}
+
+#define BACKWARD (flags & backward)
+#define FIRSTLAST(lp)  (BACKWARD? g_list_last(lp): g_list_first(lp))
+#define NEXTPREVIOUS(lp) (BACKWARD? g_list_previous(lp): g_list_next(lp))
+textentry *
+gtk_xtext_search (GtkXText * xtext, const gchar *text, gtk_xtext_search_flags flags, GError **perr)
+{
+	textentry *ent = NULL;
+	xtext_buffer *buf = xtext->buffer;
+	GList *gl;
+
+	if (buf->text_first == NULL)
 	{
-		ent->mark_start = str - hay;
-		ent->mark_end = ent->mark_start + strlen (nee);
+		return NULL;
+	}
 
-		/* is the match visible? Might need to scroll */
-		if (!gtk_xtext_check_ent_visibility (xtext, ent, 0))
+	/* If the text arg is NULL, one of these has been toggled: highlight follow */
+	if (text == NULL)		/* Here on highlight or follow toggle */
+	{
+		gint oldfollow = buf->search_flags & follow;
+		gint newfollow = flags & follow;
+
+		/* If "Follow" has just been checked, search possible new textentries --- */
+		if (newfollow && (newfollow != oldfollow))
 		{
-			ent = xtext->buffer->text_first;
-			line = 0;
-			while (ent)
+			gl = g_list_last (buf->search_found);
+			ent = gl? gl->data: buf->text_first;
+			for (; ent; ent = ent->next)
 			{
-				line += ent->lines_taken;
-				ent = ent->next;
-				if (ent == fent)
-					break;
+				gtk_xtext_search_textentry (buf, ent, FALSE);
+			}
+		}
+		buf->search_flags = flags;
+		ent = buf->pagetop_ent;
+	}
+
+	/* if the text arg is "", the reset button has been clicked or Control-Shift-F has been hit */
+	else if (text[0] == 0)		/* Let a null string do a reset. */
+	{
+		gtk_xtext_search_fini (buf);
+	}
+
+	/* If the text arg is neither NULL nor "", it's the search string */
+	else
+	{
+		if (gtk_xtext_search_init (buf, text, flags, perr) == FALSE)	/* If a new search: */
+		{
+			if (perr && *perr)
+			{
+				return NULL;
+			}
+			for (ent = buf->text_first; ent; ent = ent->next)
+			{
+				gtk_xtext_search_textentry (buf, ent, TRUE);
+			}
+			buf->search_found = g_list_reverse (buf->search_found);
+		}
+
+		/* Now base search results are in place. */
+
+		if (buf->search_found)
+		{
+			/* If we're in the midst of moving among found items */
+			if (buf->cursearch)
+			{
+				ent = buf->cursearch->data;
+				buf->curmark = NEXTPREVIOUS (buf->curmark);
+				if (buf->curmark == NULL)
+				{
+					/* We've returned all the matches for this textentry. */
+					buf->cursearch = NEXTPREVIOUS (buf->cursearch);
+					if (buf->cursearch)
+					{
+						ent = buf->cursearch->data;
+						buf->curmark = FIRSTLAST (ent->marks);
+					}
+					else	/* We've returned all the matches for all textentries */
+					{
+						ent = NULL;
+					}
+				}
+			}
+#if 0
+			/* If user changed the search, let's look starting where he was */
+			else if (buf->hintsearch)
+			{
+				for (ent = buf->hintsearch; ent; ent = BACKWARD? ent->prev: ent->next)
+					if (ent->marks)
+						break;
+				if (ent == NULL)
+					for (ent = buf->hintsearch; ent; ent = BACKWARD? ent->next: ent->prev)
+						if (ent->marks)
+							break;
+				if (ent)
+				{
+					buf->cursearch = g_list_find (buf->search_found, ent);
+					buf->curmark = FIRSTLAST (ent->marks);
+				}
+			}
+#endif
+			/* This is a fresh search */
+			else
+			{
+				buf->cursearch = FIRSTLAST (buf->search_found);
+				ent = buf->cursearch->data;
+				buf->curmark = FIRSTLAST (ent->marks);
 			}
-			while (line > xtext->adj->upper - xtext->adj->page_size)
-				line--;
-			if (backward)
-				line -= xtext->adj->page_size - ent->lines_taken;
-			xtext->adj->value = line;
-			xtext->buffer->scrollbar_down = FALSE;
-			gtk_adjustment_changed (xtext->adj);
 		}
 	}
+	buf->hintsearch = ent;
+
+	if (!gtk_xtext_check_ent_visibility (xtext, ent, 1))
+	{
+		GtkAdjustment *adj = xtext->adj;
+		float value;
+
+		buf->pagetop_ent = NULL;
+		for (value = 0, ent = buf->text_first;
+			  ent && ent != buf->hintsearch; ent = ent->next)
+		{
+			value += ent->lines_taken;
+		}
+		if (value > adj->upper - adj->page_size)
+		{
+			value = adj->upper - adj->page_size;
+		}
+		else if ((flags & backward)  && ent)
+		{
+			value -= adj->page_size - ent->lines_taken;
+			if (value < 0)
+			{
+				value = 0;
+			}
+		}
+		gtk_adjustment_set_value (adj, value);
+	}
 
-	g_free (nee);
 	gtk_widget_queue_draw (GTK_WIDGET (xtext));
 
-	return fent;
+	return buf->hintsearch;
 }
+#undef BACKWARD
+#undef FIRSTLAST
+#undef NEXTPREVIOUS
 
 static int
 gtk_xtext_render_page_timeout (GtkXText * xtext)
@@ -5079,6 +5628,7 @@ gtk_xtext_append_entry (xtext_buffer *buf, textentry * ent, time_t stamp)
 	ent->mark_start = -1;
 	ent->mark_end = -1;
 	ent->next = NULL;
+	ent->marks = NULL;
 
 	if (ent->indent < MARGIN)
 		ent->indent = MARGIN;	  /* 2 pixels is the left margin */
@@ -5097,10 +5647,11 @@ gtk_xtext_append_entry (xtext_buffer *buf, textentry * ent, time_t stamp)
 	if (buf->reset_marker_pos || 
 		((buf->marker_pos == NULL || buf->marker_seen) && (buf->xtext->buffer != buf || 
 #if GTK_CHECK_VERSION(2,4,0)
-		!gtk_window_has_toplevel_focus (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (buf->xtext)))))))
+		!gtk_window_has_toplevel_focus (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (buf->xtext))))
 #else
-		!(GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (buf->xtext))))->has_focus)))
+		!(GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (buf->xtext))))->has_focus
 #endif
+	   )))
 	{
 		buf->marker_pos = ent;
 		dontscroll (buf); /* force scrolling off */
@@ -5140,6 +5691,10 @@ gtk_xtext_append_entry (xtext_buffer *buf, textentry * ent, time_t stamp)
 		if (buf->old_value < 0)
 			buf->old_value = 0;
 	}
+	if (buf->search_flags & follow)
+	{
+		gtk_xtext_search_textentry (buf, ent, FALSE);
+	}
 }
 
 /* the main two public functions */
@@ -5466,6 +6021,11 @@ gtk_xtext_buffer_free (xtext_buffer *buf)
 	if (buf->xtext->selection_buffer == buf)
 		buf->xtext->selection_buffer = NULL;
 
+	if (buf->search_found)
+	{
+		gtk_xtext_search_fini (buf);
+	}
+
 	ent = buf->text_first;
 	while (ent)
 	{
diff --git a/src/fe-gtk/xtext.h b/src/fe-gtk/xtext.h
index a37ddc32..6c126346 100644
--- a/src/fe-gtk/xtext.h
+++ b/src/fe-gtk/xtext.h
@@ -43,6 +43,13 @@
 typedef struct _GtkXText GtkXText;
 typedef struct _GtkXTextClass GtkXTextClass;
 typedef struct textentry textentry;
+typedef enum gtk_xtext_search_flags_e {
+	case_match = 1,
+	backward = 2,
+	highlight = 4,
+	follow = 8,
+	regexp = 16
+} gtk_xtext_search_flags;
 
 typedef struct {
 	GtkXText *xtext;					/* attached to this widget */
@@ -77,6 +84,16 @@ typedef struct {
 	unsigned int grid_dirty:1;
 	unsigned int marker_seen:1;
 	unsigned int reset_marker_pos:1;
+
+	GList *search_found;		/* list of textentries where search found strings */
+	gchar *search_text;		/* desired text to search for */
+	gchar *search_nee;		/* prepared needle to look in haystack for */
+	gint search_lnee;		/* its length */
+	gtk_xtext_search_flags search_flags;	/* match, bwd, highlight */
+	GList *cursearch;			/* GList whose 'data' pts to current textentry */
+	GList *curmark;			/* current item in ent->marks */
+	GRegex *search_re;		/* Compiled regular expression */
+	textentry *hintsearch;	/* textentry found for last search */
 } xtext_buffer;
 
 struct _GtkXText
@@ -247,7 +264,7 @@ void gtk_xtext_clear (xtext_buffer *buf, int lines);
 void gtk_xtext_save (GtkXText * xtext, int fh);
 void gtk_xtext_refresh (GtkXText * xtext, int do_trans);
 int gtk_xtext_lastlog (xtext_buffer *out, xtext_buffer *search_area, int (*cmp_func) (char *, void *userdata), void *userdata);
-textentry *gtk_xtext_search (GtkXText * xtext, const gchar *text, textentry *start, gboolean case_match, gboolean backward);
+textentry *gtk_xtext_search (GtkXText * xtext, const gchar *text, gtk_xtext_search_flags flags, GError **err);
 void gtk_xtext_reset_marker_pos (GtkXText *xtext);
 void gtk_xtext_check_marker_visibility(GtkXText *xtext);
 
@@ -270,6 +287,7 @@ void gtk_xtext_set_wordwrap (GtkXText *xtext, gboolean word_wrap);
 xtext_buffer *gtk_xtext_buffer_new (GtkXText *xtext);
 void gtk_xtext_buffer_free (xtext_buffer *buf);
 void gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render);
+void gtk_xtext_copy_selection (GtkXText *xtext);
 GType gtk_xtext_get_type (void);
 
 #endif
diff --git a/src/fe-text/fe-text.c b/src/fe-text/fe-text.c
index 2bc2e649..f3c1ff05 100644
--- a/src/fe-text/fe-text.c
+++ b/src/fe-text/fe-text.c
@@ -22,60 +22,51 @@
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
 #endif
+#ifdef WIN32
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#else
+#include <unistd.h>
 #include <sys/time.h>
+#endif
 #include <sys/types.h>
-#include <unistd.h>
 #include <ctype.h>
+#include <glib.h>
 #include "../common/xchat.h"
 #include "../common/xchatc.h"
+#include "../common/cfgfiles.h"
 #include "../common/outbound.h"
 #include "../common/util.h"
 #include "../common/fe.h"
 #include "fe-text.h"
 
 
-static GSList *tmr_list;		  /* timer list */
-static int tmr_list_count;
-static GSList *se_list;			  /* socket event list */
-static int se_list_count;
 static int done = FALSE;		  /* finished ? */
 
 
 static void
 send_command (char *cmd)
 {
-	handle_multiline (sess_list->data, cmd, TRUE, FALSE);
+	handle_multiline (current_tab, cmd, TRUE, FALSE);
 }
 
-static void
-read_stdin (void)
+static gboolean
+handle_line (GIOChannel *channel, GIOCondition cond, gpointer data)
 {
-	int len, i = 0;
-	static int pos = 0;
-	static char inbuf[1024];
-	char tmpbuf[512];
-
-	len = read (STDIN_FILENO, tmpbuf, sizeof tmpbuf - 1);
-
-	while (i < len)
-	{
-		switch (tmpbuf[i])
-		{
-		case '\r':
-			break;
 
-		case '\n':
-			inbuf[pos] = 0;
-			pos = 0;
-			send_command (inbuf);
-			break;
+	gchar *str_return;
+	gsize length, terminator_pos;
+	GError *error = NULL;
+	GIOStatus result;
 
-		default:
-			inbuf[pos] = tmpbuf[i];
-			if (pos < (sizeof inbuf - 2))
-				pos++;
-		}
-		i++;
+	result = g_io_channel_read_line(channel, &str_return, &length, &terminator_pos, &error);
+	if (result == G_IO_STATUS_ERROR) {
+		return FALSE;
+	}
+	else {
+		send_command(str_return);
+		g_free(str_return);
+		return TRUE;
 	}
 }
 
@@ -87,12 +78,13 @@ fe_new_window (struct session *sess, int focus)
 	char buf[512];
 
 	sess->gui = malloc (4);
+	current_sess = sess;
 
 	if (!sess->server->front_session)
 		sess->server->front_session = sess;
 	if (!sess->server->server_session)
 		sess->server->server_session = sess;
-	if (!current_tab)
+	if (!current_tab || focus)
 		current_tab = sess;
 
 	if (done_intro)
@@ -101,7 +93,7 @@ fe_new_window (struct session *sess, int focus)
 
 	snprintf (buf, sizeof (buf),
 				"\n"
-				" \017xchat \00310"PACKAGE_VERSION"\n"
+				" \017XChat-Text \00310"PACKAGE_VERSION"\n"
 				" \017Running on \00310%s \017glib \00310%d.%d.%d\n"
 				" \017This binary compiled \00310"__DATE__"\017\n",
 				get_cpu_str(),
@@ -133,15 +125,21 @@ get_stamp_str (time_t tim, char *dest, int size)
 }
 
 static int
-timecat (char *buf)
+timecat (char *buf, time_t stamp)
 {
 	char stampbuf[64];
 
-	get_stamp_str (time (0), stampbuf, sizeof (stampbuf));
+	/* set the stamp to the current time if not provided */
+	if (!stamp)
+		stamp = time (0);
+
+	get_stamp_str (stamp, stampbuf, sizeof (stampbuf));
 	strcat (buf, stampbuf);
 	return strlen (stampbuf);
 }
 
+/* Windows doesn't handle ANSI codes in cmd.exe, need to not display them */
+#ifndef WIN32
 /*                       0  1  2  3  4  5  6  7   8   9   10 11  12  13  14 15 */
 static const short colconv[] = { 0, 7, 4, 2, 1, 3, 5, 11, 13, 12, 6, 16, 14, 15, 10, 7 };
 
@@ -157,7 +155,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp)
 	if (prefs.timestamp)
 	{
 		newtext[0] = 0;
-		j += timecat (newtext);
+		j += timecat (newtext, stamp);
 	}
 	while (i < len)
 	{
@@ -165,7 +163,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp)
 		{
 			dotime = FALSE;
 			newtext[j] = 0;
-			j += timecat (newtext);
+			j += timecat (newtext, stamp);
 		}
 		switch (text[i])
 		{
@@ -179,8 +177,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp)
 				j++;
 				newtext[j] = 'm';
 				j++;
-				i--;
-				goto jump2;
+				goto endloop;
 			}
 			k = 0;
 			comma = FALSE;
@@ -226,13 +223,16 @@ fe_print_text (struct session *sess, char *text, time_t stamp)
 						comma = TRUE;
 						break;
 					default:
-						goto jump;
+						goto endloop;
 					}
 					k = 0;
 				}
 				i++;
 			}
 			break;
+		/* don't actually want hidden text */
+		case '\010':				  /* hidden */
+			break;
 		case '\026':				  /* REVERSE */
 			if (reverse)
 			{
@@ -296,120 +296,246 @@ fe_print_text (struct session *sess, char *text, time_t stamp)
 			newtext[j] = text[i];
 			j++;
 		}
-	 jump2:
 		i++;
-	 jump:
-		i += 0;
+		endloop:
+			;
 	}
+
+	/* make sure last character is a new line */
+	if (text[i-1] != '\n')
+		newtext[j++] = '\n';
+
 	newtext[j] = 0;
 	write (STDOUT_FILENO, newtext, j);
 	free (newtext);
 }
-
+#else
+/* The win32 version for cmd.exe */
 void
-fe_timeout_remove (int tag)
+fe_print_text (struct session *sess, char *text, time_t stamp)
 {
-	timerevent *te;
-	GSList *list;
+	int dotime = FALSE;
+	int comma, k, i = 0, j = 0, len = strlen (text);
+
+	unsigned char *newtext = malloc (len + 1024);
 
-	list = tmr_list;
-	while (list)
+	if (prefs.timestamp)
 	{
-		te = (timerevent *) list->data;
-		if (te->tag == tag)
+		newtext[0] = 0;
+		j += timecat (newtext, stamp);
+	}
+	while (i < len)
+	{
+		if (dotime && text[i] != 0)
 		{
-			tmr_list = g_slist_remove (tmr_list, te);
-			free (te);
-			return;
+			dotime = FALSE;
+			newtext[j] = 0;
+			j += timecat (newtext, stamp);
 		}
-		list = list->next;
+		switch (text[i])
+		{
+		case 3:
+			i++;
+			if (!isdigit (text[i]))
+			{
+				goto endloop;
+			}
+			k = 0;
+			comma = FALSE;
+			while (i < len)
+			{
+				if (text[i] >= '0' && text[i] <= '9' && k < 2)
+				{
+					k++;
+				} else
+				{
+					switch (text[i])
+					{
+					case ',':
+						comma = TRUE;
+						break;
+					default:
+						goto endloop;
+					}
+					k = 0;
+
+				}
+				i++;
+			}
+			break;
+		/* don't actually want hidden text */
+		case '\010':				  /* hidden */
+		case '\026':				  /* REVERSE */
+		case '\037':				  /* underline */
+		case '\002':				  /* bold */
+		case '\017':				  /* reset all */
+			break;
+		case '\007':
+			if (!prefs.filterbeep)
+			{
+				newtext[j] = text[i];
+				j++;
+			}
+			break;
+		case '\t':
+			newtext[j] = ' ';
+			j++;
+			break;
+		case '\n':
+			newtext[j] = '\r';
+			j++;
+			if (prefs.timestamp)
+				dotime = TRUE;
+		default:
+			newtext[j] = text[i];
+			j++;
+		}
+		i++;
+		endloop:
+			;
 	}
+
+	/* make sure last character is a new line */
+	if (text[i-1] != '\n')
+		newtext[j++] = '\n';
+
+	newtext[j] = 0;
+	write (STDOUT_FILENO, newtext, j);
+	free (newtext);
+}
+#endif
+
+void
+fe_timeout_remove (int tag)
+{
+	g_source_remove (tag);
 }
 
 int
 fe_timeout_add (int interval, void *callback, void *userdata)
 {
-	struct timeval now;
-	timerevent *te = malloc (sizeof (timerevent));
-
-	tmr_list_count++;				  /* this overflows at 2.2Billion, who cares!! */
-
-	te->tag = tmr_list_count;
-	te->interval = interval;
-	te->callback = callback;
-	te->userdata = userdata;
-
-	gettimeofday (&now, NULL);
-	te->next_call = now.tv_sec * 1000 + (now.tv_usec / 1000) + te->interval;
-
-	tmr_list = g_slist_prepend (tmr_list, te);
-
-	return te->tag;
+	return g_timeout_add (interval, (GSourceFunc) callback, userdata);
 }
 
 void
 fe_input_remove (int tag)
 {
-	socketevent *se;
-	GSList *list;
-
-	list = se_list;
-	while (list)
-	{
-		se = (socketevent *) list->data;
-		if (se->tag == tag)
-		{
-			se_list = g_slist_remove (se_list, se);
-			free (se);
-			return;
-		}
-		list = list->next;
-	}
+	g_source_remove (tag);
 }
 
 int
 fe_input_add (int sok, int flags, void *func, void *data)
 {
-	socketevent *se = malloc (sizeof (socketevent));
+	int tag, type = 0;
+	GIOChannel *channel;
 
-	se_list_count++;				  /* this overflows at 2.2Billion, who cares!! */
+	channel = g_io_channel_unix_new (sok);
 
-	se->tag = se_list_count;
-	se->sok = sok;
-	se->rread = flags & FIA_READ;
-	se->wwrite = flags & FIA_WRITE;
-	se->eexcept = flags & FIA_EX;
-	se->callback = func;
-	se->userdata = data;
-	se_list = g_slist_prepend (se_list, se);
+	if (flags & FIA_READ)
+		type |= G_IO_IN | G_IO_HUP | G_IO_ERR;
+	if (flags & FIA_WRITE)
+		type |= G_IO_OUT | G_IO_ERR;
+	if (flags & FIA_EX)
+		type |= G_IO_PRI;
 
-	return se->tag;
+	tag = g_io_add_watch (channel, type, (GIOFunc) func, data);
+	g_io_channel_unref (channel);
+
+	return tag;
 }
 
+/* === command-line parameter parsing : requires glib 2.6 === */
+
+static char *arg_cfgdir = NULL;
+static gint arg_show_autoload = 0;
+static gint arg_show_config = 0;
+static gint arg_show_version = 0;
+
+static const GOptionEntry gopt_entries[] = 
+{
+ {"no-auto",	'a', 0, G_OPTION_ARG_NONE,	&arg_dont_autoconnect, N_("Don't auto connect to servers"), NULL},
+ {"cfgdir",	'd', 0, G_OPTION_ARG_STRING,	&arg_cfgdir, N_("Use a different config directory"), "PATH"},
+ {"no-plugins",	'n', 0, G_OPTION_ARG_NONE,	&arg_skip_plugins, N_("Don't auto load any plugins"), NULL},
+ {"plugindir",	'p', 0, G_OPTION_ARG_NONE,	&arg_show_autoload, N_("Show plugin auto-load directory"), NULL},
+ {"configdir",	'u', 0, G_OPTION_ARG_NONE,	&arg_show_config, N_("Show user config directory"), NULL},
+ {"url",	 0,  0, G_OPTION_ARG_STRING,	&arg_url, N_("Open an irc://server:port/channel URL"), "URL"},
+ {"version",	'v', 0, G_OPTION_ARG_NONE,	&arg_show_version, N_("Show version information"), NULL},
+ {NULL}
+};
+
 int
 fe_args (int argc, char *argv[])
 {
-	if (argc > 1)
+	GError *error = NULL;
+	GOptionContext *context;
+
+#ifdef ENABLE_NLS
+	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+#endif
+
+	context = g_option_context_new (NULL);
+	g_option_context_add_main_entries (context, gopt_entries, GETTEXT_PACKAGE);
+	g_option_context_parse (context, &argc, &argv, &error);
+
+	if (error)
+	{
+		if (error->message)
+			printf ("%s\n", error->message);
+		return 1;
+	}
+
+	g_option_context_free (context);
+
+	if (arg_show_version)
+	{
+		printf (PACKAGE_TARNAME" "PACKAGE_VERSION"\n");
+		return 0;
+	}
+
+	if (arg_show_autoload)
 	{
-		if (!strcasecmp (argv[1], "--version") || !strcasecmp (argv[1], "-v"))
+#ifdef WIN32
+		/* see the chdir() below */
+		char *sl, *exe = strdup (argv[0]);
+		sl = strrchr (exe, '\\');
+		if (sl)
 		{
-			puts (PACKAGE_VERSION);
-			return 0;
+			*sl = 0;
+			printf ("%s\\plugins\n", exe);
 		}
+#else
+		printf ("%s\n", XCHATLIBDIR"/plugins");
+#endif
+		return 0;
 	}
+
+	if (arg_show_config)
+	{
+		printf ("%s\n", get_xdir_fs ());
+		return 0;
+	}
+
+	if (arg_cfgdir)	/* we want filesystem encoding */
+	{
+		xdir_fs = strdup (arg_cfgdir);
+		if (xdir_fs[strlen (xdir_fs) - 1] == '/')
+			xdir_fs[strlen (xdir_fs) - 1] = 0;
+		g_free (arg_cfgdir);
+	}
+
 	return -1;
 }
 
 void
 fe_init (void)
 {
-	se_list = 0;
-	se_list_count = 0;
-	tmr_list = 0;
-	tmr_list_count = 0;
+	/* the following should be default generated, not enfoced in binary */
 	prefs.autosave = 0;
 	prefs.use_server_tab = 0;
 	prefs.autodialog = 0;
+	/* except for these, there is no lag meter, there is no server list */
 	prefs.lagometer = 0;
 	prefs.slist_skip = 1;
 }
@@ -417,129 +543,29 @@ fe_init (void)
 void
 fe_main (void)
 {
-	struct timeval timeout, now;
-	socketevent *se;
-	timerevent *te;
-	fd_set rd, wd, ex;
-	GSList *list;
-	guint64 shortest, delay;
+	GIOChannel *keyboard_input;
 
-	if (!sess_list)
-		new_ircwindow (NULL, NULL, SESS_SERVER, 0);
+	main_loop = g_main_loop_new(NULL, FALSE);
 
-#ifdef ENABLE_NLS
-	bindtextdomain (GETTEXT_PACKAGE, PREFIX"/share/locale");
-	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-	textdomain (GETTEXT_PACKAGE);
+	/* Keyboard Entry Setup */
+#ifdef G_OS_WIN32
+	keyboard_input = g_io_channel_win32_new_fd(STDIN_FILENO);
+#else
+	keyboard_input = g_io_channel_unix_new(STDIN_FILENO);
 #endif
 
-	while (!done)
-	{
-		FD_ZERO (&rd);
-		FD_ZERO (&wd);
-		FD_ZERO (&ex);
-
-		list = se_list;
-		while (list)
-		{
-			se = (socketevent *) list->data;
-			if (se->rread)
-				FD_SET (se->sok, &rd);
-			if (se->wwrite)
-				FD_SET (se->sok, &wd);
-			if (se->eexcept)
-				FD_SET (se->sok, &ex);
-			list = list->next;
-		}
-
-		FD_SET (STDIN_FILENO, &rd);	/* for reading keyboard */
-
-		/* find the shortest timeout event */
-		shortest = 0;
-		list = tmr_list;
-		while (list)
-		{
-			te = (timerevent *) list->data;
-			if (te->next_call < shortest || shortest == 0)
-				shortest = te->next_call;
-			list = list->next;
-		}
-		gettimeofday (&now, NULL);
-		delay = shortest - ((now.tv_sec * 1000) + (now.tv_usec / 1000));
-		timeout.tv_sec = delay / 1000;
-		timeout.tv_usec = (delay % 1000) * 1000;
-
-		select (FD_SETSIZE, &rd, &wd, &ex, &timeout);
-
-		if (FD_ISSET (STDIN_FILENO, &rd))
-			read_stdin ();
-
-		/* set all checked flags to false */
-		list = se_list;
-		while (list)
-		{
-			se = (socketevent *) list->data;
-			se->checked = 0;
-			list = list->next;
-		}
-
-		/* check all the socket callbacks */
-		list = se_list;
-		while (list)
-		{
-			se = (socketevent *) list->data;
-			se->checked = 1;
-			if (se->rread && FD_ISSET (se->sok, &rd))
-			{
-				se->callback (NULL, 1, se->userdata);
-			} else if (se->wwrite && FD_ISSET (se->sok, &wd))
-			{
-				se->callback (NULL, 2, se->userdata);
-			} else if (se->eexcept && FD_ISSET (se->sok, &ex))
-			{
-				se->callback (NULL, 4, se->userdata);
-			}
-			list = se_list;
-			if (list)
-			{
-				se = (socketevent *) list->data;
-				while (se->checked)
-				{
-					list = list->next;
-					if (!list)
-						break;
-					se = (socketevent *) list->data;
-				}
-			}
-		}
+	g_io_add_watch(keyboard_input, G_IO_IN, handle_line, NULL);
 
-		/* now check our list of timeout events, some might need to be called! */
-		gettimeofday (&now, NULL);
-		list = tmr_list;
-		while (list)
-		{
-			te = (timerevent *) list->data;
-			list = list->next;
-			if (now.tv_sec * 1000 + (now.tv_usec / 1000) >= te->next_call)
-			{
-				/* if the callback returns 0, it must be removed */
-				if (te->callback (te->userdata) == 0)
-				{
-					fe_timeout_remove (te->tag);
-				} else
-				{
-					te->next_call = now.tv_sec * 1000 + (now.tv_usec / 1000) + te->interval;
-				}
-			}
-		}
+	g_main_loop_run(main_loop);
 
-	}
+	return;
 }
 
 void
 fe_exit (void)
 {
 	done = TRUE;
+	g_main_loop_quit(main_loop);
 }
 
 void
@@ -793,10 +819,23 @@ fe_get_int (char *prompt, int def, void *callback, void *ud)
 void
 fe_idle_add (void *func, void *data)
 {
+	g_idle_add (func, data);
 }
 void
 fe_ctrl_gui (session *sess, fe_gui_action action, int arg)
 {
+	/* only one action type handled for now, but could add more */
+	switch (action)
+	{
+	/* gui focus is really the only case xchat-text needs to wory about */
+	case FE_GUI_FOCUS:
+		current_sess = sess;
+		current_tab = sess;
+		sess->server->front_session = sess;
+		break;
+	default:
+		break;
+	}
 }
 int
 fe_gui_info (session *sess, int info_type)
diff --git a/src/fe-text/fe-text.h b/src/fe-text/fe-text.h
index b8afa284..e4f6f6c0 100644
--- a/src/fe-text/fe-text.h
+++ b/src/fe-text/fe-text.h
@@ -1,29 +1 @@
-
-typedef int (*socket_callback) (void *source, int condition, void *user_data);
-typedef int (*timer_callback) (void *user_data);
-
-struct socketeventRec
-{
-	socket_callback callback;
-	void *userdata;
-	int sok;
-	int tag;
-	int rread:1;
-	int wwrite:1;
-	int eexcept:1;
-	int checked:1;
-};
-
-typedef struct socketeventRec socketevent;
-
-
-struct timerRec
-{
-	timer_callback callback;
-	void *userdata;
-	int interval;
-	int tag;
-	guint64 next_call;	/* miliseconds */
-};
-
-typedef struct timerRec timerevent;
+GMainLoop *main_loop;
diff --git a/src/fe-text/fe-text.vcxproj b/src/fe-text/fe-text.vcxproj
new file mode 100644
index 00000000..e8ed04b0
--- /dev/null
+++ b/src/fe-text/fe-text.vcxproj
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{E93E1255-95D1-4B08-8FDF-B53CC6A21280}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>fetext</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <TargetName>xchat-text</TargetName>

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <TargetName>xchat-text</TargetName>

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level1</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalDependencies>$(DepLibs);"$(OutDir)\common.lib";"$(OutDir)\dirent-win32.lib";%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level1</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;_WIN64;NDEBUG;_CONSOLE;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalDependencies>$(DepLibs);"$(OutDir)\common.lib";"$(OutDir)\dirent-win32.lib";%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClInclude Include="fe-text.h" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="fe-text.c" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/fe-text/fe-text.vcxproj.filters b/src/fe-text/fe-text.vcxproj.filters
new file mode 100644
index 00000000..e8a4bcc5
--- /dev/null
+++ b/src/fe-text/fe-text.vcxproj.filters
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="fe-text.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="fe-text.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/fe-text/fe-text.vcxproj.user b/src/fe-text/fe-text.vcxproj.user
new file mode 100644
index 00000000..695b5c78
--- /dev/null
+++ b/src/fe-text/fe-text.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+</Project>
\ No newline at end of file
diff --git a/src/fe-text/makefile.mak b/src/fe-text/makefile.mak
new file mode 100644
index 00000000..59d277d3
--- /dev/null
+++ b/src/fe-text/makefile.mak
@@ -0,0 +1,20 @@
+include "..\makeinc.mak"

+

+COMLIB = ..\common\xchatcommon.lib

+PROG = xchat-text.exe

+

+!ifdef X64

+PLATOBJ = msvcrt_win2003.obj

+!else

+PLATOBJ = msvcrt_winxp.obj

+!endif

+

+all: fe-text.obj

+	link /out:$(PROG) /subsystem:console /nologo $(PLATOBJ) $(LIBS) $(COMLIB) fe-text.obj

+

+fe-text.obj: fe-text.c makefile.mak

+	cl $(CFLAGS) $(GLIB) fe-text.c

+

+clean:

+	@del *.obj

+	@del $(PROG)

diff --git a/src/gtk2-prefs/callbacks.cpp b/src/gtk2-prefs/callbacks.cpp
new file mode 100644
index 00000000..9cc5c928
--- /dev/null
+++ b/src/gtk2-prefs/callbacks.cpp
@@ -0,0 +1,224 @@
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <iostream>
+
+#include "callbacks.h"
+#include "interface.h"
+#include "support.h"
+
+#include "main.h"
+
+
+
+extern GtkWidget* g_main_window;
+
+void
+on_main_showpreviewtoggle_toggled               (GtkToggleButton *togglebutton,
+                                        gpointer         user_data)
+{
+	if (gtk_toggle_button_get_active (togglebutton)) {
+		gtk_widget_show(lookup_widget(g_main_window, "main_previewhbox"));
+		gtk_button_set_label(GTK_BUTTON(togglebutton), "Hide preview <<");
+		gtk_window_resize(GTK_WINDOW(g_main_window), 700, 330);
+	} else {
+		gtk_widget_hide(lookup_widget(g_main_window, "main_previewhbox"));
+		gtk_button_set_label(GTK_BUTTON(togglebutton), "Show preview >>");
+		gtk_window_resize(GTK_WINDOW(g_main_window), 300, 330);
+	}
+
+}
+
+
+/*
+extern GtkWidget* g_fontsel_dialog;
+
+
+void
+on_fontsel_dialog_response             (GtkDialog       *dialog,
+                                        gint             id,
+                                        gpointer         user_data)
+{
+
+	switch(id) {
+		case GTK_RESPONSE_OK:
+		{
+			const char* font = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG(dialog));
+			std::string f = (font ? font : "");
+			set_theme(get_selected_theme(), f);
+			break;
+		}
+//		case GTK_RESPONSE_CANCEL:
+//			gtk_widget_destroy(g_fontsel_dialog);
+//			g_fontsel_dialog = 0;
+//			return;
+
+	}
+	gtk_widget_destroy(g_fontsel_dialog);
+	g_fontsel_dialog = 0;
+
+}
+
+
+gboolean
+on_fontsel_dialog_delete_event         (GtkWidget       *widget,
+                                        GdkEvent        *event,
+                                        gpointer         user_data)
+{
+	gtk_widget_destroy(g_fontsel_dialog);
+	g_fontsel_dialog = 0;
+
+	return FALSE;
+}
+
+
+void
+on_main_fontselectbutton_clicked       (GtkButton       *button,
+                                        gpointer         user_data)
+{
+	g_fontsel_dialog = create_fontsel_dialog();
+	gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(g_fontsel_dialog), get_current_font().c_str());
+	gtk_widget_show(g_fontsel_dialog);
+}
+*/
+
+
+
+
+
+void
+on_main_ok_button_clicked              (GtkButton       *button,
+                                        gpointer         user_data)
+{
+	if (save_current_theme())
+		gtk_main_quit();
+}
+
+
+void
+on_main_cancel_button_clicked          (GtkButton       *button,
+                                        gpointer         user_data)
+{
+	gtk_main_quit();
+}
+
+
+void
+on_main_reset_button_clicked           (GtkButton       *button,
+                                        gpointer         user_data)
+{
+	set_theme(get_orig_theme(), get_orig_font());
+}
+
+
+gboolean
+on_main_window_delete_event            (GtkWidget       *widget,
+                                        GdkEvent        *event,
+                                        gpointer         user_data)
+{
+	program_shutdown();
+	return true;
+}
+
+
+void
+on_main_use_default_font_radio_toggled (GtkToggleButton *togglebutton,
+                                        gpointer         user_data)
+{
+	bool default_font = gtk_toggle_button_get_active(togglebutton);
+
+	gtk_widget_set_sensitive(lookup_widget(g_main_window, "main_font_selector_button"), !default_font);
+
+	apply_theme(get_selected_theme(), get_selected_font());
+}
+
+
+void
+on_main_font_selector_button_font_set  (GtkFontButton   *fontbutton,
+                                        gpointer         user_data)
+{
+	apply_theme(get_selected_theme(), get_selected_font());
+}
+
+
+void
+on_new2_activate                       (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_open2_activate                      (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_save2_activate                      (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_save_as2_activate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_quit2_activate                      (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_cut2_activate                       (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_copy2_activate                      (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_paste2_activate                     (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_delete2_activate                    (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_about2_activate                     (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
diff --git a/src/gtk2-prefs/callbacks.h b/src/gtk2-prefs/callbacks.h
new file mode 100644
index 00000000..5759aebc
--- /dev/null
+++ b/src/gtk2-prefs/callbacks.h
@@ -0,0 +1,71 @@
+#include <gtk/gtk.h>
+
+
+void
+on_main_showpreviewtoggle_toggled               (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+on_main_ok_button_clicked              (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+on_main_cancel_button_clicked          (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+on_main_reset_button_clicked           (GtkButton       *button,
+                                        gpointer         user_data);
+
+gboolean
+on_main_window_delete_event            (GtkWidget       *widget,
+                                        GdkEvent        *event,
+                                        gpointer         user_data);
+
+void
+on_main_use_default_font_radio_toggled (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+on_main_font_selector_button_font_set  (GtkFontButton   *fontbutton,
+                                        gpointer         user_data);
+
+void
+on_new2_activate                       (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+void
+on_open2_activate                      (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+void
+on_save2_activate                      (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+void
+on_save_as2_activate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+void
+on_quit2_activate                      (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+void
+on_cut2_activate                       (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+void
+on_copy2_activate                      (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+void
+on_paste2_activate                     (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+void
+on_delete2_activate                    (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+void
+on_about2_activate                     (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
diff --git a/src/gtk2-prefs/config.h b/src/gtk2-prefs/config.h
new file mode 100644
index 00000000..4501a33b
--- /dev/null
+++ b/src/gtk2-prefs/config.h
@@ -0,0 +1,59 @@
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* For gmessages.h error message */
+#define G_HAVE_ISO_VARARGS
+
+/* For mkdir */
+#define HAVE_DIRECT_H 1
+
+/* Name of package */
+#define PACKAGE gtk2-prefs
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME gtk2-prefs
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING gtk2-prefs 0.4.1
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME gtk2-prefs
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION 0.4.1
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION 0.4.1
diff --git a/src/gtk2-prefs/interface.cpp b/src/gtk2-prefs/interface.cpp
new file mode 100644
index 00000000..7c1cc53c
--- /dev/null
+++ b/src/gtk2-prefs/interface.cpp
@@ -0,0 +1,836 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "callbacks.h"
+#include "interface.h"
+#include "support.h"
+
+#define GLADE_HOOKUP_OBJECT(component,widget,name) \
+  g_object_set_data_full (G_OBJECT (component), name, \
+    gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
+
+#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
+  g_object_set_data (G_OBJECT (component), name, widget)
+
+GtkWidget*
+create_main_window (void)
+{
+  GtkWidget *main_window;
+  GtkWidget *main_hbox;
+  GtkWidget *vbox1;
+  GtkWidget *hbox1;
+  GtkWidget *frame2;
+  GtkWidget *alignment3;
+  GtkWidget *scrolledwindow3;
+  GtkWidget *main_themelist;
+  GtkWidget *label1234;
+  GtkWidget *frame3;
+  GtkWidget *alignment4;
+  GtkWidget *vbox7;
+  GtkWidget *hbox8;
+  GtkWidget *vbox9;
+  GtkWidget *main_use_default_font_radio;
+  GSList *main_use_default_font_radio_group = NULL;
+  GtkWidget *main_use_custom_font_radio;
+  GtkWidget *alignment5;
+  GtkWidget *vbox10;
+  GtkWidget *hbox9;
+  GtkWidget *vbox11;
+  GtkWidget *main_font_selector_button;
+  GtkWidget *label669;
+  GtkWidget *vbox13;
+  GtkWidget *hbox6666;
+  GtkWidget *main_use_system_config_checkbutton;
+  GtkWidget *main_showpreviewtoggle;
+  GtkWidget *hbuttonbox1;
+  GtkWidget *hbox7;
+  GtkWidget *hbox6665;
+  GtkWidget *image2;
+  GtkWidget *label2;
+  GtkWidget *vbox6;
+  GtkWidget *hbox5;
+  GtkWidget *main_ok_button;
+  GtkWidget *main_cancel_button;
+  GtkWidget *main_reset_button;
+  GtkWidget *alignment2;
+  GtkWidget *hbox6;
+  GtkWidget *image1;
+  GtkWidget *label667;
+  GtkWidget *main_previewhbox;
+  GtkWidget *vseparator2;
+  GtkWidget *frame4;
+  GtkWidget *alignment6;
+  GtkWidget *vbox12;
+  GtkWidget *main_previewbook;
+  GtkWidget *table1;
+  GtkWidget *vbox2;
+  GtkWidget *checkbutton1;
+  GtkWidget *checkbutton2;
+  GtkWidget *button4;
+  GtkWidget *togglebutton1;
+  GtkObject *spinbutton1_adj;
+  GtkWidget *spinbutton1;
+  GtkWidget *vbox4;
+  GtkWidget *menubar2;
+  GtkWidget *menuitem5;
+  GtkWidget *menuitem5_menu;
+  GtkWidget *new2;
+  GtkWidget *open2;
+  GtkWidget *save2;
+  GtkWidget *save_as2;
+  GtkWidget *separatormenuitem2;
+  GtkWidget *quit2;
+  GtkWidget *menuitem6;
+  GtkWidget *menuitem6_menu;
+  GtkWidget *cut2;
+  GtkWidget *copy2;
+  GtkWidget *paste2;
+  GtkWidget *delete2;
+  GtkWidget *menuitem8;
+  GtkWidget *menuitem8_menu;
+  GtkWidget *about2;
+  GtkWidget *combobox1;
+  GtkWidget *comboboxentry1;
+  GtkWidget *hscale1;
+  GtkWidget *scrolledwindow1;
+  GtkWidget *preview_treeview;
+  GtkWidget *statusbar1;
+  GtkWidget *progressbar1;
+  GtkWidget *vseparator1;
+  GtkWidget *frame1;
+  GtkWidget *vbox3;
+  GtkWidget *radiobutton1;
+  GSList *radiobutton1_group = NULL;
+  GtkWidget *radiobutton2;
+  GtkWidget *radiobutton3;
+  GtkWidget *label6;
+  GtkWidget *label4;
+  GtkWidget *scrolledwindow2;
+  GtkWidget *textview1;
+  GtkWidget *label5;
+  GtkWidget *vbox5;
+  GtkWidget *hbox4;
+  GtkWidget *about_label;
+  GtkWidget *label666;
+  GtkWidget *label670;
+  GtkAccelGroup *accel_group;
+  GtkTooltips *tooltips;
+
+  tooltips = gtk_tooltips_new ();
+
+  accel_group = gtk_accel_group_new ();
+
+  main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_widget_set_name (main_window, "main_window");
+  gtk_window_set_title (GTK_WINDOW (main_window), "GTK+ Preference Tool");
+
+  main_hbox = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (main_hbox, "main_hbox");
+  gtk_widget_show (main_hbox);
+  gtk_container_add (GTK_CONTAINER (main_window), main_hbox);
+  gtk_widget_set_size_request (main_hbox, 310, 320);
+
+  vbox1 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox1, "vbox1");
+  gtk_widget_show (vbox1);
+  gtk_box_pack_start (GTK_BOX (main_hbox), vbox1, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox1), 3);
+
+  hbox1 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox1, "hbox1");
+  gtk_widget_show (hbox1);
+  gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
+
+  frame2 = gtk_frame_new (NULL);
+  gtk_widget_set_name (frame2, "frame2");
+  gtk_widget_show (frame2);
+  gtk_box_pack_start (GTK_BOX (hbox1), frame2, TRUE, TRUE, 0);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_NONE);
+
+  alignment3 = gtk_alignment_new (0.5, 0.5, 1, 1);
+  gtk_widget_set_name (alignment3, "alignment3");
+  gtk_widget_show (alignment3);
+  gtk_container_add (GTK_CONTAINER (frame2), alignment3);
+  gtk_alignment_set_padding (GTK_ALIGNMENT (alignment3), 0, 0, 12, 0);
+
+  scrolledwindow3 = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_name (scrolledwindow3, "scrolledwindow3");
+  gtk_widget_show (scrolledwindow3);
+  gtk_container_add (GTK_CONTAINER (alignment3), scrolledwindow3);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow3), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow3), GTK_SHADOW_IN);
+
+  main_themelist = gtk_tree_view_new ();
+  gtk_widget_set_name (main_themelist, "main_themelist");
+  gtk_widget_show (main_themelist);
+  gtk_container_add (GTK_CONTAINER (scrolledwindow3), main_themelist);
+  GTK_WIDGET_SET_FLAGS (main_themelist, GTK_CAN_DEFAULT);
+  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (main_themelist), FALSE);
+
+  label1234 = gtk_label_new ("<b>Theme</b>");
+  gtk_widget_set_name (label1234, "label1234");
+  gtk_widget_show (label1234);
+  gtk_frame_set_label_widget (GTK_FRAME (frame2), label1234);
+  gtk_label_set_use_markup (GTK_LABEL (label1234), TRUE);
+
+  frame3 = gtk_frame_new (NULL);
+  gtk_widget_set_name (frame3, "frame3");
+  gtk_widget_show (frame3);
+  gtk_box_pack_start (GTK_BOX (vbox1), frame3, FALSE, FALSE, 9);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_NONE);
+
+  alignment4 = gtk_alignment_new (0.5, 0.5, 1, 1);
+  gtk_widget_set_name (alignment4, "alignment4");
+  gtk_widget_show (alignment4);
+  gtk_container_add (GTK_CONTAINER (frame3), alignment4);
+  gtk_alignment_set_padding (GTK_ALIGNMENT (alignment4), 0, 0, 12, 0);
+
+  vbox7 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox7, "vbox7");
+  gtk_widget_show (vbox7);
+  gtk_container_add (GTK_CONTAINER (alignment4), vbox7);
+
+  hbox8 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox8, "hbox8");
+  gtk_widget_show (hbox8);
+  gtk_box_pack_start (GTK_BOX (vbox7), hbox8, FALSE, FALSE, 0);
+
+  vbox9 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox9, "vbox9");
+  gtk_widget_show (vbox9);
+  gtk_box_pack_start (GTK_BOX (hbox8), vbox9, TRUE, TRUE, 0);
+
+  main_use_default_font_radio = gtk_radio_button_new_with_mnemonic (NULL, "Use theme default font");
+  gtk_widget_set_name (main_use_default_font_radio, "main_use_default_font_radio");
+  gtk_widget_show (main_use_default_font_radio);
+  gtk_box_pack_start (GTK_BOX (vbox9), main_use_default_font_radio, FALSE, FALSE, 0);
+  gtk_radio_button_set_group (GTK_RADIO_BUTTON (main_use_default_font_radio), main_use_default_font_radio_group);
+  main_use_default_font_radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (main_use_default_font_radio));
+
+  main_use_custom_font_radio = gtk_radio_button_new_with_mnemonic (NULL, "Use custom font:");
+  gtk_widget_set_name (main_use_custom_font_radio, "main_use_custom_font_radio");
+  gtk_widget_show (main_use_custom_font_radio);
+  gtk_box_pack_start (GTK_BOX (vbox9), main_use_custom_font_radio, FALSE, FALSE, 0);
+  gtk_radio_button_set_group (GTK_RADIO_BUTTON (main_use_custom_font_radio), main_use_default_font_radio_group);
+  main_use_default_font_radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (main_use_custom_font_radio));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (main_use_custom_font_radio), TRUE);
+
+  alignment5 = gtk_alignment_new (0.5, 0.5, 1, 1);
+  gtk_widget_set_name (alignment5, "alignment5");
+  gtk_widget_show (alignment5);
+  gtk_box_pack_start (GTK_BOX (vbox9), alignment5, TRUE, TRUE, 0);
+  gtk_alignment_set_padding (GTK_ALIGNMENT (alignment5), 0, 0, 12, 0);
+
+  vbox10 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox10, "vbox10");
+  gtk_widget_show (vbox10);
+  gtk_container_add (GTK_CONTAINER (alignment5), vbox10);
+
+  hbox9 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox9, "hbox9");
+  gtk_widget_show (hbox9);
+  gtk_box_pack_start (GTK_BOX (vbox10), hbox9, FALSE, FALSE, 0);
+
+  vbox11 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox11, "vbox11");
+  gtk_widget_show (vbox11);
+  gtk_box_pack_start (GTK_BOX (hbox9), vbox11, TRUE, TRUE, 0);
+
+  main_font_selector_button = gtk_font_button_new ();
+  gtk_widget_set_name (main_font_selector_button, "main_font_selector_button");
+  gtk_widget_show (main_font_selector_button);
+  gtk_box_pack_start (GTK_BOX (vbox11), main_font_selector_button, FALSE, FALSE, 0);
+
+  label669 = gtk_label_new ("<b>Font</b>");
+  gtk_widget_set_name (label669, "label669");
+  gtk_widget_show (label669);
+  gtk_frame_set_label_widget (GTK_FRAME (frame3), label669);
+  gtk_label_set_use_markup (GTK_LABEL (label669), TRUE);
+
+  vbox13 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox13, "vbox13");
+  gtk_widget_show (vbox13);
+  gtk_box_pack_start (GTK_BOX (vbox1), vbox13, FALSE, FALSE, 0);
+
+  hbox6666 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox6666, "hbox6666");
+  gtk_widget_show (hbox6666);
+  gtk_box_pack_start (GTK_BOX (vbox13), hbox6666, TRUE, TRUE, 0);
+
+  /* main_use_system_config_checkbutton = gtk_check_button_new_with_mnemonic ("Apply for all users");
+  gtk_widget_set_name (main_use_system_config_checkbutton, "main_use_system_config_checkbutton");
+  gtk_widget_show (main_use_system_config_checkbutton);
+  gtk_box_pack_start (GTK_BOX (hbox6666), main_use_system_config_checkbutton, FALSE, FALSE, 12);
+  gtk_tooltips_set_tip (tooltips, main_use_system_config_checkbutton, "If this is enabled, the program will update the system-wide configuration file. NOT RECOMMENDED!", NULL); */
+
+  main_showpreviewtoggle = gtk_toggle_button_new_with_mnemonic ("Show preview >>");
+  gtk_widget_set_name (main_showpreviewtoggle, "main_showpreviewtoggle");
+  gtk_widget_show (main_showpreviewtoggle);
+  gtk_box_pack_end (GTK_BOX (hbox6666), main_showpreviewtoggle, FALSE, FALSE, 2);
+
+  hbuttonbox1 = gtk_hbutton_box_new ();
+  gtk_widget_set_name (hbuttonbox1, "hbuttonbox1");
+  gtk_widget_show (hbuttonbox1);
+  gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox1, FALSE, FALSE, 0);
+
+  hbox7 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox7, "hbox7");
+  gtk_widget_show (hbox7);
+  gtk_box_pack_start (GTK_BOX (vbox1), hbox7, FALSE, TRUE, 6);
+
+  hbox6665 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox6665, "hbox6665");
+  gtk_widget_show (hbox6665);
+  gtk_box_pack_start (GTK_BOX (hbox7), hbox6665, TRUE, FALSE, 0);
+
+  image2 = gtk_image_new_from_stock ("gtk-dialog-info", GTK_ICON_SIZE_LARGE_TOOLBAR);
+  gtk_widget_set_name (image2, "image2");
+  gtk_widget_show (image2);
+  gtk_box_pack_start (GTK_BOX (hbox6665), image2, FALSE, FALSE, 0);
+
+  label2 = gtk_label_new ("You should restart XChat-WDK\nfor this change to take effect.");
+  gtk_widget_set_name (label2, "label2");
+  gtk_widget_show (label2);
+  gtk_box_pack_start (GTK_BOX (hbox6665), label2, FALSE, FALSE, 0);
+  gtk_label_set_line_wrap (GTK_LABEL (label2), TRUE);
+  gtk_misc_set_alignment (GTK_MISC (label2), 0, 0.5);
+
+  vbox6 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox6, "vbox6");
+  gtk_widget_show (vbox6);
+  gtk_box_pack_start (GTK_BOX (vbox1), vbox6, FALSE, FALSE, 0);
+
+  hbox5 = gtk_hbox_new (TRUE, 0);
+  gtk_widget_set_name (hbox5, "hbox5");
+  gtk_widget_show (hbox5);
+  gtk_box_pack_start (GTK_BOX (vbox6), hbox5, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox5), 4);
+
+  main_ok_button = gtk_button_new_from_stock ("gtk-ok");
+  gtk_widget_set_name (main_ok_button, "main_ok_button");
+  gtk_widget_show (main_ok_button);
+  gtk_box_pack_end (GTK_BOX (hbox5), main_ok_button, TRUE, TRUE, 4);
+  GTK_WIDGET_SET_FLAGS (main_ok_button, GTK_CAN_DEFAULT);
+
+  main_cancel_button = gtk_button_new_from_stock ("gtk-cancel");
+  gtk_widget_set_name (main_cancel_button, "main_cancel_button");
+  gtk_widget_show (main_cancel_button);
+  gtk_box_pack_end (GTK_BOX (hbox5), main_cancel_button, TRUE, TRUE, 4);
+  GTK_WIDGET_SET_FLAGS (main_cancel_button, GTK_CAN_DEFAULT);
+
+  main_reset_button = gtk_button_new ();
+  gtk_widget_set_name (main_reset_button, "main_reset_button");
+  gtk_widget_show (main_reset_button);
+  gtk_box_pack_end (GTK_BOX (hbox5), main_reset_button, TRUE, TRUE, 4);
+
+  alignment2 = gtk_alignment_new (0.5, 0.5, 0, 0);
+  gtk_widget_set_name (alignment2, "alignment2");
+  gtk_widget_show (alignment2);
+  gtk_container_add (GTK_CONTAINER (main_reset_button), alignment2);
+
+  hbox6 = gtk_hbox_new (FALSE, 2);
+  gtk_widget_set_name (hbox6, "hbox6");
+  gtk_widget_show (hbox6);
+  gtk_container_add (GTK_CONTAINER (alignment2), hbox6);
+
+  image1 = gtk_image_new_from_stock ("gtk-revert-to-saved", GTK_ICON_SIZE_BUTTON);
+  gtk_widget_set_name (image1, "image1");
+  gtk_widget_show (image1);
+  gtk_box_pack_start (GTK_BOX (hbox6), image1, FALSE, FALSE, 0);
+
+  label667 = gtk_label_new_with_mnemonic ("_Reset");
+  gtk_widget_set_name (label667, "label667");
+  gtk_widget_show (label667);
+  gtk_box_pack_start (GTK_BOX (hbox6), label667, FALSE, FALSE, 0);
+
+  main_previewhbox = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (main_previewhbox, "main_previewhbox");
+  gtk_box_pack_start (GTK_BOX (main_hbox), main_previewhbox, TRUE, TRUE, 0);
+
+  vseparator2 = gtk_vseparator_new ();
+  gtk_widget_set_name (vseparator2, "vseparator2");
+  gtk_widget_show (vseparator2);
+  gtk_box_pack_start (GTK_BOX (main_previewhbox), vseparator2, FALSE, TRUE, 4);
+
+  frame4 = gtk_frame_new (NULL);
+  gtk_widget_set_name (frame4, "frame4");
+  gtk_widget_show (frame4);
+  gtk_box_pack_start (GTK_BOX (main_previewhbox), frame4, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame4), 3);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame4), GTK_SHADOW_NONE);
+
+  alignment6 = gtk_alignment_new (0.5, 0.5, 1, 1);
+  gtk_widget_set_name (alignment6, "alignment6");
+  gtk_widget_show (alignment6);
+  gtk_container_add (GTK_CONTAINER (frame4), alignment6);
+
+  vbox12 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox12, "vbox12");
+  gtk_widget_show (vbox12);
+  gtk_container_add (GTK_CONTAINER (alignment6), vbox12);
+
+  main_previewbook = gtk_notebook_new ();
+  gtk_widget_set_name (main_previewbook, "main_previewbook");
+  gtk_widget_show (main_previewbook);
+  gtk_box_pack_start (GTK_BOX (vbox12), main_previewbook, TRUE, TRUE, 0);
+
+  table1 = gtk_table_new (3, 3, FALSE);
+  gtk_widget_set_name (table1, "table1");
+  gtk_widget_show (table1);
+  gtk_container_add (GTK_CONTAINER (main_previewbook), table1);
+  gtk_container_set_border_width (GTK_CONTAINER (table1), 5);
+
+  vbox2 = gtk_vbox_new (FALSE, 4);
+  gtk_widget_set_name (vbox2, "vbox2");
+  gtk_widget_show (vbox2);
+  gtk_table_attach (GTK_TABLE (table1), vbox2, 0, 1, 0, 1,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
+
+  checkbutton1 = gtk_check_button_new_with_mnemonic ("check button 1");
+  gtk_widget_set_name (checkbutton1, "checkbutton1");
+  gtk_widget_show (checkbutton1);
+  gtk_box_pack_start (GTK_BOX (vbox2), checkbutton1, FALSE, FALSE, 0);
+
+  checkbutton2 = gtk_check_button_new_with_mnemonic ("check button 2");
+  gtk_widget_set_name (checkbutton2, "checkbutton2");
+  gtk_widget_show (checkbutton2);
+  gtk_box_pack_start (GTK_BOX (vbox2), checkbutton2, FALSE, FALSE, 0);
+
+  button4 = gtk_button_new_with_mnemonic ("button");
+  gtk_widget_set_name (button4, "button4");
+  gtk_widget_show (button4);
+  gtk_box_pack_start (GTK_BOX (vbox2), button4, FALSE, FALSE, 0);
+
+  togglebutton1 = gtk_toggle_button_new_with_mnemonic ("toggle button");
+  gtk_widget_set_name (togglebutton1, "togglebutton1");
+  gtk_widget_show (togglebutton1);
+  gtk_box_pack_start (GTK_BOX (vbox2), togglebutton1, FALSE, FALSE, 0);
+
+  spinbutton1_adj = gtk_adjustment_new (0, 0, 100, 1, 10, 10);
+  spinbutton1 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton1_adj), 1, 0);
+  gtk_widget_set_name (spinbutton1, "spinbutton1");
+  gtk_widget_show (spinbutton1);
+  gtk_box_pack_start (GTK_BOX (vbox2), spinbutton1, FALSE, FALSE, 0);
+
+  vbox4 = gtk_vbox_new (FALSE, 4);
+  gtk_widget_set_name (vbox4, "vbox4");
+  gtk_widget_show (vbox4);
+  gtk_table_attach (GTK_TABLE (table1), vbox4, 2, 3, 0, 1,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+  menubar2 = gtk_menu_bar_new ();
+  gtk_widget_set_name (menubar2, "menubar2");
+  gtk_widget_show (menubar2);
+  gtk_box_pack_start (GTK_BOX (vbox4), menubar2, FALSE, FALSE, 0);
+
+  menuitem5 = gtk_menu_item_new_with_mnemonic ("_File");
+  gtk_widget_set_name (menuitem5, "menuitem5");
+  gtk_widget_show (menuitem5);
+  gtk_container_add (GTK_CONTAINER (menubar2), menuitem5);
+
+  menuitem5_menu = gtk_menu_new ();
+  gtk_widget_set_name (menuitem5_menu, "menuitem5_menu");
+  gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem5), menuitem5_menu);
+
+  new2 = gtk_image_menu_item_new_from_stock ("gtk-new", accel_group);
+  gtk_widget_set_name (new2, "new2");
+  gtk_widget_show (new2);
+  gtk_container_add (GTK_CONTAINER (menuitem5_menu), new2);
+
+  open2 = gtk_image_menu_item_new_from_stock ("gtk-open", accel_group);
+  gtk_widget_set_name (open2, "open2");
+  gtk_widget_show (open2);
+  gtk_container_add (GTK_CONTAINER (menuitem5_menu), open2);
+
+  save2 = gtk_image_menu_item_new_from_stock ("gtk-save", accel_group);
+  gtk_widget_set_name (save2, "save2");
+  gtk_widget_show (save2);
+  gtk_container_add (GTK_CONTAINER (menuitem5_menu), save2);
+
+  save_as2 = gtk_image_menu_item_new_from_stock ("gtk-save-as", accel_group);
+  gtk_widget_set_name (save_as2, "save_as2");
+  gtk_widget_show (save_as2);
+  gtk_container_add (GTK_CONTAINER (menuitem5_menu), save_as2);
+
+  separatormenuitem2 = gtk_separator_menu_item_new ();
+  gtk_widget_set_name (separatormenuitem2, "separatormenuitem2");
+  gtk_widget_show (separatormenuitem2);
+  gtk_container_add (GTK_CONTAINER (menuitem5_menu), separatormenuitem2);
+  gtk_widget_set_sensitive (separatormenuitem2, FALSE);
+
+  quit2 = gtk_image_menu_item_new_from_stock ("gtk-quit", accel_group);
+  gtk_widget_set_name (quit2, "quit2");
+  gtk_widget_show (quit2);
+  gtk_container_add (GTK_CONTAINER (menuitem5_menu), quit2);
+
+  menuitem6 = gtk_menu_item_new_with_mnemonic ("_Edit");
+  gtk_widget_set_name (menuitem6, "menuitem6");
+  gtk_widget_show (menuitem6);
+  gtk_container_add (GTK_CONTAINER (menubar2), menuitem6);
+
+  menuitem6_menu = gtk_menu_new ();
+  gtk_widget_set_name (menuitem6_menu, "menuitem6_menu");
+  gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem6), menuitem6_menu);
+
+  cut2 = gtk_image_menu_item_new_from_stock ("gtk-cut", accel_group);
+  gtk_widget_set_name (cut2, "cut2");
+  gtk_widget_show (cut2);
+  gtk_container_add (GTK_CONTAINER (menuitem6_menu), cut2);
+
+  copy2 = gtk_image_menu_item_new_from_stock ("gtk-copy", accel_group);
+  gtk_widget_set_name (copy2, "copy2");
+  gtk_widget_show (copy2);
+  gtk_container_add (GTK_CONTAINER (menuitem6_menu), copy2);
+
+  paste2 = gtk_image_menu_item_new_from_stock ("gtk-paste", accel_group);
+  gtk_widget_set_name (paste2, "paste2");
+  gtk_widget_show (paste2);
+  gtk_container_add (GTK_CONTAINER (menuitem6_menu), paste2);
+
+  delete2 = gtk_image_menu_item_new_from_stock ("gtk-delete", accel_group);
+  gtk_widget_set_name (delete2, "delete2");
+  gtk_widget_show (delete2);
+  gtk_container_add (GTK_CONTAINER (menuitem6_menu), delete2);
+
+  menuitem8 = gtk_menu_item_new_with_mnemonic ("_Help");
+  gtk_widget_set_name (menuitem8, "menuitem8");
+  gtk_widget_show (menuitem8);
+  gtk_container_add (GTK_CONTAINER (menubar2), menuitem8);
+
+  menuitem8_menu = gtk_menu_new ();
+  gtk_widget_set_name (menuitem8_menu, "menuitem8_menu");
+  gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem8), menuitem8_menu);
+
+  about2 = gtk_menu_item_new_with_mnemonic ("_About");
+  gtk_widget_set_name (about2, "about2");
+  gtk_widget_show (about2);
+  gtk_container_add (GTK_CONTAINER (menuitem8_menu), about2);
+
+  combobox1 = gtk_combo_box_new_text ();
+  gtk_widget_set_name (combobox1, "combobox1");
+  gtk_widget_show (combobox1);
+  gtk_box_pack_start (GTK_BOX (vbox4), combobox1, FALSE, FALSE, 0);
+  gtk_combo_box_append_text (GTK_COMBO_BOX (combobox1), "item 1");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (combobox1), "item 2");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (combobox1), "item 3");
+
+  comboboxentry1 = gtk_combo_box_entry_new_text ();
+  gtk_widget_set_name (comboboxentry1, "comboboxentry1");
+  gtk_widget_show (comboboxentry1);
+  gtk_box_pack_start (GTK_BOX (vbox4), comboboxentry1, FALSE, FALSE, 0);
+  gtk_widget_set_size_request (comboboxentry1, 80, 25);
+  gtk_combo_box_append_text (GTK_COMBO_BOX (comboboxentry1), "item 1");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (comboboxentry1), "item 2");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (comboboxentry1), "item 3");
+
+  hscale1 = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (15, 0, 50, 1, 0, 0)));
+  gtk_widget_set_name (hscale1, "hscale1");
+  gtk_widget_show (hscale1);
+  gtk_box_pack_start (GTK_BOX (vbox4), hscale1, TRUE, TRUE, 0);
+  gtk_scale_set_digits (GTK_SCALE (hscale1), 0);
+
+  scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_name (scrolledwindow1, "scrolledwindow1");
+  gtk_widget_show (scrolledwindow1);
+  gtk_table_attach (GTK_TABLE (table1), scrolledwindow1, 2, 3, 1, 2,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+  preview_treeview = gtk_tree_view_new ();
+  gtk_widget_set_name (preview_treeview, "preview_treeview");
+  gtk_widget_show (preview_treeview);
+  gtk_container_add (GTK_CONTAINER (scrolledwindow1), preview_treeview);
+  gtk_tree_view_set_reorderable (GTK_TREE_VIEW (preview_treeview), TRUE);
+
+  statusbar1 = gtk_statusbar_new ();
+  gtk_widget_set_name (statusbar1, "statusbar1");
+  gtk_widget_show (statusbar1);
+  gtk_table_attach (GTK_TABLE (table1), statusbar1, 1, 3, 2, 3,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_widget_set_size_request (statusbar1, 6, 20);
+
+  progressbar1 = gtk_progress_bar_new ();
+  gtk_widget_set_name (progressbar1, "progressbar1");
+  gtk_widget_show (progressbar1);
+  gtk_table_attach (GTK_TABLE (table1), progressbar1, 0, 1, 2, 3,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_widget_set_size_request (progressbar1, 80, 20);
+  gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progressbar1), 0.56);
+  gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progressbar1), "56%");
+
+  vseparator1 = gtk_vseparator_new ();
+  gtk_widget_set_name (vseparator1, "vseparator1");
+  gtk_widget_show (vseparator1);
+  gtk_table_attach (GTK_TABLE (table1), vseparator1, 1, 2, 0, 2,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (GTK_FILL), 5, 0);
+
+  frame1 = gtk_frame_new (NULL);
+  gtk_widget_set_name (frame1, "frame1");
+  gtk_widget_show (frame1);
+  gtk_table_attach (GTK_TABLE (table1), frame1, 0, 1, 1, 2,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (GTK_EXPAND), 0, 0);
+  gtk_frame_set_label_align (GTK_FRAME (frame1), 0.5, 0.5);
+
+  vbox3 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox3, "vbox3");
+  gtk_widget_show (vbox3);
+  gtk_container_add (GTK_CONTAINER (frame1), vbox3);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox3), 5);
+
+  radiobutton1 = gtk_radio_button_new_with_mnemonic (NULL, "radio 1");
+  gtk_widget_set_name (radiobutton1, "radiobutton1");
+  gtk_widget_show (radiobutton1);
+  gtk_box_pack_start (GTK_BOX (vbox3), radiobutton1, FALSE, FALSE, 0);
+  gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton1), radiobutton1_group);
+  radiobutton1_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton1));
+
+  radiobutton2 = gtk_radio_button_new_with_mnemonic (NULL, "radio 2");
+  gtk_widget_set_name (radiobutton2, "radiobutton2");
+  gtk_widget_show (radiobutton2);
+  gtk_box_pack_start (GTK_BOX (vbox3), radiobutton2, FALSE, FALSE, 0);
+  gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton2), radiobutton1_group);
+  radiobutton1_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton2));
+
+  radiobutton3 = gtk_radio_button_new_with_mnemonic (NULL, "radio 3");
+  gtk_widget_set_name (radiobutton3, "radiobutton3");
+  gtk_widget_show (radiobutton3);
+  gtk_box_pack_start (GTK_BOX (vbox3), radiobutton3, FALSE, FALSE, 0);
+  gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton3), radiobutton1_group);
+  radiobutton1_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton3));
+
+  label6 = gtk_label_new ("frame");
+  gtk_widget_set_name (label6, "label6");
+  gtk_widget_show (label6);
+  gtk_frame_set_label_widget (GTK_FRAME (frame1), label6);
+  gtk_misc_set_padding (GTK_MISC (label6), 1, 0);
+
+  label4 = gtk_label_new ("Common widgets");
+  gtk_widget_set_name (label4, "label4");
+  gtk_widget_show (label4);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (main_previewbook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (main_previewbook), 0), label4);
+
+  scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_name (scrolledwindow2, "scrolledwindow2");
+  gtk_widget_show (scrolledwindow2);
+  gtk_container_add (GTK_CONTAINER (main_previewbook), scrolledwindow2);
+
+  textview1 = gtk_text_view_new ();
+  gtk_widget_set_name (textview1, "textview1");
+  gtk_widget_show (textview1);
+  gtk_container_add (GTK_CONTAINER (scrolledwindow2), textview1);
+  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (textview1), GTK_WRAP_WORD);
+  gtk_text_view_set_left_margin (GTK_TEXT_VIEW (textview1), 8);
+  gtk_text_view_set_right_margin (GTK_TEXT_VIEW (textview1), 8);
+  gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview1)), "You can type some text here.\nYou can also click the right mouse button for a popup menu.", -1);
+
+  label5 = gtk_label_new ("Text area");
+  gtk_widget_set_name (label5, "label5");
+  gtk_widget_show (label5);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (main_previewbook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (main_previewbook), 1), label5);
+
+  vbox5 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox5, "vbox5");
+  gtk_widget_show (vbox5);
+  gtk_container_add (GTK_CONTAINER (main_previewbook), vbox5);
+
+  hbox4 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox4, "hbox4");
+  gtk_widget_show (hbox4);
+  gtk_box_pack_start (GTK_BOX (vbox5), hbox4, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox4), 7);
+
+  about_label = gtk_label_new ("");
+  gtk_widget_set_name (about_label, "about_label");
+  gtk_widget_show (about_label);
+  gtk_box_pack_start (GTK_BOX (hbox4), about_label, FALSE, FALSE, 0);
+  gtk_label_set_line_wrap (GTK_LABEL (about_label), TRUE);
+
+  label666 = gtk_label_new ("About");
+  gtk_widget_set_name (label666, "label666");
+  gtk_widget_show (label666);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (main_previewbook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (main_previewbook), 2), label666);
+
+  label670 = gtk_label_new ("<b>Preview</b>");
+  gtk_widget_set_name (label670, "label670");
+  gtk_widget_show (label670);
+  gtk_frame_set_label_widget (GTK_FRAME (frame4), label670);
+  gtk_label_set_use_markup (GTK_LABEL (label670), TRUE);
+
+  g_signal_connect ((gpointer) main_window, "delete_event",
+                    G_CALLBACK (on_main_window_delete_event),
+                    NULL);
+  g_signal_connect ((gpointer) main_use_default_font_radio, "toggled",
+                    G_CALLBACK (on_main_use_default_font_radio_toggled),
+                    NULL);
+  g_signal_connect ((gpointer) main_font_selector_button, "font_set",
+                    G_CALLBACK (on_main_font_selector_button_font_set),
+                    NULL);
+  g_signal_connect ((gpointer) main_showpreviewtoggle, "toggled",
+                    G_CALLBACK (on_main_showpreviewtoggle_toggled),
+                    NULL);
+  g_signal_connect ((gpointer) main_ok_button, "clicked",
+                    G_CALLBACK (on_main_ok_button_clicked),
+                    NULL);
+  g_signal_connect ((gpointer) main_cancel_button, "clicked",
+                    G_CALLBACK (on_main_cancel_button_clicked),
+                    NULL);
+  g_signal_connect ((gpointer) main_reset_button, "clicked",
+                    G_CALLBACK (on_main_reset_button_clicked),
+                    NULL);
+  g_signal_connect ((gpointer) new2, "activate",
+                    G_CALLBACK (on_new2_activate),
+                    NULL);
+  g_signal_connect ((gpointer) open2, "activate",
+                    G_CALLBACK (on_open2_activate),
+                    NULL);
+  g_signal_connect ((gpointer) save2, "activate",
+                    G_CALLBACK (on_save2_activate),
+                    NULL);
+  g_signal_connect ((gpointer) save_as2, "activate",
+                    G_CALLBACK (on_save_as2_activate),
+                    NULL);
+  g_signal_connect ((gpointer) quit2, "activate",
+                    G_CALLBACK (on_quit2_activate),
+                    NULL);
+  g_signal_connect ((gpointer) cut2, "activate",
+                    G_CALLBACK (on_cut2_activate),
+                    NULL);
+  g_signal_connect ((gpointer) copy2, "activate",
+                    G_CALLBACK (on_copy2_activate),
+                    NULL);
+  g_signal_connect ((gpointer) paste2, "activate",
+                    G_CALLBACK (on_paste2_activate),
+                    NULL);
+  g_signal_connect ((gpointer) delete2, "activate",
+                    G_CALLBACK (on_delete2_activate),
+                    NULL);
+  g_signal_connect ((gpointer) about2, "activate",
+                    G_CALLBACK (on_about2_activate),
+                    NULL);
+
+  /* Store pointers to all widgets, for use by lookup_widget(). */
+  GLADE_HOOKUP_OBJECT_NO_REF (main_window, main_window, "main_window");
+  GLADE_HOOKUP_OBJECT (main_window, main_hbox, "main_hbox");
+  GLADE_HOOKUP_OBJECT (main_window, vbox1, "vbox1");
+  GLADE_HOOKUP_OBJECT (main_window, hbox1, "hbox1");
+  GLADE_HOOKUP_OBJECT (main_window, frame2, "frame2");
+  GLADE_HOOKUP_OBJECT (main_window, alignment3, "alignment3");
+  GLADE_HOOKUP_OBJECT (main_window, scrolledwindow3, "scrolledwindow3");
+  GLADE_HOOKUP_OBJECT (main_window, main_themelist, "main_themelist");
+  GLADE_HOOKUP_OBJECT (main_window, label1234, "label1234");
+  GLADE_HOOKUP_OBJECT (main_window, frame3, "frame3");
+  GLADE_HOOKUP_OBJECT (main_window, alignment4, "alignment4");
+  GLADE_HOOKUP_OBJECT (main_window, vbox7, "vbox7");
+  GLADE_HOOKUP_OBJECT (main_window, hbox8, "hbox8");
+  GLADE_HOOKUP_OBJECT (main_window, vbox9, "vbox9");
+  GLADE_HOOKUP_OBJECT (main_window, main_use_default_font_radio, "main_use_default_font_radio");
+  GLADE_HOOKUP_OBJECT (main_window, main_use_custom_font_radio, "main_use_custom_font_radio");
+  GLADE_HOOKUP_OBJECT (main_window, alignment5, "alignment5");
+  GLADE_HOOKUP_OBJECT (main_window, vbox10, "vbox10");
+  GLADE_HOOKUP_OBJECT (main_window, hbox9, "hbox9");
+  GLADE_HOOKUP_OBJECT (main_window, vbox11, "vbox11");
+  GLADE_HOOKUP_OBJECT (main_window, main_font_selector_button, "main_font_selector_button");
+  GLADE_HOOKUP_OBJECT (main_window, label669, "label669");
+  GLADE_HOOKUP_OBJECT (main_window, vbox13, "vbox13");
+  GLADE_HOOKUP_OBJECT (main_window, hbox6666, "hbox6666");
+  /* GLADE_HOOKUP_OBJECT (main_window, main_use_system_config_checkbutton, "main_use_system_config_checkbutton"); */
+  GLADE_HOOKUP_OBJECT (main_window, main_showpreviewtoggle, "main_showpreviewtoggle");
+  GLADE_HOOKUP_OBJECT (main_window, hbuttonbox1, "hbuttonbox1");
+  GLADE_HOOKUP_OBJECT (main_window, hbox7, "hbox7");
+  GLADE_HOOKUP_OBJECT (main_window, hbox6665, "hbox6665");
+  GLADE_HOOKUP_OBJECT (main_window, image2, "image2");
+  GLADE_HOOKUP_OBJECT (main_window, label2, "label2");
+  GLADE_HOOKUP_OBJECT (main_window, vbox6, "vbox6");
+  GLADE_HOOKUP_OBJECT (main_window, hbox5, "hbox5");
+  GLADE_HOOKUP_OBJECT (main_window, main_ok_button, "main_ok_button");
+  GLADE_HOOKUP_OBJECT (main_window, main_cancel_button, "main_cancel_button");
+  GLADE_HOOKUP_OBJECT (main_window, main_reset_button, "main_reset_button");
+  GLADE_HOOKUP_OBJECT (main_window, alignment2, "alignment2");
+  GLADE_HOOKUP_OBJECT (main_window, hbox6, "hbox6");
+  GLADE_HOOKUP_OBJECT (main_window, image1, "image1");
+  GLADE_HOOKUP_OBJECT (main_window, label667, "label667");
+  GLADE_HOOKUP_OBJECT (main_window, main_previewhbox, "main_previewhbox");
+  GLADE_HOOKUP_OBJECT (main_window, vseparator2, "vseparator2");
+  GLADE_HOOKUP_OBJECT (main_window, frame4, "frame4");
+  GLADE_HOOKUP_OBJECT (main_window, alignment6, "alignment6");
+  GLADE_HOOKUP_OBJECT (main_window, vbox12, "vbox12");
+  GLADE_HOOKUP_OBJECT (main_window, main_previewbook, "main_previewbook");
+  GLADE_HOOKUP_OBJECT (main_window, table1, "table1");
+  GLADE_HOOKUP_OBJECT (main_window, vbox2, "vbox2");
+  GLADE_HOOKUP_OBJECT (main_window, checkbutton1, "checkbutton1");
+  GLADE_HOOKUP_OBJECT (main_window, checkbutton2, "checkbutton2");
+  GLADE_HOOKUP_OBJECT (main_window, button4, "button4");
+  GLADE_HOOKUP_OBJECT (main_window, togglebutton1, "togglebutton1");
+  GLADE_HOOKUP_OBJECT (main_window, spinbutton1, "spinbutton1");
+  GLADE_HOOKUP_OBJECT (main_window, vbox4, "vbox4");
+  GLADE_HOOKUP_OBJECT (main_window, menubar2, "menubar2");
+  GLADE_HOOKUP_OBJECT (main_window, menuitem5, "menuitem5");
+  GLADE_HOOKUP_OBJECT (main_window, menuitem5_menu, "menuitem5_menu");
+  GLADE_HOOKUP_OBJECT (main_window, new2, "new2");
+  GLADE_HOOKUP_OBJECT (main_window, open2, "open2");
+  GLADE_HOOKUP_OBJECT (main_window, save2, "save2");
+  GLADE_HOOKUP_OBJECT (main_window, save_as2, "save_as2");
+  GLADE_HOOKUP_OBJECT (main_window, separatormenuitem2, "separatormenuitem2");
+  GLADE_HOOKUP_OBJECT (main_window, quit2, "quit2");
+  GLADE_HOOKUP_OBJECT (main_window, menuitem6, "menuitem6");
+  GLADE_HOOKUP_OBJECT (main_window, menuitem6_menu, "menuitem6_menu");
+  GLADE_HOOKUP_OBJECT (main_window, cut2, "cut2");
+  GLADE_HOOKUP_OBJECT (main_window, copy2, "copy2");
+  GLADE_HOOKUP_OBJECT (main_window, paste2, "paste2");
+  GLADE_HOOKUP_OBJECT (main_window, delete2, "delete2");
+  GLADE_HOOKUP_OBJECT (main_window, menuitem8, "menuitem8");
+  GLADE_HOOKUP_OBJECT (main_window, menuitem8_menu, "menuitem8_menu");
+  GLADE_HOOKUP_OBJECT (main_window, about2, "about2");
+  GLADE_HOOKUP_OBJECT (main_window, combobox1, "combobox1");
+  GLADE_HOOKUP_OBJECT (main_window, comboboxentry1, "comboboxentry1");
+  GLADE_HOOKUP_OBJECT (main_window, hscale1, "hscale1");
+  GLADE_HOOKUP_OBJECT (main_window, scrolledwindow1, "scrolledwindow1");
+  GLADE_HOOKUP_OBJECT (main_window, preview_treeview, "preview_treeview");
+  GLADE_HOOKUP_OBJECT (main_window, statusbar1, "statusbar1");
+  GLADE_HOOKUP_OBJECT (main_window, progressbar1, "progressbar1");
+  GLADE_HOOKUP_OBJECT (main_window, vseparator1, "vseparator1");
+  GLADE_HOOKUP_OBJECT (main_window, frame1, "frame1");
+  GLADE_HOOKUP_OBJECT (main_window, vbox3, "vbox3");
+  GLADE_HOOKUP_OBJECT (main_window, radiobutton1, "radiobutton1");
+  GLADE_HOOKUP_OBJECT (main_window, radiobutton2, "radiobutton2");
+  GLADE_HOOKUP_OBJECT (main_window, radiobutton3, "radiobutton3");
+  GLADE_HOOKUP_OBJECT (main_window, label6, "label6");
+  GLADE_HOOKUP_OBJECT (main_window, label4, "label4");
+  GLADE_HOOKUP_OBJECT (main_window, scrolledwindow2, "scrolledwindow2");
+  GLADE_HOOKUP_OBJECT (main_window, textview1, "textview1");
+  GLADE_HOOKUP_OBJECT (main_window, label5, "label5");
+  GLADE_HOOKUP_OBJECT (main_window, vbox5, "vbox5");
+  GLADE_HOOKUP_OBJECT (main_window, hbox4, "hbox4");
+  GLADE_HOOKUP_OBJECT (main_window, about_label, "about_label");
+  GLADE_HOOKUP_OBJECT (main_window, label666, "label666");
+  GLADE_HOOKUP_OBJECT (main_window, label670, "label670");
+  GLADE_HOOKUP_OBJECT_NO_REF (main_window, tooltips, "tooltips");
+
+  gtk_widget_grab_default (main_themelist);
+  gtk_window_add_accel_group (GTK_WINDOW (main_window), accel_group);
+
+  return main_window;
+}
+
diff --git a/src/gtk2-prefs/interface.h b/src/gtk2-prefs/interface.h
new file mode 100644
index 00000000..11c79152
--- /dev/null
+++ b/src/gtk2-prefs/interface.h
@@ -0,0 +1,5 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+GtkWidget* create_main_window (void);
diff --git a/src/gtk2-prefs/main.cpp b/src/gtk2-prefs/main.cpp
new file mode 100644
index 00000000..42e425c2
--- /dev/null
+++ b/src/gtk2-prefs/main.cpp
@@ -0,0 +1,616 @@
+/***************************************************************************
+                          main.cpp  -  description
+                             -------------------
+    begin                : Wed Jan  1 19:06:46 GMT+4 2003
+    copyright            : (C) 2003 - 2005 by Alex Shaduri
+    email                : ashaduri '@' gmail.com
+ ***************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <sstream>
+#include <gtk/gtk.h>
+
+#ifdef _WIN32
+#include "win32util.h"
+#include <io.h>
+#else
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "interface.h"
+#include "callbacks.h"
+#include "support.h"
+
+#include "main.h"
+
+
+// ------------------------------------------------------
+
+
+
+GtkWidget* g_main_window = 0;
+// GtkWidget* g_fontsel_dialog = 0;
+
+
+static std::string s_tmp_file;
+
+
+
+// ------------------------------------------------------
+
+
+
+static std::string gchar_to_string(gchar* gstr)
+{
+	std::string str = (gstr ? gstr : "");
+	g_free(gstr);
+	return str;
+}
+
+
+
+std::string get_home_dir()
+{
+	std::string dir;
+
+	if (g_get_home_dir())
+		dir = g_get_home_dir();
+
+#ifdef _WIN32
+	if (dir == "") {
+		dir = win32_get_registry_value_string(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Personal");
+	}
+	if (dir == "") {
+		dir = win32_get_registry_value_string(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "User");
+	}
+#endif
+
+	return dir;
+
+}
+
+
+
+
+// ------------------------------------------------------
+
+
+static std::string s_orig_theme;
+static std::string s_orig_font;
+
+std::string& get_orig_theme()
+{
+	return s_orig_theme;
+}
+
+
+std::string& get_orig_font()
+{
+	return s_orig_font;
+}
+
+
+// ------------------------------------------------------
+
+
+std::string get_current_theme()
+{
+
+	GtkSettings* settings = gtk_settings_get_default();
+	gchar* theme;
+	g_object_get(settings, "gtk-theme-name", &theme, NULL);
+
+	return gchar_to_string(theme);
+}
+
+
+
+
+std::string get_current_font()
+{
+	return gchar_to_string(pango_font_description_to_string(gtk_rc_get_style(g_main_window)->font_desc));
+}
+
+
+
+// ------------------------------------------------------
+
+
+
+std::string get_selected_theme()
+{
+	GtkTreeView* treeview = GTK_TREE_VIEW(lookup_widget(g_main_window, "main_themelist"));
+	GtkTreeModel* model = gtk_tree_view_get_model(treeview);
+	GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
+
+	GtkTreeIter iter;
+	gtk_tree_selection_get_selected(selection, 0, &iter);
+
+	gchar* theme_name;
+	gtk_tree_model_get(model, &iter, 0, &theme_name, -1);
+// 	std::cout << theme_name << "\n";
+	return gchar_to_string(theme_name);
+}
+
+
+
+std::string get_selected_font()
+{
+// 	GtkWidget* fontentry = lookup_widget(g_main_window, "main_fontentry");
+// 	return gtk_entry_get_text(GTK_ENTRY(fontentry));
+
+	bool default_font = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(g_main_window, "main_use_default_font_radio")));
+
+	if (default_font)
+		return "";
+
+	GtkWidget* fontbutton = lookup_widget(g_main_window, "main_font_selector_button");
+	return gtk_font_button_get_font_name(GTK_FONT_BUTTON(fontbutton));
+}
+
+
+// ------------------------------------------------------
+
+
+
+static void themelist_selection_changed_cb(GtkTreeSelection* selection, gpointer data)
+{
+	if (gtk_tree_selection_get_selected (selection, 0, 0))
+		apply_theme(get_selected_theme(), get_current_font());
+}
+
+
+
+// ------------------------------------------------------
+
+
+
+static void populate_with_themes(GtkWidget* w)
+{
+
+	std::string search_path = gchar_to_string(gtk_rc_get_theme_dir());
+	//std::string search_path = gchar_to_string(g_build_filename("lib", "gtk-2.0", "2.10.0", "engines", NULL));
+
+	if (search_path.size() && search_path[search_path.size() -1] != G_DIR_SEPARATOR)
+		search_path += G_DIR_SEPARATOR_S;
+
+	GDir* gdir = g_dir_open(search_path.c_str(), 0, NULL);
+	if (gdir == NULL)
+		return;
+
+
+	char* name;
+	GList* glist = 0;
+
+	while ( (name = const_cast<char*>(g_dir_read_name(gdir))) != NULL ) {
+		std::string filename = name;
+
+//		if (g_ascii_strup(fname.c_str(), -1) == "Default")
+//			continue;
+
+		std::string fullname = search_path + filename;
+		std::string rc = fullname; rc += G_DIR_SEPARATOR_S; rc += "gtk-2.0"; rc += G_DIR_SEPARATOR_S; rc += "gtkrc";
+
+		bool is_dir = 0;
+		if (g_file_test(fullname.c_str(), G_FILE_TEST_IS_DIR))
+			is_dir = 1;
+
+		if (is_dir && g_file_test(rc.c_str(), G_FILE_TEST_IS_REGULAR)) {
+			glist = g_list_insert_sorted(glist, g_strdup(filename.c_str()), (GCompareFunc)strcmp);
+		}
+	}
+
+	g_dir_close(gdir);
+
+
+
+
+	// ---------------- tree
+
+
+	GtkTreeView* treeview = GTK_TREE_VIEW(w);
+	GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);
+	gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(store));
+
+	GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes (
+												"Theme", gtk_cell_renderer_text_new(),
+												"text", 0,
+												NULL);
+	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+
+	GtkTreeIter   iter;
+
+	int i =0, curr=0;
+	while (char* theme = (char*)g_list_nth_data(glist, i)) {
+		gtk_list_store_append (store, &iter);
+		gtk_list_store_set (store, &iter, 0, theme, -1);
+
+		if (strcmp(theme, get_current_theme().c_str()) == 0) {
+			curr = i;
+		}
+
+		++i;
+	}
+
+
+	GtkTreeSelection* selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+	// set the default theme
+
+	// THIS IS IMPORTANT!!!
+	gtk_widget_grab_focus(w);
+
+	std::stringstream str;
+	str << curr;
+	GtkTreePath* selpath = gtk_tree_path_new_from_string (str.str().c_str());
+	if (selpath) {
+		gtk_tree_selection_select_path(selection, selpath);
+		gtk_tree_view_scroll_to_cell(treeview, selpath, NULL, true, 0.5, 0.0);
+		gtk_tree_path_free(selpath);
+	}
+
+	g_signal_connect (G_OBJECT (selection), "changed",
+                  G_CALLBACK (themelist_selection_changed_cb), NULL);
+
+	g_object_unref (G_OBJECT (store));
+
+
+	// ---------------- font
+
+// 	GtkWidget* fontentry = lookup_widget(g_main_window, "main_fontentry");
+// 	gtk_entry_set_text(GTK_ENTRY(fontentry), get_current_font().c_str());
+
+	GtkWidget* fontbutton = lookup_widget(g_main_window, "main_font_selector_button");
+	gtk_font_button_set_font_name(GTK_FONT_BUTTON(fontbutton), get_current_font().c_str());
+
+
+}
+
+
+
+
+// ------------------------------------------------------
+
+#ifdef _WIN32
+static void redirect_to_file (const gchar* log_domain, GLogLevelFlags log_level,
+									const gchar* message, gpointer user_data)
+{
+	/* only write logs if running in portable mode, otherwise
+	   we would get a permission error in program files */
+	if ((_access( "portable-mode", 0 )) != -1)
+	{
+		std::fstream f;
+		f.open("gtk2-prefs.log", std::ios::app);
+		f << message << "\n";
+		f.close();
+	}
+}
+#endif
+
+// ------------------------------------------------------
+
+
+
+
+int main(int argc, char *argv[])
+{
+
+	// work around pango weirdness
+#ifdef _WIN32
+	// no longer needed as of pango 1.2.5, but won't do any harm
+// 	putenv("PANGO_WIN32_NO_UNISCRIBE=1");
+#endif
+
+
+
+
+	std::string user = g_get_user_name();
+	std::string tmp = g_get_tmp_dir();
+	std::string tmp_file = tmp + G_DIR_SEPARATOR_S + "gtk_prefs_tmprc_" + user;
+	s_tmp_file = tmp_file;
+	gtk_rc_add_default_file(tmp_file.c_str());
+
+
+
+	gtk_init (&argc, &argv);
+
+	// redirect gtk warnings to file when in win32
+#if defined _WIN32 && !defined DEBUG
+	g_log_set_handler ("GLib", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
+                     | G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
+	g_log_set_handler ("GModule", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
+                     | G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
+	g_log_set_handler ("GLib-GObject", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
+                     | G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
+	g_log_set_handler ("GThread", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
+                     | G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
+	g_log_set_handler ("Gtk", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
+                     | G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
+	g_log_set_handler ("Gdk", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
+                     | G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
+	g_log_set_handler ("GdkPixbuf", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
+                     | G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
+#endif
+
+
+	add_pixmap_directory(".");
+
+	g_main_window = create_main_window();
+
+
+	populate_with_themes(lookup_widget(g_main_window, "main_themelist"));
+
+
+	std::string about_text = std::string("GTK+ Preference Tool") + "\n\
+\n\
+by Alex Shaduri <ashaduri@gmail.com>\n\
+\n\
+  The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose.  This software is provided \"AS IS\", and you, its user, assume the entire risk as to its quality and accuracy.\n\
+\n\
+  This is free software, and you are welcome to redistribute it under terms of GNU General Public License v2.";
+
+
+	gtk_label_set_text(GTK_LABEL(lookup_widget(g_main_window, "about_label")), about_text.c_str());
+
+
+	GtkTreeView* treeview = GTK_TREE_VIEW(lookup_widget(g_main_window, "preview_treeview"));
+	GtkTreeStore *store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
+	gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(store));
+
+
+	GtkTreeViewColumn* column1 = gtk_tree_view_column_new_with_attributes ("Text", gtk_cell_renderer_text_new(), "text", 0, NULL);
+	gtk_tree_view_column_set_sizing(column1, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
+	gtk_tree_view_column_set_resizable(column1, true);
+	gtk_tree_view_column_set_reorderable (column1, true);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column1);
+
+	GtkTreeViewColumn* column2 = gtk_tree_view_column_new_with_attributes ("Number", gtk_cell_renderer_text_new(), "text", 1, NULL);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column2);
+
+
+	GtkTreeIter   iter1, iter2;
+
+	gtk_tree_store_append (store, &iter1, NULL);
+	gtk_tree_store_set (store, &iter1, 0, "Parent 2", 1, 66, -1);
+
+	gtk_tree_store_append (store, &iter1, NULL);
+	gtk_tree_store_set (store, &iter1, 0, "Parent 1", 1, 65, -1);
+
+	gtk_tree_store_append (store, &iter2, &iter1);
+	gtk_tree_store_set (store, &iter2, 0, "Child 1", 1, 67, -1);
+
+	gtk_tree_view_column_set_sort_column_id(column1, 0);
+	gtk_tree_view_column_set_sort_order (column1, GTK_SORT_ASCENDING);
+	gtk_tree_view_column_set_sort_indicator(column1, true);
+	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), 0, GTK_SORT_ASCENDING);
+
+	g_object_unref (G_OBJECT (store));
+
+
+	get_orig_theme() = get_current_theme();
+	get_orig_font() = get_current_font();
+
+
+	gtk_widget_show (g_main_window);
+
+
+	gtk_main();
+
+	return EXIT_SUCCESS;
+
+}
+
+
+
+// -------------------------------
+
+
+
+void set_theme(const std::string& theme_name, const std::string& font)
+{
+	// set widgets accordingly
+
+	// tree
+	GtkTreeView* treeview = GTK_TREE_VIEW(lookup_widget(g_main_window, "main_themelist"));
+	GtkTreeModel* model = gtk_tree_view_get_model(treeview);
+	GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
+
+	GtkTreeIter iter;
+	gtk_tree_model_get_iter_first(model, &iter);
+
+	while(gtk_tree_model_iter_next(model, &iter)) {
+
+		gchar* text;
+		gtk_tree_model_get (model, &iter, 0, &text, -1);
+		std::string theme = gchar_to_string(text);
+
+		if (theme_name == theme) {
+			gtk_tree_selection_select_iter(selection, &iter);
+			break;
+		}
+
+	}
+
+
+	// font
+// 	GtkWidget* fontentry = lookup_widget(g_main_window, "main_fontentry");
+// 	gtk_entry_set_text(GTK_ENTRY(fontentry), font.c_str());
+
+	if (font != "") {
+		GtkWidget* fontbutton = lookup_widget(g_main_window, "main_font_selector_button");
+		gtk_font_button_set_font_name(GTK_FONT_BUTTON(fontbutton), get_current_font().c_str());
+	}
+
+
+	apply_theme(get_selected_theme(), get_selected_font());
+
+}
+
+
+
+
+void apply_theme(const std::string& theme_name, const std::string& font)
+{
+
+	std::stringstream strstr;
+	strstr << "gtk-theme-name = \"" << theme_name << "\"\n";
+
+	if (font != "")
+		strstr << "style \"user-font\"\n{\nfont_name=\"" << font << "\"\n}\nwidget_class \"*\" style \"user-font\"";
+
+// 	std::cout << strstr.str() << "\n\n\n";
+	std::fstream f;
+	f.open(s_tmp_file.c_str(), std::ios::out);
+		f << strstr.str();
+	f.close();
+
+
+	GtkSettings* settings = gtk_settings_get_default();
+
+  	gtk_rc_reparse_all_for_settings (settings, true);
+// 	gtk_rc_parse_string(strstr.str().c_str());
+//  	gtk_rc_parse("/root/.gtk-tmp");
+//  	gtk_rc_reset_styles(settings);
+
+	unlink(s_tmp_file.c_str());
+
+	while (gtk_events_pending())
+		gtk_main_iteration();
+
+
+}
+
+
+
+
+#ifdef _WIN32
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#define mkdir(a) _mkdir(a)
+#else
+#define mkdir(a, b) mkdir(a)
+#endif
+#endif
+
+
+bool save_current_theme()
+{
+
+	std::string conf_file = "";
+
+	if ((_access( "portable-mode", 0 )) != -1) {
+
+		char* themes_dir_c = gtk_rc_get_theme_dir();
+		char* conf_file_c = g_build_filename("etc", "gtk-2.0", "gtkrc", NULL);
+
+		conf_file = (conf_file_c ? conf_file_c : "");
+
+		// file doesn't exist, try to get it from gtk.
+		if (!g_file_test(conf_file.c_str(), G_FILE_TEST_EXISTS)) {
+
+			gchar** rc_files = gtk_rc_get_default_files();
+			if (rc_files[0] != 0) {
+				conf_file = rc_files[0];
+			}
+
+		}
+
+
+		g_free(themes_dir_c);
+		g_free(conf_file_c);
+
+
+		// mkdir a directory, only one level deep
+		char* etc = g_path_get_dirname(conf_file.c_str());
+		if (!g_file_test(etc, G_FILE_TEST_IS_DIR)) {
+			mkdir(etc, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+		}
+		g_free(etc);
+
+
+	} else {
+
+		conf_file = get_home_dir();
+
+		if (conf_file[conf_file.length()-1] != G_DIR_SEPARATOR)
+			conf_file += G_DIR_SEPARATOR_S;
+
+		conf_file += ".gtkrc-2.0";
+
+	}
+
+
+
+	// ask
+
+	GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+	GtkWidget* dialog = gtk_dialog_new_with_buttons ("Query", GTK_WINDOW(window),
+											GtkDialogFlags(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL),
+											GTK_STOCK_NO, GTK_RESPONSE_REJECT,
+											GTK_STOCK_YES, GTK_RESPONSE_ACCEPT,
+											NULL);
+	gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
+	GtkWidget* hbox = gtk_hbox_new(1, 1);
+	gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
+
+	gtk_container_add (GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
+	gtk_container_add (GTK_CONTAINER(hbox),
+			gtk_label_new((std::string("\n\nThe file \"") + conf_file +  "\" will be overwritten.\nAre you sure?\n\n").c_str()));
+
+	gtk_widget_show_all (dialog);
+
+	bool ret = 0;
+	gint result = gtk_dialog_run (GTK_DIALOG (dialog));
+	switch (result) {
+		case GTK_RESPONSE_ACCEPT:
+			ret = 1;
+			break;
+	}
+	gtk_widget_destroy(dialog);
+	gtk_widget_destroy(window);
+
+	if (!ret)  // the user pressed "No".
+		return false;
+
+
+	std::string font = get_selected_font();
+
+	std::fstream f;
+	f.open(conf_file.c_str(), std::ios::out);
+		f << "# Auto-written by gtk2_prefs. Do not edit.\n\n";
+		f << "gtk-theme-name = \"" << get_selected_theme() << "\"\n";
+
+		if (font != "")
+			f << "style \"user-font\"\n{\n\tfont_name=\"" << font << "\"\n}\nwidget_class \"*\" style \"user-font\"";
+	f.close();
+
+
+	return true;
+
+}
+
+
+
+
+void program_shutdown()
+{
+	gtk_main_quit();
+}
+
+
+
+
+
diff --git a/src/gtk2-prefs/main.h b/src/gtk2-prefs/main.h
new file mode 100644
index 00000000..ab4e5cbd
--- /dev/null
+++ b/src/gtk2-prefs/main.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+                          main.cpp  -  description
+                             -------------------
+    begin                : Wed Jan  1 2003
+    copyright            : (C) 2003 - 2005 by Alex Shaduri
+    email                : ashaduri '@' gmail.com
+ ***************************************************************************/
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+
+#include <string>
+
+
+std::string& get_orig_theme();
+std::string& get_orig_font();
+
+std::string get_current_theme();
+std::string get_current_font();
+
+std::string get_selected_theme();
+std::string get_selected_font();
+
+void set_theme(const std::string& theme_name, const std::string& font);
+void apply_theme(const std::string& theme_name, const std::string& font);
+bool save_current_theme();
+
+void program_shutdown();
+
+
+#endif
diff --git a/src/gtk2-prefs/makefile.mak b/src/gtk2-prefs/makefile.mak
new file mode 100644
index 00000000..1eeeb565
--- /dev/null
+++ b/src/gtk2-prefs/makefile.mak
@@ -0,0 +1,24 @@
+include "..\makeinc.mak"
+
+TARGET = gtk2-prefs.exe
+
+PREF_OBJECTS = \
+callbacks.obj \
+interface.obj \
+support.obj \
+win32util.obj \
+main.obj
+
+CPPFLAGS = $(CPPFLAGS) /D_STL70_ /D_STATIC_CPPLIB /EHsc /DHAVE_CONFIG_H
+
+all: $(PREF_OBJECTS) $(TARGET)
+
+.cpp.obj:
+	$(CC) $(CPPFLAGS) $(GLIB) $(GTK) /I. /c $<
+	
+$(TARGET): $(PREF_OBJECTS)
+	$(LINK) /out:$(TARGET) /entry:mainCRTStartup $(LDFLAGS) $(PREF_OBJECTS) ntstc_msvcrt.lib $(LIBS)
+
+clean:
+	del $(TARGET)
+	del *.obj
diff --git a/src/gtk2-prefs/support.cpp b/src/gtk2-prefs/support.cpp
new file mode 100644
index 00000000..bb19f284
--- /dev/null
+++ b/src/gtk2-prefs/support.cpp
@@ -0,0 +1,146 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+
+#include "support.h"
+
+GtkWidget*
+lookup_widget                          (GtkWidget       *widget,
+                                        const gchar     *widget_name)
+{
+  GtkWidget *parent, *found_widget;
+
+  for (;;)
+    {
+      if (GTK_IS_MENU (widget))
+        parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
+      else
+        parent = widget->parent;
+      if (!parent)
+        parent = (GtkWidget*)g_object_get_data (G_OBJECT (widget), "GladeParentKey");
+      if (parent == NULL)
+        break;
+      widget = parent;
+    }
+
+  found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget),
+                                                 widget_name);
+  if (!found_widget)
+    g_warning ("Widget not found: %s", widget_name);
+  return found_widget;
+}
+
+static GList *pixmaps_directories = NULL;
+
+/* Use this function to set the directory containing installed pixmaps. */
+void
+add_pixmap_directory                   (const gchar     *directory)
+{
+  pixmaps_directories = g_list_prepend (pixmaps_directories,
+                                        g_strdup (directory));
+}
+
+/* This is an internally used function to find pixmap files. */
+static gchar*
+find_pixmap_file                       (const gchar     *filename)
+{
+  GList *elem;
+
+  /* We step through each of the pixmaps directory to find it. */
+  elem = pixmaps_directories;
+  while (elem)
+    {
+      gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data,
+                                         G_DIR_SEPARATOR_S, filename);
+      if (g_file_test (pathname, G_FILE_TEST_EXISTS))
+        return pathname;
+      g_free (pathname);
+      elem = elem->next;
+    }
+  return NULL;
+}
+
+/* This is an internally used function to create pixmaps. */
+GtkWidget*
+create_pixmap                          (GtkWidget       *widget,
+                                        const gchar     *filename)
+{
+  gchar *pathname = NULL;
+  GtkWidget *pixmap;
+
+  if (!filename || !filename[0])
+      return gtk_image_new ();
+
+  pathname = find_pixmap_file (filename);
+
+  if (!pathname)
+    {
+      g_warning ("Couldn't find pixmap file: %s", filename);
+      return gtk_image_new ();
+    }
+
+  pixmap = gtk_image_new_from_file (pathname);
+  g_free (pathname);
+  return pixmap;
+}
+
+/* This is an internally used function to create pixmaps. */
+GdkPixbuf*
+create_pixbuf                          (const gchar     *filename)
+{
+  gchar *pathname = NULL;
+  GdkPixbuf *pixbuf;
+  GError *error = NULL;
+
+  if (!filename || !filename[0])
+      return NULL;
+
+  pathname = find_pixmap_file (filename);
+
+  if (!pathname)
+    {
+      g_warning ("Couldn't find pixmap file: %s", filename);
+      return NULL;
+    }
+
+  pixbuf = gdk_pixbuf_new_from_file (pathname, &error);
+  if (!pixbuf)
+    {
+      fprintf (stderr, "Failed to load pixbuf file: %s: %s\n",
+               pathname, error->message);
+      g_error_free (error);
+    }
+  g_free (pathname);
+  return pixbuf;
+}
+
+/* This is used to set ATK action descriptions. */
+void
+glade_set_atk_action_description       (AtkAction       *action,
+                                        const gchar     *action_name,
+                                        const gchar     *description)
+{
+  gint n_actions, i;
+
+  n_actions = atk_action_get_n_actions (action);
+  for (i = 0; i < n_actions; i++)
+    {
+      if (!strcmp (atk_action_get_name (action, i), action_name))
+        atk_action_set_description (action, i, description);
+    }
+}
+
diff --git a/src/gtk2-prefs/support.h b/src/gtk2-prefs/support.h
new file mode 100644
index 00000000..2dea079c
--- /dev/null
+++ b/src/gtk2-prefs/support.h
@@ -0,0 +1,44 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+/*
+ * Public Functions.
+ */
+
+/*
+ * This function returns a widget in a component created by Glade.
+ * Call it with the toplevel widget in the component (i.e. a window/dialog),
+ * or alternatively any widget in the component, and the name of the widget
+ * you want returned.
+ */
+GtkWidget*  lookup_widget              (GtkWidget       *widget,
+                                        const gchar     *widget_name);
+
+
+/* Use this function to set the directory containing installed pixmaps. */
+void        add_pixmap_directory       (const gchar     *directory);
+
+
+/*
+ * Private Functions.
+ */
+
+/* This is used to create the pixmaps used in the interface. */
+GtkWidget*  create_pixmap              (GtkWidget       *widget,
+                                        const gchar     *filename);
+
+/* This is used to create the pixbufs used in the interface. */
+GdkPixbuf*  create_pixbuf              (const gchar     *filename);
+
+/* This is used to set ATK action descriptions. */
+void        glade_set_atk_action_description (AtkAction       *action,
+                                              const gchar     *action_name,
+                                              const gchar     *description);
+
diff --git a/src/gtk2-prefs/sys_win32.h b/src/gtk2-prefs/sys_win32.h
new file mode 100644
index 00000000..0a106690
--- /dev/null
+++ b/src/gtk2-prefs/sys_win32.h
@@ -0,0 +1,28 @@
+/***************************************************************************
+                          sys_win32.h  -  description
+                             -------------------
+    begin                : Wed Oct 22 2003
+    copyright            : (C) 2003 by Alex Shaduri, Irakli A. Elizbarashvili
+    email                : alex_sh@land.ru
+ ***************************************************************************/
+#ifndef SYS_WIN32_H
+#define SYS_WIN32_H
+
+
+
+
+
+#ifdef _WIN32
+
+#	define WIN32_LEAN_AND_MEAN
+#	include <windows.h>
+
+#endif
+
+
+
+
+
+
+
+#endif
diff --git a/src/gtk2-prefs/win32util.cpp b/src/gtk2-prefs/win32util.cpp
new file mode 100644
index 00000000..79cab17d
--- /dev/null
+++ b/src/gtk2-prefs/win32util.cpp
@@ -0,0 +1,80 @@
+/***************************************************************************
+                          win32util.cpp  -  description
+                             -------------------
+    begin                : Tue Jan 14 2003
+    copyright            : (C) 2003 by Alex Shaduri
+    email                : alex_sh@land.ru
+ ***************************************************************************/
+
+#ifdef _WIN32
+
+#include <string>
+#include "sys_win32.h"
+#include "win32util.h"
+
+
+
+
+
+std::string win32_get_registry_value_string(HKEY base, const std::string& keydir, const std::string& key)
+{
+
+	HKEY reg_key = NULL;
+	DWORD type;
+	DWORD nbytes;
+	char* result = NULL;
+//HKEY_CURRENT_USER
+	nbytes = 0;
+	if ( RegOpenKeyEx ( base, keydir.c_str(), 0, KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS
+			&& RegQueryValueEx (reg_key, key.c_str(), 0, &type, NULL, &nbytes) == ERROR_SUCCESS ) {
+		result = (char*)malloc(nbytes + 1);
+		RegQueryValueEx (reg_key,  key.c_str(), 0, &type, (BYTE*)result, &nbytes);
+		result[nbytes] = '\0';
+	}
+
+	if (reg_key != NULL)
+		RegCloseKey (reg_key);
+
+	std::string ret = "";
+
+	if (result) {
+		ret = result;
+	}
+
+	return ret;
+
+}
+
+
+
+
+void win32_set_registry_value_string(HKEY base, const std::string& keydir, const std::string& key, const std::string& value)
+{
+
+	HKEY reg_key = NULL;
+	DWORD nbytes;
+
+	nbytes = value.length() + 1;
+
+	if ( RegOpenKeyEx ( base, keydir.c_str(), 0, KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS) {
+		RegSetValueEx (reg_key,  key.c_str(), 0, REG_SZ, (const BYTE*)(value.c_str()), nbytes);
+	}
+
+	if (reg_key != NULL)
+		RegCloseKey (reg_key);
+
+}
+
+
+
+
+
+
+
+#endif
+
+
+
+
+
+
diff --git a/src/gtk2-prefs/win32util.h b/src/gtk2-prefs/win32util.h
new file mode 100644
index 00000000..8c194a19
--- /dev/null
+++ b/src/gtk2-prefs/win32util.h
@@ -0,0 +1,26 @@
+/***************************************************************************
+                          win32util.h  -  description
+                             -------------------
+    begin                : Tue Jan 14 2003
+    copyright            : (C) 2003 by Alex Shaduri
+    email                : alex_sh@land.ru
+ ***************************************************************************/
+#ifndef WIN32UTIL_H
+#define WIN32UTIL_H
+
+#ifdef _WIN32
+
+#include <string>
+#include "sys_win32.h"
+
+
+
+std::string win32_get_registry_value_string(HKEY base, const std::string& keydir, const std::string& key);
+void win32_set_registry_value_string(HKEY base, const std::string& keydir, const std::string& key, const std::string& value);
+
+
+
+
+#endif //_WIN32
+
+#endif // WIN32UTIL_H
diff --git a/src/makefile.mak b/src/makefile.mak
new file mode 100644
index 00000000..cd73b879
--- /dev/null
+++ b/src/makefile.mak
@@ -0,0 +1,23 @@
+all:
+	@cd pixmaps
+	@-$(MAKE) /nologo /s /f makefile.mak $@
+	@cd ..\common
+	@-$(MAKE) /nologo /s /f makefile.mak $@
+	@cd ..\fe-gtk
+	@-$(MAKE) /nologo /s /f makefile.mak $@
+	@cd ..\fe-text
+	@-$(MAKE) /nologo /s /f makefile.mak $@
+	@cd ..\gtk2-prefs
+	@-$(MAKE) /nologo /s /f makefile.mak $@
+
+clean:
+	@cd pixmaps
+	@-$(MAKE) /nologo /s /f makefile.mak clean $@
+	@cd ..\common
+	@-$(MAKE) /nologo /s /f makefile.mak clean $@
+	@cd ..\fe-gtk
+	@-$(MAKE) /nologo /s /f makefile.mak clean $@
+	@cd ..\fe-text
+	@-$(MAKE) /nologo /s /f makefile.mak clean $@
+	@cd ..\gtk2-prefs
+	@-$(MAKE) /nologo /s /f makefile.mak clean $@
diff --git a/src/makeinc.skel.mak b/src/makeinc.skel.mak
new file mode 100644
index 00000000..552b6a6e
--- /dev/null
+++ b/src/makeinc.skel.mak
@@ -0,0 +1,45 @@
+CC = cl
+LINK = link
+CFLAGS = $(CFLAGS) /Ox /c /MD /MP /W0 /nologo
+CFLAGS = $(CFLAGS) /DWIN32 /DG_DISABLE_CAST_CHECKS /DG_DISABLE_DEPRECATED /DGDK_PIXBUF_DISABLE_DEPRECATED /DGDK_DISABLE_DEPRECATED /DHAVE_STRTOULL /Dstrtoull=_strtoui64 /Dstrcasecmp=stricmp /Dstrncasecmp=strnicmp
+CFLAGS = $(CFLAGS) /I$(DEV)\include
+CPPFLAGS = /c /MD /W0 /nologo /DWIN32
+LDFLAGS = /subsystem:windows /nologo
+LIBS = $(LIBS) gdi32.lib shell32.lib user32.lib advapi32.lib imm32.lib ole32.lib winmm.lib ws2_32.lib wininet.lib comdlg32.lib libeay32.lib ssleay32.lib
+
+GLIB = /I$(DEV)\include\glib-2.0 /I$(DEV)\lib\glib-2.0\include /I$(DEV)\include\libxml2
+GTK = /I$(DEV)\include\gtk-2.0 /I$(DEV)\lib\gtk-2.0\include /I$(DEV)\include\atk-1.0 /I$(DEV)\include\cairo /I$(DEV)\include\pango-1.0 /I$(DEV)\include\gdk-pixbuf-2.0
+LIBS = $(LIBS) /libpath:$(DEV)\lib gtk-win32-2.0.lib gdk-win32-2.0.lib atk-1.0.lib gio-2.0.lib gdk_pixbuf-2.0.lib pangowin32-1.0.lib pangocairo-1.0.lib pango-1.0.lib cairo.lib gobject-2.0.lib gmodule-2.0.lib glib-2.0.lib intl.lib libxml2.lib
+#obs LIBS = $(LIBS) /libpath:$(DEV)\lib libgtk-win32-2.0-0.lib libgdk-win32-2.0-0.lib libatk-1.0-0.lib libgio-2.0-0.lib libgdk_pixbuf-2.0-0.lib libpangowin32-1.0-0.lib libpangocairo-1.0-0.lib libpango-1.0-0.lib libcairo-2.lib libgobject-2.0-0.lib libgmodule-2.0-0.lib libglib-2.0-0.lib libintl-8.lib libxml2-2.lib
+
+LUALIB = lua51
+LUAOUTPUT = xclua.dll
+
+PERL512LIB = perl512
+PERL512OUTPUT = xcperl-512.dll
+PERL514LIB = perl514
+PERL514OUTPUT = xcperl-514.dll
+
+PYTHONLIB = python27
+PYTHONOUTPUT = xcpython.dll
+
+TCLLIB = tcl85
+TCLOUTPUT = xctcl.dll
+
+!ifdef X64
+CFLAGS = $(CFLAGS) /favor:AMD64 /D_WIN64
+CPPFLAGS = $(CPPFLAGS) /favor:AMD64 /D_WIN64
+LDFLAGS = $(LDFLAGS) msvcrt_win2003.obj
+
+PERL512PATH = c:\mozilla-build\perl-5.12-x64
+PERL514PATH = c:\mozilla-build\perl-5.14-x64
+PYTHONPATH = c:\mozilla-build\python-2.7-x64
+TCLPATH = c:\mozilla-build\tcl-8.5-x64
+!else
+LDFLAGS = $(LDFLAGS) msvcrt_winxp.obj
+
+PERL512PATH = c:\mozilla-build\perl-5.12-x86
+PERL514PATH = c:\mozilla-build\perl-5.14-x86
+PYTHONPATH = c:\mozilla-build\python-2.7-x86
+TCLPATH = c:\mozilla-build\tcl-8.5-x86
+!endif
diff --git a/src/pixmaps/makefile.mak b/src/pixmaps/makefile.mak
new file mode 100644
index 00000000..f9535dbe
--- /dev/null
+++ b/src/pixmaps/makefile.mak
@@ -0,0 +1,18 @@
+CONV = gdk-pixbuf-csource
+
+LIST =	bookpng book.png \
+			hoppng hop.png \
+			oppng op.png \
+			purplepng purple.png \
+			redpng red.png \
+			trayfilepng fileoffer.png \
+			trayhilightpng highlight.png \
+			traymsgpng message.png \
+			voicepng voice.png \
+			xchatpng ..\..\xchat.png
+
+all: 
+	@$(CONV) --build-list $(LIST) > inline_pngs.h
+
+clean:
+	@del *.h
diff --git a/src/pixmaps/pixmaps.vcxproj b/src/pixmaps/pixmaps.vcxproj
new file mode 100644
index 00000000..ec33a49b
--- /dev/null
+++ b/src/pixmaps/pixmaps.vcxproj
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{626DA61C-FA8B-474C-B2F5-72AD9DFEE642}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>pixmaps</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+    <PostBuildEvent>

+      <Command>"$(DepsRoot)\bin\gdk-pixbuf-csource" --build-list $(Pixmaps) &gt; "$(SolutionDir)\..\src\pixmaps\inline_pngs.h"</Command>

+    </PostBuildEvent>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+    <PostBuildEvent>

+      <Command>"$(DepsRoot)\bin\gdk-pixbuf-csource" --build-list $(Pixmaps) &gt; "$(SolutionDir)\..\src\pixmaps\inline_pngs.h"</Command>

+    </PostBuildEvent>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <None Include="..\..\xchat.png" />

+    <None Include="book.png" />

+    <None Include="fileoffer.png" />

+    <None Include="highlight.png" />

+    <None Include="hop.png" />

+    <None Include="message.png" />

+    <None Include="op.png" />

+    <None Include="purple.png" />

+    <None Include="red.png" />

+    <None Include="voice.png" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/pixmaps/pixmaps.vcxproj.filters b/src/pixmaps/pixmaps.vcxproj.filters
new file mode 100644
index 00000000..aca4cd4b
--- /dev/null
+++ b/src/pixmaps/pixmaps.vcxproj.filters
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Resource Files">

+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>

+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="book.png">

+      <Filter>Resource Files</Filter>

+    </None>

+    <None Include="fileoffer.png">

+      <Filter>Resource Files</Filter>

+    </None>

+    <None Include="highlight.png">

+      <Filter>Resource Files</Filter>

+    </None>

+    <None Include="hop.png">

+      <Filter>Resource Files</Filter>

+    </None>

+    <None Include="message.png">

+      <Filter>Resource Files</Filter>

+    </None>

+    <None Include="op.png">

+      <Filter>Resource Files</Filter>

+    </None>

+    <None Include="purple.png">

+      <Filter>Resource Files</Filter>

+    </None>

+    <None Include="red.png">

+      <Filter>Resource Files</Filter>

+    </None>

+    <None Include="voice.png">

+      <Filter>Resource Files</Filter>

+    </None>

+    <None Include="..\..\xchat.png">

+      <Filter>Resource Files</Filter>

+    </None>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/pixmaps/pixmaps.vcxproj.user b/src/pixmaps/pixmaps.vcxproj.user
new file mode 100644
index 00000000..695b5c78
--- /dev/null
+++ b/src/pixmaps/pixmaps.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+</Project>
\ No newline at end of file
diff --git a/src/version-script b/src/version-script
index 048c1f55..4441aeae 100644
--- a/src/version-script
+++ b/src/version-script
@@ -30,5 +30,11 @@ EXPORTED {
 		xchat_send_modes;
 		xchat_strip;
 		xchat_free;
+		xchat_pluginpref_set_str;
+		xchat_pluginpref_get_str;
+		xchat_pluginpref_set_int;
+		xchat_pluginpref_get_int;
+		xchat_pluginpref_delete;
+		xchat_pluginpref_list;
 	local: *;
 };
diff --git a/src/version/version.c b/src/version/version.c
new file mode 100644
index 00000000..53af5675
--- /dev/null
+++ b/src/version/version.c
@@ -0,0 +1,143 @@
+/* XChat-WDK
+ * Copyright (c) 2011 Berke Viktor.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include "../../config.h"
+
+char *
+comma ()
+{
+	int major, minor;
+	char *version_string; /* nnnn,n,n,n format */
+
+	version_string = (char*) malloc (11);
+
+	if (sscanf (PACKAGE_VERSION, "%d-%d", &major, &minor) > 1)
+	{
+		sprintf (version_string, "%d,%d,0,0", major, minor);
+	} else
+	{
+		sprintf (version_string, "%d,0,0,0", major);
+	}
+
+	return version_string;
+}
+
+char *
+point ()
+{
+	int major1, major2, major3, major4, minor;
+	char *version_string; /* nn.nn.nn.nn format */
+
+	version_string = (char*) malloc (12);
+
+	if (sscanf (PACKAGE_VERSION, "%c%c%c%c-%d", &major1, &major2, &major3, &major4, &minor) > 4)
+	{
+		sprintf (version_string, "%c%c.%c%c.%d.0", major1, major2, major3, major4, minor);
+	} else
+	{
+		sprintf (version_string, "%c%c.%c%c.0.0", major1, major2, major3, major4);
+	}
+
+	return version_string;
+}
+
+int
+main (int argc, char *argv[])
+{
+	if (argc > 1)
+	{
+		if (!strcmp (argv[1], "-r"))			/* xchat.rc/FILEVERSION, PRODUCTVERSION */
+		{
+			printf ("#define COMMA_VERSION %s\n", comma ());
+		}
+		else if (!strcmp (argv[1], "-a"))	/* xchat-wdk.iss/AppVerName */
+		{
+#ifdef _WIN64
+			printf ("AppVerName=XChat-WDK %s (x64)\n", PACKAGE_VERSION);
+#else
+			printf ("AppVerName=XChat-WDK %s (x86)\n", PACKAGE_VERSION);
+#endif
+		}
+		else if (!strcmp (argv[1], "-v"))	/* xchat-wdk.iss/AppVersion */
+		{
+			printf ("AppVersion=%s\n", point ());
+		}
+		else if (!strcmp (argv[1], "-i"))	/* xchat-wdk.iss/VersionInfoVersion */
+		{
+			printf ("VersionInfoVersion=%s\n", point ());
+		}
+		else if (!strcmp (argv[1], "-o"))	/* xchat-wdk.iss/OutputBaseFilename */
+		{
+#ifdef _WIN64
+			printf ("OutputBaseFilename=XChat-WDK %s x64\n", PACKAGE_VERSION);
+#else
+			printf ("OutputBaseFilename=XChat-WDK %s x86\n", PACKAGE_VERSION);
+#endif
+		}
+		else if (!strcmp (argv[1], "-v"))	/* version.txt */
+		{
+			printf ("%s", PACKAGE_VERSION);
+		} else
+		{
+			printf ("usage:\n\t-a\txchat-wdk.iss/AppVerName\n\t-i\txchat-wdk.iss/VersionInfoVersion\n\t-o\txchat-wdk.iss/OutputBaseFilename\n\t-r\txchat.rc/FILEVERSION, PRODUCTVERSION\n\t-v\txchat-wdk.iss/AppVersion\n");
+		}
+	} else
+	{
+		printf ("usage:\n\t-a\txchat-wdk.iss/AppVerName\n\t-i\txchat-wdk.iss/VersionInfoVersion\n\t-o\txchat-wdk.iss/OutputBaseFilename\n\t-r\txchat.rc/FILEVERSION, PRODUCTVERSION\n\t-v\txchat-wdk.iss/AppVersion\n");
+	}
+
+#if 0 /* ugly hack */
+	switch ((int) argv[1][0])
+	{
+		case 'r':	/* xchat.rc/FILEVERSION, PRODUCTVERSION*/
+			printf ("#define COMMA_VERSION \"%s\"\n", comma ());
+			break;
+		case 'a':	/* xchat-wdk.iss/AppVerName */
+			printf ("AppVerName=XChat-WDK %s\n", PACKAGE_VERSION);
+			break;
+		case 'v':	/* xchat-wdk.iss/AppVersion */
+			printf ("AppVersion=%s\n", point ());
+			break;
+		case 'i':	/* xchat-wdk.iss/VersionInfoVersion */
+			printf ("VersionInfoVersion=%s\n", point ());
+			break;
+		case 'o':	/* xchat-wdk.iss/OutputBaseFilename */
+			printf ("OutputBaseFilename=XChat-WDK %s\n", PACKAGE_VERSION);
+			break;
+		case 'u':	/* version.txt */
+			printf ("%s", PACKAGE_VERSION);
+			break;
+		default:
+			printf ("use a, i, o, r or v.\n");
+			break;
+	}
+#endif
+
+	return 0;
+}
diff --git a/src/version/version.vcxproj b/src/version/version.vcxproj
new file mode 100644
index 00000000..5a4fe5cc
--- /dev/null
+++ b/src/version/version.vcxproj
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{6CD3647E-4541-4849-9DD7-C8816665AE42}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>version</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>MultiByte</CharacterSet>

+    <PlatformToolset>WDK7</PlatformToolset>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\win32\xchat.props" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir>

+    <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level1</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+    <PostBuildEvent>

+      <Command>"$(OutDir)\$(TargetName)$(TargetExt)" -r &gt; "$(SolutionDir)\..\resource.h"</Command>

+    </PostBuildEvent>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level1</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;_WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+    <PostBuildEvent>

+      <Command>"$(OutDir)\$(TargetName)$(TargetExt)" -r &gt; "$(SolutionDir)\..\resource.h"</Command>

+    </PostBuildEvent>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClCompile Include="version.c" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/version/version.vcxproj.filters b/src/version/version.vcxproj.filters
new file mode 100644
index 00000000..decec7d0
--- /dev/null
+++ b/src/version/version.vcxproj.filters
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="version.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/version/version.vcxproj.user b/src/version/version.vcxproj.user
new file mode 100644
index 00000000..695b5c78
--- /dev/null
+++ b/src/version/version.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+</Project>
\ No newline at end of file
diff --git a/src/xtm/Main.Designer.cs b/src/xtm/Main.Designer.cs
new file mode 100644
index 00000000..6a7c9cf1
--- /dev/null
+++ b/src/xtm/Main.Designer.cs
@@ -0,0 +1,316 @@
+namespace thememan
+{
+    partial class XTM
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(XTM));

+            this.themelist = new System.Windows.Forms.ListBox();

+            this.themecolor0 = new System.Windows.Forms.Label();

+            this.themecolor1 = new System.Windows.Forms.Label();

+            this.themecolor2 = new System.Windows.Forms.Label();

+            this.themecolor3 = new System.Windows.Forms.Label();

+            this.themecolor4 = new System.Windows.Forms.Label();

+            this.themecolor5 = new System.Windows.Forms.Label();

+            this.themecolor6 = new System.Windows.Forms.Label();

+            this.themecolor7 = new System.Windows.Forms.Label();

+            this.themecolor8 = new System.Windows.Forms.Label();

+            this.themecolor9 = new System.Windows.Forms.Label();

+            this.themecolora = new System.Windows.Forms.Label();

+            this.themecolorb = new System.Windows.Forms.Label();

+            this.themecolorc = new System.Windows.Forms.Label();

+            this.themecolord = new System.Windows.Forms.Label();

+            this.themecolore = new System.Windows.Forms.Label();

+            this.themecolorf = new System.Windows.Forms.Label();

+            this.themecolorfg = new System.Windows.Forms.Label();

+            this.themecolortextbg = new System.Windows.Forms.Label();

+            this.importbutton = new System.Windows.Forms.Button();

+            this.applybutton = new System.Windows.Forms.Button();

+            this.themecolorfgmarked = new System.Windows.Forms.Label();

+            this.deleteButton = new System.Windows.Forms.Button();

+            this.SuspendLayout();

+            // 

+            // themelist

+            // 

+            this.themelist.FormattingEnabled = true;

+            this.themelist.Location = new System.Drawing.Point(12, 12);

+            this.themelist.Name = "themelist";

+            this.themelist.Size = new System.Drawing.Size(160, 199);

+            this.themelist.TabIndex = 0;

+            this.themelist.SelectedIndexChanged += new System.EventHandler(this.theme_selected);

+            // 

+            // themecolor0

+            // 

+            this.themecolor0.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolor0.Location = new System.Drawing.Point(189, 36);

+            this.themecolor0.Name = "themecolor0";

+            this.themecolor0.Size = new System.Drawing.Size(40, 40);

+            this.themecolor0.TabIndex = 6;

+            // 

+            // themecolor1

+            // 

+            this.themecolor1.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolor1.Location = new System.Drawing.Point(239, 36);

+            this.themecolor1.Name = "themecolor1";

+            this.themecolor1.Size = new System.Drawing.Size(40, 40);

+            this.themecolor1.TabIndex = 10;

+            // 

+            // themecolor2

+            // 

+            this.themecolor2.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolor2.Location = new System.Drawing.Point(289, 36);

+            this.themecolor2.Name = "themecolor2";

+            this.themecolor2.Size = new System.Drawing.Size(40, 40);

+            this.themecolor2.TabIndex = 14;

+            // 

+            // themecolor3

+            // 

+            this.themecolor3.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolor3.Location = new System.Drawing.Point(339, 36);

+            this.themecolor3.Name = "themecolor3";

+            this.themecolor3.Size = new System.Drawing.Size(40, 40);

+            this.themecolor3.TabIndex = 18;

+            // 

+            // themecolor4

+            // 

+            this.themecolor4.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolor4.Location = new System.Drawing.Point(189, 87);

+            this.themecolor4.Name = "themecolor4";

+            this.themecolor4.Size = new System.Drawing.Size(40, 40);

+            this.themecolor4.TabIndex = 4;

+            // 

+            // themecolor5

+            // 

+            this.themecolor5.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolor5.Location = new System.Drawing.Point(239, 87);

+            this.themecolor5.Name = "themecolor5";

+            this.themecolor5.Size = new System.Drawing.Size(40, 40);

+            this.themecolor5.TabIndex = 8;

+            // 

+            // themecolor6

+            // 

+            this.themecolor6.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolor6.Location = new System.Drawing.Point(289, 87);

+            this.themecolor6.Name = "themecolor6";

+            this.themecolor6.Size = new System.Drawing.Size(40, 40);

+            this.themecolor6.TabIndex = 12;

+            // 

+            // themecolor7

+            // 

+            this.themecolor7.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolor7.Location = new System.Drawing.Point(339, 87);

+            this.themecolor7.Name = "themecolor7";

+            this.themecolor7.Size = new System.Drawing.Size(40, 40);

+            this.themecolor7.TabIndex = 16;

+            // 

+            // themecolor8

+            // 

+            this.themecolor8.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolor8.Location = new System.Drawing.Point(189, 138);

+            this.themecolor8.Name = "themecolor8";

+            this.themecolor8.Size = new System.Drawing.Size(40, 40);

+            this.themecolor8.TabIndex = 5;

+            // 

+            // themecolor9

+            // 

+            this.themecolor9.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolor9.Location = new System.Drawing.Point(239, 138);

+            this.themecolor9.Name = "themecolor9";

+            this.themecolor9.Size = new System.Drawing.Size(40, 40);

+            this.themecolor9.TabIndex = 9;

+            // 

+            // themecolora

+            // 

+            this.themecolora.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolora.Location = new System.Drawing.Point(289, 138);

+            this.themecolora.Name = "themecolora";

+            this.themecolora.Size = new System.Drawing.Size(40, 40);

+            this.themecolora.TabIndex = 13;

+            // 

+            // themecolorb

+            // 

+            this.themecolorb.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolorb.Location = new System.Drawing.Point(339, 138);

+            this.themecolorb.Name = "themecolorb";

+            this.themecolorb.Size = new System.Drawing.Size(40, 40);

+            this.themecolorb.TabIndex = 17;

+            // 

+            // themecolorc

+            // 

+            this.themecolorc.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolorc.Location = new System.Drawing.Point(189, 189);

+            this.themecolorc.Name = "themecolorc";

+            this.themecolorc.Size = new System.Drawing.Size(40, 40);

+            this.themecolorc.TabIndex = 7;

+            // 

+            // themecolord

+            // 

+            this.themecolord.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolord.Location = new System.Drawing.Point(239, 189);

+            this.themecolord.Name = "themecolord";

+            this.themecolord.Size = new System.Drawing.Size(40, 40);

+            this.themecolord.TabIndex = 11;

+            // 

+            // themecolore

+            // 

+            this.themecolore.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolore.Location = new System.Drawing.Point(289, 189);

+            this.themecolore.Name = "themecolore";

+            this.themecolore.Size = new System.Drawing.Size(40, 40);

+            this.themecolore.TabIndex = 15;

+            // 

+            // themecolorf

+            // 

+            this.themecolorf.BackColor = System.Drawing.SystemColors.HotTrack;

+            this.themecolorf.Location = new System.Drawing.Point(339, 189);

+            this.themecolorf.Name = "themecolorf";

+            this.themecolorf.Size = new System.Drawing.Size(40, 40);

+            this.themecolorf.TabIndex = 19;

+            // 

+            // themecolorfg

+            // 

+            this.themecolorfg.AutoSize = true;

+            this.themecolorfg.BackColor = System.Drawing.Color.Transparent;

+            this.themecolorfg.Location = new System.Drawing.Point(190, 18);

+            this.themecolorfg.Name = "themecolorfg";

+            this.themecolorfg.Size = new System.Drawing.Size(66, 13);

+            this.themecolorfg.TabIndex = 21;

+            this.themecolorfg.Text = "Sample Text";

+            // 

+            // themecolortextbg

+            // 

+            this.themecolortextbg.Location = new System.Drawing.Point(180, 15);

+            this.themecolortextbg.Name = "themecolortextbg";

+            this.themecolortextbg.Size = new System.Drawing.Size(208, 223);

+            this.themecolortextbg.TabIndex = 20;

+            // 

+            // importbutton

+            // 

+            this.importbutton.Location = new System.Drawing.Point(12, 217);

+            this.importbutton.Name = "importbutton";

+            this.importbutton.Size = new System.Drawing.Size(52, 23);

+            this.importbutton.TabIndex = 1;

+            this.importbutton.Text = "Add...";

+            this.importbutton.UseVisualStyleBackColor = true;

+            this.importbutton.Click += new System.EventHandler(this.importbutton_Click_1);

+            // 

+            // applybutton

+            // 

+            this.applybutton.Location = new System.Drawing.Point(120, 217);

+            this.applybutton.Name = "applybutton";

+            this.applybutton.Size = new System.Drawing.Size(52, 23);

+            this.applybutton.TabIndex = 3;

+            this.applybutton.Text = "Apply";

+            this.applybutton.UseVisualStyleBackColor = true;

+            this.applybutton.Click += new System.EventHandler(this.applybutton_Click_1);

+            // 

+            // themecolorfgmarked

+            // 

+            this.themecolorfgmarked.AutoSize = true;

+            this.themecolorfgmarked.Location = new System.Drawing.Point(313, 18);

+            this.themecolorfgmarked.Name = "themecolorfgmarked";

+            this.themecolorfgmarked.Size = new System.Drawing.Size(67, 13);

+            this.themecolorfgmarked.TabIndex = 22;

+            this.themecolorfgmarked.Text = "Marked Text";

+            // 

+            // deleteButton

+            // 

+            this.deleteButton.Location = new System.Drawing.Point(66, 217);

+            this.deleteButton.Name = "deleteButton";

+            this.deleteButton.Size = new System.Drawing.Size(52, 23);

+            this.deleteButton.TabIndex = 2;

+            this.deleteButton.Text = "Delete";

+            this.deleteButton.UseVisualStyleBackColor = true;

+            this.deleteButton.Click += new System.EventHandler(this.deleteButton_Click);

+            // 

+            // XTM

+            // 

+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

+            this.ClientSize = new System.Drawing.Size(397, 248);

+            this.Controls.Add(this.deleteButton);

+            this.Controls.Add(this.themecolorfgmarked);

+            this.Controls.Add(this.themecolorfg);

+            this.Controls.Add(this.themecolorf);

+            this.Controls.Add(this.themecolor3);

+            this.Controls.Add(this.themecolorb);

+            this.Controls.Add(this.themecolor7);

+            this.Controls.Add(this.themecolore);

+            this.Controls.Add(this.themecolor2);

+            this.Controls.Add(this.themecolora);

+            this.Controls.Add(this.themecolor6);

+            this.Controls.Add(this.themecolord);

+            this.Controls.Add(this.themecolor1);

+            this.Controls.Add(this.themecolor9);

+            this.Controls.Add(this.themecolor5);

+            this.Controls.Add(this.themecolorc);

+            this.Controls.Add(this.themecolor0);

+            this.Controls.Add(this.themecolor8);

+            this.Controls.Add(this.themecolor4);

+            this.Controls.Add(this.importbutton);

+            this.Controls.Add(this.applybutton);

+            this.Controls.Add(this.themelist);

+            this.Controls.Add(this.themecolortextbg);

+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;

+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

+            this.MaximizeBox = false;

+            this.Name = "XTM";

+            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;

+            this.Text = "XChat Theme Manager";

+            this.ResumeLayout(false);

+            this.PerformLayout();

+

+        }
+
+        #endregion
+
+        private System.Windows.Forms.ListBox themelist;
+        private System.Windows.Forms.Label themecolor0;
+        private System.Windows.Forms.Label themecolor1;
+        private System.Windows.Forms.Label themecolor2;
+        private System.Windows.Forms.Label themecolor3;
+        private System.Windows.Forms.Label themecolor4;
+        private System.Windows.Forms.Label themecolor5;
+        private System.Windows.Forms.Label themecolor6;
+        private System.Windows.Forms.Label themecolor7;
+        private System.Windows.Forms.Label themecolor8;
+        private System.Windows.Forms.Label themecolor9;
+        private System.Windows.Forms.Label themecolora;
+        private System.Windows.Forms.Label themecolorb;
+        private System.Windows.Forms.Label themecolorc;
+        private System.Windows.Forms.Label themecolord;
+        private System.Windows.Forms.Label themecolore;
+        private System.Windows.Forms.Label themecolorf;
+        private System.Windows.Forms.Label themecolorfg;
+        private System.Windows.Forms.Label themecolortextbg;
+        private System.Windows.Forms.Button importbutton;
+        private System.Windows.Forms.Button applybutton;
+        private System.Windows.Forms.Label themecolorfgmarked;

+        private System.Windows.Forms.Button deleteButton;
+    }
+}
+
diff --git a/src/xtm/Main.cs b/src/xtm/Main.cs
new file mode 100644
index 00000000..2e10c650
--- /dev/null
+++ b/src/xtm/Main.cs
@@ -0,0 +1,327 @@
+/* XChat Theme Manager

+ *

+ * Copyright (C) 2012 Patrick Griffs

+ * Copyright (C) 2012 Berke Viktor

+ *

+ * 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

+ */

+

+using System;

+using System.Collections.Generic;

+using System.Collections;

+using System.ComponentModel;

+using System.Data;

+using System.Drawing;

+using System.IO;

+/* using System.IO.Compression; */

+using System.IO.Packaging;

+using System.Linq;

+using System.Text;

+using System.Windows.Forms;

+using System.Net;

+

+namespace thememan

+{

+    public partial class XTM : Form

+    {

+        public string appdata = (Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\X-Chat 2\\");

+        public string home = (Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/.xchat2/");

+

+        public string xchatdir;

+        public string themedir = "themes\\";

+

+        OpenFileDialog importDialog;

+

+        public XTM ()

+		{

+			InitializeComponent ();

+            

+			if (File.Exists ("portable-mode"))

+				xchatdir = ("config\\");

+			else if (Directory.Exists (appdata))

+				xchatdir = (appdata);

+			else if (Directory.Exists (home)) {

+				xchatdir = (home); themedir = "themes/";

+			} else

+				Console.WriteLine("Install not found");

+

+            ListThemes();

+

+            String[] arguments = Environment.GetCommandLineArgs();

+            if (arguments.Length > 1)

+            {

+                FileInfo fi = new FileInfo(arguments[1]);

+                attemptImport(fi);

+            }

+        }

+

+        private void ListThemes()

+        {

+            themelist.Items.Clear();

+

+            if (Directory.Exists(xchatdir + themedir))

+            {

+                foreach (string theme in Directory.GetDirectories(xchatdir + themedir))

+                {

+                    themelist.Items.Add(theme.Remove(0, xchatdir.Length + themedir.Length));

+                }

+            }

+            else

+            {

+                Directory.CreateDirectory(xchatdir + themedir);

+            }

+

+            if (themelist.Items.Count == 0)

+            {

+                applybutton.Enabled = false;

+                deleteButton.Enabled = false;

+            }

+            else

+            {

+                themelist.SetSelected(0, true);

+            }

+        }

+

+        private void ShowColors(List<List<string>> themecolors)

+        {

+            List<Control> labels = this.Controls.OfType<Label>().Cast<Control>().OrderBy(label => label.Name).ToList();

+            for (byte themecolor = 0; themecolor < themecolors.Count; themecolor++)

+            {

+                byte rval = Convert.ToByte(int.Parse(themecolors[themecolor][0].ToString(), System.Globalization.NumberStyles.HexNumber) / 257);

+                byte gval = Convert.ToByte(int.Parse(themecolors[themecolor][1].ToString(), System.Globalization.NumberStyles.HexNumber) / 257);

+                byte bval = Convert.ToByte(int.Parse(themecolors[themecolor][2].ToString(), System.Globalization.NumberStyles.HexNumber) / 257);

+                

+                if (themecolor <= 15)

+                    labels[themecolor].BackColor = Color.FromArgb(rval, gval, bval);

+                else if (themecolor == 16)

+                    themecolorfgmarked.ForeColor = Color.FromArgb(rval, gval, bval);

+                else if (themecolor == 17)

+                    themecolorfgmarked.BackColor = Color.FromArgb(rval, gval, bval);

+                else if (themecolor == 18)

+                    themecolorfg.ForeColor = Color.FromArgb(rval, gval, bval);

+                else if (themecolor == 19)

+                {

+                    themecolortextbg.BackColor = Color.FromArgb(rval, gval, bval);

+                    themecolorfg.BackColor = themecolortextbg.BackColor;

+                }

+            }

+        }

+

+        private List<List<string>> ReadTheme(string theme)

+        {

+            List<List<string>> themecolors = new List<List<string>>();

+            foreach (string line in File.ReadLines(xchatdir + themedir + theme + "/colors.conf"))

+            {

+                List<string> colors = new List<string>();

+                List<string> colorlist = new List<string>();

+                string[] possiblecolors = { "color_256", "color_257", "color_258", "color_259" };

+

+                for (byte num = 16; num <=31; num++)

+                    colorlist.Add("color_" + num);

+                colorlist.AddRange(possiblecolors);

+

+                string[] config = line.Split(new char[] { ' ' });

+                if(colorlist.Contains(config[0]) == true)

+                {

+                    colors.Add(config[2]);

+                    colors.Add(config[3]);

+                    colors.Add(config[4]);

+                    themecolors.Add(colors);

+                }

+            }

+            return themecolors;

+        }

+

+        private void applybutton_Click_1(object sender, EventArgs e)

+        {

+            DialogResult result = MessageBox.Show("XChat must be closed and this will overwrite your current theme!\n\nDo you wish to continue?", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);

+            if (result == DialogResult.OK)

+            {

+                File.Copy(xchatdir + themedir + themelist.SelectedItem.ToString() + "\\colors.conf", xchatdir + "colors.conf", true);

+                if (File.Exists(xchatdir + themedir + themelist.SelectedItem.ToString() + "\\pevents.conf"))

+                {

+                    File.Copy(xchatdir + themedir + themelist.SelectedItem.ToString() + "\\pevents.conf", xchatdir + "pevents.conf", true);

+                }

+            }

+        }

+

+        private void theme_selected(object sender, EventArgs e)

+        {

+            if (themelist.SelectedItem != null)

+            {

+                ShowColors(ReadTheme(themelist.SelectedItem.ToString()));

+                applybutton.Enabled = true;

+                deleteButton.Enabled = true;

+            }

+        }

+

+        private void importbutton_Click_1(object sender, EventArgs e)

+        {

+            importDialog = new OpenFileDialog();

+            importDialog.Filter = "XChat Theme Files|*.xct";

+            importDialog.FilterIndex = 1;

+            importDialog.FileOk += new CancelEventHandler(importdialog_FileOk);

+            importDialog.ShowDialog();

+        }

+

+        private void importdialog_FileOk(object sender, System.ComponentModel.CancelEventArgs e)

+        {

+            FileInfo fi = new FileInfo(importDialog.FileName);

+            attemptImport(fi);

+        }

+

+        private void attemptImport(FileInfo fi)

+        {

+            string themeName = fi.Name.Remove(fi.Name.Length - fi.Extension.Length);

+            int result = extractTheme(fi);

+            ListThemes();

+            /* although a check is added to ListThemes(), this would still fail if the theme file was invalid or the theme is already installed */

+            switch (result)

+            {

+                case 0:

+                    themelist.SetSelected(themelist.FindStringExact(themeName), true);

+                    /* required for command line invoking */

+                    ShowColors(ReadTheme(themeName));

+                    break;

+                case 1:

+                    MessageBox.Show("This theme is already installed!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);

+                    themelist.SetSelected(themelist.FindStringExact(themeName), true);

+                    /* required for command line invoking */

+                    ShowColors(ReadTheme(themeName));

+                    break;

+                case 2:

+                    MessageBox.Show("Invalid theme file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

+                    break;

+            }

+        }

+        /* gzip solution, not good enough coz we need multiple files

+         * 

+        public string extractTheme(FileInfo fi)

+        {

+            using (FileStream inFile = fi.OpenRead())

+            {

+                string themeName = fi.Name.Remove(fi.Name.Length - fi.Extension.Length);

+                string destFolder = xchatdir + themedir + themeName;

+

+                if (!Directory.Exists(destFolder))

+                {

+                    Directory.CreateDirectory(destFolder);

+                }

+

+                using (FileStream outFile = File.Create(destFolder + "\\colors.conf"))

+                {

+                    using (GZipStream Decompress = new GZipStream(inFile, CompressionMode.Decompress))

+                    {

+                        Decompress.CopyTo(outFile);

+                    }

+                }

+                return themeName;

+            }

+        }

+         */

+

+        /* using System.IO.Package:

+         * http://weblogs.asp.net/jgalloway/archive/2007/10/25/creating-zip-archives-in-net-without-an-external-library-like-sharpziplib.aspx

+         * [Content_Types].xml must be present for every zip file

+         */

+

+        private const long BUFFER_SIZE = 4096;

+

+        private int extractTheme(FileInfo zipFile)

+        {

+            string themeName = zipFile.Name.Remove(zipFile.Name.Length - zipFile.Extension.Length);

+            string destFolder = xchatdir + themedir + themeName;

+

+            try

+            {

+                using (Package zip = Package.Open(zipFile.FullName, FileMode.Open))

+                {

+                    PackagePartCollection parts = zip.GetParts();

+

+                    if (Directory.Exists(destFolder))

+                    {

+                        return 1;

+                    }

+                    else

+                    {

+                        Directory.CreateDirectory(destFolder);

+                    }

+

+                    foreach (PackagePart part in parts)

+                    {

+                        /* not sure what's this good for */

+                        /* String archive = part.Uri.ToString().Replace(@"/", @"\"); */

+                        String destFile = destFolder + part.Uri.ToString();

+

+                            using (FileStream outFileStream = new FileStream(destFile, FileMode.CreateNew, FileAccess.ReadWrite))

+                            {

+                                using (Stream inStream = part.GetStream())

+                                {

+                                    long bufferSize = inStream.Length < BUFFER_SIZE ? inStream.Length : BUFFER_SIZE;

+                                    byte[] buffer = new byte[bufferSize];

+                                    int bytesRead = 0;

+                                    long bytesWritten = 0;

+

+                                    while ((bytesRead = inStream.Read(buffer, 0, buffer.Length)) != 0)

+                                    {

+                                        outFileStream.Write(buffer, 0, bytesRead);

+                                        bytesWritten += bufferSize;

+                                    }

+                                }

+                            }

+

+

+                    }

+                }

+            }

+            catch (System.IO.FileFormatException)

+            {

+                return 2;

+            }

+

+            if (IsDirectoryEmpty(destFolder))

+            {

+                Directory.Delete(destFolder);

+                return 2;

+            }

+            else

+            {

+                return 0;

+            }

+        }

+

+        public bool IsDirectoryEmpty(string path)

+        {

+            return !Directory.EnumerateFileSystemEntries(path).Any();

+        }

+

+        private void deleteButton_Click(object sender, EventArgs e)

+        {

+            DialogResult result = MessageBox.Show("Are you sure you want to delete this theme from the theme repo?\n\nYour currently applied theme won't be affected.", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);

+            if (result == DialogResult.OK)

+            {

+                Directory.Delete(xchatdir + themedir + themelist.SelectedItem.ToString(), true);

+                ListThemes();

+                if (themelist.Items.Count == 0)

+                {

+                    deleteButton.Enabled = false;

+                }

+            }

+        }

+

+

+

+    }

+}

diff --git a/src/xtm/Main.resx b/src/xtm/Main.resx
new file mode 100644
index 00000000..75c99568
--- /dev/null
+++ b/src/xtm/Main.resx
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="utf-8"?>

+<root>

+  <!-- 

+    Microsoft ResX Schema 

+    

+    Version 2.0

+    

+    The primary goals of this format is to allow a simple XML format 

+    that is mostly human readable. The generation and parsing of the 

+    various data types are done through the TypeConverter classes 

+    associated with the data types.

+    

+    Example:

+    

+    ... ado.net/XML headers & schema ...

+    <resheader name="resmimetype">text/microsoft-resx</resheader>

+    <resheader name="version">2.0</resheader>

+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>

+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>

+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>

+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>

+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">

+        <value>[base64 mime encoded serialized .NET Framework object]</value>

+    </data>

+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>

+        <comment>This is a comment</comment>

+    </data>

+                

+    There are any number of "resheader" rows that contain simple 

+    name/value pairs.

+    

+    Each data row contains a name, and value. The row also contains a 

+    type or mimetype. Type corresponds to a .NET class that support 

+    text/value conversion through the TypeConverter architecture. 

+    Classes that don't support this are serialized and stored with the 

+    mimetype set.

+    

+    The mimetype is used for serialized objects, and tells the 

+    ResXResourceReader how to depersist the object. This is currently not 

+    extensible. For a given mimetype the value must be set accordingly:

+    

+    Note - application/x-microsoft.net.object.binary.base64 is the format 

+    that the ResXResourceWriter will generate, however the reader can 

+    read any of the formats listed below.

+    

+    mimetype: application/x-microsoft.net.object.binary.base64

+    value   : The object must be serialized with 

+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

+            : and then encoded with base64 encoding.

+    

+    mimetype: application/x-microsoft.net.object.soap.base64

+    value   : The object must be serialized with 

+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter

+            : and then encoded with base64 encoding.

+

+    mimetype: application/x-microsoft.net.object.bytearray.base64

+    value   : The object must be serialized into a byte array 

+            : using a System.ComponentModel.TypeConverter

+            : and then encoded with base64 encoding.

+    -->

+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />

+    <xsd:element name="root" msdata:IsDataSet="true">

+      <xsd:complexType>

+        <xsd:choice maxOccurs="unbounded">

+          <xsd:element name="metadata">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" />

+              </xsd:sequence>

+              <xsd:attribute name="name" use="required" type="xsd:string" />

+              <xsd:attribute name="type" type="xsd:string" />

+              <xsd:attribute name="mimetype" type="xsd:string" />

+              <xsd:attribute ref="xml:space" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="assembly">

+            <xsd:complexType>

+              <xsd:attribute name="alias" type="xsd:string" />

+              <xsd:attribute name="name" type="xsd:string" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="data">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />

+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />

+              </xsd:sequence>

+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />

+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />

+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />

+              <xsd:attribute ref="xml:space" />

+            </xsd:complexType>

+          </xsd:element>

+          <xsd:element name="resheader">

+            <xsd:complexType>

+              <xsd:sequence>

+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />

+              </xsd:sequence>

+              <xsd:attribute name="name" type="xsd:string" use="required" />

+            </xsd:complexType>

+          </xsd:element>

+        </xsd:choice>

+      </xsd:complexType>

+    </xsd:element>

+  </xsd:schema>

+  <resheader name="resmimetype">

+    <value>text/microsoft-resx</value>

+  </resheader>

+  <resheader name="version">

+    <value>2.0</value>

+  </resheader>

+  <resheader name="reader">

+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

+  </resheader>

+  <resheader name="writer">

+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

+  </resheader>

+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

+    <value>

+        AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAHAAAACQAAAAgAAAAFAAAAAgAAAAEAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABwAAABEBAQEbBAQEIQICAh4AAAAVAAAACwAA

+        AAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAFwMDAywDAwM/AwMDSQUF

+        BUUEBAQ1AQEBHwAAAA0AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAUAAAAZAgICRQMD

+        A3IBAQGDAQEBegICA20EBARYBAQEOgEBARsAAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA

+        ABQEBARjGhsZricnJcsXFxbYBgYGzgAAAJwCAgJwBQUFTwICAioAAAANAAAAAgAAAAAAAAAAAAAAAAAA

+        AAAAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAIAAAACAAAAAQAA

+        AAEAAAABAAAABQMDAlM8Pjqcp6ug17O3rPiFiID3NTcz6QEBAdMBAQGPBAQEWgICAjQAAAATAAAABAAA

+        AAEAAAABAAAAAgAAAAUAAAAHAAAACAAAAAcAAAAEAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAwAAAAYAAAAKAAAADAAA

+        AA0AAAAMAAAACwAAAAgAAAAGAQEBGRcYF3uqrqPU3ePV+MrPwv+usqf+b3Ns8QcHB+QAAACnBAQEYAQE

+        BDsAAAAYAAAABwAAAAUAAAAIAAAADgAAABUCAgIdAgICIAEBARwAAAASAAAACQAAAAMAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAADgEB

+        ARkDAwMiAgICJwICAikCAgIoAgICJQAAAB8AAAAXAQIBTmFjXaTX3c/p4uja/9bczv/Cx7v+en127hMU

+        E+QAAAC3BAQEZQQEBD4AAAAfAAAAEgAAABUBAQEeAgICKgICAjcCAgNEAwMDSAQEBEACAgIuAQEBGQAA

+        AAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA

+        AAUAAAARAwMDJgMDAzsDAwNJAgICTwICAlICAgJTBAQETwMDA0cEAwQ5AgICd5WZj9vq8OL54ObY/9/l

+        1//Kz8P/fYF57BscGt4AAADBAgICbAMDA0UAAAAwAAAALQICAjcCAgJNAgICbgICAoUBAQGJAQEBeAIC

+        AmQDAwNMBAQELQAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAgAAAA0AAAA0AgICbAICAo8CAgGbAQEBngAAAJkBAQGOAgICfAMDA28CAgJfAgICjJyf

+        lufo7d/+5Orc/+Pp2v/Gy7//io2F6SEiINQAAADDAQEBcwMDA1UCAgJSAwMDaQYGBosSExKePD46vjw9

+        OtYTFBPTAgICuwAAAJADAwNdBAQEOQICAhgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAQEBBwYGBkgZGhiOJSYkszAxLsgsLSvRHyAe2RESEd0KCgrdAgICzwAA

+        ALQAAACKAgICoJygl+ru9OX+6/Hi/+Dl2P7N0sb/jJCI6hscGtEAAADBAgIBgwcHB4MTExKmMzQwvXh8

+        dM2hpZvms7mt9Kito/qEiH/2IiMg3QICAr0BAQJrAwMDNgAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBQUFGS8wLYO1uq/Yyc/C8sLHu/awtan4n6OZ+pGV

+        jPtydW70Li8s4RUVFNoCAgLGAQEBvZGUjOjt8+X86O7g/+Xq3P/S18r/g4Z+7A8PDs4EBATFGxwax0dI

+        RM6RlIvjvsK29sXKvfi6vrL9w8m8/8TJvf+mq6D7UFJN3gUGBb4BAQFqAgICKAAAAA8AAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAACAAAAAgAAAAIAAAAEBwcHOFBSTZjb4NPw6O7g/uHn

+        2f7U2s3/yc3B/7q/s/+2uq/+pquh+4WIgPYrLCrhBwcH03x+d+Lk6dv78Pbn/+nv4f/Y3tD9jZCH6RkZ

+        GM48PTnXm56V8MXKvfrK0ML90dXI/8rPwv+3vLH/wsi7/8DFuf+bnpT4LC0qzQICAqQBAQFKAAAAFgAA

+        AAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAMAAAAEAAAABQAAAAcAAAAJAgICMyco

+        JpW4vLHa3ePV+Nzh1Pvc4tT/1NnM/8zRxP/HzL//t7uw/6qvpP+Sl433QkQ/2n1/eOHf5Nb88vjp/+/1

+        5v/i6Nr8sLWq732AeOimqp/2ub6y/r7EuP+9wrf/vcK2/7/Dt/+3vLD/ub+y/6Wpnvtwc2vmEBEQswEB

+        AWQAAAAdAAAACQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAADAAAABQAAAAcAAAAJAAAADAAA

+        AA8AAAATAAAAHwYGBm88Pjqom5+V2MTJvfPGy7//wMW5/77Ct/+9wbX/uL2y/7O3rP+3vLD/o6id8rm9

+        svLl693+6e/g/+bs3f/c4tP/x83A/7G1qv6mqqD/nKCW/5ygl/+go5r/o6ed/6aqoP+kqJ7/j5OK81VY

+        UtwREhG4AQEBbAAAACUAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAQAAAAHAAAACgAA

+        AA4AAAATAAAAGQAAAB4AAAAjAAAAKwAAAEQCAgKJHB0bul5gW9eQlIvyn6OZ/p6imP+go5r/pqqg/6+z

+        qf+5vrL/wMS5/rm+s/+XnJL/eX11/3J4c/9zgoP/Z3R0/2xxbP+ChX3/g4Z+/3+Cev+BhHv/iIyD/32A

+        eP5iZF3wNjc01goKCbQAAAB4AAAALAAAAA8AAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAADAAAABAAA

+        AAgAAAANAAAAFAAAABoAAAAiAAAAKgAAADIAAAA7AAAARQAAAFMAAABrAAAAkAoLCrwpKifkVVdS9Hh7

+        dPuDhn7/j5KK/5uflv+anpX/aWxl/0ZOTP9BVl3/M1Ff/ytIV/8wTmD/MEpZ/zRIUv9FTk//cXRu/3p+

+        dv5ydW7+UFJO+CorKOwPDw7UAQEBrQICAoECAgJOAwMDLwAAABgAAAAKAAAAAwAAAAAAAAABAAAAAgAA

+        AAMAAAAGAAAACgAAABAAAAAYAAAAIQAAACoAAAA1AAAAPwAAAEsAAABYAAAAZQAAAHMAAACAAAAAjgAA

+        AKEBAQG1Dg4N0iEiIOpAQj71cHNs/ICDfP1WWVT+LDk8/0Rsdv9UhZH/Uomd/0CBoP88b4r/PGB1/y9K

+        W/8rQEz/SE9P/jIzMPQiIyHoEhMS3AECAdQAAADCAQEBngICAnoEBARkBQUFTQMDAzMAAAAaAAAACgAA

+        AAIAAAACAAAAAwAAAAYAAAALAAAAEgAAABsAAAAmAAAAMQAAAD0AAABKAAAAWAAAAGcAAAB2AAAAhgAA

+        AJUAAAClAAAAsQAAALoFBQXFDAwM1gcHB+MJCQnrKCkn8lRWUfZDTU7/VX+M/054gv9KVVj/V2Fk/zxc

+        av9EUln/U1pf/ztRX/8wTF3/JzU9/0ZKRvk/QT3lODo34R4fHecJCQnjAQEB0wAAALABAQGGAwMDagQE

+        BFEDAwMzAAAAFwAAAAcAAAADAAAABgAAAAsAAAATAAAAHAAAACkAAAA2AAAARQAAAFQAAABkAAAAdAAA

+        AIUAAACZAAAAsAMDA8QWFhbXKSkp5j4+PvRLS0v5Ojo6+iAgH/YpKifxYGJc+HFzbf1FWmL/XZiu/0td

+        Yf9iY2P/uLm5/1laW/9jZGT/t7i4/05ZX/9AYXf/LURS/2RqZ/+Ch378goZ+/ICDe/hLTUjtHB0b6wUF

+        BeUAAADBAQEBjgICAmoFBQVLAwMDJwAAAA0AAAAEAAAACQAAABEAAAAdAAAAKQAAADgAAABIAAAAWgAA

+        AGwAAAB/AQEBmQICArgcHBzUR0dH7G9vb/uUlJT9u7u7/tra2v+NjY39JSUk+DY3NPdbXVj7eXx1/nh7

+        dP88TVT/WI6k/1prcP/P0ND/09TU/2psbP/Q0dH/0tPU/1NjbP9Oe5f/OFFe/4SLhf+ippz/n6OZ/5+j

+        mf+Rloz+en529Ts8OekMDAvlAAEAxgEBAYYDAwNXBAQEMAAAABIAAAAHAAAADwAAABsAAAApAAAAOQAA

+        AEsAAABdAAAAcgEBAYwICAi1Kioq3GxsbPOnp6f92dnZ//r6+v/9/f3//Pz8/5ycm/4rLCv6Kiso+EZH

+        Q/xhY13+fH94/4qNhf9bYV7/QV9s/010g/9ve37/bnyA/09weP9vfYH/aXqB/0qCn/9ThaH/P0tQ/6So

+        n//DyLz/wsa7/7a7r/+zuKz/rbKm/5KXjvdVWFLrEREQ3QEBAawBAQJVAgICLwAAABIAAAALAAAAFgAA

+        ACQAAAA3AAAASgAAAF8AAAB3CwsLpCsrK9p1dXXzx8fH/u3t7f/////////////////+/v7/vb29/zY2

+        Nv0cHRv8LS8s+0JDP/xZW1b8dHdw/I+Tiv6NkYf8TFNS+UBpevxiqcL/d8fc/4Ta7v95yd//Z7jd/1+h

+        w/9EW2X/e4F6/8TJvf/R1sn/1NnM/9HWyf/N08X/yc/C/8TJvP+qrqP6WVtW3AcHBrACAgJKAwMDJQAA

+        AA4AAAAPAAAAHAAAAC8AAABEAAAAXAICAnsXFxezY2Nj6sjIyP3w8PD/8/P0//Pz8///////////////

+        ///39/f/jIyM/hsbG/0WFxX8IyQh+jM0MfpAQT34RUdD90BBPfJCREDcKisotj9KTdVCYGv+THOA/3Cs

+        xf9wr8z/TXWJ/0hZYP9/hX//ztPH/ubr3f7m7N3/7/Xm//D25//m7N3/3+XX/9bczv7L0MP2kJSLwQ4O

+        DYcCAgJCAQEBFgAAAAgAAAAUAAAAJAAAADkAAABTAgICdiMjI7iHh4f25eXl/v7+/v/+/v//oaHs/62t

+        vP/4+Pj/////////////////5OTk/25ubv4iIiL9CwwL+wwNDPgMDQzvDAwM1wgIB7AFBQWHAQEBhHN2

+        b7enraTzjJKN/3SCgv90goP/mqKc/77Dt/+Tl473YGNd7ImNhfG/xLj55evd+OTq3Pjb4dP40NXJ+MXK

+        vuutsaa9RkhDiQUFBWQAAAAiAAAACQAAAAMAAAAYAAAAKwAAAEQDAwNrKCgot5iYmPb39/f/////////

+        ////////oqL3/1pauv/k5OT//////////////////////+fn5/+np6f/T09P+QsLC+gAAADMAAAArwAA

+        AI8AAAByAQEBhllbVqXKz8Pi2+HT/9zi1P/f5df/5evd/+Pp2/+us6j1MTMw2BUVFMInKCW1Ojs4p0FC

+        PqxAQj2qNDYyqC0uK54gIB6JBwcGXgAAACIAAAAHAAAAAgAAAAAAAAAaAAAAMAEBAVQjIyOrm5ub9Pf3

+        9///////////////////////vr76/0FBzv/S0tT///////z8/P/o6On/2tra//Pz8//9/f3/2dnZ/3Nz

+        c/gRERHbAAAAtgAAAJkAAAB9AAAAhRQUE5KorKHE3uTW+O3z5P/x9+j/6O7g/97k1v+vs6juLi8tzAAA

+        AJICAgJPAgICPgQEBEcDAwNNAQEBPgAAACYAAAATAAAACwAAAAMAAAABAAAAAAAAAAAAAAAcAAAANQwM

+        DH5zc3Pm6urq////////////////////////////6Oj9/0ND3v+ysrn/3Nzj/5OTx/87O83/Li63/39/

+        nP/o6Oj//////97e3v9WVlb0BQUFywAAAKcAAACKAAAAeQICApdGSESVxMm9zOju4Pru9OX/5Orc/97j

+        1f+WmZDfHh8dwAEBAX0CAgIyAAAAFAAAAAcAAAAEAAAAAgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAcAAAARDo6Ora8vLz9///////////////////////////+/v7/7e31/0JC5v9KSqb/LS3T/wYG

+        8/8AAP7/AQH9/yoqz//Ly9b//v7+//7+/v+np6f+ISEh4gAAALQAAACTAAAAdAAAAIgFBQWjV1lUpMvQ

+        xNHr8eP85evd/9ne0fdrbWfQCgoJpgEBAVEAAAAdAAAACQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAaAAAAU1lZWeDp6en//////////////////v7+//Ly8//BwdT/ZmbI/xMR

+        6P8KBfL/AAD//wAA/v8SEvX/V1ft/8DA7v/4+Pv////////////f39//Ozs78QAAALsAAACYAAAAeAAA

+        AGMAAAByBgYFm0NFQcO1uq/Z3ePV6qqupM4pKii4AAAAcQAAACMAAAALAAAAAwAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAAAAWGRkZPP9/f3////////////s7O//s7PQ/1pa

+        xf8TE+j/AgL6/wAA/v8ZDOf/Dw7w/2lp6f/IyPL/+fn8///////////////////////39/f/R0dH+AAA

+        AL0AAACYAAAAeAAAAFcAAAA8AAAARAkJCHM0NjKdUVNOuDM0MZcEBQRkAAAAJgAAAAkAAAADAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAUWJiYu35+fn///////j4

+        /v9ycuv/ERHp/wEB/f8AAP//AwP8/yws8P9DQe7/Wlq8/+rq7P//////////////////////////////

+        ///z8/P/RERE9QAAALgAAACSAAAAcgAAAFEAAAAyAAAAGwAAABcAAAAmAAAANwAAAC8AAAASAAAABAAA

+        AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAPlJS

+        Uszb29v+//////7+//+4uPz/JSX8/w0N+v82NvL/nJzr/+jo9/+2tvn/Tk7C/9ra2///////////////

+        ///////////////////Nzc3+NDQ05wAAAKsAAACHAAAAZwAAAEUAAAApAAAAFQAAAAgAAAAEAAAABAAA

+        AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAKAAAAIi4uLo6lpaX1/Pz8////////////6Oj+/9DQ+f/z8/v//v7+///////R0fv/OzvY/8LC

+        yP/+/v7///////////////////////n5+f+MjIz5FxcXygAAAJcAAAB2AAAAVwAAADkAAAAgAAAADgAA

+        AAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAGAAAADgQEBEBWVlbA0dHR/P7+/v//////////////////////////////

+        ///x8f7/S0vn/6mpuf/8/Pz//////////////////f39/8DAwP05OTndAQEBoAAAAH4AAABhAAAARAAA

+        ACkAAAAVAAAACAAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAACAEBARUXFxdYWVlZyby8vPj19fX/////////

+        ///////////////////7+///c3P1/5iYyP/5+fn///////7+/v/x8fH/rKys+kRERN0ICAiiAAAAfAAA

+        AGMAAABIAAAALwAAABoAAAALAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABQAAAAoBAQEXDw8PRjs7

+        O6h9fX3ox8fH+ubm5v/19fX//Pz8////////////4uL+/9zc9P/y8vL/5OTk/76+vvpvb2/tKSkpwgUF

+        BYwAAABvAAAAWgAAAEUAAAAwAAAAHAAAAA4AAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAA

+        AAUAAAAJAAAAEgcHBysWFhZqKysrsFlZWdaHh4fppaWl9re3t/y5ubn+tra2/KGhofWAgIDrUFBQ2yMj

+        I70ODg6NAgICZwAAAFcAAABLAAAAPAAAACwAAAAcAAAADwAAAAYAAAACAAAAAQAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAQAAAAIAAAAEAAAACAAAAA0AAAAVAwMDJwkJCUwLCwt0DAwMjwwMDJ8MDAylDAwMoQsL

+        C5UJCQl/BgYGYQEBAUkAAABAAAAAOwAAADUAAAAsAAAAIgAAABcAAAANAAAABgAAAAIAAAABAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAwAAAAUAAAAIAAAADAAAABEAAAAVAAAAGgAA

+        AB0AAAAgAAAAIwAAACQAAAAkAAAAJAAAACMAAAAhAAAAHgAAABoAAAAVAAAADwAAAAoAAAAFAAAAAgAA

+        AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAABQAA

+        AAcAAAAJAAAACwAAAA4AAAAPAAAAEAAAABAAAAARAAAAEAAAAA8AAAAOAAAADQAAAAsAAAAIAAAABQAA

+        AAQAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAQAAAAIAAAADAAAABAAAAAUAAAAGAAAABgAAAAYAAAAGAAAABQAAAAQAAAAEAAAAAwAA

+        AAMAAAACAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAQAA

+        AAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAP///////wAA////////

+        AAD///////8AAP///////wAA/////f//AAD////wf/8AAP///+A//wAA////4D//AAD////AP/8AAP//

+        /8A/nwAA//+DgDwHAAD//gAAAAcAAP/8AAAABwAA//wAAAAHAAD//AAAAA8AAP/+AAAAHwAA//4AAAA/

+        AAD//wAAAD8AAP/+AAAAfwAA//gAAAAfAAD/4AAAAA8AAP/AAAAABwAA/wAAAAAHAAD+AAAAAAcAAPwA

+        AAAABwAA+AAAAAAPAADwAACAAB8AAOAAAIAP/wAA4AAAQB//AADAAABAH/8AAMAAAHA//wAAwAAAfH//

+        AADAAAB///8AAMAAAH///wAAwAAA////AADgAAH///8AAPAAA////wAA+AAH////AAD+AB////8AAP/B

+        /////wAA////////AAD///////8AAP///////wAA////////AAD///////8AAP///////wAA////////

+        AAA=

+</value>

+  </data>

+</root>
\ No newline at end of file
diff --git a/src/xtm/Program.cs b/src/xtm/Program.cs
new file mode 100644
index 00000000..c9bb7144
--- /dev/null
+++ b/src/xtm/Program.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace thememan
+{
+    static class Program
+    {
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            Application.EnableVisualStyles();
+            Application.SetCompatibleTextRenderingDefault(false);
+            Application.Run(new XTM());
+        }
+    }
+}
diff --git a/src/xtm/Properties/AssemblyInfo.cs b/src/xtm/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..75d92f87
--- /dev/null
+++ b/src/xtm/Properties/AssemblyInfo.cs
@@ -0,0 +1,38 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Resources;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("XChat Theme Manager")]
+[assembly: AssemblyDescription("Manages XChat Themes.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("thememan")]
+[assembly: AssemblyCopyright("Copyright ©  2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("adb04fa6-faee-4dcc-be53-7ba67e74c2a0")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
diff --git a/src/xtm/Properties/Resources.Designer.cs b/src/xtm/Properties/Resources.Designer.cs
new file mode 100644
index 00000000..829857ee
--- /dev/null
+++ b/src/xtm/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------

+// <auto-generated>

+//     This code was generated by a tool.

+//     Runtime Version:4.0.30319.17626

+//

+//     Changes to this file may cause incorrect behavior and will be lost if

+//     the code is regenerated.

+// </auto-generated>

+//------------------------------------------------------------------------------

+

+namespace thememan.Properties {

+    using System;

+    

+    

+    /// <summary>

+    ///   A strongly-typed resource class, for looking up localized strings, etc.

+    /// </summary>

+    // This class was auto-generated by the StronglyTypedResourceBuilder

+    // class via a tool like ResGen or Visual Studio.

+    // To add or remove a member, edit your .ResX file then rerun ResGen

+    // with the /str option, or rebuild your VS project.

+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]

+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

+    internal class Resources {

+        

+        private static global::System.Resources.ResourceManager resourceMan;

+        

+        private static global::System.Globalization.CultureInfo resourceCulture;

+        

+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]

+        internal Resources() {

+        }

+        

+        /// <summary>

+        ///   Returns the cached ResourceManager instance used by this class.

+        /// </summary>

+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]

+        internal static global::System.Resources.ResourceManager ResourceManager {

+            get {

+                if (object.ReferenceEquals(resourceMan, null)) {

+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("thememan.Properties.Resources", typeof(Resources).Assembly);

+                    resourceMan = temp;

+                }

+                return resourceMan;

+            }

+        }

+        

+        /// <summary>

+        ///   Overrides the current thread's CurrentUICulture property for all

+        ///   resource lookups using this strongly typed resource class.

+        /// </summary>

+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]

+        internal static global::System.Globalization.CultureInfo Culture {

+            get {

+                return resourceCulture;

+            }

+            set {

+                resourceCulture = value;

+            }

+        }

+    }

+}

diff --git a/src/xtm/Properties/Resources.resources b/src/xtm/Properties/Resources.resources
new file mode 100644
index 00000000..6c05a977
--- /dev/null
+++ b/src/xtm/Properties/Resources.resources
Binary files differdiff --git a/src/xtm/Properties/Resources.resx b/src/xtm/Properties/Resources.resx
new file mode 100644
index 00000000..1af7de15
--- /dev/null
+++ b/src/xtm/Properties/Resources.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/src/xtm/Properties/Settings.Designer.cs b/src/xtm/Properties/Settings.Designer.cs
new file mode 100644
index 00000000..35939b71
--- /dev/null
+++ b/src/xtm/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------

+// <auto-generated>

+//     This code was generated by a tool.

+//     Runtime Version:4.0.30319.17626

+//

+//     Changes to this file may cause incorrect behavior and will be lost if

+//     the code is regenerated.

+// </auto-generated>

+//------------------------------------------------------------------------------

+

+namespace thememan.Properties {

+    

+    

+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]

+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {

+        

+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

+        

+        public static Settings Default {

+            get {

+                return defaultInstance;

+            }

+        }

+    }

+}

diff --git a/src/xtm/Properties/Settings.settings b/src/xtm/Properties/Settings.settings
new file mode 100644
index 00000000..39645652
--- /dev/null
+++ b/src/xtm/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>
diff --git a/src/xtm/README.md b/src/xtm/README.md
new file mode 100644
index 00000000..7f837263
--- /dev/null
+++ b/src/xtm/README.md
@@ -0,0 +1,7 @@
+xchat-theme-manager
+------------------
+
+- Shows previews of and can load/save themes
+- Will run on windows/linux (still wip)
+
+![XTM Screenshot](http://puu.sh/uoZz)
\ No newline at end of file
diff --git a/src/xtm/Resources/xtm.ico b/src/xtm/Resources/xtm.ico
new file mode 100644
index 00000000..f5cac031
--- /dev/null
+++ b/src/xtm/Resources/xtm.ico
Binary files differdiff --git a/src/xtm/app.config b/src/xtm/app.config
new file mode 100644
index 00000000..2f7cce78
--- /dev/null
+++ b/src/xtm/app.config
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<configuration>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup></configuration>
diff --git a/src/xtm/xtm.csproj b/src/xtm/xtm.csproj
new file mode 100644
index 00000000..10a9ccce
--- /dev/null
+++ b/src/xtm/xtm.csproj
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <PropertyGroup>

+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>

+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>

+    <ProductVersion>8.0.30703</ProductVersion>

+    <SchemaVersion>2.0</SchemaVersion>

+    <ProjectGuid>{DE87FFCA-9606-4116-B747-062D88A56A28}</ProjectGuid>

+    <OutputType>WinExe</OutputType>

+    <AppDesignerFolder>Properties</AppDesignerFolder>

+    <RootNamespace>thememan</RootNamespace>

+    <AssemblyName>thememan</AssemblyName>

+    <FileAlignment>512</FileAlignment>

+    <IsWebBootstrapper>false</IsWebBootstrapper>

+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>

+    <TargetFrameworkProfile>Client</TargetFrameworkProfile>

+    <PublishUrl>publish\</PublishUrl>

+    <Install>true</Install>

+    <InstallFrom>Disk</InstallFrom>

+    <UpdateEnabled>false</UpdateEnabled>

+    <UpdateMode>Foreground</UpdateMode>

+    <UpdateInterval>7</UpdateInterval>

+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>

+    <UpdatePeriodically>false</UpdatePeriodically>

+    <UpdateRequired>false</UpdateRequired>

+    <MapFileExtensions>true</MapFileExtensions>

+    <AutorunEnabled>true</AutorunEnabled>

+    <ApplicationRevision>1</ApplicationRevision>

+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>

+    <UseApplicationTrust>false</UseApplicationTrust>

+    <PublishWizardCompleted>true</PublishWizardCompleted>

+    <BootstrapperEnabled>true</BootstrapperEnabled>

+  </PropertyGroup>

+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">

+    <PlatformTarget>x86</PlatformTarget>

+    <DebugType>pdbonly</DebugType>

+    <Optimize>true</Optimize>

+    <OutputPath>..\..\win32\build\Win32\bin\</OutputPath>

+    <DefineConstants>TRACE</DefineConstants>

+    <ErrorReport>prompt</ErrorReport>

+    <WarningLevel>4</WarningLevel>

+    <CodeAnalysisIgnoreGeneratedCode>false</CodeAnalysisIgnoreGeneratedCode>

+  </PropertyGroup>

+  <PropertyGroup>

+    <ApplicationIcon>Resources\xtm.ico</ApplicationIcon>

+  </PropertyGroup>

+  <PropertyGroup>

+    <ManifestCertificateThumbprint>25412E3EF25458D894050F8209E4D9DCCDF432D7</ManifestCertificateThumbprint>

+  </PropertyGroup>

+  <PropertyGroup>

+    <ManifestKeyFile>xtm_TemporaryKey.pfx</ManifestKeyFile>

+  </PropertyGroup>

+  <PropertyGroup>

+    <GenerateManifests>false</GenerateManifests>

+  </PropertyGroup>

+  <PropertyGroup>

+    <SignManifests>false</SignManifests>

+  </PropertyGroup>

+  <PropertyGroup>

+    <TargetZone>LocalIntranet</TargetZone>

+  </PropertyGroup>

+  <PropertyGroup />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">

+    <OutputPath>..\..\win32\build\x64\bin\</OutputPath>

+    <DefineConstants>TRACE</DefineConstants>

+    <Optimize>true</Optimize>

+    <DebugType>pdbonly</DebugType>

+    <PlatformTarget>x64</PlatformTarget>

+    <CodeAnalysisLogFile>bin\Release\thememan.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>

+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>

+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>

+    <ErrorReport>prompt</ErrorReport>

+    <CodeAnalysisIgnoreGeneratedCode>false</CodeAnalysisIgnoreGeneratedCode>

+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>

+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>

+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>

+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>

+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>

+    <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>

+  </PropertyGroup>

+  <ItemGroup>

+    <Reference Include="Microsoft.VisualBasic" />

+    <Reference Include="System" />

+    <Reference Include="System.Core" />

+    <Reference Include="System.Xml.Linq" />

+    <Reference Include="System.Data.DataSetExtensions" />

+    <Reference Include="Microsoft.CSharp" />

+    <Reference Include="System.Data" />

+    <Reference Include="System.Deployment" />

+    <Reference Include="System.Drawing" />

+    <Reference Include="System.Windows.Forms" />

+    <Reference Include="System.Xml" />

+    <Reference Include="WindowsBase" />

+  </ItemGroup>

+  <ItemGroup>

+    <Compile Include="Main.cs">

+      <SubType>Form</SubType>

+    </Compile>

+    <Compile Include="Main.Designer.cs">

+      <DependentUpon>Main.cs</DependentUpon>

+    </Compile>

+    <Compile Include="Program.cs" />

+    <Compile Include="Properties\AssemblyInfo.cs" />

+    <EmbeddedResource Include="Main.resx">

+      <DependentUpon>Main.cs</DependentUpon>

+    </EmbeddedResource>

+    <EmbeddedResource Include="Properties\Resources.resx">

+      <Generator>ResXFileCodeGenerator</Generator>

+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>

+      <SubType>Designer</SubType>

+    </EmbeddedResource>

+    <Compile Include="Properties\Resources.Designer.cs">

+      <AutoGen>True</AutoGen>

+      <DependentUpon>Resources.resx</DependentUpon>

+      <DesignTime>True</DesignTime>

+    </Compile>

+    <None Include="app.config">

+      <SubType>Designer</SubType>

+    </None>

+    <None Include="Properties\Settings.settings">

+      <Generator>SettingsSingleFileGenerator</Generator>

+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>

+    </None>

+    <Compile Include="Properties\Settings.Designer.cs">

+      <AutoGen>True</AutoGen>

+      <DependentUpon>Settings.settings</DependentUpon>

+      <DesignTimeSharedInput>True</DesignTimeSharedInput>

+    </Compile>

+  </ItemGroup>

+  <ItemGroup>

+    <BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">

+      <Visible>False</Visible>

+      <ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>

+      <Install>true</Install>

+    </BootstrapperPackage>

+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">

+      <Visible>False</Visible>

+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>

+      <Install>false</Install>

+    </BootstrapperPackage>

+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">

+      <Visible>False</Visible>

+      <ProductName>.NET Framework 3.5 SP1</ProductName>

+      <Install>false</Install>

+    </BootstrapperPackage>

+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">

+      <Visible>False</Visible>

+      <ProductName>Windows Installer 3.1</ProductName>

+      <Install>true</Install>

+    </BootstrapperPackage>

+  </ItemGroup>

+  <ItemGroup>

+    <Content Include="Resources\xtm.ico" />

+  </ItemGroup>

+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->

+</Project>
\ No newline at end of file
diff --git a/src/xtm/xtm.csproj.user b/src/xtm/xtm.csproj.user
new file mode 100644
index 00000000..1f4a1d77
--- /dev/null
+++ b/src/xtm/xtm.csproj.user
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <PropertyGroup>

+    <PublishUrlHistory>publish\</PublishUrlHistory>

+    <InstallUrlHistory />

+    <SupportUrlHistory />

+    <UpdateUrlHistory />

+    <BootstrapperUrlHistory />

+    <ErrorReportUrlHistory />

+    <FallbackCulture>en-US</FallbackCulture>

+    <VerifyUploadedFiles>false</VerifyUploadedFiles>

+  </PropertyGroup>

+</Project>
\ No newline at end of file