summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml11
-rwxr-xr-xautogen.sh25
-rw-r--r--configure.ac636
-rw-r--r--m4/ac-check-cflags.m460
-rw-r--r--m4/ax_check_enable_debug.m4124
-rw-r--r--m4/ax_is_release.m469
-rw-r--r--m4/ax_perl_ext_flags.m4116
-rw-r--r--m4/ax_require_defined.m437
-rw-r--r--m4/clang-analyze.am8
-rw-r--r--plugins/Make.plugin38
-rw-r--r--plugins/checksum/Makefile.am6
-rw-r--r--plugins/checksum/checksum.c274
-rw-r--r--plugins/checksum/checksum.vcxproj64
-rw-r--r--plugins/doat/Makefile.am6
-rw-r--r--plugins/doat/doat.c18
-rw-r--r--plugins/doat/doat.vcxproj68
-rw-r--r--plugins/exec/exec.vcxproj60
-rw-r--r--plugins/fishlim/Makefile.am8
-rw-r--r--plugins/fishlim/fish.c44
-rw-r--r--plugins/fishlim/fish.h3
-rw-r--r--plugins/fishlim/fishlim.vcxproj66
-rw-r--r--plugins/fishlim/fishlim.vcxproj.filters6
-rw-r--r--plugins/fishlim/irc.c54
-rw-r--r--plugins/fishlim/irc.h5
-rw-r--r--plugins/fishlim/keystore.c92
-rw-r--r--plugins/fishlim/keystore.h9
-rw-r--r--plugins/fishlim/misc.c54
-rw-r--r--plugins/fishlim/misc.h36
-rw-r--r--plugins/fishlim/plugin_hexchat.c137
-rw-r--r--plugins/fishlim/plugin_hexchat.h1
-rw-r--r--plugins/fishlim/test.c94
-rw-r--r--plugins/mpcinfo/functions.c105
-rw-r--r--plugins/mpcinfo/mp3Info.c102
-rw-r--r--plugins/mpcinfo/mpcInfo.c27
-rw-r--r--plugins/mpcinfo/mpcinfo.vcxproj68
-rw-r--r--plugins/mpcinfo/oggInfo.c20
-rw-r--r--plugins/mpcinfo/theme.c44
-rw-r--r--plugins/perl/Makefile.am11
-rw-r--r--plugins/perl/perl.c127
-rw-r--r--plugins/perl/perl.vcxproj78
-rw-r--r--plugins/plugin-conf.in19
-rw-r--r--plugins/python/Makefile.am8
-rw-r--r--plugins/python/python.c166
-rw-r--r--plugins/python/python2.vcxproj68
-rw-r--r--plugins/python/python3.vcxproj68
-rw-r--r--plugins/sysinfo/Makefile.am18
-rw-r--r--plugins/sysinfo/format.c90
-rw-r--r--plugins/sysinfo/format.h (renamed from plugins/sysinfo/xsys.h)18
-rw-r--r--plugins/sysinfo/hwmon.c63
-rw-r--r--plugins/sysinfo/match.c240
-rw-r--r--plugins/sysinfo/osx/backend.m263
-rw-r--r--plugins/sysinfo/pci.c156
-rw-r--r--plugins/sysinfo/shared/df.c53
-rw-r--r--plugins/sysinfo/shared/df.h (renamed from src/common/identd.h)12
-rw-r--r--plugins/sysinfo/sysinfo-backend.h33
-rw-r--r--plugins/sysinfo/sysinfo.c277
-rw-r--r--plugins/sysinfo/sysinfo.cpp416
-rw-r--r--plugins/sysinfo/sysinfo.h (renamed from plugins/sysinfo/hwmon.h)15
-rw-r--r--plugins/sysinfo/sysinfo.vcxproj84
-rw-r--r--plugins/sysinfo/sysinfo.vcxproj.filters22
-rw-r--r--plugins/sysinfo/unix/backend.c170
-rw-r--r--plugins/sysinfo/unix/match.c98
-rw-r--r--plugins/sysinfo/unix/match.h (renamed from plugins/sysinfo/match.h)6
-rw-r--r--plugins/sysinfo/unix/parse.c (renamed from plugins/sysinfo/parse.c)271
-rw-r--r--plugins/sysinfo/unix/parse.h (renamed from plugins/sysinfo/parse.h)9
-rw-r--r--plugins/sysinfo/unix/pci.c169
-rw-r--r--plugins/sysinfo/unix/pci.h (renamed from plugins/sysinfo/pci.h)0
-rw-r--r--plugins/sysinfo/win32/backend.c493
-rw-r--r--plugins/sysinfo/xsys-changelog116
-rw-r--r--plugins/sysinfo/xsys-install15
-rw-r--r--plugins/sysinfo/xsys-makefile38
-rw-r--r--plugins/sysinfo/xsys-readme105
-rw-r--r--plugins/sysinfo/xsys.c923
-rw-r--r--plugins/upd/upd.c236
-rw-r--r--plugins/upd/upd.vcxproj74
-rw-r--r--plugins/winamp/winamp.c215
-rw-r--r--plugins/winamp/winamp.vcxproj70
-rw-r--r--po/POTFILES.in3
-rw-r--r--src/common/Makefile.am20
-rw-r--r--src/common/cfgfiles.c96
-rw-r--r--src/common/cfgfiles.h6
-rw-r--r--src/common/chanopt.c18
-rw-r--r--src/common/common.vcxproj88
-rw-r--r--src/common/common.vcxproj.filters30
-rw-r--r--src/common/ctcp.c8
-rw-r--r--src/common/dbus/dbus-client.c4
-rw-r--r--src/common/dbus/dbus-plugin.c5
-rw-r--r--src/common/dbus/example.c2
-rw-r--r--src/common/dcc.c594
-rw-r--r--src/common/dcc.h27
-rw-r--r--src/common/fe.h4
-rw-r--r--src/common/hexchat.c153
-rw-r--r--src/common/hexchat.h46
-rw-r--r--src/common/history.c18
-rw-r--r--src/common/identd.c201
-rw-r--r--src/common/ignore.c43
-rw-r--r--src/common/inbound.c47
-rw-r--r--src/common/inet.h6
-rw-r--r--src/common/make-te.c4
-rw-r--r--src/common/make-te.vcxproj63
-rw-r--r--src/common/modes.c67
-rw-r--r--src/common/msproxy.c470
-rw-r--r--src/common/msproxy.h262
-rw-r--r--src/common/network.c209
-rw-r--r--src/common/network.h11
-rw-r--r--src/common/notify.c77
-rw-r--r--src/common/outbound.c441
-rw-r--r--src/common/outbound.h2
-rw-r--r--src/common/plugin-identd.c220
-rw-r--r--src/common/plugin-identd.h28
-rw-r--r--src/common/plugin-timer.c24
-rw-r--r--src/common/plugin.c117
-rw-r--r--src/common/plugin.h3
-rw-r--r--src/common/proto-irc.c27
-rw-r--r--src/common/server.c540
-rw-r--r--src/common/server.h3
-rw-r--r--src/common/servlist.c331
-rw-r--r--src/common/servlist.h1
-rw-r--r--src/common/ssl.c237
-rw-r--r--src/common/ssl.h4
-rw-r--r--src/common/text.c582
-rw-r--r--src/common/text.h10
-rw-r--r--src/common/tree.c7
-rw-r--r--src/common/tree.h2
-rw-r--r--src/common/url.c34
-rw-r--r--src/common/url.h2
-rw-r--r--src/common/userlist.c107
-rw-r--r--src/common/userlist.h2
-rw-r--r--src/common/util.c184
-rw-r--r--src/common/util.h6
-rw-r--r--src/dirent/dirent-win32.h184
-rw-r--r--src/fe-gtk/Makefile.am26
-rw-r--r--src/fe-gtk/banlist.c25
-rw-r--r--src/fe-gtk/chanlist.c14
-rw-r--r--src/fe-gtk/chanview-tabs.c7
-rw-r--r--src/fe-gtk/chanview.c19
-rw-r--r--src/fe-gtk/custom-list.c11
-rw-r--r--src/fe-gtk/custom-list.h8
-rw-r--r--src/fe-gtk/dccgui.c49
-rw-r--r--src/fe-gtk/editlist.c2
-rw-r--r--src/fe-gtk/fe-gtk.c70
-rw-r--r--src/fe-gtk/fe-gtk.h25
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj89
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj.filters15
-rw-r--r--src/fe-gtk/fkeys.c153
-rw-r--r--src/fe-gtk/gtkutil.c4
-rw-r--r--src/fe-gtk/gtkutil.h8
-rw-r--r--src/fe-gtk/hexchat.rc.tt5
-rw-r--r--src/fe-gtk/joind.c12
-rw-r--r--src/fe-gtk/maingui.c166
-rw-r--r--src/fe-gtk/menu.c92
-rw-r--r--src/fe-gtk/notifications/notification-backend.h27
-rw-r--r--src/fe-gtk/notifications/notification-dummy.c39
-rw-r--r--src/fe-gtk/notifications/notification-libnotify.c72
-rw-r--r--src/fe-gtk/notifications/notification-osx.m54
-rw-r--r--src/fe-gtk/notifications/notification-windows.c87
-rw-r--r--src/fe-gtk/notifications/notification-winrt.cpp100
-rw-r--r--src/fe-gtk/notifications/notifications-winrt.vcxproj62
-rw-r--r--src/fe-gtk/notifications/notifications-winrt.vcxproj.filters22
-rw-r--r--src/fe-gtk/notifygui.c10
-rw-r--r--src/fe-gtk/palette.c56
-rw-r--r--src/fe-gtk/pixmaps.c3
-rw-r--r--src/fe-gtk/plugin-notification.c215
-rw-r--r--src/fe-gtk/plugin-notification.h25
-rw-r--r--src/fe-gtk/plugin-tray.c124
-rw-r--r--src/fe-gtk/plugingui.c33
-rw-r--r--src/fe-gtk/rawlog.c6
-rw-r--r--src/fe-gtk/servlistgui.c39
-rw-r--r--src/fe-gtk/setup.c118
-rw-r--r--src/fe-gtk/sexy-iso-codes.c3
-rw-r--r--src/fe-gtk/sexy-spell-entry.c34
-rw-r--r--src/fe-gtk/textgui.c36
-rw-r--r--src/fe-gtk/userlistgui.c116
-rw-r--r--src/fe-gtk/userlistgui.h2
-rw-r--r--src/fe-gtk/xtext.c249
-rw-r--r--src/fe-gtk/xtext.h2
-rw-r--r--src/fe-text/fe-text.c41
-rw-r--r--src/fe-text/fe-text.vcxproj60
-rw-r--r--src/htm/htm.csproj15
-rw-r--r--src/libenchant_win8/libenchant_win8.def2
-rw-r--r--src/libenchant_win8/libenchant_win8.vcxproj47
-rw-r--r--src/libenchant_win8/libenchant_win8.vcxproj.filters22
-rw-r--r--src/libenchant_win8/win8_provider.cpp293
-rw-r--r--win32/config.h.tt4
-rw-r--r--win32/copy/copy.vcxproj121
-rw-r--r--win32/copy/copy.vcxproj.filters49
-rw-r--r--win32/ext/nss-wdk/build-x64.bat13
-rw-r--r--win32/ext/nss-wdk/build-x86.bat13
-rw-r--r--win32/ext/nss-wdk/nss-wdk.patch257
-rw-r--r--win32/hexchat.exe.manifest (renamed from src/fe-gtk/hexchat.exe.manifest)12
-rw-r--r--win32/hexchat.props109
-rw-r--r--win32/hexchat.sln50
-rw-r--r--win32/installer/hexchat.iss.tt36
-rw-r--r--win32/installer/installer.vcxproj45
-rw-r--r--win32/nls/nls.vcxproj68
-rw-r--r--win32/version.txt2
-rw-r--r--win32/wdkpt/vs2010/Microsoft.Cpp.Win32.WDK7.props68
-rw-r--r--win32/wdkpt/vs2010/Microsoft.Cpp.Win32.WDK7.targets20
-rw-r--r--win32/wdkpt/vs2010/Microsoft.Cpp.x64.WDK7.props68
-rw-r--r--win32/wdkpt/vs2010/Microsoft.Cpp.x64.WDK7.targets20
-rw-r--r--win32/wdkpt/vs2010/wdkpt.aip137
-rw-r--r--win32/wdkpt/vs2012/Microsoft.Cpp.Win32.WDK7.props52
-rw-r--r--win32/wdkpt/vs2012/Microsoft.Cpp.Win32.WDK7.targets20
-rw-r--r--win32/wdkpt/vs2012/Microsoft.Cpp.x64.WDK7.props52
-rw-r--r--win32/wdkpt/vs2012/Microsoft.Cpp.x64.WDK7.targets20
-rw-r--r--win32/wdkpt/vs2012/wdkpt.aip138
207 files changed, 7439 insertions, 10340 deletions
diff --git a/.gitignore b/.gitignore
index 137204b8..63675ee5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
 # Unix generated files
 .deps/
 .libs/
+.dirstamp
 Makefile
 Makefile.in
 aclocal.m4
@@ -69,6 +70,7 @@ stamp-h1
 *.po~
 *.pot
 *.patch
+src/**/*.plist
 # Win32 generated files
 plugins/wmpa/wmpa_h.h
 plugins/wmpa/wmpa_i.c
@@ -85,6 +87,7 @@ resource.h
 *.sdf
 *.suo
 *.user
+*.exe
 #OSX
 osx/HexChat.app
 osx/.HexChat.app
diff --git a/.travis.yml b/.travis.yml
index f5f5d4b7..5f61475d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,19 +1,16 @@
 language: c
-compiler:
-    - gcc
-    - clang
+compiler: clang
 before_script:
     - sudo apt-get update
     - sudo apt-get build-dep -qq xchat
-    - sudo apt-get install -qq libnotify-dev libproxy-dev libpci-dev libcanberra-dev monodevelop gnome-common
+    - sudo apt-get install -qq libnotify-dev libproxy-dev libpci-dev libcanberra-dev monodevelop intltool
 script: 
-    - ./autogen.sh
-    - ./configure --enable-textfe --with-theme-manager
+    - ./autogen.sh --enable-textfe --with-theme-manager --enable-static-analysis
     - make V=1 -j$(nproc)
 notifications:
     irc:
         channels: "chat.freenode.net#hexchat-devel"
-        template: "Build #%{build_number} (%{commit}) by %{author}: %{message}"
+        template: "Build %{build_url} (%{commit} in %{branch}) by %{author}: %{message}"
         on_success: change
 matrix:
      fast_finish: true
diff --git a/autogen.sh b/autogen.sh
index b1e4db22..d669a37b 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -4,19 +4,24 @@
 srcdir=`dirname $0`
 test -z "$srcdir" && srcdir=.
 
-NOCONFIGURE=1
-PKG_NAME="hexchat"
-
 (test -f $srcdir/src/common/hexchat.c) || {
-	echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
-	echo " top-level $PKG_NAME directory"
+	echo -n "**Error**: Directory "\`$srcdir\'" does not look like the top-level directory"
 	exit 1
 }
 
-which gnome-autogen.sh || {
-	echo "You need to install gnome-common"
-	exit 1
-}
+aclocal --install -I m4 || exit 1
+glib-gettextize --force --copy || exit 1
+intltoolize --force --copy --automake || exit 1
+autoreconf --force --install -Wno-portability || exit 1
+
+if [ "$NOCONFIGURE" = "" ]; then
+        $srcdir/configure "$@" || exit 1
 
-. gnome-autogen.sh
+        if [ "$1" = "--help" ]; then exit 0 else
+                echo "Now type \`make\' to compile" || exit 1
+        fi
+else
+        echo "Skipping configure process."
+fi
 
+set +x
diff --git a/configure.ac b/configure.ac
index 61feba80..1c186016 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
 
 AC_INIT([HexChat],[2.11.0])
 
-AC_PREREQ([2.60])
+AC_PREREQ([2.64])
 AC_COPYRIGHT([Copyright (C) 1998-2010 Peter Zelezny])
 
 AC_CONFIG_HEADERS([config.h])
@@ -10,19 +10,25 @@ AC_CONFIG_SRCDIR([configure.ac])
 
 AC_CONFIG_MACRO_DIR([m4])
 
-AM_INIT_AUTOMAKE([1.11 dist-bzip2 subdir-objects no-define foreign])
+AM_INIT_AUTOMAKE([1.11.1 dist-bzip2 subdir-objects no-define foreign])
 AM_SILENT_RULES([yes])
 
+AX_IS_RELEASE([minor-version])
+AX_CHECK_ENABLE_DEBUG([yes])
+AX_REQUIRE_DEFINED([PKG_PROG_PKG_CONFIG])
+
 AC_USE_SYSTEM_EXTENSIONS
-AM_MAINTAINER_MODE
+AM_MAINTAINER_MODE([enable])
 AC_PROG_CC
 AM_PROG_CC_C_O
 AC_PROG_CPP
+AC_PROG_OBJC
 AM_PROG_AS
 AM_PROG_AR
-AM_DISABLE_STATIC
-AC_PROG_LIBTOOL
+LT_PREREQ([2.2.6])
+LT_INIT([disable-static])
 AC_PATH_PROG(MDTOOL, mdtool, no)
+PKG_PROG_PKG_CONFIG
 
 dnl -----------------------------------------------------------
 dnl Language Support
@@ -38,14 +44,12 @@ AH_VERBATIM([OLD_PERL],[#undef OLD_PERL])
 AH_VERBATIM([PREFIX],[#undef PREFIX])
 AH_VERBATIM([HEXCHATLIBDIR],[#undef HEXCHATLIBDIR])
 AH_VERBATIM([HEXCHATSHAREDIR],[#undef HEXCHATSHAREDIR])
-AH_VERBATIM([SOCKS],[#undef SOCKS])
-AH_VERBATIM([USE_MSPROXY],[#undef USE_MSPROXY])
 AH_VERBATIM([USE_LIBPROXY],[#undef USE_LIBPROXY])
+AH_VERBATIM([HAVE_LIBPCI],[#undef HAVE_LIBPCI])
 AH_VERBATIM([HAVE_ISO_CODES],[#undef HAVE_ISO_CODES])
 AH_VERBATIM([HAVE_GTK_MAC],[#undef HAVE_GTK_MAC])
 AH_VERBATIM([USE_LIBNOTIFY],[#undef USE_LIBNOTIFY])
 AH_VERBATIM([USE_LIBCANBERRA],[#undef USE_LIBCANBERRA])
-AH_VERBATIM([USE_IPV6],[#undef USE_IPV6])
 AH_VERBATIM([USE_OPENSSL],[#undef USE_OPENSSL])
 AH_VERBATIM([USE_PLUGIN],[#undef USE_PLUGIN])
 AH_VERBATIM([USE_SIGACTION],[#undef USE_SIGACTION])
@@ -55,37 +59,39 @@ AH_VERBATIM([socklen_t],[#undef socklen_t])
 AH_VERBATIM([USE_DBUS],[#undef USE_DBUS])
 
 AC_PATH_PROG(sedpath, sed)
-if test "_$sedpath" = _; then
+AS_IF([test "_$sedpath" = _], [
 	AC_MSG_ERROR(Cannot find sed: I need it!)
-fi
+])
 
 AC_PATH_PROG(unamepath, uname)
-if test "_$unamepath" = _; then
+AS_IF([test "_$unamepath" = _], [
 	system="unknown"
-else
+], [
 	AC_MSG_CHECKING(system type)
 	system=`$unamepath -s`
 	AC_MSG_RESULT($system)
-	if test "$system" = "Linux"; then
+	AS_IF([test "$system" = "Linux"], [
 		AC_DEFINE(USING_LINUX)
-	fi
-	if test "$system" = "FreeBSD"; then
+	], [test "$system" = "FreeBSD"], [
 		AC_DEFINE(USING_FREEBSD)
-	fi
-fi
+	])
+])
+
+platform_win32=no
+platform_osx=no
+AS_CASE([$host_os],
+	[*mingw*|*cygwin*|*msys*], [
+		platform_win32=yes
+	],
+	[darwin*], [
+		platform_osx=yes
+	]
+)
 
 dnl *********************************************************************
 dnl ** configure switches ***********************************************
 dnl *********************************************************************
 
-AC_ARG_ENABLE(socks,
-	[AS_HELP_STRING([--enable-socks],[link with SOCKS5 library (default: no)])],
-        socks=$enableval, socks=no)
-
-AC_ARG_ENABLE(ipv6,
-	[AS_HELP_STRING([--disable-ipv6],[disable IPv6])],
-        ipv6=$enableval, ipv6=yes)
-
 AC_ARG_ENABLE(openssl,
 	[AS_HELP_STRING([--enable-openssl[=PATH]],[enable use of openSSL])],
         openssl=$enableval, openssl=yes)
@@ -143,10 +149,6 @@ AC_ARG_ENABLE(libcanberra,
 	[AS_HELP_STRING([--disable-libcanberra],[disable libcanberra support])],
 		libcanberra=$enableval, libcanberra=yes)
 
-AC_ARG_ENABLE(ntlm,
-	[AS_HELP_STRING([--enable-ntlm],[enable Microsoft\'s NTLM auth (libntlm) library support (default: no)])],
-	ntlm=$enableval, ntlm=no)
-
 AC_ARG_ENABLE(libproxy,
 	[AS_HELP_STRING([--disable-libproxy],[disable libproxy support (default: auto)])],
         libproxy=$enableval, libproxy=auto)
@@ -155,9 +157,9 @@ AC_ARG_ENABLE(isocodes,
 	[AS_HELP_STRING([--disable-isocodes],[disable iso-codes with spell-check])],
         isocodes=$enableval, isocodes=yes)
 
-AC_ARG_ENABLE(minimal-flags,
-	[AS_HELP_STRING([--enable-minimal-flags],[only add those CFLAGS that are really needed or not intrusive (default: no)])],
-        minimalflags=$enableval, minimalflags=no)
+AC_ARG_ENABLE(static-analysis,
+	[AS_HELP_STRING([--enable-static-analysis],[if using clang run static analysis during build (default: no)])],
+        analyze=$enableval, analyze=no)
 
 AC_ARG_WITH(theme-manager,
 	[AS_HELP_STRING([--with-theme-manager],[compile theme manager (needs monodevelop, default: off)])],
@@ -168,174 +170,141 @@ AC_ARG_WITH(theme-manager,
 dnl *********************************************************************
 dnl ** THEME-MANAGER ****************************************************
 dnl *********************************************************************
-if test "x$theme_manager" != "xno" ; then
-	if test "x$MDTOOL" = "xno"; then
+AS_IF([test "x$theme_manager" != "xno"], [
+	AS_IF([test "x$MDTOOL" = "xno"], [
 		AC_MSG_ERROR([No "mdtool" found, you need to install monodevelop!])
-	fi
-fi
+	])
+])
 
 
 dnl *********************************************************************
 dnl ** GLIB *************************************************************
 dnl *********************************************************************
 
-AM_PATH_GLIB_2_0(2.28.0, glib=yes, glib=no)
-if test "$glib" = no; then
-	AC_MSG_ERROR(Cannot find GLib!)
-fi
-
-PKG_CHECK_MODULES([GOBJECT], [gobject-2.0], [], [AC_MSG_ERROR(Cannot find gobject-2.0!)])
-PKG_CHECK_MODULES([GIO], [gio-2.0], [], [AC_MSG_ERROR(Cannot find gio-2.0!)])
-PKG_CHECK_MODULES([GMODULE], [gmodule-2.0], [], [AC_MSG_ERROR(Cannot find gmodule-2.0!)])
-
-COMMON_CFLAGS="$GLIB_CFLAGS $GIO_CFLAGS $GOBJECT_CFLAGS $GMODULE_CFLAGS -DG_DISABLE_SINGLE_INCLUDES"
-COMMON_LIBS="$GLIB_LIBS $GIO_LIBS $GOBJECT_LIBS $GMODULE_LIBS"
+AM_PATH_GLIB_2_0([2.32.0], [], [AC_MSG_ERROR([Glib not found!])], [gmodule gobject gio])
+COMMON_CFLAGS="$GLIB_CFLAGS -DG_DISABLE_SINGLE_INCLUDES"
+COMMON_LIBS="$GLIB_LIBS"
+AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_32], [Dont warn using older APIs])
+AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_32], [Prevents using newer APIs])
 
 dnl *********************************************************************
 dnl ** GTK **************************************************************
 dnl *********************************************************************
 
-# we might get undefined macro without this test
-if test "$gtkfe" = yes ; then
-	AM_PATH_GTK_2_0(2.24.0, havegtk=yes, havegtk=no)
-
-	if test "$havegtk" = no; then
+AS_IF([test "$gtkfe" = yes], [
+	PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.24.0], [
+		GUI_LIBS="$GUI_LIBS $GTK_LIBS"
+		GUI_CFLAGS="$GUI_CFLAGS $GTK_CFLAGS -DGDK_PIXBUF_DISABLE_SINGLE_INCLUDES -DGTK_DISABLE_SINGLE_INCLUDES -DGTK_DISABLE_DEPRECATED"
+	], [
 		gtkfe=no
-		echo
-		echo Cannot find GTK\! Not building GTK FrontEnd.
-		echo
-	fi
-fi
-
-GUI_LIBS="$GUI_LIBS $GTK_LIBS"
-GUI_CFLAGS="$GUI_CFLAGS $GTK_CFLAGS -DG_DISABLE_SINGLE_INCLUDES -DGDK_PIXBUF_DISABLE_SINGLE_INCLUDES -DGTK_DISABLE_SINGLE_INCLUDES -DGTK_DISABLE_DEPRECATED"
+	])
+])
 
 dnl *********************************************************************
 dnl ** MAC_INTEGRATION **************************************************
 dnl *********************************************************************
 
 _gdk_tgt=`$PKG_CONFIG --variable=target gdk-2.0`
-if test "x$_gdk_tgt" = xquartz; then
-		PKG_CHECK_MODULES(GTK_MAC, gtk-mac-integration-gtk2, [
-			GUI_LIBS="$GUI_LIBS $GTK_MAC_LIBS"
-			GUI_CFLAGS="$GUI_CFLAGS $GTK_MAC_CFLAGS"
-			AC_DEFINE(HAVE_GTK_MAC)
-		])
-fi
+AS_IF([test "x$_gdk_tgt" = xquartz], [
+	PKG_CHECK_MODULES(GTK_MAC, gtk-mac-integration-gtk2, [
+		GUI_LIBS="$GUI_LIBS $GTK_MAC_LIBS"
+		GUI_CFLAGS="$GUI_CFLAGS $GTK_MAC_CFLAGS"
+		AC_DEFINE(HAVE_GTK_MAC)
+	])
+])
 
 dnl *********************************************************************
 dnl ** PERL *************************************************************
 dnl *********************************************************************
 
-if test "$perl" = yes; then
+AS_IF([test "$perl" = yes], [
 	AC_MSG_CHECKING(for plugin interface used by Perl)
-	if test "$plugin" = yes; then
+	AS_IF([test "$plugin" = yes], [
 		AC_MSG_RESULT([yes])
-		AC_PATH_PROG(perlpath, perl)
-		AC_MSG_CHECKING(for Perl compile flags)
-		PERL_CFLAGS=`$perlpath -MExtUtils::Embed -e ccopts 2>/dev/null`
-		if test "_$PERL_CFLAGS" = _ ; then
-			AC_MSG_RESULT([not found, building without perl.])
+
+		AX_PERL_EXT_FLAGS([PERL_CFLAGS], [PERL_LDFLAGS])
+		original_cflags="$CFLAGS"
+		original_ldflags="$LDFLAGS"
+		CFLAGS="$PERL_CFLAGS"
+		LDFLAGS="$PERL_LDFLAGS"
+		AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+				#define PERL_NO_INLINE_FUNCTIONS
+				#include <EXTERN.h>
+				#include <perl.h>
+			]], [[]])],[perl_is_usable=yes],[perl_is_usable=no])
+		CFLAGS="$original_cflags"
+		LDFLAGS="$original_ldflags"
+		AS_IF([test "$perl_is_usable" = "no"], [
+			AC_MSG_WARN([perl test failed to compile, disabling])
 			perl=no
-		else
-			PERL_LDFLAGS=`$perlpath -MExtUtils::Embed -e ldopts |$sedpath 's/-lgdbm //'`
-			PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-ldb //'`
-			PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lndbm //'`
-			if test "$system" = "Linux"; then
-				PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lnsl //'`
-				PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lposix //'`
-			fi
-			PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lc //'`
-			AC_MSG_RESULT(ok)
-
-			AC_MSG_CHECKING(for perl >= 5.8.0)
-			PERL_VER=`$perlpath -e 'print $]>= 5.008?"yes":"no"'`
-			if test "$PERL_VER" = "yes"; then
-				original_cflags="$CFLAGS"
-				original_ldflags="$LDFLAGS"
-				CFLAGS="$PERL_CFLAGS"
-				LDFLAGS="$PERL_LDFLAGS"
-				AC_TRY_LINK([#include <EXTERN.h>
-	#include <perl.h>], [], perl_is_usable=yes, perl_is_usable=no)
-				CFLAGS="$original_cflags"
-				LDFLAGS="$original_ldflags"
-				if test x$perl_is_usable = xno ; then
-					AC_MSG_RESULT(no)
-					perl=no
-				else
-					AC_MSG_RESULT(yes)
-					AC_MSG_CHECKING(if perl plugin will be backward compatible)
-					if test "$perl_old" = "yes"; then
-							  AC_MSG_RESULT(yes)
-							  AC_DEFINE(OLD_PERL)
-					else
-							  AC_MSG_RESULT(no)
-					fi
-				fi
-			else
-				AC_MSG_RESULT(no)
-				echo "perl version too old, building without perl."
-				perl=no
-			fi
-		fi
-	else
+		], [
+			AC_MSG_CHECKING([if perl plugin will be backward compatible])
+			AS_IF([test "$perl_old" = "yes"], [
+				  AC_MSG_RESULT([yes])
+				  AC_DEFINE(OLD_PERL)
+			], [
+				  AC_MSG_RESULT([no])
+			])
+		])
+	], [
 		AC_MSG_RESULT([plugins are disabled, use the --enable-plugin option for Perl])
 		perl=no
-	fi
-fi
+	])
+])
 
 dnl *********************************************************************
 dnl ** PYTHON ***********************************************************
 dnl *********************************************************************
 
-if test "x$python" != xno ; then
+AS_IF([test "x$python" != xno], [
 	AC_MSG_CHECKING(for plugin interface used by Python)
-	if test "$plugin" = yes; then
+	AS_IF([test "$plugin" = yes], [
 		AC_MSG_RESULT([yes])
-		case $python in
+		AS_CASE([$python],
 			dnl set python2 default here
-			python2)
+			[python2], [
 				PKG_CHECK_MODULES([PY], [python-2.7],
 								  [PY_VER="`$PKG_CONFIG --modversion python-2.7`"],
 								  [true])
-				;;
+			],
 			dnl set python3 default here
-			python3)
+			[python3], [
 				PKG_CHECK_MODULES([PY], [python-3.4],
 								  [PY_VER="`$PKG_CONFIG --modversion python-3.4`"],
 								  [true])
-				if test "$PY_VER" = "" ; then
+				AS_IF([test "$PY_VER" = ""], [
 					PKG_CHECK_MODULES([PY], [python-3.3],
 									  [PY_VER="`$PKG_CONFIG --modversion python-3.3`"],
 									  [true])
-				fi
-				;;
+				])
+			], 
 			dnl add broken versions here
-			python2.5|python2.6|python3.1|python3.2)
-				AC_MSG_WARN(Unsupported Python version ${python}!);;
-			python*)
+			[python2.5|python2.6|python3.1|python3.2], [
+				AC_MSG_WARN(Unsupported Python version ${python}!)
+			],
+			[python*], [
 				python="python-${python#python}" # stay posix compliant
 				PKG_CHECK_MODULES([PY], [${python}],
 								  [PY_VER="`$PKG_CONFIG --modversion ${python}`"],
 								  [AC_MSG_WARN(Cannot find "${python}.pc"!)])
-				;;
-			*)
+			],[
 				AC_MSG_WARN(Unsupported Python ${python}!)
-		esac
+			]
+		)
 		AC_MSG_CHECKING(Python version)
 
-		if test "$PY_VER"; then
+		AS_IF([test "$PY_VER"], [
 			AC_MSG_RESULT($PY_VER)
 			python="python-${PY_VER}"
-		else
+		], [
 			AC_MSG_RESULT(Not found)
 			python=no
-		fi
-	else
+		])
+	], [
 		AC_MSG_RESULT([plugins are disabled, use the --enable-plugin option for Python])
 		python=no
-	fi
-fi
+	])
+])
 
 dnl *********************************************************************
 dnl ** IPv6 *************************************************************
@@ -351,182 +320,175 @@ AC_CHECK_FUNC(select, ,
 						AC_MSG_WARN(i can not find select.  you might need to help me)))))))
 AC_CHECK_LIB(socket, select)
 
-if test "$ipv6" = yes; then
-	AC_CHECK_FUNCS(getaddrinfo, have_getaddrinfo=yes)
-	AC_MSG_CHECKING(whether to enable IPv6 support)
-	if test "$have_getaddrinfo" = yes; then
-		AC_MSG_RESULT(yes)
-		AC_DEFINE(USE_IPV6)
-	else
-		ipv6=no
-		AC_MSG_RESULT(no)
-	fi
-fi
+AC_CHECK_FUNCS(getaddrinfo, have_getaddrinfo=yes)
+AC_MSG_CHECKING(whether IPv6 is supported)
+AS_IF([test "$have_getaddrinfo" = yes], [
+	AC_MSG_RESULT(yes)
+], [
+	AC_MSG_RESULT(no)
+	AC_MSG_ERROR(ipv6 support not found!)
+])
 
 dnl *********************************************************************
 dnl ** OPENSSL **********************************************************
 dnl *********************************************************************
 
-retry=no
-if test "$openssl" != no; then
-	AC_MSG_CHECKING(for openssl through pkg-config)
-	if $PKG_CONFIG openssl --exists; then
-		CPPFLAGS="$CPPFLAGS `$PKG_CONFIG openssl --cflags`"
-		LIBS="$LIBS `$PKG_CONFIG openssl --libs`"
+
+AS_IF([test "$openssl" != no], [
+	PKG_CHECK_MODULES(OPENSSL, [openssl], [
 		AC_DEFINE(USE_OPENSSL)
-		AC_MSG_RESULT(yes)
 		openssl=yes
-	else
-		AC_MSG_RESULT(no)
-		retry=yes
-	fi
-fi
-
-if test "$retry" = "yes"; then
-	unset openssl_path ac_cv_lib_ssl_SSL_new ac_cv_header_openssl_ssl_h
-	if test "$openssl" != yes; then
-		openssl_path=$openssl
-	fi
-	openssl=no
-	SAVED_LIBS=$LIBS
-	LIBS="$LIBS -lcrypto"
-	if test -n "$openssl_path"; then
-		LIBS="-L$openssl_path/lib $LIBS"
-	fi
-	AC_CHECK_LIB(ssl, SSL_new, have_openssl=yes)
-	LIBS=$SAVED_LIBS
-	if test "$have_openssl" = yes; then
-		SAVED_CPPFLAGS=$CPPFLAGS
-		if test -n "$openssl_path"; then
-			CPPFLAGS="-I$openssl_path/include $CPPFLAGS"
-		fi
-		AC_CHECK_HEADERS(openssl/ssl.h, have_openssl_h=yes)
-		if test "$have_openssl_h" = yes; then
-			openssl=yes
-			AC_DEFINE(USE_OPENSSL)
-			LIBS="$LIBS -lssl -lcrypto"
-			if test -n "$openssl_path"; then
-				LIBS="-L$openssl_path/lib $LIBS"
-			fi
-		else
-			CPPFLAGS=$SAVED_CPPFLAGS
-		fi
-	fi
-fi
+		COMMON_LIBS="$COMMON_LIBS $OPENSSL_LIBS"
+		COMMON_CFLAGS="$COMMON_CFLAGS $OPENSSL_CFLAGS"
+	], [
+		unset openssl_path ac_cv_lib_ssl_SSL_new ac_cv_header_openssl_ssl_h
+		AS_IF([test "$openssl" != yes], [
+			openssl_path=$openssl
+		])
+		openssl=no
+		OPENSSL_LIBS="-lcrypto"
+		AS_IF([test -n "$openssl_path"], [
+			OPENSSL_LIBS="-L$openssl_path/lib $OPENSSL_LIBS"
+		])
+		SAVED_LIBS=$LIBS
+		LIBS="$LIBS $OPENSSL_LIBS"
+		AC_CHECK_LIB(ssl, SSL_new, [
+			AS_IF([test -n "$openssl_path"], [
+				OPENSSL_CFLAGS="-I$openssl_path/include"
+			])
+			SAVED_CFLAGS=$CFLAGS
+			CFLAGS="$CFLAGS $OPENSSL_CFLAGS"
+			AC_CHECK_HEADERS(openssl/ssl.h, [
+				openssl=yes
+				AC_DEFINE(USE_OPENSSL)
+				OPENSSL_LIBS="$OPENSSL_LIBS -lssl"
+
+				COMMON_LIBS="$COMMON_LIBS $OPENSSL_LIBS"
+				COMMON_CFLAGS="$COMMON_CFLAGS $OPENSSL_CFLAGS"
+			])
+			CFLAGS=$SAVED_CFLAGS
+		])
+		LIBS=$SAVED_LIBS
+	])
+])
 
 dnl *********************************************************************
 dnl ** LIBPROXY *********************************************************
 dnl *********************************************************************
 
-if test "x$libproxy" = "xyes" -o "x$libproxy" = "xauto" ; then
+AS_IF([test "x$libproxy" = "xyes" -o "x$libproxy" = "xauto"], [
 	PKG_CHECK_MODULES([LIBPROXY], [libproxy-1.0], [
 		COMMON_LIBS="$COMMON_LIBS $LIBPROXY_LIBS"
 		COMMON_CFLAGS="$COMMON_CFLAGS $LIBPROXY_CFLAGS"
 		AC_DEFINE(USE_LIBPROXY)
 		libproxy=yes
 	], [
-		if test "x$libproxy" = "xyes" ; then
+		AS_IF([test "x$libproxy" = "xyes"], [
 			AC_MSG_ERROR(Cannot find libproxy!)
-		fi
+		])
 		libproxy=no
 	])
-else
+], [
 	libproxy=no
-fi
+])
 
 dnl *********************************************************************
 dnl ** PLUGIN ***********************************************************
 dnl *********************************************************************
 
-if test "$plugin" = yes; then
+AS_IF([test "$plugin" = yes], [
 	AC_DEFINE(USE_PLUGIN)
-fi
+	PLUGIN_LDFLAGS="-avoid-version"
+	AS_IF([test "$platform_win32" = yes], [
+		PLUGIN_LDFLAGS="$PLUGIN_LDFLAGS -no-undefined"
+	])
+])
 
 dnl *********************************************************************
 dnl ** Checksum *********************************************************
 dnl *********************************************************************
 
-if test "$checksum" != "no"; then
+AS_IF([test "$checksum" != "no"], [
 	checksum=no
 	AC_MSG_CHECKING(for plugin interface used by Checksum)
-	if test "$plugin" = yes; then
+	AS_IF([test "$plugin" = yes], [
+		checksum=yes
 		AC_MSG_RESULT([yes])
-		AC_MSG_CHECKING(for OpenSSL used by Checksum)
-		if test "$openssl" = yes; then
-			checksum=yes
-			AC_MSG_RESULT([yes])
-		else
-			AC_MSG_RESULT([OpenSSL cannot be found, use the --enable-openssl option])
-		fi
-	else
+	], [
 		AC_MSG_RESULT([plugins are disabled, use the --enable-plugin option])
-	fi
-fi
+	])
+])
 
 dnl *********************************************************************
 dnl ** DO AT ************************************************************
 dnl *********************************************************************
 
-if test "$doat" != "no"; then
+AS_IF([test "$doat" != "no"], [
 	AC_MSG_CHECKING(for plugin interface used by Do At)
 	doat=no
-	if test "$plugin" = yes; then
+	AS_IF([test "$plugin" = yes], [
 		doat=yes
 		AC_MSG_RESULT([yes])
-	else
+	], [
 		AC_MSG_RESULT([plugins are disabled, use the --enable-plugin option for Do At])
-	fi
-fi
+	])
+])
 
 dnl *********************************************************************
 dnl ** FiSHLiM **********************************************************
 dnl *********************************************************************
 
-if test "$fishlim" != "no"; then
+AS_IF([test "$fishlim" != "no"], [
 	fishlim=no
 	AC_MSG_CHECKING(for plugin interface used by FiSHLiM)
-	if test "$plugin" = yes; then
+	AS_IF([test "$plugin" = yes], [
 		AC_MSG_RESULT([yes])
 		AC_MSG_CHECKING(for OpenSSL used by FiSHLiM)
-		if test "$openssl" = yes; then
+		AS_IF([test "$openssl" = yes], [
 			fishlim=yes
 			AC_MSG_RESULT([yes])
-		else
+		], [
 			AC_MSG_RESULT([OpenSSL cannot be found, use the --enable-openssl option])
-		fi
-	else
+		])
+	], [
 		AC_MSG_RESULT([plugins are disabled, use the --enable-plugin option])
-	fi
-fi
+	])
+])
 
 dnl *********************************************************************
 dnl ** SYSINFO **********************************************************
 dnl *********************************************************************
 
-if test "$sysinfo" != "no"; then
+AS_IF([test "$sysinfo" != "no"], [
 	AC_MSG_CHECKING(for plugin interface used by SysInfo)
-	if test "$plugin" = yes; then
+	AS_IF([test "$plugin" = yes], [
 		AC_MSG_RESULT([yes])
-		PKG_CHECK_MODULES(LIBPCI, libpci >= 3.0.0, [sysinfo=yes], [sysinfo=no])
-	else
+		AS_IF([test "$platform_osx" = yes], [
+			sysinfo=yes
+		], [
+			PKG_CHECK_MODULES(LIBPCI, libpci >= 3.0.0, [
+				sysinfo=yes
+				AC_DEFINE(HAVE_LIBPCI)
+			], [sysinfo=no])
+		])
+	], [
 		AC_MSG_RESULT([plugins are disabled, use the --enable-plugin option for SysInfo])
 		sysinfo=no
-	fi
-fi
+	])
+])
 
 dnl #######################################################################
 dnl # Check for DBUS libraries
 dnl #######################################################################
 
-if test "x$dbus" = "xyes" ; then
+AS_IF([test "x$dbus" = "xyes"], [
 	PKG_CHECK_MODULES(DBUS, [dbus-1 >= 0.60 dbus-glib-1 >= 0.60 gthread-2.0], dbus=yes, [
 		dbus=no
 	])
 	AC_PATH_PROG(DBUS_BINDING_TOOL, dbus-binding-tool, no)
-	AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal, no)
-	if test "x$DBUS_BINDING_TOOL" = "xno" || test "x$GLIB_GENMARSHAL" = "xno" || test "x$dbus" = "xno" ; then
+	AS_IF([test "x$DBUS_BINDING_TOOL" = "xno" || test "x$dbus" = "xno"], [
 		dbus="no"
-	else
+	], [
 		COMMON_LIBS="$COMMON_LIBS $DBUS_LIBS"
 		COMMON_CFLAGS="$COMMON_CFLAGS $DBUS_CFLAGS"
 		AC_DEFINE(USE_DBUS)
@@ -534,44 +496,44 @@ if test "x$dbus" = "xyes" ; then
 		AS_AC_EXPAND(DBUS_SERVICES_DIR, "$datadir/dbus-1/services")
 		AC_SUBST(DBUS_SERVICES_DIR)
 		AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for DBUS is])
-	fi
-fi
+	])
+])
 
 dnl *********************************************************************
 dnl ** LIBNOTIFY ********************************************************
 dnl *********************************************************************
 
-if test "x$libnotify" = "xyes" ; then
+AS_IF([test "x$libnotify" = "xyes"], [
 	PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= 0.4, [], [
 		libnotify=no
 	])
-	if test "$libnotify" != "no" ; then
+	AS_IF([test "$libnotify" != "no"], [
 		GUI_LIBS="$GUI_LIBS $LIBNOTIFY_LIBS"
 		GUI_CFLAGS="$GUI_CFLAGS $LIBNOTIFY_CFLAGS"
 		AC_DEFINE(USE_LIBNOTIFY)
-	fi
-fi
+	])
+])
 
 dnl *********************************************************************
 dnl ** LIBCANBERRA ******************************************************
 dnl *********************************************************************
 
-if test "x$libcanberra" = "xyes" ; then
+AS_IF([test "x$libcanberra" = "xyes"], [
 	PKG_CHECK_MODULES(LIBCANBERRA, libcanberra >= 0.22, [], [
 		libcanberra=no
 	])
-	if test "$libcanberra" != "no" ; then
+	AS_IF([test "$libcanberra" != "no"], [
 		COMMON_LIBS="$COMMON_LIBS $LIBCANBERRA_LIBS"
 		COMMON_CFLAGS="$COMMON_CFLAGS $LIBCANBERRA_CFLAGS"
 		AC_DEFINE(USE_LIBCANBERRA)
-	fi
-fi
+	])
+])
 
 dnl *********************************************************************
 dnl ** SPELL ************************************************************
 dnl *********************************************************************
 
-if test "x$isocodes" = "xyes" ; then
+AS_IF([test "x$isocodes" = "xyes"], [
 	PKG_CHECK_MODULES(ISOCODES, "iso-codes", [
 		iso_codes_prefix=`$PKG_CONFIG --variable=prefix iso-codes 2>/dev/null || echo /usr`
     	AC_MSG_NOTICE([iso-codes prefix: $iso_codes_prefix])
@@ -582,7 +544,18 @@ if test "x$isocodes" = "xyes" ; then
     	isocodes=no
     	AC_MSG_WARN(iso-codes not found!)
     ])
-fi
+])
+
+dnl *********************************************************************
+dnl ** Static Analysis **************************************************
+dnl *********************************************************************
+
+AS_IF([test "x$analyze" = "xyes"], [
+	AS_IF([test "$CC" != "clang"], [
+		AC_MSG_WARN(CC is not clang for static analysis)
+		analyze=no
+	])
+])
 
 dnl *********************************************************************
 dnl ** CONDITIONALS *****************************************************
@@ -591,7 +564,6 @@ dnl *********************************************************************
 AM_CONDITIONAL(USE_OPENSSL, test "x$openssl" = "xyes")
 AM_CONDITIONAL(USE_LIBNOTIFY, test "x$libnotify" = "xyes")
 AM_CONDITIONAL(USE_LIBCANBERRA, test "x$libcanberra" = "xyes")
-AM_CONDITIONAL(USE_MSPROXY, test "x$ntlm" = "xyes")
 AM_CONDITIONAL(DO_TEXT, test "x$textfe" = "xyes")
 AM_CONDITIONAL(DO_GTK, test "x$gtkfe" = "xyes")
 AM_CONDITIONAL(DO_PERL, test "x$perl" = "xyes")
@@ -601,128 +573,30 @@ AM_CONDITIONAL(DO_CHECKSUM, test "x$checksum" = "xyes")
 AM_CONDITIONAL(DO_DOAT, test "x$doat" = "xyes")
 AM_CONDITIONAL(DO_FISHLIM, test "x$fishlim" = "xyes")
 AM_CONDITIONAL(DO_SYSINFO, test "x$sysinfo" = "xyes")
+AM_CONDITIONAL(DO_STATIC_ANALYSIS, test "x$analyze" = "xyes")
 AM_CONDITIONAL(USE_DBUS, test "x$dbus" = "xyes")
 AM_CONDITIONAL(HAVE_ISO_CODES, test "x$isocodes" = "xyes")
+AM_CONDITIONAL(HAVE_GTK_MAC, test "x$_gdk_tgt" = xquartz)
 AM_CONDITIONAL(WITH_TM, test "x$theme_manager" != "xno")
+AM_CONDITIONAL(PLATFORM_OSX, test "x$platform_osx" == "xyes")
 
 dnl *********************************************************************
-dnl ** SOCKS5 ***********************************************************
+dnl ** CFLAGS ***********************************************************
 dnl *********************************************************************
 
-if test "$socks" = yes; then
-	socks=no
-	AC_CHECK_LIB(socks5, SOCKSconnect, have_socks=yes)
-	if test "$have_socks" = yes; then
-		AC_CHECK_HEADERS(socks.h, have_socks_h=yes)
-		if test "$have_socks_h" = yes; then
-			socks=yes
-			AC_DEFINE(SOCKS)
-			LIBS="$LIBS -lsocks5"
-		fi
-	fi
-fi
-
-dnl *********************************************************************
-dnl ** MS PROXY *********************************************************
-dnl *********************************************************************
-
-have_ntlm="no"
-if test "x$ntlm" = "xyes" ; then
-	have_ntlm="no"
-	AC_CHECK_LIB(ntlm, ntlm_smb_encrypt, have_ntlm=yes)
-	if test "$have_ntlm" = yes; then
-		LIBS="$LIBS -lntlm"
-		AC_DEFINE(USE_MSPROXY)
-	fi
-fi
-
-dnl *********************************************************************
-dnl ** GCC FLAGS ********************************************************
-dnl *********************************************************************
-
-dnl Only use -Wall and -pipe if we have gcc
-if test "x$GCC" = "xyes"; then
-	if test -z "`echo "$CFLAGS" | grep "\-Wall" 2> /dev/null`" ; then
-		CFLAGS="$CFLAGS -Wall"
-	fi
-	dnl these flags might be unwanted
-	if test x$minimalflags != xyes; then
-		if test "$system" = "Linux" -o "$system" = "FreeBSD"; then
-			if test -z "`echo "$CFLAGS" | grep "\-pipe" 2> /dev/null`" ; then
-				CFLAGS="$CFLAGS -pipe"
-			fi
-		fi
-		if test -z "`echo "$CFLAGS" | grep "\-g " 2> /dev/null`" ; then
-			CFLAGS="$CFLAGS -g"
-		fi
-	fi
-fi
-
-dnl does this compiler support -Wno-pointer-sign ?
-AC_MSG_CHECKING([if $CC accepts -Wno-pointer-sign ])
-
-safe_CFLAGS=$CFLAGS
-CFLAGS="-Wno-pointer-sign"
-
-AC_TRY_COMPILE(, [
-return 0;
-],
-[
-no_pointer_sign=yes
-AC_MSG_RESULT([yes])
-], [
-no_pointer_sign=no
-AC_MSG_RESULT([no])
-])
-CFLAGS=$safe_CFLAGS
-
-if test x$no_pointer_sign = xyes; then
-	CFLAGS="$CFLAGS -Wno-pointer-sign"
-fi
-
-dnl does this compiler support -funsigned-char ?
-AC_MSG_CHECKING([if $CC accepts -funsigned-char ])
-
-safe_CFLAGS=$CFLAGS
-CFLAGS="-funsigned-char"
-
-AC_TRY_COMPILE(, [
-return 0;
-],
-[
-unsigned_char=yes
-AC_MSG_RESULT([yes])
-], [
-unsigned_char=no
-AC_MSG_RESULT([no])
+CC_CHECK_FLAGS_APPEND([CFLAGS], [CFLAGS], [ \
+	-pipe \
+	-funsigned-char \
+	-Wall \
+	-Wextra \
+	-Wno-unused-parameter \
+	-Wno-sign-compare \
+	-Wno-pointer-sign \
+	-Wno-missing-field-initializers \
+	-Wno-unused-result \
+	-Werror=format-security \
+	-Werror=declaration-after-statement \
 ])
-CFLAGS=$safe_CFLAGS
-
-if test x$unsigned_char = xyes; then
-	CFLAGS="$CFLAGS -funsigned-char"
-fi
-
-dnl does this compiler support -Wno-unused-result ?
-AC_MSG_CHECKING([if $CC accepts -Wno-unused-result ])
-
-safe_CFLAGS=$CFLAGS
-CFLAGS="-Wno-unused-result"
-
-AC_TRY_COMPILE(, [
-return 0;
-],
-[
-no_unused_result=yes
-AC_MSG_RESULT([yes])
-], [
-no_unused_result=no
-AC_MSG_RESULT([no])
-])
-CFLAGS=$safe_CFLAGS
-
-if test x$no_unused_result = xyes; then
-	CFLAGS="$CFLAGS -Wno-unused-result"
-fi
 
 dnl *********************************************************************
 dnl ** FUNCTIONS/LIBS/CFLAGS ********************************************
@@ -731,19 +605,14 @@ dnl *********************************************************************
 AC_MSG_CHECKING(for modern sigaction)
 dnl libc5 on linux and FreeBSD 3.x doesn\'t have siginfo_t
 dnl and the sa_sigation field.
-AC_TRY_COMPILE(
-	[#include <signal.h>],
-	[struct sigaction act;
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <signal.h>]], [[struct sigaction act;
 	 siginfo_t *si;
-	 act.sa_sigaction = 0;],
-	[
+	 act.sa_sigaction = 0;]])],[
 		AC_MSG_RESULT(yes)
 		AC_DEFINE(USE_SIGACTION) 
-	],
-	AC_MSG_RESULT(no))
+	],[AC_MSG_RESULT(no)])
 
-dnl if we don\'t have this, use g_snprintf instead
-AC_CHECK_FUNCS(snprintf vsnprintf memrchr strtoull)
+AC_CHECK_FUNCS(memrchr)
 
 AC_CHECK_FUNC(gethostbyname, ,
 	AC_CHECK_LIB(resolv, gethostbyname, ,
@@ -765,9 +634,9 @@ AC_EGREP_CPP([socklen_t[^a-zA-Z_0-9]], [#include <sys/types.h>
 ac_cv_type_socklen_t=yes,
 ac_cv_type_socklen_t=no)
 ])
-if test $ac_cv_type_socklen_t = no; then
+AS_IF([test $ac_cv_type_socklen_t = no], [
 	AC_DEFINE(socklen_t, int)
-fi
+])
 
 dnl Mac OS X and Darwin use lookupd, which caches DNS queries by default
 AC_EGREP_CPP(lookupd, dnl
@@ -777,7 +646,6 @@ AC_EGREP_CPP(lookupd, dnl
 
 dnl freebsd needs this
 LIBS="$LIBS $INTLLIBS"
-CFLAGS="$CFLAGS $CPPFLAGS"
 
 GUI_LIBS="$GUI_LIBS $COMMON_LIBS"
 
@@ -792,15 +660,19 @@ AC_SUBST(PY_CFLAGS)
 AC_SUBST(PY_LIBS)
 AC_SUBST(DBUS_CFLAGS)
 AC_SUBST(DBUS_LIBS)
+AC_SUBST(OPENSSL_LIBS)
+AC_SUBST(OPENSSL_CFLAGS)
+AC_SUBST(PLUGIN_LDFLAGS)
 
 m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR], AC_SUBST([pkgconfigdir], ${libdir}/pkgconfig))
 
-PLUGIN_INCLUDES='-I$(top_srcdir)/plugins'
-AC_SUBST(PLUGIN_INCLUDES)
-
 dnl for plugin.c and pixmaps.c
-test "x$prefix" = xNONE && prefix="$ac_default_prefix"
-test "x$exec_prefix" = xNONE && exec_prefix="$prefix"
+AS_IF([test "x$prefix" = xNONE], [
+	prefix="$ac_default_prefix"
+])
+AS_IF([test "x$exec_prefix" = xNONE], [
+	exec_prefix="$prefix"
+])
 
 AC_DEFINE_UNQUOTED(PREFIX, "${prefix}")
 
@@ -855,8 +727,6 @@ echo D-Bus support ......... : $dbus
 echo libnotify support ..... : $libnotify
 echo libcanberra support ... : $libcanberra
 echo Plugin interface ...... : $plugin
-echo IPv6 support .......... : $ipv6
-echo MS Proxy NTLM \(ISA\) ... : $have_ntlm
 echo libproxy support ...... : $libproxy
 echo
 echo Perl .................. : $perl
@@ -867,6 +737,8 @@ echo Do At ................. : $doat
 echo FiSHLiM ............... : $fishlim
 echo SysInfo ............... : $sysinfo
 echo
+echo Debug mode ............ : $enable_debug
+echo
 echo The binary will be installed in $prefix/bin
 echo
 
diff --git a/m4/ac-check-cflags.m4 b/m4/ac-check-cflags.m4
new file mode 100644
index 00000000..a45b17f0
--- /dev/null
+++ b/m4/ac-check-cflags.m4
@@ -0,0 +1,60 @@
+dnl Macros to check the presence of generic (non-typed) symbols.
+dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes@gmail.com>
+dnl Copyright (c) 2006-2008 xine project
+dnl Copyright (c) 2012 Lucas De Marchi <lucas.de.marchi@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+dnl 02110-1301, USA.
+dnl
+dnl As a special exception, the copyright owners of the
+dnl macro gives unlimited permission to copy, distribute and modify the
+dnl configure scripts that are the output of Autoconf when processing the
+dnl Macro. You need not follow the terms of the GNU General Public
+dnl License when using or distributing such scripts, even though portions
+dnl of the text of the Macro appear in them. The GNU General Public
+dnl License (GPL) does govern all other use of the material that
+dnl constitutes the Autoconf Macro.
+dnl
+dnl This special exception to the GPL applies to versions of the
+dnl Autoconf Macro released by this project. When you make and
+dnl distribute a modified version of the Autoconf Macro, you may extend
+dnl this special exception to the GPL to apply to your modified version as
+dnl well.
+
+dnl Check if FLAG in ENV-VAR is supported by compiler and append it
+dnl to WHERE-TO-APPEND variable
+dnl CC_CHECK_FLAG_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG])
+
+AC_DEFUN([CC_CHECK_FLAG_APPEND], [
+  AC_CACHE_CHECK([if $CC supports flag $3 in envvar $2],
+                 AS_TR_SH([cc_cv_$2_$3]),
+		 [eval "AS_TR_SH([cc_save_$2])='${$2}'"
+		  eval "AS_TR_SH([$2])='$3'"
+		  AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a = 0; int main(void) { return a; } ])],
+                                    [eval "AS_TR_SH([cc_cv_$2_$3])='yes'"],
+                                    [eval "AS_TR_SH([cc_cv_$2_$3])='no'"])
+		  eval "AS_TR_SH([$2])='$cc_save_$2'"])
+
+  AS_IF([eval test x$]AS_TR_SH([cc_cv_$2_$3])[ = xyes],
+        [eval "$1='${$1} $3'"])
+])
+
+dnl CC_CHECK_FLAGS_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG1 FLAG2])
+AC_DEFUN([CC_CHECK_FLAGS_APPEND], [
+  for flag in $3; do
+    CC_CHECK_FLAG_APPEND($1, $2, $flag)
+  done
+])
+
diff --git a/m4/ax_check_enable_debug.m4 b/m4/ax_check_enable_debug.m4
new file mode 100644
index 00000000..f99d75fe
--- /dev/null
+++ b/m4/ax_check_enable_debug.m4
@@ -0,0 +1,124 @@
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_check_enable_debug.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_ENABLE_DEBUG([enable by default=yes/info/profile/no], [ENABLE DEBUG VARIABLES ...], [DISABLE DEBUG VARIABLES NDEBUG ...], [IS-RELEASE])
+#
+# DESCRIPTION
+#
+#   Check for the presence of an --enable-debug option to configure, with
+#   the specified default value used when the option is not present.  Return
+#   the value in the variable $ax_enable_debug.
+#
+#   Specifying 'yes' adds '-g -O0' to the compilation flags for all
+#   languages. Specifying 'info' adds '-g' to the compilation flags.
+#   Specifying 'profile' adds '-g -pg' to the compilation flags and '-pg' to
+#   the linking flags. Otherwise, nothing is added.
+#
+#   Define the variables listed in the second argument if debug is enabled,
+#   defaulting to no variables.  Defines the variables listed in the third
+#   argument if debug is disabled, defaulting to NDEBUG.  All lists of
+#   variables should be space-separated.
+#
+#   If debug is not enabled, ensure AC_PROG_* will not add debugging flags.
+#   Should be invoked prior to any AC_PROG_* compiler checks.
+#
+#   IS-RELEASE can be used to change the default to 'no' when making a
+#   release.  Set IS-RELEASE to 'yes' or 'no' as appropriate. By default, it
+#   uses the value of $ax_is_release, so if you are using the AX_IS_RELEASE
+#   macro, there is no need to pass this parameter.
+#
+#     AX_IS_RELEASE([git-directory])
+#     AX_CHECK_ENABLE_DEBUG()
+#
+# LICENSE
+#
+#   Copyright (c) 2011 Rhys Ulerich <rhys.ulerich@gmail.com>
+#   Copyright (c) 2014, 2015 Philip Withnall <philip@tecnocode.co.uk>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.
+
+#serial 5
+
+AC_DEFUN([AX_CHECK_ENABLE_DEBUG],[
+    AC_BEFORE([$0],[AC_PROG_CC])dnl
+    AC_BEFORE([$0],[AC_PROG_CXX])dnl
+    AC_BEFORE([$0],[AC_PROG_F77])dnl
+    AC_BEFORE([$0],[AC_PROG_FC])dnl
+
+    AC_MSG_CHECKING(whether to enable debugging)
+
+    ax_enable_debug_default=m4_tolower(m4_normalize(ifelse([$1],,[no],[$1])))
+    ax_enable_debug_is_release=m4_tolower(m4_normalize(ifelse([$4],,
+                                                              [$ax_is_release],
+                                                              [$4])))
+
+    # If this is a release, override the default.
+    AS_IF([test "$ax_enable_debug_is_release" = "yes"],
+      [ax_enable_debug_default="no"])
+
+    m4_define(ax_enable_debug_vars,[m4_normalize(ifelse([$2],,,[$2]))])
+    m4_define(ax_disable_debug_vars,[m4_normalize(ifelse([$3],,[NDEBUG],[$3]))])
+
+    AC_ARG_ENABLE(debug,
+	[AS_HELP_STRING([--enable-debug=]@<:@yes/info/profile/no@:>@,[compile with debugging])],
+	[],enable_debug=$ax_enable_debug_default)
+
+    # empty mean debug yes
+    AS_IF([test "x$enable_debug" = "x"],
+      [enable_debug="yes"])
+
+    # case of debug
+    AS_CASE([$enable_debug],
+      [yes],[
+	AC_MSG_RESULT(yes)
+	CFLAGS="${CFLAGS} -g -O0"
+	CXXFLAGS="${CXXFLAGS} -g -O0"
+	FFLAGS="${FFLAGS} -g -O0"
+	FCFLAGS="${FCFLAGS} -g -O0"
+	OBJCFLAGS="${OBJCFLAGS} -g -O0"
+      ],
+      [info],[
+	AC_MSG_RESULT(info)
+	CFLAGS="${CFLAGS} -g"
+	CXXFLAGS="${CXXFLAGS} -g"
+	FFLAGS="${FFLAGS} -g"
+	FCFLAGS="${FCFLAGS} -g"
+	OBJCFLAGS="${OBJCFLAGS} -g"
+      ],
+      [profile],[
+	AC_MSG_RESULT(profile)
+	CFLAGS="${CFLAGS} -g -pg"
+	CXXFLAGS="${CXXFLAGS} -g -pg"
+	FFLAGS="${FFLAGS} -g -pg"
+	FCFLAGS="${FCFLAGS} -g -pg"
+	OBJCFLAGS="${OBJCFLAGS} -g -pg"
+	LDFLAGS="${LDFLAGS} -pg"
+      ],
+      [
+	AC_MSG_RESULT(no)
+	dnl Ensure AC_PROG_CC/CXX/F77/FC/OBJC will not enable debug flags
+	dnl by setting any unset environment flag variables
+	AS_IF([test "x${CFLAGS+set}" != "xset"],
+	  [CFLAGS=""])
+	AS_IF([test "x${CXXFLAGS+set}" != "xset"],
+	  [CXXFLAGS=""])
+	AS_IF([test "x${FFLAGS+set}" != "xset"],
+	  [FFLAGS=""])
+	AS_IF([test "x${FCFLAGS+set}" != "xset"],
+	  [FCFLAGS=""])
+	AS_IF([test "x${OBJCFLAGS+set}" != "xset"],
+	  [OBJCFLAGS=""])
+      ])
+
+    dnl Define various variables if debugging is disabled.
+    dnl assert.h is a NOP if NDEBUG is defined, so define it by default.
+    AS_IF([test "x$enable_debug" = "xyes"],
+      [m4_map_args_w(ax_enable_debug_vars, [AC_DEFINE(], [,,[Define if debugging is enabled])])],
+      [m4_map_args_w(ax_disable_debug_vars, [AC_DEFINE(], [,,[Define if debugging is disabled])])])
+    ax_enable_debug=$enable_debug
+])
diff --git a/m4/ax_is_release.m4 b/m4/ax_is_release.m4
new file mode 100644
index 00000000..9ec67469
--- /dev/null
+++ b/m4/ax_is_release.m4
@@ -0,0 +1,69 @@
+# ===========================================================================
+#       http://www.gnu.org/software/autoconf-archive/ax_is_release.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_IS_RELEASE(POLICY)
+#
+# DESCRIPTION
+#
+#   Determine whether the code is being configured as a release, or from
+#   git. Set the ax_is_release variable to 'yes' or 'no'.
+#
+#   If building a release version, it is recommended that the configure
+#   script disable compiler errors and debug features, by conditionalising
+#   them on the ax_is_release variable.  If building from git, these
+#   features should be enabled.
+#
+#   The POLICY parameter specifies how ax_is_release is determined. It can
+#   take the following values:
+#
+#    * git-directory:  ax_is_release will be 'no' if a '.git' directory exists
+#    * minor-version:  ax_is_release will be 'no' if the minor version number
+#                      in $PACKAGE_VERSION is odd; this assumes
+#                      $PACKAGE_VERSION follows the 'major.minor.micro' scheme
+#    * micro-version:  ax_is_release will be 'no' if the micro version number
+#                      in $PACKAGE_VERSION is odd; this assumes
+#                      $PACKAGE_VERSION follows the 'major.minor.micro' scheme
+#    * always:         ax_is_release will always be 'yes'
+#    * never:          ax_is_release will always be 'no'
+#
+#   Other policies may be added in future.
+#
+# LICENSE
+#
+#   Copyright (c) 2015 Philip Withnall <philip@tecnocode.co.uk>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.
+
+#serial 3
+
+AC_DEFUN([AX_IS_RELEASE],[
+    AC_BEFORE([AC_INIT],[$0])
+
+    m4_case([$1],
+      [git-directory],[
+        # $is_release = (.git directory does not exist)
+        AS_IF([test -d .git],[ax_is_release=no],[ax_is_release=yes])
+      ],
+      [minor-version],[
+        # $is_release = ($minor_version is even)
+        minor_version=`echo "$PACKAGE_VERSION" | sed 's/[[^.]][[^.]]*.\([[^.]][[^.]]*\).*/\1/'`
+        AS_IF([test "$(( $minor_version % 2 ))" -ne 0],
+              [ax_is_release=no],[ax_is_release=yes])
+      ],
+      [micro-version],[
+        # $is_release = ($micro_version is even)
+        micro_version=`echo "$PACKAGE_VERSION" | sed 's/[[^.]]*\.[[^.]]*\.\([[^.]]*\).*/\1/'`
+        AS_IF([test "$(( $micro_version % 2 ))" -ne 0],
+              [ax_is_release=no],[ax_is_release=yes])
+      ],
+      [always],[ax_is_release=yes],
+      [never],[ax_is_release=no],
+      [
+        AC_MSG_ERROR([Invalid policy. Valid policies: git-directory, minor-version.])
+      ])
+])
diff --git a/m4/ax_perl_ext_flags.m4 b/m4/ax_perl_ext_flags.m4
new file mode 100644
index 00000000..03f16435
--- /dev/null
+++ b/m4/ax_perl_ext_flags.m4
@@ -0,0 +1,116 @@
+# ===========================================================================
+#     http://www.gnu.org/software/autoconf-archive/ax_perl_ext_flags.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_PERL_EXT_FLAGS([CFLAGS-VARIABLE], [LDFLAGS-VARIABLE], [EXTRA-MODULES])
+#   AX_PERL_EXT_CFLAGS([CFLAGS-VARIABLE])
+#   AX_PERL_EXT_LDFLAGS([LDFLAGS-VARIABLE], [EXTRA-MODULES])
+#
+# DESCRIPTION
+#
+#   Fetches the linker flags and C compiler flags for compiling and linking
+#   programs that embed a Perl interpreter. If the EXTRA-MODULES argument is
+#   submitted, it is a space separated list of extra modules to link. The
+#   flags will be stored in the provided variables.
+#
+#   Examples:
+#
+#     AX_PERL_EXT_FLAGS([PERLXS_CFLAGS], [PERLXS_LDFLAGS])
+#     AC_SUBST([PERLXS_CFLAGS])
+#     AC_SUBST([PERLXS_LDFLAGS])
+#
+#     AX_PERL_EXT_CFLAGS([PERLXS_CFLAGS])
+#     AC_SUBST([PERLXS_CFLAGS])
+#
+#     AX_PERL_EXT_LDFLAGS([PERLXS_LDFLAGS], [-std Socket])
+#
+# LICENSE
+#
+#   Copyright (c) 2009 Mats Kindahl of Sun Microsystems <mats@sun.com>
+#
+#   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.
+
+#serial 5
+
+AC_DEFUN([AX_PERL_EXT_CFLAGS],
+[AC_CHECK_PROG(PERL,perl,perl)
+ _AX_PERL_EXT_MODULE_CHECK([ExtUtils::Embed], [have_embed=yes],
+                           [have_embed=no])
+ AS_IF([test $have_embed = no],
+       AC_MSG_ERROR([Require ExtUtils::Embed to proceed]))
+ _AX_PERL_EXT_EMBED_CHECK([$1],[ccopts])
+])
+
+
+AC_DEFUN([AX_PERL_EXT_LDFLAGS],
+[AC_CHECK_PROG(PERL,perl,perl)
+ _AX_PERL_EXT_MODULE_CHECK([ExtUtils::Embed], [have_embed=yes],
+                           [have_embed=no])
+ AS_IF([test $have_embed = no],
+       AC_MSG_ERROR([Require ExtUtils::Embed to proceed]))
+ _AX_PERL_EXT_EMBED_CHECK([$1],[ldopts],[$2])
+])
+
+
+AC_DEFUN([AX_PERL_EXT_FLAGS],
+[AC_CHECK_PROG(PERL,perl,perl)
+ _AX_PERL_EXT_MODULE_CHECK([ExtUtils::Embed], [have_embed=yes],
+                           [have_embed=no])
+ AS_IF([test $have_embed = no],
+       AC_MSG_ERROR([Require ExtUtils::Embed to proceed]))
+ _AX_PERL_EXT_EMBED_CHECK([$1],[ccopts])
+ _AX_PERL_EXT_EMBED_CHECK([$2],[ldopts],[$3])
+])
+
+
+dnl _AX_PERL_EXT_MODULE_CHECK(MODULE-NAME, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND)
+dnl
+dnl Check for the existance of the perl module given by MODULE-NAME.
+dnl
+AC_DEFUN([_AX_PERL_EXT_MODULE_CHECK],
+[AC_MSG_CHECKING([for perl module $1])
+ $PERL "-M$1" -e exit > /dev/null 2>&1
+ AS_IF([test $? -eq 0],
+ [AC_MSG_RESULT(yes)
+  $2],
+ [AC_MSG_RESULT(no)
+  $3])
+])
+
+dnl _AX_PERL_EXT_EMBED_CHECK(VARIABLE, COMMAND, [EXTRA-FLAGS]) Use
+dnl
+dnl ExtUtils::Embed fetch flags for embedding Perl in a C/C++
+dnl application
+dnl
+AC_DEFUN([_AX_PERL_EXT_EMBED_CHECK],
+[AC_MSG_CHECKING([for perl $2 embed flags])
+ ax_c_perlxs_extras="$3"
+ $1=`$PERL -MExtUtils::Embed -e $2 ${ax_c_perlxs_extras:+"-- $3"}`
+ AC_MSG_RESULT($$1)
+])
diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4
new file mode 100644
index 00000000..cae11112
--- /dev/null
+++ b/m4/ax_require_defined.m4
@@ -0,0 +1,37 @@
+# ===========================================================================
+#    http://www.gnu.org/software/autoconf-archive/ax_require_defined.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_REQUIRE_DEFINED(MACRO)
+#
+# DESCRIPTION
+#
+#   AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
+#   been defined and thus are available for use.  This avoids random issues
+#   where a macro isn't expanded.  Instead the configure script emits a
+#   non-fatal:
+#
+#     ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
+#
+#   It's like AC_REQUIRE except it doesn't expand the required macro.
+#
+#   Here's an example:
+#
+#     AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+#
+# LICENSE
+#
+#   Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 1
+
+AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
+  m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
+])dnl AX_REQUIRE_DEFINED
diff --git a/m4/clang-analyze.am b/m4/clang-analyze.am
new file mode 100644
index 00000000..a5765774
--- /dev/null
+++ b/m4/clang-analyze.am
@@ -0,0 +1,8 @@
+analysis_verbose = $(analysis_verbose_$(V))
+analysis_verbose_ = $(analysis_verbose_$(AM_DEFAULT_VERBOSITY))
+analysis_verbose_0 = @echo "  CCSA    " $@; $(COMPILE) --analyze $< -o $@;
+analysis_verbose_1 = $(COMPILE) --analyze $< -o $@;
+
+%.plist: %.c
+	$(analysis_verbose)
+
diff --git a/plugins/Make.plugin b/plugins/Make.plugin
deleted file mode 100644
index 4a4c56fd..00000000
--- a/plugins/Make.plugin
+++ /dev/null
@@ -1,38 +0,0 @@
-# Makefile stub for creating standalone plugin distributions.
-
-plugin_dist: pg_dist pg_dist/config.status
-	pgi=`cd $(srcdir)/.. && pwd`; cd pg_dist; \
-		$(MAKE) $(AM_MAKEFLAGS) PLUGIN_INCLUDES=-I$$pgi distcheck dist
-
-pg_dist: pg_distdir pg_dist/configure.in pg_dist/install-sh
-	cd pg_dist \
-	&& libtoolize --copy --force --automake \
-	&& automake --copy --add-missing --foreign \
-	&& autoconf -l ../$(top_srcdir)
-
-pg_distdir: $(DISTFILES)
-	test -d pg_dist || mkdir pg_dist
-	for dfile in $(DISTFILES); do \
-		test -f $$dfile && cp $$dfile pg_dist \
-		|| test -f $(srcdir)/$$dfile && cp $(srcdir)/$$dfile pg_dist; done
-	sed '/Make.plugin/d' < $(srcdir)/Makefile.am > pg_dist/Makefile.am
-
-pg_dist/configure.in: $(srcdir)/../plugin-conf.in
-	rm -f pg_dist/configure.in
-	test -f $(srcdir)/config.stub \
-	&& cat $(srcdir)/config.stub > pg_dist/configure.in || true
-	cat $(srcdir)/../plugin-conf.in | \
-		sed 's%@PLUGIN_VERSION@%$(PLUGIN_VERSION)%; \
-		s%@PLUGIN@%$(PLUGIN)%' >> pg_dist/configure.in
-
-pg_dist/install-sh: pg_distdir
-	cp $(top_srcdir)/install-sh pg_dist
-
-pg_dist/config.status: pg_dist/configure
-	cd pg_dist \
-	&& test -f config.status && $(SHELL) ./config.status --recheck \
-	|| $(SHELL) ./configure --enable-maintainer-mode
-
-DISTCLEANFILES = pg_dist/* pg_dist
-
-#
diff --git a/plugins/checksum/Makefile.am b/plugins/checksum/Makefile.am
index 419c762f..4e911f28 100644
--- a/plugins/checksum/Makefile.am
+++ b/plugins/checksum/Makefile.am
@@ -2,6 +2,6 @@ libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = checksum.la
 checksum_la_SOURCES = checksum.c
-checksum_la_LDFLAGS = -avoid-version -module 
-checksum_la_LIBADD = 
-AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+checksum_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+checksum_la_LIBADD = $(GLIB_LIBS)
+checksum_la_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)/src/common
diff --git a/plugins/checksum/checksum.c b/plugins/checksum/checksum.c
index 6ace8543..9a7f0ebd 100644
--- a/plugins/checksum/checksum.c
+++ b/plugins/checksum/checksum.c
@@ -20,222 +20,194 @@
  * THE SOFTWARE.
  */
 
-#ifdef __APPLE__
-#define __AVAILABILITYMACROS__
-#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#endif
+#include "config.h"
 
-#include <stdio.h>
-#include <string.h>
 #include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <openssl/sha.h>
 #include <glib.h>
-
-#ifdef WIN32
-#ifndef snprintf
-#define snprintf _snprintf
-#endif
-#define stat _stat64
-#else
-/* for INT_MAX */
-#include <limits.h>
-#define __USE_LARGEFILE64
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-#endif
+#include <glib/gstdio.h>
+#include <gio/gio.h>
 
 #include "hexchat-plugin.h"
 
 #define BUFSIZE 32768
 #define DEFAULT_LIMIT 256									/* default size is 256 MiB */
+#define SHA256_DIGEST_LENGTH 32
+#define SHA256_BUFFER_LENGTH 65
 
 static hexchat_plugin *ph;									/* plugin handle */
 static char name[] = "Checksum";
 static char desc[] = "Calculate checksum for DCC file transfers";
 static char version[] = "3.1";
 
-/* Use of OpenSSL SHA256 interface: http://adamlamers.com/?p=5 */
 static void
-sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65])
+set_limit (char *size)
 {
-	int i;
-	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
+	int limit = atoi (size);
+
+	if (limit > 0 && limit < INT_MAX)
 	{
-		sprintf (outputBuffer + (i * 2), "%02x", hash[i]);
+		if (hexchat_pluginpref_set_int (ph, "limit", limit))
+			hexchat_printf (ph, "Checksum: File size limit has successfully been set to: %d MiB\n", limit);
+		else
+			hexchat_printf (ph, "Checksum: File access error while saving!\n");
 	}
-	outputBuffer[64] = 0;
-}
-
-#if 0
-static void
-sha256 (char *string, char outputBuffer[65])
-{
-	int i;
-	unsigned char hash[SHA256_DIGEST_LENGTH];
-	SHA256_CTX sha256;
-
-	SHA256_Init (&sha256);
-	SHA256_Update (&sha256, string, strlen (string));
-	SHA256_Final (hash, &sha256);
-
-	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
+	else
 	{
-		sprintf (outputBuffer + (i * 2), "%02x", hash[i]);
+		hexchat_printf (ph, "Checksum: Invalid input!\n");
 	}
-	outputBuffer[64] = 0;
 }
-#endif
 
 static int
-sha256_file (char *path, char outputBuffer[65])
+get_limit ()
 {
-	int bytesRead;
-	unsigned char *buffer;
-	unsigned char hash[SHA256_DIGEST_LENGTH];
-	SHA256_CTX sha256;
+	int size = hexchat_pluginpref_get_int (ph, "limit");
 
-	FILE *file = fopen (path, "rb");
-	if (!file)
-	{
-		return -534;
-	}
+	if (size <= 0 || size >= INT_MAX)
+		return DEFAULT_LIMIT;
+	else
+		return size;
+}
 
-	SHA256_Init (&sha256);
-	buffer = malloc (BUFSIZE);
-	bytesRead = 0;
+static gboolean
+check_limit (GFile *file)
+{
+	GFileInfo *file_info;
+	goffset file_size;
 
-	if (!buffer)
-	{
-		fclose (file);
-		return ENOMEM;
-	}
+	file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE,
+									NULL, NULL);
 
-	while ((bytesRead = fread (buffer, 1, BUFSIZE, file)))
-	{
-		SHA256_Update (&sha256, buffer, bytesRead);
-	}
+	if (!file_info)
+		return FALSE;
 
-	SHA256_Final (hash, &sha256);
-	sha256_hash_string (hash, outputBuffer);
+	file_size = g_file_info_get_size (file_info);
+	g_object_unref (file_info);
 
-	fclose (file);
-	free (buffer);
-	return 0;
+	if (file_size > get_limit () * 1048576ll)
+		return FALSE;
+
+	return TRUE;
 }
 
-static void
-set_limit (char* size)
+static gboolean
+sha256_from_stream (GFileInputStream *file_stream, char out_buf[])
 {
-	int buffer = atoi (size);
+	GChecksum *checksum;
+	gssize bytes_read;
+	guint8 digest[SHA256_DIGEST_LENGTH];
+	gsize digest_len = sizeof(digest);
+	guchar buffer[BUFSIZE];
+	gsize i;
+
+	checksum = g_checksum_new (G_CHECKSUM_SHA256);
 
-	if (buffer > 0 && buffer < INT_MAX)
+	while ((bytes_read = g_input_stream_read (G_INPUT_STREAM (file_stream), buffer, sizeof (buffer), NULL, NULL)))
 	{
-		if (hexchat_pluginpref_set_int (ph, "limit", buffer))
-		{
-			hexchat_printf (ph, "File size limit has successfully been set to: %d MiB\n", buffer);
-		}
-		else
+		if (bytes_read == -1)
 		{
-			hexchat_printf (ph, "File access error while saving!\n");
+			g_checksum_free (checksum);
+			return FALSE;
 		}
+
+		g_checksum_update (checksum, buffer, bytes_read);
 	}
-	else
+
+	g_checksum_get_digest (checksum, digest, &digest_len);
+	g_checksum_free (checksum);
+
+	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
 	{
-		hexchat_printf (ph, "Invalid input!\n");
+		/* out_buf will be exactly SHA256_BUFFER_LENGTH including null */
+		g_sprintf (out_buf + (i * 2), "%02x", digest[i]);
 	}
+
+	return TRUE;
 }
 
-static int
-get_limit ()
+static gboolean
+sha256_from_file (char *filename, char out_buf[])
 {
-	int size = hexchat_pluginpref_get_int (ph, "limit");
+	GFileInputStream *file_stream;
+	char *filename_fs;
+	GFile *file;
 
-	if (size <= -1 || size >= INT_MAX)
+	filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
+	if (!filename_fs)
 	{
-		return DEFAULT_LIMIT;
+		hexchat_printf (ph, "Checksum: Invalid filename (%s)\n", filename);
+		return FALSE;
 	}
-	else
+
+	file = g_file_new_for_path (filename_fs);
+	g_free (filename_fs);
+	if (!file)
 	{
-		return size;
+		hexchat_printf (ph, "Checksum: Failed to open %s\n", filename);
+		return FALSE;
 	}
-}
-
-static void
-print_limit ()
-{
-	hexchat_printf (ph, "File size limit for checksums: %d MiB", get_limit ());
-}
 
-static int
-dccrecv_cb (char *word[], void *userdata)
-{
-	int result;
-	struct stat buffer;									/* buffer for storing file info */
-	char sum[65];											/* buffer for checksum */
-	const char *file;
-	char *cfile;
-
-	if (hexchat_get_prefs (ph, "dcc_completed_dir", &file, NULL) == 1 && file[0] != 0)
+	if (!check_limit (file))
 	{
-		cfile = g_strconcat (file, G_DIR_SEPARATOR_S, word[1], NULL);
+		hexchat_printf (ph, "Checksum: %s is larger than size limit. You can increase it with /CHECKSUM SET.\n", filename);
+		g_object_unref (file);
+		return FALSE;
 	}
-	else
+
+	file_stream = g_file_read (file, NULL, NULL);
+	if (!file_stream)
 	{
-		cfile = g_strdup(word[2]);
+		hexchat_printf (ph, "Checksum: Failed to read file %s\n", filename);
+		g_object_unref (file);
+		return FALSE;
 	}
 
-	result = stat (cfile, &buffer);
-	if (result == 0)										/* stat returns 0 on success */
+	if (!sha256_from_stream (file_stream, out_buf))
 	{
-		if (buffer.st_size <= (unsigned long long) get_limit () * 1048576)
-		{
-			sha256_file (cfile, sum);						/* file is the full filename even if completed dir set */
-			/* try to print the checksum in the privmsg tab of the sender */
-			hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
-			hexchat_printf (ph, "SHA-256 checksum for %s (local):  %s\n", word[1], sum);
-		}
-		else
-		{
-			hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
-			hexchat_printf (ph, "SHA-256 checksum for %s (local):  (size limit reached, no checksum calculated, you can increase it with /CHECKSUM INC)\n", word[1]);
-		}
+		hexchat_printf (ph, "Checksum: Failed to generate checksum for %s\n", filename);
+		g_object_unref (file_stream);
+		g_object_unref (file);
+		return FALSE;
 	}
+
+	g_object_unref (file_stream);
+	g_object_unref (file);
+	return TRUE;
+}
+
+static int
+dccrecv_cb (char *word[], void *userdata)
+{
+	const char *dcc_completed_dir;
+	char *filename, checksum[SHA256_BUFFER_LENGTH];
+
+	/* Print in the privmsg tab of the sender */
+	hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
+
+	if (hexchat_get_prefs (ph, "dcc_completed_dir", &dcc_completed_dir, NULL) == 1 && dcc_completed_dir[0] != '\0')
+		filename = g_build_filename (dcc_completed_dir, word[1], NULL);
 	else
+		filename = g_strdup (word[2]);
+
+	if (sha256_from_file (filename, checksum))
 	{
-		hexchat_printf (ph, "File access error!\n");
+		hexchat_printf (ph, "SHA-256 checksum for %s (local): %s\n", word[1], checksum);
 	}
 
-	g_free (cfile);
+	g_free (filename);
 	return HEXCHAT_EAT_NONE;
 }
 
 static int
 dccoffer_cb (char *word[], void *userdata)
 {
-	int result;
-	struct stat buffer;									/* buffer for storing file info */
-	char sum[65];											/* buffer for checksum */
+	char checksum[SHA256_BUFFER_LENGTH];
 
-	result = stat (word[3], &buffer);
-	if (result == 0)										/* stat returns 0 on success */
-	{
-		if (buffer.st_size <= (unsigned long long) get_limit () * 1048576)
-		{
-			sha256_file (word[3], sum);						/* word[3] is the full filename */
-			hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], sum);
-		}
-		else
-		{
-			hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
-			hexchat_printf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): (size limit reached, no checksum calculated)", word[2], word[1]);
-		}
-	}
-	else
+	/* Print in the privmsg tab of the receiver */
+	hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
+
+	if (sha256_from_file (word[3], checksum))
 	{
-		hexchat_printf (ph, "File access error!\n");
+		hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], checksum);
 	}
 
 	return HEXCHAT_EAT_NONE;
@@ -246,7 +218,7 @@ checksum (char *word[], char *word_eol[], void *userdata)
 {
 	if (!g_ascii_strcasecmp ("GET", word[2]))
 	{
-		print_limit ();
+		hexchat_printf (ph, "File size limit for checksums: %d MiB", get_limit ());
 	}
 	else if (!g_ascii_strcasecmp ("SET", word[2]))
 	{
@@ -259,7 +231,7 @@ checksum (char *word[], char *word_eol[], void *userdata)
 		hexchat_printf (ph, "  SET <filesize> - set the maximum file size (in MiB) to be hashed\n");
 	}
 
-	return HEXCHAT_EAT_NONE;
+	return HEXCHAT_EAT_ALL;
 }
 
 int
@@ -277,7 +249,7 @@ hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **p
 		hexchat_pluginpref_set_int (ph, "limit", DEFAULT_LIMIT);
 	}
 
-	hexchat_hook_command (ph, "CHECKSUM", HEXCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|SET", 0);
+	hexchat_hook_command (ph, "CHECKSUM", HEXCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|SET", NULL);
 	hexchat_hook_print (ph, "DCC RECV Complete", HEXCHAT_PRI_NORM, dccrecv_cb, NULL);
 	hexchat_hook_print (ph, "DCC Offer", HEXCHAT_PRI_NORM, dccoffer_cb, NULL);
 
diff --git a/plugins/checksum/checksum.vcxproj b/plugins/checksum/checksum.vcxproj
index 7838cb4a..948295a0 100644
--- a/plugins/checksum/checksum.vcxproj
+++ b/plugins/checksum/checksum.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,57 +20,19 @@
     <RootNamespace>checksum</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hcchecksum</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcchecksum</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CHECKSUM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>checksum.def</ModuleDefinitionFile>

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

       <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

@@ -77,19 +40,10 @@
   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;CHECKSUM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>checksum.def</ModuleDefinitionFile>

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

       <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

@@ -102,6 +56,4 @@
     <None Include="checksum.def" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/doat/Makefile.am b/plugins/doat/Makefile.am
index abfca29e..a04d2863 100644
--- a/plugins/doat/Makefile.am
+++ b/plugins/doat/Makefile.am
@@ -2,7 +2,7 @@ libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = doat.la
 doat_la_SOURCES = doat.c
-doat_la_LDFLAGS = -avoid-version -module 
-doat_la_LIBADD = 
-AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+doat_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+doat_la_LIBADD = $(GLIB_LIBS)
+doat_la_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)/src/common
 
diff --git a/plugins/doat/doat.c b/plugins/doat/doat.c
index 194be1a3..1d1bfcdf 100644
--- a/plugins/doat/doat.c
+++ b/plugins/doat/doat.c
@@ -5,9 +5,12 @@
  * http://sam.zoy.org/wtfpl/COPYING or http://lwsitu.com/xchat/COPYING
  * for more details. */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <glib.h>
 #include "hexchat-plugin.h"
 
 static hexchat_plugin *ph;
@@ -31,7 +34,7 @@ parse_command( char *word[], char *word_eol[], void *userdata ) {
 				break;
 			}
 
-			channel = strdup( token );
+			channel = g_strdup( token );
 				
 			delimiter = strchr( channel, '/' );
 
@@ -40,13 +43,13 @@ parse_command( char *word[], char *word_eol[], void *userdata ) {
 				*delimiter = '\0';
 
 				if( strlen( delimiter + 1 ) > 0 ) {
-					server = strdup( delimiter + 1 );
+					server = g_strdup( delimiter + 1 );
 				}
 			}
 
 			/* /Network form */
 			if( strlen( channel ) == 0 ) {
-				free( channel );
+				g_free( channel );
 				channel = NULL;
 			}
 
@@ -58,13 +61,8 @@ parse_command( char *word[], char *word_eol[], void *userdata ) {
 				}
 			}
 
-			if( channel != NULL ) {
-				free( channel );
-			}
-
-			if( server != NULL ) {
-				free( server );
-			}
+			g_free( channel );
+			g_free( server );
 		}
 	}
 	return HEXCHAT_EAT_HEXCHAT;
diff --git a/plugins/doat/doat.vcxproj b/plugins/doat/doat.vcxproj
index 171e2b0d..ae44d7f8 100644
--- a/plugins/doat/doat.vcxproj
+++ b/plugins/doat/doat.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,75 +20,32 @@
     <RootNamespace>doat</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hcdoat</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcdoat</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;DOAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>..\..\src\common;$(HexChatLib);$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

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

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>doat.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;DOAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>..\..\src\common;$(HexChatLib);$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

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

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>doat.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

@@ -98,6 +56,4 @@
     <None Include="doat.def" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/exec/exec.vcxproj b/plugins/exec/exec.vcxproj
index a04c0046..d691bb11 100644
--- a/plugins/exec/exec.vcxproj
+++ b/plugins/exec/exec.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,75 +20,28 @@
     <RootNamespace>exec</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hcexec</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcexec</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXEC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

       <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>exec.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;EXEC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

       <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>exec.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

@@ -98,6 +52,4 @@
     <ClCompile Include="exec.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/fishlim/Makefile.am b/plugins/fishlim/Makefile.am
index 255ea0c3..df541396 100644
--- a/plugins/fishlim/Makefile.am
+++ b/plugins/fishlim/Makefile.am
@@ -3,7 +3,7 @@ EXTRA_DIST = INSTALL LICENSE
 libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = fishlim.la
-fishlim_la_SOURCES = fish.c irc.c keystore.c misc.c plugin_hexchat.c
-fishlim_la_LDFLAGS = -avoid-version -module 
-fishlim_la_LIBADD = 
-AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+fishlim_la_SOURCES = fish.c irc.c keystore.c plugin_hexchat.c
+fishlim_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+fishlim_la_LIBADD = $(GLIB_LIBS) $(OPENSSL_LIBS)
+fishlim_la_CFLAGS = $(GLIB_CFLAGS) $(OPENSSL_CFLAGS) -I$(top_srcdir)/src/common
diff --git a/plugins/fishlim/fish.c b/plugins/fishlim/fish.c
index 93420f23..00ecfbfa 100644
--- a/plugins/fishlim/fish.c
+++ b/plugins/fishlim/fish.c
@@ -39,17 +39,17 @@ static const char fish_base64[64] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDE
 static const signed char fish_unbase64[256] = {
     IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB,IB,IB,
     IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB,IB,IB,
-//      !  "  #  $  %  &  '  (    )  *  +  ,  -  .  /
+/*      !  "  #  $  %  &  '  (    )  *  +  ,  -  .  / */
     IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB, 0, 1,
-//   0  1  2  3  4  5  6  7    8  9  :  ;  <  =  >  ?
+/*   0  1  2  3  4  5  6  7    8  9  :  ;  <  =  >  ? */
      2, 3, 4, 5, 6, 7, 8, 9,  10,11,IB,IB,IB,IB,IB,IB,
-//   @  A  B  C  D  E  F  G    H  I  J  K  L  M  N  O
+/*   @  A  B  C  D  E  F  G    H  I  J  K  L  M  N  O */
     IB,38,39,40,41,42,43,44,  45,46,47,48,49,50,51,52,
-//   P  Q  R  S  T  U  V  W    X  Y  Z  [  \  ]  ^  _
+/*   P  Q  R  S  T  U  V  W    X  Y  Z  [  \  ]  ^  _*/
     53,54,55,56,57,58,59,60,  61,62,63,IB,IB,IB,IB,IB,
-//   `  a  b  c  d  e  f  g    h  i  j  k  l  m  n  o
+/*   `  a  b  c  d  e  f  g    h  i  j  k  l  m  n  o */
     IB,12,13,14,15,16,17,18,  19,20,21,22,23,24,25,26,
-//   p  q  r  s  t  u  v  w    x  y  z  {  |  }  ~  <del>
+/*   p  q  r  s  t  u  v  w    x  y  z  {  |  }  ~  <del> */
     27,28,29,30,31,32,33,34,  35,36,37,IB,IB,IB,IB,IB,
 };
 
@@ -75,12 +75,11 @@ char *fish_encrypt(const char *key, size_t keylen, const char *message) {
     
     messagelen = strlen(message);
     if (messagelen == 0) return NULL;
-    encrypted = malloc(((messagelen-1)/8)*12 + 12 + 1); // each 8-byte block becomes 12 bytes
+    encrypted = g_malloc(((messagelen - 1) / 8) * 12 + 12 + 1); /* each 8-byte block becomes 12 bytes */
     end = encrypted;
-    if (!encrypted) return NULL;
      
     while (*message) {
-        // Read 8 bytes (a Blowfish block)
+        /* Read 8 bytes (a Blowfish block) */
         BF_LONG binary[2] = { 0, 0 };
         unsigned char c;
         for (i = 0; i < 8; i++) {
@@ -90,10 +89,10 @@ char *fish_encrypt(const char *key, size_t keylen, const char *message) {
         }
         message += 8;
         
-        // Encrypt block
+        /* Encrypt block */
         BF_encrypt(binary, &bfkey);
         
-        // Emit FiSH-BASE64
+        /* Emit FiSH-BASE64 */
         bit = 0;
         word = 1;
         for (j = 0; j < 12; j++) {
@@ -106,7 +105,7 @@ char *fish_encrypt(const char *key, size_t keylen, const char *message) {
             }
         }
         
-        // Stop if a null terminator was found
+        /* Stop if a null terminator was found */
         if (c == '\0') break;
     }
     *end = '\0';
@@ -124,12 +123,11 @@ char *fish_decrypt(const char *key, size_t keylen, const char *data) {
     unsigned char d;
     BF_set_key(&bfkey, keylen, (const unsigned char*)key);
     
-    decrypted = malloc(strlen(data)+1);
+    decrypted = g_malloc(strlen(data) + 1);
     end = decrypted;
-    if (!decrypted) return NULL;
     
     while (*data) {
-        // Convert from FiSH-BASE64
+        /* Convert from FiSH-BASE64 */
         BF_LONG binary[2] = { 0, 0 };
         bit = 0;
         word = 1;
@@ -144,10 +142,10 @@ char *fish_decrypt(const char *key, size_t keylen, const char *data) {
             }
         }
         
-        // Decrypt block
+        /* Decrypt block */
         BF_decrypt(binary, &bfkey);
         
-        // Copy to buffer
+        /* Copy to buffer */
         GET_BYTES(end, binary[0]);
         GET_BYTES(end, binary[1]);
     }
@@ -165,14 +163,14 @@ char *fish_encrypt_for_nick(const char *nick, const char *data) {
     char *key;
     char *encrypted;
 
-    // Look for key
+    /* Look for key */
     key = keystore_get_key(nick);
     if (!key) return NULL;
     
-    // Encrypt
+    /* Encrypt */
     encrypted = fish_encrypt(key, strlen(key), data);
     
-    free(key);
+    g_free(key);
     return encrypted;
 }
 
@@ -183,14 +181,14 @@ char *fish_encrypt_for_nick(const char *nick, const char *data) {
 char *fish_decrypt_from_nick(const char *nick, const char *data) {
     char *key;
     char *decrypted;
-    // Look for key
+    /* Look for key */
     key = keystore_get_key(nick);
     if (!key) return NULL;
     
-    // Decrypt
+    /* Decrypt */
     decrypted = fish_decrypt(key, strlen(key), data);
     
-    free(key);
+    g_free(key);
     return decrypted;
 }
 
diff --git a/plugins/fishlim/fish.h b/plugins/fishlim/fish.h
index db471326..238f52e7 100644
--- a/plugins/fishlim/fish.h
+++ b/plugins/fishlim/fish.h
@@ -25,9 +25,10 @@
 #ifndef FISH_H
 #define FISH_H
 
-#include <stdbool.h>
 #include <stddef.h>
 
+#include <glib.h>
+
 char *fish_encrypt(const char *key, size_t keylen, const char *message);
 char *fish_decrypt(const char *key, size_t keylen, const char *data);
 char *fish_encrypt_for_nick(const char *nick, const char *data);
diff --git a/plugins/fishlim/fishlim.vcxproj b/plugins/fishlim/fishlim.vcxproj
index f1eb95ba..25492a82 100644
--- a/plugins/fishlim/fishlim.vcxproj
+++ b/plugins/fishlim/fishlim.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,57 +20,19 @@
     <RootNamespace>fishlim</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hcfishlim</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcfishlim</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>fishlim.def</ModuleDefinitionFile>

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

       <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

@@ -77,19 +40,10 @@
   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>fishlim.def</ModuleDefinitionFile>

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

       <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

@@ -103,17 +57,13 @@
     <ClInclude Include="fish.h" />

     <ClInclude Include="irc.h" />

     <ClInclude Include="keystore.h" />

-    <ClInclude Include="misc.h" />

     <ClInclude Include="plugin_hexchat.h" />

   </ItemGroup>

   <ItemGroup>

     <ClCompile Include="fish.c" />

     <ClCompile Include="irc.c" />

     <ClCompile Include="keystore.c" />

-    <ClCompile Include="misc.c" />

     <ClCompile Include="plugin_hexchat.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/fishlim/fishlim.vcxproj.filters b/plugins/fishlim/fishlim.vcxproj.filters
index 7c13733b..d8fbf454 100644
--- a/plugins/fishlim/fishlim.vcxproj.filters
+++ b/plugins/fishlim/fishlim.vcxproj.filters
@@ -32,9 +32,6 @@
     <ClInclude Include="keystore.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="misc.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

     <ClInclude Include="plugin_hexchat.h">

       <Filter>Header Files</Filter>

     </ClInclude>

@@ -49,9 +46,6 @@
     <ClCompile Include="keystore.c">

       <Filter>Source Files</Filter>

     </ClCompile>

-    <ClCompile Include="misc.c">

-      <Filter>Source Files</Filter>

-    </ClCompile>

     <ClCompile Include="plugin_hexchat.c">

       <Filter>Source Files</Filter>

     </ClCompile>

diff --git a/plugins/fishlim/irc.c b/plugins/fishlim/irc.c
index 3586921b..deba545b 100644
--- a/plugins/fishlim/irc.c
+++ b/plugins/fishlim/irc.c
@@ -22,8 +22,9 @@
 
 */
 
-#include <stdlib.h>
-#include <string.h>
+#include "config.h"
+
+#include <glib.h>
 #include "irc.h"
 
 /**
@@ -31,26 +32,26 @@
  * at spaces. The prefix and command is extracted from the message, and
  * parameters_offset is set to the index of the first parameter.
  */
-bool irc_parse_message(const char *words[],
+gboolean irc_parse_message(const char *words[],
                        const char **prefix, const char **command,
                        size_t *parameters_offset) {
     size_t w = 1;
     if (prefix) *prefix = NULL;
     if (command) *command = NULL;
     
-    // See if the message starts with a prefix (sender user)
+    /* See if the message starts with a prefix (sender user) */
     if (words[w][0] == ':') {
         if (prefix) *prefix = &words[w][1];
         w++;
     }
     
-    // Check command
-    if (words[w][0] == '\0') return false;
+    /* Check command */
+    if (words[w][0] == '\0') return FALSE;
     if (command) *command = words[w];
     w++;
     
     *parameters_offset = w;
-    return true;
+    return TRUE;
 }
 
 
@@ -65,48 +66,15 @@ bool irc_parse_message(const char *words[],
  */
 char *irc_prefix_get_nick(const char *prefix) {
     const char *end;
-    char *nick;
     size_t length;
     
     if (!prefix) return NULL;
     
-    // Find end of nick
+    /* Find end of nick */
     end = prefix;
     while (*end != '\0' && *end != '!' && *end != '@') end++;
     
-    // Allocate string
+    /* Allocate string */
     length = end - prefix;
-    nick = malloc(length+1);
-    if (!nick) return NULL;
-    
-    // Copy to string
-    memcpy(nick, prefix, length);
-    nick[length] = '\0';
-    return nick;
-}
-
-
-/**
- * Compares two nick names. Return 0 if equal. Otherwise the return value is
- * less than zero if a is less than b or greater than zero if a is greater
- * than b.
- */
-int irc_nick_cmp(const char *a, const char *b) {
-    char ac;
-    char bc;
-    char diff;
-    for (;;) {
-        ac = *(a++);
-        bc = *(b++);
-        
-        // Change into IRC uppercase (see RFC 2812 section 2.2)
-        if (ac >= 'a' && ac <= '~') ac &= ~0x20;
-        if (bc >= 'a' && bc <= '~') bc &= ~0x20;
-        
-        diff = ac - bc;
-        if (diff) return diff;
-        if (!ac) return 0;
-    }
+    return g_strndup (prefix, length);
 }
-
-
diff --git a/plugins/fishlim/irc.h b/plugins/fishlim/irc.h
index 87317130..c5649233 100644
--- a/plugins/fishlim/irc.h
+++ b/plugins/fishlim/irc.h
@@ -25,14 +25,13 @@
 #ifndef IRC_H
 #define IRC_H
 
-#include <stdbool.h>
 #include <stddef.h>
+#include <glib.h>
 
-bool irc_parse_message(const char *words[],
+gboolean irc_parse_message(const char *words[],
                        const char **prefix, const char **command,
                        size_t *parameters_offset);
 char *irc_prefix_get_nick(const char *prefix);
-int irc_nick_cmp(const char *a, const char *b);
 
 #endif
 
diff --git a/plugins/fishlim/keystore.c b/plugins/fishlim/keystore.c
index 9f1c446e..84373996 100644
--- a/plugins/fishlim/keystore.c
+++ b/plugins/fishlim/keystore.c
@@ -22,12 +22,13 @@
 
 */
 
+#include "config.h"
+
 #include <glib.h>
 #include <stdlib.h>
 #include <string.h>
 #include "irc.h"
 #include "fish.h"
-#include "misc.h"
 #include "keystore.h"
 #include "plugin_hexchat.h"
 
@@ -57,7 +58,7 @@ static GKeyFile *getConfigFile() {
 static const char *get_keystore_password() {
     return (keystore_password != NULL ?
         keystore_password :
-        // Silly default value...
+        /* Silly default value... */
         "blowinikey");
 }
 
@@ -87,17 +88,17 @@ static gchar *get_nick_value(GKeyFile *keyfile, const char *nick, const char *it
  * Extracts a key from the key store file.
  */
 char *keystore_get_key(const char *nick) {
-    // Get the key
+    /* Get the key */
     GKeyFile *keyfile = getConfigFile();
     gchar *value = get_nick_value(keyfile, nick, "key");
     g_key_file_free(keyfile);
     if (!value) return NULL;
     
     if (strncmp(value, "+OK ", 4) != 0) {
-        // Key is stored in plaintext
-        return import_glib_string(value);
+        /* Key is stored in plaintext */
+        return value;
     } else {
-        // Key is encrypted
+        /* Key is encrypted */
         const char *encrypted = value+4;
         const char *password = get_keystore_password();
         char *decrypted = fish_decrypt(password, strlen(password), encrypted);
@@ -109,10 +110,10 @@ char *keystore_get_key(const char *nick) {
 /**
  * Deletes a nick and the associated key in the key store file.
  */
-static bool delete_nick(GKeyFile *keyfile, const char *nick) {
+static gboolean delete_nick(GKeyFile *keyfile, const char *nick) {
     gchar **group;
     gchar **groups = g_key_file_get_groups(keyfile, NULL);
-    bool ok = false;
+    gboolean ok = FALSE;
     
     for (group = groups; *group != NULL; group++) {
         if (!irc_nick_cmp(*group, nick)) {
@@ -125,58 +126,77 @@ static bool delete_nick(GKeyFile *keyfile, const char *nick) {
     return ok;
 }
 
+#if !GLIB_CHECK_VERSION(2,40,0)
 /**
  * Writes the key store file to disk.
  */
-static bool save_keystore(GKeyFile *keyfile) {
-    char *filename;
-    bool ok;
-    // Serialize
+static gboolean keyfile_save_to_file (GKeyFile *keyfile, char *filename) {
+    gboolean ok;
+
+    /* Serialize */
     gsize file_length;
     gchar *file_data = g_key_file_to_data(keyfile, &file_length, NULL);
-    if (!file_data) return false;
-    
-    // Write to file
-    filename = get_config_filename();
-    ok = g_file_set_contents(filename, file_data, file_length, NULL);
-    g_free(filename);
+    if (!file_data)
+        return FALSE;
+
+    /* Write to file */
+    ok = g_file_set_contents (filename, file_data, file_length, NULL);
     g_free(file_data);
     return ok;
 }
+#endif
+
+/**
+ * Writes the key store file to disk.
+ */
+static gboolean save_keystore(GKeyFile *keyfile) {
+    char *filename;
+    gboolean ok;
+
+    filename = get_config_filename();
+#if !GLIB_CHECK_VERSION(2,40,0)
+    ok = keyfile_save_to_file (keyfile, filename);
+#else
+    ok = g_key_file_save_to_file (keyfile, filename, NULL);
+#endif
+    g_free (filename);
+
+    return ok;
+}
 
 /**
  * Sets a key in the key store file.
  */
-bool keystore_store_key(const char *nick, const char *key) {
+gboolean keystore_store_key(const char *nick, const char *key) {
     const char *password;
     char *encrypted;
     char *wrapped;
-    bool ok = false;
+    gboolean ok = FALSE;
     GKeyFile *keyfile = getConfigFile();
     
-    // Remove old key
+    /* Remove old key */
     delete_nick(keyfile, nick);
     
-    // Add new key
+    /* Add new key */
     password = get_keystore_password();
     if (password) {
-        // Encrypt the password
+        /* Encrypt the password */
         encrypted = fish_encrypt(password, strlen(password), key);
         if (!encrypted) goto end;
         
-        // Prepend "+OK "
+        /* Prepend "+OK " */
         wrapped = g_strconcat("+OK ", encrypted, NULL);
         g_free(encrypted);
         
-        // Store encrypted in file
+        /* Store encrypted in file */
         g_key_file_set_string(keyfile, nick, "key", wrapped);
-        free(wrapped);
+        g_free(wrapped);
     } else {
-        // Store unencrypted in file
+        /* Store unencrypted in file */
         g_key_file_set_string(keyfile, nick, "key", key);
     }
     
-    // Save key store file
+    /* Save key store file */
     ok = save_keystore(keyfile);
     
   end:
@@ -187,23 +207,15 @@ bool keystore_store_key(const char *nick, const char *key) {
 /**
  * Deletes a nick from the key store.
  */
-bool keystore_delete_nick(const char *nick) {
+gboolean keystore_delete_nick(const char *nick) {
     GKeyFile *keyfile = getConfigFile();
     
-    // Delete entry
-    bool ok = delete_nick(keyfile, nick);
+    /* Delete entry */
+    gboolean ok = delete_nick(keyfile, nick);
     
-    // Save
+    /* Save */
     if (ok) save_keystore(keyfile);
     
     g_key_file_free(keyfile);
     return ok;
 }
-
-
-void keystore_secure_free(void *ptr, size_t size) {
-    secure_erase(ptr, size);
-    free(ptr);
-}
-
-
diff --git a/plugins/fishlim/keystore.h b/plugins/fishlim/keystore.h
index a2c33f02..3d90606a 100644
--- a/plugins/fishlim/keystore.h
+++ b/plugins/fishlim/keystore.h
@@ -25,14 +25,13 @@
 #ifndef KEYSTORE_H
 #define KEYSTORE_H
 
-#include <stdbool.h>
 #include <stddef.h>
 
-char *keystore_get_key(const char *nick);
-bool keystore_store_key(const char *nick, const char *key);
-bool keystore_delete_nick(const char *nick);
+#include <glib.h>
 
-void keystore_secure_free(void *ptr, size_t size);
+char *keystore_get_key(const char *nick);
+gboolean keystore_store_key(const char *nick, const char *key);
+gboolean keystore_delete_nick(const char *nick);
 
 #endif
 
diff --git a/plugins/fishlim/misc.c b/plugins/fishlim/misc.c
deleted file mode 100644
index 2b78961d..00000000
--- a/plugins/fishlim/misc.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  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 THE
-  AUTHORS OR COPYRIGHT HOLDERS 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.
-
-*/
-
-#include <glib.h>
-#include <stdlib.h>
-#include <string.h>
-#include "misc.h"
-
-
-void secure_erase(void *ptr, size_t size) {
-    // "volatile" prevents this code from being optimized away
-    volatile char* volptr = ptr;
-    while (size--) *volptr++ = 0;
-}
-
-/**
- * Re-allocates a string with the native allocator.
- */
-char *import_glib_string(gchar *gstr) {
-    size_t size;
-    char *native;
-    if (g_mem_is_system_malloc()) return gstr;
-    
-    size = strlen(gstr)+1;
-    native = malloc(size);
-    memcpy(native, gstr, size);
-    
-    secure_erase(gstr, size);
-    g_free(gstr);
-    return native;
-}
-
-
diff --git a/plugins/fishlim/misc.h b/plugins/fishlim/misc.h
deleted file mode 100644
index ee4fc5b8..00000000
--- a/plugins/fishlim/misc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  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 THE
-  AUTHORS OR COPYRIGHT HOLDERS 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.
-
-*/
-
-#ifndef MISC_H
-#define MISC_H
-
-void secure_erase(void *ptr, size_t size);
-
-#ifdef __G_LIB_H__
-char *import_glib_string(gchar *gstr);
-#endif
-
-#endif
-
-
diff --git a/plugins/fishlim/plugin_hexchat.c b/plugins/fishlim/plugin_hexchat.c
index f200ea8c..556a2f51 100644
--- a/plugins/fishlim/plugin_hexchat.c
+++ b/plugins/fishlim/plugin_hexchat.c
@@ -22,17 +22,14 @@
 
 */
 
+#include "config.h"
+
 #include <glib.h>
 #include <stdlib.h>
 #include <string.h>
 
-// #pragma GCC visibility push(default)
 #include "hexchat-plugin.h"
 #define HEXCHAT_MAX_WORDS 32
-// #pragma GCC visibility pop
-
-//#define EXPORT __attribute((visibility("default")))
-//#define EXPORT
 
 #include "fish.h"
 #include "keystore.h"
@@ -52,26 +49,18 @@ static hexchat_plugin *ph;
  * Returns the path to the key store file.
  */
 gchar *get_config_filename() {
-    return g_build_filename(hexchat_get_info(ph, "configdir"), "addon_fishlim.conf", NULL);
-}
+    char *filename_fs, *filename_utf8;
 
-/**
- * Appends data to a string. Returns true if there was sufficient memory.
- * Frees *s and returns false if an error occurs.
- */
-static bool append(char **s, size_t *length, const char *data) {
-    size_t datalen = strlen(data);
-    char *extended = realloc(*s, *length + datalen + 1);
-    if (!extended) {
-        free(*s);
-        return false;
-    }
-    memcpy(extended + *length, data, datalen + 1);
-    *s = extended;
-    *length += datalen;
-    return true;
+    filename_utf8 = g_build_filename(hexchat_get_info(ph, "configdir"), "addon_fishlim.conf", NULL);
+    filename_fs = g_filename_from_utf8 (filename_utf8, -1, NULL, NULL, NULL);
+
+    g_free (filename_utf8);
+    return filename_fs;
 }
 
+int irc_nick_cmp(const char *a, const char *b) {
+	return hexchat_nickcmp (ph, a, b);
+}
 
 /*static int handle_debug(char *word[], char *word_eol[], void *userdata) {
     hexchat_printf(ph, "debug incoming: ");
@@ -87,26 +76,26 @@ static bool append(char **s, size_t *length, const char *data) {
  */
 static int handle_outgoing(char *word[], char *word_eol[], void *userdata) {
     const char *own_nick;
-    // Encrypt the message if possible
+    /* Encrypt the message if possible */
     const char *channel = hexchat_get_info(ph, "channel");
     char *encrypted = fish_encrypt_for_nick(channel, word_eol[1]);
     if (!encrypted) return HEXCHAT_EAT_NONE;
     
-    // Display message
+    /* Display message */
     own_nick = hexchat_get_info(ph, "nick");
     hexchat_emit_print(ph, "Your Message", own_nick, word_eol[1], NULL);
     
-    // Send message
+    /* Send message */
     hexchat_commandf(ph, "PRIVMSG %s :+OK %s", channel, encrypted);
     
-    free(encrypted);
+    g_free(encrypted);
     return HEXCHAT_EAT_HEXCHAT;
 }
 
 /**
  * Called when a channel message or private message is received.
  */
-static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
+static int handle_incoming(char *word[], char *word_eol[], hexchat_event_attrs *attrs, void *userdata) {
     const char *prefix;
     const char *command;
     const char *recipient;
@@ -114,20 +103,19 @@ static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
     const char *peice;
     char *sender_nick;
     char *decrypted;
-    char *message;
     size_t w;
     size_t ew;
     size_t uw;
-    size_t length;
     char prefix_char = 0;
+    GString *message;
 
     if (!irc_parse_message((const char **)word, &prefix, &command, &w))
         return HEXCHAT_EAT_NONE;
     
-    // Topic (command 332) has an extra parameter
+    /* Topic (command 332) has an extra parameter */
     if (!strcmp(command, "332")) w++;
     
-    // Look for encrypted data
+    /* Look for encrypted data */
     for (ew = w+1; ew < HEXCHAT_MAX_WORDS-1; ew++) {
         const char *s = (ew == w+1 ? word[ew]+1 : word[ew]);
         if (*s && (s[1] == '+' || s[1] == 'm')) { prefix_char = *(s++); }
@@ -136,61 +124,70 @@ static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
     }
     return HEXCHAT_EAT_NONE;
   has_encrypted_data: ;
-    // Extract sender nick and recipient nick/channel
+    /* Extract sender nick and recipient nick/channel */
     sender_nick = irc_prefix_get_nick(prefix);
     recipient = word[w];
     
-    // Try to decrypt with these (the keys are searched for in the key store)
+    /* Try to decrypt with these (the keys are searched for in the key store) */
     encrypted = word[ew+1];
     decrypted = fish_decrypt_from_nick(recipient, encrypted);
     if (!decrypted) decrypted = fish_decrypt_from_nick(sender_nick, encrypted);
     
-    // Check for error
+    /* Check for error */
     if (!decrypted) goto decrypt_error;
     
-    // Build unecrypted message
-    message = NULL;
-    length = 0;
-    if (!append(&message, &length, "RECV")) goto decrypt_error;
-    
+    /* Build unecrypted message */
+    message = g_string_sized_new (100); /* TODO: more accurate estimation of size */
+    g_string_append (message, "RECV");
+
+    if (attrs->server_time_utc)
+    {
+        GTimeVal tv = { (glong)attrs->server_time_utc, 0 };
+        char *timestamp = g_time_val_to_iso8601 (&tv);
+
+       g_string_append (message, " @time=");
+       g_string_append (message, timestamp);
+       g_free (timestamp);
+    }
+
     for (uw = 1; uw < HEXCHAT_MAX_WORDS; uw++) {
-        if (word[uw][0] != '\0' && !append(&message, &length, " ")) goto decrypt_error;
+        if (word[uw][0] != '\0')
+            g_string_append_c (message, ' ');
         
         if (uw == ew) {
-            // Add the encrypted data
+            /* Add the encrypted data */
             peice = decrypted;
-            uw++; // Skip "OK+"
+            uw++; /* Skip "OK+" */
             
             if (ew == w+1) {
-                // Prefix with colon, which gets stripped out otherwise
-                if (!append(&message, &length, ":")) goto decrypt_error;
+                /* Prefix with colon, which gets stripped out otherwise */
+                g_string_append_c (message, ':');
             }
             
             if (prefix_char) {
-                char prefix_str[2] = { prefix_char, '\0' };
-                if (!append(&message, &length, prefix_str)) goto decrypt_error;
+                g_string_append_c (message, prefix_char);
             }
             
         } else {
-            // Add unencrypted data (for example, a prefix from a bouncer or bot)
+            /* Add unencrypted data (for example, a prefix from a bouncer or bot) */
             peice = word[uw];
         }
-        
-        if (!append(&message, &length, peice)) goto decrypt_error;
+
+        g_string_append (message, peice);
     }
-    free(decrypted);
+    g_free(decrypted);
     
-    // Simulate unencrypted message
-    //hexchat_printf(ph, "simulating: %s\n", message);
-    hexchat_command(ph, message);
-    
-    free(message);
-    free(sender_nick);
+    /* Simulate unencrypted message */
+    /* hexchat_printf(ph, "simulating: %s\n", message->str); */
+    hexchat_command(ph, message->str);
+
+    g_string_free (message, TRUE);
+    g_free(sender_nick);
     return HEXCHAT_EAT_HEXCHAT;
   
   decrypt_error:
-    free(decrypted);
-    free(sender_nick);
+    g_free(decrypted);
+    g_free(sender_nick);
     return HEXCHAT_EAT_NONE;
 }
 
@@ -201,23 +198,23 @@ static int handle_setkey(char *word[], char *word_eol[], void *userdata) {
     const char *nick;
     const char *key;
     
-    // Check syntax
+    /* Check syntax */
     if (*word[2] == '\0') {
         hexchat_printf(ph, "%s\n", usage_setkey);
         return HEXCHAT_EAT_HEXCHAT;
     }
     
     if (*word[3] == '\0') {
-        // /setkey password
+        /* /setkey password */
         nick = hexchat_get_info(ph, "channel");
         key = word_eol[2];
     } else {
-        // /setkey #channel password
+        /* /setkey #channel password */
         nick = word[2];
         key = word_eol[3];
     }
     
-    // Set password
+    /* Set password */
     if (keystore_store_key(nick, key)) {
         hexchat_printf(ph, "Stored key for %s\n", nick);
     } else {
@@ -233,15 +230,15 @@ static int handle_setkey(char *word[], char *word_eol[], void *userdata) {
 static int handle_delkey(char *word[], char *word_eol[], void *userdata) {
     const char *nick;
     
-    // Check syntax
+    /* Check syntax */
     if (*word[2] == '\0' || *word[3] != '\0') {
         hexchat_printf(ph, "%s\n", usage_delkey);
         return HEXCHAT_EAT_HEXCHAT;
     }
     
-    nick = word_eol[2];
+    nick = g_strstrip (word_eol[2]);
     
-    // Delete the given nick from the key store
+    /* Delete the given nick from the key store */
     if (keystore_delete_nick(nick)) {
         hexchat_printf(ph, "Deleted key for %s\n", nick);
     } else {
@@ -282,11 +279,11 @@ int hexchat_plugin_init(hexchat_plugin *plugin_handle,
     
     /* Add handlers */
     hexchat_hook_command(ph, "", HEXCHAT_PRI_NORM, handle_outgoing, NULL, NULL);
-    hexchat_hook_server(ph, "NOTICE", HEXCHAT_PRI_NORM, handle_incoming, NULL);
-    hexchat_hook_server(ph, "PRIVMSG", HEXCHAT_PRI_NORM, handle_incoming, NULL);
-    //hexchat_hook_server(ph, "RAW LINE", HEXCHAT_PRI_NORM, handle_debug, NULL);
-    hexchat_hook_server(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
-    hexchat_hook_server(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    hexchat_hook_server_attrs(ph, "NOTICE", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    hexchat_hook_server_attrs(ph, "PRIVMSG", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    /* hexchat_hook_server(ph, "RAW LINE", HEXCHAT_PRI_NORM, handle_debug, NULL); */
+    hexchat_hook_server_attrs(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    hexchat_hook_server_attrs(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
     
     hexchat_printf(ph, "%s plugin loaded\n", plugin_name);
     /* Return success */
diff --git a/plugins/fishlim/plugin_hexchat.h b/plugins/fishlim/plugin_hexchat.h
index 04a1f4ff..f60522e6 100644
--- a/plugins/fishlim/plugin_hexchat.h
+++ b/plugins/fishlim/plugin_hexchat.h
@@ -26,6 +26,7 @@
 #define PLUGIN_HEXCHAT_H
 
 gchar *get_config_filename();
+int irc_nick_cmp (const char *, const char *);
 
 #endif
 
diff --git a/plugins/fishlim/test.c b/plugins/fishlim/test.c
deleted file mode 100644
index b4dc8d91..00000000
--- a/plugins/fishlim/test.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  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 THE
-  AUTHORS OR COPYRIGHT HOLDERS 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.
-
-*/
-
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "fish.h"
-
-// We can't use the HexChat plugin API from here...
-gchar *get_config_filename() {
-    const gchar *homedir = g_get_home_dir();
-    return g_build_filename(homedir, ".config", "hexchat", "blow.ini", NULL);
-}
-
-
-static int decrypt(int nick_count, char *nicks[]) {
-    char encrypted[8192];
-    while (fgets(encrypted, sizeof(encrypted), stdin)) {
-        char *msg;
-        for (int i = 0; i < nick_count; i++) {
-            msg = fish_decrypt_from_nick(nicks[i], encrypted);
-            if (msg) goto success;
-        }
-        fprintf(stderr, "None of the recipients were found in the key store!\n");
-        return 1;
-      success:
-        fprintf(stderr, "Decrypted text >>>%s<<<\n", msg);
-        free(msg);
-    }
-    return 0;
-}
-
-static int encrypt(int nick_count, char *nicks[]) {
-    char message[8192];
-    while (fgets(message, sizeof(message), stdin)) {
-        // Remove newline character
-        char *newline = strchr(message, '\n');
-        if (newline) *newline = '\0';
-        
-        bool error = false;
-        for (int i = 0; i < nick_count; i++) {
-            char *encrypted = fish_encrypt_for_nick(nicks[i], message);
-            if (encrypted) {
-                fprintf(stderr, "Encrypted [%s]:  >>>%s<<<\n", nicks[i], encrypted);
-                free(encrypted);
-            } else {
-                error = true;
-            }
-        }
-        
-        if (error) {
-            fprintf(stderr, "Some of the recipients were't found in the key store!\n");
-            return 1;
-        }
-    }
-    return 0;
-}
-
-int main(int argc, char *argv[]) {
-    if (argc < 2) {
-        fprintf(stderr, "usage: %s [-e] nick...\n", argv[0]);
-        return 2;
-    }
-    
-    if (strcmp(argv[1], "-e") == 0) {
-        return encrypt(argc-2, &argv[2]);
-    } else {
-        return decrypt(argc-1, &argv[1]);
-    }
-}
-
-
diff --git a/plugins/mpcinfo/functions.c b/plugins/mpcinfo/functions.c
index ff2d563e..e5993948 100644
--- a/plugins/mpcinfo/functions.c
+++ b/plugins/mpcinfo/functions.c
@@ -14,54 +14,27 @@
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-/*
-typedef int (*MYPROC)(HWND,HWND,char*,char*,BOOL,BOOL); 
-
-int dllProc(char *name, char *data){
-    HINSTANCE hinstLib; 
-    hinstLib = LoadLibrary("mpcinfo");
-    //MYPROC proc;
-    int res;
-    if (hinstLib != NULL){
-       //proc = ;
-       if ((MYPROC) GetProcAddress(hinstLib, name)!=NULL){
-          res=(MYPROC)(NULL,NULL,data,NULL,TRUE,TRUE);
-       }
-       else{fprintf(stderr,"can't get proc: %s\n",name);res=-2;}
-    }
-    else{fprintf(stderr,"can't access dll\n");return -1;}
-    FreeLibrary(hinstLib);
-    return res;
-}
-*/
+#include <glib.h>
 
-/*
-int dllProc(char *name, char *data)
+char *split(char *text, char separator)
 {
-	static HMODULE lib = NULL;
-	if (!lib)
+	int pos = -1;
+	size_t i;
+	for (i = 0; i < strlen(text); i++)
 	{
-		lib = LoadLibraryA ("mpcinfo");
-		if (!lib)
-		{
-			return FALSE;
+		if (text[i] == separator) {
+			pos = i;
+			i = strlen(text) + 1;
 		}
-		FreeLibrary (lib);
 	}
 
-	return TRUE;
-}
-*/
+	if (pos == -1)
+	{
+		return text;
+	}
 
-char *split(char *text, char seperator){
-     //if (DEBUG==1) putlog("splitting");
-     int i;int pos=-1;
-     for (i=0;i<strlen(text);i++){
-         if (text[i]==seperator){pos=i;i=strlen(text)+1;}
-     }
-     if (pos==-1) return text;
-     text[pos]=0;
-     return &(text[pos+1]);
+	text[pos] = 0;
+	return &(text[pos + 1]);
 }
 
 int endsWith(char *text, char *suffix){
@@ -71,21 +44,32 @@ int endsWith(char *text, char *suffix){
     return 0;
 }
 
-int inStr(char *s1, int sl1, char *s2){
-    //if (DEBUG==1) putlog("checking instr");
-	int i;int j;
-	for(i=0;i<sl1-strlen(s2);i++){
-		for (j=0;j<strlen(s2);j++){
-			if (s1[i+j]!=s2[j]) j=strlen(s2)+2;
+int inStr(char *s1, size_t sl1, char *s2)
+{
+	size_t i;
+	for (i = 0; i < sl1 - strlen(s2); i++)
+	{
+		size_t j;
+		for (j = 0; j < strlen(s2); j++)
+		{
+			if (s1[i + j] != s2[j])
+			{
+				j = strlen(s2) + 2;
+			}
+		}
+
+		if (j == strlen(s2))
+		{
+			return i;
 		}
-		if (j==strlen(s2)) return i;
 	}
+
 	return -1;
 }
 
 static char *subString(char *text, int first, int length, int spcKill){
 //if (DEBUG==1) putlog("creating substring");
-	char *ret=(char*) calloc (length+1,sizeof(char)); //malloc(sizeof(char)*(length+1));
+	char *ret = g_new (char, length + 1);
 	int i;
 	ret[length]=0;
 	for (i=0;i<length;i++){
@@ -107,7 +91,7 @@ static char *substring(char *text, int first, int length){return subString(text,
 
 char *readLine(FILE *f){
      //if (DEBUG==1) putlog("reading line from file");
-     char *buffer=(char*)calloc(1024,sizeof(char)); //malloc(sizeof(char)*1024);
+     char *buffer = g_new (char, 1024);
      int pos=0;
      int cc=0;
      while((cc!=EOF)&&(pos<1024)&&(cc!=10)){
@@ -121,14 +105,19 @@ char *readLine(FILE *f){
      return buffer;
 }
 
-char *toUpper(char *text){
-     //if (DEBUG==1) putlog("converting text to upper case");
-     char *ret=(char*) calloc(strlen(text)+1,sizeof(char));
-     int i;
-     for (i=0;i<strlen(text);i++) ret[i]=toupper(text[i]);
-     ret[strlen(text)]=0;
-     //if (DEBUG==1) putlog("uc done");
-     return ret;
+char *toUpper(char *text)
+{
+	char *ret = (char*) calloc(strlen(text) + 1, sizeof(char));
+
+	size_t i;
+	for (i = 0; i < strlen(text); i++)
+	{
+		ret[i] = toupper(text[i]);
+	}
+
+	ret[strlen(text)] = 0;
+
+	return ret;
 }
 
 static char *str3cat(char *s1, char *s2, char *s3){
diff --git a/plugins/mpcinfo/mp3Info.c b/plugins/mpcinfo/mp3Info.c
index 99718624..1af29e45 100644
--- a/plugins/mpcinfo/mp3Info.c
+++ b/plugins/mpcinfo/mp3Info.c
@@ -75,62 +75,25 @@ static char MODES [][13]={"Stereo","Joint-Stereo","Dual-Channel","Mono"};
 
 int iPow(int x, int y){return (int)(pow((double)x,(double) y));}
 
-int str2int(char *text){
-    //if (DEBUG==1) putlog("converting string to int");
-    int i;
-    int ret=0;
-    for (i=1;i<=strlen(text);i++){
-        if ((text[strlen(text)-i]>57)||(text[strlen(text)-i]<48)){
-           hexchat_printf(ph,"invalid char in string: %i",text[strlen(text)-i]);
-           return 255;
-        }
-        ret+=((int)text[strlen(text)-i]-48)*iPow(10,i-1);
-    }
-    //hexchat_printf(ph, "str2int(%s)=%i",text,ret);
-    //if (DEBUG==1) putlog("int converted");
-    return ret;
-}
-/*
-static int getSize(char *file){
-    //if (DEBUG==1) putlog("reading filesize");
-	struct stat info;
-	if (stat(file,&info)!=0) return -1;
-	return info.st_size;
-}*/
-/*
-int inStr(char *s1, int sl1, char *s2){
-    //if (DEBUG==1) putlog("checking instr");
-	int i;int j;
-	for(i=0;i<sl1-strlen(s2);i++){
-		for (j=0;j<strlen(s2);j++){
-			if (s1[i+j]!=s2[j]) j=strlen(s2)+2;
+int str2int(char *text)
+{
+	int ret = 0;
+
+	size_t i;
+	for (i = 1; i <= strlen(text); i++)
+	{
+		if ((text[strlen(text) - i] > 57) || (text[strlen(text) - i] < 48))
+		{
+			hexchat_printf(ph, "invalid char in string: %i", (int) text[strlen(text) - i]);
+			return 255;
 		}
-		if (j==strlen(s2)) return i;
-	}
-	return -1;
-}
 
-static char *subString(char *text, int first, int length, int spcKill){
-//if (DEBUG==1) putlog("creating substring");
-	char *ret=(char*) calloc (length+1,sizeof(char)); //malloc(sizeof(char)*(length+1));
-	ret[length]=0;int i;
-	for (i=0;i<length;i++){
-		ret[i]=text[i+first];
-		//if (ret[i]==0) ret[i]='0';
+		ret += ((int) text[strlen(text) - i] - 48)*iPow(10, i - 1);
 	}
-	if (spcKill==1){
-	   for (i=length-1;i>=0;i--){
-           if (ret[i]==32) ret[i]=0;
-           else i=-1;
-       }
-    }
-    //if (DEBUG==1) putlog("substring created");
+
 	return ret;
 }
 
-static char *substring(char *text, int first, int length){return subString(text,first,length,0);} //1
-*/
-
 static char *tagExtract(char *tag, int tagLen, char* info){
 //if (DEBUG==1) putlog("extracting tag");
 	int pos, len, i;
@@ -204,23 +167,28 @@ struct tagInfo readID3V1(char *file){
 	return ret;
 }
 
-char *extractID3Genre(char *tag){
-     //if (DEBUG==1) putlog("extracting id3 genre");
-     if (tag[strlen(tag)-1]==')'){
-        tag[strlen(tag)-1]=0;
-        tag=&tag[1];
-        return GENRES[str2int(tag)];
-        //return tag;
-     }
-     else{
-          int i;
-          //hexchat_print(ph, "Using 2 criteria");
-          for (i=0;i<strlen(tag);i++){
-              if (tag[i]==')'){ tag=&tag[i]+1;return tag;}
-          //return tag;
-          }
-     }
-     return "[152] failed";
+char *extractID3Genre(char *tag)
+{
+	if (tag[strlen(tag) - 1] == ')')
+	{
+		tag[strlen(tag) - 1] = 0;
+		tag = &tag[1];
+		return GENRES[str2int(tag)];
+	}
+	else
+	{
+		size_t i;
+		for (i = 0; i < strlen(tag); i++)
+		{
+			if (tag[i] == ')')
+			{
+				tag = &tag[i] + 1;
+				return tag;
+			}
+		}
+	}
+
+	return "[152] failed";
 }
 
 struct tagInfo readID3V2(char *file){
diff --git a/plugins/mpcinfo/mpcInfo.c b/plugins/mpcinfo/mpcInfo.c
index 4ab16642..4ad17689 100644
--- a/plugins/mpcinfo/mpcInfo.c
+++ b/plugins/mpcinfo/mpcInfo.c
@@ -48,12 +48,20 @@ static int mpc_tell(char *word[], char *word_eol[], void *userdata){
 	   HWND hwnd = FindWindow("MediaPlayerClassicW",NULL);
        if (hwnd==0) {hexchat_print(ph, randomLine(notRunTheme));return HEXCHAT_EAT_ALL;}
        
-       tTitle=(char*)malloc(sizeof(char)*1024);
+       tTitle = g_new(char, 1024);
        GetWindowText(hwnd, tTitle, 1024);
-       zero=strstr(tTitle," - Media Player Classic");
-       if (zero!=NULL) zero[0]=0;
-       else hexchat_print(ph,"pattern not found");
-       
+       zero = strstr (tTitle, " - Media Player Classic");
+	   if (zero != NULL)
+	   {
+		   zero[0] = 0;
+	   }
+	   else
+	   {
+		   g_free(tTitle);
+		   hexchat_print(ph, "pattern not found");
+		   return HEXCHAT_EAT_ALL;
+	   }
+
        if ((tTitle[1]==':')&&(tTitle[2]=='\\')){
           //hexchat_print(ph,"seams to be full path");
           if (endsWith(tTitle,".mp3")==1){
@@ -82,7 +90,8 @@ static int mpc_tell(char *word[], char *word_eol[], void *userdata){
                 //mp3Line=intReplace(mp3Line,"%perc",perc);
                 //mp3Line=replace(mp3Line,"%plTitle",title);
                 mp3Line=replace(mp3Line,"%file",tTitle);
-                hexchat_command(ph, mp3Line);
+				g_free(tTitle);
+				hexchat_command(ph, mp3Line);
                 return HEXCHAT_EAT_ALL;
              }
           }
@@ -111,14 +120,16 @@ static int mpc_tell(char *word[], char *word_eol[], void *userdata){
                 //oggLine=intReplace(oggLine,"%perc",perc);
                 //oggLine=replace(oggLine,"%plTitle",title);
                 oggLine=replace(oggLine,"%file",tTitle);
-                hexchat_command(ph, oggLine);
+				g_free(tTitle);
+				hexchat_command(ph, oggLine);
                 return HEXCHAT_EAT_ALL;
              }
           }
        }
        line=randomLine(titleTheme);
        line=replace(line,"%title", tTitle);
-       hexchat_command(ph,line); 
+	   g_free(tTitle);
+	   hexchat_command(ph, line);
        return HEXCHAT_EAT_ALL;
 }
 
diff --git a/plugins/mpcinfo/mpcinfo.vcxproj b/plugins/mpcinfo/mpcinfo.vcxproj
index f69e8968..3c4b3e7d 100644
--- a/plugins/mpcinfo/mpcinfo.vcxproj
+++ b/plugins/mpcinfo/mpcinfo.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,75 +20,32 @@
     <RootNamespace>mpcinfo</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hcmpcinfo</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcmpcinfo</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MPCINFO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>..\..\src\common;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

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

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>mpcinfo.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;MPCINFO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>..\..\src\common;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

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

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>mpcinfo.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

@@ -98,6 +56,4 @@
     <ClCompile Include="mpcInfo.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/mpcinfo/oggInfo.c b/plugins/mpcinfo/oggInfo.c
index 59d84791..e1191649 100644
--- a/plugins/mpcinfo/oggInfo.c
+++ b/plugins/mpcinfo/oggInfo.c
@@ -25,14 +25,18 @@ static int getOggInt(char *buff, int beg, int bytes){
 	return ret;
 }
 
-static char *upperStr(char *text){
-//if (DEBUG==1) putlog("converting text to uc");
-    //printf("upperStr(%s)\n",text);
-	int i;
-	char *ret=(char*) malloc(sizeof(char)*(strlen(text)+1));
-	ret[strlen(text)]=0;
-	for (i=0;i<strlen(text);i++) ret[i]=toupper(text[i]);
-	//printf("Result: %s\n",ret);
+static char *upperStr(char *text)
+{
+	char *ret = (char*) malloc(sizeof(char)*(strlen(text) + 1));
+
+	size_t i;
+	for (i = 0; i < strlen(text); i++)
+	{
+		ret[i] = toupper(text[i]);
+	}
+
+	ret[strlen(text)] = 0;
+
 	return ret;
 }
 
diff --git a/plugins/mpcinfo/theme.c b/plugins/mpcinfo/theme.c
index 3f98a59c..3d8a7a0e 100644
--- a/plugins/mpcinfo/theme.c
+++ b/plugins/mpcinfo/theme.c
@@ -49,24 +49,32 @@ void printThemes(){
      hexchat_printf(ph,"\nTitle-Theme:\n");printTheme(titleTheme);
 }
 
-void cbFix(char *line){
-     //if (DEBUG==1) putlog("cbfix");
-     int i, j;
-     for (i=0;i<strlen(line);i++){
-         if (line[i]=='%'){
-            if ((line[i+1]=='C')||(line[i+1]=='B')||(line[i+1]=='U')||(line[i+1]=='O')||(line[i+1]=='R')){
-               if(line[i+1]=='C') line[i]=3;
-               if(line[i+1]=='B') line[i]=2;
-               if(line[i+1]=='U') line[i]=37;
-               if(line[i+1]=='O') line[i]=17;
-               if(line[i+1]=='R') line[i]=26;
-
-               for (j=i+1;j<strlen(line)-1;j++) line[j]=line[j+1];
-               line[strlen(line)-1]=0;
-            }
-         }
-     }
-     //if (DEBUG==1) putlog("cbfix done");
+void cbFix(char *line)
+{
+	size_t i;
+	for (i = 0; i < strlen(line); i++)
+	{
+		size_t j;
+
+		if (line[i] == '%')
+		{
+			if ((line[i + 1] == 'C') || (line[i + 1] == 'B') || (line[i + 1] == 'U') || (line[i + 1] == 'O') || (line[i + 1] == 'R'))
+			{
+				if (line[i + 1] == 'C') line[i] = 3;
+				if (line[i + 1] == 'B') line[i] = 2;
+				if (line[i + 1] == 'U') line[i] = 37;
+				if (line[i + 1] == 'O') line[i] = 17;
+				if (line[i + 1] == 'R') line[i] = 26;
+
+				for (j = i + 1; j < strlen(line) - 1; j++)
+				{
+					line[j] = line[j + 1];
+				}
+
+				line[strlen(line) - 1] = 0;
+			}
+		}
+	}
 }
 
 struct theme themeAdd(struct theme data, char *info){
diff --git a/plugins/perl/Makefile.am b/plugins/perl/Makefile.am
index 79621549..83239672 100644
--- a/plugins/perl/Makefile.am
+++ b/plugins/perl/Makefile.am
@@ -6,12 +6,13 @@ libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = perl.la
 perl_la_SOURCES = perl.c
-perl_la_LDFLAGS = -avoid-version -module 
-perl_la_LIBADD = $(PERL_LDFLAGS)
+perl_la_LDFLAGS = $(PERL_LDFLAGS) $(PLUGIN_LDFLAGS) -module
+perl_la_LIBADD = $(GLIB_LIBS)
+perl_la_CFLAGS = $(PERL_CFLAGS) $(GLIB_CFLAGS) -I$(top_srcdir)/src/common
+
 BUILT_SOURCES = hexchat.pm.h irc.pm.h
-#CFLAGS = @CFLAGS@ -Wno-unused
-AM_CPPFLAGS = $(PERL_CFLAGS) $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
-CLEANFILES = hexchat.pm.h irc.pm.h
+CLEANFILES = $(BUILT_SOURCES)
+
 hexchat.pm.h irc.pm.h: lib/HexChat.pm lib/Xchat.pm lib/HexChat/Embed.pm \
 	lib/HexChat/List/Network.pm lib/HexChat/List/Network/Entry.pm \
 	lib/HexChat/List/Network/AutoJoin.pm lib/IRC.pm
diff --git a/plugins/perl/perl.c b/plugins/perl/perl.c
index 74333516..b954fb0b 100644
--- a/plugins/perl/perl.c
+++ b/plugins/perl/perl.c
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -31,8 +33,9 @@
 #include <dirent.h>
 #endif
 
+#include <glib.h>
+
 #undef PACKAGE
-#include "../../config.h"
 
 #include "hexchat-plugin.h"
 
@@ -75,37 +78,26 @@ thread_mbox (char *str)
 static void
 perl_auto_load_from_path (const char *path)
 {
-	WIN32_FIND_DATA find_data;
-	HANDLE find_handle;
-	char *search_path;
-	int path_len = strlen (path);
-
-	/* +6 for \*.pl and \0 */
-	search_path = malloc(path_len + 6);
-	sprintf (search_path, "%s\\*.pl", path);
-
-	find_handle = FindFirstFile (search_path, &find_data);
+	char *search_path = g_build_filename (path, "*.pl", NULL);
+	WIN32_FIND_DATAA find_data;
+	HANDLE find_handle = FindFirstFileA (search_path, &find_data);
 
 	if (find_handle != INVALID_HANDLE_VALUE)
 	{
 		do
 		{
-			if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
-				||find_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
+			if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 && (find_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0)
 			{
-				char *full_path =
-					malloc (path_len + strlen (find_data.cFileName) + 2);
-				sprintf (full_path, "%s\\%s", path, find_data.cFileName);
-
+				char *full_path = g_build_filename (path, find_data.cFileName, NULL);
 				perl_load_file (full_path);
-				free (full_path);
+				g_free (full_path);
 			}
 		}
-		while (FindNextFile (find_handle, &find_data) != 0);
+		while (FindNextFileA (find_handle, &find_data) != 0);
 		FindClose (find_handle);
 	}
 
-	free (search_path);
+	g_free (search_path);
 }
 #else
 static void
@@ -115,14 +107,16 @@ perl_auto_load_from_path (const char *path)
 	struct dirent *ent;
 
 	dir = opendir (path);
-	if (dir) {
-		while ((ent = readdir (dir))) {
+	if (dir)
+	{
+		while ((ent = readdir (dir)))
+		{
 			int len = strlen (ent->d_name);
-			if (len > 3 && strcasecmp (".pl", ent->d_name + len - 3) == 0) {
-				char *file = malloc (len + strlen (path) + 2);
-				sprintf (file, "%s/%s", path, ent->d_name);
+			if (len > 3 && strcasecmp (".pl", ent->d_name + len - 3) == 0)
+			{
+				char *file = g_build_filename (path, ent->d_name, NULL);
 				perl_load_file (file);
-				free (file);
+				g_free (file);
 			}
 		}
 		closedir (dir);
@@ -145,31 +139,10 @@ perl_auto_load (void *unused)
 
 	/* don't pollute the filesystem with script files, this only causes misuse of the folders
 	 * only use ~/.config/hexchat/addons/ and %APPDATA%\HexChat\addons */
-#if 0
-	/* autoload from ~/.config/hexchat/ or %APPDATA%\HexChat\ on win32 */
-	perl_auto_load_from_path (xdir);
-#endif
-
-	sub_dir = malloc (strlen (xdir) + 8);
-	strcpy (sub_dir, xdir);
-	strcat (sub_dir, "/addons");
+	sub_dir = g_build_filename (xdir, "addons", NULL);
 	perl_auto_load_from_path (sub_dir);
-	free (sub_dir);
+	g_free (sub_dir);
 
-#if 0
-#ifdef WIN32
-	/* autoload from  C:\Program Files\HexChat\plugins\ */
-	sub_dir = malloc (1025 + 9);
-	copied = GetModuleFileName( 0, sub_dir, 1024 );
-	sub_dir[copied] = '\0';
-	slash = strrchr( sub_dir, '\\' );
-	if( slash != NULL ) {
-		*slash = '\0';
-	}
-	perl_auto_load_from_path ( strncat (sub_dir, "\\plugins", 9));
-	free (sub_dir);
-#endif
-#endif
 	return 0;
 }
 
@@ -288,7 +261,19 @@ list_item_to_sv ( hexchat_list *list, const char *const *fields )
 			field_value = newSVuv (hexchat_list_int (ph, list, field_name));
 			break;
 		case 't':
-			field_value = newSVnv (hexchat_list_time (ph, list, field_name));
+			/* From perldoc for Perl's own timelocal() and timegm():
+			 * <quote>
+			 * On perl versions older than 5.12.0, the range of dates that can be actually be handled depends on the size of time_t (usually a signed integer) on the given platform.
+			 * As of version 5.12.0, perl has stopped using the underlying time library of the operating system it's running on and has its own implementation of those routines with a
+			 * safe range of at least +/ 2**52 (about 142 million years).
+			 * </quote>
+			 *
+			 * This is further confirmed from looking at the source for Time::Local - it's a Perl module and the implementations of timelocal() and timegm() use simple addition and
+			 * subtraction of numbers. Perl automatically promotes numbers from int32_t (IV) to uint32_t (UV) to 64-bit IEEE754 double (NV) as required.
+			 *
+			 * This means that using a double (NV) for our own time_t suffers from the same assumptions that Perl's own functions do.
+			 */
+			field_value = newSVnv ((const NV) hexchat_list_time (ph, list, field_name));
 			break;
 		default:
 			field_value = &PL_sv_undef;
@@ -372,7 +357,7 @@ fd_cb (int fd, int flags, void *userdata)
 				if (data->userdata) {
 					SvREFCNT_dec (data->userdata);
 				}
-				free (data);
+				g_free (data);
 			}
 		}
 
@@ -736,7 +721,7 @@ XS (XS_HexChat_send_modes)
 		if (SvROK (ST (0))) {
 			p_targets = (AV*) SvRV (ST (0));
 			target_count = av_len (p_targets) + 1;
-			targets = malloc (target_count * sizeof (char *));
+			targets = g_new (const char *, target_count);
 			for (i = 0; i < target_count; i++ ) {
 				elem = av_fetch (p_targets, i, 0);
 
@@ -747,13 +732,13 @@ XS (XS_HexChat_send_modes)
 				}
 			}
 		} else{
-			targets = malloc (sizeof (char *));
+			targets = g_new (const char *, 1);
 			targets[0] = SvPV_nolen (ST (0));
 			target_count = 1;
 		}
 		
 		if (target_count == 0) {
-			free (targets);
+			g_free ((char**) targets);
 			XSRETURN_EMPTY;
 		}
 
@@ -765,7 +750,7 @@ XS (XS_HexChat_send_modes)
 		}
 
 		hexchat_send_modes (ph, targets, target_count, modes_per_line, sign, mode);
-		free (targets);
+		g_free ((char**) targets);
 	}
 }
 static
@@ -883,11 +868,7 @@ XS (XS_HexChat_hook_server)
 		userdata = ST (3);
 		package = ST (4);
 		data = NULL;
-		data = malloc (sizeof (HookData));
-		if (data == NULL) {
-			XSRETURN_UNDEF;
-		}
-
+		data = g_new (HookData, 1);
 		data->callback = newSVsv (callback);
 		data->userdata = newSVsv (userdata);
 		data->depth = 0;
@@ -932,11 +913,7 @@ XS (XS_HexChat_hook_command)
 		package = ST (5);
 		data = NULL;
 
-		data = malloc (sizeof (HookData));
-		if (data == NULL) {
-			XSRETURN_UNDEF;
-		}
-
+		data = g_new (HookData, 1);
 		data->callback = newSVsv (callback);
 		data->userdata = newSVsv (userdata);
 		data->depth = 0;
@@ -972,11 +949,7 @@ XS (XS_HexChat_hook_print)
 		userdata = ST (3);
 		package = ST (4);
 
-		data = malloc (sizeof (HookData));
-		if (data == NULL) {
-			XSRETURN_UNDEF;
-		}
-
+		data = g_new (HookData, 1);
 		data->callback = newSVsv (callback);
 		data->userdata = newSVsv (userdata);
 		data->depth = 0;
@@ -1010,11 +983,7 @@ XS (XS_HexChat_hook_timer)
 		userdata = ST (2);
 		package = ST (3);
 
-		data = malloc (sizeof (HookData));
-		if (data == NULL) {
-			XSRETURN_UNDEF;
-		}
-
+		data = g_new (HookData, 1);
 		data->callback = newSVsv (callback);
 		data->userdata = newSVsv (userdata);
 		data->ctx = hexchat_get_context (ph);
@@ -1064,11 +1033,7 @@ XS (XS_HexChat_hook_fd)
 		}
 #endif
 
-		data = malloc (sizeof (HookData));
-		if (data == NULL) {
-			XSRETURN_UNDEF;
-		}
-
+		data = g_new (HookData, 1);
 		data->callback = newSVsv (callback);
 		data->userdata = newSVsv (userdata);
 		data->depth = 0;
@@ -1108,7 +1073,7 @@ XS (XS_HexChat_unhook)
 				SvREFCNT_dec (userdata->package);
 			}
 
-			free (userdata);
+			g_free (userdata);
 		}
 		XSRETURN (retCount);
 	}
diff --git a/plugins/perl/perl.vcxproj b/plugins/perl/perl.vcxproj
index 1a76928d..e9b380ee 100644
--- a/plugins/perl/perl.vcxproj
+++ b/plugins/perl/perl.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,66 +20,28 @@
     <RootNamespace>perl520</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>$(PerlOutput)</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>$(PerlOutput)</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

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

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

+  <PropertyGroup>

+    <TargetName>hcperl</TargetName>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

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

-      <AdditionalIncludeDirectories>$(PerlPath)\lib\CORE;$(IntDir);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(IntDir);..\..\src\common;$(HexChatLib);$(PerlPath)\lib\CORE;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <AdditionalDependencies>$(PerlLib).lib;%(AdditionalDependencies)</AdditionalDependencies>

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

+      <AdditionalDependencies>$(PerlLib).lib;$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>perl.def</ModuleDefinitionFile>

       <DelayLoadDLLs>$(PerlLib).dll;%(DelayLoadDLLs)</DelayLoadDLLs>

     </Link>

     <PreBuildEvent>

       <Command>"$(GendefPath)\gendef" "$(PerlPath)\bin\$(PerlLib).dll"

 move $(PerlLib).def "$(IntDir)"

-lib /nologo /machine:x86 "/def:$(IntDir)$(PerlLib).def" "/out:$(OutDir)\$(PerlLib).lib"

+lib /nologo /machine:x86 "/def:$(IntDir)$(PerlLib).def" "/out:$(IntDir)\$(PerlLib).lib"

 "$(PerlPath)\bin\perl.exe" generate_header

 move irc.pm.h "$(IntDir)"

 move hexchat.pm.h "$(IntDir)"</Command>

@@ -86,28 +49,19 @@ move hexchat.pm.h "$(IntDir)"</Command>
   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;PERL520_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(PerlPath)\lib\CORE;$(IntDir);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(IntDir);..\..\src\common;$(HexChatLib);$(PerlPath)\lib\CORE;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <AdditionalDependencies>$(PerlLib).lib;%(AdditionalDependencies)</AdditionalDependencies>

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

+      <AdditionalDependencies>$(PerlLib).lib;$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>perl.def</ModuleDefinitionFile>

       <DelayLoadDLLs>$(PerlLib).dll;%(DelayLoadDLLs)</DelayLoadDLLs>

     </Link>

     <PreBuildEvent>

       <Command>"$(GendefPath)\gendef" "$(PerlPath)\bin\$(PerlLib).dll"

 move $(PerlLib).def "$(IntDir)"

-lib /nologo /machine:x64 "/def:$(IntDir)$(PerlLib).def" "/out:$(OutDir)\$(PerlLib).lib"

+lib /nologo /machine:x64 "/def:$(IntDir)$(PerlLib).def" "/out:$(IntDir)\$(PerlLib).lib"

 "$(PerlPath)\bin\perl.exe" generate_header

 move irc.pm.h "$(IntDir)"

 move hexchat.pm.h "$(IntDir)"</Command>

@@ -120,6 +74,4 @@ move hexchat.pm.h "$(IntDir)"</Command>
     <ClCompile Include="perl.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/plugin-conf.in b/plugins/plugin-conf.in
deleted file mode 100644
index f43f5c53..00000000
--- a/plugins/plugin-conf.in
+++ /dev/null
@@ -1,19 +0,0 @@
-AC_INIT(@PLUGIN@-config.h.in)
-AM_CONFIG_HEADER(@PLUGIN@-config.h)
-AM_INIT_AUTOMAKE(hexchat-@PLUGIN@, @PLUGIN_VERSION@)
-AM_MAINTAINER_MODE
-AM_DISABLE_STATIC
-AM_PROG_LIBTOOL
-
-AC_ARG_WITH(plugin-includes,
-[  --with-plugin-includes  directory containing hexchat-plugin.h],
-	PLUGIN_INCLUDES=$enableval)
-
-AC_SUBST(PLUGIN_INCLUDES)
-
-hexchatlibdir=${libdir}/hexchat
-AC_SUBST(hexchatlibdir)
-
-AC_OUTPUT(
-Makefile
-)
diff --git a/plugins/python/Makefile.am b/plugins/python/Makefile.am
index 259f2a0f..063f2009 100644
--- a/plugins/python/Makefile.am
+++ b/plugins/python/Makefile.am
@@ -1,10 +1,8 @@
-EXTRA_DIST = 
-
 libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = python.la
 python_la_SOURCES = python.c
-python_la_LDFLAGS = -avoid-version -module 
-python_la_LIBADD = $(PY_LIBS)
-AM_CPPFLAGS = $(PY_CFLAGS) $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+python_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+python_la_LIBADD = $(PY_LIBS) $(GLIB_LIBS)
+python_la_CFLAGS = $(PY_CFLAGS) $(GLIB_CFLAGS) -I$(top_srcdir)/src/common
 
diff --git a/plugins/python/python.c b/plugins/python/python.c
index 1904a3e9..1f9c7cc9 100644
--- a/plugins/python/python.c
+++ b/plugins/python/python.c
@@ -51,6 +51,8 @@
  *
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <glib/gstdio.h>
 #include <string.h>
@@ -64,9 +66,9 @@
 #include <dirent.h>
 #endif
 
-#include "../../config.h"
 #include "hexchat-plugin.h"
-#undef _POSIX_C_SOURCE	/* Avoid warning: also in /usr/include/features.h from glib.h */
+#undef _POSIX_C_SOURCE	/* Avoid warnings from /usr/include/features.h */
+#undef _XOPEN_SOURCE
 #include <Python.h>
 #include <structmember.h>
 #include <pythread.h>
@@ -414,6 +416,9 @@ Util_BuildEOLList(char *word[])
 	PyObject *list;
 	int listsize = 31;
 	int i;
+	char *accum = NULL;
+	char *last = NULL;
+
 	/* Find the last valid array member; there may be intermediate NULLs that
 	 * would otherwise cause us to drop some members. */
 	while (listsize > 0 &&
@@ -424,10 +429,9 @@ Util_BuildEOLList(char *word[])
 		PyErr_Print();
 		return NULL;
 	}
-	char *accum = NULL;
-	char *last = NULL;
 	for (i = listsize; i > 0; i--) {
 		char *part = word[i];
+		PyObject *uni_part;
 		if (accum == NULL) {
 			accum = g_strdup (part);
 		} else if (part != NULL && part[0] != 0) {
@@ -443,14 +447,12 @@ Util_BuildEOLList(char *word[])
 				return NULL;
 			}
 		}
-		PyObject *uni_part = PyUnicode_FromString(accum);
+		uni_part = PyUnicode_FromString(accum);
 		PyList_SetItem(list, i - 1, uni_part);
 	}
 
-	if (last)
-		g_free (last);
-	if (accum)
-		g_free (accum);
+	g_free (last);
+	g_free (accum);
 
 	return list;
 }
@@ -800,9 +802,7 @@ Callback_ThreadTimer(void *userdata)
 /* We keep this information global, so we can reset it when the
  * deinit function is called. */
 /* XXX This should be somehow bound to the printing context. */
-static char *xchatout_buffer = NULL;
-static int xchatout_buffer_size = 0;
-static int xchatout_buffer_pos = 0;
+static GString *xchatout_buffer = NULL;
 
 static PyObject *
 XChatOut_New()
@@ -826,76 +826,42 @@ XChatOut_dealloc(PyObject *self)
 static PyObject *
 XChatOut_write(PyObject *self, PyObject *args)
 {
-	int new_buffer_pos, data_size, print_limit, add_space;
+	gboolean add_space;
 	char *data, *pos;
-	if (!PyArg_ParseTuple(args, "s#:write", &data, &data_size))
+
+	if (!PyArg_ParseTuple(args, "s:write", &data))
 		return NULL;
-	if (!data_size) {
-		Py_INCREF(Py_None);
-		return Py_None;
+	if (!data || !*data) {
+		Py_RETURN_NONE;
 	}
 	BEGIN_XCHAT_CALLS(RESTORE_CONTEXT|ALLOW_THREADS);
 	if (((XChatOutObject *)self)->softspace) {
-		add_space = 1;
+		add_space = TRUE;
 		((XChatOutObject *)self)->softspace = 0;
 	} else {
-		add_space = 0;
-	}
-	if (xchatout_buffer_size-xchatout_buffer_pos < data_size+add_space) {
-		char *new_buffer;
-		/* This buffer grows whenever needed, and does not
-		 * shrink. If we ever implement unloading of the
-		 * python interface, we must find some way to free
-		 * this buffer as well. */
-		xchatout_buffer_size += data_size*2+16;
-		new_buffer = g_realloc(xchatout_buffer, xchatout_buffer_size);
-		if (new_buffer == NULL) {
-			hexchat_print(ph, "Not enough memory to print");
-			/* The system is out of resources. Let's help. */
-			g_free(xchatout_buffer);
-			xchatout_buffer = NULL;
-			xchatout_buffer_size = 0;
-			xchatout_buffer_pos = 0;
-			/* Return something valid, since we have
-			 * already warned the user, and he probably
-			 * won't be able to notice this exception. */
-			goto exit;
-		}
-		xchatout_buffer = new_buffer;
-	}
-	memcpy(xchatout_buffer+xchatout_buffer_pos, data, data_size);
-	print_limit = new_buffer_pos = xchatout_buffer_pos+data_size;
-	pos = xchatout_buffer+print_limit;
-	if (add_space && *(pos-1) != '\n') {
-		*pos = ' ';
-		*(pos+1) = 0;
-		new_buffer_pos++;
-	}
-	while (*pos != '\n' && print_limit > xchatout_buffer_pos) {
-		pos--;
-		print_limit--;
-	}
-	if (*pos == '\n') {
-		/* Crop it, inserting the string limiter there. */
-		*pos = 0;
-		hexchat_print(ph, xchatout_buffer);
-		if (print_limit < new_buffer_pos) {
-			/* There's still data to be printed. */
-			print_limit += 1; /* Include the limiter. */
-			xchatout_buffer_pos = new_buffer_pos-print_limit;
-			memmove(xchatout_buffer, xchatout_buffer+print_limit,
-				xchatout_buffer_pos);
-		} else {
-			xchatout_buffer_pos = 0;
-		}
-	} else {
-		xchatout_buffer_pos = new_buffer_pos;
+		add_space = FALSE;
+	}
+
+	g_string_append (xchatout_buffer, data);
+
+	/* If not end of line add space to continue buffer later */
+	if (add_space && xchatout_buffer->str[xchatout_buffer->len - 1] != '\n')
+	{
+		g_string_append_c (xchatout_buffer, ' ');
+	}
+
+	/* If there is an end of line print up to that */
+	if ((pos = strrchr (xchatout_buffer->str, '\n')))
+	{
+		*pos = '\0';
+		hexchat_print (ph, xchatout_buffer->str);
+
+		/* Then remove it from buffer */
+		g_string_erase (xchatout_buffer, 0, pos - xchatout_buffer->str + 1);
 	}
 
-exit:
 	END_XCHAT_CALLS();
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 #define OFF(x) offsetof(XChatOutObject, x)
@@ -1047,8 +1013,7 @@ Context_set(ContextObject *self, PyObject *args)
 {
 	PyObject *plugin = Plugin_GetCurrent();
 	Plugin_SetContext(plugin, self->context);
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1061,8 +1026,7 @@ Context_command(ContextObject *self, PyObject *args)
 	hexchat_set_context(ph, self->context);
 	hexchat_command(ph, text);
 	END_XCHAT_CALLS();
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1075,8 +1039,7 @@ Context_prnt(ContextObject *self, PyObject *args)
 	hexchat_set_context(ph, self->context);
 	hexchat_print(ph, text);
 	END_XCHAT_CALLS();
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1121,8 +1084,7 @@ Context_get_info(ContextObject *self, PyObject *args)
 	info = hexchat_get_info(ph, name);
 	END_XCHAT_CALLS();
 	if (info == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
+		Py_RETURN_NONE;
 	}
 	return PyUnicode_FromString(info);
 }
@@ -1405,11 +1367,7 @@ static Hook *
 Plugin_AddHook(int type, PyObject *plugin, PyObject *callback,
 	       PyObject *userdata, char *name, void *data)
 {
-	Hook *hook = (Hook *) g_malloc(sizeof(Hook));
-	if (hook == NULL) {
-		PyErr_NoMemory();
-		return NULL;
-	}
+	Hook *hook = g_new(Hook, 1);
 	hook->type = type;
 	hook->plugin = plugin;
 	Py_INCREF(callback);
@@ -1463,8 +1421,7 @@ Plugin_RemoveHook(PyObject *plugin, Hook *hook)
 					       hook));
 		Py_DECREF(hook->callback);
 		Py_DECREF(hook->userdata);
-		if (hook->name)
-			g_free(hook->name);
+		g_free(hook->name);
 		g_free(hook);
 	}
 }
@@ -1483,8 +1440,7 @@ Plugin_RemoveAllHooks(PyObject *plugin)
 		}
 		Py_DECREF(hook->callback);
 		Py_DECREF(hook->userdata);
-		if (hook->name)
-			g_free(hook->name);
+		g_free(hook->name);
 		g_free(hook);
 		list = list->next;
 	}
@@ -1713,8 +1669,7 @@ Module_hexchat_command(PyObject *self, PyObject *args)
 	BEGIN_XCHAT_CALLS(RESTORE_CONTEXT|ALLOW_THREADS);
 	hexchat_command(ph, text);
 	END_XCHAT_CALLS();
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1726,8 +1681,7 @@ Module_xchat_prnt(PyObject *self, PyObject *args)
 	BEGIN_XCHAT_CALLS(RESTORE_CONTEXT|ALLOW_THREADS);
 	hexchat_print(ph, text);
 	END_XCHAT_CALLS();
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1770,8 +1724,7 @@ Module_hexchat_get_info(PyObject *self, PyObject *args)
 	info = hexchat_get_info(ph, name);
 	END_XCHAT_CALLS();
 	if (info == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
+		Py_RETURN_NONE;
 	}
 	if (strcmp (name, "gtkwin_ptr") == 0)
 		return PyUnicode_FromFormat("%p", info); /* format as pointer */
@@ -1824,8 +1777,7 @@ Module_hexchat_get_context(PyObject *self, PyObject *args)
 		return NULL;
 	ctxobj = Context_FromContext(Plugin_GetContext(plugin));
 	if (ctxobj == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
+		Py_RETURN_NONE;
 	}
 	return ctxobj;
 }
@@ -1842,8 +1794,7 @@ Module_hexchat_find_context(PyObject *self, PyObject *args, PyObject *kwargs)
 		return NULL;
 	ctxobj = Context_FromServerAndChannel(server, channel);
 	if (ctxobj == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
+		Py_RETURN_NONE;
 	}
 	return ctxobj;
 }
@@ -1889,7 +1840,7 @@ Module_hexchat_pluginpref_get(PyObject *self, PyObject *args)
 	if (!PyArg_ParseTuple(args, "s:get_pluginpref", &var))
 		return NULL;
 		
-	// This will always return numbers as integers.
+	/* This will always return numbers as integers. */
 	BEGIN_XCHAT_CALLS(NONE);
 	result = hexchat_pluginpref_get_str(prefph, var, retstr);
 	END_XCHAT_CALLS();
@@ -2223,8 +2174,7 @@ Module_hexchat_unhook(PyObject *self, PyObject *args)
 		Plugin_RemoveHook(plugin, hook);
 	}	
 
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -2532,11 +2482,8 @@ IInterp_Exec(char *command)
 	}
 	d = PyModule_GetDict(m);
 	len = strlen(command);
-	buffer = (char *) g_malloc(len+2);
-	if (buffer == NULL) {
-		hexchat_print(ph, "Not enough memory for command buffer");
-		goto fail;
-	}
+
+	buffer = g_malloc(len + 2);
 	memcpy(buffer, command, len);
 	buffer[len] = '\n';
 	buffer[len+1] = 0;
@@ -2782,6 +2729,7 @@ hexchat_plugin_init(hexchat_plugin *plugin_handle,
 	Py_Initialize();
 	PySys_SetArgv(1, argv);
 
+	xchatout_buffer = g_string_new (NULL);
 	xchatout = XChatOut_New();
 	if (xchatout == NULL) {
 		hexchat_print(ph, "Can't allocate xchatout object");
@@ -2852,10 +2800,8 @@ hexchat_plugin_deinit()
 	plugin_list = NULL;
 
 	/* Reset xchatout buffer. */
-	g_free(xchatout_buffer);
+	g_string_free (xchatout_buffer, TRUE);
 	xchatout_buffer = NULL;
-	xchatout_buffer_size = 0;
-	xchatout_buffer_pos = 0;
 
 	if (interp_plugin) {
 		Py_DECREF(interp_plugin);
diff --git a/plugins/python/python2.vcxproj b/plugins/python/python2.vcxproj
index 58a9e45e..ecf0df75 100644
--- a/plugins/python/python2.vcxproj
+++ b/plugins/python/python2.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,80 +20,33 @@
     <RootNamespace>python2</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>$(Python2Output)</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>$(Python2Output)</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

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

-      <AdditionalIncludeDirectories>$(Glib);$(Python2Path)\include;..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(Glib);$(Python2Path)\include;..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>python.def</ModuleDefinitionFile>

       <AdditionalDependencies>"$(Python2Lib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(OutDir);$(Python2Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

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

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(Glib);$(Python2Path)\include;..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(Glib);$(Python2Path)\include;..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>python.def</ModuleDefinitionFile>

       <AdditionalDependencies>"$(Python2Lib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(OutDir);$(Python2Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

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

     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

@@ -102,6 +56,4 @@
     <ClCompile Include="python.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/python/python3.vcxproj b/plugins/python/python3.vcxproj
index 5f970975..511421e6 100644
--- a/plugins/python/python3.vcxproj
+++ b/plugins/python/python3.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,80 +20,33 @@
     <RootNamespace>python3</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>$(Python3Output)</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>$(Python3Output)</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

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

-      <AdditionalIncludeDirectories>$(Glib);$(Python3Path)\include;..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(Glib);$(Python3Path)\include;..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>python.def</ModuleDefinitionFile>

       <AdditionalDependencies>"$(Python3Lib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(OutDir);$(Python3Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

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

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(Glib);$(Python3Path)\include;..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(Glib);$(Python3Path)\include;..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>python.def</ModuleDefinitionFile>

       <AdditionalDependencies>"$(Python3Lib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(OutDir);$(Python3Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

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

     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

@@ -102,6 +56,4 @@
     <ClCompile Include="python.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/sysinfo/Makefile.am b/plugins/sysinfo/Makefile.am
index 0b8d7fad..bd44a19d 100644
--- a/plugins/sysinfo/Makefile.am
+++ b/plugins/sysinfo/Makefile.am
@@ -1,7 +1,17 @@
 libdir = $(hexchatlibdir)
 
+sources = sysinfo.c format.c shared/df.c
+
+if PLATFORM_OSX
+sources += osx/backend.m
+else
+sources += unix/backend.c unix/match.c unix/parse.c unix/pci.c
+endif
+
+EXTRA_DIST = osx unix win32 shared format.h sysinfo.h sysinfo-backend.h
+
 lib_LTLIBRARIES = sysinfo.la
-sysinfo_la_SOURCES = hwmon.c match.c parse.c pci.c xsys.c
-sysinfo_la_LDFLAGS = -avoid-version -module
-sysinfo_la_LIBADD = -lpci
-AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+sysinfo_la_SOURCES = $(sources)
+sysinfo_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+sysinfo_la_LIBADD = $(LIBPCI_LIBS) $(GLIB_LIBS)
+AM_CPPFLAGS = $(LIBPCI_CFLAGS) $(GLIB_CFLAGS) -I$(top_srcdir)/src/common -I$(srcdir)/shared
diff --git a/plugins/sysinfo/format.c b/plugins/sysinfo/format.c
new file mode 100644
index 00000000..741c43e2
--- /dev/null
+++ b/plugins/sysinfo/format.c
@@ -0,0 +1,90 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <glib.h>
+
+char *
+sysinfo_format_uptime (gint64 uptime)
+{
+	char buffer[128];
+
+	gint64 weeks = uptime / 604800;
+	int days     = (uptime / 86400) % 7;
+	int hours    = (uptime / 3600) % 24;
+	int minutes  = (uptime / 60) % 60;
+	int seconds  = uptime % 60;
+
+	if (weeks != 0)
+	{
+		g_snprintf (buffer, sizeof(buffer), "%" G_GINT64_FORMAT "w %dd %dh %dm %ds", weeks, days, hours, minutes, seconds);
+	}
+	else if (days != 0)
+	{
+		g_snprintf (buffer, sizeof(buffer), "%dd %dh %dm %ds", days, hours, minutes, seconds);
+	}
+	else if (hours != 0)
+	{
+		g_snprintf (buffer, sizeof(buffer), "%dh %dm %ds", hours, minutes, seconds);
+	}
+	else if (minutes != 0)
+	{
+		g_snprintf (buffer, sizeof(buffer), "%dm %ds", minutes, seconds);
+	}
+	else
+	{
+		g_snprintf (buffer, sizeof(buffer), "%ds", seconds);
+	}
+
+	return g_strdup (buffer);
+}
+
+char *
+sysinfo_format_memory (guint64 totalmem, guint64 freemem)
+{
+	char *total_fmt, *free_fmt, *ret;
+
+	total_fmt = g_format_size_full (totalmem, G_FORMAT_SIZE_IEC_UNITS);
+	free_fmt = g_format_size_full (freemem, G_FORMAT_SIZE_IEC_UNITS);
+	ret = g_strdup_printf ("%s Total (%s Free)", total_fmt, free_fmt);
+
+	g_free (total_fmt);
+	g_free (free_fmt);
+	return ret;
+}
+
+char *
+sysinfo_format_disk (guint64 total, guint64 free)
+{
+	char *total_fmt, *free_fmt, *used_fmt, *ret;
+	GFormatSizeFlags format_flags = G_FORMAT_SIZE_DEFAULT;
+
+#ifdef WIN32 /* Windows uses IEC size (with SI format) */
+	format_flags = G_FORMAT_SIZE_IEC_UNITS;
+#endif
+
+	total_fmt = g_format_size_full (total, format_flags);
+	free_fmt = g_format_size_full (free, format_flags);
+	used_fmt = g_format_size_full (total - free, format_flags);
+	ret = g_strdup_printf ("%s / %s (%s Free)", used_fmt, total_fmt, free_fmt);
+
+	g_free (total_fmt);
+	g_free (free_fmt);
+	g_free (used_fmt);
+	return ret;
+}
diff --git a/plugins/sysinfo/xsys.h b/plugins/sysinfo/format.h
index 4daf8545..5fe209be 100644
--- a/plugins/sysinfo/xsys.h
+++ b/plugins/sysinfo/format.h
@@ -1,7 +1,6 @@
 /*
- * xsys.h - X-Sys general parameters header
- * Copyright (C) 2005 Gustavo Zacarias
- * Copyright (C) 2006, 2007 Tony Vroon
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
  *
  * 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
@@ -19,14 +18,11 @@
  */
 
 
-#ifndef _XSYS_H_
-#define _XSYS_H_
+#ifndef FORMAT_H
+#define FORMAT_H
 
-#define bsize 1024
-#define delims ":="
-
-int sysinfo_get_percent ();
-void sysinfo_get_pciids (char *dest);
-void sysinfo_print_error (const char* msg);
+char *sysinfo_format_uptime(gint64 uptime);
+char *sysinfo_format_memory(guint64 totalmem, guint64 freemem);
+char *sysinfo_format_disk(guint64 total, guint64 free);
 
 #endif
diff --git a/plugins/sysinfo/hwmon.c b/plugins/sysinfo/hwmon.c
deleted file mode 100644
index 389244ac..00000000
--- a/plugins/sysinfo/hwmon.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * hwmon.c - Hardware monitoring functions for X-Sys
- * Copyright (C) 2005 Tony Vroon
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include "xsys.h"
-
-int hwmon_chip_present()
-{
-	FILE *fp = fopen("/sys/class/hwmon/hwmon0/device/name", "r");
-	if(fp != NULL) {
-		fclose(fp);
-		return 1;
-	}
-	return 0;
-}
-
-#if 0
-void get_hwmon_chip_name(char *name)
-{
-	char *position, buffer[bsize];
-	FILE *fp = fopen("/sys/class/hwmon/hwmon0/device/name", "r");
-	if(fp != NULL) {
-		if(fgets(buffer, bsize, fp) != NULL) {
-			position = strstr(buffer, "\n");
-                        *(position) = '\0';
-			snprintf(name, sizeof(name), "%s", buffer);
-		}
-		fclose(fp);
-	}
-}
-#endif
-
-void get_hwmon_temp(unsigned int *value, unsigned int *sensor)
-{
-	char buffer[bsize];
-	snprintf(buffer, bsize, "/sys/class/hwmon/hwmon0/device/temp%i_input", *sensor);
-	FILE *fp = fopen(buffer, "r");
-	if(fp != NULL) {
-		if(fgets(buffer, bsize, fp) != NULL)
-			*value = atoi(buffer);
-		fclose(fp);
-	}
-}
diff --git a/plugins/sysinfo/match.c b/plugins/sysinfo/match.c
deleted file mode 100644
index adfbff1b..00000000
--- a/plugins/sysinfo/match.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * match.c - matching functions for X-Sys
- * Copyright (C) 2005, 2006, 2007 Tony Vroon
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include "xsys.h"
-
-float percentage(unsigned long long *free, unsigned long long *total)
-{
-        unsigned long long result = (*free) * (unsigned long long)1000 / (*total);
-        return result / 10.0;
-}
-
-char *pretty_freespace(const char *desc, unsigned long long *free_k, unsigned long long *total_k)
-{
-        char *result, **quantity;
-	double free_space, total_space;
-	free_space = *free_k;
-	total_space = *total_k;
-        result = malloc(bsize * sizeof(char));
-	char *quantities[] = { "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", 0 };
-	if (total_space == 0)
-	{
-		snprintf(result, bsize, "%s: none", desc);
-		return result;
-	}
-        quantity = quantities;
-	while (total_space > 1023 && *(quantity + 1))
-	{
-		quantity++;
-		free_space = free_space / 1024;
-		total_space = total_space / 1024;
-	}
-	if (sysinfo_get_percent () != 0)
-		snprintf(result, bsize, "%s: %.1f%s, %.1f%% free",
-		desc, total_space, *quantity,
-		percentage(free_k, total_k));
-	else
-		snprintf(result, bsize, "%s: %.1f%s/%.1f%s free",
-		desc, free_space, *quantity, total_space, *quantity);
-        return result;
-}
-
-
-void remove_leading_whitespace(char *buffer)
-{
-	char *buffer2 = NULL;
-	int i = 0, j = 0, ews = 0;
-
-	buffer2 = (char*)malloc(strlen(buffer) * sizeof(char));
-	if (buffer2 == NULL)
-		return;
-
-	memset (buffer2, (char)0, strlen(buffer));
-	while (i < strlen(buffer))
-	{
-		/* count tabs, spaces as whitespace. */
-		if (!(buffer[i] == (char)32 || buffer[i] == (char)9) || ews == 1)
-		{
-			ews = 1;
-			buffer2[j] = buffer[i];
-			j++;
-		}
-		i++;
-	}
-	memset (buffer, (char)0, strlen(buffer));
-	strcpy (buffer, buffer2);
-	free (buffer2);
-}
-
-char *decruft_filename(char *buffer)
-{
-	char *match, *match_end;
-
-	while ((match = strstr(buffer, "%20")))
-	{
-		match_end = match + 3;
-		*match++ = ' ';
-		while (*match_end)
-			*match++ = *match_end++;
-		*match = 0;
-	}
-	return buffer;
-}
-
-void find_match_char(char *buffer, char *match, char *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-				position += 1;
-				strcpy(result, position);
-				position = strstr(result, "\n");
-				*(position) = '\0';
-				remove_leading_whitespace(result);
-				}
-			else
-				strcpy(result, "\0");
-		}
-}
-
-void find_match_double(char *buffer, char *match, double *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-                        	position += 1;
-                        	*result = strtod(position, NULL);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void find_match_double_hex(char *buffer, char *match, double *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-				memcpy(position,"0x",2);
-				*result = strtod(position,NULL);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void find_match_int(char *buffer, char *match, unsigned int *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-                        	position += 1;
-                        	*result = atoi(position);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void find_match_ll(char *buffer, char *match, unsigned long long *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-		               	position += 1;
-		               	*result = strtoll(position, NULL, 10);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void format_output(const char *arg, char *string, char *format)
-{
-        char *pos1, *pos2, buffer[bsize];
-        pos1 = &format[0];
-        strncpy(buffer, string, bsize);
-        string[0] = '\0';
-
-        while((pos2 = strstr(pos1, "%")) != NULL)
-        {
-                strncat(string, pos1, (size_t)(pos2-pos1));
-                if(*(pos2+1) == '1')
-                        strcat(string, arg);
-                else if(*(pos2+1) == '2')
-                        strcat(string, buffer);
-                else if(*(pos2+1) == 'C' || *(pos2+1) == 'c')
-                        strcat(string, "\003");
-                else if(*(pos2+1) == 'B' || *(pos2+1) == 'b')
-                        strcat(string, "\002");
-                else if(*(pos2+1) == 'R' || *(pos2+1) == 'r')
-                        strcat(string, "\026");
-                else if(*(pos2+1) == 'O' || *(pos2+1) == 'o')
-                        strcat(string, "\017");
-                else if(*(pos2+1) == 'U' || *(pos2+1) == 'u')
-                        strcat(string, "\037");
-                else if(*(pos2+1) == '%')
-                        strcat(string, "%");
-                pos1=pos2+2;
-        }
-
-        strcat(string, pos1);
-}
-
-void flat_format_output(const char *arg, char *string, char *format)
-{
-        char *pos1, *pos2, buffer[bsize];
-        pos1 = &format[0];
-        strncpy(buffer, string, bsize);
-        string[0] = '\0';
-
-        while((pos2 = strstr(pos1, "%")) != NULL)
-        {
-                strncat(string, pos1, (size_t)(pos2-pos1));
-                if(*(pos2+1) == '1')
-                        strcat(string, arg);
-                else if(*(pos2+1) == '2')
-                        strcat(string, buffer);
-                else if(*(pos2+1) == '%')
-                        strcat(string, "%");
-                pos1=pos2+2;
-        }
-
-        strcat(string, pos1);
-}
diff --git a/plugins/sysinfo/osx/backend.m b/plugins/sysinfo/osx/backend.m
new file mode 100644
index 00000000..450a557a
--- /dev/null
+++ b/plugins/sysinfo/osx/backend.m
@@ -0,0 +1,263 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+ /*
+	* Some snippets based upon Textual's System Profiler plugin.
+	* https://github.com/Codeux-Software/Textual
+	*/
+
+#import <Cocoa/Cocoa.h>
+
+#include <sys/sysctl.h>
+#include <mach/mach.h>
+#include <mach/mach_host.h>
+#include <mach/host_info.h>
+#include <mach/mach_vm.h>
+
+#include <glib.h>
+
+#include "format.h"
+#include "df.h"
+
+static char *
+get_os (void)
+{
+	NSDictionary *systemversion = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
+	NSString *build = [systemversion objectForKey:@"ProductBuildVersion"];
+	if (!build)
+		return NULL;
+	NSString *version = [systemversion objectForKey:@"ProductUserVisibleVersion"];
+	if (!version)
+	{
+		[build release];
+		return NULL;
+	}
+
+	NSDictionary *profiler = [NSDictionary dictionaryWithContentsOfFile:[@"~/Library/Preferences/com.apple.SystemProfiler.plist" stringByExpandingTildeInPath]];
+	NSDictionary *names = [profiler objectForKey:@"OS Names"];
+	NSString *os_name = nil;
+
+	for (NSString *name in names)
+	{
+		if ([name hasPrefix:build])
+		{
+			os_name = [names objectForKey:name];
+			break;
+		}
+	}
+	[build release];
+
+	if (!os_name)
+	{
+		[version release];
+		return NULL;
+	}
+
+	char *ret = g_strdup_printf ("%s %s", [os_name UTF8String], [version UTF8String]);
+	[version release];
+
+	return ret;
+}
+
+static char *
+get_os_fallback (void)
+{
+	NSProcessInfo *info = [NSProcessInfo processInfo];
+	NSOperatingSystemVersion version = [info operatingSystemVersion];
+
+	return g_strdup_printf ("OS X %ld.%ld.%ld", version.majorVersion, version.minorVersion, version.patchVersion);
+}
+char *
+sysinfo_backend_get_os(void)
+{
+	static char *os_str = NULL;
+	if (!os_str)
+	{
+		os_str = get_os();
+		if (!os_str)
+			os_str = get_os_fallback();
+	}
+	return g_strdup (os_str);
+}
+
+char *
+sysinfo_backend_get_disk(void)
+{
+	gint64 total, free_space;
+
+	if (xs_parse_df (&total, &free_space))
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_disk (total, free_space);
+}
+
+static guint64
+get_free_memory (void)
+{
+	mach_msg_type_number_t infoCount = (sizeof(vm_statistics_data_t) / sizeof(natural_t));
+
+	vm_size_t pagesize;
+	vm_statistics_data_t vm_stat;
+
+	host_page_size(mach_host_self(), &pagesize);
+
+	if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stat, &infoCount) == KERN_SUCCESS)
+		return ((vm_stat.inactive_count + vm_stat.free_count) * pagesize);
+
+	return 0;
+}
+
+char *
+sysinfo_backend_get_memory(void)
+{
+	NSProcessInfo *info = [NSProcessInfo processInfo];
+	guint64 totalmem, freemem;
+
+	totalmem = [info physicalMemory];
+
+	if ((freemem = get_free_memory()) == 0)
+		return NULL;
+
+	return sysinfo_format_memory (totalmem, freemem);
+}
+
+char *
+sysinfo_backend_get_cpu(void)
+{
+	guint64 cpu_clock_uint = 0;
+	double cpu_clock;
+	char cpu_string[256];
+	gsize len;
+	gboolean giga = FALSE;
+
+	len = sizeof(cpu_string);
+	if (sysctlbyname ("machdep.cpu.brand_string", cpu_string, &len, NULL, 0) != 0)
+		return NULL;
+	cpu_string[sizeof(cpu_string) - 1] = '\0';
+
+	len = sizeof(cpu_clock_uint);
+	if (sysctlbyname("hw.cpufrequency", &cpu_clock_uint, &len, NULL, 0) < 0)
+		return NULL;
+
+	cpu_clock = cpu_clock_uint / 1000000;
+	if (cpu_clock > 1000)
+	{
+		cpu_clock /= 1000;
+		giga = TRUE;
+	}
+
+	if (giga)
+		return g_strdup_printf ("%s (%.2fGHz)", cpu_string, cpu_clock);
+	else
+		return g_strdup_printf ("%s (%.0fMHz)", cpu_string, cpu_clock);
+}
+
+static char *
+get_gpu(void)
+{
+	CFMutableDictionaryRef pciDevices = IOServiceMatching("IOPCIDevice");
+	io_iterator_t entry_iterator, serviceObject;
+
+	if (IOServiceGetMatchingServices(kIOMasterPortDefault, pciDevices, &entry_iterator) != kIOReturnSuccess)
+		return NULL;
+
+	GString *gpu_list = g_string_new(NULL);
+	while ((serviceObject = IOIteratorNext(entry_iterator)))
+	{
+		CFMutableDictionaryRef serviceDictionary;
+
+		kern_return_t status = IORegistryEntryCreateCFProperties(serviceObject, &serviceDictionary,
+														 kCFAllocatorDefault, kNilOptions);
+
+		if (status != kIOReturnSuccess)
+		{
+			IOObjectRelease(serviceObject);
+			continue;
+		}
+
+		const void *class = CFDictionaryGetValue(serviceDictionary, @"class-code");
+		if (!class || *(guint32*)CFDataGetBytePtr(class) != 0x30000) /* DISPLAY_VGA */
+		{
+			CFRelease(serviceDictionary);
+			continue;
+		}
+
+		const void *model = CFDictionaryGetValue(serviceDictionary, @"model");
+		if (model)
+		{
+			if (CFGetTypeID(model) == CFDataGetTypeID() && CFDataGetLength(model) > 1)
+			{
+				if (gpu_list->len != 0)
+						g_string_append (gpu_list, ", ");
+				g_string_append_len (gpu_list, (const char*)CFDataGetBytePtr(model), CFDataGetLength(model) - 1);
+			}
+		}
+
+		CFRelease(serviceDictionary);
+	}
+
+	if (gpu_list->len == 0)
+	{
+		g_string_free (gpu_list, TRUE);
+		return NULL;
+	}
+
+	/* The string may contain nul-chars we must replace */
+	int i;
+	for (i = 0; i < gpu_list->len; i++)
+	{
+		if (gpu_list->str[i] == '\0')
+			gpu_list->str[i] = ' ';
+	}
+
+	return g_string_free (gpu_list, FALSE);
+}
+
+char *
+sysinfo_backend_get_gpu(void)
+{
+	static char *gpu_str = NULL;
+	if (!gpu_str)
+		gpu_str = get_gpu();
+
+	return g_strdup (gpu_str);
+}
+
+char *
+sysinfo_backend_get_sound(void)
+{
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_uptime(void)
+{
+	NSProcessInfo *info = [NSProcessInfo processInfo];
+	double uptime = [info systemUptime];
+
+	return sysinfo_format_uptime ((gint64)uptime);
+}
+
+char *
+sysinfo_backend_get_network(void)
+{
+	return NULL;
+}
diff --git a/plugins/sysinfo/pci.c b/plugins/sysinfo/pci.c
deleted file mode 100644
index bc8fb11f..00000000
--- a/plugins/sysinfo/pci.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * pci.c - PCI functions for X-Sys
- * Copyright (C) 1997-1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz> [PCI routines from lspci]
- * Copyright (C) 2000 Tom Rini <trini@kernel.crashing.org> [XorgAutoConfig pci.c, based on lspci]
- * Copyright (C) 2005, 2006 Tony Vroon
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <pci/pci.h>
-#include "xsys.h"
-
-static struct pci_filter filter;       /* Device filter */
-static struct pci_access *pacc;
-int bus, dev, func; /* Location of the card */
-
-struct device {
-  	struct device *next;
-  	struct pci_dev *dev;
-  	unsigned int config_cnt;
-  	u8 config[256];
-};
-
-static struct device *first_dev;
-
-static struct device *scan_device(struct pci_dev *p)
-{
-  	int how_much = 64;
-  	struct device *d;
-
-  	if (!pci_filter_match(&filter, p))
-    		return NULL;
-  	d = malloc(sizeof(struct device));
-  	bzero(d, sizeof(*d));
-  	d->dev = p;
-  	if (!pci_read_block(p, 0, d->config, how_much))
-    		exit(1);
-  	if (how_much < 128 && (d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS) {
-      		/* For cardbus bridges, we need to fetch 64 bytes more to get the full standard header... */
-      		if (!pci_read_block(p, 64, d->config+64, 64))
-        		exit(1);
-      		how_much = 128;
-    	}
-  	d->config_cnt = how_much;
-  	pci_setup_cache(p, d->config, d->config_cnt);
-  	pci_fill_info(p, PCI_FILL_IDENT);
-  	return d;
-}
-
-static void scan_devices(void)
-{
-  	struct device *d;
-  	struct pci_dev *p;
-
-  	pci_scan_bus(pacc);
-  	for(p=pacc->devices; p; p=p->next)
-    	if ((d = scan_device(p))) {
-        	d->next = first_dev;
-        	first_dev = d;
-      	}
-}
-
-static u16 get_conf_word(struct device *d, unsigned int pos)
-{
-  	return d->config[pos] | (d->config[pos+1] << 8);
-}
-
-int pci_find_by_class(u16 *class, char *vendor, char *device)
-{
-	struct device *d;
-	struct pci_dev *p;
-	int nomatch = 1;
-
-	pacc = pci_alloc();
-	pci_filter_init(pacc, &filter);
-	pci_init(pacc);
-	scan_devices();
-
-	for(d=first_dev; d; d=d->next) {
-    		p = d->dev;
-    		/* Acquire vendor & device ID if the class matches */
-    		if(get_conf_word(d, PCI_CLASS_DEVICE) == *class) {
-      			nomatch = 0;
-			snprintf(vendor,7,"%04x",p->vendor_id);
-			snprintf(device,7,"%04x",p->device_id);
-      			break;
-    		}
-  	}
-
-  	pci_cleanup(pacc);
-  	return nomatch;
-}
-
-void pci_find_fullname(char *fullname, char *vendor, char *device)
-{
-	char buffer[bsize];
-	char vendorname[bsize/2] = "";
-	char devicename[bsize/2] = "";
-	char *position;
-	int cardfound = 0;
-
-	sysinfo_get_pciids (buffer);
-	FILE *fp = fopen (buffer, "r");
-
-	if(fp == NULL) {
-		snprintf(fullname, bsize, "%s:%s", vendor, device);
-		sysinfo_print_error ("pci.ids file not found! You might want to adjust your pciids setting with /SYSINFO SET pciids (you can query its current value with /SYSINFO LIST).\n");
-		return;
-	}
-
-	while(fgets(buffer, bsize, fp) != NULL)	{
-		if (!isspace(buffer[0]) && strstr(buffer, vendor) != NULL) {
-                       	position = strstr(buffer, vendor);
-                       	position += 6;
-                       	strncpy(vendorname, position, bsize/2);
-                       	position = strstr(vendorname, "\n");
-                       	*(position) = '\0';
-			break;
-                }
-	}
-	while(fgets(buffer, bsize, fp) != NULL) {
-		if(strstr(buffer, device) != NULL) {
-                        position = strstr(buffer, device);
-                        position += 6;
-                        strncpy(devicename, position, bsize/2);
-			position = strstr(devicename, " (");
-			if (position == NULL)
-                        	position = strstr(devicename, "\n");
-                        *(position) = '\0';
-			cardfound = 1;
-			break;
- 		}
-	}
-	if (cardfound == 1)
-		snprintf(fullname, bsize, "%s %s", vendorname, devicename);
-	else
-		snprintf(fullname, bsize, "%s:%s", vendor, device);	
-	fclose(fp);
-}
diff --git a/plugins/sysinfo/shared/df.c b/plugins/sysinfo/shared/df.c
new file mode 100644
index 00000000..ce0760a6
--- /dev/null
+++ b/plugins/sysinfo/shared/df.c
@@ -0,0 +1,53 @@
+/*
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include "sysinfo.h"
+
+int xs_parse_df(gint64 *out_total, gint64 *out_free)
+{
+	FILE *pipe;
+	char buffer[bsize];
+	
+	pipe = popen("df -k -l -P", "r");
+	if(pipe==NULL)
+		return 1;
+
+	*out_total = *out_free = 0;
+
+	while(fgets(buffer, bsize, pipe) != NULL)
+	{
+		long long int avail, total;
+
+		/* Filesystem 1024-blocks Used Available Capacity Mounted-on */
+		if (sscanf (buffer, "%*s %lld %*s %lld %*s %*s", &total, &avail) == 2)
+		{
+			*out_total += total;
+			*out_free += avail;
+		}
+	}
+
+	/* Convert to bytes */
+	*out_total *= 1000;
+	*out_free *= 1000;
+
+	pclose(pipe);
+	return 0;
+}
diff --git a/src/common/identd.h b/plugins/sysinfo/shared/df.h
index 3b29135f..5f7f3296 100644
--- a/src/common/identd.h
+++ b/plugins/sysinfo/shared/df.h
@@ -1,7 +1,4 @@
-/* HexChat
- * Copyright (C) 1998-2010 Peter Zelezny.
- * Copyright (C) 2009-2013 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
@@ -17,9 +14,10 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#ifndef HEXCHAT_IDENTD_H
-#define HEXCHAT_IDENTD_H
 
-void identd_start (char *username);
+#ifndef SYSINFO_SHARED_H
+#define SYSINFO_SHARED_H
+
+int xs_parse_df(gint64 *total_bytes, gint64 *free_bytes);
 
 #endif
diff --git a/plugins/sysinfo/sysinfo-backend.h b/plugins/sysinfo/sysinfo-backend.h
new file mode 100644
index 00000000..c69a0853
--- /dev/null
+++ b/plugins/sysinfo/sysinfo-backend.h
@@ -0,0 +1,33 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#ifndef SYSINFO_BACKEND_H
+#define SYSINFO_BACKEND_H
+
+char *sysinfo_backend_get_os(void);
+char *sysinfo_backend_get_disk(void);
+char *sysinfo_backend_get_memory(void);
+char *sysinfo_backend_get_cpu(void);
+char *sysinfo_backend_get_gpu(void);
+char *sysinfo_backend_get_sound(void);
+char *sysinfo_backend_get_uptime(void);
+char *sysinfo_backend_get_network(void);
+
+#endif
diff --git a/plugins/sysinfo/sysinfo.c b/plugins/sysinfo/sysinfo.c
new file mode 100644
index 00000000..10c9d796
--- /dev/null
+++ b/plugins/sysinfo/sysinfo.c
@@ -0,0 +1,277 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2012 Berke Viktor.
+ *
+ * xsys.c - main functions for X-Sys 2
+ * by mikeshoup
+ * Copyright (C) 2003, 2004, 2005 Michael Shoup
+ * Copyright (C) 2005, 2006, 2007 Tony Vroon
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include "hexchat-plugin.h"
+#include "sysinfo-backend.h"
+#include "sysinfo.h"
+
+#define _(x) hexchat_gettext(ph,x)
+#define DEFAULT_ANNOUNCE TRUE
+
+static hexchat_plugin *ph;
+
+static char name[] = "Sysinfo";
+static char desc[] = "Display info about your hardware and OS";
+static char version[] = "1.0";
+static char sysinfo_help[] = "SysInfo Usage:\n  /SYSINFO [-e|-o] [CLIENT|OS|CPU|RAM|DISK|VGA|SOUND|ETHERNET|UPTIME], print various details about your system or print a summary without arguments\n  /SYSINFO SET <variable>\n";
+
+typedef struct
+{
+	const char *name; /* Lower case name used for prefs */
+	const char *title; /* Used for the end formatting */
+	char *(*callback) (void);
+	gboolean def; /* Hide by default? */
+} hwinfo;
+
+static char *
+get_client (void)
+{
+	return g_strdup_printf ("HexChat %s", hexchat_get_info(ph, "version"));
+}
+
+static hwinfo hwinfos[] = {
+	{"client", "Client", get_client},
+	{"os", "OS", sysinfo_backend_get_os},
+	{"cpu", "CPU", sysinfo_backend_get_cpu},
+	{"memory", "Memory", sysinfo_backend_get_memory},
+	{"storage", "Storage", sysinfo_backend_get_disk},
+	{"vga", "VGA", sysinfo_backend_get_gpu},
+	{"sound", "Sound", sysinfo_backend_get_sound, TRUE},
+	{"ethernet", "Ethernet", sysinfo_backend_get_network, TRUE},
+	{"uptime", "Uptime", sysinfo_backend_get_uptime},
+	{NULL, NULL},
+};
+
+static gboolean sysinfo_get_bool_pref (const char *pref, gboolean def);
+
+static gboolean
+should_show_info (hwinfo info)
+{
+	char hide_pref[32];
+
+	g_snprintf (hide_pref, sizeof(hide_pref), "hide_%s", info.name);
+	return !sysinfo_get_bool_pref (hide_pref, info.def);
+}
+
+static void
+print_summary (gboolean announce)
+{
+	char **strings = g_new0 (char*, G_N_ELEMENTS(hwinfos));
+	int i, x;
+	char *output;
+
+	for (i = 0, x = 0; hwinfos[i].name != NULL; i++)
+	{
+		if (should_show_info (hwinfos[i]))
+		{
+			char *str = hwinfos[i].callback();
+			if (str)
+			{
+				strings[x++] = g_strdup_printf ("\002%s\002: %s", hwinfos[i].title, str);
+				g_free (str);
+			}
+		}
+	}
+
+	output = g_strjoinv (" \002\342\200\242\002 ", strings);
+	hexchat_commandf (ph, "%s %s", announce ? "SAY" : "ECHO", output);
+
+	g_strfreev (strings);
+	g_free (output);
+}
+
+static void
+print_info (char *info, gboolean announce)
+{
+	int i;
+
+	for (i = 0; hwinfos[i].name != NULL; i++)
+	{
+		if (!g_ascii_strcasecmp (info, hwinfos[i].name))
+		{
+			char *str = hwinfos[i].callback();
+			if (str)
+			{
+				hexchat_commandf (ph, "%s \002%s\002: %s", announce ? "SAY" : "ECHO",
+									hwinfos[i].title, str);
+				g_free (str);
+			}
+			else
+				hexchat_print (ph, _("Sysinfo: Failed to get info. Either not supported or error."));
+			return;
+		}
+	}
+
+	hexchat_print (ph, _("Sysinfo: No info by that name\n"));
+}
+
+/*
+ * Simple wrapper for backend specific options.
+ * Ensure dest >= 512.
+ */
+int
+sysinfo_get_str_pref (const char *pref, char *dest)
+{
+	return hexchat_pluginpref_get_str (ph, pref, dest);
+}
+
+static gboolean
+sysinfo_get_bool_pref (const char *pref, gboolean def)
+{
+	int value = hexchat_pluginpref_get_int (ph, pref);
+
+	if (value != -1)
+		return value;
+
+	return def;
+}
+
+static void
+sysinfo_set_pref_real (const char *pref, char *value, gboolean def)
+{
+	if (value && value[0])
+	{
+		guint64 i = g_ascii_strtoull (value, NULL, 0);
+		hexchat_pluginpref_set_int (ph, pref, i != 0);
+		hexchat_printf (ph, _("Sysinfo: %s is set to: %d\n"), pref, i != 0);
+	}
+	else
+	{
+		hexchat_printf (ph, _("Sysinfo: %s is set to: %d\n"), pref,
+						sysinfo_get_bool_pref(pref, def));
+	}
+}
+
+static void
+sysinfo_set_pref (char *key, char *value)
+{
+	if (!key || !key[0])
+	{
+		hexchat_print (ph, _("Sysinfo: Valid settings are: announce and hide_* for each piece of information. e.g. hide_os. Without a value it will show current (or default) setting.\n"));
+		return;
+	}
+
+	if (!strcmp (key, "announce"))
+	{
+		sysinfo_set_pref_real (key, value, DEFAULT_ANNOUNCE);
+		return;
+	}
+#ifdef HAVE_LIBPCI
+	else if (!strcmp (key, "pciids"))
+	{
+		if (value && value[0])
+		{
+			hexchat_pluginpref_set_str (ph, "pciids", value);
+			hexchat_printf (ph, _("Sysinfo: pciids is set to: %s\n"), value);
+		}
+		else
+		{
+			char buf[512];
+			if (hexchat_pluginpref_get_str (ph, "pciids", buf) == 0)
+				strcpy (buf, DEFAULT_PCIIDS);
+			hexchat_printf (ph, _("Sysinfo: pciids is set to: %s\n"), buf);
+		}
+		return;
+	}
+#endif
+	else if (g_str_has_prefix (key, "hide_"))
+	{
+		int i;
+		for (i = 0; hwinfos[i].name != NULL; i++)
+		{
+			if (!strcmp (key + 5, hwinfos[i].name))
+			{
+				sysinfo_set_pref_real (key, value, hwinfos[i].def);
+				return;
+			}
+		}
+	}
+
+	hexchat_print (ph, _("Sysinfo: Invalid variable name\n"));
+}
+
+static int
+sysinfo_cb (char *word[], char *word_eol[], void *userdata)
+{
+	gboolean announce = sysinfo_get_bool_pref("announce", DEFAULT_ANNOUNCE);
+	int offset = 0, channel_type;
+	char *cmd;
+
+	/* Allow overriding global announce setting */
+	if (!strcmp ("-e", word[2]))
+	{
+		announce = FALSE;
+		offset++;
+	}
+	else if (!strcmp ("-o", word[2]))
+	{
+		announce = TRUE;
+		offset++;
+	}
+
+	/* Cannot send to server tab */
+	channel_type = hexchat_list_int (ph, NULL, "type");
+	if (channel_type != 2 /* SESS_CHANNEL */ && channel_type != 3 /* SESS_DIALOG */)
+		announce = FALSE;
+
+	cmd = word[2+offset];
+	if (!g_ascii_strcasecmp ("SET", cmd))
+		sysinfo_set_pref (word[3+offset], word_eol[4+offset]);
+	else if (!cmd || !cmd[0])
+		print_summary (announce);
+	else
+		print_info (cmd, announce);
+
+	return HEXCHAT_EAT_ALL;
+}
+
+int
+hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
+{
+	ph = plugin_handle;
+	*plugin_name = name;
+	*plugin_desc = desc;
+	*plugin_version = version;
+
+	hexchat_hook_command (ph, "SYSINFO", HEXCHAT_PRI_NORM, sysinfo_cb, sysinfo_help, NULL);
+
+	hexchat_command (ph, "MENU ADD \"Window/Send System Info\" \"SYSINFO\"");
+	hexchat_printf (ph, _("%s plugin loaded\n"), name);
+	return 1;
+}
+
+int
+hexchat_plugin_deinit (void)
+{
+	hexchat_command (ph, "MENU DEL \"Window/Display System Info\"");
+	hexchat_printf (ph, _("%s plugin unloaded\n"), name);
+	return 1;
+}
diff --git a/plugins/sysinfo/sysinfo.cpp b/plugins/sysinfo/sysinfo.cpp
deleted file mode 100644
index 43ab48c0..00000000
--- a/plugins/sysinfo/sysinfo.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-/* HexChat
- * Copyright (c) 2011-2012 Berke Viktor.
- *
- * 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 THE
- * AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-
-#include <stdio.h>
-#include <windows.h>
-#include <comutil.h>
-#include <wbemidl.h>
-
-#include "hexchat-plugin.h"
-
-static hexchat_plugin *ph;   /* plugin handle */
-static char name[] = "SysInfo";
-static char desc[] = "Display info about your hardware and OS";
-static char version[] = "1.1";
-static char helptext[] = "USAGE: /sysinfo - Sends info about your hardware and OS to current channel.";
-static int firstRun;
-static char *wmiOs;
-static char *wmiCpu;
-static char *wmiVga;
-
-static int
-getCpuArch (void)
-{
-	OSVERSIONINFOEX osvi;
-	SYSTEM_INFO si;
-
-	osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
-	GetVersionEx ((LPOSVERSIONINFOW) &osvi);
-
-	GetSystemInfo (&si);
-
-	if (si.wProcessorArchitecture == 9)
-	{
-		return 64;
-	}
-	else
-	{
-		return 86;
-	}
-}
-
-#if 0
-/* use WMI instead, wProcessorArchitecture displays current binary arch instead of OS arch anyway */
-static char *
-getOsName (void)
-{
-	static char winver[32];
-	double mhz;
-	OSVERSIONINFOEX osvi;
-	SYSTEM_INFO si;
-
-	osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
-	GetVersionEx ((LPOSVERSIONINFOW) &osvi);
-
-	GetSystemInfo (&si);
-
-	strcpy (winver, "Windows ");
-
-	switch (osvi.dwMajorVersion)
-	{
-		case 5:
-			switch (osvi.dwMinorVersion)
-			{
-				case 1:
-					strcat (winver, "XP");
-					break;
-				case 2:
-					if (osvi.wProductType == VER_NT_WORKSTATION)
-					{
-						strcat (winver, "XP x64 Edition");
-					}
-					else
-					{
-						if (GetSystemMetrics(SM_SERVERR2) == 0)
-						{
-							strcat (winver, "Server 2003");
-						}
-						else
-						{
-							strcat (winver, "Server 2003 R2");
-						}
-					}
-					break;
-			}
-			break;
-		case 6:
-			switch (osvi.dwMinorVersion)
-			{
-				case 0:
-					if (osvi.wProductType == VER_NT_WORKSTATION)
-					{
-						strcat (winver, "Vista");
-					}
-					else
-					{
-						strcat (winver, "Server 2008");
-					}
-					break;
-				case 1:
-					if (osvi.wProductType == VER_NT_WORKSTATION)
-					{
-						strcat (winver, "7");
-					}
-					else
-					{
-						strcat (winver, "Server 2008 R2");
-					}
-					break;
-				case 2:
-					if (osvi.wProductType == VER_NT_WORKSTATION)
-					{
-						strcat (winver, "8");
-					}
-					else
-					{
-						strcat (winver, "8 Server");
-					}
-					break;
-			}
-			break;
-	}
-
-	if (si.wProcessorArchitecture == 9)
-	{
-		strcat (winver, " (x64)");
-	}
-	else
-	{
-		strcat (winver, " (x86)");
-	}
-
-	return winver;
-}
-
-/* x86-only, SDK-only, use WMI instead */
-static char *
-getCpuName (void)
-{
-	// Get extended ids.
-	unsigned int nExIds;
-	unsigned int i;
-	int CPUInfo[4] = {-1};
-	static char CPUBrandString[128];
-
-	__cpuid (CPUInfo, 0x80000000);
-	nExIds = CPUInfo[0];
-
-	/* Get the information associated with each extended ID. */
-	for (i=0x80000000; i <= nExIds; ++i)
-	{
-		__cpuid (CPUInfo, i);
-
-		if (i == 0x80000002)
-		{
-			memcpy (CPUBrandString, CPUInfo, sizeof (CPUInfo));
-		}
-		else if (i == 0x80000003)
-		{
-			memcpy( CPUBrandString + 16, CPUInfo, sizeof (CPUInfo));
-		}
-		else if (i == 0x80000004)
-		{
-			memcpy (CPUBrandString + 32, CPUInfo, sizeof (CPUInfo));
-		}
-	}
-
-	return CPUBrandString;
-}
-#endif
-
-static char *
-getCpuMhz (void)
-{
-	HKEY hKey;
-	int result;
-	int data;
-	int dataSize;
-	double cpuspeed;
-	static char buffer[16];
-	const char *cpuspeedstr;
-
-	if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("Hardware\\Description\\System\\CentralProcessor\\0"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
-	{
-		dataSize = sizeof (data);
-		result = RegQueryValueEx (hKey, TEXT("~MHz"), 0, 0, (LPBYTE)&data, (LPDWORD)&dataSize);
-		RegCloseKey (hKey);
-		if (result == ERROR_SUCCESS)
-		{
-			cpuspeed = ( data > 1000 ) ? data / 1000 : data;
-			cpuspeedstr = ( data > 1000 ) ? "GHz" : "MHz";
-			sprintf (buffer, "%.2f %s", cpuspeed, cpuspeedstr);
-		}
-	}
-
-	return buffer;
-}
-
-static char *
-getMemoryInfo (void)
-{
-	static char buffer[32];
-	MEMORYSTATUSEX meminfo;
-
-	meminfo.dwLength = sizeof (meminfo);
-	GlobalMemoryStatusEx (&meminfo);
-
-	sprintf (buffer, "%I64d MB Total (%I64d MB Free)", meminfo.ullTotalPhys / 1024 / 1024, meminfo.ullAvailPhys / 1024 / 1024);
-
-	return buffer;
-}
-
-static char *
-getWmiInfo (int mode)
-{
-	/* for more details about this wonderful API, see 
-	http://msdn.microsoft.com/en-us/site/aa394138
-	http://msdn.microsoft.com/en-us/site/aa390423
-	http://msdn.microsoft.com/en-us/library/windows/desktop/aa394138%28v=vs.85%29.aspx
-	http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/d6420012-e432-4964-8506-6f6b65e5a451
-	*/
-
-	char *buffer = (char *) malloc (128);
-	HRESULT hres;
-	HRESULT hr;
-	IWbemLocator *pLoc = NULL;
-	IWbemServices *pSvc = NULL;
-	IEnumWbemClassObject *pEnumerator = NULL;
-	IWbemClassObject *pclsObj;
-	ULONG uReturn = 0;
-
-	hres =  CoInitializeEx (0, COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY);
-
-	if (FAILED (hres))
-	{
-		strcpy (buffer, "Error Code 0");
-		return buffer;
-	}
-
-	hres =  CoInitializeSecurity (NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
-
-	/* mysteriously failing after the first execution, but only when used as a plugin, skip it */
-	/*if (FAILED (hres))
-	{
-		CoUninitialize ();
-		strcpy (buffer, "Error Code 1");
-		return buffer;
-	}*/
-
-	hres = CoCreateInstance (CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc);
-
-	if (FAILED (hres))
-	{
-		CoUninitialize ();
-		strcpy (buffer, "Error Code 2");
-		return buffer;
-	}
-
-	hres = pLoc->ConnectServer (_bstr_t (L"root\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
-
-	if (FAILED (hres))
-	{
-		pLoc->Release ();
-		CoUninitialize ();
-		strcpy (buffer, "Error Code 3");
-		return buffer;
-	}
-
-	hres = CoSetProxyBlanket (pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
-
-	if (FAILED (hres))
-	{
-		pSvc->Release ();
-		pLoc->Release ();
-		CoUninitialize ();
-		strcpy (buffer, "Error Code 4");
-		return buffer;
-	}
-
-	switch (mode)
-	{
-		case 0:
-			hres = pSvc->ExecQuery (_bstr_t ("WQL"), _bstr_t ("SELECT * FROM Win32_OperatingSystem"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
-			break;
-		case 1:
-			hres = pSvc->ExecQuery (_bstr_t ("WQL"), _bstr_t ("SELECT * FROM Win32_Processor"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
-			break;
-		case 2:
-			hres = pSvc->ExecQuery (_bstr_t ("WQL"), _bstr_t ("SELECT * FROM Win32_VideoController"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
-			break;
-
-	}
-
-	if (FAILED (hres))
-	{
-		pSvc->Release ();
-		pLoc->Release ();
-		CoUninitialize ();
-		strcpy (buffer, "Error Code 5");
-		return buffer;
-	}
-
-	while (pEnumerator)
-	{
-		hr = pEnumerator->Next (WBEM_INFINITE, 1, &pclsObj, &uReturn);
-		if (0 == uReturn)
-		{
-			break;
-		}
-		VARIANT vtProp;
-		switch (mode)
-		{
-			case 0:
-				hr = pclsObj->Get (L"Caption", 0, &vtProp, 0, 0);
-				break;
-			case 1:
-				hr = pclsObj->Get (L"Name", 0, &vtProp, 0, 0);
-				break;
-			case 2:
-				hr = pclsObj->Get (L"Name", 0, &vtProp, 0, 0);
-				break;
-		}
-		WideCharToMultiByte (CP_ACP, 0, vtProp.bstrVal, -1, buffer, SysStringLen (vtProp.bstrVal)+1, NULL, NULL);
-		VariantClear (&vtProp);
-    }
-
-	pSvc->Release ();
-	pLoc->Release ();
-	pEnumerator->Release ();
-	pclsObj->Release ();
-	CoUninitialize ();
-	return buffer;
-}
-
-static int
-printInfo (char *word[], char *word_eol[], void *user_data)
-{
-	/* query WMI info only at the first time SysInfo is called, then cache it to save time */
-	if (firstRun)
-	{
-		hexchat_printf (ph, "%s first execution, querying and caching WMI info...\n", name);
-		wmiOs = getWmiInfo (0);
-		wmiCpu = getWmiInfo (1);
-		wmiVga = getWmiInfo (2);
-		firstRun = 0;
-	}
-	if (hexchat_list_int (ph, NULL, "type") >= 2)
-	{
-		/* uptime will work correctly for up to 50 days, should be enough */
-		hexchat_commandf (ph, "ME ** SysInfo ** Client: HexChat %s (x%d) ** OS: %s ** CPU: %s (%s) ** RAM: %s ** VGA: %s ** Uptime: %.2f Hours **",
-			hexchat_get_info (ph, "version"),
-			getCpuArch (),
-			wmiOs,
-			wmiCpu,
-			getCpuMhz (),
-			getMemoryInfo (),
-			wmiVga, (float) GetTickCount() / 1000 / 60 / 60);
-	}
-	else
-	{
-		hexchat_printf (ph, " * Client:  HexChat %s (x%d)\n", hexchat_get_info (ph, "version"), getCpuArch ());
-		hexchat_printf (ph, " * OS:      %s\n", wmiOs);
-		hexchat_printf (ph, " * CPU:     %s (%s)\n", wmiCpu, getCpuMhz ());
-		hexchat_printf (ph, " * RAM:     %s\n", getMemoryInfo ());
-		hexchat_printf (ph, " * VGA:     %s\n", wmiVga);
-		hexchat_printf (ph, " * Uptime:  %.2f Hours\n", (float) GetTickCount() / 1000 / 60 / 60);
-	}
-
-	return HEXCHAT_EAT_HEXCHAT;
-}
-
-int
-hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
-{
-	ph = plugin_handle;
-
-	*plugin_name = name;
-	*plugin_desc = desc;
-	*plugin_version = version;
-
-	firstRun = 1;
-
-	hexchat_hook_command (ph, "SYSINFO", HEXCHAT_PRI_NORM, printInfo, helptext, NULL);
-	hexchat_command (ph, "MENU -ishare\\system.png ADD \"Window/Send System Info\" \"SYSINFO\"");
-
-	hexchat_printf (ph, "%s plugin loaded\n", name);
-
-	return 1;       /* return 1 for success */
-}
-
-
-int
-hexchat_plugin_deinit (void)
-{
-	hexchat_command (ph, "MENU DEL \"Window/Display System Info\"");
-	hexchat_printf (ph, "%s plugin unloaded\n", name);
-	return 1;
-}
diff --git a/plugins/sysinfo/hwmon.h b/plugins/sysinfo/sysinfo.h
index fe71274b..cfde8408 100644
--- a/plugins/sysinfo/hwmon.h
+++ b/plugins/sysinfo/sysinfo.h
@@ -1,6 +1,6 @@
 /*
- * hwmon.h - Hardware monitoring header for X-Sys
- * Copyright (C) 2005 Tony Vroon
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
  *
  * 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
@@ -18,11 +18,12 @@
  */
 
 
-#ifndef _HWMON_H_
-#define _HWMON_H_
+#ifndef SYSINFO_H
+#define SYSINFO_H
 
-int hwmon_chip_present();
-void get_hwmon_chip_name(char *name);
-void get_hwmon_temp(unsigned int *value, unsigned int *sensor);
+#define bsize 1024
+#define DEFAULT_PCIIDS "/usr/share/hwdata/pci.ids"
+
+int sysinfo_get_str_pref (const char *name, char *dest);
 
 #endif
diff --git a/plugins/sysinfo/sysinfo.vcxproj b/plugins/sysinfo/sysinfo.vcxproj
index 7286b89a..3d429295 100644
--- a/plugins/sysinfo/sysinfo.vcxproj
+++ b/plugins/sysinfo/sysinfo.vcxproj
@@ -2,6 +2,8 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>Unicode</CharacterSet>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,91 +21,51 @@
     <RootNamespace>sysinfo</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>Unicode</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcsysinfo</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hcsysinfo</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SYSINFO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>..\..\src\common;$(DepsRoot)\include;$(Glib);$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

       <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <ModuleDefinitionFile>sysinfo.def</ModuleDefinitionFile>

-      <AdditionalDependencies>wbemuuid.lib;comsupp.lib;%(AdditionalDependencies)</AdditionalDependencies>

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

+      <AdditionalDependencies>wbemuuid.lib;comsupp.lib;$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <IgnoreSpecificDefaultLibraries>comsupp.lib</IgnoreSpecificDefaultLibraries>

+      <ModuleDefinitionFile>sysinfo.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;SYSINFO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>..\..\src\common;$(DepsRoot)\include;$(Glib);$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

       <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <ModuleDefinitionFile>sysinfo.def</ModuleDefinitionFile>

-      <AdditionalDependencies>wbemuuid.lib;comsupp.lib;%(AdditionalDependencies)</AdditionalDependencies>

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

+      <AdditionalDependencies>wbemuuid.lib;comsupp.lib;$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <IgnoreSpecificDefaultLibraries>comsupp.lib</IgnoreSpecificDefaultLibraries>

+      <ModuleDefinitionFile>sysinfo.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

     <None Include="sysinfo.def" />

   </ItemGroup>

   <ItemGroup>

-    <ClCompile Include="sysinfo.cpp" />

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

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

+    <ClCompile Include="win32\backend.c" />

+  </ItemGroup>

+  <ItemGroup>

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

+    <ClInclude Include="sysinfo-backend.h" />

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

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/sysinfo/sysinfo.vcxproj.filters b/plugins/sysinfo/sysinfo.vcxproj.filters
index 1ef90f5b..aa173bb5 100644
--- a/plugins/sysinfo/sysinfo.vcxproj.filters
+++ b/plugins/sysinfo/sysinfo.vcxproj.filters
@@ -9,6 +9,9 @@
       <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>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{c873eb6b-aca6-434d-8ec9-199838b80838}</UniqueIdentifier>

+    </Filter>

   </ItemGroup>

   <ItemGroup>

     <None Include="sysinfo.def">

@@ -16,8 +19,25 @@
     </None>

   </ItemGroup>

   <ItemGroup>

-    <ClCompile Include="sysinfo.cpp">

+    <ClCompile Include="sysinfo.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="win32\backend.c">

       <Filter>Source Files</Filter>

     </ClCompile>

+    <ClCompile Include="format.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="sysinfo.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="sysinfo-backend.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="format.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

   </ItemGroup>

 </Project>
\ No newline at end of file
diff --git a/plugins/sysinfo/unix/backend.c b/plugins/sysinfo/unix/backend.c
new file mode 100644
index 00000000..dc065518
--- /dev/null
+++ b/plugins/sysinfo/unix/backend.c
@@ -0,0 +1,170 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <glib.h>
+#include "parse.h"
+#include "match.h"
+#include "sysinfo.h"
+#include "format.h"
+#include "df.h"
+
+char *sysinfo_backend_get_os(void)
+{
+	char name[bsize];
+
+	if (xs_parse_distro (name) != 0)
+	{
+		return NULL;
+	}
+
+	return g_strdup(name);
+}
+
+char *sysinfo_backend_get_disk(void)
+{
+	gint64 total, free;
+
+	if (xs_parse_df (&total, &free))
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_disk (total, free);
+}
+
+char *sysinfo_backend_get_memory(void)
+{
+	unsigned long long mem_total;
+	unsigned long long mem_free;
+	unsigned long long swap_total;
+	unsigned long long swap_free;
+	char *swap_fmt = NULL, *mem_fmt, *ret;
+
+	if (xs_parse_meminfo (&mem_total, &mem_free, 0) == 1)
+	{
+		return NULL;
+	}
+	if (xs_parse_meminfo (&swap_total, &swap_free, 1) != 1)
+	{
+		swap_fmt = sysinfo_format_memory (swap_total, swap_free);
+	}
+
+	mem_fmt = sysinfo_format_memory (mem_total, mem_free);
+
+	if (swap_fmt)
+	{
+		ret = g_strdup_printf ("Physical: %s Swap: %s", mem_fmt, swap_fmt);
+		g_free (mem_fmt);
+		g_free (swap_fmt);
+	}
+	else
+		ret = mem_fmt;
+
+	return ret;
+}
+
+char *sysinfo_backend_get_cpu(void)
+{
+	char model[bsize];
+	char vendor[bsize];
+	char buffer[bsize];
+	double freq;
+	int giga = 0;
+
+	if (xs_parse_cpu (model, vendor, &freq) != 0)
+	{
+		return NULL;
+	}
+
+	if (freq > 1000)
+	{
+		freq /= 1000;
+		giga = 1;
+	}
+
+	if (giga)
+	{
+		g_snprintf (buffer, bsize, "%s (%.2fGHz)", model, freq);
+	}
+	else
+	{
+		g_snprintf (buffer, bsize, "%s (%.0fMHz)", model, freq);
+	}
+	
+	return g_strdup (buffer);
+}
+
+char *sysinfo_backend_get_gpu(void)
+{
+	char vid_card[bsize];
+	char agp_bridge[bsize];
+	char buffer[bsize];
+	int ret;
+
+	if ((ret = xs_parse_video (vid_card)) != 0)
+	{
+		return NULL;
+	}
+
+	if (xs_parse_agpbridge (agp_bridge) != 0)
+	{
+		g_snprintf (buffer, bsize, "%s", vid_card);
+	}
+	else
+	{
+		g_snprintf (buffer, bsize, "%s @ %s", vid_card, agp_bridge);
+	}
+
+	return g_strdup (buffer);
+}
+
+char *sysinfo_backend_get_sound(void)
+{
+	char sound[bsize];
+
+	if (xs_parse_sound (sound) != 0)
+	{
+		return NULL;
+	}
+	return g_strdup (sound);
+}
+
+char *sysinfo_backend_get_uptime(void)
+{
+	gint64 uptime;
+
+	if ((uptime = xs_parse_uptime ()) == 0)
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_uptime (uptime);
+}
+
+char *sysinfo_backend_get_network(void)
+{
+	char ethernet_card[bsize];
+
+	if (xs_parse_ether (ethernet_card))
+	{
+		g_strlcpy (ethernet_card, "None found", bsize);
+	}
+	
+	return g_strdup (ethernet_card);
+}
diff --git a/plugins/sysinfo/unix/match.c b/plugins/sysinfo/unix/match.c
new file mode 100644
index 00000000..2ef51f3f
--- /dev/null
+++ b/plugins/sysinfo/unix/match.c
@@ -0,0 +1,98 @@
+/*
+ * match.c - matching functions for X-Sys
+ * Copyright (C) 2005, 2006, 2007 Tony Vroon
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include "sysinfo.h"
+
+#define delims ":="
+
+void find_match_char(char *buffer, char *match, char *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+			position += 1;
+			strcpy(result, position);
+			position = strstr(result, "\n");
+			*(position) = '\0';
+			g_strchug(result);
+		}
+		else
+			strcpy(result, "\0");
+	}
+}
+
+void find_match_double(char *buffer, char *match, double *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+        	position += 1;
+        	*result = strtod(position, NULL);
+		}
+		else
+			*result = 0;
+	}
+}
+
+void find_match_double_hex(char *buffer, char *match, double *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+			memcpy(position,"0x",2);
+			*result = strtod(position,NULL);
+		}
+		else
+			*result = 0;
+	}
+}
+
+void find_match_ll(char *buffer, char *match, unsigned long long *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+			position += 1;
+			*result = strtoll(position, NULL, 10);
+		}
+		else
+			*result = 0;
+	}
+}
+
diff --git a/plugins/sysinfo/match.h b/plugins/sysinfo/unix/match.h
index 61811e4a..16999fa2 100644
--- a/plugins/sysinfo/match.h
+++ b/plugins/sysinfo/unix/match.h
@@ -23,13 +23,7 @@
 void find_match_char(char *buffer, char *match, char *result);
 void find_match_double(char *buffer, char *match, double *result);
 void find_match_double_hex(char *buffer, char *match, double *result);
-void find_match_int(char *buffer, char *match, unsigned int *result);
 void find_match_ll(char *buffer, char *match, unsigned long long *result);
-void format_output(const char *arg, char *string, char *format);
-void flat_format_output(const char *arg, char *string, char *format);
-float percentage(unsigned long long *free, unsigned long long *total);
-char *pretty_freespace(const char *desc, unsigned long long *free_k, unsigned long long *total_k);
 void remove_leading_whitespace(char *buffer);
-char *decruft_filename(char *buffer);
 
 #endif
diff --git a/plugins/sysinfo/parse.c b/plugins/sysinfo/unix/parse.c
index 4c15897a..f41f89a7 100644
--- a/plugins/sysinfo/parse.c
+++ b/plugins/sysinfo/unix/parse.c
@@ -23,19 +23,19 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-#include <time.h>
-#include <dirent.h>
-#include <sys/types.h>
 #include <pci/header.h>
+#include <glib.h>
+
+#ifdef __sparc__
+#include <dirent.h>
+#endif
 
 #include "pci.h"
 #include "match.h"
-#include "hwmon.h"
-#include "xsys.h"
+#include "parse.h"
+#include "sysinfo.h"
 
-int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned int *count)
+int xs_parse_cpu(char *model, char *vendor, double *freq)
 {
 #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__alpha__) || defined(__ia64__) || defined(__parisc__) || defined(__sparc__)
 	char buffer[bsize];
@@ -46,8 +46,6 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 	FILE *fp = fopen("/proc/cpuinfo", "r");
 	if(fp == NULL)
 		return 1;
-	if(count != NULL) *count = 0;
-	strcpy(cache,"unknown\0");
 	
 	#if defined(__i386__) || defined(__x86_64__)
 	while(fgets(buffer, bsize, fp) != NULL)
@@ -55,10 +53,7 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "model name", model);
 		find_match_char(buffer, "vendor_id", vendor);
 		find_match_double(buffer, "cpu MHz", freq);
-		find_match_char(buffer, "cache size", cache);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	#endif
 	#ifdef __powerpc__
 	while(fgets(buffer, bsize, fp) != NULL)
@@ -66,10 +61,7 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "cpu", model);
 		find_match_char(buffer, "machine", vendor);
 		find_match_double(buffer, "clock", freq);
-		find_match_char(buffer, "L2 cache", cache);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	pos = strstr(model, ",");
 	if (pos != NULL) *pos = '\0';
 	#endif
@@ -79,8 +71,6 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "cpu model", model);
 		find_match_char(buffer, "system type", vendor);
 		find_match_double(buffer, "cycle frequency [Hz]", freq);
-		find_match_char(buffer, "L2 cache", cache);
-		find_match_int(buffer, "cpus detected", count);
 	}
 	*freq = *freq / 1000000;
 	#endif
@@ -90,20 +80,15 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "model", model);
 		find_match_char(buffer, "vendor", vendor);
 		find_match_double(buffer, "cpu MHz", freq);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	#endif
 	#ifdef __parisc__
 	while(fgets(buffer, bsize, fp) != NULL)
 	{
 		find_match_char(buffer, "cpu  ", model);
 		find_match_char(buffer, "cpu family", vendor);
-		find_match_char(buffer, "D-cache", cache);
 		find_match_double(buffer, "cpu MHz", freq);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	#endif
 	#ifdef __sparc__
 	DIR *dir;
@@ -113,22 +98,8 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 	{
 		find_match_char(buffer, "cpu	", model);
 		find_match_char(buffer, "type	", vendor);
-		find_match_int(buffer, "ncpus active", count);
 		find_match_double_hex(buffer, "Cpu0ClkTck", freq);
 	}
-	/* Cache is tricky, only implemented for sparc64 */
-	if ((dir = opendir("/proc/openprom")) != NULL)
-		while ((entry = readdir(dir)) != NULL)
-			if (strncmp(entry->d_name,"SUNW,UltraSPARC",15) == 0)
-			{
-				snprintf(buffer,bsize,"/proc/openprom/%s/ecache-size",entry->d_name);
-				fp2 = fopen(buffer, "r");
-				if (fp2 == NULL) break;
-				fscanf(fp2,"%16s",cache);
-				fclose(fp2);
-				sprintf(buffer,"0x%s",cache);
-				sprintf(cache,"%0.0f KB",strtod(buffer,NULL)/1024);
-			}
 	*freq = *freq / 1000000;
 	#endif
 	fclose(fp);
@@ -136,43 +107,20 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 	return 0;
 }
 
-int xs_parse_uptime(int *weeks, int *days, int *hours, int *minutes, int *seconds)
+gint64 xs_parse_uptime(void)
 {
 	char buffer[bsize];
-	long long uptime = 0;
+	gint64 uptime = 0;
 	FILE *fp = fopen("/proc/uptime", "r");
 	if(fp == NULL)
-		return 1;
+		return 0;
 
 	if(fgets(buffer, bsize, fp) != NULL)
-		uptime = strtol(buffer, NULL, 0);
-	
-	*seconds = uptime%60;
-	*minutes = (uptime/60)%60;
-	*hours   = (uptime/3600)%24;
-	*days    = (uptime/86400)%7;
-	*weeks   = uptime/604800;
+		uptime = g_ascii_strtoll(buffer, NULL, 0);
 	
 	fclose(fp);
 	
-	return 0;
-}
-
-int xs_parse_os(char *user, char *host, char *kernel)
-{
-	struct utsname osinfo;
-	char hostn[bsize], *usern = getenv("USER");
-	
-	if(uname(&osinfo)<0)
-		return 1;	
-	if(gethostname(hostn, bsize)<0)
-		return 1;
-	
-	strncpy(user, usern, bsize);
-	strcpy(host, hostn);
-	snprintf(kernel, bsize, "%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine);
-	
-	return 0;
+	return uptime;
 }
 
 int xs_parse_sound(char *snd_card)
@@ -181,12 +129,13 @@ int xs_parse_sound(char *snd_card)
 	u16 class = PCI_CLASS_MULTIMEDIA_AUDIO;
 
 	FILE *fp = NULL;
-	if((fp = fopen("/proc/asound/cards", "r"))== NULL) {
+	if((fp = fopen("/proc/asound/cards", "r"))== NULL)
+	{
 		if (pci_find_by_class(&class, vendor, device) == 0) 
-			{
-				pci_find_fullname(snd_card, vendor, device);
-				return 0;
-			}
+		{
+			pci_find_fullname(snd_card, vendor, device);
+			return 0;
+		}
 		else
 			return 1;
 	}
@@ -197,13 +146,13 @@ int xs_parse_sound(char *snd_card)
 		if(isdigit(buffer[0]) || isdigit(buffer[1]))
 		{
 			char card_buf[bsize];
-			long card_id = 0;
+			gint64 card_id = 0;
 			pos = strstr(buffer, ":");
-			card_id = strtoll(buffer, NULL, 0);
+			card_id = g_ascii_strtoll(buffer, NULL, 0);
 			if (card_id == 0)
-				snprintf(card_buf, bsize, "%s", pos+2);
+				g_snprintf(card_buf, bsize, "%s", pos+2);
 			else
-				snprintf(card_buf, bsize, "%ld: %s", card_id, pos+2);
+				g_snprintf(card_buf, bsize, "%"G_GINT64_FORMAT": %s", card_id, pos+2);
 			pos = strstr(card_buf, "\n");
 			*pos = '\0';
 			strcat(cards, card_buf);
@@ -249,129 +198,42 @@ int xs_parse_agpbridge(char *agp_bridge)
 	return 0;
 }
 
-int xs_parse_netdev(const char *device, unsigned long long *bytes_recv, unsigned long long *bytes_sent)
-{
-	FILE *fp;
-	char buffer[bsize], *pos;
-	int i;
-	
-	fp=fopen("/proc/net/dev", "r");
-	if(fp==NULL)
-		return 1;
-	
-	while(fgets(buffer, bsize, fp) != NULL)
-	{
-		for(i=0; isspace(buffer[i]); i++);
-		if(strncmp(device, &buffer[i], strlen(device)) == 0) break;
-	}
-	fclose(fp);
-	pos = strstr(buffer, ":");
-	pos++;
-	*bytes_recv = strtoull(pos, &pos, 0);
-
-	for(i=0;i<7;i++) strtoull(pos, &pos, 0);
-	
-	*bytes_sent = strtoull(pos, NULL, 0);
-
-	return 0;
-}
-
-int xs_parse_df(const char *mount_point, char *result)
-{
-	FILE *pipe;
-	char buffer[bsize], *pos;
-	unsigned long long total_k=0, free_k=0;
-	int i=0;
-	
-	pipe = popen("df -k -l -P", "r");
-	if(pipe==NULL)
-		return 1;
-	
-	while(fgets(buffer, bsize, pipe) != NULL)
-	{
-		/* Skip over pseudo-filesystems and description line */
-		if(isalpha(buffer[0]))
-			continue;
-		
-		for(pos=buffer; !isspace(*pos); pos++);
-		for(;isspace(*pos);pos++);
-		if(mount_point == NULL)
-		{
-			total_k += strtoull(pos, &pos, 0);
-			strtoull(pos, &pos, 0);
-			free_k += strtoull(pos, &pos, 0);
-			continue;
-		}
-		total_k = strtoull(pos, &pos, 0);
-		strtoull(pos, &pos, 0);
-		free_k = strtoull(pos, &pos, 0);
-		strtoull(pos, &pos, 0);
-		for(;isspace(*pos);pos++);
-		for(;*pos!='/';pos++);
-		for(i=0;*(buffer+i)!='\n';i++);
-		*(buffer+i)='\0';
-		
-		if(strncasecmp(mount_point, "ALL", 3)==0)
-		{
-			char *tmp_buf = pretty_freespace(pos, &free_k, &total_k);
-			strcat(tmp_buf, " | ");
-			strcat(result, tmp_buf);
-			free(tmp_buf);
-		}
-		else if(strncmp(mount_point, pos, strlen(mount_point)) == 0)
-		{
-			char *tmp_buf = pretty_freespace(mount_point, &free_k, &total_k);
-			strncpy(result, tmp_buf, bsize);
-			free(tmp_buf);
-			break;
-		}
-		else snprintf(result, bsize, "Mount point %s not found!", mount_point);
-	}
-	
-	if(mount_point != NULL && strncasecmp(mount_point, "ALL", 3)==0)
-		*(result+strlen(result)-3) = '\0';
-	
-	if(mount_point == NULL)
-	{
-		char *tmp_buf = pretty_freespace("Total", &free_k, &total_k);
-		strncpy(result, tmp_buf, bsize);
-		free(tmp_buf);
-	}
-	pclose(pipe);
-	return 0;
-}
-
 int xs_parse_meminfo(unsigned long long *mem_tot, unsigned long long *mem_free, int swap)
 {
 	FILE *fp;
-        char buffer[bsize];
+	char buffer[bsize];
 	unsigned long long freemem = 0, buffers = 0, cache = 0;
-        *mem_tot = 0;
-        *mem_free = 0;
+	*mem_tot = 0;
+	*mem_free = 0;
 
-        if((fp = fopen("/proc/meminfo", "r")) == NULL)
-                return 1;
+	if((fp = fopen("/proc/meminfo", "r")) == NULL)
+		return 1;
 
-        while(fgets(buffer, bsize, fp) != NULL)
-        {
-                if(!swap)
-                {
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		if(!swap)
+		{
 			find_match_ll(buffer, "MemTotal:", mem_tot);
 			find_match_ll(buffer, "MemFree:", &freemem);
 			find_match_ll(buffer, "Buffers:", &buffers);
 			find_match_ll(buffer, "Cached:", &cache);
-                }
-                else
-                {
+		}
+		else
+		{
 			find_match_ll(buffer, "SwapTotal:", mem_tot);
 			find_match_ll(buffer, "SwapFree:", mem_free);
-                }
-        }
-	if (!swap) {
+		}
+	}
+	if (!swap)
+	{
 		*mem_free = freemem + buffers + cache;
 	}
-        fclose(fp);
-        return 0;
+	fclose(fp);
+
+	/* Convert to bytes */
+	*mem_free *= 1000;
+	*mem_tot *= 1000;
+	return 0;
 }
 
 int xs_parse_distro(char *name)
@@ -387,9 +249,9 @@ int xs_parse_distro(char *name)
 			find_match_char(buffer, "ACCEPT_KEYWORDS", keywords);
 		/* cppcheck-suppress uninitvar */
 		if (strstr(keywords, "\"") == NULL)
-			snprintf(buffer, bsize, "Gentoo Linux (stable)");
+			g_snprintf(buffer, bsize, "Gentoo Linux (stable)");
 		else
-			snprintf(buffer, bsize, "Gentoo Linux %s", keywords);
+			g_snprintf(buffer, bsize, "Gentoo Linux %s", keywords);
 	}
 	else if((fp = fopen("/etc/redhat-release", "r")) != NULL)
 		fgets(buffer, bsize, fp);
@@ -404,7 +266,7 @@ int xs_parse_distro(char *name)
 	else if((fp = fopen("/etc/turbolinux-release", "r")) != NULL)
 		fgets(buffer, bsize, fp);
 	else if((fp = fopen("/etc/arch-release", "r")) != NULL)
-		snprintf(buffer, bsize, "ArchLinux");
+		g_snprintf(buffer, bsize, "ArchLinux");
 	else if((fp = fopen("/etc/lsb-release", "r")) != NULL)
 	{
 		char id[bsize], codename[bsize], release[bsize];
@@ -417,45 +279,22 @@ int xs_parse_distro(char *name)
 			find_match_char(buffer, "DISTRIB_CODENAME", codename);
 			find_match_char(buffer, "DISTRIB_RELEASE", release);
 		}
-		snprintf(buffer, bsize, "%s \"%s\" %s", id, codename, release);
+		g_snprintf(buffer, bsize, "%s \"%s\" %s", id, codename, release);
 	}
 	else if((fp = fopen("/etc/debian_version", "r")) != NULL)
 	{
 		char release[bsize];
 		fgets(release, bsize, fp);
-		snprintf(buffer, bsize, "Debian %s", release);
+		g_snprintf(buffer, bsize, "Debian %s", release);
 	}
 	else
-		snprintf(buffer, bsize, "Unknown Distro");
-	if(fp != NULL) fclose(fp);
+		g_snprintf(buffer, bsize, "Unknown Distro");
+	if(fp != NULL)
+		fclose(fp);
 	
 	pos=strchr(buffer, '\n');
-	if(pos != NULL) *pos = '\0';
+	if(pos != NULL)
+		*pos = '\0';
 	strcpy(name, buffer);
 	return 0;
 }
-
-int xs_parse_hwmon_chip(char *chip)
-{
-	if (!hwmon_chip_present())
-		return 1;
-#if 0
-	else
-		get_hwmon_chip_name(chip);
-#endif
-	return 0;
-}
-
-int xs_parse_hwmon_temp(char *temp, unsigned int *sensor)
-{
-	unsigned int value;
-	float celsius;
-
-	if (!hwmon_chip_present())
-		return 1;
-	else
-		get_hwmon_temp(&value, sensor);
-		celsius = (float)value;
-		snprintf(temp, bsize, "%.1fC", celsius/1000.0);
-	return 0;
-}
diff --git a/plugins/sysinfo/parse.h b/plugins/sysinfo/unix/parse.h
index 27aac7da..c7cb571e 100644
--- a/plugins/sysinfo/parse.h
+++ b/plugins/sysinfo/unix/parse.h
@@ -23,18 +23,13 @@
 #ifndef _PARSE_H_
 #define _PARSE_H_
 
-int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned int *count);
-int xs_parse_uptime(int *weeks, int *days, int *hours, int *minutes, int *seconds);
-int xs_parse_os(char *user, char *host, char *kernel);
+int xs_parse_cpu(char *model, char *vendor, double *freq);
+gint64 xs_parse_uptime(void);
 int xs_parse_sound(char *snd_card);
-int xs_parse_netdev(const char *device, unsigned long long *bytes_recv, unsigned long long *bytes_sent);
-int xs_parse_df(const char *mount_point, char *string);
 int xs_parse_meminfo(unsigned long long *mem_tot, unsigned long long *mem_free, int swap);
 int xs_parse_video(char *vid_card);
 int xs_parse_agpbridge(char *agp_bridge);
 int xs_parse_ether(char *ethernet_card);
 int xs_parse_distro(char *name);
-int xs_parse_hwmon_chip(char *chip);
-int xs_parse_hwmon_temp(char *temp, unsigned int *sensor);
 
 #endif
diff --git a/plugins/sysinfo/unix/pci.c b/plugins/sysinfo/unix/pci.c
new file mode 100644
index 00000000..71b085fe
--- /dev/null
+++ b/plugins/sysinfo/unix/pci.c
@@ -0,0 +1,169 @@
+/*
+ * pci.c - PCI functions for X-Sys
+ * Copyright (C) 1997-1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz> [PCI routines from lspci]
+ * Copyright (C) 2000 Tom Rini <trini@kernel.crashing.org> [XorgAutoConfig pci.c, based on lspci]
+ * Copyright (C) 2005, 2006 Tony Vroon
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <pci/pci.h>
+#include <glib.h>
+
+#include "sysinfo.h"
+
+static struct pci_filter filter;       /* Device filter */
+static struct pci_access *pacc;
+int bus, dev, func; /* Location of the card */
+
+struct device {
+	struct device *next;
+	struct pci_dev *dev;
+	unsigned int config_cnt;
+	u8 config[256];
+};
+
+static struct device *first_dev;
+
+static struct device *scan_device(struct pci_dev *p)
+{
+	int how_much = 64;
+	struct device *d;
+
+	if (!pci_filter_match(&filter, p))
+		return NULL;
+	d = g_new0 (struct device, 1);
+	d->dev = p;
+	if (!pci_read_block(p, 0, d->config, how_much))
+		exit(1);
+	if (how_much < 128 && (d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
+	{
+		/* For cardbus bridges, we need to fetch 64 bytes more to get the full standard header... */
+		if (!pci_read_block(p, 64, d->config+64, 64))
+			exit(1);
+		how_much = 128;
+	}
+	d->config_cnt = how_much;
+	pci_setup_cache(p, d->config, d->config_cnt);
+	pci_fill_info(p, PCI_FILL_IDENT);
+	return d;
+}
+
+static void scan_devices(void)
+{
+	struct device *d;
+	struct pci_dev *p;
+
+	pci_scan_bus(pacc);
+	for(p=pacc->devices; p; p=p->next)
+	{
+		if ((d = scan_device(p)))
+		{
+			d->next = first_dev;
+			first_dev = d;
+		}
+	}
+}
+
+static u16 get_conf_word(struct device *d, unsigned int pos)
+{
+	  return d->config[pos] | (d->config[pos+1] << 8);
+}
+
+int pci_find_by_class(u16 *class, char *vendor, char *device)
+{
+	struct device *d;
+	struct pci_dev *p;
+	int nomatch = 1;
+
+	pacc = pci_alloc();
+	pci_filter_init(pacc, &filter);
+	pci_init(pacc);
+	scan_devices();
+
+	for(d=first_dev; d; d=d->next)
+	{
+		p = d->dev;
+		/* Acquire vendor & device ID if the class matches */
+		if(get_conf_word(d, PCI_CLASS_DEVICE) == *class)
+		{
+			nomatch = 0;
+			g_snprintf(vendor,7,"%04x",p->vendor_id);
+			g_snprintf(device,7,"%04x",p->device_id);
+			break;
+		}
+	  }
+
+	  pci_cleanup(pacc);
+	  return nomatch;
+}
+
+void pci_find_fullname(char *fullname, char *vendor, char *device)
+{
+	char buffer[bsize];
+	char vendorname[bsize/2] = "";
+	char devicename[bsize/2] = "";
+	char *position;
+	int cardfound = 0;
+	FILE *fp;
+	
+	if (!sysinfo_get_str_pref ("pciids", buffer))
+		strcpy (buffer, DEFAULT_PCIIDS);
+
+	fp = fopen (buffer, "r");
+	if(fp == NULL)
+	{
+		g_snprintf(fullname, bsize, "%s:%s", vendor, device);
+		//sysinfo_print_error ("pci.ids file not found! You might want to adjust your pciids setting with /SYSINFO SET pciids (you can query its current value with /SYSINFO LIST).\n");
+		return;
+	}
+
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		if (!isspace(buffer[0]) && strstr(buffer, vendor) != NULL)
+		{
+			position = strstr(buffer, vendor);
+			position += 6;
+			strncpy(vendorname, position, bsize/2);
+			position = strstr(vendorname, "\n");
+			*(position) = '\0';
+			break;
+		}
+	}
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		if(strstr(buffer, device) != NULL)
+		{
+			position = strstr(buffer, device);
+			position += 6;
+			strncpy(devicename, position, bsize/2);
+			position = strstr(devicename, " (");
+			if (position == NULL)
+				position = strstr(devicename, "\n");
+			*(position) = '\0';
+			cardfound = 1;
+			break;
+		 }
+	}
+	if (cardfound == 1)
+		g_snprintf(fullname, bsize, "%s %s", vendorname, devicename);
+	else
+		g_snprintf(fullname, bsize, "%s:%s", vendor, device);	
+	fclose(fp);
+}
diff --git a/plugins/sysinfo/pci.h b/plugins/sysinfo/unix/pci.h
index 673f0a0a..673f0a0a 100644
--- a/plugins/sysinfo/pci.h
+++ b/plugins/sysinfo/unix/pci.h
diff --git a/plugins/sysinfo/win32/backend.c b/plugins/sysinfo/win32/backend.c
new file mode 100644
index 00000000..2451c122
--- /dev/null
+++ b/plugins/sysinfo/win32/backend.c
@@ -0,0 +1,493 @@
+/* HexChat
+ * Copyright (c) 2011-2012 Berke Viktor.
+ *
+ * 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 THE
+ * AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <stdio.h>
+#include <windows.h>
+#include <wbemidl.h>
+
+#include <glib.h>
+
+#include "../format.h"
+
+/* Cache the info for subsequent invocations of /SYSINFO */
+static int cpu_arch = 0;
+static char *os_name = NULL;
+static char *cpu_info = NULL;
+static char *vga_name = NULL;
+
+static int command_callback (char *word[], char *word_eol[], void *user_data);
+
+typedef enum
+{
+	QUERY_WMI_OS,
+	QUERY_WMI_CPU,
+	QUERY_WMI_VGA,
+	QUERY_WMI_HDD,
+} QueryWmiType;
+
+void print_info (void);
+int get_cpu_arch (void);
+char *query_wmi (QueryWmiType mode);
+char *read_os_name (IWbemClassObject *object);
+char *read_cpu_info (IWbemClassObject *object);
+char *read_vga_name (IWbemClassObject *object);
+
+guint64 hdd_capacity;
+guint64 hdd_free_space;
+char *read_hdd_info (IWbemClassObject *object);
+
+char *get_memory_info (void);
+char *bstr_to_utf8 (BSTR bstr);
+guint64 variant_to_uint64 (VARIANT *variant);
+
+char *
+sysinfo_backend_get_sound (void)
+{
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_network (void)
+{
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_uptime (void)
+{
+	return sysinfo_format_uptime (GetTickCount64 () / 1000);
+}
+
+char *
+sysinfo_backend_get_disk (void)
+{
+	char *hdd_info;
+
+	/* HDD information is always loaded dynamically since it includes the current amount of free space */
+	hdd_capacity = 0;
+	hdd_free_space = 0;
+	hdd_info = query_wmi (QUERY_WMI_HDD);
+	if (hdd_info)
+		return sysinfo_format_disk (hdd_capacity, hdd_free_space);
+
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_cpu (void)
+{
+	if (cpu_info == NULL)
+		cpu_info = query_wmi (QUERY_WMI_CPU);
+
+	return g_strdup (cpu_info);
+}
+
+char *
+sysinfo_backend_get_memory (void)
+{
+	/* Memory information is always loaded dynamically since it includes the current amount of free memory */
+	return get_memory_info ();
+}
+
+char *
+sysinfo_backend_get_gpu (void)
+{
+	if (vga_name == NULL)
+		vga_name = query_wmi (QUERY_WMI_VGA);
+
+	return g_strdup (vga_name);
+}
+
+char *
+sysinfo_backend_get_os (void)
+{
+	if (os_name == NULL)
+		os_name = query_wmi (QUERY_WMI_OS);
+
+	if (cpu_arch == 0)
+		cpu_arch = get_cpu_arch ();
+
+	return g_strdup_printf ("%s (x%d)", os_name, cpu_arch);
+}
+
+static int get_cpu_arch (void)
+{
+	SYSTEM_INFO si;
+
+	GetNativeSystemInfo (&si);
+
+	if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+	{
+		return 64;
+	}
+	else
+	{
+		return 86;
+	}
+}
+
+/* http://msdn.microsoft.com/en-us/site/aa390423 */
+static char *query_wmi (QueryWmiType type)
+{
+	GString *result = NULL;
+	HRESULT hr;
+
+	IWbemLocator *locator = NULL;
+	BSTR namespaceName = NULL;
+	BSTR queryLanguageName = NULL;
+	BSTR query = NULL;
+	IWbemServices *namespace = NULL;
+	IUnknown *namespaceUnknown = NULL;
+	IEnumWbemClassObject *enumerator = NULL;
+	int i;
+	gboolean atleast_one_appended = FALSE;
+
+	hr = CoCreateInstance (&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &locator);
+	if (FAILED (hr))
+	{
+		goto exit;
+	}
+
+	namespaceName = SysAllocString (L"root\\CIMV2");
+
+	hr = locator->lpVtbl->ConnectServer (locator, namespaceName, NULL, NULL, NULL, 0, NULL, NULL, &namespace);
+	if (FAILED (hr))
+	{
+		goto release_locator;
+	}
+
+	hr = namespace->lpVtbl->QueryInterface (namespace, &IID_IUnknown, &namespaceUnknown);
+	if (FAILED (hr))
+	{
+		goto release_namespace;
+	}
+
+	hr = CoSetProxyBlanket (namespaceUnknown, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
+	if (FAILED (hr))
+	{
+		goto release_namespaceUnknown;
+	}
+
+	queryLanguageName = SysAllocString (L"WQL");
+
+	switch (type)
+	{
+	case QUERY_WMI_OS:
+		query = SysAllocString (L"SELECT Caption FROM Win32_OperatingSystem");
+		break;
+	case QUERY_WMI_CPU:
+		query = SysAllocString (L"SELECT Name, MaxClockSpeed FROM Win32_Processor");
+		break;
+	case QUERY_WMI_VGA:
+		query = SysAllocString (L"SELECT Name FROM Win32_VideoController");
+		break;
+	case QUERY_WMI_HDD:
+		query = SysAllocString (L"SELECT Name, Capacity, FreeSpace FROM Win32_Volume");
+		break;
+	default:
+		goto release_queryLanguageName;
+	}
+
+	hr = namespace->lpVtbl->ExecQuery (namespace, queryLanguageName, query, WBEM_FLAG_FORWARD_ONLY, NULL, &enumerator);
+	if (FAILED (hr))
+	{
+		goto release_query;
+	}
+
+	result = g_string_new ("");
+
+	for (i = 0;; i++)
+	{
+		ULONG numReturned = 0;
+		IWbemClassObject *object;
+		char *line;
+
+		hr = enumerator->lpVtbl->Next (enumerator, WBEM_INFINITE, 1, &object, &numReturned);
+		if (FAILED (hr) || numReturned == 0)
+		{
+			break;
+		}
+
+		switch (type)
+		{
+			case QUERY_WMI_OS:
+				line = read_os_name (object);
+				break;
+
+			case QUERY_WMI_CPU:
+				line = read_cpu_info (object);
+				break;
+
+			case QUERY_WMI_VGA:
+				line = read_vga_name (object);
+				break;
+
+			case QUERY_WMI_HDD:
+				line = read_hdd_info (object);
+				break;
+
+			default:
+				break;
+		}
+
+		object->lpVtbl->Release (object);
+
+		if (line != NULL)
+		{
+			if (atleast_one_appended)
+			{
+				g_string_append (result, ", ");
+			}
+
+			g_string_append (result, line);
+
+			g_free (line);
+
+			atleast_one_appended = TRUE;
+		}
+	}
+
+	enumerator->lpVtbl->Release (enumerator);
+
+release_query:
+	SysFreeString (query);
+
+release_queryLanguageName:
+	SysFreeString (queryLanguageName);
+
+release_namespaceUnknown:
+	namespaceUnknown->lpVtbl->Release (namespaceUnknown);
+
+release_namespace:
+	namespace->lpVtbl->Release (namespace);
+
+release_locator:
+	locator->lpVtbl->Release (locator);
+	SysFreeString (namespaceName);
+
+exit:
+	if (result == NULL)
+	{
+		return NULL;
+	}
+
+	return g_string_free (result, FALSE);
+}
+
+static char *read_os_name (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT caption_variant;
+	char *caption_utf8;
+
+	hr = object->lpVtbl->Get (object, L"Caption", 0, &caption_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	caption_utf8 = bstr_to_utf8 (caption_variant.bstrVal);
+
+	VariantClear(&caption_variant);
+
+	if (caption_utf8 == NULL)
+	{
+		return NULL;
+	}
+
+	g_strchomp (caption_utf8);
+
+	return caption_utf8;
+}
+
+static char *read_cpu_info (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT name_variant;
+	char *name_utf8;
+	VARIANT max_clock_speed_variant;
+	guint cpu_freq_mhz;
+	char *result;
+
+	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	name_utf8 = bstr_to_utf8 (name_variant.bstrVal);
+
+	VariantClear (&name_variant);
+
+	if (name_utf8 == NULL)
+	{
+		return NULL;
+	}
+
+	hr = object->lpVtbl->Get (object, L"MaxClockSpeed", 0, &max_clock_speed_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		g_free (name_utf8);
+
+		return NULL;
+	}
+
+	cpu_freq_mhz = max_clock_speed_variant.uintVal;
+
+	VariantClear (&max_clock_speed_variant);
+
+	if (cpu_freq_mhz > 1000)
+	{
+		result = g_strdup_printf ("%s (%.2fGHz)", name_utf8, cpu_freq_mhz / 1000.f);
+	}
+	else
+	{
+		result = g_strdup_printf ("%s (%" G_GUINT32_FORMAT "MHz)", name_utf8, cpu_freq_mhz);
+	}
+
+	g_free (name_utf8);
+
+	return result;
+}
+
+static char *read_vga_name (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT name_variant;
+	char *name_utf8;
+
+	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	name_utf8 = bstr_to_utf8 (name_variant.bstrVal);
+
+	VariantClear (&name_variant);
+
+	if (name_utf8 == NULL)
+	{
+		return NULL;
+	}
+
+	return g_strchomp (name_utf8);
+}
+
+static char *read_hdd_info (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT name_variant;
+	BSTR name_bstr;
+	gsize name_len;
+	VARIANT capacity_variant;
+	guint64 capacity;
+	VARIANT free_space_variant;
+	guint64 free_space;
+
+	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	name_bstr = name_variant.bstrVal;
+	name_len = SysStringLen (name_variant.bstrVal);
+
+	if (name_len >= 4 && name_bstr[0] == L'\\' && name_bstr[1] == L'\\' && name_bstr[2] == L'?' && name_bstr[3] == L'\\')
+	{
+		// This is not a named volume. Skip it.
+		VariantClear (&name_variant);
+
+		return NULL;
+	}
+
+	VariantClear (&name_variant);
+
+	hr = object->lpVtbl->Get (object, L"Capacity", 0, &capacity_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	capacity = variant_to_uint64 (&capacity_variant);
+
+	VariantClear (&capacity_variant);
+
+	if (capacity == 0)
+	{
+		return NULL;
+	}
+
+	hr = object->lpVtbl->Get (object, L"FreeSpace", 0, &free_space_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	free_space = variant_to_uint64 (&free_space_variant);
+
+	VariantClear (&free_space_variant);
+
+	if (free_space == 0)
+	{
+		return NULL;
+	}
+
+	hdd_capacity += capacity;
+	hdd_free_space += free_space;
+
+	return NULL;
+}
+
+static char *get_memory_info (void)
+{
+	MEMORYSTATUSEX meminfo = { 0 };
+	meminfo.dwLength = sizeof (meminfo);
+
+	if (!GlobalMemoryStatusEx (&meminfo))
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_memory (meminfo.ullTotalPhys, meminfo.ullAvailPhys);
+}
+
+static char *bstr_to_utf8 (BSTR bstr)
+{
+	return g_utf16_to_utf8 (bstr, SysStringLen (bstr), NULL, NULL, NULL);
+}
+
+static guint64 variant_to_uint64 (VARIANT *variant)
+{
+	switch (V_VT (variant))
+	{
+	case VT_UI8:
+		return variant->ullVal;
+
+	case VT_BSTR:
+		return wcstoull (variant->bstrVal, NULL, 10);
+
+	default:
+		return 0;
+	}
+}
diff --git a/plugins/sysinfo/xsys-changelog b/plugins/sysinfo/xsys-changelog
deleted file mode 100644
index 9ea20727..00000000
--- a/plugins/sysinfo/xsys-changelog
+++ /dev/null
@@ -1,116 +0,0 @@
-v2.2.0
-	* (Thomas Cort) Report L2 cache info for Alpha CPUs
-	* (Tony Vroon) Drop XMMS, port audacious features to D-Bus, make dependency mandatory
-	* (Tony Vroon) Use pretty_freespace for memory & swap reporting as well as disk space
-	* (Tony Vroon) Make pretty_freespace report none if total_size is 0, thanks to Emopig <andrew@nelless.net> for the report
-	* (Tony Vroon) Make pretty_freespace aware of terabytes, petabytes, exabytes, zettabytes & yottabytes
-	* (Tony Vroon) Remove xchatdirfs workaround
-
-v2.1.0
-	Removals & pending removal:
-	* (Tony Vroon) Remove support for BMP, it is an abandoned project. Suggested upgrade path: audacious
-	* (Tony Vroon) Remove /uname & /euname; the OS part of sysinfo displays similar info without requiring a process pipe
-	* (Tony Vroon) Added a note that the xchatdirfs workaround is due for removal as X-Chat Gnome has fixed the bug
-
-	Bugfixes:
-	* (Tony Vroon) Actually show the vendor that we retrieve in cpuinfo
-	* (Tony Vroon) Display Gentoo Linux as stable or ~arch, the baselayout version doesn't really interest anyone
-	* (Tony Vroon) Match framework: Make remove_leading_whitespace actually work
-	* (Tony Vroon) Match framework: Do not assume that a delimiter is always followed by a space
-
-	Code improvements:
-	* (Tony Vroon) PCI framework: We were requesting more info then we actually return to the caller
-	* (Tony Vroon) Match framework: Consolidate delimiters in a single define & use 1 strpbrk instead of 2 strstr's
-	* (Tony Vroon) Display the machine string instead of the pmac-generation as vendor info for PPC machines
-
-	New features
-	* (Tony Vroon) Show memory capacity in gigabytes instead of in megabytes when appropriate
-	* (Tony Vroon) Cut cpu name at comma (so overly long other info such as "altivec supported" is no longer displayed)
-	* (Tony Vroon) Now Playing: Report time played as well as the song length
-	* (Tony Vroon) Now Playing: Support reporting as an action; configurable at runtime
-	* (Tony Vroon) Check LSB release data, prefer above all others; based on a code sample submitted by Thomas Winwood
-
-v2.0.9
-	* (Tony Vroon) Protect the matching framework against spurious matches (bug reported by Harm Geerts)
-	* (Tony Vroon) Unexporting unnecessary symbols for PCI framework
-	* (Tony Vroon) Deal with incompatible header changes in pciutils
-	* (Tony Vroon) Begin implementing hardware monitoring support, not yet activated
-	* (Tony Vroon) Add support for Audacious, a BMP fork
-
-v2.0.8
-	* (Tony Vroon) Make XMMS interface actually work, thanks to a patch from Morten Cools
-	* (Tony Vroon) Use percentages for df information as well
-	* (Gustavo Zacarias) Add support for Sparc architecture, cache size detection on sparc64 only
-	* (Gustavo Zacarias) Consolidate buffer sizes into a single define
-
-v2.0.7
-	* (Tony Vroon) Have df parser ignore pseudo-filesystems; deal with other locales more gracefully
-	* (Tony Vroon) Change default formatstring not to use mIRC color codes
-	* (Tony Vroon) Add fallback to ~/.xchat2 for xchat-gnome which does not report xchatdirfs properly
-	* (Tony Vroon) Revert to beepctrl.h style calls as infopipe is too unreliable
-
-v2.0.6
-	* (Tony Vroon) Rewrote PCI framework, no longer depends on sysfs, kernel 2.4 and lower will work now
-	* (Tony Vroon) Made percentages configurable, can be set at runtime (feature request by Halcy0n)
-	* (Tony Vroon) Abstract out all pointer voodoo from xsys.c
-	* (Tony Vroon) Do not return XCHAT_EAT_NONE, causes spurious "unknown command" errors
-	* (Tony Vroon) Deal more gracefully with a missing soundcard or unknown linux distribution
-	* (Tony Vroon) Add error handling to the matching framework
-
-v2.0.5
-	* (Tony Vroon) Added support for parisc/hppa & ia64 architectures
-	* (Tony Vroon) Proper report of L2 cache as "unknown" instead of showing bits of unitialized memory
-	* (Tony Vroon) Upped PCI parser yield for ppc64 architecture, has high bus number for AGP card
-	* (Tony Vroon) Use percentages in memory/swap information
-
-v2.0.4
-	* (Tony Vroon) /sound uses ALSA if possible, PCI now fallback (false positives reported with PCI code)
-	* (Tony Vroon) Remove 0 prefix from first ALSA card; 1: and up will be shown for extra cards
-	* (Tony Vroon) Matching code rewritten and separated out from other code
-	* (Tony Vroon) Use new matching framework where possible
-	* (Tony Vroon) Added support for Alpha architecture, thanks to Bert (bert@ev6.net)
-
-v2.0.3
-	* (Tony Vroon) Fix buttons, XMMS -> NP
-	* (Tony Vroon) PCI functions separated out from other code; fully rewritten
-	* (Tony Vroon) Use new PCI framework for sound detection; ALSA is now fallback
-	* (Tony Vroon) Implement /ether
-	* (Tony Vroon) /video now reports video card @ AGP bridge; resolution info dropped
-
-v2.0.2
-	* (Tony Vroon) XMMS/BMP: Delete XMMS/BMP detection; it just got obsoleted by a BMP bugfix
-	* (Tony Vroon) XMMS/BMP: Change to /np & /enp as commands (np -> now playing)
-	* (Tony Vroon) Allow customization of now_playing with /playing
-	* (Tony Vroon) Separate out the length field for now_playing
-	* (Tony Vroon) Better configuration file handling
-	* (Tony Vroon) Set homepage to http://dev.gentoo.org/~chainsaw/xsys
-	* (Tony Vroon) Make channel buttons optional, not everyone appreciates them
-	* (Tony Vroon) Fix cpuinfo parsing on x86_64, a necessary define was missing
-
-v2.0.1
-	* (Tony Vroon) XMMS/BMP: Report "stream" if song length is -1
-	* (Tony Vroon) XMMS/BMP: Determine whether XMMS or BMP is playing
-	* (Tony Vroon) Better errorhandling if pci.ids parsing fails; at least mention raw PCI ID of card
-	* (Tony Vroon) Remove AGP from video card messages; we detect plain PCI cards too
-	* (Tony Vroon) Fix Debian release detector
-
-v2.0.0
-	* (mikeshoup)  Clean up of code for 2.0.0 release
-	* (Tony Vroon) Added PowerPC /proc/cpuinfo support
-	* (Tony Vroon) Changed LSPCI to SYSFS
-
-v1.9.3
-	* (mikeshoup) Introduced distro function
-	* (mikeshoup, Tony Vroon's suggestion) Removed bitrate from /XMMS
-
-v1.9.2
-	* 2005/01/14 (mikeshoup) Put in the userlist buttons
-	* 2005/01/10 (mikeshoup) Added XMMS/BMP Support
-
-v1.9.1
-	* 2004/12/20 (mikeshoup) Added a dynamic formatting scheme
-	* 2004/12/19 (mikeshoup) Changed some commands
-	* 2004/12/18 (mikeshoup) Reintroducted /VIDEO
-
-v1.9.0
-	* 2004/12/17 (mikeshoup) Initial Release
diff --git a/plugins/sysinfo/xsys-install b/plugins/sysinfo/xsys-install
deleted file mode 100644
index 8f148569..00000000
--- a/plugins/sysinfo/xsys-install
+++ /dev/null
@@ -1,15 +0,0 @@
-INSTALLATION
-============
-Installation is straightforward. You need Audacious 1.4 or higher and D-Bus.
-Open up the Makefile, check to make sure PCIIDS points to your pci.ids file.
-	(Symptom if you get it wrong: raw PCI ID's (XXXX:XXXX) emitted by /VIDEO and friends).
-
-Run: make
-Run: make install
-
-Voila!
-
-NOTES:
-`make install' copies the compiled library (something like xsys-v.v.v.so) to
-$HOME/.xchat2/xsys-plugin.so for autoloading. If $HOME/.xchat2/xsys-plugin.so
-exists, it is removed first.
diff --git a/plugins/sysinfo/xsys-makefile b/plugins/sysinfo/xsys-makefile
deleted file mode 100644
index 8b51a53d..00000000
--- a/plugins/sysinfo/xsys-makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-#### SET THIS VALUE TO THE LOCATION OF THE `pci.ids` file ####
-PCIIDS = /usr/share/misc/pci.ids
-
-#### UNCOMMENT THIS IF YOU WANT THE BUTTONS ####
-#BUTTON = -Dbuttonbar
-
-#### SHOULD NOT NEED TO EDIT BELOW THIS LINE ####
-VER_MAJOR = 2
-VER_MINOR = 2
-VER_PATCH = 0
-CC = gcc
-CFLAGS += -O2 -Wall -fPIC
-CFLAGS += -DVER_MINOR=$(VER_MINOR) -DVER_MAJOR=$(VER_MAJOR) -DVER_PATCH=$(VER_PATCH) \
-          -DVER_STRING=\"$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH)\" -DPCIIDS=\"$(PCIIDS)\" $(BUTTON)
-LDFLAGS = $(CFLAGS) -shared
-LIBRARY = xsys-$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH).so
-OBJECTS = xsys.o parse.o pci.o match.o hwmon.o
-
-ALL : $(LIBRARY)
-
-$(LIBRARY) : $(OBJECTS)
-	$(CC) $(LDFLAGS) -o $(LIBRARY) $(OBJECTS) -lpci
-
-xsys.o : xsys.c
-parse.o : parse.c
-pci.o : pci.c
-match.o : match.c
-hwmon.o : hwmon.c
-
-.PHONY : clean
-clean :
-	rm -rf *.o *.so *~
-
-.PHONY : install
-install : $(LIBRARY)
-	rm -f $(HOME)/.xchat2/xsys-plugin.so
-	cp ./$(LIBRARY) $(HOME)/.xchat2/xsys-plugin.so
-
diff --git a/plugins/sysinfo/xsys-readme b/plugins/sysinfo/xsys-readme
deleted file mode 100644
index 6226e725..00000000
--- a/plugins/sysinfo/xsys-readme
+++ /dev/null
@@ -1,105 +0,0 @@
-X-Sys README
-============
-What is X-Sys?
-
-X-Sys is a plugin for X-Chat that allows you to display your current system statistics in
-a channel, private conversation or just in an echo to yourself for testing purposes.
-It is supported on Linux, running on various architectures. Right now x86, ppc, ppc64, sparc,
-sparc64 and alpha are supported, with parisc and ia64 implemented but awaiting testing.
-
----------------
-Who wrote this?
-
-X-Sys is originally a Mike Shoup creation, from the very first alpha releases to the open-source
-version 1 releases. But then, things stalled. For a few months (more like a year almost)
-Mike didn't work on X-Sys. The last version that had been written was 1.0.5.
-The website was gone, and I (Tony) couldn't find Mike. So, I took over and improved it to my liking. 
-It turned out that Mike was still around, though, he contacted me and started development again,
-now called version 2, a complete rewrite. Various 1.9 betas came out that I contributed patches to,
-and starting with version 2.0.0 I'm maintaining xchat-xsys again, this time with Mike's blessing.
-
----------------
-What do I need?
-
-- X-Chat (regular or Gnome version)
-- Audacious 1.4 or higher
-- D-Bus (for communication with Audacious)
-- a working toolchain (compiler, binutils, etc).
-
-------------------------------------------------
-What if I get errors about u8 not being defined?
-
-Sorry to hear that, it appears your linux distribution neglected to install essential headers on your 
-system. On Debian & Ubuntu, apt-get install pciutils-dev should make it happy.
-
-========
-COMMANDS
-
-X-Sys 2 has the following implemented commands:
-/XSYS & /EXSYS - Output current version, either to channel or echoed on screen.
-/CPUINFO & /ECPUINFO - Echoes or says current cpu statistics
-/SYSUPTIME & /ESYSUPTIME - Echoes or says current uptime
-/OSINFO & /EOSINFO - Echoes or says various OS statistics
-/SOUND & /ESOUND - Echoes or says the current sound card, as determined by ALSA
-/NETDATA & /ENETDATA - Echoes or says total amount transferred through a network
-	interface. Use like: `/netdata eth0' (where eth0 is a network interface)
-/NETSTREAM & /ENETSTREAM - Echoes or says amount of bandwidth being used.
-	Use like: `/netstream eth0' (where eth0 is a network interface)
-/DISKINFO & /EDISKINFO - Echoes or says free space on partitions. The DISK command has a
-	few arguments as follows:
-	ALL - Displays every partitions
-	/mount - Displays free space for that specific mount point
-	No arguments just displays total free space
-/MEMINFO & /EMEMINFO - Echoes or says memory information.
-/VIDEO & /EVIDEO - Echoes or says the current video card on the PCI bus
-/ETHER & /EETHER - Echoes or says the current network card on the PCI bus
-/DISTRO & /EDISTRO - Echoes or says which distro you're running
-	If this doesn't work for your distro, look for a *-release file or similar in /etc
-	E-mail this to chainsaw@gentoo.org
-
-and the big one:
-/SYSINFO & /ESYSINFO - Complete system information!
-
-Two output control commands:
-/XSYS2FORMAT , No arguments, it will print just the current formatting string.
-   It will take any arguments to it as the formatting string.
-   The formatting string can consist of any letter/numbers, and is used to format
-   the output. The following special symbols can be used:
-   
-   %B      : Bold
-   %Cnn    : Foreground Color, where nn is a number corresponding to a mIRC color
-   %Cnn,nn : Foreground,Background Color
-   %R      : Reverse Foreground/Background Colors
-   %O      : Reset Color and Format (thats an 'oh' not a 'zero (0)')
-   %C      : Reset Color
-   %U      : Underline 
-
-/PLAYING will either print or allow you to set the text for /np.
-The default is now_playing, but you can set this to whatever text you prefer.
-
-/PERCENTAGES will allow you to set whether to use percentages in plugin output or not.
-Percentages are enabled  by default. Use a zero value to disable, and a non-zero value
-to enable. If unsure, use 1.
-
-/NP & /ENP - Reports what's currently playing in Audacious.
-
-====
-BUGS
-(none known)
-
-E-mail me your bug reports at chainsaw@gentoo.org
-Please include the following information:
-- what architecture you are using (amd64, ia64, parisc, ppc, ppc64, sparc, sparc64 or x86)
-- what linux distribution you are using (Gentoo 2007.1, Fedora Core 8, etc)
-- what compiler you have used to compile X-Sys, i.e. gcc (GCC) 4.1.2 (Gentoo 4.1.2)
-- what version of X-Sys you are using
-
-=======
-Thanks!
-Remember, everything here is:
-(C) 2003, 2004, 2005 by Michael Shoup
-(C) 2005, 2006, 2007 by Tony Vroon
-All Rights Reserved.
-Visit http://dev.gentoo.org/~chainsaw/xsys/ for release information.
-
-Feel free to e-mail me for feature requests, or see if I'm online on irc.freenode.net
diff --git a/plugins/sysinfo/xsys.c b/plugins/sysinfo/xsys.c
deleted file mode 100644
index 4ab6e873..00000000
--- a/plugins/sysinfo/xsys.c
+++ /dev/null
@@ -1,923 +0,0 @@
-/*
- * SysInfo - sysinfo plugin for HexChat
- * Copyright (c) 2012 Berke Viktor.
- *
- * xsys.c - main functions for X-Sys 2
- * by mikeshoup
- * Copyright (C) 2003, 2004, 2005 Michael Shoup
- * Copyright (C) 2005, 2006, 2007 Tony Vroon
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#include "hexchat-plugin.h"
-#include "parse.h"
-#include "match.h"
-#include "xsys.h"
-
-#define DEFAULT_FORMAT "%B%1:%B %2 **"
-#define DEFAULT_PERCENT 1
-#define DEFAULT_ANNOUNCE 1
-#define DEFAULT_PCIIDS "/usr/share/hwdata/pci.ids"
-
-static hexchat_plugin *ph;	/* plugin handle */
-static int error_printed = 0;	/* semaphore, make sure not to print the same error more than once during one execution */
-
-static char name[] = "SysInfo";
-static char desc[] = "Display info about your hardware and OS";
-static char version[] = "3.0";
-static char sysinfo_help[] = "SysInfo Usage:\n  /SYSINFO [-e|-o] [OS|DISTRO|CPU|RAM|DISK|VGA|SOUND|ETHERNET|UPTIME], print various details about your system or print a summary without arguments\n  /SYSINFO LIST, print current settings\n  /SYSINFO SET <variable>, update given setting\n  /SYSINFO RESET, reset settings to defaults\n  /NETDATA <iface>, show transmitted data on given interface\n  /NETSTREAM <iface>, show current bandwidth on given interface\n";
-
-void
-sysinfo_get_pciids (char* dest)
-{
-	hexchat_pluginpref_get_str (ph, "pciids", dest);
-}
-
-int
-sysinfo_get_percent ()
-{
-	return hexchat_pluginpref_get_int (ph, "percent");
-}
-
-int
-sysinfo_get_announce ()
-{
-	return hexchat_pluginpref_get_int (ph, "announce");
-}
-
-void
-sysinfo_print_error (const char* msg)
-{
-	if (!error_printed)
-	{
-		hexchat_printf (ph, "%s\t%s", name, msg);
-	}
-	error_printed++;
-	
-}
-
-static int
-print_summary (int announce, char* format)
-{
-	char sysinfo[bsize];
-	char buffer[bsize];
-	char cpu_model[bsize];
-	char cpu_cache[bsize];
-	char cpu_vendor[bsize];
-	char os_host[bsize];
-	char os_user[bsize];
-	char os_kernel[bsize];
-	unsigned long long mem_total;
-	unsigned long long mem_free;
-	unsigned int count;
-	double cpu_freq;
-	int giga = 0;
-	int weeks;
-	int days;
-	int hours;
-	int minutes;
-	int seconds;
-	sysinfo[0] = '\0';
-
-	snprintf (buffer, bsize, "%s", hexchat_get_info (ph, "version"));
-	format_output ("HexChat", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN OS PARSING */
-	if (xs_parse_os (os_user, os_host, os_kernel) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_os()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	snprintf (buffer, bsize, "%s", os_kernel);
-	format_output ("OS", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN DISTRO PARSING */
-        if (xs_parse_distro (buffer) != 0)
-        {
-		strncpy (buffer, "Unknown", bsize);
-	}
-
-	format_output ("Distro", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));	
-
-	/* BEGIN CPU PARSING */
-	if (xs_parse_cpu (cpu_model, cpu_vendor, &cpu_freq, cpu_cache, &count) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_cpu()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (cpu_freq > 1000)
-	{
-		cpu_freq /= 1000;
-		giga = 1;
-	}
-
-	if (giga)
-	{
-		snprintf (buffer, bsize, "%u x %s (%s) @ %.2fGHz", count, cpu_model, cpu_vendor, cpu_freq);
-	}
-	else
-	{
-		snprintf (buffer, bsize, "%u x %s (%s) @ %.0fMHz", count, cpu_model, cpu_vendor, cpu_freq);
-	}
-
-	format_output ("CPU", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN MEMORY PARSING */
-	if (xs_parse_meminfo (&mem_total, &mem_free, 0) == 1)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_meminfo!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	snprintf (buffer, bsize, "%s", pretty_freespace ("Physical", &mem_free, &mem_total));
-	format_output ("RAM", buffer, format);	
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN DISK PARSING */
-	if (xs_parse_df (NULL, buffer))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_df", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("Disk", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN VIDEO PARSING */
-	if (xs_parse_video (buffer))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_video", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("VGA", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN SOUND PARSING */
-	if (xs_parse_sound (buffer))
-	{
-		strncpy (buffer, "Not present", bsize);
-	}
-
-	format_output ("Sound", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN ETHERNET PARSING */
-	if (xs_parse_ether (buffer))
-	{
-		strncpy (buffer, "None found", bsize);
-	}
-
-	format_output ("Ethernet", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN UPTIME PARSING */
-	if (xs_parse_uptime (&weeks, &days, &hours, &minutes, &seconds))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_uptime()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (minutes != 0 || hours != 0 || days != 0 || weeks != 0)
-	{
-		if (hours != 0 || days != 0 || weeks != 0)
-		{
-			if (days  !=0 || weeks != 0)
-			{
-				if (weeks != 0)
-				{
-					snprintf (buffer, bsize, "%dw %dd %dh %dm %ds", weeks, days, hours, minutes, seconds);
-				}
-				else
-				{
-					snprintf (buffer, bsize, "%dd %dh %dm %ds", days, hours, minutes, seconds);
-				}
-			}
-			else
-			{
-				snprintf (buffer, bsize, "%dh %dm %ds", hours, minutes, seconds);
-			}
-		}
-		else
-		{
-			snprintf (buffer, bsize, "%dm %ds", minutes, seconds);
-		}
-	}
-
-        format_output ("Uptime", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", sysinfo);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", sysinfo);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_os (int announce, char* format)
-{
-	char buffer[bsize];
-	char user[bsize];
-	char host[bsize];
-	char kernel[bsize];
-
-	if (xs_parse_os (user, host, kernel) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_os()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	snprintf (buffer, bsize, "%s@%s, %s", user, host, kernel);
-	format_output ("OS", buffer, format);
-	
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_distro (int announce, char* format)
-{
-	char name[bsize];
-
-	if (xs_parse_distro (name) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_distro()!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output("Distro", name, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", name);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", name);
-	}
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_cpu (int announce, char* format)
-{
-	char model[bsize];
-	char vendor[bsize];
-	char cache[bsize];
-	char buffer[bsize];
-	unsigned int count;
-	double freq;
-	int giga = 0;
-
-	if (xs_parse_cpu (model, vendor, &freq, cache, &count) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_cpu()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (freq > 1000)
-	{
-		freq /= 1000;
-		giga = 1;
-	}
-
-	if (giga)
-	{
-		snprintf (buffer, bsize, "%u x %s (%s) @ %.2fGHz w/ %s L2 Cache", count, model, vendor, freq, cache);
-	}
-	else
-	{
-		snprintf (buffer, bsize, "%u x %s (%s) @ %.0fMHz w/ %s L2 Cache", count, model, vendor, freq, cache);
-	}
-
-	format_output ("CPU", buffer, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_ram (int announce, char* format)
-{
-	unsigned long long mem_total;
-	unsigned long long mem_free;
-	unsigned long long swap_total;
-	unsigned long long swap_free;
-	char string[bsize];
-
-	if (xs_parse_meminfo (&mem_total, &mem_free, 0) == 1)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_meminfo!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-	if (xs_parse_meminfo (&swap_total, &swap_free, 1) == 1)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_meminfo!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	snprintf (string, bsize, "%s - %s", pretty_freespace ("Physical", &mem_free, &mem_total), pretty_freespace ("Swap", &swap_free, &swap_total));
-	format_output ("RAM", string, format);
-	
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", string);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", string);
-	}
-	
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_disk (int announce, char* format)
-{
-	char string[bsize] = {0,};
-
-#if 0
-	if (*word == '\0')
-	{
-		if (xs_parse_df (NULL, string))
-		{
-			hexchat_printf (ph, "ERROR in parse_df");
-			return HEXCHAT_EAT_ALL;
-		}
-	}
-	else
-	{
-		if (xs_parse_df (*word, string))
-		{
-			hexchat_printf (ph, "ERROR in parse_df");
-			return HEXCHAT_EAT_ALL;
-		}
-	}
-#endif
-
-	if (xs_parse_df (NULL, string))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_df", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("Disk", string, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", string);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", string);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_vga (int announce, char* format)
-{
-	char vid_card[bsize];
-	char agp_bridge[bsize];
-	char buffer[bsize];
-	int ret;
-
-	if ((ret = xs_parse_video (vid_card)) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_video! %d", name, ret);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (xs_parse_agpbridge (agp_bridge) != 0)
-	{
-		snprintf (buffer, bsize, "%s", vid_card);
-	}
-	else
-	{
-		snprintf (buffer, bsize, "%s @ %s", vid_card, agp_bridge);
-	}
-
-	format_output ("VGA", buffer, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_sound (int announce, char* format)
-{
-	char sound[bsize];
-
-	if (xs_parse_sound (sound) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_asound()!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("Sound", sound, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", sound);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", sound);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-
-static int
-print_ethernet (int announce, char* format)
-{
-	char ethernet_card[bsize];
-
-	if (xs_parse_ether (ethernet_card))
-	{
-		strncpy (ethernet_card, "None found", bsize);
-	}
-
-	format_output ("Ethernet", ethernet_card, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", ethernet_card);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", ethernet_card);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_uptime (int announce, char* format)
-{
-	char buffer[bsize];
-	int weeks;
-	int days;
-	int hours;
-	int minutes;
-	int seconds;
-
-	if (xs_parse_uptime (&weeks, &days, &hours, &minutes, &seconds))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_uptime()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (minutes != 0 || hours != 0 || days != 0 || weeks != 0)
-	{
-		if (hours != 0 || days != 0 || weeks != 0)
-		{
-			if (days  !=0 || weeks != 0)
-			{
-				if (weeks != 0)
-				{
-					snprintf (buffer, bsize, "%dw %dd %dh %dm %ds", weeks, days, hours, minutes, seconds);
-				}
-				else
-				{
-					snprintf (buffer, bsize, "%dd %dh %dm %ds", days, hours, minutes, seconds);
-				}
-			}
-			else
-			{
-				snprintf (buffer, bsize, "%dh %dm %ds", hours, minutes, seconds);
-			}
-		}
-		else
-		{
-			snprintf (buffer, bsize, "%dm %ds", minutes, seconds);
-		}
-	}
-
-	format_output ("Uptime", buffer, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-netdata_cb (char *word[], char *word_eol[], void *userdata)
-{
-	char netdata[bsize];
-	char format[bsize];
-	unsigned long long bytes_recv;
-	unsigned long long bytes_sent;
-	
-	if (*word[2] == '\0')
-	{
-		hexchat_printf (ph, "%s\tYou must specify a network device (e.g. /NETDATA eth0)!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (xs_parse_netdev (word[2], &bytes_recv, &bytes_sent) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_netdev", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	bytes_recv /= 1024;
-	bytes_sent /= 1024;
-	
-	snprintf (netdata, bsize, "%s: %.1f MB Received, %.1f MB Sent", word[2], (double)bytes_recv/1024.0, (double)bytes_sent/1024.0);
-	hexchat_pluginpref_get_str (ph, "format", format);
-	format_output ("Netdata", netdata, format);
-
-	if (hexchat_list_int (ph, NULL, "type") >= 2)
-	{
-		hexchat_commandf (ph, "SAY %s", netdata);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", netdata);
-	}
-	
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-netstream_cb (char *word[], char *word_eol[], void *userdata)
-{
-	char netstream[bsize];
-	char mag_r[5];
-	char mag_s[5];
-	char format[bsize];
-	unsigned long long bytes_recv;
-	unsigned long long bytes_sent;
-	unsigned long long bytes_recv_p;
-	unsigned long long bytes_sent_p;
-
-	struct timespec ts = {1, 0};
-
-	if (*word[2] == '\0')
-	{
-		hexchat_printf (ph, "%s\tYou must specify a network device (e.g. /NETSTREAM eth0)!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (xs_parse_netdev(word[2], &bytes_recv, &bytes_sent) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_netdev", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	while (nanosleep (&ts, &ts) < 0);
-
-	if (xs_parse_netdev(word[2], &bytes_recv_p, &bytes_sent_p) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_netdev", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	bytes_recv = (bytes_recv_p - bytes_recv);
-	bytes_sent = (bytes_sent_p - bytes_sent);
-
-	if (bytes_recv > 1024)
-	{
-		bytes_recv /= 1024;
-		snprintf (mag_r, 5, "KB/s");
-	}
-	else
-	{
-		snprintf (mag_r, 5, "B/s");
-	}
-
-	if (bytes_sent > 1024)
-	{
-		bytes_sent /= 1024;
-		snprintf (mag_s, 5, "KB/s");
-	}
-	else
-	{
-		snprintf (mag_s, 5, "B/s");
-	}
-
-	snprintf (netstream, bsize, "%s: Receiving %llu %s, Sending %llu %s", word[2], bytes_recv, mag_r, bytes_sent, mag_s);
-	hexchat_pluginpref_get_str (ph, "format", format);
-	format_output ("Netstream", netstream, format);
-
-	if (hexchat_list_int (ph, NULL, "type") >= 2)
-	{
-		hexchat_commandf (ph, "SAY %s", netstream);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", netstream);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static void
-list_settings ()
-{
-	char list[512];
-	char buffer[512];
-	char* token;
-
-	hexchat_pluginpref_list (ph, list);
-	hexchat_printf (ph, "%s\tCurrent Settings:", name);
-	token = strtok (list, ",");
-
-	while (token != NULL)
-	{
-		hexchat_pluginpref_get_str (ph, token, buffer);
-		hexchat_printf (ph, "%s\t%s: %s\n", name, token, buffer);
-		token = strtok (NULL, ",");
-	}
-}
-
-static void
-reset_settings ()
-{
-	hexchat_pluginpref_set_str (ph, "pciids", DEFAULT_PCIIDS);
-	hexchat_pluginpref_set_str (ph, "format", DEFAULT_FORMAT);
-	hexchat_pluginpref_set_int (ph, "percent", DEFAULT_PERCENT);
-	hexchat_pluginpref_set_int (ph, "announce", DEFAULT_ANNOUNCE);
-}
-
-static int
-sysinfo_cb (char *word[], char *word_eol[], void *userdata)
-{
-	error_printed = 0;
-	int announce = sysinfo_get_announce ();
-	int offset = 0;
-	int buffer;
-	char format[bsize];
-
-	if (!hexchat_pluginpref_get_str (ph, "format", format))
-	{
-		hexchat_printf (ph, "%s\tError reading config file!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	/* Cannot send to server tab */
-	if (hexchat_list_int (ph, NULL, "type") == 1)
-	{
-		announce = 0;
-	}
-
-	/* Allow overriding global announce setting */
-	if (!strcmp ("-e", word[2]))
-	{
-		announce = 0;
-		offset++;
-	}
-	else if (!strcmp ("-o", word[2]))
-	{
-		announce = 1;
-		offset++;
-	}
-
-	if (!g_ascii_strcasecmp ("HELP", word[2+offset]))
-	{
-		hexchat_printf (ph, "%s", sysinfo_help);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("LIST", word[2+offset]))
-	{
-		list_settings ();
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("SET", word[2+offset]))
-	{
-		if (!g_ascii_strcasecmp ("", word_eol[4+offset]))
-		{
-			hexchat_printf (ph, "%s\tEnter a value!\n", name);
-			return HEXCHAT_EAT_ALL;
-		}
-		if (!g_ascii_strcasecmp ("format", word[3+offset]))
-		{
-			hexchat_pluginpref_set_str (ph, "format", word_eol[4+offset]);
-			hexchat_printf (ph, "%s\tformat is set to: %s\n", name, word_eol[4+offset]);
-		}
-		else if (!g_ascii_strcasecmp ("percent", word[3+offset]))
-		{
-			buffer = atoi (word[4+offset]);	/* don't use word_eol, numbers must not contain spaces */
-
-			if (buffer > 0 && buffer < INT_MAX)
-			{
-				hexchat_pluginpref_set_int (ph, "percent", buffer);
-				hexchat_printf (ph, "%s\tpercent is set to: %d\n", name, buffer);
-			}
-			else
-			{
-				hexchat_printf (ph, "%s\tInvalid input!\n", name);
-			}
-		}
-		else if (!g_ascii_strcasecmp ("announce", word[3+offset]))
-		{
-			buffer = atoi (word[4+offset]);	/* don't use word_eol, numbers must not contain spaces */
-
-			if (buffer > 0)
-			{
-				hexchat_pluginpref_set_int (ph, "announce", 1);
-				hexchat_printf (ph, "%s\tannounce is set to: On\n", name);
-			}
-			else
-			{
-				hexchat_pluginpref_set_int (ph, "announce", 0);
-				hexchat_printf (ph, "%s\tannounce is set to: Off\n", name);
-			}
-		}
-		else if (!g_ascii_strcasecmp ("pciids", word[3+offset]))
-		{
-			hexchat_pluginpref_set_str (ph, "pciids", word_eol[4+offset]);
-			hexchat_printf (ph, "%s\tpciids is set to: %s\n", name, word_eol[4+offset]);
-		}
-		else
-		{
-			hexchat_printf (ph, "%s\tInvalid variable name! Use 'pciids', 'format' or 'percent'!\n", name);
-			return HEXCHAT_EAT_ALL;
-		}
-
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("RESET", word[2+offset]))
-	{
-		reset_settings ();
-		hexchat_printf (ph, "%s\tSettings have been restored to defaults.\n", name);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("OS", word[2+offset]))
-	{
-		print_os (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("DISTRO", word[2+offset]))
-	{
-		print_distro (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("CPU", word[2+offset]))
-	{
-		print_cpu (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("RAM", word[2+offset]))
-	{
-		print_ram (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("DISK", word[2+offset]))
-	{
-		print_disk (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("VGA", word[2+offset]))
-	{
-		print_vga (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("SOUND", word[2+offset]))
-	{
-		print_sound (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("ETHERNET", word[2+offset]))
-	{
-		print_ethernet (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("UPTIME", word[2+offset]))
-	{
-		print_uptime (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("", word[2+offset]))
-	{
-		print_summary (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", sysinfo_help);
-		return HEXCHAT_EAT_ALL;
-	}
-}
-
-int
-hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
-{
-	ph = plugin_handle;
-	*plugin_name    = name;
-	*plugin_desc    = desc;
-	*plugin_version = version;
-	char buffer[bsize];
-
-	hexchat_hook_command (ph, "SYSINFO",	HEXCHAT_PRI_NORM,	sysinfo_cb,	sysinfo_help, NULL);
-	hexchat_hook_command (ph, "NETDATA",	HEXCHAT_PRI_NORM,	netdata_cb,	NULL, NULL);
-	hexchat_hook_command (ph, "NETSTREAM",	HEXCHAT_PRI_NORM,	netstream_cb,	NULL, NULL);
-
-	/* this is required for the very first run */
-	if (hexchat_pluginpref_get_str (ph, "pciids", buffer) == 0)
-	{
-		hexchat_pluginpref_set_str (ph, "pciids", DEFAULT_PCIIDS);
-	}
-
-	if (hexchat_pluginpref_get_str (ph, "format", buffer) == 0)
-	{
-		hexchat_pluginpref_set_str (ph, "format", DEFAULT_FORMAT);
-	}
-
-	if (hexchat_pluginpref_get_int (ph, "percent") == -1)
-	{
-		hexchat_pluginpref_set_int (ph, "percent", DEFAULT_PERCENT);
-	}
-
-	if (hexchat_pluginpref_get_int (ph, "announce") == -1)
-	{
-		hexchat_pluginpref_set_int (ph, "announce", DEFAULT_ANNOUNCE);
-	}
-
-	hexchat_command (ph, "MENU ADD \"Window/Send System Info\" \"SYSINFO\"");
-	hexchat_printf (ph, "%s plugin loaded\n", name);
-	return 1;
-}
-
-int
-hexchat_plugin_deinit (void)
-{
-	hexchat_command (ph, "MENU DEL \"Window/Display System Info\"");
-	hexchat_printf (ph, "%s plugin unloaded\n", name);
-	return 1;
-}
diff --git a/plugins/upd/upd.c b/plugins/upd/upd.c
index 6fcf3be9..c9011c04 100644
--- a/plugins/upd/upd.c
+++ b/plugins/upd/upd.c
@@ -20,260 +20,50 @@
  * THE SOFTWARE.
  */
 
-#include <windows.h>
-#include <wininet.h>
-
-#include <glib.h>
+#include <winsparkle.h>
 
 #include "hexchat-plugin.h"
 
-#define DEFAULT_DELAY 30	/* 30 seconds */
-#define DEFAULT_FREQ 360	/* 6 hours */
-#define DOWNLOAD_URL "http://dl.hexchat.net/hexchat"
+#define APPCAST_URL "https://dl.hexchat.net/appcast.xml"
 
 static hexchat_plugin *ph;   /* plugin handle */
 static char name[] = "Update Checker";
 static char desc[] = "Check for HexChat updates automatically";
-static char version[] = "4.0";
-static const char upd_help[] = "Update Checker Usage:\n  /UPDCHK, check for HexChat updates\n  /UPDCHK SET delay|freq, set startup delay or check frequency\n";
-
-static char*
-check_version ()
-{
-	HINTERNET hOpen, hConnect, hResource;
-
-	hOpen = InternetOpen (TEXT ("Update Checker"),
-						INTERNET_OPEN_TYPE_PRECONFIG,
-						NULL,
-						NULL,
-						0);
-	if (!hOpen)
-	{
-		return "Unknown";
-	}
-
-	hConnect = InternetConnect (hOpen,
-								TEXT ("raw.github.com"),
-								INTERNET_DEFAULT_HTTPS_PORT,
-								NULL,
-								NULL,
-								INTERNET_SERVICE_HTTP,
-								0,
-								0);
-	if (!hConnect)
-	{
-		InternetCloseHandle (hOpen);
-		return "Unknown";
-	}
-
-	hResource = HttpOpenRequest (hConnect,
-								TEXT ("GET"),
-								TEXT ("/hexchat/hexchat/master/win32/version.txt"),
-								TEXT ("HTTP/1.0"),
-								NULL,
-								NULL,
-								INTERNET_FLAG_SECURE | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_AUTH,
-								0);
-	if (!hResource)
-	{
-		InternetCloseHandle (hConnect);
-		InternetCloseHandle (hOpen);
-		return "Unknown";
-	}
-	else
-	{
-		static char buffer[1024];
-		char infobuffer[32];
-		int statuscode;
-
-		DWORD dwRead;
-		DWORD infolen = sizeof(infobuffer);
-
-		HttpAddRequestHeaders (hResource, TEXT ("Connection: close\r\n"), -1L, HTTP_ADDREQ_FLAG_ADD);	/* workaround for GC bug */
-		HttpSendRequest (hResource, NULL, 0, NULL, 0);
-
-		while (InternetReadFile (hResource, buffer, 1023, &dwRead))
-		{
-			if (dwRead == 0)
-			{
-				break;
-			}
-			buffer[dwRead] = 0;
-		}
-
-		HttpQueryInfo(hResource,
-					HTTP_QUERY_STATUS_CODE,
-					&infobuffer,
-					&infolen,
-					NULL);
-
-		InternetCloseHandle (hResource);
-		InternetCloseHandle (hConnect);
-		InternetCloseHandle (hOpen);
-
-		statuscode = atoi(infobuffer);
-		if (statuscode == 200)
-			return buffer;
-		else
-			return "Unknown";
-	}
-}
-
-static int
-print_version (char *word[], char *word_eol[], void *userdata)
-{
-	char *version;
-	int prevbuf;
-	int convbuf;
-
-	if (!g_ascii_strcasecmp ("HELP", word[2]))
-	{
-		hexchat_printf (ph, "%s", upd_help);
-		return HEXCHAT_EAT_HEXCHAT;
-	}
-	else if (!g_ascii_strcasecmp ("SET", word[2]))
-	{
-		if (!g_ascii_strcasecmp ("", word_eol[4]))
-		{
-			hexchat_printf (ph, "%s\tEnter a value!\n", name);
-			return HEXCHAT_EAT_HEXCHAT;
-		}
-		if (!g_ascii_strcasecmp ("delay", word[3]))
-		{
-			convbuf = atoi (word[4]);	/* don't use word_eol, numbers must not contain spaces */
-
-			if (convbuf > 0 && convbuf < INT_MAX)
-			{
-				prevbuf = hexchat_pluginpref_get_int (ph, "delay");
-				hexchat_pluginpref_set_int (ph, "delay", convbuf);
-				hexchat_printf (ph, "%s\tUpdate check startup delay is set to %d seconds (from %d).\n", name, convbuf, prevbuf);
-			}
-			else
-			{
-				hexchat_printf (ph, "%s\tInvalid input!\n", name);
-			}
-		}
-		else if (!g_ascii_strcasecmp ("freq", word[3]))
-		{
-			convbuf = atoi (word[4]);	/* don't use word_eol, numbers must not contain spaces */
-
-			if (convbuf > 0 && convbuf < INT_MAX)
-			{
-				prevbuf = hexchat_pluginpref_get_int (ph, "freq");
-				hexchat_pluginpref_set_int (ph, "freq", convbuf);
-				hexchat_printf (ph, "%s\tUpdate check frequency is set to %d minutes (from %d).\n", name, convbuf, prevbuf);
-			}
-			else
-			{
-				hexchat_printf (ph, "%s\tInvalid input!\n", name);
-			}
-		}
-		else
-		{
-			hexchat_printf (ph, "%s\tInvalid variable name! Use 'delay' or 'freq'!\n", name);
-			return HEXCHAT_EAT_HEXCHAT;
-		}
-
-		return HEXCHAT_EAT_HEXCHAT;
-	}
-	else if (!g_ascii_strcasecmp ("", word[2]))
-	{
-		version = check_version ();
-
-		if (strcmp (version, hexchat_get_info (ph, "version")) == 0)
-		{
-			hexchat_printf (ph, "%s\tYou have the latest version of HexChat installed!\n", name);
-		}
-		else if (strcmp (version, "Unknown") == 0)
-		{
-			hexchat_printf (ph, "%s\tUnable to check for HexChat updates!\n", name);
-		}
-		else
-		{
-#ifdef _WIN64 /* use this approach, the wProcessorArchitecture method always returns 0 (=x86) for some reason */
-			hexchat_printf (ph, "%s:\tA HexChat update is available! You can download it from here:\n%s/HexChat%%20%s%%20x64.exe\n", name, DOWNLOAD_URL, version);
-#else
-			hexchat_printf (ph, "%s:\tA HexChat update is available! You can download it from here:\n%s/HexChat%%20%s%%20x86.exe\n", name, DOWNLOAD_URL, version);
-#endif
-		}
-		return HEXCHAT_EAT_HEXCHAT;
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", upd_help);
-		return HEXCHAT_EAT_HEXCHAT;
-	}
-}
-
-static int
-print_version_quiet (void *userdata)
-{
-	char *version = check_version ();
-
-	/* if it's not the current version AND not network error */
-	if (!(strcmp (version, hexchat_get_info (ph, "version")) == 0) && !(strcmp (version, "Unknown") == 0))
-	{
-#ifdef _WIN64 /* use this approach, the wProcessorArchitecture method always returns 0 (=x86) for plugins for some reason */
-		hexchat_printf (ph, "%s\tA HexChat update is available! You can download it from here:\n%s/HexChat%%20%s%%20x64.exe\n", name, DOWNLOAD_URL, version);
-#else
-		hexchat_printf (ph, "%s\tA HexChat update is available! You can download it from here:\n%s/HexChat%%20%s%%20x86.exe\n", name, DOWNLOAD_URL, version);
-#endif
-		/* print update url once, then stop the timer */
-		return 0;
-	}
-	/* keep checking */
-	return 1;
-}
+static char version[] = "5.0";
+static const char upd_help[] = "Update Checker Usage:\n  /UPDCHK, check for HexChat updates\n";
 
 static int
-delayed_check (void *userdata)
+check_cmd (char *word[], char *word_eol[], void *userdata)
 {
-	int freq = hexchat_pluginpref_get_int (ph, "freq");
+	win_sparkle_check_update_with_ui ();
 
-	/* only start the timer if there's no update available during startup */
-	if (print_version_quiet (NULL))
-	{
-		/* check for updates, every 6 hours by default */
-		hexchat_hook_timer (ph, freq * 1000 * 60, print_version_quiet, NULL);
-	}
-
-	return 0;	/* run delayed_check() only once */
+	return HEXCHAT_EAT_ALL;
 }
 
 int
 hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
 {
-	int delay;
 	ph = plugin_handle;
 
 	*plugin_name = name;
 	*plugin_desc = desc;
 	*plugin_version = version;
 
-	/* these are required for the very first run */
-	delay = hexchat_pluginpref_get_int (ph, "delay");
-	if (delay == -1)
-	{
-		delay = DEFAULT_DELAY;
-		hexchat_pluginpref_set_int (ph, "delay", DEFAULT_DELAY);
-	}
-
-	if (hexchat_pluginpref_get_int (ph, "freq") == -1)
-	{
-		hexchat_pluginpref_set_int (ph, "freq", DEFAULT_FREQ);
-	}
+	win_sparkle_set_appcast_url (APPCAST_URL);
+	win_sparkle_init ();
 
-	hexchat_hook_command (ph, "UPDCHK", HEXCHAT_PRI_NORM, print_version, upd_help, NULL);
-	hexchat_hook_timer (ph, delay * 1000, delayed_check, NULL);
+	hexchat_hook_command (ph, "UPDCHK", HEXCHAT_PRI_NORM, check_cmd, upd_help, NULL);
 	hexchat_command (ph, "MENU -ishare\\download.png ADD \"Help/Check for Updates\" \"UPDCHK\"");
 	hexchat_printf (ph, "%s plugin loaded\n", name);
 
-	return 1;       /* return 1 for success */
+	return 1;
 }
 
 int
 hexchat_plugin_deinit (void)
 {
+	win_sparkle_cleanup ();
+
 	hexchat_command (ph, "MENU DEL \"Help/Check for updates\"");
 	hexchat_printf (ph, "%s plugin unloaded\n", name);
 	return 1;
diff --git a/plugins/upd/upd.vcxproj b/plugins/upd/upd.vcxproj
index e7e7785a..e39a2887 100644
--- a/plugins/upd/upd.vcxproj
+++ b/plugins/upd/upd.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,80 +20,33 @@
     <RootNamespace>upd</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hcupd</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcupd</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UPD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UPD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>..\..\src\common;$(WinSparklePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>upd.def</ModuleDefinitionFile>

-      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

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

+      <AdditionalDependencies>$(DepLibs);WinSparkle.lib;%(AdditionalDependencies)</AdditionalDependencies>

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

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;UPD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>..\..\src\common;$(WinSparklePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>upd.def</ModuleDefinitionFile>

-      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

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

+      <AdditionalDependencies>$(DepLibs);WinSparkle.lib;%(AdditionalDependencies)</AdditionalDependencies>

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

     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

@@ -102,6 +56,4 @@
     <ClCompile Include="upd.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/winamp/winamp.c b/plugins/winamp/winamp.c
index 389adcbc..d8788164 100644
--- a/plugins/winamp/winamp.c
+++ b/plugins/winamp/winamp.c
@@ -13,6 +13,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <glib.h>
 
 #include "hexchat-plugin.h"
 
@@ -21,163 +22,127 @@
 
 static hexchat_plugin *ph;   /* plugin handle */
 
-BOOL winamp_found = FALSE;
-
-int status = 0;
-
-/* Slightly modified from X-Chat's log_escape_strcpy */
-static char *
-song_strcpy (char *dest, char *src)
+static int
+winamp(char *word[], char *word_eol[], void *userdata)
 {
-	while (*src)
-	{
-		*dest = *src;
-		dest++;
-		src++;
+	HWND hwndWinamp = FindWindowW(L"Winamp v1.x",NULL);
 
-		if (*src == '%')
+	if (hwndWinamp)
+	{
+		if (!stricmp("PAUSE", word[2]))
 		{
-			dest[0] = '%';
-			dest++;
+			if (SendMessage(hwndWinamp,WM_USER, 0, 104))
+			{
+				SendMessage(hwndWinamp, WM_COMMAND, 40046, 0);
+			
+				if (SendMessage(hwndWinamp, WM_USER, 0, 104) == PLAYING)
+					hexchat_printf(ph, "Winamp: playing");
+				else
+					hexchat_printf(ph, "Winamp: paused");
+			}
 		}
-	}
-
-	dest[0] = 0;
-	return dest - 1;
-}
-
-static int
-winamp(char *word[], char *word_eol[], void *userdata)
-{
+		else if (!stricmp("STOP", word[2]))
+		{
+			SendMessage(hwndWinamp, WM_COMMAND, 40047, 0);
+			hexchat_printf(ph, "Winamp: stopped");
+		}
+		else if (!stricmp("PLAY", word[2]))
+		{
+			SendMessage(hwndWinamp, WM_COMMAND, 40045, 0);
+			hexchat_printf(ph, "Winamp: playing");
+		}
+		else if (!stricmp("NEXT", word[2]))
+		{
+			SendMessage(hwndWinamp, WM_COMMAND, 40048, 0);
+			hexchat_printf(ph, "Winamp: next playlist entry");
+		}
+		else if (!stricmp("PREV", word[2]))
+		{
+			SendMessage(hwndWinamp, WM_COMMAND, 40044, 0);
+			hexchat_printf(ph, "Winamp: previous playlist entry");
+		}
+		else if (!stricmp("START", word[2]))
+		{
+			SendMessage(hwndWinamp, WM_COMMAND, 40154, 0);
+			hexchat_printf(ph, "Winamp: playlist start");
+		}
+		else if (!word_eol[2][0])
+		{
+			wchar_t wcurrent_play[2048];
+			char *current_play, *p;
+			int len = GetWindowTextW(hwndWinamp, wcurrent_play, G_N_ELEMENTS(wcurrent_play));
 
-char current_play[2048], *p;
-char p_esc[2048];
-char cur_esc[2048];
-char truc[2048];
-HWND hwndWinamp = FindWindow("Winamp v1.x",NULL);
+			current_play = g_utf16_to_utf8 (wcurrent_play, len, NULL, NULL, NULL);
+			if (!current_play)
+			{
+				hexchat_print (ph, "Winamp: Error getting song information.");
+				return HEXCHAT_EAT_ALL;
+			}
 
-    if (hwndWinamp)
-	{
-	    {
-	        if (!stricmp("PAUSE", word[2]))
+			if (strchr(current_play, '-'))
 			{
-			   if (SendMessage(hwndWinamp,WM_USER, 0, 104))
+				/* Remove any trailing text and whitespace */
+				p = current_play + strlen(current_play) - 8;
+				while (p >= current_play)
 				{
-			   	   SendMessage(hwndWinamp, WM_COMMAND, 40046, 0);
-			
-			       if (SendMessage(hwndWinamp, WM_USER, 0, 104) == PLAYING)
-			   	       hexchat_printf(ph, "Winamp: playing");
-			       else
-                       hexchat_printf(ph, "Winamp: paused");
+					if (!strnicmp(p, "- Winamp", 8))
+						break;
+					p--;
 				}
-            }
-			else
-		        if (!stricmp("STOP", word[2]))
-			    {
-			       SendMessage(hwndWinamp, WM_COMMAND, 40047, 0);
-			       hexchat_printf(ph, "Winamp: stopped");
-			    }
-			else
-			    if (!stricmp("PLAY", word[2]))
-			    {
-			         SendMessage(hwndWinamp, WM_COMMAND, 40045, 0);
-			         hexchat_printf(ph, "Winamp: playing");
-			    }
-        	else
-
-			    if (!stricmp("NEXT", word[2]))
-			    {
-			         SendMessage(hwndWinamp, WM_COMMAND, 40048, 0);
-			         hexchat_printf(ph, "Winamp: next playlist entry");
-			    }
-			else
 
-                if (!stricmp("PREV", word[2]))
-			    {
-			         SendMessage(hwndWinamp, WM_COMMAND, 40044, 0);
-			         hexchat_printf(ph, "Winamp: previous playlist entry");
-			    }
-		    else
-
-                if (!stricmp("START", word[2]))
-			    {
-			         SendMessage(hwndWinamp, WM_COMMAND, 40154, 0);
-			         hexchat_printf(ph, "Winamp: playlist start");
-			    }
-
-		    else
-
-                if (!word_eol[2][0])
-			    {
-					GetWindowText(hwndWinamp, current_play, sizeof(current_play));
-
-					if (strchr(current_play, '-'))
-					{
-	
-					p = current_play + strlen(current_play) - 8;
-					while (p >= current_play)
-					{
-						if (!strnicmp(p, "- Winamp", 8)) break;
-							p--;
-					}
-
-					if (p >= current_play) p--;
-	
-					while (p >= current_play && *p == ' ') p--;
-						*++p=0;
-	
-	
-					p = strchr(current_play, '.') + 1;
-
- 					song_strcpy(p_esc, p);
- 					song_strcpy(cur_esc, current_play);
-	
-					if (p)
-					{
-						sprintf(truc, "me is now playing:%s", p_esc);
-					}
-					else
-					{
-						sprintf(truc, "me is now playing:%s", cur_esc);
-					}
-	
-	   				hexchat_commandf(ph, truc);
-	
-				}
-				else hexchat_print(ph, "Winamp: Nothing being played.");
+				if (p >= current_play)
+					p--;
+
+				while (p >= current_play && *p == ' ')
+					p--;
+				*++p = '\0';
+
+				/* Ignore any leading track number */
+				p = strstr (current_play, ". ");
+				if (p)
+					p += 2;
+				else
+					p = current_play;
+
+				if (*p != '\0')
+					hexchat_commandf (ph, "me is now playing: %s", p);
+				else
+					hexchat_print (ph, "Winamp: No song information found.");
+				g_free (current_play);
 			}
-		    else
-                hexchat_printf(ph, "Usage: /WINAMP [PAUSE|PLAY|STOP|NEXT|PREV|START]\n");
-         }
-
+			else
+				hexchat_print(ph, "Winamp: Nothing being played.");
+		}
+		else
+			hexchat_printf(ph, "Usage: /WINAMP [PAUSE|PLAY|STOP|NEXT|PREV|START]\n");
 	}
 	else
 	{
-       hexchat_print(ph, "Winamp not found.\n");
+		hexchat_print(ph, "Winamp not found.\n");
 	}
 	return HEXCHAT_EAT_ALL;
 }
 
 int
 hexchat_plugin_init(hexchat_plugin *plugin_handle,
-                      char **plugin_name,
-                      char **plugin_desc,
-                      char **plugin_version,
-                      char *arg)
+					  char **plugin_name,
+					  char **plugin_desc,
+					  char **plugin_version,
+					  char *arg)
 {
 	/* we need to save this for use with any hexchat_* functions */
 	ph = plugin_handle;
 
 	*plugin_name = "Winamp";
 	*plugin_desc = "Winamp plugin for HexChat";
-	*plugin_version = "0.5";
+	*plugin_version = "0.6";
 
 	hexchat_hook_command (ph, "WINAMP", HEXCHAT_PRI_NORM, winamp, "Usage: /WINAMP [PAUSE|PLAY|STOP|NEXT|PREV|START] - control Winamp or show what's currently playing", 0);
    	hexchat_command (ph, "MENU -ishare\\music.png ADD \"Window/Display Current Song (Winamp)\" \"WINAMP\"");
 
 	hexchat_print (ph, "Winamp plugin loaded\n");
 
-	return 1;       /* return 1 for success */
+	return 1;	   /* return 1 for success */
 }
 
 int
diff --git a/plugins/winamp/winamp.vcxproj b/plugins/winamp/winamp.vcxproj
index 3c0cfb34..cf839cfa 100644
--- a/plugins/winamp/winamp.vcxproj
+++ b/plugins/winamp/winamp.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,76 +20,31 @@
     <RootNamespace>winamp</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hcwinamp</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcwinamp</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WINAMP_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

-    <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <ModuleDefinitionFile>winamp.def</ModuleDefinitionFile>

-    </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;WINAMP_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup>

+    <ClCompile>

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

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>winamp.def</ModuleDefinitionFile>

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

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

     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

@@ -98,6 +54,4 @@
     <ClCompile Include="winamp.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

 </Project>
\ No newline at end of file
diff --git a/po/POTFILES.in b/po/POTFILES.in
index fa918608..5bde0376 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -10,6 +10,7 @@ src/common/inbound.c
 src/common/notify.c
 src/common/outbound.c
 src/common/plugin.c
+src/common/plugin-identd.c
 src/common/plugin-timer.c
 src/common/server.c
 src/common/servlist.c
@@ -31,6 +32,7 @@ src/fe-gtk/joind.c
 src/fe-gtk/maingui.c
 src/fe-gtk/menu.c
 src/fe-gtk/notifygui.c
+src/fe-gtk/plugin-notification.c
 src/fe-gtk/plugin-tray.c
 src/fe-gtk/plugingui.c
 src/fe-gtk/rawlog.c
@@ -41,3 +43,4 @@ src/fe-gtk/textgui.c
 src/fe-gtk/urlgrab.c
 src/fe-gtk/userlistgui.c
 src/fe-text/fe-text.c
+plugins/sysinfo/sysinfo.c
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index e9255d0c..75aa12bc 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -1,5 +1,7 @@
 ## Process this file with automake to produce Makefile.in
 
+include $(top_srcdir)/m4/clang-analyze.am
+
 noinst_LIBRARIES = libhexchatcommon.a
 
 AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(top_srcdir)
@@ -14,17 +16,16 @@ EXTRA_DIST = \
 	hexchatc.h \
 	hexchat-plugin.h \
 	history.h \
-	identd.c \
 	ignore.h \
 	inbound.h \
 	inet.h \
 	make-te.c \
 	modes.h \
-	msproxy.h \
 	network.h \
 	notify.h \
 	outbound.h \
 	plugin.h \
+	plugin-identd.h \
 	plugin-timer.h \
 	proto-irc.h \
 	server.h \
@@ -32,6 +33,7 @@ EXTRA_DIST = \
 	ssl.h \
 	ssl.c	\
 	text.h \
+	typedef.h \
 	textenums.h \
 	textevents.h \
 	textevents.in \
@@ -44,10 +46,6 @@ if USE_OPENSSL
 ssl_c = ssl.c
 endif
 
-if USE_MSPROXY
-msproxy_c = msproxy.c
-endif
-
 if USE_DBUS
 dbusdir = dbus
 libhexchatcommon_a_LIBADD =				\
@@ -62,8 +60,8 @@ endif
 noinst_PROGRAMS = make-te
 
 libhexchatcommon_a_SOURCES = cfgfiles.c chanopt.c ctcp.c dcc.c hexchat.c \
-	history.c ignore.c inbound.c marshal.c modes.c $(msproxy_c) network.c notify.c \
-	outbound.c plugin.c plugin-timer.c proto-irc.c server.c servlist.c \
+	history.c ignore.c inbound.c marshal.c modes.c network.c notify.c \
+	outbound.c plugin.c plugin-identd.c plugin-timer.c proto-irc.c server.c servlist.c \
 	$(ssl_c) text.c tree.c url.c userlist.c util.c
 libhexchatcommon_a_CFLAGS = $(LIBPROXY_CFLAGS)
 
@@ -79,6 +77,12 @@ marshal.c: $(srcdir)/marshalers.list
 	$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=_hexchat_marshal --body $< > $@
 
 
+if DO_STATIC_ANALYSIS
+analyze_plists = $(libhexchatcommon_a_SOURCES:%.c=%.plist)
+all-local: $(analyze_plists)
+MOSTLYCLEANFILES = $(analyze_plists)
+endif
+
 BUILT_SOURCES = textenums.h textevents.h marshal.c marshal.h
 
 CLEANFILES = $(BUILT_SOURCES)
diff --git a/src/common/cfgfiles.c b/src/common/cfgfiles.c
index a8bd32f9..a49e17ae 100644
--- a/src/common/cfgfiles.c
+++ b/src/common/cfgfiles.c
@@ -39,7 +39,7 @@
 #endif
 
 #define DEF_FONT "Monospace 9"
-#define DEF_FONT_ALTER "Arial Unicode MS,Lucida Sans Unicode,MS Gothic,Unifont"
+#define DEF_FONT_ALTER "Arial Unicode MS,Segoe UI Emoji,Lucida Sans Unicode,Meiryo,Symbola,Unifont"
 
 const char * const languages[LANGUAGES_LENGTH] = {
 	"af", "sq", "am", "ast", "az", "eu", "be", "bg", "ca", "zh_CN",      /*  0 ..  9 */
@@ -57,15 +57,11 @@ list_addentry (GSList ** list, char *cmd, char *name)
 	size_t name_len;
 	size_t cmd_len = 1;
 
-	/* remove <2.8.0 stuff */
-	if (!strcmp (cmd, "away") && !strcmp (name, "BACK"))
-		return;
-
 	if (cmd)
 		cmd_len = strlen (cmd) + 1;
 	name_len = strlen (name) + 1;
 
-	pop = malloc (sizeof (struct popup) + cmd_len + name_len);
+	pop = g_malloc (sizeof (struct popup) + cmd_len + name_len);
 	pop->name = (char *) pop + sizeof (struct popup);
 	pop->cmd = pop->name + name_len;
 
@@ -137,13 +133,13 @@ list_loadconf (char *file, GSList ** list, char *defaultconf)
 		abort ();
 	}
 
-	ibuf = malloc (st.st_size);
+	ibuf = g_malloc (st.st_size);
 	read (fd, ibuf, st.st_size);
 	close (fd);
 
 	list_load_from_data (list, ibuf, st.st_size);
 
-	free (ibuf);
+	g_free (ibuf);
 }
 
 void
@@ -153,7 +149,7 @@ list_free (GSList ** list)
 	while (*list)
 	{
 		data = (void *) (*list)->data;
-		free (data);
+		g_free (data);
 		*list = g_slist_remove (*list, data);
 	}
 }
@@ -170,7 +166,7 @@ list_delentry (GSList ** list, char *name)
 		if (!g_ascii_strcasecmp (name, pop->name))
 		{
 			*list = g_slist_remove (*list, pop);
-			free (pop);
+			g_free (pop);
 			return 1;
 		}
 		alist = alist->next;
@@ -211,10 +207,10 @@ cfg_get_str (char *cfg, const char *var, char *dest, int dest_len)
 		while (*cfg != 0 && *cfg != '\n')
 			cfg++;
 		if (*cfg == 0)
-			return 0;
+			return NULL;
 		cfg++;
 		if (*cfg == 0)
-			return 0;
+			return NULL;
 	}
 }
 
@@ -224,18 +220,18 @@ cfg_put_str (int fh, char *var, char *value)
 	char buf[512];
 	int len;
 
-	snprintf (buf, sizeof buf, "%s = %s\n", var, value);
+	g_snprintf (buf, sizeof buf, "%s = %s\n", var, value);
 	len = strlen (buf);
 	return (write (fh, buf, len) == len);
 }
 
 int
-cfg_put_color (int fh, int r, int g, int b, char *var)
+cfg_put_color (int fh, guint16 r, guint16 g, guint16 b, char *var)
 {
 	char buf[400];
 	int len;
 
-	snprintf (buf, sizeof buf, "%s = %04x %04x %04x\n", var, r, g, b);
+	g_snprintf (buf, sizeof buf, "%s = %04hx %04hx %04hx\n", var, r, g, b);
 	len = strlen (buf);
 	return (write (fh, buf, len) == len);
 }
@@ -249,20 +245,20 @@ cfg_put_int (int fh, int value, char *var)
 	if (value == -1)
 		value = 1;
 
-	snprintf (buf, sizeof buf, "%s = %d\n", var, value);
+	g_snprintf (buf, sizeof buf, "%s = %d\n", var, value);
 	len = strlen (buf);
 	return (write (fh, buf, len) == len);
 }
 
 int
-cfg_get_color (char *cfg, char *var, int *r, int *g, int *b)
+cfg_get_color (char *cfg, char *var, guint16 *r, guint16 *g, guint16 *b)
 {
 	char str[128];
 
 	if (!cfg_get_str (cfg, var, str, sizeof (str)))
 		return 0;
 
-	sscanf (str, "%04x %04x %04x", r, g, b);
+	sscanf (str, "%04hx %04hx %04hx", r, g, b);
 	return 1;
 }
 
@@ -312,9 +308,7 @@ get_xdir (void)
 
 		if (portable_mode () || SHGetKnownFolderPath (&FOLDERID_RoamingAppData, 0, NULL, &roaming_path_wide) != S_OK)
 		{
-			char *path;
-
-			path = g_win32_get_package_installation_directory_of_module (NULL);
+			char *path = g_win32_get_package_installation_directory_of_module (NULL);
 			if (path)
 			{
 				xdir = g_build_filename (path, "config", NULL);
@@ -440,6 +434,7 @@ const struct prefs vars[] =
 	{"gui_tab_dots", P_OFFINT (hex_gui_tab_dots), TYPE_BOOL},
 	{"gui_tab_icons", P_OFFINT (hex_gui_tab_icons), TYPE_BOOL},
 	{"gui_tab_layout", P_OFFINT (hex_gui_tab_layout), TYPE_INT},
+	{"gui_tab_middleclose", P_OFFINT (hex_gui_tab_middleclose), TYPE_BOOL},
 	{"gui_tab_newtofront", P_OFFINT (hex_gui_tab_newtofront), TYPE_INT},
 	{"gui_tab_pos", P_OFFINT (hex_gui_tab_pos), TYPE_INT},
 	{"gui_tab_scrollchans", P_OFFINT (hex_gui_tab_scrollchans), TYPE_BOOL},
@@ -482,11 +477,11 @@ const struct prefs vars[] =
 	{"gui_win_width", P_OFFINT (hex_gui_win_width), TYPE_INT},
 
 	{"identd", P_OFFINT (hex_identd), TYPE_BOOL},
+	{"identd_port", P_OFFINT (hex_identd_port), TYPE_INT},
 
 	{"input_balloon_chans", P_OFFINT (hex_input_balloon_chans), TYPE_BOOL},
 	{"input_balloon_hilight", P_OFFINT (hex_input_balloon_hilight), TYPE_BOOL},
 	{"input_balloon_priv", P_OFFINT (hex_input_balloon_priv), TYPE_BOOL},
-	{"input_balloon_time", P_OFFINT (hex_input_balloon_time), TYPE_INT},
 	{"input_beep_chans", P_OFFINT (hex_input_beep_chans), TYPE_BOOL},
 	{"input_beep_hilight", P_OFFINT (hex_input_beep_hilight), TYPE_BOOL},
 	{"input_beep_priv", P_OFFINT (hex_input_beep_priv), TYPE_BOOL},
@@ -590,10 +585,10 @@ const struct prefs vars[] =
 	{0, 0, 0},
 };
 
-static char *
+static const char *
 convert_with_fallback (const char *str, const char *fallback)
 {
-	char *utf;
+	const char *utf;
 
 #ifndef WIN32
 	/* On non-Windows, g_get_user_name and g_get_real_name return a string in system locale, so convert it to utf-8. */
@@ -652,7 +647,7 @@ get_default_language (void)
 
 	if (lang_no >= 0)
 	{
-		free (lang);
+		g_free (lang);
 		return lang_no;
 	}
 
@@ -661,7 +656,7 @@ get_default_language (void)
 
 	lang_no = find_language_number (lang);
 
-	free (lang);
+	g_free (lang);
 
 	return lang_no >= 0 ? lang_no : find_language_number ("en");
 }
@@ -703,8 +698,8 @@ get_default_spell_languages (void)
 				}
 			}
 		}
-		if (last != NULL)
-			g_free(last);
+
+		g_free (last);
 
 		if (lang_list[0])
 			return g_strdup (ret);
@@ -765,6 +760,7 @@ load_default_config(void)
 	prefs.hex_gui_tab_chans = 1;
 	prefs.hex_gui_tab_dialogs = 1;
 	prefs.hex_gui_tab_icons = 1;
+	prefs.hex_gui_tab_middleclose = 1;
 	prefs.hex_gui_tab_server = 1;
 	prefs.hex_gui_tab_sort = 1;
 	prefs.hex_gui_topicbar = 1;
@@ -776,7 +772,6 @@ load_default_config(void)
 	prefs.hex_gui_ulist_resizable = 1;
 	prefs.hex_gui_ulist_style = 1;
 	prefs.hex_gui_win_save = 1;
-	prefs.hex_identd = 1;
 	prefs.hex_input_flash_hilight = 1;
 	prefs.hex_input_flash_priv = 1;
 	prefs.hex_input_tray_hilight = 1;
@@ -832,7 +827,6 @@ load_default_config(void)
 	prefs.hex_gui_ulist_pos = 3;
 	prefs.hex_gui_win_height = 400;
 	prefs.hex_gui_win_width = 640;
-	prefs.hex_input_balloon_time = 20;
 	prefs.hex_irc_ban_type = 1;
 	prefs.hex_irc_join_delay = 5;
 	prefs.hex_net_reconnect_delay = 10;
@@ -847,7 +841,7 @@ load_default_config(void)
 #ifdef WIN32
 	if (portable_mode () || SHGetKnownFolderPath (&FOLDERID_Downloads, 0, NULL, &roaming_path_wide) != S_OK)
 	{
-		snprintf (prefs.hex_dcc_dir, sizeof (prefs.hex_dcc_dir), "%s\\downloads", get_xdir ());
+		g_snprintf (prefs.hex_dcc_dir, sizeof (prefs.hex_dcc_dir), "%s\\downloads", get_xdir ());
 	}
 	else
 	{
@@ -861,34 +855,36 @@ load_default_config(void)
 #else
 	if (g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD))
 	{
-		strcpy (prefs.hex_dcc_dir, g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD));
+		safe_strcpy (prefs.hex_dcc_dir, g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD), sizeof(prefs.hex_dcc_dir));
 	}
 	else
 	{
-		strcpy (prefs.hex_dcc_dir, g_build_filename (g_get_home_dir (), "Downloads", NULL));
+		char *download_dir = g_build_filename (g_get_home_dir (), "Downloads", NULL);
+		safe_strcpy (prefs.hex_dcc_dir, download_dir, sizeof(prefs.hex_dcc_dir));
+		g_free (download_dir);
 	}
 #endif
 	strcpy (prefs.hex_gui_ulist_doubleclick, "QUERY %s");
 	strcpy (prefs.hex_input_command_char, "/");
-	strcpy (prefs.hex_irc_logmask, g_build_filename ("%n", "%c.log", NULL));
-	strcpy (prefs.hex_irc_nick1, username);
-	strcpy (prefs.hex_irc_nick2, username);
-	strcat (prefs.hex_irc_nick2, "_");
-	strcpy (prefs.hex_irc_nick3, username);
-	strcat (prefs.hex_irc_nick3, "__");
+	strcpy (prefs.hex_irc_logmask, "%n"G_DIR_SEPARATOR_S"%c.log");
+	safe_strcpy (prefs.hex_irc_nick1, username, sizeof(prefs.hex_irc_nick1));
+	safe_strcpy (prefs.hex_irc_nick2, username, sizeof(prefs.hex_irc_nick2));
+	g_strlcat (prefs.hex_irc_nick2, "_", sizeof(prefs.hex_irc_nick2));
+	safe_strcpy (prefs.hex_irc_nick3, username, sizeof(prefs.hex_irc_nick3));
+	g_strlcat (prefs.hex_irc_nick3, "__", sizeof(prefs.hex_irc_nick3));
 	strcpy (prefs.hex_irc_no_hilight, "NickServ,ChanServ,InfoServ,N,Q");
-	strcpy (prefs.hex_irc_part_reason, _("Leaving"));
-	strcpy (prefs.hex_irc_quit_reason, prefs.hex_irc_part_reason);
-	strcpy (prefs.hex_irc_real_name, realname);
-	strcpy (prefs.hex_irc_user_name, username);
+	safe_strcpy (prefs.hex_irc_part_reason, _("Leaving"), sizeof(prefs.hex_irc_part_reason));
+	safe_strcpy (prefs.hex_irc_quit_reason, prefs.hex_irc_part_reason, sizeof(prefs.hex_irc_quit_reason));
+	safe_strcpy (prefs.hex_irc_real_name, realname, sizeof(prefs.hex_irc_real_name));
+	safe_strcpy (prefs.hex_irc_user_name, username, sizeof(prefs.hex_irc_user_name));
 	strcpy (prefs.hex_stamp_log_format, "%b %d %H:%M:%S ");
 	strcpy (prefs.hex_stamp_text_format, "[%H:%M:%S] ");
 
 	font = fe_get_default_font ();
 	if (font)
 	{
-		strcpy (prefs.hex_text_font, font);
-		strcpy (prefs.hex_text_font_main, font);
+		safe_strcpy (prefs.hex_text_font, font, sizeof(prefs.hex_text_font));
+		safe_strcpy (prefs.hex_text_font_main, font, sizeof(prefs.hex_text_font_main));
 	}
 	else
 	{
@@ -898,7 +894,7 @@ load_default_config(void)
 
 	strcpy (prefs.hex_text_font_alternative, DEF_FONT_ALTER);
 	langs = get_default_spell_languages ();
-	strcpy (prefs.hex_text_spell_langs, langs);
+	safe_strcpy (prefs.hex_text_spell_langs, langs, sizeof(prefs.hex_text_spell_langs));
 
 
 	/* private variables */
@@ -1228,7 +1224,7 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 				if (erase || *val)
 				{
 					/* save the previous value until we print it out */
-					prev_string = (char*) malloc (vars[i].len + 1);
+					prev_string = g_malloc (vars[i].len + 1);
 					strncpy (prev_string, (char *) &prefs + vars[i].offset, vars[i].len);
 
 					/* update the variable */
@@ -1240,7 +1236,7 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 						PrintTextf (sess, "%s set to: %s (was: %s)\n", var, (char *) &prefs + vars[i].offset, prev_string);
 					}
 
-					free (prev_string);
+					g_free (prev_string);
 				}
 				else
 				{
@@ -1315,7 +1311,7 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 }
 
 int
-hexchat_open_file (char *file, int flags, int mode, int xof_flags)
+hexchat_open_file (const char *file, int flags, int mode, int xof_flags)
 {
 	char *buf;
 	int fd;
@@ -1351,7 +1347,7 @@ hexchat_fopen_file (const char *file, const char *mode, int xof_flags)
 	FILE *fh;
 
 	if (xof_flags & XOF_FULLPATH)
-		return fopen (file, mode);
+		return g_fopen (file, mode);
 
 	buf = g_build_filename (get_xdir (), file, NULL);
 	fh = g_fopen (buf, mode);
diff --git a/src/common/cfgfiles.h b/src/common/cfgfiles.h
index 8b996ca0..b421884a 100644
--- a/src/common/cfgfiles.h
+++ b/src/common/cfgfiles.h
@@ -34,8 +34,8 @@ int cfg_get_bool (char *var);
 int cfg_get_int_with_result (char *cfg, char *var, int *result);
 int cfg_get_int (char *cfg, char *var);
 int cfg_put_int (int fh, int value, char *var);
-int cfg_get_color (char *cfg, char *var, int *r, int *g, int *b);
-int cfg_put_color (int fh, int r, int g, int b, char *var);
+int cfg_get_color (char *cfg, char *var, guint16 *r, guint16 *g, guint16 *b);
+int cfg_put_color (int fh, guint16 r, guint16 g, guint16 b, char *var);
 char *get_xdir (void);
 int check_config_dir (void);
 void load_default_config (void);
@@ -48,7 +48,7 @@ void list_loadconf (char *file, GSList ** list, char *defaultconf);
 int list_delentry (GSList ** list, char *name);
 void list_addentry (GSList ** list, char *cmd, char *name);
 int cmd_set (session *sess, char *tbuf, char *word[], char *word_eol[]);
-int hexchat_open_file (char *file, int flags, int mode, int xof_flags);
+int hexchat_open_file (const char *file, int flags, int mode, int xof_flags);
 FILE *hexchat_fopen_file (const char *file, const char *mode, int xof_flags);
 
 #define XOF_DOMODE 1
diff --git a/src/common/chanopt.c b/src/common/chanopt.c
index 820a31fb..7bd66b4a 100644
--- a/src/common/chanopt.c
+++ b/src/common/chanopt.c
@@ -119,7 +119,7 @@ chanopt_command (session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (!quiet)
 		PrintTextf (sess, "\002Network\002: %s \002Channel\002: %s\n",
 						sess->server->network ? server_get_network (sess->server, TRUE) : _("<none>"),
-						sess->channel[0] ? sess->channel : _("<none>"));
+						sess->session_name[0] ? sess->session_name : _("<none>"));
 
 	while (i < sizeof (chanopt) / sizeof (channel_options))
 	{
@@ -208,7 +208,7 @@ chanopt_find (char *network, char *channel, gboolean add_new)
 		return NULL;
 
 	/* allocate a new one */
-	co = g_malloc0 (sizeof (chanopt_in_memory));
+	co = g_new0 (chanopt_in_memory, 1);
 	co->channel = g_strdup (channel);
 	co->network = g_strdup (network);
 
@@ -298,7 +298,7 @@ chanopt_load (session *sess)
 	chanopt_in_memory *co;
 	char *network;
 
-	if (sess->channel[0] == 0)
+	if (sess->session_name[0] == 0)
 		return;
 
 	network = server_get_network (sess->server, FALSE);
@@ -311,7 +311,7 @@ chanopt_load (session *sess)
 		chanopt_load_all ();
 	}
 
-	co = chanopt_find (network, sess->channel, FALSE);
+	co = chanopt_find (network, sess->session_name, FALSE);
 	if (!co)
 		return;
 
@@ -334,7 +334,7 @@ chanopt_save (session *sess)
 	chanopt_in_memory *co;
 	char *network;
 
-	if (sess->channel[0] == 0)
+	if (sess->session_name[0] == 0)
 		return;
 
 	network = server_get_network (sess->server, FALSE);
@@ -343,7 +343,7 @@ chanopt_save (session *sess)
 
 	/* 2. reconcile sess with what we loaded from disk */
 
-	co = chanopt_find (network, sess->channel, TRUE);
+	co = chanopt_find (network, sess->session_name, TRUE);
 
 	i = 0;
 	while (i < sizeof (chanopt) / sizeof (channel_options))
@@ -368,10 +368,10 @@ chanopt_save_one_channel (chanopt_in_memory *co, int fh)
 	char buf[256];
 	guint8 val;
 
-	snprintf (buf, sizeof (buf), "%s = %s\n", "network", co->network);
+	g_snprintf (buf, sizeof (buf), "%s = %s\n", "network", co->network);
 	write (fh, buf, strlen (buf));
 
-	snprintf (buf, sizeof (buf), "%s = %s\n", "channel", co->channel);
+	g_snprintf (buf, sizeof (buf), "%s = %s\n", "channel", co->channel);
 	write (fh, buf, strlen (buf));
 
 	i = 0;
@@ -380,7 +380,7 @@ chanopt_save_one_channel (chanopt_in_memory *co, int fh)
 		val = G_STRUCT_MEMBER (guint8, co, chanopt[i].offset);
 		if (val != SET_DEFAULT)
 		{
-			snprintf (buf, sizeof (buf), "%s = %d\n", chanopt[i].name, val);
+			g_snprintf (buf, sizeof (buf), "%s = %d\n", chanopt[i].name, val);
 			write (fh, buf, strlen (buf));
 		}
 		i++;
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
index 02449340..28a4da11 100644
--- a/src/common/common.vcxproj
+++ b/src/common/common.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>StaticLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -20,16 +21,15 @@
     <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="marshal.h" />

+    <ClInclude Include="$(HexChatLib)marshal.h" />

     <ClInclude Include="modes.h" />

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

     <ClInclude Include="network.h" />

     <ClInclude Include="notify.h" />

     <ClInclude Include="outbound.h" />

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

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

     <ClInclude Include="plugin.h" />

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

@@ -37,8 +37,8 @@
     <ClInclude Include="servlist.h" />

     <ClInclude Include="ssl.h" />

     <ClInclude Include="text.h" />

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

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

+    <ClInclude Include="$(HexChatLib)textenums.h" />

+    <ClInclude Include="$(HexChatLib)textevents.h" />

     <ClInclude Include="tree.h" />

     <ClInclude Include="typedef.h" />

     <ClInclude Include="url.h" />

@@ -54,12 +54,11 @@
     <ClCompile Include="ctcp.c" />

     <ClCompile Include="dcc.c" />

     <ClCompile Include="history.c" />

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

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

     <ClCompile Include="ignore.c" />

     <ClCompile Include="inbound.c" />

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

+    <ClCompile Include="$(HexChatLib)marshal.c" />

     <ClCompile Include="modes.c" />

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

     <ClCompile Include="network.c" />

     <ClCompile Include="notify.c" />

     <ClCompile Include="outbound.c" />

@@ -78,7 +77,7 @@
   </ItemGroup>

   <ItemGroup>

     <None Include="..\..\win32\config.h.tt" />

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

+    <ClInclude Include="$(HexChatLib)config.h" />

   </ItemGroup>

   <PropertyGroup Label="Globals">

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

@@ -86,85 +85,36 @@
     <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>

-  </PropertyGroup>

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

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

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

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

+  <PropertyGroup>

+    <OutDir>$(HexChatLib)</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

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

-      <AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

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

     </ClCompile>

-    <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-    </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

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

-      <AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

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

       <DisableSpecificWarnings>4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>

     </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>

   <ItemDefinitionGroup>

     <PreBuildEvent>

       <Command><![CDATA[

 SET SOLUTIONDIR=$(SolutionDir)..\

-powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\win32\config.h.tt" "$(SolutionDir)..\config.h"

-"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --header "$(ProjectDir)marshalers.list" > "$(ProjectDir)marshal.h"

-"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --body "$(ProjectDir)marshalers.list" > "$(ProjectDir)marshal.c"

+"$(HexChatLib)make-te.exe" < "$(ProjectDir)textevents.in" > "$(HexChatLib)textevents.h" 2> "$(HexChatLib)textenums.h"

+powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\win32\config.h.tt" "$(HexChatLib)config.h"

+"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --header "$(ProjectDir)marshalers.list" > "$(HexChatLib)marshal.h"

+"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --body "$(ProjectDir)marshalers.list" > "$(HexChatLib)marshal.c"

 

       ]]></Command>

     </PreBuildEvent>

   </ItemDefinitionGroup>

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

diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters
index c2d0ce5d..79e64cb4 100644
--- a/src/common/common.vcxproj.filters
+++ b/src/common/common.vcxproj.filters
@@ -29,9 +29,6 @@
     <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>

@@ -44,9 +41,6 @@
     <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>

@@ -77,10 +71,10 @@
     <ClInclude Include="text.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="textenums.h">

+    <ClInclude Include="$(HexChatLib)textenums.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="textevents.h">

+    <ClInclude Include="$(HexChatLib)textevents.h">

       <Filter>Header Files</Filter>

     </ClInclude>

     <ClInclude Include="tree.h">

@@ -104,13 +98,16 @@
     <ClInclude Include="hexchat-plugin.h">

       <Filter>Header Files</Filter>

     </ClInclude>

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

+    <ClInclude Include="$(HexChatLib)config.h">

       <Filter>Header Files</Filter>

     </ClInclude>

     <ClInclude Include="typedef.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="marshal.h">

+    <ClInclude Include="$(HexChatLib)marshal.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

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

       <Filter>Header Files</Filter>

     </ClInclude>

   </ItemGroup>

@@ -130,9 +127,6 @@
     <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>

@@ -142,9 +136,6 @@
     <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>

@@ -190,11 +181,14 @@
     <ClCompile Include="hexchat.c">

       <Filter>Source Files</Filter>

     </ClCompile>

-    <ClCompile Include="marshal.c">

+    <ClCompile Include="$(HexChatLib)marshal.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

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

       <Filter>Source Files</Filter>

     </ClCompile>

   </ItemGroup>

   <ItemGroup>

     <None Include="..\..\win32\config.h.tt" />

   </ItemGroup>

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

diff --git a/src/common/ctcp.c b/src/common/ctcp.c
index b4fb55b7..bf0a8e7f 100644
--- a/src/common/ctcp.c
+++ b/src/common/ctcp.c
@@ -44,12 +44,12 @@ ctcp_reply (session *sess, char *nick, char *word[], char *word_eol[],
 {
 	char tbuf[4096];	/* can receive 2048 from IRC, so this is enough */
 
-	conf = strdup (conf);
+	conf = g_strdup (conf);
 	/* process %C %B etc */
 	check_special_chars (conf, TRUE);
 	auto_insert (tbuf, sizeof (tbuf), conf, word, word_eol, "", "", word_eol[5],
 					 server_get_network (sess->server, TRUE), "", "", nick, "");
-	free (conf);
+	g_free (conf);
 	handle_command (sess, tbuf, FALSE);
 }
 
@@ -139,10 +139,10 @@ ctcp_handle (session *sess, char *to, char *nick, char *ip,
 	if (!g_ascii_strcasecmp (msg, "VERSION") && !prefs.hex_irc_hide_version)
 	{
 #ifdef WIN32
-		snprintf (outbuf, sizeof (outbuf), "VERSION HexChat "PACKAGE_VERSION" [x%d] / %s",
+		g_snprintf (outbuf, sizeof (outbuf), "VERSION HexChat "PACKAGE_VERSION" [x%d] / %s",
 					 get_cpu_arch (), get_sys_str (1));
 #else
-		snprintf (outbuf, sizeof (outbuf), "VERSION HexChat "PACKAGE_VERSION" / %s",
+		g_snprintf (outbuf, sizeof (outbuf), "VERSION HexChat "PACKAGE_VERSION" / %s",
 					 get_sys_str (1));
 #endif
 		serv->p_nctcp (serv, nick, outbuf);
diff --git a/src/common/dbus/dbus-client.c b/src/common/dbus/dbus-client.c
index e507883d..bbbe10e8 100644
--- a/src/common/dbus/dbus-client.c
+++ b/src/common/dbus/dbus-client.c
@@ -19,6 +19,8 @@
  * xclaesse@gmail.com
  */
 
+#include "config.h"
+
 #define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include <dbus/dbus-glib.h>
 #include "dbus-client.h"
@@ -91,7 +93,7 @@ hexchat_remote (void)
 	g_object_unref (dbus);
 
 	if (!hexchat_running) {
-		//dbus_g_connection_unref (connection);
+		/* dbus_g_connection_unref (connection); */
 		return;
 	}
 
diff --git a/src/common/dbus/dbus-plugin.c b/src/common/dbus/dbus-plugin.c
index ee8accfe..1afd9ef0 100644
--- a/src/common/dbus/dbus-plugin.c
+++ b/src/common/dbus/dbus-plugin.c
@@ -26,6 +26,7 @@
 #include <dbus/dbus-glib-lowlevel.h>
 #include <glib/gi18n.h>
 #include "hexchat-plugin.h"
+#include "dbus-plugin.h"
 
 #define PNAME _("remote access")
 #define PDESC _("plugin for remote access using DBUS")
@@ -365,6 +366,7 @@ remote_object_connect (RemoteObject *obj,
 	static guint count = 0;
 	char *sender, *path;
 	RemoteObject *remote_object;
+	gchar count_buffer[15];
 	
 	sender = dbus_g_method_get_sender (context);
 	remote_object = g_hash_table_lookup (clients, sender);
@@ -373,7 +375,8 @@ remote_object_connect (RemoteObject *obj,
 		g_free (sender);
 		return TRUE;
 	}
-	path = g_build_filename (DBUS_OBJECT_PATH, count++, NULL);
+	g_snprintf(count_buffer, sizeof(count_buffer), "%u", count++);
+	path = g_build_filename (DBUS_OBJECT_PATH, count_buffer, NULL);
 	remote_object = g_object_new (REMOTE_TYPE_OBJECT, NULL);
 	remote_object->dbus_path = path;
 	remote_object->filename = g_path_get_basename (filename);
diff --git a/src/common/dbus/example.c b/src/common/dbus/example.c
index c3ad4ff3..0228b884 100644
--- a/src/common/dbus/example.c
+++ b/src/common/dbus/example.c
@@ -33,7 +33,7 @@ guint command_id;
 guint server_id;
 
 static void
-write_error (char *message,
+write_error (const char *message,
 	     GError **error)
 {
 	if (error == NULL || *error == NULL) {
diff --git a/src/common/dcc.c b/src/common/dcc.c
index 169a0f76..881bcf78 100644
--- a/src/common/dcc.c
+++ b/src/common/dcc.c
@@ -23,8 +23,9 @@
  * Jim Seymour (jseymour@LinxNet.com)
  */
 
-/* we only use 32 bits, but without this define, you get only 31! */
+/* Required to make lseek use off64_t, but doesn't work on Windows */
 #define _FILE_OFFSET_BITS 64
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -57,13 +58,9 @@
 #include "url.h"
 #include "hexchatc.h"
 
-#ifdef USE_DCC64
-#define BIG_STR_TO_INT(x) strtoull(x,NULL,10)
+/* Setting _FILE_OFFSET_BITS to 64 doesn't change lseek to use off64_t on Windows, so override lseek to the version that does */
 #ifdef WIN32
-#define stat _stat64
-#endif
-#else
-#define BIG_STR_TO_INT(x) strtoul(x,NULL,10)
+#define lseek _lseeki64
 #endif
 
 static char *dcctypes[] = { "SEND", "RECV", "CHAT", "CHAT" };
@@ -78,7 +75,7 @@ struct dccstat_info dccstat[] = {
 };
 
 static int dcc_global_throttle;	/* 0x1 = sends, 0x2 = gets */
-/*static*/ int dcc_sendcpssum, dcc_getcpssum;
+static gint64 dcc_sendcpssum, dcc_getcpssum;
 
 static struct DCC *new_dcc (void);
 static void dcc_close (struct DCC *dcc, int dccstat, int destroy);
@@ -127,11 +124,12 @@ static void
 dcc_calc_cps (struct DCC *dcc)
 {
 	GTimeVal now;
-	int oldcps;
+	gint64 oldcps;
 	double timediff, startdiff;
 	int glob_throttle_bit, wasthrottled;
-	int *cpssum, glob_limit;
-	DCC_SIZE pos, posdiff;
+	gint64 *cpssum;
+	int glob_limit;
+	goffset pos, posdiff;
 
 	g_get_current_time (&now);
 
@@ -169,8 +167,7 @@ dcc_calc_cps (struct DCC *dcc)
 
 		posdiff = pos - dcc->lastcpspos;
 		oldcps = dcc->cps;
-		dcc->cps = ((double) posdiff / timediff) * (timediff / startdiff) +
-			(double) dcc->cps * (1.0 - (timediff / startdiff));
+		dcc->cps = (gint64) ((posdiff / timediff) * (timediff / startdiff) + dcc->cps * (1.0 - (timediff / startdiff)));
 
 		*cpssum += dcc->cps - oldcps;
 	}
@@ -312,7 +309,7 @@ dcc_lookup_proxy (char *host, struct sockaddr_in *addr)
 			memcpy (&addr->sin_addr, &cache_addr, 4);
 			return TRUE;
 		}
-		free (cache_host);
+		g_free (cache_host);
 		cache_host = NULL;
 	}
 
@@ -321,7 +318,7 @@ dcc_lookup_proxy (char *host, struct sockaddr_in *addr)
 	{
 		memcpy (&addr->sin_addr, h->h_addr, 4);
 		memcpy (&cache_addr, h->h_addr, 4);
-		cache_host = strdup (host);
+		cache_host = g_strdup (host);
 		/* cppcheck-suppress memleak */
 		return TRUE;
 	}
@@ -409,7 +406,7 @@ dcc_close (struct DCC *dcc, int dccstat, int destroy)
 	dcc->dccstat = dccstat;
 	if (dcc->dccchat)
 	{
-		free (dcc->dccchat);
+		g_free (dcc->dccchat);
 		dcc->dccchat = NULL;
 	}
 
@@ -417,14 +414,11 @@ dcc_close (struct DCC *dcc, int dccstat, int destroy)
 	{
 		dcc_list = g_slist_remove (dcc_list, dcc);
 		fe_dcc_remove (dcc);
-		if (dcc->proxy)
-			free (dcc->proxy);
-		if (dcc->file)
-			free (dcc->file);
-		if (dcc->destfile)
-			g_free (dcc->destfile);
-		free (dcc->nick);
-		free (dcc);
+		g_free (dcc->proxy);
+		g_free (dcc->file);
+		g_free (dcc->destfile);
+		g_free (dcc->nick);
+		g_free (dcc);
 		return;
 	}
 
@@ -493,14 +487,13 @@ dcc_write_chat (char *nick, char *text)
 	if (dcc && dcc->dccstat == STAT_ACTIVE)
 	{
 		len = strlen (text);
-		tcp_send_real (NULL, dcc->sok, dcc->serv->encoding, dcc->serv->using_irc,
-							text, len);
+		tcp_send_real (NULL, dcc->sok, dcc->serv->write_converter, text, len);
 		send (dcc->sok, "\n", 1, 0);
 		dcc->size += len;
 		fe_dcc_update (dcc);
 		return dcc;
 	}
-	return 0;
+	return NULL;
 }
 
 /* returns: 0 - ok
@@ -512,36 +505,11 @@ dcc_chat_line (struct DCC *dcc, char *line)
 	session *sess;
 	char *word[PDIWORDS];
 	char *po;
-	char *utf;
-	char *conv;
 	int ret, i;
-	int len;
-	gsize utf_len;
 	char portbuf[32];
 	message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT;
 
-	len = strlen (line);
-	if (dcc->serv->using_cp1255)
-		len++;	/* include the NUL terminator */
-
-	if (dcc->serv->using_irc) /* using "IRC" encoding (CP1252/UTF-8 hybrid) */
-		utf = NULL;
-	else if (dcc->serv->encoding == NULL)     /* system */
-		utf = g_locale_to_utf8 (line, len, NULL, &utf_len, NULL);
-	else
-		utf = g_convert (line, len, "UTF-8", dcc->serv->encoding, 0, &utf_len, 0);
-
-	if (utf)
-	{
-		line = utf;
-		len = utf_len;
-	}
-
-	if (dcc->serv->using_cp1255 && len > 0)
-		len--;
-
-	/* we really need valid UTF-8 now */
-	conv = text_validate (&line, &len);
+	line = text_convert_invalid (line, -1, dcc->serv->read_converter, unicode_fallback_string, NULL);
 
 	sess = find_dialog (dcc->serv, dcc->nick);
 	if (!sess)
@@ -562,24 +530,18 @@ dcc_chat_line (struct DCC *dcc, char *line)
 	/* did the plugin close it? */
 	if (!g_slist_find (dcc_list, dcc))
 	{
-		if (utf)
-			g_free (utf);
-		if (conv)
-			g_free (conv);
+		g_free (line);
 		return 1;
 	}
 
 	/* did the plugin eat the event? */
 	if (ret)
 	{
-		if (utf)
-			g_free (utf);
-		if (conv)
-			g_free (conv);
+		g_free (line);
 		return 0;
 	}
 
-	url_check_line (line, len);
+	url_check_line (line);
 
 	if (line[0] == 1 && !g_ascii_strncasecmp (line + 1, "ACTION", 6))
 	{
@@ -592,10 +554,7 @@ dcc_chat_line (struct DCC *dcc, char *line)
 	{
 		inbound_privmsg (dcc->serv, dcc->nick, "", line, FALSE, &no_tags);
 	}
-	if (utf)
-		g_free (utf);
-	if (conv)
-		g_free (conv);
+	g_free (line);
 	return 0;
 }
 
@@ -700,20 +659,26 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 
 		if (dcc->resumable)
 		{
-			dcc->fp = g_open (dcc->destfile, O_WRONLY | O_APPEND | OFLAGS, 0);
+			gchar *filename_fs = g_filename_from_utf8(dcc->destfile, -1, NULL, NULL, NULL);
+			dcc->fp = g_open(dcc->destfile, O_WRONLY | O_APPEND | OFLAGS, 0);
+			g_free (filename_fs);
+
 			dcc->pos = dcc->resumable;
 			dcc->ack = dcc->resumable;
-		} else
+		}
+		else
 		{
+			gchar *filename_fs;
+
 			if (g_access (dcc->destfile, F_OK) == 0)
 			{
 				n = 0;
 				do
 				{
 					n++;
-					snprintf (buf, sizeof (buf), "%s.%d", dcc->destfile, n);
+					g_snprintf (buf, sizeof (buf), "%s.%d", dcc->destfile, n);
 				}
-				while (access (buf, F_OK) == 0);
+				while (g_access (buf, F_OK) == 0);
 
 				old = dcc->destfile;
 				dcc->destfile = g_strdup (buf);
@@ -722,9 +687,10 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 								 old, dcc->destfile, NULL, NULL, 0);
 				g_free (old);
 			}
-			dcc->fp =
-				g_open (dcc->destfile, OFLAGS | O_TRUNC | O_WRONLY | O_CREAT,
-						prefs.hex_dcc_permissions);
+
+			filename_fs = g_filename_from_utf8 (dcc->destfile, -1, NULL, NULL, NULL);
+			dcc->fp = g_open (filename_fs, OFLAGS | O_TRUNC | O_WRONLY | O_CREAT, prefs.hex_dcc_permissions);
+			g_free (filename_fs);
 		}
 	}
 	if (dcc->fp == -1)
@@ -792,7 +758,7 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 			dcc_close (dcc, STAT_DONE, FALSE);
 			dcc_calc_average_cps (dcc);	/* this must be done _after_ dcc_close, or dcc_remove_from_sum will see the wrong value in dcc->cps */
 			/* cppcheck-suppress deallocuse */
-			sprintf (buf, "%d", dcc->cps);
+			sprintf (buf, "%" G_GINT64_FORMAT, dcc->cps);
 			EMIT_SIGNAL (XP_TE_DCCRECVCOMP, dcc->serv->front_session,
 							 dcc->file, dcc->destfile, dcc->nick, buf, 0);
 			return TRUE;
@@ -870,7 +836,7 @@ dcc_connect_finished (GIOChannel *source, GIOCondition condition, struct DCC *dc
 		return TRUE;
 
 	dcc->dccstat = STAT_ACTIVE;
-	snprintf (host, sizeof host, "%s:%d", net_ip (dcc->addr), dcc->port);
+	g_snprintf (host, sizeof host, "%s:%d", net_ip (dcc->addr), dcc->port);
 
 	switch (dcc->type)
 	{
@@ -893,8 +859,7 @@ dcc_connect_finished (GIOChannel *source, GIOCondition condition, struct DCC *dc
 		dcc_open_query (dcc->serv, dcc->nick);
 	case TYPE_CHATRECV:	/* normal chat */
 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read_chat, dcc);
-		dcc->dccchat = malloc (sizeof (struct dcc_chat));
-		dcc->dccchat->pos = 0;
+		dcc->dccchat = g_new0 (struct dcc_chat, 1);
 		EMIT_SIGNAL (XP_TE_DCCCONCHAT, dcc->serv->front_session,
 						 dcc->nick, host, NULL, NULL, 0);
 		break;
@@ -990,7 +955,7 @@ dcc_wingate_proxy_traverse (GIOChannel *source, GIOCondition condition, struct D
 	struct proxy_state *proxy = dcc->proxy;
 	if (proxy->phase == 0)
 	{
-		proxy->buffersize = snprintf ((char*) proxy->buffer, MAX_PROXY_BUFFER,
+		proxy->buffersize = g_snprintf ((char*) proxy->buffer, MAX_PROXY_BUFFER,
 										"%s %d\r\n", net_ip(dcc->addr),
 										dcc->port);
 		proxy->bufferused = 0;
@@ -1288,16 +1253,16 @@ dcc_http_proxy_traverse (GIOChannel *source, GIOCondition condition, struct DCC
 		char auth_data2[68];
 		int n, n2;
 
-		n = snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
+		n = g_snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
                                           net_ip(dcc->addr), dcc->port);
 		if (prefs.hex_net_proxy_auth)
 		{
-			n2 = snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
+			n2 = g_snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
 							prefs.hex_net_proxy_user, prefs.hex_net_proxy_pass);
 			base64_encode (auth_data, auth_data2, n2);
-			n += snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
+			n += g_snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
 		}
-		n += snprintf (buf+n, sizeof (buf)-n, "\r\n");
+		n += g_snprintf (buf+n, sizeof (buf)-n, "\r\n");
 		proxy->buffersize = n;
 		proxy->bufferused = 0;
 		memcpy (proxy->buffer, buf, proxy->buffersize);
@@ -1373,14 +1338,7 @@ dcc_proxy_connect (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 	if (!dcc_did_connect (source, condition, dcc))
 		return TRUE;
 
-	dcc->proxy = malloc (sizeof (struct proxy_state));
-	if (!dcc->proxy)
-	{
-		dcc->dccstat = STAT_FAILED;
-		fe_dcc_update (dcc);
-		return TRUE;
-	}
-	memset (dcc->proxy, 0, sizeof (struct proxy_state));
+	dcc->proxy = g_new0 (struct proxy_state, 1);
 
 	switch (prefs.hex_net_proxy_type)
 	{
@@ -1415,12 +1373,12 @@ dcc_connect (struct DCC *dcc)
 		}
 		/* possible problems with filenames containing spaces? */
 		if (dcc->type == TYPE_RECV)
-			snprintf (tbuf, sizeof (tbuf), strchr (dcc->file, ' ') ?
-					"DCC SEND \"%s\" %u %d %"DCC_SFMT" %d" :
-					"DCC SEND %s %u %d %"DCC_SFMT" %d", dcc->file,
+			g_snprintf (tbuf, sizeof (tbuf), strchr (dcc->file, ' ') ?
+					"DCC SEND \"%s\" %u %d %" G_GUINT64_FORMAT " %d" :
+					"DCC SEND %s %u %d %" G_GUINT64_FORMAT " %d", dcc->file,
 					dcc->addr, dcc->port, dcc->size, dcc->pasvid);
 		else
-			snprintf (tbuf, sizeof (tbuf), "DCC CHAT chat %u %d %d",
+			g_snprintf (tbuf, sizeof (tbuf), "DCC CHAT chat %u %d %d",
 				dcc->addr, dcc->port, dcc->pasvid);
 		dcc->serv->p_ctcp (dcc->serv, dcc->nick, tbuf);
 	}
@@ -1463,15 +1421,13 @@ dcc_send_data (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 
 	if (!dcc->fastsend)
 	{
-		if (dcc->ack < dcc->pos)
+		if (dcc->ack < (dcc->pos & 0xFFFFFFFF))
 			return TRUE;
 	}
 	else if (!dcc->wiotag)
 		dcc->wiotag = fe_input_add (sok, FIA_WRITE, dcc_send_data, dcc);
 
-	buf = malloc (prefs.hex_dcc_blocksize);
-	if (!buf)
-		return TRUE;
+	buf = g_malloc (prefs.hex_dcc_blocksize);
 
 	lseek (dcc->fp, dcc->pos, SEEK_SET);
 	len = read (dcc->fp, buf, prefs.hex_dcc_blocksize);
@@ -1482,7 +1438,7 @@ dcc_send_data (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 	if (sent < 0 && !(would_block ()))
 	{
 abortit:
-		free (buf);
+		g_free (buf);
 		EMIT_SIGNAL (XP_TE_DCCSENDFAIL, dcc->serv->front_session,
 						 file_part (dcc->file), dcc->nick,
 						 errorstring (sock_error ()), NULL, 0);
@@ -1506,7 +1462,7 @@ abortit:
 		}
 	}
 
-	free (buf);
+	g_free (buf);
 
 	return TRUE;
 }
@@ -1538,7 +1494,7 @@ dcc_handle_new_ack (struct DCC *dcc)
 		dcc_close (dcc, STAT_DONE, FALSE);
 		dcc_calc_average_cps (dcc);	/* this must be done _after_ dcc_close, or dcc_remove_from_sum will see the wrong value in dcc->cps */
 		/* cppcheck-suppress deallocuse */
-		sprintf (buf, "%d", dcc->cps);
+		sprintf (buf, "%" G_GINT64_FORMAT, dcc->cps);
 		EMIT_SIGNAL (XP_TE_DCCSENDCOMP, dcc->serv->front_session,
 						 file_part (dcc->file), dcc->nick, buf, NULL, 0);
 		done = TRUE;
@@ -1548,12 +1504,10 @@ dcc_handle_new_ack (struct DCC *dcc)
 		dcc_send_data (NULL, 0, (gpointer)dcc);
 	}
 
-#ifdef USE_DCC64
 	/* take the top 32 of "bytes send" and bottom 32 of "ack" */
 	dcc->ack = (dcc->pos & G_GINT64_CONSTANT (0xffffffff00000000)) |
 					(dcc->ack & 0xffffffff);
 	/* dcc->ack is only used for CPS and PERCENTAGE calcs from now on... */
-#endif
 
 	return done;
 }
@@ -1622,7 +1576,7 @@ dcc_accept (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 	dcc->lasttime = dcc->starttime = time (0);
 	dcc->fastsend = prefs.hex_dcc_fast_send;
 
-	snprintf (host, sizeof (host), "%s:%d", net_ip (dcc->addr), dcc->port);
+	g_snprintf (host, sizeof (host), "%s:%d", net_ip (dcc->addr), dcc->port);
 
 	switch (dcc->type)
 	{
@@ -1638,8 +1592,7 @@ dcc_accept (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 	case TYPE_CHATSEND:
 		dcc_open_query (dcc->serv, dcc->nick);
 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read_chat, dcc);
-		dcc->dccchat = malloc (sizeof (struct dcc_chat));
-		dcc->dccchat->pos = 0;
+		dcc->dccchat = g_new0 (struct dcc_chat, 1);
 		EMIT_SIGNAL (XP_TE_DCCCONCHAT, dcc->serv->front_session,
 						 dcc->nick, host, NULL, NULL, 0);
 		break;
@@ -1762,7 +1715,7 @@ dcc_listen_init (struct DCC *dcc, session *sess)
 
 static struct session *dccsess;
 static char *dccto;				  /* lame!! */
-static int dccmaxcps;
+static gint64 dccmaxcps;
 static int recursive = FALSE;
 
 static void
@@ -1772,21 +1725,25 @@ dcc_send_wild (char *file)
 }
 
 void
-dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
+dcc_send (struct session *sess, char *to, char *filename, gint64 maxcps, int passive)
 {
 	char outbuf[512];
-	GStatBuf st;
+	GFileInfo *file_info;
+	GFile *file;
 	struct DCC *dcc;
+	gchar *filename_fs;
+	GFileType file_type;
+	goffset file_size;
 
-	file = expand_homedir (file);
+	filename = expand_homedir (filename);
 
-	if (!recursive && (strchr (file, '*') || strchr (file, '?')))
+	if (!recursive && (strchr (filename, '*') || strchr (filename, '?')))
 	{
 		char path[256];
 		char wild[256];
 
-		safe_strcpy (wild, file_part (file), sizeof (wild));
-		path_part (file, path, sizeof (path));
+		safe_strcpy (wild, file_part (filename), sizeof (wild));
+		path_part (filename, path, sizeof (path));
 		if (path[0] != '/' || path[1] != '\0')
 			path[strlen (path) - 1] = 0;	/* remove trailing slash */
 
@@ -1794,7 +1751,7 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 		dccto = to;
 		dccmaxcps = maxcps;
 
-		free (file);
+		g_free (filename);
 
 		recursive = TRUE;
 		for_files (path, wild, dcc_send_wild);
@@ -1806,91 +1763,135 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 	dcc = new_dcc ();
 	if (!dcc)
 	{
-		free (file);
+		g_free (filename);
 		return;
 	}
-	dcc->file = file;
+
+	dcc->file = filename;
 	dcc->maxcps = maxcps;
 
-	if (g_stat (file, &st) != -1)
+	filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
+	if (filename_fs == NULL)
 	{
+		PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
+		PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
 
-#ifndef USE_DCC64
-		if (sizeof (st.st_size) > 4 && st.st_size > 4294967295U)
-		{
-			PrintText (sess, "Cannot send files larger than 4 GB.\n");
-			goto xit;
-		}
-#endif
+		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
 
-		if (!(*file_part (file)) || S_ISDIR (st.st_mode) || st.st_size < 1)
-		{
-			PrintText (sess, "Cannot send directories or empty files.\n");
-			goto xit;
-		}
+		return;
+	}
 
-		dcc->starttime = dcc->offertime = time (0);
-		dcc->serv = sess->server;
-		dcc->dccstat = STAT_QUEUED;
-		dcc->size = st.st_size;
-		dcc->type = TYPE_SEND;
-		dcc->fp = g_open (file, OFLAGS | O_RDONLY, 0);
-		if (dcc->fp != -1)
-		{
-			if (passive || dcc_listen_init (dcc, sess))
-			{
-				char havespaces = 0;
-				while (*file)
-				{
-					if (*file == ' ')
-					{
-						if (prefs.hex_dcc_send_fillspaces)
-				    		*file = '_';
-					  	else
-					   	havespaces = 1;
-					}
-					file++;
-				}
-				dcc->nick = strdup (to);
-				if (prefs.hex_gui_autoopen_send)
-				{
-					if (fe_dcc_open_send_win (TRUE))	/* already open? add */
-						fe_dcc_add (dcc);
-				} else
-					fe_dcc_add (dcc);
+	file = g_file_new_for_path (filename_fs);
+	if (file == NULL)
+	{
+		PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
+		PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
 
-				if (passive)
-				{
-					dcc->pasvid = new_id();
-					snprintf (outbuf, sizeof (outbuf), (havespaces) ?
-							"DCC SEND \"%s\" 199 0 %" DCC_SFMT " %d" :
-							"DCC SEND %s 199 0 %" DCC_SFMT " %d",
-							file_part (dcc->file),
-							dcc->size, dcc->pasvid);
-				}
-				else
-				{
-					snprintf (outbuf, sizeof (outbuf), (havespaces) ?
-							"DCC SEND \"%s\" %u %d %"DCC_SFMT :
-							"DCC SEND %s %u %d %"DCC_SFMT,
-							file_part (dcc->file), dcc->addr,
-							dcc->port, dcc->size);
-				}
-				sess->server->p_ctcp (sess->server, to, outbuf);
+		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
 
-				EMIT_SIGNAL (XP_TE_DCCOFFER, sess, file_part (dcc->file),
-								 to, dcc->file, NULL, 0);
-			} else
+		g_free (filename_fs);
+
+		return;
+	}
+
+	file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+
+	g_object_unref (file);
+
+	if (file_info == NULL)
+	{
+		PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
+		PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
+
+		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
+
+		g_free (filename_fs);
+
+		return;
+	}
+
+	file_type = g_file_info_get_file_type (file_info);
+	file_size = g_file_info_get_size (file_info);
+
+	g_object_unref (file_info);
+
+	if (*file_part (filename) == '\0' || file_type == G_FILE_TYPE_DIRECTORY || file_size <= 0)
+	{
+		PrintText (sess, "Cannot send directories or empty files.\n");
+
+		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
+
+		g_free (filename_fs);
+
+		return;
+	}
+
+	dcc->starttime = dcc->offertime = time (0);
+	dcc->serv = sess->server;
+	dcc->dccstat = STAT_QUEUED;
+	dcc->size = file_size;
+	dcc->type = TYPE_SEND;
+	dcc->fp = g_open (filename_fs, OFLAGS | O_RDONLY, 0);
+
+	g_free (filename_fs);
+
+	if (dcc->fp == -1)
+	{
+		PrintText (sess, "Cannot send directories or empty files.\n");
+
+		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
+
+		return;
+	}
+
+	if (passive || dcc_listen_init (dcc, sess))
+	{
+		char havespaces = 0;
+		while (*filename)
+		{
+			if (*filename == ' ')
 			{
-				dcc_close (dcc, 0, TRUE);
+				if (prefs.hex_dcc_send_fillspaces)
+				    *filename = '_';
+				else
+				havespaces = 1;
 			}
-			return;
+			filename++;
 		}
+		dcc->nick = g_strdup (to);
+		if (prefs.hex_gui_autoopen_send)
+		{
+			if (fe_dcc_open_send_win (TRUE))	/* already open? add */
+				fe_dcc_add (dcc);
+		} else
+			fe_dcc_add (dcc);
+
+		if (passive)
+		{
+			dcc->pasvid = new_id();
+			g_snprintf (outbuf, sizeof (outbuf), (havespaces) ?
+					"DCC SEND \"%s\" 199 0 %" G_GUINT64_FORMAT " %d" :
+					"DCC SEND %s 199 0 %" G_GUINT64_FORMAT " %d",
+					file_part (dcc->file),
+					dcc->size, dcc->pasvid);
+		}
+		else
+		{
+			g_snprintf (outbuf, sizeof (outbuf), (havespaces) ?
+					"DCC SEND \"%s\" %u %d %" G_GUINT64_FORMAT :
+					"DCC SEND %s %u %d %" G_GUINT64_FORMAT,
+					file_part (dcc->file), dcc->addr,
+					dcc->port, dcc->size);
+		}
+		sess->server->p_ctcp (sess->server, to, outbuf);
+
+		EMIT_SIGNAL (XP_TE_DCCOFFER, sess, file_part (dcc->file),
+							to, dcc->file, NULL, 0);
+	}
+	else
+	{
+		dcc_close (dcc, 0, TRUE);
 	}
-	PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
-	PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
-xit:
-	dcc_close (dcc, 0, TRUE);		/* dcc_close will free dcc->file */
 }
 
 static struct DCC *
@@ -1906,7 +1907,7 @@ find_dcc_from_id (int id, int type)
 		return dcc;
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 static struct DCC *
@@ -1922,7 +1923,7 @@ find_dcc_from_port (int port, int type)
 			return dcc;
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 struct DCC *
@@ -1947,7 +1948,7 @@ find_dcc (char *nick, char *file, int type)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 /* called when we receive a NICK change from server */
@@ -1965,9 +1966,8 @@ dcc_change_nick (struct server *serv, char *oldnick, char *newnick)
 		{
 			if (!serv->p_cmp (dcc->nick, oldnick))
 			{
-				if (dcc->nick)
-					free (dcc->nick);
-				dcc->nick = strdup (newnick);
+				g_free (dcc->nick);
+				dcc->nick = g_strdup (newnick);
 			}
 		}
 		list = list->next;
@@ -1976,68 +1976,153 @@ dcc_change_nick (struct server *serv, char *oldnick, char *newnick)
 
 /* is the destination file the same? new_dcc is not opened yet */
 
-static int
+static gboolean
 is_same_file (struct DCC *dcc, struct DCC *new_dcc)
 {
-#ifndef WIN32
-	GStatBuf st_a, st_b;
-#endif
+	gboolean result = FALSE;
+	gchar *filename_fs = NULL, *new_filename_fs = NULL;
+	GFile *file = NULL, *new_file = NULL;
+	GFileInfo *file_info = NULL, *new_file_info = NULL;
+	char *file_id = NULL, *new_file_id = NULL;
+	char *filesystem_id = NULL, *new_filesystem_id = NULL;
 
 	/* if it's the same filename, must be same */
 	if (strcmp (dcc->destfile, new_dcc->destfile) == 0)
+	{
 		return TRUE;
+	}
 
-	/* now handle case-insensitive Filesystems: HFS+, FAT */
-#ifdef WIN32
-	/* warning no win32 implementation - behaviour may be unreliable */
-#else
-	/* this fstat() shouldn't really fail */
-	if ((dcc->fp == -1 ? g_stat (dcc->destfile, &st_a) : fstat (dcc->fp, &st_a)) == -1)
-		return FALSE;
-	if (g_stat (new_dcc->destfile, &st_b) == -1)
-		return FALSE;
+	filename_fs = g_filename_from_utf8 (dcc->file, -1, NULL, NULL, NULL);
+	if (filename_fs == NULL)
+	{
+		goto exit;
+	}
 
-	/* same inode, same device, same file! */
-	if (st_a.st_ino == st_b.st_ino &&
-		 st_a.st_dev == st_b.st_dev)
-		return TRUE;
-#endif
+	new_filename_fs = g_filename_from_utf8 (new_dcc->file, -1, NULL, NULL, NULL);
+	if (new_filename_fs == NULL)
+	{
+		goto exit;
+	}
 
-	return FALSE;
+	file = g_file_new_for_path (filename_fs);
+	if (file == NULL)
+	{
+		goto exit;
+	}
+
+	new_file = g_file_new_for_path (new_filename_fs);
+	if (new_file == NULL)
+	{
+		goto exit;
+	}
+
+	file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_ID_FILE "," G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+	if (file_info == NULL)
+	{
+		goto exit;
+	}
+
+	new_file_info = g_file_query_info (new_file, G_FILE_ATTRIBUTE_ID_FILE "," G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+	if (new_file_info == NULL)
+	{
+		goto exit;
+	}
+
+	file_id = g_file_info_get_attribute_as_string (file_info, G_FILE_ATTRIBUTE_ID_FILE);
+	new_file_id = g_file_info_get_attribute_as_string (new_file_info, G_FILE_ATTRIBUTE_ID_FILE);
+
+	filesystem_id = g_file_info_get_attribute_as_string (file_info, G_FILE_ATTRIBUTE_ID_FILE);
+	new_filesystem_id = g_file_info_get_attribute_as_string (new_file_info, G_FILE_ATTRIBUTE_ID_FILE);
+
+	if (file_id != NULL && new_file_id != NULL && filesystem_id != NULL && new_filesystem_id != NULL && strcmp (file_id, new_file_id) == 0 && strcmp (filesystem_id, new_filesystem_id) == 0)
+	{
+		result = TRUE;
+	}
+
+exit:
+	g_free (filename_fs);
+	g_free (new_filename_fs);
+
+	if (file != NULL)
+	{
+		g_object_unref (file);
+	}
+
+	if (new_file != NULL)
+	{
+		g_object_unref (new_file);
+	}
+
+	if (file_info != NULL)
+	{
+		g_object_unref (file_info);
+	}
+
+	if (new_file_info != NULL)
+	{
+		g_object_unref (new_file_info);
+	}
+
+	g_free (file_id);
+	g_free (new_file_id);
+	g_free(filesystem_id);
+	g_free(new_filesystem_id);
+
+	return result;
 }
 
-static int
-is_resumable (struct DCC *dcc)
+static void
+update_is_resumable (struct DCC *dcc)
 {
+	gchar *filename_fs = g_filename_from_utf8 (dcc->destfile, -1, NULL, NULL, NULL);
+
 	dcc->resumable = 0;
 
 	/* Check the file size */
-	if (g_access (dcc->destfile, W_OK) == 0)
+	if (filename_fs != NULL && g_access(filename_fs, W_OK) == 0)
 	{
-		GStatBuf st;
-
-		if (g_stat (dcc->destfile, &st) != -1)
+		GFile *file = g_file_new_for_path (filename_fs);
+		if (file != NULL)
 		{
-			if (st.st_size < dcc->size)
+			GFileInfo *file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+
+			if (file_info != NULL)
 			{
-				dcc->resumable = st.st_size;
-				dcc->pos = st.st_size;
+				goffset file_size_offset = g_file_info_get_size (file_info);
+				guint64 file_size = (file_size_offset >= 0) ? (guint64) file_size_offset : 0;
+				if (file_size < dcc->size)
+				{
+					dcc->resumable = file_size;
+					dcc->pos = file_size;
+				}
+				else
+				{
+					dcc->resume_error = 2;
+				}
+
+				g_object_unref (file_info);
 			}
 			else
-				dcc->resume_error = 2;
-		} else
+			{
+				dcc->resume_errno = errno;
+				dcc->resume_error = 1;
+			}
+
+			g_object_unref(file);
+		}
+		else
 		{
 			dcc->resume_errno = errno;
 			dcc->resume_error = 1;
 		}
-	} else
+	}
+	else
 	{
 		dcc->resume_errno = errno;
 		dcc->resume_error = 1;
 	}
 
 	/* Now verify that this DCC is not already in progress from someone else */
-
 	if (dcc->resumable)
 	{
 		GSList *list = dcc_list;
@@ -2059,8 +2144,6 @@ is_resumable (struct DCC *dcc)
 			list = list->next;
 		}
 	}
-
-	return dcc->resumable;
 }
 
 void
@@ -2100,7 +2183,7 @@ dcc_get_with_destfile (struct DCC *dcc, char *file)
 	dcc->destfile = g_strdup (file);	/* utf-8 */
 
 	/* since destfile changed, must check resumability again */
-	is_resumable (dcc);
+	update_is_resumable (dcc);
 
 	dcc_get (dcc);
 }
@@ -2133,14 +2216,11 @@ dcc_get_nick (struct session *sess, char *nick)
 static struct DCC *
 new_dcc (void)
 {
-	struct DCC *dcc = malloc (sizeof (struct DCC));
-	if (!dcc)
-		return 0;
-	memset (dcc, 0, sizeof (struct DCC));
+	struct DCC *dcc = g_new0 (struct DCC, 1);
 	dcc->sok = -1;
 	dcc->fp = -1;
 	dcc_list = g_slist_prepend (dcc_list, dcc);
-	return (dcc);
+	return dcc;
 }
 
 void
@@ -2187,7 +2267,7 @@ dcc_chat (struct session *sess, char *nick, int passive)
 	dcc->serv = sess->server;
 	dcc->dccstat = STAT_QUEUED;
 	dcc->type = TYPE_CHATSEND;
-	dcc->nick = strdup (nick);
+	dcc->nick = g_strdup (nick);
 	if (passive || dcc_listen_init (dcc, sess))
 	{
 		if (prefs.hex_gui_autoopen_chat)
@@ -2200,11 +2280,11 @@ dcc_chat (struct session *sess, char *nick, int passive)
 		if (passive)
 		{
 			dcc->pasvid = new_id ();
-			snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat 199 %d %d",
+			g_snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat 199 %d %d",
 						 dcc->port, dcc->pasvid);
 		} else
 		{
-			snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat %u %d",
+			g_snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat %u %d",
 						 dcc->addr, dcc->port);
 		}
 		dcc->serv->p_ctcp (dcc->serv, nick, outbuf);
@@ -2230,9 +2310,9 @@ dcc_resume (struct DCC *dcc)
 	{
 		dcc->resume_sent = 1;
 		/* filename contains spaces? Quote them! */
-		snprintf (tbuf, sizeof (tbuf) - 10, strchr (dcc->file, ' ') ?
-					  "DCC RESUME \"%s\" %d %"DCC_SFMT :
-					  "DCC RESUME %s %d %"DCC_SFMT,
+		g_snprintf (tbuf, sizeof (tbuf) - 10, strchr (dcc->file, ' ') ?
+					  "DCC RESUME \"%s\" %d %" G_GUINT64_FORMAT :
+					  "DCC RESUME %s %d %" G_GUINT64_FORMAT,
 					  dcc->file, dcc->port, dcc->resumable);
 
 		if (dcc->pasvid)
@@ -2287,7 +2367,7 @@ dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid)
 		dcc->addr = addr;
 		dcc->port = port;
 		dcc->pasvid = pasvid;
-		dcc->nick = strdup (nick);
+		dcc->nick = g_strdup (nick);
 		dcc->starttime = time (0);
 
 		EMIT_SIGNAL (XP_TE_DCCCHATOFFER, sess->server->front_session, nick,
@@ -2307,7 +2387,7 @@ dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid)
 		else
 		{
 			char buff[128];
-			snprintf (buff, sizeof (buff), "%s is offering DCC Chat. Do you want to accept?", nick);
+			g_snprintf (buff, sizeof (buff), "%s is offering DCC Chat. Do you want to accept?", nick);
 			fe_confirm (buff, dcc_confirm_chat, dcc_deny_chat, dcc);
 		}
 	}
@@ -2316,7 +2396,7 @@ dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid)
 }
 
 static struct DCC *
-dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, guint32 addr, int pasvid)
+dcc_add_file (session *sess, char *file, guint64 size, int port, char *nick, guint32 addr, int pasvid)
 {
 	struct DCC *dcc;
 	char tbuf[512];
@@ -2324,7 +2404,7 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu
 	dcc = new_dcc ();
 	if (dcc)
 	{
-		dcc->file = strdup (file);
+		dcc->file = g_strdup (file);
 
 		dcc->destfile = g_malloc (strlen (prefs.hex_dcc_dir) + strlen (nick) +
 										  strlen (file) + 4);
@@ -2359,14 +2439,14 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu
 		dcc->port = port;
 		dcc->pasvid = pasvid;
 		dcc->size = size;
-		dcc->nick = strdup (nick);
+		dcc->nick = g_strdup (nick);
 		dcc->maxcps = prefs.hex_dcc_max_get_cps;
 
-		is_resumable (dcc);
+		update_is_resumable (dcc);
 
 		if (prefs.hex_dcc_auto_recv == 1)
 		{
-			snprintf (tbuf, sizeof (tbuf), _("%s is offering \"%s\". Do you want to accept?"), nick, file);
+			g_snprintf (tbuf, sizeof (tbuf), _("%s is offering \"%s\". Do you want to accept?"), nick, file);
 			fe_confirm (tbuf, dcc_confirm_send, dcc_deny_send, dcc);
 		}
 		else if (prefs.hex_dcc_auto_recv == 2)
@@ -2380,8 +2460,8 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu
 		} else
 			fe_dcc_add (dcc);
 	}
-	sprintf (tbuf, "%"DCC_SFMT, size);
-	snprintf (tbuf + 24, 300, "%s:%d", net_ip (addr), port);
+	sprintf (tbuf, "%" G_GUINT64_FORMAT, size);
+	g_snprintf (tbuf + 24, 300, "%s:%d", net_ip (addr), port);
 	EMIT_SIGNAL (XP_TE_DCCSENDOFFER, sess->server->front_session, nick,
 					 file, tbuf, tbuf + 24, 0);
 
@@ -2397,7 +2477,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 	char *type = word[5];
 	int port, pasvid = 0;
 	guint32 addr;
-	DCC_SIZE size;
+	guint64 size;
 	int psend = 0;
 
 	if (!g_ascii_strcasecmp (type, "CHAT"))
@@ -2463,7 +2543,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 			dcc = find_dcc (nick, word[6], TYPE_SEND);
 		if (dcc)
 		{
-			size = BIG_STR_TO_INT (word[8]);
+			size = g_ascii_strtoull (word[8], NULL, 10);
 			dcc->resumable = size;
 			if (dcc->resumable < dcc->size)
 			{
@@ -2473,19 +2553,19 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 
 				/* Checking if dcc is passive and if filename contains spaces */
 				if (dcc->pasvid)
-					snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
-							"DCC ACCEPT \"%s\" %d %"DCC_SFMT" %d" :
-							"DCC ACCEPT %s %d %"DCC_SFMT" %d",
+					g_snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
+							"DCC ACCEPT \"%s\" %d %" G_GUINT64_FORMAT " %d" :
+							"DCC ACCEPT %s %d %" G_GUINT64_FORMAT " %d",
 							file_part (dcc->file), port, dcc->resumable, dcc->pasvid);
 				else
-					snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
-							"DCC ACCEPT \"%s\" %d %"DCC_SFMT :
-							"DCC ACCEPT %s %d %"DCC_SFMT,
+					g_snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
+							"DCC ACCEPT \"%s\" %d %" G_GUINT64_FORMAT :
+							"DCC ACCEPT %s %d %" G_GUINT64_FORMAT,
 							file_part (dcc->file), port, dcc->resumable);
 
 				dcc->serv->p_ctcp (dcc->serv, dcc->nick, tbuf);
 			}
-			sprintf (tbuf, "%"DCC_SFMT, dcc->pos);
+			sprintf (tbuf, "%" G_GUINT64_FORMAT, dcc->pos);
 			EMIT_SIGNAL_TIMESTAMP (XP_TE_DCCRESUMEREQUEST, sess, nick,
 										  file_part (dcc->file), tbuf, NULL, 0,
 										  tags_data->timestamp);
@@ -2508,7 +2588,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 
 		port = atoi (word[8]);
 		addr = strtoul (word[7], NULL, 10);
-		size = BIG_STR_TO_INT (word[9]);
+		size = g_ascii_strtoull (word[9], NULL, 10);
 
 		if (port == 0) /* Passive dcc requested */
 			pasvid = atoi (word[10]);
@@ -2576,7 +2656,7 @@ dcc_show_list (struct session *sess)
 	{
 		dcc = (struct DCC *) list->data;
 		i++;
-		PrintTextf (sess, " %s  %-10.10s %-7.7s %-7"DCC_SFMT" %-7"DCC_SFMT" %s\n",
+		PrintTextf (sess, " %s  %-10.10s %-7.7s %-7" G_GUINT64_FORMAT " %-7" G_GUINT64_FORMAT " %s\n",
 					 dcctypes[dcc->type], dcc->nick,
 					 _(dccstat[dcc->dccstat].name), dcc->size, dcc->pos,
 					 file_part (dcc->file));
diff --git a/src/common/dcc.h b/src/common/dcc.h
index ade1dae7..e7115b32 100644
--- a/src/common/dcc.h
+++ b/src/common/dcc.h
@@ -39,17 +39,6 @@
 
 #define CPS_AVG_WINDOW 10
 
-/* can we do 64-bit dcc? */
-#if defined(G_GINT64_FORMAT) && defined(HAVE_STRTOULL)
-#define USE_DCC64
-/* we really get only 63 bits, since st_size is signed */
-#define DCC_SIZE gint64
-#define DCC_SFMT G_GINT64_FORMAT
-#else
-#define DCC_SIZE unsigned int
-#define DCC_SFMT "u"
-#endif
-
 struct DCC
 {
 	struct server *serv;
@@ -62,21 +51,21 @@ struct DCC
 	int wiotag;						/* writing/sending io tag */
 	int port;
 	int pasvid;						/* mIRC's passive DCC id */
-	int cps;
+	gint64 cps;
 	int resume_error;
 	int resume_errno;
 
 	GTimeVal lastcpstv, firstcpstv;
-	DCC_SIZE lastcpspos;
-	int maxcps;
+	goffset lastcpspos;
+	gint64 maxcps;
 
 	unsigned char ack_buf[4];	/* buffer for reading 4-byte ack */
 	int ack_pos;
 
-	DCC_SIZE size;
-	DCC_SIZE resumable;
-	DCC_SIZE ack;
-	DCC_SIZE pos;
+	guint64 size;
+	guint64 resumable;
+	guint64 ack;
+	guint64 pos;
 	time_t starttime;
 	time_t offertime;
 	time_t lasttime;
@@ -125,7 +114,7 @@ void dcc_check_timeouts (void);
 void dcc_change_nick (server *serv, char *oldnick, char *newnick);
 void dcc_notify_kill (struct server *serv);
 struct DCC *dcc_write_chat (char *nick, char *text);
-void dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive);
+void dcc_send (struct session *sess, char *to, char *file, gint64 maxcps, int passive);
 struct DCC *find_dcc (char *nick, char *file, int type);
 void dcc_get_nick (struct session *sess, char *nick);
 void dcc_chat (session *sess, char *nick, int passive);
diff --git a/src/common/fe.h b/src/common/fe.h
index 2ca15c60..a3bd2afa 100644
--- a/src/common/fe.h
+++ b/src/common/fe.h
@@ -88,11 +88,10 @@ void fe_progressbar_start (struct session *sess);
 void fe_progressbar_end (struct server *serv);
 void fe_print_text (struct session *sess, char *text, time_t stamp,
 					gboolean no_activity);
-void fe_userlist_insert (struct session *sess, struct User *newuser, int row, int sel);
+void fe_userlist_insert (struct session *sess, struct User *newuser, gboolean sel);
 int fe_userlist_remove (struct session *sess, struct User *user);
 void fe_userlist_rehash (struct session *sess, struct User *user);
 void fe_userlist_update (struct session *sess, struct User *user);
-void fe_userlist_move (struct session *sess, struct User *user, int new_row);
 void fe_userlist_numbers (struct session *sess);
 void fe_userlist_clear (struct session *sess);
 void fe_userlist_set_selected (struct session *sess);
@@ -179,7 +178,6 @@ typedef enum
 } feicon;
 void fe_tray_set_icon (feicon icon);
 void fe_tray_set_tooltip (const char *text);
-void fe_tray_set_balloon (const char *title, const char *text);
 void fe_open_chan_list (server *serv, char *filter, int do_refresh);
 const char *fe_get_default_font ();
 
diff --git a/src/common/hexchat.c b/src/common/hexchat.c
index 09afa445..a76db332 100644
--- a/src/common/hexchat.c
+++ b/src/common/hexchat.c
@@ -41,7 +41,9 @@
 #include "chanopt.h"
 #include "ignore.h"
 #include "hexchat-plugin.h"
+#include "inbound.h"
 #include "plugin.h"
+#include "plugin-identd.h"
 #include "plugin-timer.h"
 #include "notify.h"
 #include "server.h"
@@ -55,15 +57,6 @@
 #include <glib-object.h>			/* for g_type_init() */
 #endif
 
-#ifdef USE_OPENSSL
-#include <openssl/ssl.h>			/* SSL_() */
-#include "ssl.h"
-#endif
-
-#ifdef USE_MSPROXY
-#include "msproxy.h"
-#endif
-
 #ifdef USE_LIBPROXY
 #include <proxy.h>
 #endif
@@ -118,10 +111,6 @@ struct session *current_tab;
 struct session *current_sess = 0;
 struct hexchatprefs prefs;
 
-#ifdef USE_OPENSSL
-SSL_CTX *ctx = NULL;
-#endif
-
 #ifdef USE_LIBPROXY
 pxProxyFactory *libproxy_factory;
 #endif
@@ -221,7 +210,7 @@ find_dialog (server *serv, char *nick)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 session *
@@ -232,14 +221,14 @@ find_channel (server *serv, char *chan)
 	while (list)
 	{
 		sess = list->data;
-		if ((!serv || serv == sess->server) && sess->type == SESS_CHANNEL)
+		if ((serv == sess->server) && sess->type == SESS_CHANNEL)
 		{
 			if (!serv->p_cmp (chan, sess->channel))
 				return sess;
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 static void
@@ -269,7 +258,7 @@ lag_check (void)
 	unsigned long tim;
 	char tbuf[128];
 	time_t now = time (0);
-	int lag;
+	time_t lag;
 
 	tim = make_ping_time ();
 
@@ -279,16 +268,17 @@ lag_check (void)
 		if (serv->connected && serv->end_of_motd)
 		{
 			lag = now - serv->ping_recv;
-			if (prefs.hex_net_ping_timeout && lag > prefs.hex_net_ping_timeout && lag > 0)
+			if (prefs.hex_net_ping_timeout != 0 && lag > prefs.hex_net_ping_timeout && lag > 0)
 			{
-				sprintf (tbuf, "%d", lag);
+				sprintf (tbuf, "%" G_GINT64_FORMAT, (gint64) lag);
 				EMIT_SIGNAL (XP_TE_PINGTIMEOUT, serv->server_session, tbuf, NULL,
 								 NULL, NULL, 0);
 				if (prefs.hex_net_auto_reconnect)
 					serv->auto_reconnect (serv, FALSE, -1);
-			} else
+			}
+			else
 			{
-				snprintf (tbuf, sizeof (tbuf), "LAG%lu", tim);
+				g_snprintf (tbuf, sizeof (tbuf), "LAG%lu", tim);
 				serv->p_ping (serv, "", tbuf);
 				
 				if (!serv->lag_sent)
@@ -368,9 +358,6 @@ static int
 hexchat_misc_checks (void)		/* this gets called every 1/2 second */
 {
 	static int count = 0;
-#ifdef USE_MSPROXY
-	static int count2 = 0;
-#endif
 
 	count++;
 
@@ -386,15 +373,6 @@ hexchat_misc_checks (void)		/* this gets called every 1/2 second */
 		count = 0;
 	}
 
-#ifdef USE_MSPROXY	
-	count2++;
-	if (count2 >= 720)			/* 720 every 6 minutes */
-	{
-		msproxy_keepalive ();
-		count2 = 0;
-	}
-#endif
-
 	return 1;
 }
 
@@ -405,7 +383,6 @@ irc_init (session *sess)
 {
 	static int done_init = FALSE;
 	char *buf;
-	int i;
 
 	if (done_init)
 		return;
@@ -413,6 +390,7 @@ irc_init (session *sess)
 	done_init = TRUE;
 
 	plugin_add (sess, NULL, NULL, timer_plugin_init, NULL, NULL, FALSE);
+	plugin_add (sess, NULL, NULL, identd_plugin_init, identd_plugin_deinit, NULL, FALSE);
 
 #ifdef USE_PLUGIN
 	if (!arg_skip_plugins)
@@ -440,7 +418,8 @@ irc_init (session *sess)
 	
 	if (arg_urls != NULL)
 	{
-		for (i = 0; i < g_strv_length(arg_urls); i++)
+		guint i;
+		for (i = 0; i < g_strv_length (arg_urls); i++)
 		{
 			buf = g_strdup_printf ("%s %s", i==0? "server" : "newserver", arg_urls[i]);
 			handle_command (sess, buf, FALSE);
@@ -464,12 +443,7 @@ session_new (server *serv, char *from, int type, int focus)
 {
 	session *sess;
 
-	sess = malloc (sizeof (struct session));
-	if (sess == NULL)
-	{
-		return NULL;
-	}
-	memset (sess, 0, sizeof (struct session));
+	sess = g_new0 (struct session, 1);
 
 	sess->server = serv;
 	sess->logfd = -1;
@@ -488,7 +462,10 @@ session_new (server *serv, char *from, int type, int focus)
 	sess->lastact_idx = LACT_NONE;
 
 	if (from != NULL)
-		safe_strcpy (sess->channel, from, CHANLEN);
+	{
+		safe_strcpy(sess->channel, from, CHANLEN);
+		safe_strcpy(sess->session_name, from, CHANLEN);
+	}
 
 	sess_list = g_slist_prepend (sess_list, sess);
 
@@ -515,7 +492,6 @@ new_ircwindow (server *serv, char *name, int type, int focus)
 		break;
 	case SESS_DIALOG:
 		sess = session_new (serv, name, type, focus);
-		log_open_or_close (sess);
 		break;
 	default:
 /*	case SESS_CHANNEL:
@@ -530,6 +506,16 @@ new_ircwindow (server *serv, char *name, int type, int focus)
 	scrollback_load (sess);
 	if (sess->scrollwritten && sess->scrollback_replay_marklast)
 		sess->scrollback_replay_marklast (sess);
+	if (type == SESS_DIALOG)
+	{
+		struct User *user;
+
+		log_open_or_close (sess);
+
+		user = userlist_find_global (serv, name);
+		if (user && user->hostname)
+			set_topic (sess, user->hostname, user->hostname);
+	}
 	plugin_emit_dummy_print (sess, "Open Context");
 
 	return sess;
@@ -548,9 +534,8 @@ exec_notify_kill (session * sess)
 		waitpid (re->childpid, NULL, WNOHANG);
 		fe_input_remove (re->iotag);
 		close (re->myfd);
-		if (re->linebuf)
-			free(re->linebuf);
-		free (re);
+		g_free(re->linebuf);
+		g_free (re);
 	}
 #endif
 }
@@ -656,10 +641,8 @@ session_free (session *killsess)
 	send_quit_or_part (killsess);
 
 	history_free (&killsess->history);
-	if (killsess->topic)
-		free (killsess->topic);
-	if (killsess->current_modes)
-		free (killsess->current_modes);
+	g_free (killsess->topic);
+	g_free (killsess->current_modes);
 
 	fe_session_callback (killsess);
 
@@ -670,7 +653,7 @@ session_free (session *killsess)
 			current_sess = sess_list->data;
 	}
 
-	free (killsess);
+	g_free (killsess);
 
 	if (!sess_list && !in_hexchat_exit)
 		hexchat_exit ();						/* sess_list is empty, quit! */
@@ -784,20 +767,15 @@ static void
 xchat_init (void)
 {
 	char buf[3068];
-	const char *cs = NULL;
 
 #ifdef WIN32
 	WSADATA wsadata;
 
-#ifdef USE_IPV6
 	if (WSAStartup(0x0202, &wsadata) != 0)
 	{
 		MessageBox (NULL, "Cannot find winsock 2.2+", "Error", MB_OK);
 		exit (0);
 	}
-#else
-	WSAStartup(0x0101, &wsadata);
-#endif	/* !USE_IPV6 */
 #endif	/* !WIN32 */
 
 #ifdef USE_SIGACTION
@@ -826,15 +804,12 @@ xchat_init (void)
 #endif
 #endif
 
-	if (g_get_charset (&cs))
-		prefs.utf8_locale = TRUE;
-
 	load_text_events ();
 	sound_load ();
 	notify_load ();
 	ignore_load ();
 
-	snprintf (buf, sizeof (buf),
+	g_snprintf (buf, sizeof (buf),
 		"NAME %s~%s~\n"				"CMD query %%s\n\n"\
 		"NAME %s~%s~\n"				"CMD send %%s\n\n"\
 		"NAME %s~%s~\n"				"CMD whois %%s %%s\n\n"\
@@ -890,7 +865,7 @@ xchat_init (void)
 
 	list_loadconf ("popup.conf", &popup_list, buf);
 
-	snprintf (buf, sizeof (buf),
+	g_snprintf (buf, sizeof (buf),
 		"NAME %s\n"				"CMD part\n\n"
 		"NAME %s\n"				"CMD getstr # join \"%s\"\n\n"
 		"NAME %s\n"				"CMD quote LINKS\n\n"
@@ -904,7 +879,7 @@ xchat_init (void)
 				_("Hide Version"));
 	list_loadconf ("usermenu.conf", &usermenu_list, buf);
 
-	snprintf (buf, sizeof (buf),
+	g_snprintf (buf, sizeof (buf),
 		"NAME %s\n"		"CMD op %%a\n\n"
 		"NAME %s\n"		"CMD deop %%a\n\n"
 		"NAME %s\n"		"CMD ban %%s\n\n"
@@ -921,7 +896,7 @@ xchat_init (void)
 				_("Dialog"));
 	list_loadconf ("buttons.conf", &button_list, buf);
 
-	snprintf (buf, sizeof (buf),
+	g_snprintf (buf, sizeof (buf),
 		"NAME %s\n"				"CMD whois %%s %%s\n\n"
 		"NAME %s\n"				"CMD send %%s\n\n"
 		"NAME %s\n"				"CMD dcc chat %%s\n\n"
@@ -1021,29 +996,37 @@ main (int argc, char *argv[])
 	int i;
 	int ret;
 
-	srand (time (0));	/* CL: do this only once! */
+#ifdef WIN32
+	HRESULT coinit_result;
+#endif
+
+	srand ((unsigned int) time (NULL)); /* CL: do this only once! */
 
 	/* We must check for the config dir parameter, otherwise load_config() will behave incorrectly.
 	 * load_config() must come before fe_args() because fe_args() calls gtk_init() which needs to
 	 * know the language which is set in the config. The code below is copy-pasted from fe_args()
 	 * for the most part. */
-	if (argc >= 3)
+	if (argc >= 2)
 	{
-		for (i = 1; i < argc - 1; i++)
+		for (i = 1; i < argc; i++)
 		{
-			if (strcmp (argv[i], "-d") == 0)
+			if ((strcmp (argv[i], "-d") == 0 || strcmp (argv[i], "--cfgdir") == 0)
+				&& i + 1 < argc)
 			{
-				if (xdir)
-				{
-					g_free (xdir);
-				}
-
-				xdir = strdup (argv[i + 1]);
+				xdir = g_strdup (argv[i + 1]);
+			}
+			else if (strncmp (argv[i], "--cfgdir=", 9) == 0)
+			{
+				xdir = g_strdup (argv[i] + 9);
+			}
 
+			if (xdir != NULL)
+			{
 				if (xdir[strlen (xdir) - 1] == G_DIR_SEPARATOR)
 				{
 					xdir[strlen (xdir) - 1] = 0;
 				}
+				break;
 			}
 		}
 	}
@@ -1067,10 +1050,6 @@ main (int argc, char *argv[])
 	/* we MUST do this after load_config () AND before fe_init (thus gtk_init) otherwise it will fail */
 	set_locale ();
 
-#ifdef SOCKS
-	SOCKSinit (argv[0]);
-#endif
-
 	ret = fe_args (argc, argv);
 	if (ret != -1)
 		return ret;
@@ -1083,6 +1062,14 @@ main (int argc, char *argv[])
 	libproxy_factory = px_proxy_factory_new();
 #endif
 
+#ifdef WIN32
+	coinit_result = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
+	if (SUCCEEDED (coinit_result))
+	{
+		CoInitializeSecurity (NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
+	}
+#endif
+
 	fe_init ();
 
 	/* This is done here because cfgfiles.c is too early in
@@ -1110,13 +1097,15 @@ main (int argc, char *argv[])
 
 	fe_main ();
 
-#ifdef USE_LIBPROXY
-	px_proxy_factory_free(libproxy_factory);
+#ifdef WIN32
+	if (SUCCEEDED (coinit_result))
+	{
+		CoUninitialize ();
+	}
 #endif
 
-#ifdef USE_OPENSSL
-	if (ctx)
-		_SSL_context_free (ctx);
+#ifdef USE_LIBPROXY
+	px_proxy_factory_free(libproxy_factory);
 #endif
 
 #ifdef WIN32
diff --git a/src/common/hexchat.h b/src/common/hexchat.h
index bbf32da5..652dcf1d 100644
--- a/src/common/hexchat.h
+++ b/src/common/hexchat.h
@@ -22,6 +22,7 @@
 #include <glib.h>
 #include <glib/gstdio.h>
 #include <glib/gi18n.h>
+#include <gio/gio.h>
 
 #include <time.h>			/* need time_t */
 
@@ -36,22 +37,7 @@
 #endif
 
 #include "history.h"
-
-#ifndef HAVE_SNPRINTF
-#define snprintf g_snprintf
-#endif
-
-#ifndef HAVE_VSNPRINTF
-#define vsnprintf _vsnprintf
-#endif
-
-#ifdef SOCKS
-#ifdef __sgi
-#include <sys/time.h>
-#define INCLUDE_PROTOTYPES 1
-#endif
-#include <socks.h>
-#endif
+#include "tree.h"
 
 #ifdef USE_OPENSSL
 #include <openssl/ssl.h>		  /* SSL_() */
@@ -262,6 +248,7 @@ struct hexchatprefs
 	int hex_gui_search_pos;
 	int hex_gui_slist_select;
 	int hex_gui_tab_layout;
+	int hex_gui_tab_middleclose;
 	int hex_gui_tab_newtofront;
 	int hex_gui_tab_pos;
 	int hex_gui_tab_small;
@@ -277,7 +264,7 @@ struct hexchatprefs
 	int hex_gui_win_state;
 	int hex_gui_win_top;
 	int hex_gui_win_width;
-	int hex_input_balloon_time;
+	int hex_identd_port;
 	int hex_irc_ban_type;
 	int hex_irc_join_delay;
 	int hex_irc_notice_pos;
@@ -329,7 +316,6 @@ struct hexchatprefs
 	guint32 dcc_ip;
 
 	unsigned int wait_on_exit;	/* wait for logs to be flushed to disk IF we're connected */
-	unsigned int utf8_locale;
 
 	/* Tells us if we need to save, only when they've been edited.
 		This is so that we continue using internal defaults (which can
@@ -382,12 +368,12 @@ typedef struct session
 	guint8 text_strip;
 
 	struct server *server;
-	void *usertree_alpha;			/* pure alphabetical tree */
-	void *usertree;					/* ordered with Ops first */
+	tree *usertree;					/* alphabetical tree */
 	struct User *me;					/* points to myself in the usertree */
 	char channel[CHANLEN];
 	char waitchannel[CHANLEN];		  /* waiting to join channel (/join sent) */
 	char willjoinchannel[CHANLEN];	  /* will issue /join for this channel */
+	char session_name[CHANLEN];		 /* the name of the session, should not modified */
 	char channelkey[64];			  /* XXX correct max length? */
 	int limit;						  /* channel user limit */
 	int logfd;
@@ -434,14 +420,6 @@ typedef struct session
 	void (*scrollback_replay_marklast) (struct session *sess);
 } session;
 
-struct msproxy_state_t
-{
-	gint32				clientid;
-	gint32				serverid;
-	unsigned char		seq_recv;		/* seq number of last packet recv.	*/
-	unsigned char		seq_sent;		/* seq number of last packet sent.	*/
-};
-
 /* SASL Mechanisms */
 #define MECH_PLAIN 0
 #define MECH_BLOWFISH 1
@@ -499,9 +477,9 @@ typedef struct server
 	int proxy_sok;				/* Additional information for MS Proxy beast */
 	int proxy_sok4;
 	int proxy_sok6;
-	struct msproxy_state_t msp_state;
 	int id;					/* unique ID number (for plugin API) */
 #ifdef USE_OPENSSL
+	SSL_CTX *ctx;
 	SSL *ssl;
 	int ssl_do_connect_tag;
 #else
@@ -554,7 +532,10 @@ typedef struct server
 	time_t ping_recv;					/* when we last got a ping reply */
 	time_t away_time;					/* when we were marked away */
 
-	char *encoding;					/* NULL for system */
+	char *encoding;
+	GIConv read_converter;  /* iconv converter for converting from server encoding to UTF-8. */
+	GIConv write_converter; /* iconv converter for converting from UTF-8 to server encoding. */
+
 	GSList *favlist;			/* list of channels & keys to join */
 
 	unsigned int motd_skipped:1;
@@ -587,8 +568,6 @@ typedef struct server
 	unsigned int have_except:1;	/* ban exemptions +e */
 	unsigned int have_invite:1;	/* invite exemptions +I */
 	unsigned int have_cert:1;	/* have loaded a cert */
-	unsigned int using_cp1255:1;	/* encoding is CP1255/WINDOWS-1255? */
-	unsigned int using_irc:1;		/* encoding is "IRC" (CP1252/UTF-8 hybrid)? */
 	unsigned int use_who:1;			/* whether to use WHO command to get dcc_ip */
 	unsigned int sasl_mech;			/* mechanism for sasl auth */
 	unsigned int sent_saslauth:1;	/* have sent AUTHENICATE yet */
@@ -631,7 +610,4 @@ struct popup
 /* CL: get a random int in the range [0..n-1]. DON'T use rand() % n, it gives terrible results. */
 #define RAND_INT(n) ((int)(rand() / (RAND_MAX + 1.0) * (n)))
 
-#define hexchat_filename_from_utf8 g_filename_from_utf8
-#define hexchat_filename_to_utf8 g_filename_to_utf8
-
 #endif
diff --git a/src/common/history.c b/src/common/history.c
index 1acd3327..23a8463e 100644
--- a/src/common/history.c
+++ b/src/common/history.c
@@ -18,14 +18,14 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <glib.h>
 #include "history.h"
 
 void
 history_add (struct history *his, char *text)
 {
-	if (his->lines[his->realpos])
-		free (his->lines[his->realpos]);
-	his->lines[his->realpos] = strdup (text);
+	g_free (his->lines[his->realpos]);
+	his->lines[his->realpos] = g_strdup (text);
 	his->realpos++;
 	if (his->realpos == HISTORY_SIZE)
 		his->realpos = 0;
@@ -40,7 +40,7 @@ history_free (struct history *his)
 	{
 		if (his->lines[i])
 		{
-			free (his->lines[i]);
+			g_free (his->lines[i]);
 			his->lines[i] = 0;
 		}
 	}
@@ -52,7 +52,7 @@ history_down (struct history *his)
 	int next;
 
 	if (his->pos == his->realpos)	/* allow down only after up */
-		return 0;
+		return NULL;
 	if (his->realpos == 0)
 	{
 		if (his->pos == HISTORY_SIZE - 1)
@@ -79,7 +79,7 @@ history_down (struct history *his)
 		return his->lines[his->pos];
 	}
 
-	return 0;
+	return NULL;
 }
 
 char *
@@ -90,11 +90,11 @@ history_up (struct history *his, char *current_text)
 	if (his->realpos == HISTORY_SIZE - 1)
 	{
 		if (his->pos == 0)
-			return 0;
+			return NULL;
 	} else
 	{
 		if (his->pos == his->realpos + 1)
-			return 0;
+			return NULL;
 	}
 
 	next = HISTORY_SIZE - 1;
@@ -117,5 +117,5 @@ history_up (struct history *his, char *current_text)
 		return his->lines[his->pos];
 	}
 
-	return 0;
+	return NULL;
 }
diff --git a/src/common/identd.c b/src/common/identd.c
deleted file mode 100644
index c4050929..00000000
--- a/src/common/identd.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* HexChat
- * Copyright (C) 1998-2010 Peter Zelezny.
- * Copyright (C) 2009-2013 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-/* simple identd server for HexChat under Win32 */
-
-#include "inet.h"
-#include "hexchat.h"
-#include "hexchatc.h"
-#include "text.h"
-
-static int identd_is_running = FALSE;
-#ifdef USE_IPV6
-static int identd_ipv6_is_running = FALSE;
-#endif
-
-static int
-identd (char *username)
-{
-	int sok, read_sok, len;
-	char *p;
-	char buf[256];
-	char outbuf[256];
-	char ipbuf[INET_ADDRSTRLEN];
-	struct sockaddr_in addr;
-
-	sok = socket (AF_INET, 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.sin_family = AF_INET;
-	addr.sin_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_is_running = FALSE;
-
-#if 0	/* causes random crashes, probably due to CreateThread */
-	EMIT_SIGNAL (XP_TE_IDENTD, current_sess, inet_ntoa (addr.sin_addr), username, NULL, NULL, 0);
-#endif
-	inet_ntop (AF_INET, &addr.sin_addr, ipbuf, sizeof (ipbuf));
-	snprintf (outbuf, sizeof (outbuf), "*\tServicing ident request from %s as %s\n", ipbuf, username);
-	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;
-}
-
-#ifdef USE_IPV6
-static int
-identd_ipv6 (char *username)
-{
-	int sok, read_sok, len;
-	char *p;
-	char buf[256];
-	char outbuf[256];
-	char ipbuf[INET6_ADDRSTRLEN];
-	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;
-
-	inet_ntop (AF_INET6, &addr.sin6_addr, ipbuf, sizeof (ipbuf));
-	snprintf (outbuf, sizeof (outbuf), "*\tServicing ident request from %s as %s\n", ipbuf, username);
-	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;
-		CloseHandle (CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) identd,
-						 strdup (username), 0, &tid));
-	}
-}
diff --git a/src/common/ignore.c b/src/common/ignore.c
index 045224ba..6085b657 100644
--- a/src/common/ignore.c
+++ b/src/common/ignore.c
@@ -53,7 +53,7 @@ static int ignored_total = 0;
 struct ignore *
 ignore_exists (char *mask)
 {
-	struct ignore *ig = 0;
+	struct ignore *ig = NULL;
 	GSList *list;
 
 	list = ignore_list;
@@ -79,7 +79,7 @@ ignore_exists (char *mask)
 int
 ignore_add (char *mask, int type, gboolean overwrite)
 {
-	struct ignore *ig = 0;
+	struct ignore *ig = NULL;
 	int change_only = FALSE;
 
 	/* first check if it's already ignored */
@@ -88,12 +88,9 @@ ignore_add (char *mask, int type, gboolean overwrite)
 		change_only = TRUE;
 
 	if (!change_only)
-		ig = malloc (sizeof (struct ignore));
+		ig = g_new (struct ignore, 1);
 
-	if (!ig)
-		return 0;
-
-	ig->mask = strdup (mask);
+	ig->mask = g_strdup (mask);
 
 	if (!overwrite && change_only)
 		ig->type |= type;
@@ -125,7 +122,7 @@ ignore_showlist (session *sess)
 		ig = list->data;
 		i++;
 
-		snprintf (tbuf, sizeof (tbuf), " %-25s ", ig->mask);
+		g_snprintf (tbuf, sizeof (tbuf), " %-25s ", ig->mask);
 		if (ig->type & IG_PRIV)
 			strcat (tbuf, _("YES  "));
 		else
@@ -192,8 +189,8 @@ ignore_del (char *mask, struct ignore *ig)
 	if (ig)
 	{
 		ignore_list = g_slist_remove (ignore_list, ig);
-		free (ig->mask);
-		free (ig);
+		g_free (ig->mask);
+		g_free (ig);
 		fe_ignore_update (1);
 		return TRUE;
 	}
@@ -265,7 +262,7 @@ ignore_read_next_entry (char *my_cfg, struct ignore *ignore)
 		my_cfg = cfg_get_str (my_cfg, "mask", tbuf, sizeof (tbuf));
 		if (!my_cfg)
 			return NULL;
-		ignore->mask = strdup (tbuf);
+		ignore->mask = g_strdup (tbuf);
 	}
 	if (my_cfg)
 	{
@@ -281,7 +278,7 @@ ignore_load ()
 	struct ignore *ignore;
 	struct stat st;
 	char *cfg, *my_cfg;
-	int fh, i;
+	int fh;
 
 	fh = hexchat_open_file ("ignore.conf", O_RDONLY, 0, 0);
 	if (fh != -1)
@@ -289,22 +286,18 @@ ignore_load ()
 		fstat (fh, &st);
 		if (st.st_size)
 		{
-			cfg = malloc (st.st_size + 1);
-			cfg[0] = '\0';
-			i = read (fh, cfg, st.st_size);
-			if (i >= 0)
-				cfg[i] = '\0';
+			cfg = g_malloc0 (st.st_size + 1);
+			read (fh, cfg, st.st_size);
 			my_cfg = cfg;
 			while (my_cfg)
 			{
-				ignore = malloc (sizeof (struct ignore));
-				memset (ignore, 0, sizeof (struct ignore));
+				ignore = g_new0 (struct ignore, 1);
 				if ((my_cfg = ignore_read_next_entry (my_cfg, ignore)))
 					ignore_list = g_slist_prepend (ignore_list, ignore);
 				else
-					free (ignore);
+					g_free (ignore);
 			}
-			free (cfg);
+			g_free (cfg);
 		}
 		close (fh);
 	}
@@ -326,7 +319,7 @@ ignore_save ()
 			ig = (struct ignore *) temp->data;
 			if (!(ig->type & IG_NOSAVE))
 			{
-				snprintf (buf, sizeof (buf), "mask = %s\ntype = %u\n\n",
+				g_snprintf (buf, sizeof (buf), "mask = %s\ntype = %u\n\n",
 							 ig->mask, ig->type);
 				write (fh, buf, strlen (buf));
 			}
@@ -379,9 +372,9 @@ flood_check (char *nick, char *ip, server *serv, session *sess, int what)	/*0=ct
 					for (i = 0; i < 128; i++)
 						if (ip[i] == '@')
 							break;
-					snprintf (real_ip, sizeof (real_ip), "*!*%s", &ip[i]);
+					g_snprintf (real_ip, sizeof (real_ip), "*!*%s", &ip[i]);
 
-					snprintf (buf, sizeof (buf),
+					g_snprintf (buf, sizeof (buf),
 								 _("You are being CTCP flooded from %s, ignoring %s\n"),
 								 nick, real_ip);
 					PrintText (sess, buf);
@@ -406,7 +399,7 @@ flood_check (char *nick, char *ip, server *serv, session *sess, int what)	/*0=ct
 				serv->msg_counter++;
 				if (serv->msg_counter == prefs.hex_flood_msg_num)	/*if we reached the maximun numbers of ctcp in the seconds limits */
 				{
-					snprintf (buf, sizeof (buf),
+					g_snprintf (buf, sizeof (buf),
 					 _("You are being MSG flooded from %s, setting gui_autoopen_dialog OFF.\n"),
 								 ip);
 					PrintText (sess, buf);
diff --git a/src/common/inbound.c b/src/common/inbound.c
index b80553b3..ef26890b 100644
--- a/src/common/inbound.c
+++ b/src/common/inbound.c
@@ -33,8 +33,6 @@
 #define WANTDNS
 #include "inet.h"
 
-#include <gio/gio.h>
-
 #include "hexchat.h"
 #include "util.h"
 #include "ignore.h"
@@ -64,7 +62,7 @@ clear_channel (session *sess)
 
 	if (sess->current_modes)
 	{
-		free (sess->current_modes);
+		g_free (sess->current_modes);
 		sess->current_modes = NULL;
 	}
 
@@ -83,9 +81,17 @@ clear_channel (session *sess)
 void
 set_topic (session *sess, char *topic, char *stripped_topic)
 {
-	if (sess->topic)
-		free (sess->topic);
-	sess->topic = strdup (stripped_topic);
+	/* The topic of dialogs are the users hostname which is logged is new */
+	if (sess->type == SESS_DIALOG && (!sess->topic || strcmp(sess->topic, stripped_topic))
+		&& sess->logfd != -1)
+	{
+		char tbuf[1024];
+		g_snprintf (tbuf, sizeof (tbuf), "[%s has address %s]\n", sess->channel, stripped_topic);
+		write (sess->logfd, tbuf, strlen (tbuf));
+	}
+
+	g_free (sess->topic);
+	sess->topic = g_strdup (stripped_topic);
 	fe_set_topic (sess, topic, stripped_topic);
 }
 
@@ -121,7 +127,7 @@ find_session_from_nick (char *nick, server *serv)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 static session *
@@ -182,16 +188,7 @@ inbound_privmsg (server *serv, char *from, char *ip, char *text, int id,
 		}
 
 		if (ip && ip[0])
-		{
-			if (prefs.hex_irc_logging && sess->logfd != -1 &&
-				(!sess->topic || strcmp(sess->topic, ip)))
-			{
-				char tbuf[1024];
-				snprintf (tbuf, sizeof (tbuf), "[%s has address %s]\n", from, ip);
-				write (sess->logfd, tbuf, strlen (tbuf));
-			}
 			set_topic (sess, ip, ip);
-		}
 		inbound_chanmsg (serv, NULL, NULL, from, text, FALSE, id, tags_data);
 		return;
 	}
@@ -558,7 +555,7 @@ find_unused_session (server *serv)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 static session *
@@ -576,7 +573,7 @@ find_session_from_waitchannel (char *chan, struct server *serv)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 void
@@ -682,7 +679,8 @@ inbound_nameslist (server *serv, char *chan, char *names,
 	char **name_list;
 	char *host, *nopre_name;
 	char name[NICKLEN];
-	int i, offset;
+	int i;
+	size_t offset;
 
 	sess = find_channel (serv, chan);
 	if (!sess)
@@ -916,7 +914,7 @@ inbound_ping_reply (session *sess, char *timestring, char *from,
 										  tags_data->timestamp);
 	} else
 	{
-		snprintf (outbuf, sizeof (outbuf), "%ld.%03ld", dif / 1000, dif % 1000);
+		g_snprintf (outbuf, sizeof (outbuf), "%ld.%03ld", dif / 1000, dif % 1000);
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_PINGREP, sess, from, outbuf, NULL, NULL, 0,
 									  tags_data->timestamp);
 	}
@@ -934,7 +932,7 @@ find_session_from_type (int type, server *serv)
 			return sess;
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 void
@@ -969,14 +967,14 @@ inbound_notice (server *serv, char *to, char *nick, char *msg, char *ip, int id,
 				/* guess where chanserv meant to post this -sigh- */
 				if (!g_ascii_strcasecmp (nick, "ChanServ") && !find_dialog (serv, nick))
 				{
-					char *dest = strdup (msg + 1);
+					char *dest = g_strdup (msg + 1);
 					char *end = strchr (dest, ']');
 					if (end)
 					{
 						*end = 0;
 						sess = find_channel (serv, dest);
 					}
-					free (dest);
+					g_free (dest);
 				}
 			}
 			if (!sess)
@@ -1455,8 +1453,7 @@ inbound_user_info (session *sess, char *chan, char *user, char *host,
 
 	if (user && host)
 	{
-		uhost = g_malloc (strlen (user) + strlen (host) + 2);
-		sprintf (uhost, "%s@%s", user, host);
+		uhost = g_strdup_printf ("%s@%s", user, host);
 	}
 
 	if (chan)
diff --git a/src/common/inet.h b/src/common/inet.h
index 990415be..7056d473 100644
--- a/src/common/inet.h
+++ b/src/common/inet.h
@@ -47,13 +47,9 @@
 
 #else
 
-#include "../../config.h"
-#ifdef USE_IPV6
+#include "config.h"
 #include <winsock2.h>
 #include <ws2tcpip.h>
-#else
-#include <winsock2.h>
-#endif
 
 #define set_blocking(sok)	{ \
 									unsigned long zero = 0; \
diff --git a/src/common/make-te.c b/src/common/make-te.c
index 309eec2f..834646ef 100644
--- a/src/common/make-te.c
+++ b/src/common/make-te.c
@@ -42,7 +42,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-int main()
+int main(void)
 {
 	char name[512];
 	char num[512];
@@ -87,9 +87,11 @@ int main()
 		if (i + 1 < max)
 		{
 			fprintf(stderr, "\t%s,\t\t%s,\n", defines[i], defines[i+1]);
+			free (defines[i]);
 			i++;
 		} else
 			fprintf(stderr, "\t%s,\n", defines[i]);
+		free (defines[i]);
 		i++;
 	}
 	fprintf(stderr, "\tNUM_XP\n};\n");
diff --git a/src/common/make-te.vcxproj b/src/common/make-te.vcxproj
index e9b4c533..24d8f9b6 100644
--- a/src/common/make-te.vcxproj
+++ b/src/common/make-te.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>Application</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,82 +20,30 @@
     <RootNamespace>makete</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>

-  </PropertyGroup>

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

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

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

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

+  <PropertyGroup>

+    <OutDir>$(HexChatLib)</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <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>"$(HexChatBin)make-te.exe" &lt; "$(ProjectDir)textevents.in" &gt; "$(ProjectDir)textevents.h" 2&gt; "$(ProjectDir)textenums.h"</Command>

-    </PostBuildEvent>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <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>"$(HexChatBin)make-te.exe" &lt; "$(ProjectDir)textevents.in" &gt; "$(ProjectDir)textevents.h" 2&gt; "$(ProjectDir)textenums.h"</Command>

-    </PostBuildEvent>

   </ItemDefinitionGroup>

   <ItemGroup>

     <ClCompile Include="make-te.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/src/common/modes.c b/src/common/modes.c
index b7cd471f..c65bf279 100644
--- a/src/common/modes.c
+++ b/src/common/modes.c
@@ -331,7 +331,7 @@ record_chan_mode (session *sess, char sign, char mode, char *arg)
 				current = g_string_erase(current, argument_offset+1, argument_length-1);
 				current = g_string_insert(current, argument_offset+1, arg);
 
-				free(sess->current_modes);
+				g_free(sess->current_modes);
 				sess->current_modes = g_string_free(current, FALSE);
 			}
 		}
@@ -348,7 +348,7 @@ record_chan_mode (session *sess, char sign, char mode, char *arg)
 				current = g_string_append(current, arg);
 			}
 
-			free(sess->current_modes);
+			g_free(sess->current_modes);
 			sess->current_modes = g_string_free(current, FALSE);
 		}
 	}
@@ -361,7 +361,7 @@ record_chan_mode (session *sess, char sign, char mode, char *arg)
 		/* remove the mode character */
 		current = g_string_erase(current, mode_pos, 1);
 
-		free(sess->current_modes);
+		g_free(sess->current_modes);
 		sess->current_modes = g_string_free(current, FALSE);
 	}
 }
@@ -374,12 +374,13 @@ mode_cat (char *str, char *addition)
 	if (str)
 	{
 		len = strlen (str) + strlen (addition) + 2;
-		str = realloc (str, len);
+		str = g_realloc (str, len);
 		strcat (str, " ");
 		strcat (str, addition);
-	} else
+	}
+	else
 	{
-		str = strdup (addition);
+		str = g_strdup (addition);
 	}
 
 	return str;
@@ -560,12 +561,12 @@ handle_single_mode (mode_run *mr, char sign, char mode, char *nick,
 	{
 		if (*arg)
 		{
-			char *buf = malloc (strlen (chan) + strlen (arg) + 2);
-			sprintf (buf, "%s %s", chan, arg);
+			char *buf = g_strdup_printf ("%s %s", chan, arg);
 			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMODEGEN, sess, nick, outbuf,
 										  outbuf + 2, buf, 0, tags_data->timestamp);
-			free (buf);
-		} else
+			g_free (buf);
+		}
+		else
 			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMODEGEN, sess, nick, outbuf,
 										  outbuf + 2, chan, 0, tags_data->timestamp);
 	}
@@ -635,7 +636,7 @@ mode_print_grouped (session *sess, char *nick, mode_run *mr,
 	{
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANOP, sess, nick, mr->op, NULL, NULL, 0,
 									  tags_data->timestamp);
-		free (mr->op);
+		g_free(mr->op);
 		mr->op = NULL;
 	}
 
@@ -643,7 +644,7 @@ mode_print_grouped (session *sess, char *nick, mode_run *mr,
 	{
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANDEOP, sess, nick, mr->deop, NULL, NULL,
 									  0, tags_data->timestamp);
-		free (mr->deop);
+		g_free(mr->deop);
 		mr->deop = NULL;
 	}
 
@@ -651,7 +652,7 @@ mode_print_grouped (session *sess, char *nick, mode_run *mr,
 	{
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANVOICE, sess, nick, mr->voice, NULL, NULL,
 									  0, tags_data->timestamp);
-		free (mr->voice);
+		g_free(mr->voice);
 		mr->voice = NULL;
 	}
 
@@ -659,7 +660,7 @@ mode_print_grouped (session *sess, char *nick, mode_run *mr,
 	{
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANDEVOICE, sess, nick, mr->devoice, NULL,
 									  NULL, 0, tags_data->timestamp);
-		free (mr->devoice);
+		g_free(mr->devoice);
 		mr->devoice = NULL;
 	}
 }
@@ -677,10 +678,10 @@ handle_mode (server * serv, char *word[], char *word_eol[],
 	char *argstr;
 	char sign;
 	int len;
-	int arg;
-	int i, num_args;
+	size_t arg;
+	size_t i, num_args;
 	int num_modes;
-	int offset = 3;
+	size_t offset = 3;
 	int all_modes_have_args = FALSE;
 	int using_front_tab = FALSE;
 	mode_run mr;
@@ -717,9 +718,8 @@ handle_mode (server * serv, char *word[], char *word_eol[],
 
 	if (numeric_324 && !using_front_tab)
 	{
-		if (sess->current_modes)
-			free (sess->current_modes);
-		sess->current_modes = strdup (word_eol[offset+1]);
+		g_free (sess->current_modes);
+		sess->current_modes = g_strdup (word_eol[offset+1]);
 	}
 
 	sign = *modes;
@@ -762,7 +762,7 @@ handle_mode (server * serv, char *word[], char *word_eol[],
 			break;
 		default:
 			argstr = "";
-			if ((all_modes_have_args || mode_has_arg (serv, sign, *modes)) && arg < (num_args+1))
+			if ((all_modes_have_args || mode_has_arg (serv, sign, *modes)) && arg < (num_args + 1))
 			{
 				arg++;
 				argstr = word[arg + offset];
@@ -799,30 +799,29 @@ inbound_005 (server * serv, char *word[], const message_tags_data *tags_data)
 			serv->modes_per_line = atoi (word[w] + 6);
 		} else if (strncmp (word[w], "CHANTYPES=", 10) == 0)
 		{
-			free (serv->chantypes);
-			serv->chantypes = strdup (word[w] + 10);
+			g_free (serv->chantypes);
+			serv->chantypes = g_strdup (word[w] + 10);
 		} else if (strncmp (word[w], "CHANMODES=", 10) == 0)
 		{
-			free (serv->chanmodes);
-			serv->chanmodes = strdup (word[w] + 10);
+			g_free (serv->chanmodes);
+			serv->chanmodes = g_strdup (word[w] + 10);
 		} else if (strncmp (word[w], "PREFIX=", 7) == 0)
 		{
 			pre = strchr (word[w] + 7, ')');
 			if (pre)
 			{
 				pre[0] = 0;			  /* NULL out the ')' */
-				free (serv->nick_prefixes);
-				free (serv->nick_modes);
-				serv->nick_prefixes = strdup (pre + 1);
-				serv->nick_modes = strdup (word[w] + 8);
+				g_free (serv->nick_prefixes);
+				g_free (serv->nick_modes);
+				serv->nick_prefixes = g_strdup (pre + 1);
+				serv->nick_modes = g_strdup (word[w] + 8);
 			} else
 			{
 				/* bad! some ircds don't give us the modes. */
 				/* in this case, we use it only to strip /NAMES */
 				serv->bad_prefix = TRUE;
-				if (serv->bad_nick_prefixes)
-					free (serv->bad_nick_prefixes);
-				serv->bad_nick_prefixes = strdup (word[w] + 7);
+				g_free (serv->bad_nick_prefixes);
+				serv->bad_nick_prefixes = g_strdup (word[w] + 7);
 			}
 		} else if (strncmp (word[w], "WATCH=", 6) == 0)
 		{
@@ -832,10 +831,6 @@ inbound_005 (server * serv, char *word[], const message_tags_data *tags_data)
 			serv->supports_monitor = TRUE;
 		} else if (strncmp (word[w], "NETWORK=", 8) == 0)
 		{
-/*			if (serv->networkname)
-				free (serv->networkname);
-			serv->networkname = strdup (word[w] + 8);*/
-
 			if (serv->server_session->type == SESS_SERVER)
 			{
 				safe_strcpy (serv->server_session->channel, word[w] + 8, CHANLEN);
diff --git a/src/common/msproxy.c b/src/common/msproxy.c
deleted file mode 100644
index 5f631c7f..00000000
--- a/src/common/msproxy.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/* X-Chat
- * Copyright (C) 1998 Peter Zelezny.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- *
- * MS Proxy (ISA server) support is (c) 2006 Pavel Fedin <sonic_amiga@rambler.ru>
- * based on Dante source code
- * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- *      Inferno Nettverk A/S, Norway.  All rights reserved.
- */
-
-/*#define DEBUG_MSPROXY*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
-#ifndef WIN32
-#include <unistd.h>
-#endif
-
-#define WANTSOCKET
-#define WANTARPA
-#include "inet.h"
-
-#include "hexchat.h"
-#include "network.h"
-#include "hexchatc.h"
-#include "server.h"
-#include "msproxy.h"
-
-
-#ifdef USE_MSPROXY
-#include <ntlm.h>
-
-static int
-send_msprequest(s, state, request, end)
-	int s;
-	struct msproxy_state_t *state;
-	struct msproxy_request_t *request;
-	char *end;
-{
-	ssize_t w;
-	size_t l;
-
-	request->magic25 = htonl(MSPROXY_VERSION);
-	request->serverack = state->seq_recv;
-	/* don't start incrementing sequence until we are acking packet #2. */
-	request->sequence	= (unsigned char)(request->serverack >= 2 ? state->seq_sent + 1 : 0);
-
-	memcpy(request->RWSP, "RWSP", sizeof(request->RWSP));
-
-	l = end - (char *)request;
-	/* all requests must be atleast MSPROXY_MINLENGTH it seems. */
-	if (l < MSPROXY_MINLENGTH) {
-		bzero(end, (size_t)(MSPROXY_MINLENGTH - l));
-		l = MSPROXY_MINLENGTH;
-	}
-
-	if ((w = send(s, request, l, 0)) != l) {
-#ifdef DEBUG_MSPROXY
-		printf ("send_msprequest(): send() failed (%ld bytes sent instead of %Iu\n", w, l);
-		perror ("Error is");
-#endif
-		return -1;
-	}
-	state->seq_sent = request->sequence;
-
-	return w;
-}
-
-static int
-recv_mspresponse(s, state, response)
-	int s;
-	struct msproxy_state_t *state;
-	struct msproxy_response_t *response;
-{
-	ssize_t r;
-
-	do {
-		if ((r = recv (s, response, sizeof (*response), 0)) < MSPROXY_MINLENGTH) {
-#ifdef DEBUG_MSPROXY
-			printf ("recv_mspresponse(): expected to read atleast %d, read %ld\n", MSPROXY_MINLENGTH, r);
-#endif
-			return -1;
-		}
-		if (state->seq_recv == 0)
-			break; /* not started incrementing yet. */
-#ifdef DEBUG_MSPROXY
-		if (response->sequence == state->seq_recv)
-			printf ("seq_recv: %d, dup response, seqnumber: 0x%x\n", state->seq_recv, response->sequence);
-#endif
-	} while (response->sequence == state->seq_recv);
-
-	state->seq_recv = response->sequence;
-
-	return r;
-}
-
-int
-traverse_msproxy (int sok, char *serverAddr, int port, struct msproxy_state_t *state, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound)
-{
-	struct msproxy_request_t req;
-	struct msproxy_response_t res;
-	char *data, *p;
-	char hostname[NT_MAXNAMELEN];
-	char ntdomain[NT_MAXNAMELEN];
-	char challenge[8];
-	netstore *ns_client;
-	int clientport;
-	guint32 destaddr;
-	guint32 flags;
-
-	if (!prefs.hex_net_proxy_auth || !prefs.hex_net_proxy_user[0] || !prefs.hex_net_proxy_pass[0] )
-		return 1;
-
-	/* MS proxy protocol implementation currently doesn't support IPv6 */
-	destaddr = net_getsockaddr_v4 (ns_proxy);
-	if (!destaddr)
-		return 1;
-
-	state->seq_recv = 0;
-	state->seq_sent = 0;
-
-#ifdef DEBUG_MSPROXY
-	printf ("Connecting to %s:%d via MS proxy\n", serverAddr, port);
-#endif
-
-	gethostname (hostname, NT_MAXNAMELEN);
-	p = strchr (hostname, '.');
-        if (p)
-        	*p = '\0';
-
-	bzero (&req, sizeof(req));
-	req.clientid		= htonl(0x0a000000);	/* Initial client ID is always 0x0a		*/
-	req.command		= htons(MSPROXY_HELLO);	/* HELLO command					*/
-	req.packet.hello.magic5	= htons(0x4b00);	/* Fill in magic values				*/
-	req.packet.hello.magic10	= htons(0x1400);
-	req.packet.hello.magic15	= htons(0x0400);
-	req.packet.hello.magic20	= htons(0x5704);
-	req.packet.hello.magic25	= htons(0x0004);
-	req.packet.hello.magic30	= htons(0x0100);
-	req.packet.hello.magic35	= htons(0x4a02);
-	req.packet.hello.magic40	= htons(0x3000);
-	req.packet.hello.magic45	= htons(0x4400);
-	req.packet.hello.magic50	= htons(0x3900);
-	data = req.packet.hello.data;
-	strcpy (data, prefs.hex_net_proxy_user);		/* Append a username				*/
-	data += strlen (prefs.hex_net_proxy_user)+2;		/* +2 automatically creates second empty string	*/
-	strcpy (data, MSPROXY_EXECUTABLE);		/* Append an application name			*/
-	data += strlen (MSPROXY_EXECUTABLE)+1;
-	strcpy (data, hostname);				/* Append a hostname				*/
-	data += strlen (hostname)+1;
-
-	if (send_msprequest(sok, state, &req, data) == -1)
-		return 1;
-
-	if (recv_mspresponse(sok, state, &res) == -1)
-		return 1;
-
-	if (strcmp(res.RWSP, "RWSP") != 0) {
-#ifdef DEBUG_MSPROXY
-		printf ("Received mailformed packet (no RWSP signature)\n");
-#endif
-		return 1;
-	}
-
-	if (ntohs(res.command) >> 8 != 0x10) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.command = 10??, is %x", ntohs(res.command));
-#endif
-		return 1;
-	}
-
-	state->clientid	= htonl(rand());
-	state->serverid	= res.serverid;
-
-#ifdef DEBUG_MSPROXY
-	printf ("clientid: 0x%x, serverid: 0x%0x\n", state->clientid, state->serverid);
-	printf ("packet #2\n");
-#endif
-
-	/* almost identical. */
-	req.clientid	= state->clientid;
-	req.serverid	= state->serverid;
-
-	if (send_msprequest(sok, state, &req, data) == -1)
-		return 1;
-
-	if (recv_mspresponse(sok, state, &res) == -1)
-		return 1;
-
-	if (res.serverid != state->serverid) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected serverid = 0x%x, is 0x%x\n",state->serverid, res.serverid);
-#endif
-		return 1;
-	}
-
-	if (res.sequence != 0x01) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.sequence = 0x01, is 0x%x\n", res.sequence);
-#endif
-		return 1;
-	}
-
-	if (ntohs(res.command) != MSPROXY_USERINFO_ACK) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_USERINFO_ACK, ntohs(res.command));
-#endif
-		return 1;
-	}
-
-#ifdef DEBUG_MSPROXY
-	printf ("packet #3\n");
-#endif
-
-	bzero(&req, sizeof(req));
-	req.clientid			= state->clientid;
-	req.serverid			= state->serverid;
-	req.command			= htons(MSPROXY_AUTHENTICATE);
-	memcpy(req.packet.auth.NTLMSSP, "NTLMSSP", sizeof("NTLMSSP"));
-	req.packet.auth.bindaddr	= htonl(0x02000000);
-	req.packet.auth.msgtype		= htonl(0x01000000);
-	/* NTLM flags:	0x80000000 Negotiate LAN Manager key
-			0x10000000 Negotiate sign
-			0x04000000 Request target
-			0x02000000 Negotiate OEM
-			0x00800000 Always sign
-			0x00020000 Negotiate NTLM
-	*/
-	req.packet.auth.flags		= htonl(0x06020000);
-
-	if (send_msprequest(sok, state, &req, &req.packet.auth.data) == -1)
-		return 1;
-
-	if (recv_mspresponse(sok, state, &res) == -1)
-		return 1;
-
-	if (res.serverid != state->serverid) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected serverid = 0x%x, is 0x%x\n", state->serverid, res.serverid);
-#endif
-		return 1;
-	}
-
-	if (ntohs(res.command) != MSPROXY_AUTHENTICATE_ACK) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_AUTHENTICATE_ACK, ntohs(res.command));
-#endif
-		return 1;
-	}
-
-	flags = res.packet.auth.flags & htonl(0x00020000);			/* Remember if the server supports NTLM */
-	memcpy(challenge, &res.packet.auth.challenge, sizeof(challenge));
-	memcpy(ntdomain, &res.packet.auth.NTLMSSP[res.packet.auth.target.offset], res.packet.auth.target.len);
-	ntdomain[res.packet.auth.target.len] = 0;
-
-#ifdef DEBUG_MSPROXY
-	printf ("ntdomain: \"%s\"\n", ntdomain);
-	printf ("packet #4\n");
-#endif
-
-	bzero(&req, sizeof(req));
-	req.clientid			= state->clientid;
-	req.serverid			= state->serverid;
-	req.command			= htons(MSPROXY_AUTHENTICATE_2);	/* Authentication response			*/
-	req.packet.auth2.magic3		= htons(0x0200);			/* Something					*/
-	memcpy(req.packet.auth2.NTLMSSP, "NTLMSSP", sizeof("NTLMSSP"));		/* Start of NTLM message				*/
-	req.packet.auth2.msgtype		= htonl(0x03000000);			/* Message type 2				*/
-	req.packet.auth2.flags		= flags | htonl(0x02000000);		/* Choose authentication method			*/
-	data = req.packet.auth2.data;
-	if (flags) {
-		req.packet.auth2.lm_resp.len	= 0;				/* We are here if NTLM is supported,		*/
-		req.packet.auth2.lm_resp.alloc	= 0;				/* Do not fill in insecure LM response		*/
-		req.packet.auth2.lm_resp.offset	= data - req.packet.auth2.NTLMSSP;
-		req.packet.auth2.ntlm_resp.len = 24;				/* Fill in NTLM response security buffer	*/
-		req.packet.auth2.ntlm_resp.alloc = 24;
-		req.packet.auth2.ntlm_resp.offset = data - req.packet.auth2.NTLMSSP;
-		ntlm_smb_nt_encrypt(prefs.hex_net_proxy_pass, challenge, data);		/* Append an NTLM response			*/
-		data += 24;	
-	} else {
-		req.packet.auth2.lm_resp.len	= 24;				/* Fill in LM response security buffer		*/
-		req.packet.auth2.lm_resp.alloc	= 24;
-		req.packet.auth2.lm_resp.offset	= data - req.packet.auth2.NTLMSSP;
-		ntlm_smb_encrypt(prefs.hex_net_proxy_pass, challenge, data);		/* Append an LM response			*/
-		data += 24;
-		req.packet.auth2.ntlm_resp.len = 0;				/* NTLM response is empty			*/
-		req.packet.auth2.ntlm_resp.alloc = 0;
-		req.packet.auth2.ntlm_resp.offset = data - req.packet.auth2.NTLMSSP;
-	}
-	req.packet.auth2.ntdomain_buf.len = strlen(ntdomain);			/* Domain name					*/
-	req.packet.auth2.ntdomain_buf.alloc = req.packet.auth2.ntdomain_buf.len;
-	req.packet.auth2.ntdomain_buf.offset = data - req.packet.auth2.NTLMSSP;
-	strcpy(data, ntdomain);
-	data += req.packet.auth2.ntdomain_buf.len;
-	req.packet.auth2.username_buf.len = strlen(prefs.hex_net_proxy_user);		/* Username					*/
-	req.packet.auth2.username_buf.alloc = req.packet.auth2.username_buf.len;
-	req.packet.auth2.username_buf.offset = data - req.packet.auth2.NTLMSSP;
-	strcpy(data, prefs.hex_net_proxy_user);
-	data += req.packet.auth2.username_buf.len;
-	req.packet.auth2.clienthost_buf.len = strlen(hostname);			/* Hostname					*/
-	req.packet.auth2.clienthost_buf.alloc = req.packet.auth2.clienthost_buf.len;
-	req.packet.auth2.clienthost_buf.offset = data - req.packet.auth2.NTLMSSP;
-	strcpy(data, hostname);
-	data += req.packet.auth2.clienthost_buf.len;
-	req.packet.auth2.sessionkey_buf.len = 0;				/* Session key (we don't use it)		*/
-	req.packet.auth2.sessionkey_buf.alloc = 0;
-	req.packet.auth2.sessionkey_buf.offset = data - req.packet.auth2.NTLMSSP;
-
-	if (send_msprequest(sok, state, &req, data) == -1)
-		return 1;
-
-	if (recv_mspresponse(sok, state, &res) == -1)
-		return 1;
-
-	if (res.serverid != state->serverid) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.serverid = 0x%x, is 0x%x\n", state->serverid, res.serverid);
-#endif
-		return 1;
-	}
-
-	if (res.clientack != 0x01) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.clientack = 0x01, is 0x%x\n", res.clientack);
-#endif
-		return 1;
-	}
-
-	if (ntohs(res.command) >> 8 != 0x47) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.command = 47??, is 0x%x\n", ntohs(res.command));
-#endif
-		return 1;
-	}
-
-	if (ntohs(res.command) ==  MSPROXY_AUTHENTICATE_2_NAK) {
-#ifdef DEBUG_MSPROXY
-		printf ("Authentication failed\n");
-#endif
-		return -1;
-	}
-
-#ifdef DEBUG_MSPROXY
-	printf ("packet #5\n");
-#endif
-
-	bzero(&req, sizeof(req));
-	req.clientid			= state->clientid;
-	req.serverid			= state->serverid;
-	req.command			= htons(MSPROXY_CONNECT);
-	req.packet.connect.magic2	= htons(0x0200);
-	req.packet.connect.magic6	= htons(0x0200);
-	req.packet.connect.destport	= htons(port);
-	req.packet.connect.destaddr	= destaddr;
-	data = req.packet.connect.executable;
-	strcpy(data, MSPROXY_EXECUTABLE);
-	data += strlen(MSPROXY_EXECUTABLE) + 1;
-
-	/*
-	 * need to tell server what port we will connect from, so we bind our sockets.
-	 */
-	ns_client = net_store_new ();
-	if (!bound) {
-		net_store_fill_any (ns_client);
-		net_bind(ns_client, csok4, csok6);
-#ifdef DEBUG_MSPROXY
-		perror ("bind() result");
-#endif
-	}
- 	clientport = net_getsockport(csok4, csok6);
-	if (clientport == -1) {
-#ifdef DEBUG_MSPROXY
-		printf ("Unable to obtain source port\n");
-#endif
-		return 1;
-	}
-	req.packet.connect.srcport = clientport;
-
-	if (send_msprequest(sok, state, &req, data) == -1)
-		return 1;
-
-	if (recv_mspresponse(sok, state, &res) == -1)
-		return 1;
-
-	if (ntohs(res.command) != MSPROXY_CONNECT_ACK) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.command = 0x%x, is 0x%x\n",MSPROXY_CONNECT_ACK, ntohs(res.command));
-#endif
-		return 1;
-	}
-
-	net_store_fill_v4 (ns_client, res.packet.connect.clientaddr, res.packet.connect.clientport);
-
-#ifdef DEBUG_MSPROXY
-	printf ("Connecting...\n");
-#endif
-	if (net_connect (ns_client, csok4, csok6, csok) != 0) {
-#ifdef DEBUG_MSPROXY
-		printf ("Failed to connect to port %d\n", htons(res.packet.connect.clientport));
-#endif
-		net_store_destroy (ns_client);
-		return 1;
-	}
-	net_store_destroy (ns_client);
-#ifdef DEBUG_MSPROXY
-	printf ("packet #6\n");
-#endif
-
-	req.clientid	= state->clientid;
-	req.serverid	= state->serverid;
-	req.command	= htons(MSPROXY_USERINFO_ACK);		
-
-	if (send_msprequest(sok, state, &req, req.packet.connack.data) == -1)
-		return 1;
-
-	return 0;
-}
-
-void
-msproxy_keepalive (void)
-{
-	server *serv;
-	GSList *list = serv_list;
-	struct msproxy_request_t req;
-	struct msproxy_response_t res;
-
-	while (list)
-	{
-		serv = list->data;
-		if (serv->connected && (serv->proxy_sok != -1))
-		{
-#ifdef DEBUG_MSPROXY
-			printf ("sending MS proxy keepalive packet\n");
-#endif
-
-			bzero(&req, sizeof(req));
-			req.clientid	= serv->msp_state.clientid;
-			req.serverid	= serv->msp_state.serverid;
-			req.command	= htons(MSPROXY_HELLO);
-			
-			if (send_msprequest(serv->proxy_sok, &serv->msp_state, &req, req.packet.hello.data) == -1)
-				continue;
-
-			recv_mspresponse(serv->proxy_sok, &serv->msp_state, &res);
-
-#ifdef DEBUG_MSPROXY
-			if (ntohs(res.command) != MSPROXY_USERINFO_ACK)
-				printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_USERINFO_ACK, ntohs(res.command));
-#endif
-		}
-		list = list->next;
-	}
-}
-
-#endif
diff --git a/src/common/msproxy.h b/src/common/msproxy.h
deleted file mode 100644
index 4371d704..00000000
--- a/src/common/msproxy.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/* X-Chat
- * Copyright (C) 1998 Peter Zelezny.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- *
- * MS Proxy (ISA server) support is (c) 2006 Pavel Fedin <sonic_amiga@rambler.ru>
- * based on Dante source code
- * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- *      Inferno Nettverk A/S, Norway.  All rights reserved.
- */
-
-#ifndef HEXCHAT_MSPROXY_H
-#define HEXCHAT_MSPROXY_H
-
-#include "network.h"
-
-#define MSPROXY_EXECUTABLE 		"hexchat.exe"	/* This probably can be used for access control on the server side */
-
-#define MSPROXY_MINLENGTH		172		/* minimum length of packet.				*/
-#define NT_MAXNAMELEN			17		/* maximum name length (domain etc), comes from NetBIOS */
-#define MSPROXY_VERSION			0x00010200	/* MS Proxy v2 ?					*/
-
-/* Commands / responses */
-#define MSPROXY_HELLO			0x0500	/* packet 1 from client.			*/
-#define MSPROXY_HELLO_ACK		0x1000	/* packet 1 from server.			*/
-
-#define MSPROXY_USERINFO_ACK		0x0400	/* packet 2 from server.			*/
-
-#define MSPROXY_AUTHENTICATE		0x4700	/* authentication request		*/
-#define MSPROXY_AUTHENTICATE_ACK	0x4714	/* authentication challenge		*/
-
-#define MSPROXY_AUTHENTICATE_2		0x4701	/* authentication response		*/
-#define MSPROXY_AUTHENTICATE_2_ACK	0x4715	/* authentication passed		*/
-#define MSPROXY_AUTHENTICATE_2_NAK	0x4716	/* authentication failure		*/
-
-#define MSPROXY_CONNECT			0x071e	/* connect request.			*/
-#define MSPROXY_CONNECT_ACK		0x0703	/* connect request accepted.		*/
-
-#pragma pack(1)
-
-struct ntlm_buffer {
-	guint16	len;
-	guint16	alloc;
-	guint32	offset;
-};
-
-struct msproxy_request_t {
-	guint32					clientid;			/* 1-4							*/
-	guint32					magic25;				/* 5-8							*/
-	guint32					serverid;			/* 9-12							*/
-	unsigned char				serverack;			/* 13: ack of last server packet			*/
-	char					pad10[3];			/* 14-16						*/
-	unsigned char				sequence;			/* 17: sequence # of this packet.			*/
-	char					pad11[7];			/* 18-24						*/
-	char					RWSP[4];			/* 25-28: 0x52,0x57,0x53,0x50				*/
-	char					pad15[8];			/* 29-36						*/
-	guint16					command;				/* 37-38						*/
-
-	/* packet specifics start at 39. */
-	union {
-		struct {
-			char			pad1[18];			/* 39-56						*/
-			guint16			magic3;				/* 57-58						*/
-			char           		pad3[114];			/* 59-172						*/
-			guint16			magic5;				/* 173-174: 0x4b, 0x00					*/
-			char			pad5[2];			/* 175-176						*/
-			guint16			magic10;				/* 177-178: 0x14, 0x00					*/
-			char			pad6[2];			/* 179-180						*/
-			guint16			magic15;				/* 181-182: 0x04, 0x00					*/
-			char			pad10[2];			/* 183-184						*/
-			guint16			magic16;				/* 185-186						*/
-			char			pad11[2];			/* 187-188						*/
-			guint16			magic20;				/* 189-190: 0x57, 0x04					*/
-			guint16			magic25;				/* 191-192: 0x00, 0x04					*/
-			guint16			magic30;				/* 193-194: 0x01, 0x00					*/
-			char			pad20[2];			/* 195-196: 0x4a, 0x02					*/
-			guint16			magic35;				/* 197-198: 0x4a, 0x02					*/
-			char			pad30[10];			/* 199-208						*/
-			guint16			magic40;				/* 209-210: 0x30, 0x00					*/
-			char			pad40[2];			/* 211-212						*/
-			guint16			magic45;				/* 213-214: 0x44, 0x00					*/
-			char			pad45[2];			/* 215-216						*/
-			guint16			magic50;				/* 217-218: 0x39, 0x00					*/
-			char			pad50[2];			/* 219-220						*/
-			char			data[256];			/* 221-EOP: a sequence of NULL-terminated strings:
-											- username;
-											- empty string (just a NULL);
-											- application name;
-											- hostname					*/
-		} hello;
-
-		struct {
-			char			pad1[4];			/* 39-42						*/
-			guint16			magic2;				/* 43-44						*/
-			char			pad10[12];			/* 45-56						*/
-			guint32			bindaddr;			/* 57-60: address to bind.				*/
-			guint16			bindport;			/* 61-62: port to bind.					*/
-			char           		pad15[2];			/* 63-64						*/
-			guint16			magic3;				/* 65-66						*/
-			guint16			boundport;			/* 67-68						*/
-			char           		pad20[104];			/* 69-172						*/
-			char			NTLMSSP[sizeof("NTLMSSP")];	/* 173-180: "NTLMSSP"					*/
-			guint32			msgtype;				/* 181-184: NTLM message type = 1			*/
-			guint32			flags;				/* 185-188: NTLM message flags				*/
-			guint16			magic20;				/* 189-190: 0x28, 0x00					*/
-			char			pad30[2];			/* 191-192						*/
-			guint16			magic25;				/* 193-194: 0x96, 0x82					*/
-			guint16			magic30;				/* 195-196: 0x01, 0x00					*/
-			char			pad40[12];			/* 197-208						*/
-			guint16			magic50;				/* 209-210: 0x30, 0x00					*/
-			char			pad50[6];			/* 211-216						*/
-			guint16			magic55;				/* 217-218: 0x30, 0x00					*/
-			char			pad55[2];			/* 219-220						*/
-			char			data[0];			/* Dummy end marker, no real data required		*/
-		} auth;
-
-		struct {
-			char			pad1[4];			/* 39-42						*/
-			guint16			magic1;				/* 43-44						*/
-			guint32			magic2;				/* 45-48						*/
-			char			pad2[8];			/* 49-56						*/
-			guint16			magic3;				/* 57-58						*/
-			char			pad3[6];			/* 59-64						*/
-			guint16			magic4;				/* 65-66						*/
-			guint16			boundport;			/* 67-68						*/
-			char           		pad4[104];			/* 69-172						*/
-			char			NTLMSSP[sizeof("NTLMSSP")];	/* 173-180: "NTLMSSP"					*/
-			guint32			msgtype;				/* 181-184: NTLM message type = 3			*/
-			struct ntlm_buffer	lm_resp;				/* 185-192: LM response security buffer			*/
-			struct ntlm_buffer	ntlm_resp;			/* 193-200: NTLM response security buffer		*/
-			struct ntlm_buffer	ntdomain_buf;			/* 201-208: domain name security buffer			*/
-			struct ntlm_buffer	username_buf;			/* 209-216: username security buffer			*/
-			struct ntlm_buffer	clienthost_buf;			/* 217-224: hostname security buffer			*/
-			struct ntlm_buffer	sessionkey_buf;			/* 225-232: session key security buffer			*/
-			guint32			flags;				/* 233-236: message flags				*/
-			char			data[1024];			/* 237-EOP: data area					*/
-		} auth2;
-
-		struct {
-			guint16			magic1;				/* 39-40						*/
-			char			pad1[2];			/* 41-42						*/
-			guint16			magic2;				/* 43-44						*/
-			guint32			magic3;				/* 45-48						*/
-			char			pad5[8];			/* 48-56						*/
-			guint16			magic6;				/* 57-58: 0x0200					*/
-			guint16			destport;			/* 59-60						*/
-			guint32			destaddr;			/* 61-64						*/
-			char			pad10[4];			/* 65-68						*/
-			guint16			magic10;				/* 69-70						*/
-			char			pad15[2];			/* 71-72						*/
-			guint16			srcport;			/* 73-74: port client connects from			*/
-			char			pad20[82];			/* 75-156						*/
-			char			executable[256];		/* 76-EOP: application name				*/
-		} connect;
-
-		struct {
-			guint16			magic1;				/* 39-40						*/
-			char			pad5[2];			/* 41-42						*/
-			guint16			magic5;				/* 43-44						*/
-			guint32			magic10;				/* 45-48						*/
-			char			pad10[2];			/* 49-50						*/
-			guint16			magic15;				/* 51-52						*/
-			guint32			magic16;				/* 53-56						*/
-			guint16			magic20;				/* 57-58						*/
-			guint16			clientport;			/* 59-60: forwarded port.				*/
-			guint32			clientaddr;			/* 61-64: forwarded address.				*/
-			guint32			magic30;				/* 65-68						*/
-			guint32			magic35;				/* 69-72						*/
-			guint16			serverport;			/* 73-74: port server will connect to us from.		*/
-			guint16			srcport;			/* 75-76: connect request; port used on client behalf.	*/
-			guint16			boundport;			/* 77-78: bind request; port used on client behalf.	*/
-			guint32			boundaddr;			/* 79-82: addr used on client behalf			*/
-			char			pad30[90];			/* 83-172						*/
-			char			data[0];			/* End marker						*/
-		} connack;
-
-	} packet;
-};
-
-struct msproxy_response_t {
-	guint32					packetid;			/* 1-4							*/
-	guint32					magic5;				/* 5-8							*/
-	guint32             			serverid;			/* 9-12							*/
-	char					clientack;			/* 13: ack of last client packet.			*/
-	char					pad5[3];			/* 14-16						*/
-	unsigned char				sequence;			/* 17: sequence # of this packet.			*/
-	char					pad10[7];			/* 18-24						*/
-	char					RWSP[4];			/* 25-28: 0x52,0x57,0x53,0x50				*/
-	char					pad15[8];			/* 29-36						*/
-	guint16					command;				/* 37-38						*/
-
-	union {
-		struct {
-			char			pad5[18];			/* 39-56						*/
-			guint16			magic20;				/* 57-58: 0x02, 0x00					*/
-			char			pad10[6];			/* 59-64						*/
-			guint16			magic30;				/* 65-66: 0x74, 0x01					*/
-			char			pad15[2];			/* 67-68						*/
-			guint16			magic35;				/* 69-70: 0x0c, 0x00					*/
-			char			pad20[6];			/* 71-76						*/
-			guint16			magic50;				/* 77-78: 0x04, 0x00					*/
-			char			pad30[6];			/* 79-84						*/
-			guint16			magic60;				/* 85-86: 0x65, 0x05					*/
-			char			pad35[2];			/* 87-88						*/
-			guint16			magic65;				/* 89-90: 0x02, 0x00					*/
-			char			pad40[8];			/* 91-98						*/
-			guint16			udpport;			/* 99-100						*/
-			guint32			udpaddr;			/* 101-104						*/
-		} hello;
-
-		struct {
-			char			pad1[6];			/* 39-44						*/
-			guint32			magic10;				/* 45-48						*/
-			char			pad3[10];			/* 49-58						*/
-			guint16			boundport;			/* 59-60: port server bound for us.			*/
-			guint32			boundaddr;			/* 61-64: addr server bound for us.			*/
-			char			pad10[4];			/* 65-68						*/
-			guint16			magic15;				/* 69-70						*/
-			char			pad15[102];			/* 70-172						*/
-			char			NTLMSSP[sizeof("NTLMSSP")];	/* 173-180: "NTLMSSP"					*/
-			guint32			msgtype;				/* 181-184: NTLM message type = 2			*/
-			struct ntlm_buffer	target;				/* 185-192: target security buffer			*/
-			guint32			flags;				/* 193-196: NTLM message flags				*/
-			char			challenge[8];			/* 197-204: NTLM challenge request			*/
-			char			context[8];			/* 205-212: NTLM context				*/
-			char			data[1024];			/* 213-EOP: target information data			*/
-		} auth;
-
-		struct {
-			guint16			magic1;				/* 39-40						*/
-			char			pad5[18];			/* 41-58						*/
-			guint16			clientport;			/* 59-60: forwarded port.				*/
-			guint32			clientaddr;			/* 61-64: forwarded address.				*/
-			guint32			magic10;				/* 65-68						*/
-			guint32			magic15;				/* 69-72						*/
-			guint16			serverport;			/* 73-74: port server will connect to us from.		*/
-			guint16			srcport;			/* 75-76: connect request; port used on client behalf.	*/
-			guint16			boundport;			/* 77-78: bind request; port used on client behalf.	*/
-			guint32			boundaddr;			/* 79-82: addr used on client behalf			*/
-			char			pad10[90];			/* 83-172						*/
-		} connect;
-	} packet;
-};
-
-#pragma pack()
-
-int traverse_msproxy (int sok, char *serverAddr, int port, struct msproxy_state_t *state, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound);
-void msproxy_keepalive (void);
-
-#endif
diff --git a/src/common/network.c b/src/common/network.c
index 8790f673..fcdaf547 100644
--- a/src/common/network.c
+++ b/src/common/network.c
@@ -18,6 +18,8 @@
 
 /* ipv4 and ipv6 networking functions with a common interface */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -26,7 +28,6 @@
 #ifndef WIN32
 #include <unistd.h>
 #endif
-#include "../../config.h"
 
 #define WANTSOCKET
 #define WANTARPA
@@ -64,128 +65,17 @@ net_ip (guint32 addr)
 void
 net_store_destroy (netstore * ns)
 {
-#ifdef USE_IPV6
 	if (ns->ip6_hostent)
 		freeaddrinfo (ns->ip6_hostent);
-#endif
-	free (ns);
+	g_free (ns);
 }
 
 netstore *
 net_store_new (void)
 {
-	netstore *ns;
-
-	ns = malloc (sizeof (netstore));
-	memset (ns, 0, sizeof (netstore));
-
-	return ns;
-}
-
-#ifndef USE_IPV6
-
-/* =================== IPV4 ================== */
-
-/*
-	A note about net_resolve and lookupd:
-
-	Many IRC networks rely on round-robin DNS for load balancing, rotating the list
-	of IP address on each query. However, this method breaks when DNS queries are
-	cached. Mac OS X and Darwin handle DNS lookups through the lookupd daemon, which
-	caches queries in its default configuration: thus, if we always pick the first
-	address, we will be stuck with the same host (which might be down!) until the
-	TTL reaches 0 or lookupd is reset (typically, at reboot). Therefore, we need to
-	pick a random address from the result list, instead of always using the first.
-*/
-
-char *
-net_resolve (netstore * ns, char *hostname, int port, char **real_host)
-{
-	ns->ip4_hostent = gethostbyname (hostname);
-	if (!ns->ip4_hostent)
-		return NULL;
-
-	memset (&ns->addr, 0, sizeof (ns->addr));
-#ifdef LOOKUPD
-	int count = 0;
-	while (ns->ip4_hostent->h_addr_list[count]) count++;
-	memcpy (&ns->addr.sin_addr,
-			ns->ip4_hostent->h_addr_list[RAND_INT(count)],
-			ns->ip4_hostent->h_length);
-#else
-	memcpy (&ns->addr.sin_addr, ns->ip4_hostent->h_addr,
-			  ns->ip4_hostent->h_length);
-#endif
-	ns->addr.sin_port = htons (port);
-	ns->addr.sin_family = AF_INET;
-
-	*real_host = strdup (ns->ip4_hostent->h_name);
-	return strdup (inet_ntoa (ns->addr.sin_addr));
-}
-
-int
-net_connect (netstore * ns, int sok4, int sok6, int *sok_return)
-{
-	*sok_return = sok4;
-	return connect (sok4, (struct sockaddr *) &ns->addr, sizeof (ns->addr));
-}
-
-void
-net_bind (netstore * tobindto, int sok4, int sok6)
-{
-	bind (sok4, (struct sockaddr *) &tobindto->addr, sizeof (tobindto->addr));
-}
-
-void
-net_sockets (int *sok4, int *sok6)
-{
-	*sok4 = socket (AF_INET, SOCK_STREAM, 0);
-	*sok6 = -1;
-	net_set_socket_options (*sok4);
-}
-
-void
-udp_sockets (int *sok4, int *sok6)
-{
-	*sok4 = socket (AF_INET, SOCK_DGRAM, 0);
-	*sok6 = -1;
-}
-
-void
-net_store_fill_any (netstore *ns)
-{
-	ns->addr.sin_family = AF_INET;
-	ns->addr.sin_addr.s_addr = INADDR_ANY;
-	ns->addr.sin_port = 0;
-}
-
-void
-net_store_fill_v4 (netstore *ns, guint32 addr, int port)
-{
-	ns->addr.sin_family = AF_INET;
-	ns->addr.sin_addr.s_addr = addr;
-	ns->addr.sin_port = port;
+	return g_new0 (netstore, 1);
 }
 
-guint32
-net_getsockaddr_v4 (netstore *ns)
-{
-	return ns->addr.sin_addr.s_addr;
-}
-
-int
-net_getsockport (int sok4, int sok6)
-{
-	struct sockaddr_in addr;
-	int len = sizeof (addr);
-
-	if (getsockname (sok4, (struct sockaddr *)&addr, &len) == -1)
-		return -1;
-	return addr.sin_port;
-}
-
-#else
-
 /* =================== IPV6 ================== */
 
 char *
@@ -231,11 +121,11 @@ net_resolve (netstore * ns, char *hostname, int port, char **real_host)
 					 ipstring, sizeof (ipstring), NULL, 0, NI_NUMERICHOST);
 
 	if (ns->ip6_hostent->ai_canonname)
-		*real_host = strdup (ns->ip6_hostent->ai_canonname);
+		*real_host = g_strdup (ns->ip6_hostent->ai_canonname);
 	else
-		*real_host = strdup (hostname);
+		*real_host = g_strdup (hostname);
 
-	return strdup (ipstring);
+	return g_strdup (ipstring);
 }
 
 /* the only thing making this interface unclean, this shitty sok4, sok6 business */
@@ -298,88 +188,3 @@ udp_sockets (int *sok4, int *sok6)
 	*sok4 = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 	*sok6 = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
 }
-
-/* the following functions are used only by MSPROXY and are not
-   proper ipv6 implementations - do not use in new code! */
-
-void
-net_store_fill_any (netstore *ns)
-{
-	struct addrinfo *ai;
-	struct sockaddr_in *sin;
-
-	ai = ns->ip6_hostent;
-	if (!ai) {
-		ai = malloc (sizeof (struct addrinfo));
-		memset (ai, 0, sizeof (struct addrinfo));
-		ns->ip6_hostent = ai;
-	}
-	sin = (struct sockaddr_in *)ai->ai_addr;
-	if (!sin) {
-		sin = malloc (sizeof (struct sockaddr_in));
-		memset (sin, 0, sizeof (struct sockaddr_in));
-		ai->ai_addr = (struct sockaddr *)sin;
-	}
-	ai->ai_family = AF_INET;
-	ai->ai_addrlen = sizeof(struct sockaddr_in);
-	sin->sin_family = AF_INET;
-	sin->sin_addr.s_addr = INADDR_ANY;
-	sin->sin_port = 0;
-	ai->ai_next = NULL;
-}
-
-void
-net_store_fill_v4 (netstore *ns, guint32 addr, int port)
-{
-	struct addrinfo *ai;
-	struct sockaddr_in *sin;
-
-	ai = ns->ip6_hostent;
-	if (!ai) {
-		ai = malloc (sizeof (struct addrinfo));
-		memset (ai, 0, sizeof (struct addrinfo));
-		ns->ip6_hostent = ai;
-	}
-	sin = (struct sockaddr_in *)ai->ai_addr;
-	if (!sin) {
-		sin = malloc (sizeof (struct sockaddr_in));
-		memset (sin, 0, sizeof (struct sockaddr_in));
-		ai->ai_addr = (struct sockaddr *)sin;
-	}
-	ai->ai_family = AF_INET;
-	ai->ai_addrlen = sizeof(struct sockaddr_in);
-	sin->sin_family = AF_INET;
-	sin->sin_addr.s_addr = addr;
-	sin->sin_port = port;
-	ai->ai_next = NULL;
-}
-
-guint32
-net_getsockaddr_v4 (netstore *ns)
-{
-	struct addrinfo *ai;
-	struct sockaddr_in *sin;
-
-	ai = ns->ip6_hostent;
-
-	while (ai->ai_family != AF_INET) {
-		ai = ai->ai_next;
-		if (!ai)
-			return 0;
-	}
-	sin = (struct sockaddr_in *)ai->ai_addr;
-	return sin->sin_addr.s_addr;
-}
-
-int
-net_getsockport (int sok4, int sok6)
-{
-	struct sockaddr_in addr;
-	int len = sizeof (addr);
-
-	if (getsockname (sok4, (struct sockaddr *)&addr, &len) == -1)
-		return -1;
-	return addr.sin_port;
-}
-
-#endif
diff --git a/src/common/network.h b/src/common/network.h
index 6a4dce39..8c1c0c79 100644
--- a/src/common/network.h
+++ b/src/common/network.h
@@ -23,13 +23,8 @@
 typedef struct netstore_
 {
 #ifdef NETWORK_PRIVATE
-#ifdef USE_IPV6
 	struct addrinfo *ip6_hostent;
 #else
-	struct hostent *ip4_hostent;
-	struct sockaddr_in addr;
-#endif
-#else
 	int _dummy;	/* some compilers don't like empty structs */
 #endif
 } netstore;
@@ -43,11 +38,5 @@ char *net_resolve (netstore *ns, char *hostname, int port, char **real_host);
 void net_bind (netstore *tobindto, int sok4, int sok6);
 char *net_ip (guint32 addr);
 void net_sockets (int *sok4, int *sok6);
-/* functions for MSPROXY only! */
-void udp_sockets (int *sok4, int *sok6);
-void net_store_fill_any (netstore *ns);
-void net_store_fill_v4 (netstore *ns, guint32 addr, int port);
-guint32 net_getsockaddr_v4 (netstore *ns);
-int net_getsockport(int sok4, int sok6);
 
 #endif
diff --git a/src/common/notify.c b/src/common/notify.c
index bf80a1b5..b5316c36 100644
--- a/src/common/notify.c
+++ b/src/common/notify.c
@@ -47,7 +47,7 @@ int notify_tag = 0;
 static char *
 despacify_dup (char *str)
 {
-	char *p, *res = malloc (strlen (str) + 1);
+	char *p, *res = g_malloc (strlen (str) + 1);
 
 	p = res;
 	while (1)
@@ -70,11 +70,11 @@ notify_netcmp (char *str, void *serv)
 
 	if (rfc_casecmp (str, net) == 0)
 	{
-		free (net);
+		g_free (net);
 		return 0;	/* finish & return FALSE from token_foreach() */
 	}
 
-	free (net);
+	g_free (net);
 	return 1;	/* keep going... */
 }
 
@@ -111,14 +111,10 @@ notify_find_server_entry (struct notify *notify, struct server *serv)
 	if (!notify_do_network (notify, serv))
 		return NULL;
 
-	servnot = malloc (sizeof (struct notify_per_server));
-	if (servnot)
-	{
-		memset (servnot, 0, sizeof (struct notify_per_server));
-		servnot->server = serv;
-		servnot->notify = notify;
-		notify->server_list = g_slist_prepend (notify->server_list, servnot);
-	}
+	servnot = g_new0 (struct notify_per_server, 1);
+	servnot->server = serv;
+	servnot->notify = notify;
+	notify->server_list = g_slist_prepend (notify->server_list, servnot);
 	return servnot;
 }
 
@@ -200,7 +196,7 @@ notify_find (server *serv, char *nick)
 		list = list->next;
 	}
 
-	return 0;
+	return NULL;
 }
 
 static void
@@ -247,10 +243,9 @@ notify_announce_online (server * serv, struct notify_per_server *servnot,
 
 	    /* Let's do whois with idle time (like in /quote WHOIS %s %s) */
 
-	    char *wii_str = malloc (strlen (nick) * 2 + 2);
-	    sprintf (wii_str, "%s %s", nick, nick);
+	    char *wii_str = g_strdup_printf ("%s %s", nick, nick);
 	    serv->p_whois (serv, wii_str);
-	    free (wii_str);
+	    g_free (wii_str);
 	}
 }
 
@@ -346,9 +341,9 @@ notify_watch (server * serv, char *nick, int add)
 		addchar = '-';
 
 	if (serv->supports_monitor)
-		snprintf (tbuf, sizeof (tbuf), "MONITOR %c %s", addchar, nick);
+		g_snprintf (tbuf, sizeof (tbuf), "MONITOR %c %s", addchar, nick);
 	else if (serv->supports_watch)
-		snprintf (tbuf, sizeof (tbuf), "WATCH %c%s", addchar, nick);
+		g_snprintf (tbuf, sizeof (tbuf), "WATCH %c%s", addchar, nick);
 	else
 		return;
 
@@ -561,9 +556,9 @@ notify_showlist (struct session *sess, const message_tags_data *tags_data)
 		notify = (struct notify *) list->data;
 		servnot = notify_find_server_entry (notify, sess->server);
 		if (servnot && servnot->ison)
-			snprintf (outbuf, sizeof (outbuf), _("  %-20s online\n"), notify->name);
+			g_snprintf (outbuf, sizeof (outbuf), _("  %-20s online\n"), notify->name);
 		else
-			snprintf (outbuf, sizeof (outbuf), _("  %-20s offline\n"), notify->name);
+			g_snprintf (outbuf, sizeof (outbuf), _("  %-20s offline\n"), notify->name);
 		PrintTextTimeStamp (sess, outbuf, tags_data->timestamp);
 		list = list->next;
 	}
@@ -596,14 +591,13 @@ notify_deluser (char *name)
 				servnot = (struct notify_per_server *) notify->server_list->data;
 				notify->server_list =
 					g_slist_remove (notify->server_list, servnot);
-				free (servnot);
+				g_free (servnot);
 			}
 			notify_list = g_slist_remove (notify_list, notify);
 			notify_watch_all (notify, FALSE);
-			if (notify->networks)
-				free (notify->networks);
-			free (notify->name);
-			free (notify);
+			g_free (notify->networks);
+			g_free (notify->name);
+			g_free (notify);
 			fe_notify_update (0);
 			return 1;
 		}
@@ -615,27 +609,18 @@ notify_deluser (char *name)
 void
 notify_adduser (char *name, char *networks)
 {
-	struct notify *notify = malloc (sizeof (struct notify));
-	if (notify)
-	{
-		memset (notify, 0, sizeof (struct notify));
-		if (strlen (name) >= NICKLEN)
-		{
-			notify->name = malloc (NICKLEN);
-			safe_strcpy (notify->name, name, NICKLEN);
-		} else
-		{
-			notify->name = strdup (name);
-		}
-		if (networks)
-			notify->networks = despacify_dup (networks);
-		notify->server_list = 0;
-		notify_list = g_slist_prepend (notify_list, notify);
-		notify_checklist ();
-		fe_notify_update (notify->name);
-		fe_notify_update (0);
-		notify_watch_all (notify, TRUE);
-	}
+	struct notify *notify = g_new0 (struct notify, 1);
+
+	notify->name = g_strndup (name, NICKLEN - 1);
+
+	if (networks != NULL)
+		notify->networks = despacify_dup (networks);
+	notify->server_list = 0;
+	notify_list = g_slist_prepend (notify_list, notify);
+	notify_checklist ();
+	fe_notify_update (notify->name);
+	fe_notify_update (0);
+	notify_watch_all (notify, TRUE);
 }
 
 gboolean
@@ -714,7 +699,7 @@ notify_cleanup ()
 			{
 				notify->server_list =
 					g_slist_remove (notify->server_list, servnot);
-				free (servnot);
+				g_free (servnot);
 				nslist = notify->server_list;
 			} else
 			{
diff --git a/src/common/outbound.c b/src/common/outbound.c
index 651558ce..a4611927 100644
--- a/src/common/outbound.c
+++ b/src/common/outbound.c
@@ -90,7 +90,7 @@ random_line (char *file_name)
 	{
 	 nofile:
 		/* reason is not a file, an actual reason! */
-		return strdup (file_name);
+		return g_strdup (file_name);
 	}
 
 	/* count number of lines in file */
@@ -111,7 +111,7 @@ random_line (char *file_name)
 	}
 	while (lines > ran);
 	fclose (fh);
-	return strdup (buf);
+	return g_strdup (buf);
 }
 
 void
@@ -121,7 +121,7 @@ server_sendpart (server * serv, char *channel, char *reason)
 	{
 		reason = random_line (prefs.hex_irc_part_reason);
 		serv->p_part (serv, channel, reason);
-		free (reason);
+		g_free (reason);
 	} else
 	{
 		/* reason set by /quit, /close argument */
@@ -136,12 +136,12 @@ server_sendquit (session * sess)
 
 	if (!sess->quitreason)
 	{
-		colrea = strdup (prefs.hex_irc_quit_reason);
+		colrea = g_strdup (prefs.hex_irc_quit_reason);
 		check_special_chars (colrea, FALSE);
 		rea = random_line (colrea);
-		free (colrea);
+		g_free (colrea);
 		sess->server->p_quit (sess->server, rea);
-		free (rea);
+		g_free (rea);
 	} else
 	{
 		/* reason set by /quit, /close argument */
@@ -269,7 +269,7 @@ cmd_addserver (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		if (!network)
 		{
 			network = servlist_net_add (word[2], "", TRUE);
-			network->encoding = strdup (IRC_DEFAULT_CHARSET);
+			network->encoding = g_strdup (IRC_DEFAULT_CHARSET);
 		}
 		/* if we had the network already, check if the given server already exists */
 		else if (servlist_server_find (network, word_eol[3], NULL))
@@ -379,11 +379,10 @@ cmd_away (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 
 	if (sess->server->last_away_reason != reason)
 	{
-		if (sess->server->last_away_reason)
-			free (sess->server->last_away_reason);
+		g_free (sess->server->last_away_reason);
 
 		if (reason == word_eol[2])
-			sess->server->last_away_reason = strdup (reason);
+			sess->server->last_away_reason = g_strdup (reason);
 		else
 			sess->server->last_away_reason = reason;
 	}
@@ -406,8 +405,7 @@ cmd_back (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		PrintText (sess, _("Already marked back.\n"));
 	}
 
-	if (sess->server->last_away_reason)
-		free (sess->server->last_away_reason);
+	g_free (sess->server->last_away_reason);
 	sess->server->last_away_reason = NULL;
 
 	return TRUE;
@@ -483,19 +481,19 @@ create_mask (session * sess, char *mask, char *mode, char *typestr, int deop)
 			switch (type)
 			{
 			case 0:
-				snprintf (buf, sizeof (buf), "%s %s *!*@%s.*", mode, p2, domain);
+				g_snprintf (buf, sizeof (buf), "%s %s *!*@%s.*", mode, p2, domain);
 				break;
 
 			case 1:
-				snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost);
+				g_snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost);
 				break;
 
 			case 2:
-				snprintf (buf, sizeof (buf), "%s %s *!%s@%s.*", mode, p2, username, domain);
+				g_snprintf (buf, sizeof (buf), "%s %s *!%s@%s.*", mode, p2, username, domain);
 				break;
 
 			case 3:
-				snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost);
+				g_snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost);
 				break;
 			}
 		} else
@@ -503,26 +501,26 @@ create_mask (session * sess, char *mask, char *mode, char *typestr, int deop)
 			switch (type)
 			{
 			case 0:
-				snprintf (buf, sizeof (buf), "%s %s *!*@*%s", mode, p2, domain);
+				g_snprintf (buf, sizeof (buf), "%s %s *!*@*%s", mode, p2, domain);
 				break;
 
 			case 1:
-				snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost);
+				g_snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost);
 				break;
 
 			case 2:
-				snprintf (buf, sizeof (buf), "%s %s *!%s@*%s", mode, p2, username, domain);
+				g_snprintf (buf, sizeof (buf), "%s %s *!%s@*%s", mode, p2, username, domain);
 				break;
 
 			case 3:
-				snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost);
+				g_snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost);
 				break;
 			}
 		}
 
 	} else
 	{
-		snprintf (buf, sizeof (buf), "%s %s", mode, mask);
+		g_snprintf (buf, sizeof (buf), "%s %s", mode, mask);
 	}
 	
 	return g_strdup (buf);
@@ -592,7 +590,6 @@ static int
 cmd_charset (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
 	server *serv = sess->server;
-	const char *locale = NULL;
 	int offset = 0;
 
 	if (strcmp (word[2], "-quiet") == 0)
@@ -600,9 +597,7 @@ cmd_charset (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 
 	if (!word[2 + offset][0])
 	{
-		g_get_charset (&locale);
-		PrintTextf (sess, "Current charset: %s\n",
-						serv->encoding ? serv->encoding : locale);
+		PrintTextf (sess, "Current charset: %s\n", serv->encoding);
 		return TRUE;
 	}
 
@@ -1002,14 +997,14 @@ mdehop_cb (struct User *user, multidata *data)
 static int
 cmd_mdehop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	char **nicks = malloc (sizeof (char *) * sess->hops);
+	char **nicks = g_new0 (char *, sess->hops);
 	multidata data;
 
 	data.nicks = nicks;
 	data.i = 0;
 	tree_foreach (sess->usertree, (tree_traverse_func *)mdehop_cb, &data);
 	send_channel_modes (sess, tbuf, nicks, 0, data.i, '-', 'h', 0);
-	free (nicks);
+	g_free (nicks);
 
 	return TRUE;
 }
@@ -1028,14 +1023,14 @@ mdeop_cb (struct User *user, multidata *data)
 static int
 cmd_mdeop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	char **nicks = malloc (sizeof (char *) * sess->ops);
+	char **nicks = g_new0(char *, sess->ops);
 	multidata data;
 
 	data.nicks = nicks;
 	data.i = 0;
 	tree_foreach (sess->usertree, (tree_traverse_func *)mdeop_cb, &data);
 	send_channel_modes (sess, tbuf, nicks, 0, data.i, '-', 'o', 0);
-	free (nicks);
+	g_free (nicks);
 
 	return TRUE;
 }
@@ -1045,18 +1040,13 @@ GSList *menu_list = NULL;
 static void
 menu_free (menu_entry *me)
 {
-	free (me->path);
-	if (me->label)
-		free (me->label);
-	if (me->cmd)
-		free (me->cmd);
-	if (me->ucmd)
-		free (me->ucmd);
-	if (me->group)
-		free (me->group);
-	if (me->icon)
-		free (me->icon);
-	free (me);
+	g_free (me->path);
+	g_free (me->label);
+	g_free (me->cmd);
+	g_free (me->ucmd);
+	g_free (me->group);
+	g_free (me->icon);
+	g_free (me);
 }
 
 /* strings equal? but ignore underscores */
@@ -1115,9 +1105,9 @@ menu_del_children (char *path, char *label)
 	if (!label)
 		label = "";
 	if (path[0])
-		snprintf (buf, sizeof (buf), "%s/%s", path, label);
+		g_snprintf (buf, sizeof (buf), "%s/%s", path, label);
 	else
-		snprintf (buf, sizeof (buf), "%s", label);
+		g_snprintf (buf, sizeof (buf), "%s", label);
 
 	list = menu_list;
 	while (list)
@@ -1168,7 +1158,9 @@ menu_is_mainmenu_root (char *path, gint16 *offset)
 	{
 		if (!strncmp (path, menus[i] + 1, menus[i][0]))
 		{
-			*offset = menus[i][0] + 1;	/* number of bytes to offset the root */
+			*offset = menus[i][0];	/* number of bytes to offset the root */
+			if (path[*offset] != '\0')
+				*offset += 1;
 			return 0;	/* is not main menu */
 		}
 	}
@@ -1193,7 +1185,7 @@ menu_add (char *path, char *label, char *cmd, char *ucmd, int pos, int state, in
 		return;
 	}
 
-	me = malloc (sizeof (menu_entry));
+	me = g_new (menu_entry, 1);
 	me->pos = pos;
 	me->modifier = mod;
 	me->is_main = menu_is_mainmenu_root (path, &me->root_offset);
@@ -1201,31 +1193,26 @@ menu_add (char *path, char *label, char *cmd, char *ucmd, int pos, int state, in
 	me->markup = markup;
 	me->enable = enable;
 	me->key = key;
-	me->path = strdup (path);
+	me->path = g_strdup (path);
 	me->label = NULL;
 	me->cmd = NULL;
 	me->ucmd = NULL;
 	me->group = NULL;
 	me->icon = NULL;
 
-	if (label)
-		me->label = strdup (label);
-	if (cmd)
-		me->cmd = strdup (cmd);
-	if (ucmd)
-		me->ucmd = strdup (ucmd);
-	if (group)
-		me->group = strdup (group);
-	if (icon)
-		me->icon = strdup (icon);
+	me->label = g_strdup (label);
+	me->cmd = g_strdup (cmd);
+	me->ucmd = g_strdup (ucmd);
+	me->group = g_strdup (group);
+	me->icon = g_strdup (icon);
 
 	menu_list = g_slist_append (menu_list, me);
 	label = fe_menu_add (me);
 	if (label)
 	{
 		/* FE has given us a stripped label */
-		free (me->label);
-		me->label = strdup (label);
+		g_free (me->label);
+		me->label = g_strdup (label);
 		g_free (label); /* this is from pango */
 	}
 }
@@ -1321,7 +1308,7 @@ cmd_menu (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (markup)
 	{
 		char *p;	/* to force pango closing tags through */
-		for (p = label; *p; p++)
+		for (p = label; p && *p; p++)
 			if (*p == 3)
 				*p = '/';
 	}
@@ -1454,7 +1441,7 @@ exec_check_process (struct session *sess)
 	{
 		close (sess->running_exec->myfd);
 		fe_input_remove (sess->running_exec->iotag);
-		free (sess->running_exec);
+		g_free (sess->running_exec);
 		sess->running_exec = NULL;
 	}
 }
@@ -1531,11 +1518,10 @@ cmd_execw (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		return FALSE;
 	}
 	len = strlen(word_eol[2]);
-	temp = malloc(len + 2);
-	sprintf(temp, "%s\n", word_eol[2]);
+	temp = g_strconcat (word_eol[2], "\n", NULL);
 	PrintText(sess, temp);
 	write(sess->running_exec->myfd, temp, len + 1);
-	free(temp);
+	g_free(temp);
 
 	return TRUE;
 }
@@ -1559,7 +1545,7 @@ exec_handle_colors (char *buf, int len)
 	if (strchr (buf, 27) == 0)
 		return;
 
-	nbuf = malloc (len + 1);
+	nbuf = g_malloc (len + 1);
 
 	while (i < len)
 	{
@@ -1653,7 +1639,7 @@ norm:			nbuf[j] = buf[i];
 
 	nbuf[j] = 0;
 	memcpy (buf, nbuf, j + 1);
-	free (nbuf);
+	g_free (nbuf);
 }
 
 #ifndef HAVE_MEMRCHR
@@ -1665,7 +1651,7 @@ memrchr (const void *block, int c, size_t size)
 	for (p = (unsigned char *)block + size; p != block; p--)
 		if (*p == c)
 			return p;
-	return 0;
+	return NULL;
 }
 #endif
 
@@ -1679,14 +1665,14 @@ exec_data (GIOChannel *source, GIOCondition condition, struct nbexec *s)
 	len = s->buffill;
 	if (len) {
 		/* append new data to buffered incomplete line */
-		buf = malloc(len + 2050);
+		buf = g_malloc (len + 2050);
 		memcpy(buf, s->linebuf, len);
 		readpos = buf + len;
-		free(s->linebuf);
+		g_free (s->linebuf);
 		s->linebuf = NULL;
 	}
 	else
-		readpos = buf = malloc(2050);
+		readpos = buf = g_malloc (2050);
 
 	rd = read (sok, readpos, 2048);
 	if (rd < 1)
@@ -1707,12 +1693,12 @@ exec_data (GIOChannel *source, GIOCondition condition, struct nbexec *s)
 			else
 				PrintText (s->sess, buf);
 		}
-		free(buf);
+		g_free(buf);
 		waitpid (s->childpid, NULL, 0);
 		s->sess->running_exec = NULL;
 		fe_input_remove (s->iotag);
 		close (sok);
-		free (s);
+		g_free (s);
 		return TRUE;
 	}
 	len += rd;
@@ -1725,7 +1711,7 @@ exec_data (GIOChannel *source, GIOCondition condition, struct nbexec *s)
 		rest = buf;
 	if (*rest) {
 		s->buffill = len - (rest - buf); /* = strlen(rest) */
-		s->linebuf = malloc(s->buffill + 1);
+		s->linebuf = g_malloc (s->buffill + 1);
 		memcpy(s->linebuf, rest, s->buffill);
 		*rest = '\0';
 		len -= s->buffill; /* possibly 0 */
@@ -1741,7 +1727,7 @@ exec_data (GIOChannel *source, GIOCondition condition, struct nbexec *s)
 			PrintText (s->sess, buf);
 	}
 
-	free(buf);
+	g_free (buf);
 	return TRUE;
 }
 
@@ -1803,8 +1789,7 @@ cmd_exec (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			return FALSE;
 		}
 #endif
-		s = (struct nbexec *) malloc (sizeof (struct nbexec));
-		memset(s, 0, sizeof(*s));
+		s = g_new0 (struct nbexec, 1);
 		s->myfd = fds[0];
 		s->tochannel = tochannel;
 		s->sess = sess;
@@ -1851,8 +1836,9 @@ cmd_exec (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			PrintText (sess, "Error in fork(2)\n");
 			close(fds[0]);
 			close(fds[1]);
-			free (s);
-		} else
+			g_free (s);
+		}
+		else
 		{
 			/* Parent path */
 			close(fds[1]);
@@ -1940,12 +1926,12 @@ get_bool_cb (int val, getvalinfo *info)
 {
 	char buf[512];
 
-	snprintf (buf, sizeof (buf), "%s %d", info->cmd, val);
+	g_snprintf (buf, sizeof (buf), "%s %d", info->cmd, val);
 	if (is_session (info->sess))
 		handle_command (info->sess, buf, FALSE);
 
-	free (info->cmd);
-	free (info);
+	g_free (info->cmd);
+	g_free (info);
 }
 
 static int
@@ -1956,8 +1942,8 @@ cmd_getbool (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (!word[4][0])
 		return FALSE;
 
-	info = malloc (sizeof (*info));
-	info->cmd = strdup (word[2]);
+	info = g_new (getvalinfo, 1);
+	info->cmd = g_strdup (word[2]);
 	info->sess = sess;
 
 	fe_get_bool (word[3], word_eol[4], get_bool_cb, info);
@@ -1972,13 +1958,13 @@ get_int_cb (int cancel, int val, getvalinfo *info)
 
 	if (!cancel)
 	{
-		snprintf (buf, sizeof (buf), "%s %d", info->cmd, val);
+		g_snprintf (buf, sizeof (buf), "%s %d", info->cmd, val);
 		if (is_session (info->sess))
 			handle_command (info->sess, buf, FALSE);
 	}
 
-	free (info->cmd);
-	free (info);
+	g_free (info->cmd);
+	g_free (info);
 }
 
 static int
@@ -1989,8 +1975,8 @@ cmd_getint (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (!word[4][0])
 		return FALSE;
 
-	info = malloc (sizeof (*info));
-	info->cmd = strdup (word[3]);
+	info = g_new (getvalinfo, 1);
+	info->cmd = g_strdup (word[3]);
 	info->sess = sess;
 
 	fe_get_int (word[4], atoi (word[2]), get_int_cb, info);
@@ -2007,13 +1993,13 @@ get_file_cb (char *cmd, char *file)
       no args */
 	if (file)
 	{
-		snprintf (buf, sizeof (buf), "%s %s", cmd, file);
+		g_snprintf (buf, sizeof (buf), "%s %s", cmd, file);
 		handle_command (current_sess, buf, FALSE);
 	}
 	else
 	{
 		handle_command (current_sess, cmd, FALSE);
-		free (cmd);
+		g_free (cmd);
 	}
 }
 
@@ -2044,7 +2030,7 @@ cmd_getfile (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		idx++;
 	}
 
-	fe_get_file (word[idx+1], word[idx+2], (void *)get_file_cb, strdup (word[idx]), flags);
+	fe_get_file (word[idx+1], word[idx+2], (void *)get_file_cb, g_strdup (word[idx]), flags);
 
 	return TRUE;
 }
@@ -2056,13 +2042,13 @@ get_str_cb (int cancel, char *val, getvalinfo *info)
 
 	if (!cancel)
 	{
-		snprintf (buf, sizeof (buf), "%s %s", info->cmd, val);
+		g_snprintf (buf, sizeof (buf), "%s %s", info->cmd, val);
 		if (is_session (info->sess))
 			handle_command (info->sess, buf, FALSE);
 	}
 
-	free (info->cmd);
-	free (info);
+	g_free (info->cmd);
+	g_free (info);
 }
 
 static int
@@ -2073,8 +2059,8 @@ cmd_getstr (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (!word[4][0])
 		return FALSE;
 
-	info = malloc (sizeof (*info));
-	info->cmd = strdup (word[3]);
+	info = g_new (getvalinfo, 1);
+	info->cmd = g_strdup (word[3]);
 	info->sess = sess;
 
 	fe_get_str (word[4], word[2], get_str_cb, info);
@@ -2200,7 +2186,7 @@ cmd_help (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	} else
 	{
 		struct popup *pop;
-		char *buf = malloc (4096);
+		char *buf = g_malloc (4096);
 		help_list hl;
 
 		hl.longfmt = longfmt;
@@ -2245,7 +2231,7 @@ cmd_help (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		plugin_command_foreach (sess, &hl, (void *)show_help_line);
 		strcat (buf, "\n");
 		PrintText (sess, buf);
-		free (buf);
+		g_free (buf);
 
 		PrintTextf (sess, "\n%s\n\n", _("Type /HELP <command> for more information, or /HELP -l"));
 	}
@@ -2293,7 +2279,7 @@ cmd_ignore (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			    strchr (mask, '*') == NULL)
 			{
 				mask = tbuf;
-				snprintf (tbuf, TBUFSIZE, "%s!*@*", word[2]);
+				g_snprintf (tbuf, TBUFSIZE, "%s!*@*", word[2]);
 			}
 
 			i = ignore_add (mask, type, TRUE);
@@ -2549,7 +2535,7 @@ cmd_load (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			PrintText (sess, errorstring (errno));
 			g_free (buf);
 		}
-		free (file);
+		g_free (file);
 		return TRUE;
 	}
 
@@ -2562,7 +2548,7 @@ cmd_load (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 
 		file = expand_homedir (word[2]);
 		error = plugin_load (sess, file, arg);
-		free (file);
+		g_free (file);
 
 		if (error)
 			PrintText (sess, error);
@@ -2651,7 +2637,7 @@ cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		return TRUE;
 	}
 
-	snprintf (tbuf, TBUFSIZE, "\001ACTION %s\001\r", act);
+	g_snprintf (tbuf, TBUFSIZE, "\001ACTION %s\001\r", act);
 	/* first try through DCC CHAT */
 	if (dcc_write_chat (sess->channel, tbuf))
 	{
@@ -2674,7 +2660,7 @@ cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 				if (*split_text)
 					offset += strlen(split_text);
 
-				g_free(split_text);
+				g_free (split_text);
 			}
 
 			sess->server->p_action (sess->server, sess->channel, act + offset);
@@ -2693,17 +2679,26 @@ cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 static int
 cmd_mode (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	/* +channel channels are dying, let those servers whine about modes.
-	 * return info about current channel if available and no info is given */
-	if ((*word[2] == '+') || (*word[2] == 0) || (!is_channel(sess->server, word[2]) &&
-				!(rfc_casecmp(sess->server->nick, word[2]) == 0)))
+	/* We allow omitting the target, so we have to figure it out:
+	 * - Can only use info from channels or dialogs
+	 * - Empty arg is always sess info
+	 * - Assume + is mode not channel
+	 * - We know valid channels and our nick
+	 * - We cannot easily know if other nick or valid mode (Need to store 004)
+	 */
+	if ((sess->type != SESS_CHANNEL && sess->type != SESS_DIALOG)
+	    || (!(*word[2] == '-' || *word[2] == '+' || *word[2] == '\0')
+	        && (is_channel (sess->server, word[2]) || !rfc_casecmp (sess->server->nick, word[2])))
+	   )
+	{
+		sess->server->p_mode (sess->server, word[2], word_eol[3]);
+	}
+	else
 	{
 		if(sess->channel[0] == 0)
 			return FALSE;
 		sess->server->p_mode (sess->server, sess->channel, word_eol[2]);
 	}
-	else
-		sess->server->p_mode (sess->server, word[2], word_eol[3]);
 	return TRUE;
 }
 
@@ -2721,7 +2716,7 @@ mop_cb (struct User *user, multidata *data)
 static int
 cmd_mop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	char **nicks = malloc (sizeof (char *) * (sess->total - sess->ops));
+	char **nicks = g_new0 (char *, sess->total - sess->ops);
 	multidata data;
 
 	data.nicks = nicks;
@@ -2729,7 +2724,7 @@ cmd_mop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	tree_foreach (sess->usertree, (tree_traverse_func *)mop_cb, &data);
 	send_channel_modes (sess, tbuf, nicks, 0, data.i, '+', 'o', 0);
 
-	free (nicks);
+	g_free (nicks);
 
 	return TRUE;
 }
@@ -2780,7 +2775,7 @@ cmd_msg (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 					if (*split_text)
 						offset += strlen(split_text);
 
-					g_free(split_text);
+					g_free (split_text);
 				}
 				sess->server->p_message (sess->server, nick, msg + offset);
 				offset = 0;
@@ -2801,7 +2796,7 @@ cmd_msg (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 					if (*split_text)
 						offset += strlen(split_text);
 
-					g_free(split_text);
+					g_free (split_text);
 				}
 				inbound_chanmsg (newsess->server, NULL, newsess->channel,
 									  newsess->server->nick, msg + offset, TRUE, FALSE,
@@ -2895,7 +2890,7 @@ cmd_notice (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			if (*split_text)
 				offset += strlen(split_text);
 			
-			g_free(split_text);
+			g_free (split_text);
 		}
 
 		sess->server->p_notice (sess->server, word[2], text + offset);
@@ -2991,7 +2986,7 @@ cmd_ping (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 
 	tim = make_ping_time ();
 
-	snprintf (timestring, sizeof (timestring), "%lu", tim);
+	g_snprintf (timestring, sizeof (timestring), "%lu", tim);
 	sess->server->p_ping (sess->server, to, timestring);
 
 	return TRUE;
@@ -3054,7 +3049,7 @@ cmd_query (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 				if (*split_text)
 					offset += strlen(split_text);
 
-				g_free(split_text);
+				g_free (split_text);
 			}
 			sess->server->p_message (sess->server, nick, msg + offset);
 			inbound_chanmsg (nick_sess->server, nick_sess, nick_sess->channel,
@@ -3231,9 +3226,9 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if ((addr & 0xffff0000) == 0xc0a80000 ||	/* 192.168.x.x */
 		 (addr & 0xff000000) == 0x0a000000)		/* 10.x.x.x */
 		/* we got a private net address, let's PSEND or it'll fail */
-		snprintf (tbuf, 512, "DCC PSEND %s", word_eol[2]);
+		g_snprintf (tbuf, 512, "DCC PSEND %s", word_eol[2]);
 	else
-		snprintf (tbuf, 512, "DCC SEND %s", word_eol[2]);
+		g_snprintf (tbuf, 512, "DCC SEND %s", word_eol[2]);
 
 	handle_command (sess, tbuf, FALSE);
 
@@ -3418,8 +3413,9 @@ cmd_server (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			safe_strcpy (serv->password, net->pass, sizeof (serv->password));
 			serv->loginmethod = net->logintype;
 		}
-		else /* Otherwise ensure no password is sent */
+		else /* Otherwise ensure no password is sent or SASL started */
 		{
+			serv->loginmethod = LOGIN_DEFAULT;
 			serv->password[0] = 0;
 		}
 	}
@@ -3484,12 +3480,6 @@ cmd_topic (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 static int
 cmd_tray (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	if (strcmp (word[2], "-b") == 0)
-	{
-		fe_tray_set_balloon (word[3], word[4][0] ? word[4] : NULL);
-		return TRUE;
-	}
-
 	if (strcmp (word[2], "-t") == 0)
 	{
 		fe_tray_set_tooltip (word[3][0] ? word[3] : NULL);
@@ -3533,7 +3523,7 @@ cmd_unignore (struct session *sess, char *tbuf, char *word[],
 		if (strchr (mask, '?') == NULL && strchr (mask, '*') == NULL)
 		{
 			mask = tbuf;
-			snprintf (tbuf, TBUFSIZE, "%s!*@*", word[2]);
+			g_snprintf (tbuf, TBUFSIZE, "%s!*@*", word[2]);
 		}
 		
 		if (ignore_del (mask, NULL))
@@ -3873,7 +3863,7 @@ const struct commands xc_cmds[] = {
 	 N_("ALLCHANL <cmd>, sends a command to all channels on the current server")},
 	{"ALLSERV", cmd_allservers, 0, 0, 1,
 	 N_("ALLSERV <cmd>, sends a command to all servers you're in")},
-	{"AWAY", cmd_away, 1, 0, 1, N_("AWAY [<reason>], sets you away")},
+	{"AWAY", cmd_away, 1, 0, 1, N_("AWAY [<reason>], sets you away (use /BACK to unset)")},
 	{"BACK", cmd_back, 1, 0, 1, N_("BACK, sets you back (not away)")},
 	{"BAN", cmd_ban, 1, 1, 1,
 	 N_("BAN <mask> [<bantype>], bans everyone matching the mask from the current channel. If they are already on the channel this doesn't kick them (needs chanop)")},
@@ -4096,7 +4086,7 @@ usercommand_show_help (session *sess, char *name)
 		pop = (struct popup *) list->data;
 		if (!g_ascii_strcasecmp (pop->name, name))
 		{
-			snprintf (buf, sizeof(buf), _("User Command for: %s\n"), pop->cmd);
+			g_snprintf (buf, sizeof(buf), _("User Command for: %s\n"), pop->cmd);
 			PrintText (sess, buf);
 
 			found = TRUE;
@@ -4123,7 +4113,7 @@ help (session *sess, char *tbuf, char *helpcmd, int quiet)
 	{
 		if (cmd->help)
 		{
-			snprintf (tbuf, TBUFSIZE, _("Usage: %s\n"), _(cmd->help));
+			g_snprintf (tbuf, TBUFSIZE, _("Usage: %s\n"), _(cmd->help));
 			PrintText (sess, tbuf);
 		} else
 		{
@@ -4145,7 +4135,7 @@ help (session *sess, char *tbuf, char *helpcmd, int quiet)
  * - this beast is used for UserCommands, UserlistButtons and CTCP replies   */
 
 int
-auto_insert (char *dest, int destlen, unsigned char *src, char *word[],
+auto_insert (char *dest, gsize destlen, unsigned char *src, char *word[],
 				 char *word_eol[], char *a, char *c, char *d, char *e, char *h,
 				 char *n, char *s, char *u)
 {
@@ -4217,7 +4207,7 @@ auto_insert (char *dest, int destlen, unsigned char *src, char *word[],
 				switch (src[0])
 				{
 				case '%':
-					if ((dest - orig) + 2 >= destlen)
+					if ((dest - orig) + 2u >= destlen)
 						return 2;
 					dest[0] = '%';
 					dest[1] = 0;
@@ -4252,7 +4242,7 @@ auto_insert (char *dest, int destlen, unsigned char *src, char *word[],
 				case 'y':
 					now = time (0);
 					tm_ptr = localtime (&now);
-					snprintf (buf, sizeof (buf), "%4d%02d%02d", 1900 +
+					g_snprintf (buf, sizeof (buf), "%4d%02d%02d", 1900 +
 								 tm_ptr->tm_year, 1 + tm_ptr->tm_mon, tm_ptr->tm_mday);
 					utf = buf;
 					break;
@@ -4311,81 +4301,78 @@ check_special_chars (char *cmd, int do_ascii) /* check for %X */
 	if (!len)
 		return;
 
-	buf = malloc (len + 1);
+	buf = g_malloc (len + 1);
 
-	if (buf)
+	while (cmd[j])
 	{
-		while (cmd[j])
+		switch (cmd[j])
 		{
-			switch (cmd[j])
+		case '%':
+			occur++;
+			if (	do_ascii &&
+					j + 3 < len &&
+					(isdigit ((unsigned char) cmd[j + 1]) && isdigit ((unsigned char) cmd[j + 2]) &&
+					isdigit ((unsigned char) cmd[j + 3])))
 			{
-			case '%':
-				occur++;
-				if (	do_ascii &&
-						j + 3 < len &&
-						(isdigit ((unsigned char) cmd[j + 1]) && isdigit ((unsigned char) cmd[j + 2]) &&
-						isdigit ((unsigned char) cmd[j + 3])))
+				tbuf[0] = cmd[j + 1];
+				tbuf[1] = cmd[j + 2];
+				tbuf[2] = cmd[j + 3];
+				tbuf[3] = 0;
+				buf[i] = atoi (tbuf);
+				utf = g_locale_to_utf8 (buf + i, 1, 0, &utf_len, 0);
+				if (utf)
 				{
-					tbuf[0] = cmd[j + 1];
-					tbuf[1] = cmd[j + 2];
-					tbuf[2] = cmd[j + 3];
-					tbuf[3] = 0;
-					buf[i] = atoi (tbuf);
-					utf = g_locale_to_utf8 (buf + i, 1, 0, &utf_len, 0);
-					if (utf)
-					{
-						memcpy (buf + i, utf, utf_len);
-						g_free (utf);
-						i += (utf_len - 1);
-					}
-					j += 3;
-				} else
+					memcpy (buf + i, utf, utf_len);
+					g_free (utf);
+					i += (utf_len - 1);
+				}
+				j += 3;
+			} else
+			{
+				switch (cmd[j + 1])
 				{
-					switch (cmd[j + 1])
-					{
-					case 'R':
-						buf[i] = '\026';
-						break;
-					case 'U':
-						buf[i] = '\037';
-						break;
-					case 'B':
-						buf[i] = '\002';
-						break;
-					case 'I':
-						buf[i] = '\035';
-						break;
-					case 'C':
-						buf[i] = '\003';
-						break;
-					case 'O':
-						buf[i] = '\017';
-						break;
-					case 'H':	/* CL: invisible text code */
-						buf[i] = HIDDEN_CHAR;
-						break;
-					case '%':
-						buf[i] = '%';
-						break;
-					default:
-						buf[i] = '%';
-						j--;
-						break;
-					}
-					j++;
+				case 'R':
+					buf[i] = '\026';
+					break;
+				case 'U':
+					buf[i] = '\037';
+					break;
+				case 'B':
+					buf[i] = '\002';
+					break;
+				case 'I':
+					buf[i] = '\035';
+					break;
+				case 'C':
+					buf[i] = '\003';
+					break;
+				case 'O':
+					buf[i] = '\017';
+					break;
+				case 'H':	/* CL: invisible text code */
+					buf[i] = HIDDEN_CHAR;
+					break;
+				case '%':
+					buf[i] = '%';
+					break;
+				default:
+					buf[i] = '%';
+					j--;
 					break;
-			default:
-					buf[i] = cmd[j];
 				}
+				j++;
+				break;
+		default:
+				buf[i] = cmd[j];
 			}
-			j++;
-			i++;
 		}
-		buf[i] = 0;
-		if (occur)
-			strcpy (cmd, buf);
-		free (buf);
+		j++;
+		i++;
 	}
+	buf[i] = 0;
+	if (occur)
+		strcpy (cmd, buf);
+	g_free (buf);
 }
 
 typedef struct
@@ -4408,7 +4395,7 @@ nick_comp_cb (struct User *user, nickdata *data)
 		lenu = strlen (user->nick);
 		if (lenu == data->len)
 		{
-			snprintf (data->tbuf, TBUFSIZE, "%s%s", user->nick, data->space);
+			g_snprintf (data->tbuf, TBUFSIZE, "%s%s", user->nick, data->space);
 			data->len = -1;
 			return FALSE;
 		} else if (lenu < data->bestlen)
@@ -4452,7 +4439,7 @@ perform_nick_completion (struct session *sess, char *cmd, char *tbuf)
 
 				if (data.best)
 				{
-					snprintf (tbuf, TBUFSIZE, "%s%s", data.best->nick, space - 1);
+					g_snprintf (tbuf, TBUFSIZE, "%s%s", data.best->nick, space - 1);
 					return;
 				}
 			}
@@ -4485,12 +4472,10 @@ handle_say (session *sess, char *text, int check_spch)
 	struct DCC *dcc;
 	char *word[PDIWORDS+1];
 	char *word_eol[PDIWORDS+1];
-	char pdibuf_static[1024];
-	char newcmd_static[1024];
-	char *pdibuf = pdibuf_static;
-	char *newcmd = newcmd_static;
+	char *pdibuf;
+	char *newcmd;
 	int len;
-	int newcmdlen = sizeof newcmd_static;
+	int newcmdlen;
 	message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT;
 
 	if (strcmp (sess->channel, "(lastlog)") == 0)
@@ -4500,11 +4485,9 @@ handle_say (session *sess, char *text, int check_spch)
 	}
 
 	len = strlen (text);
-	if (len >= sizeof pdibuf_static)
-		pdibuf = malloc (len + 1);
-
-	if (len + NICKLEN >= newcmdlen)
-		newcmd = malloc (newcmdlen = len + NICKLEN + 1);
+	pdibuf = g_malloc (len + 1);
+	newcmdlen = MAX(len + NICKLEN + 1, TBUFSIZE);
+	newcmd = g_malloc (newcmdlen);
 
 	if (check_spch && prefs.hex_input_perc_color)
 		check_special_chars (text, prefs.hex_input_perc_ascii);
@@ -4565,7 +4548,7 @@ handle_say (session *sess, char *text, int check_spch)
 			if (*split_text)
 				offset += strlen(split_text);
 			
-			g_free(split_text);
+			g_free (split_text);
 		}
 
 		inbound_chanmsg (sess->server, sess, sess->channel, sess->server->nick,
@@ -4577,11 +4560,9 @@ handle_say (session *sess, char *text, int check_spch)
 	}
 
 xit:
-	if (pdibuf != pdibuf_static)
-		free (pdibuf);
+	g_free (pdibuf);
 
-	if (newcmd != newcmd_static)
-		free (newcmd);
+	g_free (newcmd);
 }
 
 char *
@@ -4675,8 +4656,6 @@ handle_command (session *sess, char *cmd, int check_spch)
 	char *word_eol[PDIWORDS+1];
 	static int command_level = 0;
 	struct commands *int_cmd;
-	char pdibuf_static[1024];
-	char tbuf_static[TBUFSIZE];
 	char *pdibuf;
 	char *tbuf;
 	int len;
@@ -4691,23 +4670,8 @@ handle_command (session *sess, char *cmd, int check_spch)
 	/* anything below MUST DEC command_level before returning */
 
 	len = strlen (cmd);
-	if (len >= sizeof (pdibuf_static))
-	{
-		pdibuf = malloc (len + 1);
-	}
-	else
-	{
-		pdibuf = pdibuf_static;
-	}
-
-	if ((len * 2) >= sizeof (tbuf_static))
-	{
-		tbuf = malloc ((len * 2) + 1);
-	}
-	else
-	{
-		tbuf = tbuf_static;
-	}
+	pdibuf = g_malloc (len + 1);
+	tbuf = g_malloc (MAX(TBUFSIZE, (len * 2) + 1));
 
 	/* split the text into words and word_eol */
 	process_data_init (pdibuf, cmd, word, word_eol, TRUE, TRUE);
@@ -4786,13 +4750,13 @@ handle_command (session *sess, char *cmd, int check_spch)
 	}
 	else
 	{
-		/* unknown command, just send it to the server and hope */
 		if (!sess->server->connected)
 		{
-			PrintText (sess, _("Unknown Command. Try /help\n"));
+			PrintTextf (sess, _("Unknown Command %s. Try /help\n"), word[1]);
 		}
 		else
 		{
+			/* unknown command, just send it to the server and hope */
 			sess->server->p_raw (sess->server, cmd);
 		}
 	}
@@ -4800,15 +4764,8 @@ handle_command (session *sess, char *cmd, int check_spch)
 xit:
 	command_level--;
 
-	if (pdibuf != pdibuf_static)
-	{
-		free (pdibuf);
-	}
-
-	if (tbuf != tbuf_static)
-	{
-		free (tbuf);
-	}
+	g_free (pdibuf);
+	g_free (tbuf);
 
 	return ret;
 }
diff --git a/src/common/outbound.h b/src/common/outbound.h
index b9fe6331..490a58ca 100644
--- a/src/common/outbound.h
+++ b/src/common/outbound.h
@@ -25,7 +25,7 @@
 extern const struct commands xc_cmds[];
 extern GSList *menu_list;
 
-int auto_insert (char *dest, int destlen, unsigned char *src, char *word[], char *word_eol[],
+int auto_insert (char *dest, gsize destlen, unsigned char *src, char *word[], char *word_eol[],
 				 char *a, char *c, char *d, char *e, char *h, char *n, char *s, char *u);
 char *command_insert_vars (session *sess, char *cmd);
 int handle_command (session *sess, char *cmd, int check_spch);
diff --git a/src/common/plugin-identd.c b/src/common/plugin-identd.c
new file mode 100644
index 00000000..ce1bd1e6
--- /dev/null
+++ b/src/common/plugin-identd.c
@@ -0,0 +1,220 @@
+/* HexChat
+*
+* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#include "config.h"
+
+#include <string.h>
+#include <gio/gio.h>
+#include "hexchat-plugin.h"
+
+#define _(x) hexchat_gettext(ph,x)
+
+static hexchat_plugin *ph;
+static GSocketService *service;
+static GHashTable *responses;
+
+typedef struct ident_info
+{
+	GSocketConnection *conn;
+	gchar *username;
+	gchar read_buf[16];
+} ident_info;
+
+static int
+identd_cleanup_response_cb (gpointer userdata)
+{
+	g_return_val_if_fail (responses != NULL, 0);
+
+	g_hash_table_remove (responses, userdata);
+
+	return 0;
+}
+
+static int
+identd_command_cb (char *word[], char *word_eol[], void *userdata)
+{
+	g_return_val_if_fail (responses != NULL, HEXCHAT_EAT_ALL);
+
+	if (service == NULL) /* If we are not running plugins can handle it */
+		return HEXCHAT_EAT_HEXCHAT;
+
+	if (word[2] && *word[2] && word[3] && *word[3])
+	{
+		guint64 port = g_ascii_strtoull (word[2], NULL, 0);
+
+		if (port && port <= G_MAXUINT16)
+		{
+			g_hash_table_insert (responses, GINT_TO_POINTER (port), g_strdup (word[3]));
+			/* Automatically remove entry after 30 seconds */
+			hexchat_hook_timer (ph, 30000, identd_cleanup_response_cb, GINT_TO_POINTER (port));
+		}
+	}
+	else
+	{
+		hexchat_command (ph, "HELP IDENTD");
+	}
+
+	return HEXCHAT_EAT_ALL;
+}
+
+static void
+identd_write_ready (GOutputStream *stream, GAsyncResult *res, ident_info *info)
+{
+	g_output_stream_write_finish (stream, res, NULL);
+
+	g_free (info->username);
+	g_object_unref (info->conn);
+	g_free (info);
+}
+
+static void
+identd_read_ready (GInputStream *in_stream, GAsyncResult *res, ident_info *info)
+{
+	GSocketAddress *sok_addr;
+	GOutputStream *out_stream;
+	guint64 local, remote;
+	gchar buf[512], *p;
+
+	if (g_input_stream_read_finish (in_stream, res, NULL))
+	{
+		local = g_ascii_strtoull (info->read_buf, NULL, 0);
+		p = strchr (info->read_buf, ',');
+		if (!p)
+			goto cleanup;
+
+		remote = g_ascii_strtoull (p + 1, NULL, 0);
+
+		if (!local || !remote || local > G_MAXUINT16 || remote > G_MAXUINT16)
+			goto cleanup;
+
+		info->username = g_strdup (g_hash_table_lookup (responses, GINT_TO_POINTER (local)));
+		if (!info->username)
+			goto cleanup;
+		g_hash_table_remove (responses, GINT_TO_POINTER (local));
+
+		if ((sok_addr = g_socket_connection_get_remote_address (info->conn, NULL)))
+		{
+			GInetAddress *inet_addr;
+			gchar *addr;
+
+			inet_addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (sok_addr));
+			addr = g_inet_address_to_string (inet_addr);
+
+			hexchat_printf (ph, _("*\tServicing ident request from %s as %s"), addr, info->username);
+
+			g_object_unref (sok_addr);
+			g_object_unref (inet_addr);
+			g_free (addr);
+		}
+
+		g_snprintf (buf, sizeof (buf), "%"G_GUINT16_FORMAT", %"G_GUINT16_FORMAT" : USERID : UNIX : %s\r\n", (guint16)local, (guint16)remote, info->username);
+		out_stream = g_io_stream_get_output_stream (G_IO_STREAM (info->conn));
+		g_output_stream_write_async (out_stream, buf, strlen (buf), G_PRIORITY_DEFAULT,
+									NULL, (GAsyncReadyCallback)identd_write_ready, info);
+	}
+
+	return;
+
+cleanup:
+	g_object_unref (info->conn);
+	g_free (info);
+}
+
+static gboolean
+identd_incoming_cb (GSocketService *service, GSocketConnection *conn,
+					GObject *source, gpointer userdata)
+{
+	GInputStream *stream;
+	ident_info *info;
+
+	info = g_new0 (ident_info, 1);
+
+	info->conn = conn;
+	g_object_ref (conn);
+
+	stream = g_io_stream_get_input_stream (G_IO_STREAM (conn));
+	g_input_stream_read_async (stream, info->read_buf, sizeof (info->read_buf), G_PRIORITY_DEFAULT,
+							NULL, (GAsyncReadyCallback)identd_read_ready, info);
+
+	return TRUE;
+}
+
+static void
+identd_start_server (void)
+{
+	GError *error = NULL;
+	int enabled, port = 113;
+
+	if (hexchat_get_prefs (ph, "identd", NULL, &enabled) == 3)
+	{
+		if (!enabled)
+			return;
+	}
+	if (hexchat_get_prefs (ph, "identd_port", NULL, &port) == 2 && (port <= 0 || port > G_MAXUINT16))
+	{
+		port = 113;
+	}
+
+	service = g_socket_service_new ();
+
+	g_socket_listener_add_inet_port (G_SOCKET_LISTENER (service), port, NULL, &error);
+	if (error)
+	{
+		hexchat_printf (ph, _("*\tError starting identd server: %s"), error->message);
+
+		g_object_unref (service);
+		service = NULL;
+		return;
+	}
+	/*hexchat_printf (ph, "*\tIdentd listening on port: %d", port); */
+
+	g_signal_connect (G_OBJECT (service), "incoming", G_CALLBACK(identd_incoming_cb), NULL);
+	g_socket_service_start (service);
+}
+
+int
+identd_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name,
+					char **plugin_desc, char **plugin_version, char *arg)
+{
+	ph = plugin_handle;
+	*plugin_name = "";
+	*plugin_desc = "";
+	*plugin_version = "";
+
+
+	responses = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+	hexchat_hook_command (ph, "IDENTD", HEXCHAT_PRI_NORM, identd_command_cb,
+						_("IDENTD <port> <username>"), NULL);
+
+	identd_start_server ();
+
+	return 1; /* This must always succeed for /identd to work */
+}
+
+int
+identd_plugin_deinit (void)
+{
+	if (service)
+	{
+		g_socket_service_stop (service);
+		g_object_unref (service);
+	}
+
+	g_hash_table_destroy (responses);
+
+	return 1;
+}
diff --git a/src/common/plugin-identd.h b/src/common/plugin-identd.h
new file mode 100644
index 00000000..5efc2600
--- /dev/null
+++ b/src/common/plugin-identd.h
@@ -0,0 +1,28 @@
+/* HexChat
+ * Copyright (C) 1998-2010 Peter Zelezny.
+ * Copyright (C) 2009-2013 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef HEXCHAT_PLUGIN_IDENTD_H
+#define HEXCHAT_PLUGIN_IDENTD_H
+
+int identd_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name,
+				char **plugin_desc, char **plugin_version, char *arg);
+
+int identd_plugin_deinit ();
+
+#endif
diff --git a/src/common/plugin-timer.c b/src/common/plugin-timer.c
index e6944330..d0c82c28 100644
--- a/src/common/plugin-timer.c
+++ b/src/common/plugin-timer.c
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <glib.h>
@@ -43,7 +45,7 @@ typedef struct
 	char *command;
 	int ref;
 	int repeat;
-	float timeout;
+	int timeout;
 	unsigned int forever:1;
 } timer;
 
@@ -51,9 +53,9 @@ static void
 timer_del (timer *tim)
 {
 	timer_list = g_slist_remove (timer_list, tim);
-	free (tim->command);
+	g_free (tim->command);
 	hexchat_unhook (ph, tim->hook);
-	free (tim);
+	g_free (tim);
 }
 
 static void
@@ -99,7 +101,7 @@ timeout_cb (timer *tim)
 }
 
 static void
-timer_add (int ref, float timeout, int repeat, char *command)
+timer_add (int ref, int timeout, int repeat, char *command)
 {
 	timer *tim;
 	GSList *list;
@@ -117,18 +119,18 @@ timer_add (int ref, float timeout, int repeat, char *command)
 		}
 	}
 
-	tim = malloc (sizeof (timer));
+	tim = g_new (timer, 1);
 	tim->ref = ref;
 	tim->repeat = repeat;
 	tim->timeout = timeout;
-	tim->command = strdup (command);
+	tim->command = g_strdup (command);
 	tim->context = hexchat_get_context (ph);
 	tim->forever = FALSE;
 
 	if (repeat == 0)
 		tim->forever = TRUE;
 
-	tim->hook = hexchat_hook_timer (ph, timeout * 1000.0, (void *)timeout_cb, tim);
+	tim->hook = hexchat_hook_timer (ph, timeout, (void *)timeout_cb, tim);
 	timer_list = g_slist_append (timer_list, tim);
 }
 
@@ -150,7 +152,7 @@ timer_showlist (void)
 	while (list)
 	{
 		tim = list->data;
-		hexchat_printf (ph, _("%5d %8.1f %7d  %s\n"), tim->ref, tim->timeout,
+		hexchat_printf (ph, _("%5d %8.1f %7d  %s\n"), tim->ref, tim->timeout / 1000.0f,
 						  tim->repeat, tim->command);
 		list = list->next;
 	}
@@ -160,7 +162,7 @@ static int
 timer_cb (char *word[], char *word_eol[], void *userdata)
 {
 	int repeat = 1;
-	float timeout;
+	double timeout;
 	int offset = 0;
 	int ref = 0;
 	int quiet = FALSE;
@@ -199,10 +201,10 @@ timer_cb (char *word[], char *word_eol[], void *userdata)
 	timeout = atof (word[2 + offset]);
 	command = word_eol[3 + offset];
 
-	if (timeout < 0.1 || !command[0])
+	if (timeout < 0.1 || timeout * 1000 > INT_MAX || !command[0])
 		hexchat_print (ph, HELP);
 	else
-		timer_add (ref, timeout, repeat, command);
+		timer_add (ref, (int) timeout * 1000, repeat, command);
 
 	return HEXCHAT_EAT_HEXCHAT;
 }
diff --git a/src/common/plugin.c b/src/common/plugin.c
index d83b69ff..a397c878 100644
--- a/src/common/plugin.c
+++ b/src/common/plugin.c
@@ -161,16 +161,12 @@ plugin_free (hexchat_plugin *pl, int do_deinit, int allow_refuse)
 xit:
 	if (pl->free_strings)
 	{
-		if (pl->name)
-			free (pl->name);
-		if (pl->desc)
-			free (pl->desc);
-		if (pl->version)
-			free (pl->version);
+		g_free (pl->name);
+		g_free (pl->desc);
+		g_free (pl->version);
 	}
-	if (pl->filename)
-		free ((char *)pl->filename);
-	free (pl);
+	g_free ((char *)pl->filename);
+	g_free (pl);
 
 	plugin_list = g_slist_remove (plugin_list, pl);
 
@@ -188,7 +184,7 @@ plugin_list_add (hexchat_context *ctx, char *filename, const char *name,
 {
 	hexchat_plugin *pl;
 
-	pl = malloc (sizeof (hexchat_plugin));
+	pl = g_new (hexchat_plugin, 1);
 	pl->handle = handle;
 	pl->filename = filename;
 	pl->context = ctx;
@@ -239,9 +235,7 @@ plugin_add (session *sess, char *filename, void *handle, void *init_func,
 	hexchat_plugin *pl;
 	char *file;
 
-	file = NULL;
-	if (filename)
-		file = strdup (filename);
+	file = g_strdup (filename);
 
 	pl = plugin_list_add (sess, file, file, NULL, NULL, handle, deinit_func,
 								 fake, FALSE);
@@ -361,15 +355,11 @@ plugin_kill_all (void)
 
 #ifdef USE_PLUGIN
 
-/* load a plugin from a filename. Returns: NULL-success or an error string */
-
-char *
-plugin_load (session *sess, char *filename, char *arg)
+GModule *
+module_load (char *filename)
 {
 	void *handle;
 	char *filepart;
-	hexchat_init_func *init_func;
-	hexchat_deinit_func *deinit_func;
 	char *pluginpath;
 
 	/* get the filename without path */
@@ -389,6 +379,18 @@ plugin_load (session *sess, char *filename, char *arg)
 		handle = g_module_open (filename, 0);
 	}
 
+	return handle;
+}
+
+/* load a plugin from a filename. Returns: NULL-success or an error string */
+
+char *
+plugin_load (session *sess, char *filename, char *arg)
+{
+	GModule *handle = module_load (filename);
+	hexchat_init_func *init_func;
+	hexchat_deinit_func *deinit_func;
+
 	if (handle == NULL)
 		return (char *)g_module_error ();
 
@@ -596,7 +598,7 @@ xit:
 		if (!hook || hook->type == HOOK_DELETED)
 		{
 			hook_list = g_slist_remove (hook_list, hook);
-			free (hook);
+			g_free (hook);
 		}
 		list = next;
 	}
@@ -615,13 +617,7 @@ plugin_emit_command (session *sess, char *name, char *word[], char *word_eol[])
 hexchat_event_attrs *
 hexchat_event_attrs_create (hexchat_plugin *ph)
 {
-	hexchat_event_attrs *attrs;
-
-	attrs = g_malloc (sizeof (*attrs));
-
-	attrs->server_time_utc = (time_t) 0;
-
-	return attrs;
+	return g_new0 (hexchat_event_attrs, 1);
 }
 
 void
@@ -671,26 +667,31 @@ plugin_emit_dummy_print (session *sess, char *name)
 }
 
 int
-plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval,
-							 int len, char *string)
+plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, gunichar key)
 {
 	char *word[PDIWORDS];
 	char keyval_str[16];
 	char state_str[16];
 	char len_str[16];
-	int i;
+	char key_str[7];
+	int i, len;
 
 	if (!hook_list)
 		return 0;
 
 	sprintf (keyval_str, "%u", keyval);
 	sprintf (state_str, "%u", state);
+	if (!key)
+		len = 0;
+	else
+		len = g_unichar_to_utf8 (key, key_str);
+	key_str[len] = '\0';
 	sprintf (len_str, "%d", len);
 
 	word[0] = "Key Press";
 	word[1] = keyval_str;
 	word[2] = state_str;
-	word[3] = string;
+	word[3] = key_str;
 	word[4] = len_str;
 	for (i = 5; i < PDIWORDS; i++)
 		word[i] = "\000";
@@ -796,15 +797,11 @@ plugin_add_hook (hexchat_plugin *pl, int type, int pri, const char *name,
 {
 	hexchat_hook *hook;
 
-	hook = malloc (sizeof (hexchat_hook));
-	memset (hook, 0, sizeof (hexchat_hook));
-
+	hook = g_new0 (hexchat_hook, 1);
 	hook->type = type;
 	hook->pri = pri;
-	if (name)
-		hook->name = strdup (name);
-	if (help_text)
-		hook->help_text = strdup (help_text);
+	hook->name = g_strdup (name);
+	hook->help_text = g_strdup (help_text);
 	hook->callback = callb;
 	hook->pl = pl;
 	hook->userdata = userdata;
@@ -892,10 +889,8 @@ hexchat_unhook (hexchat_plugin *ph, hexchat_hook *hook)
 
 	hook->type = HOOK_DELETED;	/* expunge later */
 
-	if (hook->name)
-		free (hook->name);	/* NULL for timers & fds */
-	if (hook->help_text)
-		free (hook->help_text);	/* NULL for non-commands */
+	g_free (hook->name);	/* NULL for timers & fds */
+	g_free (hook->help_text);	/* NULL for non-commands */
 
 	return hook->userdata;
 }
@@ -988,8 +983,7 @@ hexchat_printf (hexchat_plugin *ph, const char *format, ...)
 void
 hexchat_command (hexchat_plugin *ph, const char *command)
 {
-	char *conv;
-	int len = -1;
+	char *command_utf8;
 
 	if (!is_session (ph->context))
 	{
@@ -998,9 +992,9 @@ hexchat_command (hexchat_plugin *ph, const char *command)
 	}
 
 	/* scripts/plugins continue to send non-UTF8... *sigh* */
-	conv = text_validate ((char **)&command, &len);
-	handle_command (ph->context, (char *)command, FALSE);
-	g_free (conv);
+	command_utf8 = text_fixup_invalid_utf8 (command, -1, NULL);
+	handle_command (ph->context, command_utf8, FALSE);
+	g_free (command_utf8);
 }
 
 void
@@ -1263,8 +1257,7 @@ hexchat_list_get (hexchat_plugin *ph, const char *name)
 {
 	hexchat_list *list;
 
-	list = malloc (sizeof (hexchat_list));
-	list->pos = NULL;
+	list = g_new0 (hexchat_list, 1);
 
 	switch (str_hash (name))
 	{
@@ -1299,7 +1292,7 @@ hexchat_list_get (hexchat_plugin *ph, const char *name)
 		}	/* fall through */
 
 	default:
-		free (list);
+		g_free (list);
 		return NULL;
 	}
 
@@ -1311,7 +1304,7 @@ hexchat_list_free (hexchat_plugin *ph, hexchat_list *xlist)
 {
 	if (xlist->type == LIST_USERS)
 		g_slist_free (xlist->head);
-	free (xlist);
+	g_free (xlist);
 }
 
 int
@@ -1531,7 +1524,14 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name)
 		case 0x34207553: /* address32 */
 			return ((struct DCC *)data)->addr;
 		case 0x181a6: /* cps */
-			return ((struct DCC *)data)->cps;
+		{
+			gint64 cps = ((struct DCC *)data)->cps;
+			if (cps <= INT_MAX)
+			{
+				return (int) cps;
+			}
+			return INT_MAX;
+		}
 		case 0x349881: /* port */
 			return ((struct DCC *)data)->port;
 		case 0x1b254: /* pos */
@@ -1569,7 +1569,7 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name)
 		case 0x5cfee87:	/* flags */
 			/* used if text_strip is unset */                    /* 16 */
 			tmp <<= 1;
-			tmp = ((struct session *)data)->text_strip;          /* 15 */
+			tmp |= ((struct session *)data)->text_strip;          /* 15 */
 			tmp <<= 1;
 			/* used if text_scrollback is unset */               /* 14 */
 			tmp <<= 1;
@@ -1644,8 +1644,8 @@ hexchat_plugingui_add (hexchat_plugin *ph, const char *filename,
 							const char *version, char *reserved)
 {
 #ifdef USE_PLUGIN
-	ph = plugin_list_add (NULL, strdup (filename), strdup (name), strdup (desc),
-								 strdup (version), NULL, NULL, TRUE, TRUE);
+	ph = plugin_list_add (NULL, g_strdup (filename), g_strdup (name), g_strdup (desc),
+								 g_strdup (version), NULL, NULL, TRUE, TRUE);
 	fe_pluginlist_update ();
 #endif
 
@@ -1771,6 +1771,8 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
 	{
 		g_free (confname);
 		g_free (confname_tmp);
+		if (fpIn)
+			fclose (fpIn);
 		return 0;
 	}
 	else if (fpIn == NULL)	/* no previous config file, no parsing */
@@ -1819,7 +1821,7 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
 	{
 		prevSetting = 0;
 
-		while (fscanf (fpIn, " %[^\n]", line_bufp) != EOF)	/* read whole lines including whitespaces */
+		while (fscanf (fpIn, " %511[^\n]", line_bufp) != EOF)	/* read whole lines including whitespaces */
 		{
 			buffer_tmp = g_strdup_printf ("%s ", var);	/* add one space, this way it works against var - var2 checks too */
 
@@ -1908,7 +1910,6 @@ hexchat_pluginpref_get_str_real (hexchat_plugin *pl, const char *var, char *dest
 		g_free (confname);
 		return 0;
 	}
-
 	g_free (confname);
 
 	if (!cfg_get_str (cfg, var, buf, sizeof(buf)))
@@ -1937,7 +1938,7 @@ hexchat_pluginpref_set_int (hexchat_plugin *pl, const char *var, int value)
 {
 	char buffer[12];
 
-	snprintf (buffer, sizeof (buffer), "%d", value);
+	g_snprintf (buffer, sizeof (buffer), "%d", value);
 	return hexchat_pluginpref_set_str_real (pl, var, buffer, 1);
 }
 
diff --git a/src/common/plugin.h b/src/common/plugin.h
index cd3f70a8..5743f39a 100644
--- a/src/common/plugin.h
+++ b/src/common/plugin.h
@@ -163,6 +163,7 @@ struct _hexchat_plugin
 };
 #endif
 
+GModule *module_load (char *filename);
 char *plugin_load (session *sess, char *filename, char *arg);
 int plugin_reload (session *sess, char *name, int by_filename);
 void plugin_add (session *sess, char *filename, void *handle, void *init_func, void *deinit_func, char *arg, int fake);
@@ -174,7 +175,7 @@ int plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[
 						time_t server_time);
 int plugin_emit_print (session *sess, char *word[], time_t server_time);
 int plugin_emit_dummy_print (session *sess, char *name);
-int plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, int len, char *string);
+int plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, gunichar key);
 GList* plugin_command_list(GList *tmp_list);
 int plugin_show_help (session *sess, char *cmd);
 void plugin_command_foreach (session *sess, void *userdata, void (*cb) (session *sess, void *userdata, char *name, char *usage));
diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c
index 34b4ece1..d8f15cb5 100644
--- a/src/common/proto-irc.c
+++ b/src/common/proto-irc.c
@@ -429,7 +429,7 @@ irc_raw (server *serv, char *raw)
 		len = strlen (raw);
 		if (len < sizeof (tbuf) - 3)
 		{
-			len = snprintf (tbuf, sizeof (tbuf), "%s\r\n", raw);
+			len = g_snprintf (tbuf, sizeof (tbuf), "%s\r\n", raw);
 			tcp_send_len (serv, tbuf, len);
 		} else
 		{
@@ -590,7 +590,7 @@ process_numeric (session * sess, int n,
 			char *tim;
 			char outbuf[64];
 
-			snprintf (outbuf, sizeof (outbuf),
+			g_snprintf (outbuf, sizeof (outbuf),
 						"%02ld:%02ld:%02ld", idle / 3600, (idle / 60) % 60,
 						idle % 60);
 			if (timestamp == 0)
@@ -666,7 +666,6 @@ process_numeric (session * sess, int n,
 			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMODES, sess, word[4], word_eol[5],
 										  NULL, NULL, 0, tags_data->timestamp);
 		fe_update_mode_buttons (sess, 'c', '-');
-		fe_update_mode_buttons (sess, 'r', '-');
 		fe_update_mode_buttons (sess, 't', '-');
 		fe_update_mode_buttons (sess, 'n', '-');
 		fe_update_mode_buttons (sess, 'i', '-');
@@ -816,10 +815,7 @@ process_numeric (session * sess, int n,
 	case 349:	/* end of exemption list */
 		sess = find_channel (serv, word[4]);
 		if (!sess)
-		{
-			sess = serv->front_session;
 			goto def;
-		}
 		if (!fe_ban_list_end (sess, 349))
 			goto def;
 		break;
@@ -844,10 +840,7 @@ process_numeric (session * sess, int n,
 	case 368:
 		sess = find_channel (serv, word[4]);
 		if (!sess)
-		{
-			sess = serv->front_session;
 			goto def;
-		}
 		if (!fe_ban_list_end (sess, 368))
 			goto def;
 		break;
@@ -1355,8 +1348,8 @@ process_named_servermsg (session *sess, char *buf, char *rawname, char *word_eol
 /* Returns the timezone offset. This should be the same as the variable
  * "timezone" in time.h, but *BSD doesn't have it.
  */
-static int
-get_timezone(void)
+static time_t
+get_timezone (void)
 {
 	struct tm tm_utc, tm_local;
 	time_t t, time_utc, time_local;
@@ -1481,13 +1474,10 @@ irc_inline (server *serv, char *buf, int len)
 	char *type, *text;
 	char *word[PDIWORDS+1];
 	char *word_eol[PDIWORDS+1];
-	char pdibuf_static[522]; /* 1 line can potentially be 512*6 in utf8 */
-	char *pdibuf = pdibuf_static;
+	char *pdibuf;
 	message_tags_data tags_data = MESSAGE_TAGS_DATA_INIT;
 
-	/* need more than 522? fall back to malloc */
-	if (len >= sizeof (pdibuf_static))
-		pdibuf = malloc (len + 1);
+	pdibuf = g_malloc (len + 1);
 
 	sess = serv->front_session;
 
@@ -1509,7 +1499,7 @@ irc_inline (server *serv, char *buf, int len)
 		handle_message_tags(serv, tags, &tags_data);
 	}
 
-	url_check_line (buf, len);
+	url_check_line (buf);
 
 	/* split line into words and words_to_end_of_line */
 	process_data_init (pdibuf, buf, word, word_eol, FALSE, FALSE);
@@ -1566,8 +1556,7 @@ irc_inline (server *serv, char *buf, int len)
 	}
 
 xit:
-	if (pdibuf != pdibuf_static)
-		free (pdibuf);
+	g_free (pdibuf);
 }
 
 void
diff --git a/src/common/server.c b/src/common/server.c
index 98785937..8ff81553 100644
--- a/src/common/server.c
+++ b/src/common/server.c
@@ -21,8 +21,6 @@
  *      Inferno Nettverk A/S, Norway.  All rights reserved.
  */
 
-/*#define DEBUG_MSPROXY*/
-
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -63,20 +61,11 @@
 #include "ssl.h"
 #endif
 
-#ifdef USE_MSPROXY
-#include "msproxy.h"
-#endif
-
-#ifdef WIN32
-#include "identd.h"
-#endif
-
 #ifdef USE_LIBPROXY
 #include <proxy.h>
 #endif
 
 #ifdef USE_OPENSSL
-extern SSL_CTX *ctx;				  /* hexchat.c */
 /* local variables */
 static struct session *g_sess = NULL;
 #endif
@@ -97,57 +86,21 @@ extern pxProxyFactory *libproxy_factory;
    send via SSL. server/dcc both use this function. */
 
 int
-tcp_send_real (void *ssl, int sok, char *encoding, int using_irc, char *buf, int len)
+tcp_send_real (void *ssl, int sok, GIConv write_converter, char *buf, int len)
 {
 	int ret;
-	char *locale;
-	gsize loc_len;
-
-	if (encoding == NULL)	/* system */
-	{
-		locale = NULL;
-		if (!prefs.utf8_locale)
-		{
-			const gchar *charset;
-
-			g_get_charset (&charset);
-			locale = g_convert_with_fallback (buf, len, charset, "UTF-8",
-														 "?", 0, &loc_len, 0);
-		}
-	} else
-	{
-		if (using_irc)	/* using "IRC" encoding (CP1252/UTF-8 hybrid) */
-			/* if all chars fit inside CP1252, use that. Otherwise this
-			   returns NULL and we send UTF-8. */
-			locale = g_convert (buf, len, "CP1252", "UTF-8", 0, &loc_len, 0);
-		else
-			locale = g_convert_with_fallback (buf, len, encoding, "UTF-8",
-														 "?", 0, &loc_len, 0);
-	}
 
-	if (locale)
-	{
-		len = loc_len;
+	gsize buf_encoded_len;
+	gchar *buf_encoded = text_convert_invalid (buf, len, write_converter, "?", &buf_encoded_len);
 #ifdef USE_OPENSSL
-		if (!ssl)
-			ret = send (sok, locale, len, 0);
-		else
-			ret = _SSL_send (ssl, locale, len);
-#else
-		ret = send (sok, locale, len, 0);
-#endif
-		g_free (locale);
-	} else
-	{
-#ifdef USE_OPENSSL
-		if (!ssl)
-			ret = send (sok, buf, len, 0);
-		else
-			ret = _SSL_send (ssl, buf, len);
+	if (!ssl)
+		ret = send (sok, buf_encoded, buf_encoded_len, 0);
+	else
+		ret = _SSL_send (ssl, buf_encoded, buf_encoded_len);
 #else
-		ret = send (sok, buf, len, 0);
+	ret = send (sok, buf_encoded, buf_encoded_len, 0);
 #endif
-	}
+	g_free (buf_encoded);
 
 	return ret;
 }
@@ -157,10 +110,9 @@ server_send_real (server *serv, char *buf, int len)
 {
 	fe_add_rawlog (serv, buf, len, TRUE);
 
-	url_check_line (buf, len);
+	url_check_line (buf);
 
-	return tcp_send_real (serv->ssl, serv->sok, serv->encoding, serv->using_irc,
-								 buf, len);
+	return tcp_send_real (serv->ssl, serv->sok, serv->write_converter, buf, len);
 }
 
 /* new throttling system, uses the same method as the Undernet
@@ -213,7 +165,7 @@ tcp_send_queue (server *serv)
 
 				buf--;
 				serv->outbound_queue = g_slist_remove (serv->outbound_queue, buf);
-				free (buf);
+				g_free (buf);
 				list = serv->outbound_queue;
 			} else
 			{
@@ -235,7 +187,7 @@ tcp_send_len (server *serv, char *buf, int len)
 	if (!prefs.hex_net_throttle)
 		return server_send_real (serv, buf, len);
 
-	dbuf = malloc (len + 2);	/* first byte is the priority */
+	dbuf = g_malloc (len + 2);	/* first byte is the priority */
 	dbuf[0] = 2;	/* pri 2 for most things */
 	memcpy (dbuf + 1, buf, len);
 	dbuf[len + 1] = 0;
@@ -266,12 +218,6 @@ tcp_send_len (server *serv, char *buf, int len)
 	return 1;
 }
 
-/*int
-tcp_send (server *serv, char *buf)
-{
-	return tcp_send_len (serv, buf, strlen (buf));
-}*/
-
 void
 tcp_sendf (server *serv, const char *fmt, ...)
 {
@@ -282,7 +228,7 @@ tcp_sendf (server *serv, const char *fmt, ...)
 	int len;
 
 	va_start (args, fmt);
-	len = vsnprintf (send_buf, sizeof (send_buf) - 1, fmt, args);
+	len = g_vsnprintf (send_buf, sizeof (send_buf) - 1, fmt, args);
 	va_end (args);
 
 	send_buf[sizeof (send_buf) - 1] = '\0';
@@ -309,103 +255,17 @@ close_socket (int sok)
 /* handle 1 line of text received from the server */
 
 static void
-server_inline (server *serv, char *line, int len)
+server_inline (server *serv, char *line, gssize len)
 {
-	char *utf_line_allocated = NULL;
-
-	/* 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 */
-		 (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
-		UTF-8 charset, and if we fail to convert, we assume
-		it to be ISO-8859-1 (see text_validate). */
-
-		utf_line_allocated = text_validate (&line, &len);
-
-	} else
-	{
-		/* Since the user has an explicit charset set, either
-		via /charset command or from his non-UTF8 locale,
-		we don't fallback to ISO-8859-1 and instead try to remove
-		errnoeous octets till the string is convertable in the
-		said charset. */
+	gsize len_utf8;
+	line = text_convert_invalid (line, len, serv->read_converter, unicode_fallback_string, &len_utf8);
 
-		const char *encoding = NULL;
-
-		if (serv->encoding != NULL)
-			encoding = serv->encoding;
-		else
-			g_get_charset (&encoding);
-
-		if (encoding != NULL)
-		{
-			char *conv_line; /* holds a copy of the original string */
-			int conv_len; /* tells g_convert how much of line to convert */
-			gsize utf_len;
-			gsize read_len;
-			GError *err;
-			gboolean retry;
-
-			conv_line = g_malloc (len + 1);
-			memcpy (conv_line, line, len);
-			conv_line[len] = 0;
-			conv_len = len;
-
-			/* if CP1255, convert it with the NUL terminator.
-				Works around SF bug #1122089 */
-			if (serv->using_cp1255)
-				conv_len++;
-
-			do
-			{
-				err = NULL;
-				retry = FALSE;
-				utf_line_allocated = g_convert_with_fallback (conv_line, conv_len, "UTF-8", encoding, "?", &read_len, &utf_len, &err);
-				if (err != NULL)
-				{
-					if (err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE && conv_len > (read_len + 1))
-					{
-						/* Make our best bet by removing the erroneous char.
-						   This will work for casual 8-bit strings with non-standard chars. */
-						memmove (conv_line + read_len, conv_line + read_len + 1, conv_len - read_len -1);
-						conv_len--;
-						retry = TRUE;
-					}
-					g_error_free (err);
-				}
-			} while (retry);
-
-			g_free (conv_line);
-
-			/* If any conversion has occured at all. Conversion might fail
-			due to errors other than invalid sequences, e.g. unknown charset. */
-			if (utf_line_allocated != NULL)
-			{
-				line = utf_line_allocated;
-				len = utf_len;
-				if (serv->using_cp1255 && len > 0)
-					len--;
-			}
-			else
-			{
-				/* If all fails, treat as UTF-8 with fallback to ISO-8859-1. */
-				utf_line_allocated = text_validate (&line, &len);
-			}
-		}
-	}
-
-	fe_add_rawlog (serv, line, len, FALSE);
+	fe_add_rawlog (serv, line, len_utf8, FALSE);
 
 	/* let proto-irc.c handle it */
-	serv->p_inline (serv, line, len);
+	serv->p_inline (serv, line, len_utf8);
 
-	if (utf_line_allocated != NULL) /* only if a special copy was allocated */
-		g_free (utf_line_allocated);
+	g_free (line);
 }
 
 /* read data from socket */
@@ -529,7 +389,7 @@ server_close_pipe (int *pipefd)	/* see comments below */
 {
 	close (pipefd[0]);	/* close WRITE end first to cause an EOF on READ */
 	close (pipefd[1]);	/* in giowin32, and end that thread. */
-	free (pipefd);
+	g_free (pipefd);
 	return FALSE;
 }
 
@@ -562,7 +422,7 @@ server_stopconnecting (server * serv)
 
 	{
 		/* if we close the pipe now, giowin32 will crash. */
-		int *pipefd = malloc (sizeof (int) * 2);
+		int *pipefd = g_new (int, 2);
 		pipefd[0] = serv->childwrite;
 		pipefd[1] = serv->childread;
 		g_idle_add ((GSourceFunc)server_close_pipe, pipefd);
@@ -593,7 +453,7 @@ ssl_cb_info (SSL * s, int where, int ret)
 
 	return;							  /* FIXME: make debug level adjustable in serverlist or settings */
 
-/*	snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
+/*	g_snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
 	if (g_sess)
 		EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
 	else
@@ -613,9 +473,9 @@ ssl_cb_verify (int ok, X509_STORE_CTX * ctx)
 	X509_NAME_oneline (X509_get_issuer_name (ctx->current_cert), issuer,
 							 sizeof (issuer));
 
-	snprintf (buf, sizeof (buf), "* Subject: %s", subject);
+	g_snprintf (buf, sizeof (buf), "* Subject: %s", subject);
 	EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
-	snprintf (buf, sizeof (buf), "* Issuer: %s", issuer);
+	g_snprintf (buf, sizeof (buf), "* Issuer: %s", issuer);
 	EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
 
 	return (TRUE);					  /* always ok */
@@ -627,6 +487,10 @@ ssl_do_connect (server * serv)
 	char buf[128];
 
 	g_sess = serv->server_session;
+
+	/* Set SNI hostname before connect */
+	SSL_set_tlsext_host_name(serv->ssl, serv->hostname);
+
 	if (SSL_connect (serv->ssl) <= 0)
 	{
 		char err_buf[128];
@@ -636,7 +500,7 @@ ssl_do_connect (server * serv)
 		if ((err = ERR_get_error ()) > 0)
 		{
 			ERR_error_string (err, err_buf);
-			snprintf (buf, sizeof (buf), "(%d) %s", err, err_buf);
+			g_snprintf (buf, sizeof (buf), "(%d) %s", err, err_buf);
 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL,
 							 NULL, NULL, 0);
 
@@ -662,59 +526,59 @@ ssl_do_connect (server * serv)
 
 		if (!_SSL_get_cert_info (&cert_info, serv->ssl))
 		{
-			snprintf (buf, sizeof (buf), "* Certification info:");
+			g_snprintf (buf, sizeof (buf), "* Certification info:");
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
-			snprintf (buf, sizeof (buf), "  Subject:");
+			g_snprintf (buf, sizeof (buf), "  Subject:");
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 			for (i = 0; cert_info.subject_word[i]; i++)
 			{
-				snprintf (buf, sizeof (buf), "    %s", cert_info.subject_word[i]);
+				g_snprintf (buf, sizeof (buf), "    %s", cert_info.subject_word[i]);
 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 								 NULL, 0);
 			}
-			snprintf (buf, sizeof (buf), "  Issuer:");
+			g_snprintf (buf, sizeof (buf), "  Issuer:");
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 			for (i = 0; cert_info.issuer_word[i]; i++)
 			{
-				snprintf (buf, sizeof (buf), "    %s", cert_info.issuer_word[i]);
+				g_snprintf (buf, sizeof (buf), "    %s", cert_info.issuer_word[i]);
 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 								 NULL, 0);
 			}
-			snprintf (buf, sizeof (buf), "  Public key algorithm: %s (%d bits)",
+			g_snprintf (buf, sizeof (buf), "  Public key algorithm: %s (%d bits)",
 						 cert_info.algorithm, cert_info.algorithm_bits);
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 			/*if (cert_info.rsa_tmp_bits)
 			{
-				snprintf (buf, sizeof (buf),
+				g_snprintf (buf, sizeof (buf),
 							 "  Public key algorithm uses ephemeral key with %d bits",
 							 cert_info.rsa_tmp_bits);
 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 								 NULL, 0);
 			}*/
-			snprintf (buf, sizeof (buf), "  Sign algorithm %s",
+			g_snprintf (buf, sizeof (buf), "  Sign algorithm %s",
 						 cert_info.sign_algorithm/*, cert_info.sign_algorithm_bits*/);
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
-			snprintf (buf, sizeof (buf), "  Valid since %s to %s",
+			g_snprintf (buf, sizeof (buf), "  Valid since %s to %s",
 						 cert_info.notbefore, cert_info.notafter);
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 		} else
 		{
-			snprintf (buf, sizeof (buf), " * No Certificate");
+			g_snprintf (buf, sizeof (buf), " * No Certificate");
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 		}
 
 		chiper_info = _SSL_get_cipher_info (serv->ssl);	/* static buffer */
-		snprintf (buf, sizeof (buf), "* Cipher info:");
+		g_snprintf (buf, sizeof (buf), "* Cipher info:");
 		EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL,
 						 0);
-		snprintf (buf, sizeof (buf), "  Version: %s, cipher %s (%u bits)",
+		g_snprintf (buf, sizeof (buf), "  Version: %s, cipher %s (%u bits)",
 					 chiper_info->version, chiper_info->chiper,
 					 chiper_info->chiper_bits);
 		EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL,
@@ -724,9 +588,22 @@ ssl_do_connect (server * serv)
 		switch (verify_error)
 		{
 		case X509_V_OK:
-			/* snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
+			{
+				X509 *cert = SSL_get_peer_certificate (serv->ssl);
+				int hostname_err;
+				if ((hostname_err = _SSL_check_hostname(cert, serv->hostname)) != 0)
+				{
+					g_snprintf (buf, sizeof (buf), "* Verify E: Failed to validate hostname? (%d)%s",
+							 hostname_err, serv->accept_invalid_cert ? " -- Ignored" : "");
+					if (serv->accept_invalid_cert)
+						EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0);
+					else
+						goto conn_fail;
+				}
+				break;
+			}
+			/* g_snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
 			/* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
-			break;
 		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
 		case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
 		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
@@ -734,7 +611,7 @@ ssl_do_connect (server * serv)
 		case X509_V_ERR_CERT_HAS_EXPIRED:
 			if (serv->accept_invalid_cert)
 			{
-				snprintf (buf, sizeof (buf), "* Verify E: %s.? (%d) -- Ignored",
+				g_snprintf (buf, sizeof (buf), "* Verify E: %s.? (%d) -- Ignored",
 							 X509_verify_cert_error_string (verify_error),
 							 verify_error);
 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
@@ -742,9 +619,10 @@ ssl_do_connect (server * serv)
 				break;
 			}
 		default:
-			snprintf (buf, sizeof (buf), "%s.? (%d)",
+			g_snprintf (buf, sizeof (buf), "%s.? (%d)",
 						 X509_verify_cert_error_string (verify_error),
 						 verify_error);
+conn_fail:
 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 
@@ -763,7 +641,7 @@ ssl_do_connect (server * serv)
 	{
 		if (serv->ssl->session && serv->ssl->session->time + SSLTMOUT < time (NULL))
 		{
-			snprintf (buf, sizeof (buf), "SSL handshake timed out");
+			g_snprintf (buf, sizeof (buf), "SSL handshake timed out");
 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL,
 							 NULL, NULL, 0);
 			server_cleanup (serv); /* ->connecting = FALSE */
@@ -861,8 +739,8 @@ server_connect_success (server *serv)
 
 		/* it'll be a memory leak, if connection isn't terminated by
 		   server_cleanup() */
-		serv->ssl = _SSL_socket (ctx, serv->sok);
-		if ((err = _SSL_set_verify (ctx, ssl_cb_verify, NULL)))
+		serv->ssl = _SSL_socket (serv->ctx, serv->sok);
+		if ((err = _SSL_set_verify (serv->ctx, ssl_cb_verify, NULL)))
 		{
 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, err, NULL,
 							 NULL, NULL, 0);
@@ -894,9 +772,6 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 	char outbuf[512];
 	char host[100];
 	char ip[100];
-#ifdef USE_MSPROXY
-	char *p;
-#endif
 
 	waitline2 (source, tbuf, sizeof tbuf);
 
@@ -911,12 +786,10 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 		closesocket (serv->sok4);
 		if (serv->proxy_sok4 != -1)
 			closesocket (serv->proxy_sok4);
-#ifdef USE_IPV6
 		if (serv->sok6 != -1)
 			closesocket (serv->sok6);
 		if (serv->proxy_sok6 != -1)
 			closesocket (serv->proxy_sok6);
-#endif
 		EMIT_SIGNAL (XP_TE_UKNHOST, sess, NULL, NULL, NULL, NULL, 0);
 		if (!servlist_cycle (serv))
 			if (prefs.hex_net_auto_reconnectonfail)
@@ -928,12 +801,10 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 		closesocket (serv->sok4);
 		if (serv->proxy_sok4 != -1)
 			closesocket (serv->proxy_sok4);
-#ifdef USE_IPV6
 		if (serv->sok6 != -1)
 			closesocket (serv->sok6);
 		if (serv->proxy_sok6 != -1)
 			closesocket (serv->proxy_sok6);
-#endif
 		EMIT_SIGNAL (XP_TE_CONNFAIL, sess, errorstring (atoi (tbuf)), NULL,
 						 NULL, NULL, 0);
 		if (!servlist_cycle (serv))
@@ -945,49 +816,10 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 		waitline2 (source, ip, sizeof ip);
 		waitline2 (source, outbuf, sizeof outbuf);
 		EMIT_SIGNAL (XP_TE_CONNECT, sess, host, ip, outbuf, NULL, 0);
-#ifdef WIN32
-		if (prefs.hex_identd)
-		{
-			if (serv->network && ((ircnet *)serv->network)->user)
-			{
-				identd_start (((ircnet *)serv->network)->user);
-			}
-			else
-			{
-				identd_start (prefs.hex_irc_user_name);
-			}
-		}
-#else
-		snprintf (outbuf, sizeof (outbuf), "%s/auth/xchat_auth",
-					 g_get_home_dir ());
-		if (access (outbuf, X_OK) == 0)
-		{
-			snprintf (outbuf, sizeof (outbuf), "exec -d %s/auth/xchat_auth %s",
-						 g_get_home_dir (), prefs.hex_irc_user_name);
-			handle_command (serv->server_session, outbuf, FALSE);
-		}
-#endif
 		break;
 	case '4':						  /* success */
 		waitline2 (source, tbuf, sizeof (tbuf));
-#ifdef USE_MSPROXY
-		serv->sok = strtol (tbuf, &p, 10);
-		if (*p++ == ' ')
-		{
-			serv->proxy_sok = strtol (p, &p, 10);
-			serv->msp_state.clientid = strtol (++p, &p, 10);
-			serv->msp_state.serverid = strtol (++p, &p, 10);
-			serv->msp_state.seq_sent = atoi (++p);
-		} else
-			serv->proxy_sok = -1;
-#ifdef DEBUG_MSPROXY
-		printf ("Parent got main socket: %d, proxy socket: %d\n", serv->sok, serv->proxy_sok);
-		printf ("Client ID 0x%08x server ID 0x%08x seq_sent %d\n", serv->msp_state.clientid, serv->msp_state.serverid, serv->msp_state.seq_sent);
-#endif
-#else
 		serv->sok = atoi (tbuf);
-#endif
-#ifdef USE_IPV6
 		/* close the one we didn't end up using */
 		if (serv->sok == serv->sok4)
 			closesocket (serv->sok6);
@@ -1000,7 +832,29 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 			else
 				closesocket (serv->proxy_sok4);
 		}
-#endif
+
+		{
+			struct sockaddr addr;
+			int addr_len = sizeof (addr);
+			guint16 port;
+
+			if (!getsockname (serv->sok, &addr, &addr_len))
+			{
+				if (addr.sa_family == AF_INET)
+					port = ntohs(((struct sockaddr_in *)&addr)->sin_port);
+				else
+					port = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port);
+
+				g_snprintf (outbuf, sizeof (outbuf), "IDENTD %"G_GUINT16_FORMAT" ", port);
+				if (serv->network && ((ircnet *)serv->network)->user)
+					g_strlcat (outbuf, ((ircnet *)serv->network)->user, sizeof (outbuf));
+				else
+					g_strlcat (outbuf, prefs.hex_irc_user_name, sizeof (outbuf));
+
+				handle_command (serv->server_session, outbuf, FALSE);
+			}
+		}
+
 		server_connect_success (serv);
 		break;
 	case '5':						  /* prefs ip discovered */
@@ -1186,7 +1040,7 @@ traverse_socks (int print_fd, int sok, char *serverAddr, int port)
 	if (buf[1] == 90)
 		return 0;
 
-	snprintf (buf, sizeof (buf), "SOCKS\tServer reported error %d,%d.\n", buf[0], buf[1]);
+	g_snprintf (buf, sizeof (buf), "SOCKS\tServer reported error %d,%d.\n", buf[0], buf[1]);
 	proxy_error (print_fd, buf);
 	return 1;
 }
@@ -1270,7 +1124,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
 
 	addrlen = strlen (serverAddr);
 	packetlen = 4 + 1 + addrlen + 2;
-	sc2 = malloc (packetlen);
+	sc2 = g_malloc (packetlen);
 	sc2[0] = 5;						  /* version */
 	sc2[1] = 1;						  /* command */
 	sc2[2] = 0;						  /* reserved */
@@ -1279,7 +1133,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
 	memcpy (sc2 + 5, serverAddr, addrlen);
 	*((unsigned short *) (sc2 + 5 + addrlen)) = htons (port);
 	send (sok, sc2, packetlen, 0);
-	free (sc2);
+	g_free (sc2);
 
 	/* consume all of the reply */
 	if (recv (sok, buf, 4, 0) != 4)
@@ -1287,9 +1141,9 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
 	if (buf[0] != 5 || buf[1] != 0)
 	{
 		if (buf[1] == 2)
-			snprintf (buf, sizeof (buf), "SOCKS\tProxy refused to connect to host (not allowed).\n");
+			g_snprintf (buf, sizeof (buf), "SOCKS\tProxy refused to connect to host (not allowed).\n");
 		else
-			snprintf (buf, sizeof (buf), "SOCKS\tProxy failed to connect to host (error %d).\n", buf[1]);
+			g_snprintf (buf, sizeof (buf), "SOCKS\tProxy failed to connect to host (error %d).\n", buf[1]);
 		proxy_error (print_fd, buf);
 		return 1;
 	}
@@ -1322,7 +1176,7 @@ traverse_wingate (int print_fd, int sok, char *serverAddr, int port)
 {
 	char buf[128];
 
-	snprintf (buf, sizeof (buf), "%s %d\r\n", serverAddr, port);
+	g_snprintf (buf, sizeof (buf), "%s %d\r\n", serverAddr, port);
 	send (sok, buf, strlen (buf), 0);
 
 	return 0;
@@ -1410,16 +1264,16 @@ traverse_http (int print_fd, int sok, char *serverAddr, int port)
 	char auth_data2[252];
 	int n, n2;
 
-	n = snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
+	n = g_snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
 					  serverAddr, port);
 	if (prefs.hex_net_proxy_auth)
 	{
-		n2 = snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
+		n2 = g_snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
 							prefs.hex_net_proxy_user, prefs.hex_net_proxy_pass);
 		base64_encode (auth_data, auth_data2, n2);
-		n += snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
+		n += g_snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
 	}
-	n += snprintf (buf+n, sizeof (buf)-n, "\r\n");
+	n += g_snprintf (buf+n, sizeof (buf)-n, "\r\n");
 	send (sok, buf, n, 0);
 
 	n = http_read_line (print_fd, sok, buf, sizeof (buf));
@@ -1439,7 +1293,7 @@ traverse_http (int print_fd, int sok, char *serverAddr, int port)
 }
 
 static int
-traverse_proxy (int proxy_type, int print_fd, int sok, char *ip, int port, struct msproxy_state_t *state, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound)
+traverse_proxy (int proxy_type, int print_fd, int sok, char *ip, int port, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound)
 {
 	switch (proxy_type)
 	{
@@ -1451,10 +1305,6 @@ traverse_proxy (int proxy_type, int print_fd, int sok, char *ip, int port, struc
 		return traverse_socks5 (print_fd, sok, ip, port);
 	case 4:
 		return traverse_http (print_fd, sok, ip, port);
-#ifdef USE_MSPROXY
-	case 5:
-		return traverse_msproxy (sok, ip, port, state, ns_proxy, csok4, csok6, csok, bound);
-#endif
 	}
 
 	return 1;
@@ -1492,7 +1342,7 @@ server_child (server * serv)
 		local_ip = net_resolve (ns_local, prefs.hex_net_bind_host, 0, &real_hostname);
 		if (local_ip != NULL)
 		{
-			snprintf (buf, sizeof (buf), "5\n%s\n", local_ip);
+			g_snprintf (buf, sizeof (buf), "5\n%s\n", local_ip);
 			write (serv->childwrite, buf, strlen (buf));
 			net_bind (ns_local, serv->sok4, serv->sok6);
 			bound = 1;
@@ -1505,10 +1355,8 @@ server_child (server * serv)
 
 	if (!serv->dont_use_proxy) /* blocked in serverlist? */
 	{
-		if (FALSE)
-			;
 #ifdef USE_LIBPROXY
-		else if (prefs.hex_net_proxy_type == 5)
+		if (prefs.hex_net_proxy_type == 5)
 		{
 			char **proxy_list;
 			char *url, *proxy;
@@ -1532,7 +1380,7 @@ server_child (server * serv)
 			if (proxy_type) {
 				char *c;
 				c = strchr (proxy, ':') + 3;
-				proxy_host = strdup (c);
+				proxy_host = g_strdup (c);
 				c = strchr (proxy_host, ':');
 				*c = '\0';
 				proxy_port = atoi (c + 1);
@@ -1542,12 +1390,12 @@ server_child (server * serv)
 			g_free (url);
 		}
 #endif
-		else if (prefs.hex_net_proxy_host[0] &&
+		if (prefs.hex_net_proxy_host[0] &&
 			   prefs.hex_net_proxy_type > 0 &&
 			   prefs.hex_net_proxy_use != 2) /* proxy is NOT dcc-only */
 		{
 			proxy_type = prefs.hex_net_proxy_type;
-			proxy_host = strdup (prefs.hex_net_proxy_host);
+			proxy_host = g_strdup (prefs.hex_net_proxy_host);
 			proxy_port = prefs.hex_net_proxy_port;
 		}
 	}
@@ -1557,10 +1405,10 @@ server_child (server * serv)
 	/* first resolve where we want to connect to */
 	if (proxy_type > 0)
 	{
-		snprintf (buf, sizeof (buf), "9\n%s\n", proxy_host);
+		g_snprintf (buf, sizeof (buf), "9\n%s\n", proxy_host);
 		write (serv->childwrite, buf, strlen (buf));
 		ip = net_resolve (ns_server, proxy_host, proxy_port, &real_hostname);
-		free (proxy_host);
+		g_free (proxy_host);
 		if (!ip)
 		{
 			write (serv->childwrite, "1\n", 2);
@@ -1579,7 +1427,7 @@ server_child (server * serv)
 				goto xit;
 			}
 		} else						  /* otherwise we can just use the hostname */
-			proxy_ip = strdup (hostname);
+			proxy_ip = g_strdup (hostname);
 	} else
 	{
 		ip = net_resolve (ns_server, hostname, port, &real_hostname);
@@ -1591,7 +1439,7 @@ server_child (server * serv)
 		connect_port = port;
 	}
 
-	snprintf (buf, sizeof (buf), "3\n%s\n%s\n%d\n",
+	g_snprintf (buf, sizeof (buf), "3\n%s\n%s\n%d\n",
 				 real_hostname, ip, connect_port);
 	write (serv->childwrite, buf, strlen (buf));
 
@@ -1605,23 +1453,17 @@ server_child (server * serv)
 
 	if (error != 0)
 	{
-		snprintf (buf, sizeof (buf), "2\n%d\n", sock_error ());
+		g_snprintf (buf, sizeof (buf), "2\n%d\n", sock_error ());
 		write (serv->childwrite, buf, strlen (buf));
 	} else
 	{
 		/* connect succeeded */
 		if (proxy_ip)
 		{
-			switch (traverse_proxy (proxy_type, serv->childwrite, psok, proxy_ip, port, &serv->msp_state, ns_proxy, serv->sok4, serv->sok6, &sok, bound))
+			switch (traverse_proxy (proxy_type, serv->childwrite, psok, proxy_ip, port, ns_proxy, serv->sok4, serv->sok6, &sok, bound))
 			{
 			case 0:	/* success */
-#ifdef USE_MSPROXY
-				if (!serv->dont_use_proxy && (proxy_type == 5))
-					snprintf (buf, sizeof (buf), "4\n%d %d %d %d %d\n", sok, psok, serv->msp_state.clientid, serv->msp_state.serverid,
-						serv->msp_state.seq_sent);
-				else
-#endif
-					snprintf (buf, sizeof (buf), "4\n%d\n", sok);	/* success */
+				g_snprintf (buf, sizeof (buf), "4\n%d\n", sok);	/* success */
 				write (serv->childwrite, buf, strlen (buf));
 				break;
 			case 1:	/* socks traversal failed */
@@ -1630,29 +1472,24 @@ server_child (server * serv)
 			}
 		} else
 		{
-			snprintf (buf, sizeof (buf), "4\n%d\n", sok);	/* success */
+			g_snprintf (buf, sizeof (buf), "4\n%d\n", sok);	/* success */
 			write (serv->childwrite, buf, strlen (buf));
 		}
 	}
 
 xit:
 
-#if defined (USE_IPV6) || defined (WIN32)
 	/* this is probably not needed */
 	net_store_destroy (ns_server);
 	if (ns_proxy)
 		net_store_destroy (ns_proxy);
-#endif
 
 	/* no need to free ip/real_hostname, this process is exiting */
 #ifdef WIN32
 	/* under win32 we use a thread -> shared memory, must free! */
-	if (proxy_ip)
-		free (proxy_ip);
-	if (ip)
-		free (ip);
-	if (real_hostname)
-		free (real_hostname);
+	g_free (proxy_ip);
+	g_free (ip);
+	g_free (real_hostname);
 #endif
 
 	return 0;
@@ -1666,9 +1503,9 @@ server_connect (server *serv, char *hostname, int port, int no_login)
 	session *sess = serv->server_session;
 
 #ifdef USE_OPENSSL
-	if (!ctx && serv->use_ssl)
+	if (!serv->ctx && serv->use_ssl)
 	{
-		if (!(ctx = _SSL_context_init (ssl_cb_info, FALSE)))
+		if (!(serv->ctx = _SSL_context_init (ssl_cb_info)))
 		{
 			fprintf (stderr, "_SSL_context_init failed\n");
 			exit (1);
@@ -1711,18 +1548,18 @@ server_connect (server *serv, char *hostname, int port, int no_login)
 		/* first try network specific cert/key */
 		cert_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "certs" G_DIR_SEPARATOR_S "%s.pem",
 					 get_xdir (), server_get_network (serv, TRUE));
-		if (SSL_CTX_use_certificate_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
+		if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
 		{
-			if (SSL_CTX_use_PrivateKey_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
+			if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
 				serv->have_cert = TRUE;
 		}
 		else
 		{
 			/* if that doesn't exist, try <config>/certs/client.pem */
 			cert_file = g_build_filename (get_xdir (), "certs", "client.pem", NULL);
-			if (SSL_CTX_use_certificate_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
+			if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
 			{
-				if (SSL_CTX_use_PrivateKey_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
+				if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
 					serv->have_cert = TRUE;
 			}
 		}
@@ -1754,16 +1591,8 @@ server_connect (server *serv, char *hostname, int port, int no_login)
 
 	/* create both sockets now, drop one later */
 	net_sockets (&serv->sok4, &serv->sok6);
-#ifdef USE_MSPROXY
-	/* In case of MS Proxy we have a separate UDP control connection */
-	if (!serv->dont_use_proxy && (serv->proxy_type == 5))
-		udp_sockets (&serv->proxy_sok4, &serv->proxy_sok6);
-	else
-#endif
-	{
-		serv->proxy_sok4 = -1;
-		serv->proxy_sok6 = -1;
-	}
+	serv->proxy_sok4 = -1;
+	serv->proxy_sok6 = -1;
 
 #ifdef WIN32
 	CloseHandle (CreateThread (NULL, 0,
@@ -1815,31 +1644,46 @@ server_set_encoding (server *serv, char *new_encoding)
 {
 	char *space;
 
-	if (serv->encoding)
-	{
-		free (serv->encoding);
-		/* can be left as NULL to indicate system encoding */
-		serv->encoding = NULL;
-		serv->using_cp1255 = FALSE;
-		serv->using_irc = FALSE;
-	}
+	g_free (serv->encoding);
 
 	if (new_encoding)
 	{
-		serv->encoding = strdup (new_encoding);
+		serv->encoding = g_strdup (new_encoding);
 		/* the serverlist GUI might have added a space 
 			and short description - remove it. */
 		space = strchr (serv->encoding, ' ');
 		if (space)
 			space[0] = 0;
 
-		/* server_inline() uses these flags */
-		if (!g_ascii_strcasecmp (serv->encoding, "CP1255") ||
-			 !g_ascii_strcasecmp (serv->encoding, "WINDOWS-1255"))
-			serv->using_cp1255 = TRUE;
-		else if (!g_ascii_strcasecmp (serv->encoding, "IRC"))
-			serv->using_irc = TRUE;
+		/* Default legacy "IRC" encoding to utf-8. */
+		if (g_ascii_strcasecmp (serv->encoding, "IRC") == 0)
+		{
+			g_free (serv->encoding);
+			serv->encoding = g_strdup ("UTF-8");
+		}
+
+		else if (!servlist_check_encoding (serv->encoding))
+		{
+			g_free (serv->encoding);
+			serv->encoding = g_strdup ("UTF-8");
+		}
+	}
+	else
+	{
+		serv->encoding = g_strdup ("UTF-8");
+	}
+
+	if (serv->read_converter != NULL)
+	{
+		g_iconv_close (serv->read_converter);
 	}
+	serv->read_converter = g_iconv_open ("UTF-8", serv->encoding);
+
+	if (serv->write_converter != NULL)
+	{
+		g_iconv_close (serv->write_converter);
+	}
+	serv->write_converter = g_iconv_open (serv->encoding, "UTF-8");
 }
 
 server *
@@ -1848,8 +1692,7 @@ server_new (void)
 	static int id = 0;
 	server *serv;
 
-	serv = malloc (sizeof (struct server));
-	memset (serv, 0, sizeof (struct server));
+	serv = g_new0 (struct server, 1);
 
 	/* use server.c and proto-irc.c functions */
 	server_fill_her_up (serv);
@@ -1875,19 +1718,17 @@ is_server (server *serv)
 void
 server_set_defaults (server *serv)
 {
-	if (serv->chantypes)
-		free (serv->chantypes);
-	if (serv->chanmodes)
-		free (serv->chanmodes);
-	if (serv->nick_prefixes)
-		free (serv->nick_prefixes);
-	if (serv->nick_modes)
-		free (serv->nick_modes);
-
-	serv->chantypes = strdup ("#&!+");
-	serv->chanmodes = strdup ("beI,k,l");
-	serv->nick_prefixes = strdup ("@%+");
-	serv->nick_modes = strdup ("ohv");
+	g_free (serv->chantypes);
+	g_free (serv->chanmodes);
+	g_free (serv->nick_prefixes);
+	g_free (serv->nick_modes);
+
+	serv->chantypes = g_strdup ("#&!+");
+	serv->chanmodes = g_strdup ("beI,k,l");
+	serv->nick_prefixes = g_strdup ("@%+");
+	serv->nick_modes = g_strdup ("ohv");
+
+	server_set_encoding (serv, "UTF-8");
 
 	serv->nickcount = 1;
 	serv->end_of_motd = FALSE;
@@ -1991,9 +1832,8 @@ server_away_free_messages (server *serv)
 		if (away->server == serv)
 		{
 			away_list = g_slist_remove (away_list, away);
-			if (away->message)
-				free (away->message);
-			free (away);
+			g_free (away->message);
+			g_free (away);
 			next = away_list;
 		}
 		list = next;
@@ -2007,20 +1847,17 @@ server_away_save_message (server *serv, char *nick, char *msg)
 
 	if (away)						  /* Change message for known user */
 	{
-		if (away->message)
-			free (away->message);
-		away->message = strdup (msg);
-	} else
-		/* Create brand new entry */
+		g_free (away->message);
+		away->message = g_strdup (msg);
+	}
+	else
 	{
-		away = malloc (sizeof (struct away_msg));
-		if (away)
-		{
-			away->server = serv;
-			safe_strcpy (away->nick, nick, sizeof (away->nick));
-			away->message = strdup (msg);
-			away_list = g_slist_prepend (away_list, away);
-		}
+		/* Create brand new entry */
+		away = g_new(struct away_msg, 1);
+		away->server = serv;
+		safe_strcpy (away->nick, nick, sizeof (away->nick));
+		away->message = g_strdup (msg);
+		away_list = g_slist_prepend (away_list, away);
 	}
 }
 
@@ -2035,22 +1872,27 @@ server_free (server *serv)
 	serv->flush_queue (serv);
 	server_away_free_messages (serv);
 
-	free (serv->nick_modes);
-	free (serv->nick_prefixes);
-	free (serv->chanmodes);
-	free (serv->chantypes);
-	if (serv->bad_nick_prefixes)
-		free (serv->bad_nick_prefixes);
-	if (serv->last_away_reason)
-		free (serv->last_away_reason);
-	if (serv->encoding)
-		free (serv->encoding);
+	g_free (serv->nick_modes);
+	g_free (serv->nick_prefixes);
+	g_free (serv->chanmodes);
+	g_free (serv->chantypes);
+	g_free (serv->bad_nick_prefixes);
+	g_free (serv->last_away_reason);
+	g_free (serv->encoding);
+
+	g_iconv_close (serv->read_converter);
+	g_iconv_close (serv->write_converter);
+
 	if (serv->favlist)
 		g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free);
+#ifdef USE_OPENSSL
+	if (serv->ctx)
+		_SSL_context_free (serv->ctx);
+#endif
 
 	fe_server_callback (serv);
 
-	free (serv);
+	g_free (serv);
 
 	notify_cleanup ();
 }
diff --git a/src/common/server.h b/src/common/server.h
index 90e9a9c1..ff8ef404 100644
--- a/src/common/server.h
+++ b/src/common/server.h
@@ -24,9 +24,8 @@ extern GSList *serv_list;
 
 /* eventually need to keep the tcp_* functions isolated to server.c */
 int tcp_send_len (server *serv, char *buf, int len);
-int tcp_send (server *serv, char *buf);
 void tcp_sendf (server *serv, const char *fmt, ...) G_GNUC_PRINTF (2, 3);
-int tcp_send_real (void *ssl, int sok, char *encoding, int using_irc, char *buf, int len);
+int tcp_send_real (void *ssl, int sok, GIConv write_converter, char *buf, int len);
 
 server *server_new (void);
 int is_server (server *serv);
diff --git a/src/common/servlist.c b/src/common/servlist.c
index 7de77596..6f9f9ed2 100644
--- a/src/common/servlist.c
+++ b/src/common/servlist.c
@@ -45,6 +45,7 @@ struct defaultserver
 	char *charset;
 	int loginmode;		/* default authentication type */
 	char *connectcmd;	/* default connect command - should only be used for rare login types, paired with LOGIN_CUSTOM */
+	gboolean ssl;
 };
 
 static const struct defaultserver def[] =
@@ -59,20 +60,11 @@ static const struct defaultserver def[] =
 
 	{"AccessIRC",	0},
 	{0,			"irc.accessirc.net"},
-	{0,			"eu.accessirc.net"},
 
 	{"AfterNET",	0},
 	{0,			"irc.afternet.org"},
-	{0,			"us.afternet.org"},
-	{0,			"eu.afternet.org"},
 
 	{"Aitvaras",	0},
-#ifdef USE_IPV6
-#ifdef USE_OPENSSL
-	{0,			"irc6.ktu.lt/+7668"},
-#endif
-	{0,			"irc6.ktu.lt/7666"},
-#endif
 #ifdef USE_OPENSSL
 	{0,			"irc.data.lt/+6668"},
 	{0,			"irc.omnitel.net/+6668"},
@@ -86,52 +78,25 @@ static const struct defaultserver def[] =
 	{0,			"irc.kis.lt"},
 	{0,			"irc.vub.lt"},
 
-	{"AlphaChat",	0, 0, 0, LOGIN_SASL},
-	{0,			"irc.alphachat.net"},
-	{0,			"na.alphachat.net"},
-	{0,			"eu.alphachat.net"},
-	{0,			"au.alphachat.net"},
-	{0,			"za.alphachat.net"},
-
-	{"Anthrochat", 0},
-#ifdef USE_OPENSSL
-	{0,			"irc.anthrochat.net/+6697"},
-#endif
+	{"Anthrochat", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.anthrochat.net"},
 
 	{"ARCNet",	0},
-	{0,			"se1.arcnet.vapor.com"},
-	{0,			"us1.arcnet.vapor.com"},
-	{0,			"us2.arcnet.vapor.com"},
-	{0,			"us3.arcnet.vapor.com"},
-	{0,			"ca1.arcnet.vapor.com"},
-	{0,			"de1.arcnet.vapor.com"},
-	{0,			"de3.arcnet.vapor.com"},
-	{0,			"ch1.arcnet.vapor.com"},
-	{0,			"be1.arcnet.vapor.com"},
-	{0,			"nl3.arcnet.vapor.com"},
-	{0,			"uk1.arcnet.vapor.com"},
-	{0,			"uk2.arcnet.vapor.com"},
-	{0,			"fr1.arcnet.vapor.com"},
+	{0,			"arcnet-irc.org"},
+
+	{"AthemeNet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.atheme.org"},
 
 	{"AustNet",	0},
-	{0,			"au.austnet.org"},
-	{0,			"us.austnet.org"},
+	{0,			"irc.austnet.org"},
 
 	{"AzzurraNet",	0},
 	{0,			"irc.azzurra.org"},
-	{0,			"crypto.azzurra.org"},
 
-	{"Canternet", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0, 		"irc.canternet.org/+6697"},
-#endif
+	{"Canternet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.canternet.org"},
 
-	{"Chat4all", 0},
-#ifdef USE_OPENSSL
-	{0,			"irc.chat4all.org/+7001"},
-#endif
+	{"Chat4all", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.chat4all.org"},
 
 	{"ChattingAway", 0},
@@ -139,26 +104,21 @@ static const struct defaultserver def[] =
 
 	{"ChatJunkies",	0},
 	{0,			"irc.chatjunkies.org"},
-	{0,			"nl.chatjunkies.org"},
 
 	{"ChatNet",	0},
-	{0,			"US.ChatNet.Org"},
+	{0,			"irc.chatnet.org"},
 
 	{"ChatSpike", 0},
 	{0,			"irc.chatspike.net"},
 
 	{"Criten", 0},
 	{0,			"irc.criten.net"},
-	{0,			"irc.eu.criten.net"},
 
 	{"DALnet", 0},
 	{0,			"irc.dal.net"},
-	{0,			"irc.eu.dal.net"},
 
 	{"Dark-Tou-Net",	0},
 	{0,			"irc.d-t-net.de"},
-	{0,			"bw.d-t-net.de"},
-	{0,			"nc.d-t-net.de"},
 
 	{"DarkMyst", 0, 0, 0, LOGIN_SASL},
 	{0,			"irc.darkmyst.org"},
@@ -177,66 +137,36 @@ static const struct defaultserver def[] =
 	{0,			"irc.lightning.net"},
 	{0,			"irc.servercentral.net"},
 
-	{"ElectroCode",		0},
-#ifdef USE_OPENSSL
-
-	{0,			"irc.electrocode.net/+6697"},
-#endif
+	{"ElectroCode", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.electrocode.net"},
 
 	{"EnterTheGame",	0},
-	{0,			"IRC.EnterTheGame.Com"},
+	{0,			"irc.enterthegame.com"},
 
-	{"EntropyNet",	0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.entropynet.net/+6697"},
-#endif
+	{"EntropyNet",	0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.entropynet.net"},
-#ifdef USE_IPV6
-#ifdef USE_OPENSSL
-	{0,			"irc6.entropynet.net/+6697"},
-#endif
-	{0,			"irc6.entropynet.net"},
-#endif
 
-	{"EsperNet", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.esper.net/+6697"},
-#endif
+	{"EsperNet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.esper.net"},
 
 	{"EUIrc",	0},
 	{0,			"irc.euirc.net"},
-	{0,			"irc.ham.de.euirc.net"},
-	{0,			"irc.ber.de.euirc.net"},
-	{0,			"irc.ffm.de.euirc.net"},
-	{0,			"irc.bre.de.euirc.net"},
-	{0,			"irc.hes.de.euirc.net"},
-	{0,			"irc.inn.at.euirc.net"},
-	{0,			"irc.bas.ch.euirc.net"},
 
 	{"EuropNet", 0},
 	{0,			"irc.europnet.org"},
 
 	{"FDFNet",	0},
 	{0,			"irc.fdfnet.net"},
-	{0,			"irc.eu.fdfnet.net"},
 
 	{"FEFNet", 0, 0, 0, LOGIN_SASL},
 	{0,			"irc.fef.net"},
 
-	{"freenode", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,				"chat.freenode.net/+6697"},
-#endif
+	{"freenode", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,				"chat.freenode.net"},
 	/* irc. points to chat. but many users and urls still reference it */
 	{0,				"irc.freenode.net"},
 
-	{"Furnet",	0},
-#ifdef USE_OPENSSL
-	{0,			"irc.furnet.org/+6697"},
-#endif
+	{"Furnet", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.furnet.org"},
 
 	{"GalaxyNet",	0},
@@ -245,18 +175,14 @@ static const struct defaultserver def[] =
 	{"GameSurge", 0},
 	{0,			"irc.gamesurge.net"},
 	
-	{"GeeksIRC", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.geeksirc.net/+6697"},
-#endif
+	{"GeeksIRC", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.geeksirc.net"},
 
 	{"GeekShed",	0},
 	{0,			"irc.geekshed.net"},
 
 	{"German-Elite",	0},
-	{0,			"dominion.german-elite.net"},
-	{0,			"komatu.german-elite.net"},
+	{0,			"irc.german-elite.net"},
 
 	{"GIMPNet",		0},
 	{0,			"irc.gimp.org"},
@@ -268,22 +194,13 @@ static const struct defaultserver def[] =
 	{"IdleMonkeys", 0},
 	{0,			"irc.idlemonkeys.net"},
 
-	{"IndirectIRC", 0},
-#ifdef USE_OPENSSL
-	{0,			"irc.indirectirc.com/+6697"},
-#endif
+	{"IndirectIRC", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.indirectirc.com"},
 	
-	{"Interlinked", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.interlinked.me/+6697"},
-#endif
+	{"Interlinked", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.interlinked.me"},
 
-	{"IRC4Fun", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,				"irc.irc4fun.net/+6697"},
-#endif
+	{"IRC4Fun", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,				"irc.irc4fun.net"},
 
 	{"IRCHighWay",	0},
@@ -294,28 +211,15 @@ static const struct defaultserver def[] =
 
 	{"IrcLink",	0},
 	{0,			"irc.irclink.net"},
-	{0,			"Alesund.no.eu.irclink.net"},
-	{0,			"Oslo.no.eu.irclink.net"},
-	{0,			"frogn.no.eu.irclink.net"},
-	{0,			"tonsberg.no.eu.irclink.net"},
 
 	{"IRCNet",		0},
 	{0,				"open.ircnet.net"},
-	{0,				"irc.de.ircnet.net"},
-	
-	{"IRCNode", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.ircnode.org/+6697"},
-#endif
-	{0,                     "irc.ircnode.org"},
 
 	{"Irctoo.net",	0},
 	{0,			"irc.irctoo.net"},
 
 	{"iZ-smart.net",	0},
-	{0,			"irc.iZ-smart.net/6666"},
-	{0,			"irc.iZ-smart.net/6667"},
-	{0,			"irc.iZ-smart.net/6668"},
+	{0,			"irc.iz-smart.net"},
 
 	{"Krstarica", 0},
 	{0,			"irc.krstarica.com"},
@@ -323,12 +227,6 @@ static const struct defaultserver def[] =
 #ifdef USE_OPENSSL
 	{"LinkNet",	0},
 	{0,			"irc.link-net.org/+7000"},
-	{0,			"as.link-net.org/+7000"},
-	{0,			"eu.link-net.org/+7000"},
-	{0,			"us.link-net.org/+7000"},
-#ifdef USE_IPV6
-	{0,			"irc6.link-net.org/+7000"},
-#endif
 #endif
 
 	{"MindForge",	0},
@@ -358,31 +256,14 @@ static const struct defaultserver def[] =
 	{"PIRC.PL",	0},
 	{0,			"irc.pirc.pl"},
 	
-	{"PonyChat", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0, 		"irc.ponychat.net/+6697"},
-#endif
+	{"PonyChat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.ponychat.net"},
 
 	{"PTNet.org",   0},
-	{0,			"irc.PTNet.org"},
-	{0,			"world.PTnet.org"},
-	{0,			"netvisao.PTnet.org"},
-	{0,			"uevora.PTnet.org"},
-	{0,			"vianetworks.PTnet.org"},
-	{0,			"uc.PTnet.org"},
-	{0,			"nfsi.ptnet.org"},
-	{0,			"fctunl.ptnet.org"},
+	{0,			"irc.ptnet.org"},
 
 	{"QuakeNet", 0, 0, 0, LOGIN_CHALLENGEAUTH},
 	{0,			"irc.quakenet.org"},
-	{0,			"irc.se.quakenet.org"},
-	{0,			"irc.dk.quakenet.org"},
-	{0,			"irc.no.quakenet.org"},
-	{0,			"irc.fi.quakenet.org"},
-	{0,			"irc.be.quakenet.org"},
-	{0,			"irc.uk.quakenet.org"},
-	{0,			"irc.it.quakenet.org"},
 
 	{"Rizon", 0},
 	{0,			"irc.rizon.net"},
@@ -395,37 +276,21 @@ static const struct defaultserver def[] =
 
 	{"SceneNet",	0},
 	{0,			"irc.scene.org"},
-	{0,			"irc.eu.scene.org"},
-	{0,			"irc.us.scene.org"},
 
 	{"SeilEn.de",	0},
 	{0,			"irc.seilen.de"},
 
-	{"SeionIRC", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.seion.us/+6697"},
-#endif
-	{0,			"irc.seion.us"},
-
 	{"Serenity-IRC",	0},
 	{0,			"irc.serenity-irc.net"},
-	{0,			"eu.serenity-irc.net"},
-	{0,			"us.serenity-irc.net"},
 
 	{"SlashNET",	0},
 	{0,			"irc.slashnet.org"},
-	{0,			"area51.slashnet.org"},
-	{0,			"moo.slashnet.org"},
-	{0,			"radon.slashnet.org"},
 
-	{"Snoonet", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.snoonet.org/+6697"},
-#endif
-	{0,			"irc.snoonet.org/6667"},
+	{"Snoonet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.snoonet.org"},
 
 	{"Snyde", 0},
-	{0,			"irc.snyde.net/6667"},
+	{0,			"irc.snyde.net"},
 
 	{"Sohbet.Net", 0},
 	{0,			"irc.sohbet.net"},
@@ -434,57 +299,28 @@ static const struct defaultserver def[] =
 	{0,			"irc.solidirc.com"},
 
 	{"SorceryNet", 0, 0, 0, LOGIN_SASL},
-	{0,			"irc.sorcery.net/9000"},
-	{0,			"irc.us.sorcery.net/9000"},
-	{0,			"irc.eu.sorcery.net/9000"},
+	{0,			"irc.sorcery.net"},
 	
-	{"SpotChat", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.spotchat.org/+6697"},
-#endif
-	{0,			"irc.spotchat.org/6667"},
+	{"SpotChat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.spotchat.org"},
 
 	{"StarChat", 0},
 	{0,			"irc.starchat.net"},
-	{0,			"gainesville.starchat.net"},
-	{0,			"freebsd.starchat.net"},
-	{0,			"sunset.starchat.net"},
-	{0,			"revenge.starchat.net"},
-	{0,			"tahoma.starchat.net"},
-	{0,			"neo.starchat.net"},
 
-	{"StaticBox", 0, 0, 0, LOGIN_SASL},
-	{0,			"irc.staticbox.net"},
-
-	{"Station51", 0},
-#ifdef USE_OPENSSL
-	{0,			"irc.station51.net/+6697"},
-#endif
+	{"Station51", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.station51.net"},
 
-	{"StormBit", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.stormbit.net/+6697"},
-#endif
+	{"StormBit", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.stormbit.net"},
 
-	{"SwiftIRC", 0},
-#ifdef USE_OPENSSL
-	{0,			"irc.swiftirc.net/+6697"},
-#endif
-	{0,			"irc.swiftirc.net/6667"},
+	{"SwiftIRC", 0, 0, 0, 0, 0, TRUE},
+	{0,			"irc.swiftirc.net"},
 
-	{"synIRC", 0},
-#ifdef USE_OPENSSL
-	{0, "irc.synirc.net/+6697"},
-#endif
-	{0, "irc.synirc.net/6667"},
+	{"synIRC", 0, 0, 0, 0, 0, TRUE},
+	{0, "irc.synirc.net"},
 
-	{"Techman's World IRC",	0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.techmansworld.com/+6697"},
-#endif
-	{0,			"irc.techmansworld.com/6667"},
+	{"Techtronix",	0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.techtronix.net"},
 
 	{"TinyCrab", 0, 0, 0, LOGIN_SASL},
 	{0,			"irc.tinycrab.net"},
@@ -508,16 +344,10 @@ static const struct defaultserver def[] =
 	{"Worldnet",		0},
 	{0,			"irc.worldnet.net"},
 
-	{"Windfyre",		0},
-#ifdef USE_OPENSSL
-	{0,			"irc.windfyre.net/+6697"},
-#endif
+	{"Windfyre", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.windfyre.net"},
 
-	{"Xertion", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.xertion.org/+6697"},
-#endif
+	{"Xertion", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.xertion.org"},
 
 	{0,0}
@@ -566,9 +396,7 @@ servlist_favchan_copy (favchannel *fav)
 {
 	favchannel *newfav;
 
-	newfav = malloc (sizeof (favchannel));
-	memset (newfav, 0, sizeof (favchannel));
-
+	newfav = g_new (favchannel, 1);
 	newfav->name = g_strdup (fav->name);
 	newfav->key = g_strdup (fav->key);		/* g_strdup() can handle NULLs so no need to check it */
 
@@ -924,9 +752,8 @@ servlist_server_add (ircnet *net, char *name)
 {
 	ircserver *serv;
 
-	serv = malloc (sizeof (ircserver));
-	memset (serv, 0, sizeof (ircserver));
-	serv->hostname = strdup (name);
+	serv = g_new (ircserver, 1);
+	serv->hostname = g_strdup (name);
 
 	net->servlist = g_slist_append (net->servlist, serv);
 
@@ -938,9 +765,8 @@ servlist_command_add (ircnet *net, char *cmd)
 {
 	commandentry *entry;
 
-	entry = malloc (sizeof (commandentry));
-	memset (entry, 0, sizeof (commandentry));
-	entry->command = strdup (cmd);
+	entry = g_new (commandentry, 1);
+	entry->command = g_strdup (cmd);
 
 	net->commandlist = g_slist_append (net->commandlist, entry);
 
@@ -952,9 +778,7 @@ servlist_favchan_listadd (GSList *chanlist, char *channel, char *key)
 {
 	favchannel *chan;
 
-	chan = malloc (sizeof (favchannel));
-	memset (chan, 0, sizeof (favchannel));
-
+	chan = g_new (favchannel, 1);
 	chan->name = g_strdup (channel);
 	chan->key = g_strdup (key);
 	chanlist = g_slist_append (chanlist, chan);
@@ -990,8 +814,8 @@ servlist_favchan_add (ircnet *net, char *channel)
 void
 servlist_server_remove (ircnet *net, ircserver *serv)
 {
-	free (serv->hostname);
-	free (serv);
+	g_free (serv->hostname);
+	g_free (serv);
 	net->servlist = g_slist_remove (net->servlist, serv);
 }
 
@@ -1044,7 +868,7 @@ free_and_clear (char *str)
 		char *orig = str;
 		while (*str)
 			*str++ = 0;
-		free (orig);
+		g_free (orig);
 	}
 }
 
@@ -1072,25 +896,18 @@ servlist_net_remove (ircnet *net)
 	servlist_server_remove_all (net);
 	network_list = g_slist_remove (network_list, net);
 
-	if (net->nick)
-		free (net->nick);
-	if (net->nick2)
-		free (net->nick2);
-	if (net->user)
-		free (net->user);
-	if (net->real)
-		free (net->real);
+	g_free (net->nick);
+	g_free (net->nick2);
+	g_free (net->user);
+	g_free (net->real);
 	free_and_clear (net->pass);
 	if (net->favchanlist)
 		g_slist_free_full (net->favchanlist, (GDestroyNotify) servlist_favchan_free);
 	if (net->commandlist)
 		g_slist_free_full (net->commandlist, (GDestroyNotify) servlist_command_free);
-	if (net->comment)
-		free (net->comment);
-	if (net->encoding)
-		free (net->encoding);
-	free (net->name);
-	free (net);
+	g_free (net->encoding);
+	g_free (net->name);
+	g_free (net);
 
 	/* for safety */
 	list = serv_list;
@@ -1110,10 +927,8 @@ servlist_net_add (char *name, char *comment, int prepend)
 {
 	ircnet *net;
 
-	net = malloc (sizeof (ircnet));
-	memset (net, 0, sizeof (ircnet));
-	net->name = strdup (name);
-/*	net->comment = strdup (comment);*/
+	net = g_new0 (ircnet, 1);
+	net->name = g_strdup (name);
 	net->flags = FLAG_CYCLE | FLAG_USE_GLOBAL | FLAG_USE_PROXY;
 
 	if (prepend)
@@ -1156,6 +971,10 @@ servlist_load_defaults (void)
 			{
 				servlist_command_add (net, def[i].connectcmd);
 			}
+			if (def[i].ssl)
+			{
+				net->flags |= FLAG_USE_SSL;
+			}
 
 			if (g_str_hash (def[i].network) == def_hash)
 			{
@@ -1210,25 +1029,25 @@ servlist_load (void)
 			switch (buf[0])
 			{
 			case 'I':
-				net->nick = strdup (buf + 2);
+				net->nick = g_strdup (buf + 2);
 				break;
 			case 'i':
-				net->nick2 = strdup (buf + 2);
+				net->nick2 = g_strdup (buf + 2);
 				break;
 			case 'U':
-				net->user = strdup (buf + 2);
+				net->user = g_strdup (buf + 2);
 				break;
 			case 'R':
-				net->real = strdup (buf + 2);
+				net->real = g_strdup (buf + 2);
 				break;
 			case 'P':
-				net->pass = strdup (buf + 2);
+				net->pass = g_strdup (buf + 2);
 				break;
 			case 'L':
 				net->logintype = atoi (buf + 2);
 				break;
 			case 'E':
-				net->encoding = strdup (buf + 2);
+				net->encoding = servlist_check_encoding (buf + 2) ? g_strdup (buf + 2) : g_strdup ("UTF-8");
 				break;
 			case 'F':
 				net->flags = atoi (buf + 2);
@@ -1258,7 +1077,7 @@ servlist_load (void)
 			case 'A':
 				if (!net->pass)
 				{
-					net->pass = strdup (buf + 2);
+					net->pass = g_strdup (buf + 2);
 					if (!net->logintype)
 					{
 						net->logintype = LOGIN_SASL;
@@ -1267,7 +1086,7 @@ servlist_load (void)
 			case 'B':
 				if (!net->pass)
 				{
-					net->pass = strdup (buf + 2);
+					net->pass = g_strdup (buf + 2);
 					if (!net->logintype)
 					{
 						net->logintype = LOGIN_NICKSERV;
@@ -1302,13 +1121,6 @@ servlist_check_encoding (char *charset)
 	if (c)
 		c[0] = 0;
 
-	if (!g_ascii_strcasecmp (charset, "IRC")) /* special case */
-	{
-		if (c)
-			c[0] = ' ';
-		return TRUE;
-	}
-
 	gic = g_iconv_open (charset, "UTF-8");
 
 	if (c)
@@ -1379,8 +1191,7 @@ servlist_save (void)
 			fprintf (fp, "P=%s\n", net->pass);
 		if (net->logintype)
 			fprintf (fp, "L=%d\n", net->logintype);
-		if (net->encoding && g_ascii_strcasecmp (net->encoding, "System") &&
-			 g_ascii_strcasecmp (net->encoding, "System default"))
+		if (net->encoding)
 		{
 			fprintf (fp, "E=%s\n", net->encoding);
 			if (!servlist_check_encoding (net->encoding))
diff --git a/src/common/servlist.h b/src/common/servlist.h
index 6d6f1bd3..a305aede 100644
--- a/src/common/servlist.h
+++ b/src/common/servlist.h
@@ -45,7 +45,6 @@ typedef struct ircnet
 	char *real;
 	char *pass;
 	int logintype;
-	char *comment;
 	char *encoding;
 	GSList *servlist;
 	GSList *commandlist;
diff --git a/src/common/ssl.c b/src/common/ssl.c
index cfa9b6cf..f4e23665 100644
--- a/src/common/ssl.c
+++ b/src/common/ssl.c
@@ -25,18 +25,29 @@
 #include "inet.h"				  /* make it first to avoid macro redefinitions */
 #include <openssl/ssl.h>		  /* SSL_() */
 #include <openssl/err.h>		  /* ERR_() */
+#include <openssl/x509v3.h>
 #ifdef WIN32
 #include <openssl/rand.h>		  /* RAND_seed() */
 #endif
-#include "../../config.h"
+#include "config.h"
 #include <time.h>				  /* asctime() */
 #include <string.h>				  /* strncpy() */
 #include "ssl.h"				  /* struct cert_info */
 
 #include <glib.h>
 #include <glib/gprintf.h>
+#include <gio/gio.h>
 #include "util.h"
 
+/* If openssl was built without ec */
+#ifndef SSL_OP_SINGLE_ECDH_USE
+#define SSL_OP_SINGLE_ECDH_USE 0
+#endif
+
+#ifndef SSL_OP_NO_COMPRESSION
+#define SSL_OP_NO_COMPRESSION 0
+#endif
+
 /* globals */
 static struct chiper_info chiper_info;		/* static buffer for _SSL_get_cipher_info() */
 static char err_buf[256];			/* generic error buffer */
@@ -69,32 +80,29 @@ __SSL_critical_error (char *funcname)
 /* +++++ SSL functions +++++ */
 
 SSL_CTX *
-_SSL_context_init (void (*info_cb_func), int server)
+_SSL_context_init (void (*info_cb_func))
 {
 	SSL_CTX *ctx;
-#ifdef WIN32
-	int i, r;
-#endif
 
 	SSLeay_add_ssl_algorithms ();
 	SSL_load_error_strings ();
-	ctx = SSL_CTX_new (server ? SSLv23_server_method() : SSLv23_client_method ());
+	ctx = SSL_CTX_new (SSLv23_client_method ());
 
 	SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_BOTH);
 	SSL_CTX_set_timeout (ctx, 300);
+	SSL_CTX_set_options (ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3
+							  |SSL_OP_NO_COMPRESSION
+							  |SSL_OP_SINGLE_DH_USE|SSL_OP_SINGLE_ECDH_USE
+							  |SSL_OP_NO_TICKET
+							  |SSL_OP_CIPHER_SERVER_PREFERENCE);
+
+#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined (OPENSSL_NO_COMP) /* workaround for OpenSSL 0.9.8 */
+	sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
+#endif
 
 	/* used in SSL_connect(), SSL_accept() */
 	SSL_CTX_set_info_callback (ctx, info_cb_func);
 
-#ifdef WIN32
-	/* under win32, OpenSSL needs to be seeded with some randomness */
-	for (i = 0; i < 128; i++)
-	{
-		r = rand ();
-		RAND_seed ((unsigned char *)&r, sizeof (r));
-	}
-#endif
-
 	return(ctx);
 }
 
@@ -329,3 +337,202 @@ _SSL_close (SSL * ssl)
 	SSL_free (ssl);
 	ERR_remove_state (0);		  /* free state buffer */
 }
+
+/* Hostname validation code based on OpenBSD's libtls. */
+
+static int
+_SSL_match_hostname (const char *cert_hostname, const char *hostname)
+{
+	const char *cert_domain, *domain, *next_dot;
+
+	if (g_ascii_strcasecmp (cert_hostname, hostname) == 0)
+		return 0;
+
+	/* Wildcard match? */
+	if (cert_hostname[0] == '*')
+	{
+		/*
+		 * Valid wildcards:
+		 * - "*.domain.tld"
+		 * - "*.sub.domain.tld"
+		 * - etc.
+		 * Reject "*.tld".
+		 * No attempt to prevent the use of eg. "*.co.uk".
+		 */
+		cert_domain = &cert_hostname[1];
+		/* Disallow "*"  */
+		if (cert_domain[0] == '\0')
+			return -1;
+		/* Disallow "*foo" */
+		if (cert_domain[0] != '.')
+			return -1;
+		/* Disallow "*.." */
+		if (cert_domain[1] == '.')
+			return -1;
+		next_dot = strchr (&cert_domain[1], '.');
+		/* Disallow "*.bar" */
+		if (next_dot == NULL)
+			return -1;
+		/* Disallow "*.bar.." */
+		if (next_dot[1] == '.')
+			return -1;
+
+		domain = strchr (hostname, '.');
+
+		/* No wildcard match against a hostname with no domain part. */
+		if (domain == NULL || strlen(domain) == 1)
+			return -1;
+
+		if (g_ascii_strcasecmp (cert_domain, domain) == 0)
+			return 0;
+	}
+
+	return -1;
+}
+
+static int
+_SSL_check_subject_altname (X509 *cert, const char *host)
+{
+	STACK_OF(GENERAL_NAME) *altname_stack = NULL;
+	GInetAddress *addr;
+	GSocketFamily family;
+	int type = GEN_DNS;
+	int count, i;
+	int rv = -1;
+
+	altname_stack = X509_get_ext_d2i (cert, NID_subject_alt_name, NULL, NULL);
+	if (altname_stack == NULL)
+		return -1;
+
+	addr = g_inet_address_new_from_string (host);
+	if (addr != NULL)
+	{
+		family = g_inet_address_get_family (addr);
+		if (family == G_SOCKET_FAMILY_IPV4 || family == G_SOCKET_FAMILY_IPV6)
+			type = GEN_IPADD;
+	}
+
+	count = sk_GENERAL_NAME_num(altname_stack);
+	for (i = 0; i < count; i++)
+	{
+		GENERAL_NAME *altname;
+
+		altname = sk_GENERAL_NAME_value (altname_stack, i);
+
+		if (altname->type != type)
+			continue;
+
+		if (type == GEN_DNS)
+		{
+			unsigned char *data;
+			int format;
+
+			format = ASN1_STRING_type (altname->d.dNSName);
+			if (format == V_ASN1_IA5STRING)
+			{
+				data = ASN1_STRING_data (altname->d.dNSName);
+
+				if (ASN1_STRING_length (altname->d.dNSName) != (int)strlen(data))
+				{
+					g_warning("NUL byte in subjectAltName, probably a malicious certificate.\n");
+					rv = -2;
+					break;
+				}
+
+				if (_SSL_match_hostname (data, host) == 0)
+				{
+					rv = 0;
+					break;
+				}
+			}
+			else
+				g_warning ("unhandled subjectAltName dNSName encoding (%d)\n", format);
+
+		}
+		else if (type == GEN_IPADD)
+		{
+			unsigned char *data;
+			const guint8 *addr_bytes;
+			int datalen, addr_len;
+
+			datalen = ASN1_STRING_length (altname->d.iPAddress);
+			data = ASN1_STRING_data (altname->d.iPAddress);
+
+			addr_bytes = g_inet_address_to_bytes (addr);
+			addr_len = (int)g_inet_address_get_native_size (addr);
+
+			if (datalen == addr_len && memcmp (data, addr_bytes, addr_len) == 0)
+			{
+				rv = 0;
+				break;
+			}
+		}
+	}
+
+	if (addr != NULL)
+		g_object_unref (addr);
+	sk_GENERAL_NAME_pop_free (altname_stack, GENERAL_NAME_free);
+	return rv;
+}
+
+static int
+_SSL_check_common_name (X509 *cert, const char *host)
+{
+	X509_NAME *name;
+	char *common_name = NULL;
+	int common_name_len;
+	int rv = -1;
+	GInetAddress *addr;
+
+	name = X509_get_subject_name (cert);
+	if (name == NULL)
+		return -1;
+
+	common_name_len = X509_NAME_get_text_by_NID (name, NID_commonName, NULL, 0);
+	if (common_name_len < 0)
+		return -1;
+
+	common_name = g_malloc0 (common_name_len + 1);
+
+	X509_NAME_get_text_by_NID (name, NID_commonName, common_name, common_name_len + 1);
+
+	/* NUL bytes in CN? */
+	if (common_name_len != (int)strlen(common_name))
+	{
+		g_warning ("NUL byte in Common Name field, probably a malicious certificate.\n");
+		rv = -2;
+		goto out;
+	}
+
+	if ((addr = g_inet_address_new_from_string (host)) != NULL)
+	{
+		/*
+		 * We don't want to attempt wildcard matching against IP
+		 * addresses, so perform a simple comparison here.
+		 */
+		if (g_strcmp0 (common_name, host) == 0)
+			rv = 0;
+		else
+			rv = -1;
+
+		g_object_unref (addr);
+	}
+	else if (_SSL_match_hostname (common_name, host) == 0)
+		rv = 0;
+
+out:
+	g_free(common_name);
+	return rv;
+}
+
+int
+_SSL_check_hostname (X509 *cert, const char *host)
+{
+	int rv;
+
+	rv = _SSL_check_subject_altname (cert, host);
+	if (rv == 0 || rv == -2)
+		return rv;
+
+	return _SSL_check_common_name (cert, host);
+}
diff --git a/src/common/ssl.h b/src/common/ssl.h
index 9c729855..e722f831 100644
--- a/src/common/ssl.h
+++ b/src/common/ssl.h
@@ -41,7 +41,7 @@ struct chiper_info {
     int chiper_bits;
 };
 
-SSL_CTX *_SSL_context_init (void (*info_cb_func), int server);
+SSL_CTX *_SSL_context_init (void (*info_cb_func));
 #define _SSL_context_free(a)	SSL_CTX_free(a);
 
 SSL *_SSL_socket (SSL_CTX *ctx, int sd);
@@ -52,7 +52,7 @@ char *_SSL_set_verify (SSL_CTX *ctx, void *(verify_callback), char *cacert);
     int SSL_get_fd(SSL *);
 */
 void _SSL_close (SSL * ssl);
-
+int _SSL_check_hostname(X509 *cert, const char *host);
 int _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl);
 struct chiper_info *_SSL_get_cipher_info (SSL * ssl);
 
diff --git a/src/common/text.c b/src/common/text.c
index 329ef37b..cd9ea26e 100644
--- a/src/common/text.c
+++ b/src/common/text.c
@@ -51,6 +51,9 @@
 #include <canberra.h>
 #endif
 
+const gchar* unicode_fallback_string = "\357\277\275"; /* The Unicode replacement character 0xFFFD */
+const gchar* arbitrary_encoding_fallback_string = "?";
+
 struct pevt_stage1
 {
 	int len;
@@ -83,7 +86,7 @@ scrollback_get_filename (session *sess)
 		buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "scrollback" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s.txt", get_xdir (), net, chan);
 	else
 		buf = NULL;
-	free (chan);
+	g_free (chan);
 
 	return buf;
 }
@@ -173,11 +176,11 @@ scrollback_shrink (session *sess)
 		p++;
 	}
 
-	fh = g_open (file, O_CREAT | O_TRUNC | O_APPEND | O_WRONLY, 0644);
+	fh = g_open (file, O_CREAT | O_TRUNC | O_APPEND | O_WRONLY | OFLAGS, 0644);
 	g_free (file);
 	if (fh == -1)
 	{
-		free (buf);
+		g_free (buf);
 		return;
 	}
 
@@ -200,14 +203,13 @@ scrollback_shrink (session *sess)
 	}
 
 	close (fh);
-	free (buf);
+	g_free (buf);
 }
 
 static void
-scrollback_save (session *sess, char *text)
+scrollback_save (session *sess, char *text, time_t stamp)
 {
 	char *buf;
-	time_t stamp;
 	int len;
 
 	if (sess->type == SESS_SERVER && prefs.hex_gui_tab_server == 1)
@@ -229,13 +231,14 @@ scrollback_save (session *sess, char *text)
 		if ((buf = scrollback_get_filename (sess)) == NULL)
 			return;
 
-		sess->scrollfd = g_open (buf, O_CREAT | O_APPEND | O_WRONLY, 0644);
+		sess->scrollfd = g_open (buf, O_CREAT | O_APPEND | O_WRONLY | OFLAGS, 0644);
 		g_free (buf);
 		if (sess->scrollfd == -1)
 			return;
 	}
 
-	stamp = time (0);
+	if (!stamp)
+		stamp = time(0);
 	if (sizeof (stamp) == 4)	/* gcc will optimize one of these out */
 		buf = g_strdup_printf ("T %d ", (int) stamp);
 	else
@@ -298,13 +301,6 @@ scrollback_load (session *sess)
 		{
 			char *buf_tmp;
 
-			/* If nothing but funny trailing matter e.g. 0x0d or 0x0d0a, toss it */
-			if (n_bytes >= 1 && buf[0] == 0x0d)
-			{
-				g_free (buf);
-				continue;
-			}
-
 			n_bytes--;
 			buf_tmp = buf;
 			buf = g_strndup (buf_tmp, n_bytes);
@@ -319,9 +315,9 @@ scrollback_load (session *sess)
 			if (buf[0] == 'T')
 			{
 				if (sizeof (time_t) == 4)
-					stamp = strtoul (buf + 2, NULL, 10);
+					stamp = g_ascii_strtoull (buf + 2, NULL, 10);
 				else
-					stamp = strtoull (buf + 2, NULL, 10); /* in case time_t is 64 bits */
+					stamp = g_ascii_strtoull (buf + 2, NULL, 10); /* in case time_t is 64 bits */
 				text = strchr (buf + 3, ' ');
 				if (text && text[1])
 				{
@@ -383,7 +379,7 @@ log_close (session *sess)
 	{
 		currenttime = time (NULL);
 		write (sess->logfd, obuf,
-			 snprintf (obuf, sizeof (obuf) - 1, _("**** ENDING LOGGING AT %s\n"),
+			 g_snprintf (obuf, sizeof (obuf) - 1, _("**** ENDING LOGGING AT %s\n"),
 						  ctime (&currenttime)));
 		close (sess->logfd);
 		sess->logfd = -1;
@@ -393,9 +389,7 @@ log_close (session *sess)
 static void
 mkdir_p (char *filename)
 {
-	char *dirname;
-	
-	dirname = g_path_get_dirname (filename);
+	char *dirname = g_path_get_dirname (filename);
 
 	g_mkdir_with_parents (dirname, 0700);
 
@@ -408,7 +402,7 @@ log_create_filename (char *channame)
 	char *tmp, *ret;
 	int mbl;
 
-	ret = tmp = strdup (channame);
+	ret = tmp = g_strdup (channame);
 	while (*tmp)
 	{
 		mbl = g_utf8_skip[((unsigned char *)tmp)[0]];
@@ -507,34 +501,6 @@ log_insert_vars (char *buf, int bufsize, char *fmt, char *c, char *n, char *s)
 	}
 }
 
-static int
-logmask_is_fullpath ()
-{
-	/* Check if final path/filename is absolute or relative.
-	 * If one uses log mask variables, such as "%c/...", %c will be empty upon
-	 * connecting since there's no channel name yet, so we have to make sure
-	 * we won't try to write to the FS root. On Windows we can be sure it's
-	 * full path if the 2nd character is a colon since Windows doesn't allow
-	 * colons in filenames.
-	 */
-#ifdef WIN32
-	/* Treat it as full path if it
-	 * - starts with '\' which denotes the root directory of the current drive letter
-	 * - starts with a drive letter and followed by ':'
-	 */
-	if (prefs.hex_irc_logmask[0] == '\\' || (((prefs.hex_irc_logmask[0] >= 'A' && prefs.hex_irc_logmask[0] <= 'Z') || (prefs.hex_irc_logmask[0] >= 'a' && prefs.hex_irc_logmask[0] <= 'z')) && prefs.hex_irc_logmask[1] == ':'))
-#else
-	if (prefs.hex_irc_logmask[0] == '/')
-#endif
-	{
-		return 1;
-	}
-	else
-	{
-		return 0;
-	}
-}
-
 static char *
 log_create_pathname (char *servname, char *channame, char *netname)
 {
@@ -544,7 +510,7 @@ log_create_pathname (char *servname, char *channame, char *netname)
 
 	if (!netname)
 	{
-		netname = strdup ("NETWORK");
+		netname = g_strdup ("NETWORK");
 	}
 	else
 	{
@@ -554,7 +520,7 @@ log_create_pathname (char *servname, char *channame, char *netname)
 	/* first, everything is in UTF-8 */
 	if (!rfc_casecmp (channame, servname))
 	{
-		channame = strdup ("server");
+		channame = g_strdup ("server");
 	}
 	else
 	{
@@ -562,27 +528,29 @@ log_create_pathname (char *servname, char *channame, char *netname)
 	}
 
 	log_insert_vars (fname, sizeof (fname), prefs.hex_irc_logmask, channame, netname, servname);
-	free (channame);
-	free (netname);
+	g_free (channame);
+	g_free (netname);
 
 	/* insert time/date */
 	now = time (NULL);
 	strftime_utf8 (fnametime, sizeof (fnametime), fname, now);
 
-	/* create final path/filename */
-	if (logmask_is_fullpath ())
+	/* If one uses log mask variables, such as "%c/...", %c will be empty upon
+	 * connecting since there's no channel name yet, so we have to make sure
+	 * we won't try to write to the FS root. */
+	if (g_path_is_absolute (prefs.hex_irc_logmask))
 	{
-		snprintf (fname, sizeof (fname), "%s", fnametime);
+		g_snprintf (fname, sizeof (fname), "%s", fnametime);
 	}
 	else	/* relative path */
 	{
-		snprintf (fname, sizeof (fname), "%s" G_DIR_SEPARATOR_S "logs" G_DIR_SEPARATOR_S "%s", get_xdir (), fnametime);
+		g_snprintf (fname, sizeof (fname), "%s" G_DIR_SEPARATOR_S "logs" G_DIR_SEPARATOR_S "%s", get_xdir (), fnametime);
 	}
 
 	/* create all the subdirectories */
 	mkdir_p (fname);
 
-	return g_strdup(fname);
+	return g_strdup (fname);
 }
 
 static int
@@ -597,18 +565,14 @@ log_open_file (char *servname, char *channame, char *netname)
 	if (!file)
 		return -1;
 
-#ifdef WIN32
-	fd = g_open (file, O_CREAT | O_APPEND | O_WRONLY, S_IREAD|S_IWRITE);
-#else
-	fd = g_open (file, O_CREAT | O_APPEND | O_WRONLY, 0644);
-#endif
+	fd = g_open (file, O_CREAT | O_APPEND | O_WRONLY | OFLAGS, 0644);
 	g_free (file);
 
 	if (fd == -1)
 		return -1;
 	currenttime = time (NULL);
 	write (fd, buf,
-			 snprintf (buf, sizeof (buf), _("**** BEGIN LOGGING AT %s\n"),
+			 g_snprintf (buf, sizeof (buf), _("**** BEGIN LOGGING AT %s\n"),
 						  ctime (&currenttime)));
 
 	return fd;
@@ -625,14 +589,15 @@ log_open (session *sess)
 
 	if (!log_error && sess->logfd == -1)
 	{
-		char *message;
+		char *filename = log_create_pathname (sess->server->servername, sess->channel, server_get_network (sess->server, FALSE));
+		char *message = g_strdup_printf (_("* Can't open log file(s) for writing. Check the\npermissions on %s"), filename);
 
-		message = g_strdup_printf (_("* Can't open log file(s) for writing. Check the\npermissions on %s"),
-			log_create_pathname (sess->server->servername, sess->channel, server_get_network (sess->server, FALSE)));
+		g_free (filename);
 
 		fe_message (message, FE_MSG_WAIT | FE_MSG_ERROR);
 
 		g_free (message);
+
 		log_error = TRUE;
 	}
 }
@@ -659,34 +624,29 @@ log_open_or_close (session *sess)
 int
 get_stamp_str (char *fmt, time_t tim, char **ret)
 {
-	char *loc = NULL;
 	char dest[128];
-	gsize len;
+	gsize len_locale;
+	gsize len_utf8;
 
-	/* strftime wants the format string in LOCALE! */
-	if (!prefs.utf8_locale)
-	{
-		const gchar *charset;
+	/* strftime requires the format string to be in locale encoding. */
+	fmt = g_locale_from_utf8 (fmt, -1, NULL, NULL, NULL);
 
-		g_get_charset (&charset);
-		loc = g_convert_with_fallback (fmt, -1, charset, "UTF-8", "?", 0, 0, 0);
-		if (loc)
-			fmt = loc;
-	}
+	len_locale = strftime_validated (dest, sizeof (dest), fmt, localtime (&tim));
 
-	len = strftime_validated (dest, sizeof (dest), fmt, localtime (&tim));
-	if (len)
+	g_free (fmt);
+
+	if (len_locale == 0)
 	{
-		if (prefs.utf8_locale)
-			*ret = g_strdup (dest);
-		else
-			*ret = g_locale_to_utf8 (dest, len, 0, &len, 0);
+		return 0;
 	}
 
-	if (loc)
-		g_free (loc);
+	*ret = g_locale_to_utf8 (dest, len_locale, NULL, &len_utf8, NULL);
+	if (*ret == NULL)
+	{
+		return 0;
+	}
 
-	return len;
+	return len_utf8;
 }
 
 static void
@@ -709,22 +669,32 @@ log_write (session *sess, char *text, time_t ts)
 	}
 
 	if (sess->logfd == -1)
+	{
 		log_open (sess);
+	}
 
 	/* change to a different log file? */
-	file = log_create_pathname (sess->server->servername, sess->channel,
-										 server_get_network (sess->server, FALSE));
+	file = log_create_pathname (sess->server->servername, sess->channel, server_get_network (sess->server, FALSE));
 	if (file)
 	{
 		if (g_access (file, F_OK) != 0)
 		{
-			close (sess->logfd);
-			sess->logfd = log_open_file (sess->server->servername, sess->channel,
-												  server_get_network (sess->server, FALSE));
+			if (sess->logfd != -1)
+			{
+				close (sess->logfd);
+			}
+
+			sess->logfd = log_open_file (sess->server->servername, sess->channel, server_get_network (sess->server, FALSE));
 		}
+
 		g_free (file);
 	}
 
+	if (sess->logfd == -1)
+	{
+		return;
+	}
+
 	if (prefs.hex_stamp_log)
 	{
 		if (!ts) ts = time(0);
@@ -735,6 +705,7 @@ log_write (session *sess, char *text, time_t ts)
 			g_free (stamp);
 		}
 	}
+
 	temp = strip_color (text, -1, STRIP_ALL);
 	len = strlen (temp);
 	write (sess->logfd, temp, len);
@@ -744,156 +715,104 @@ log_write (session *sess, char *text, time_t ts)
 	g_free (temp);
 }
 
-/* converts a CP1252/ISO-8859-1(5) hybrid to UTF-8                           */
-/* Features: 1. It never fails, all 00-FF chars are converted to valid UTF-8 */
-/*           2. Uses CP1252 in the range 80-9f because ISO doesn't have any- */
-/*              thing useful in this range and it helps us receive from mIRC */
-/*           3. The five undefined chars in CP1252 80-9f are replaced with   */
-/*              ISO-8859-15 control codes.                                   */
-/*           4. Handles 0xa4 as a Euro symbol ala ISO-8859-15.               */
-/*           5. Uses ISO-8859-1 (which matches CP1252) for everything else.  */
-/*           6. This routine measured 3x faster than g_convert :)            */
-
-static unsigned char *
-iso_8859_1_to_utf8 (unsigned char *text, int len, gsize *bytes_written)
+/**
+ * Converts a given string using the given iconv converter. This is similar to g_convert_with_fallback, except that it is tolerant of sequences in
+ * the original input that are invalid even in from_encoding. g_convert_with_fallback fails for such text, whereas this function replaces such a
+ * sequence with the fallback string.
+ *
+ * If len is -1, strlen(text) is used to calculate the length. Do not pass -1 if text is supposed to contain \0 bytes, such as if from_encoding is a
+ * multi-byte encoding like UTF-16.
+ */
+gchar *
+text_convert_invalid (const gchar* text, gssize len, GIConv converter, const gchar *fallback, gsize *len_out)
 {
-	unsigned int idx;
-	unsigned char *res, *output;
-	static const unsigned short lowtable[] = /* 74 byte table for 80-a4 */
-	{
-	/* compressed utf-8 table: if the first byte's 0x20 bit is set, it
-	   indicates a 2-byte utf-8 sequence, otherwise prepend a 0xe2. */
-		0x82ac, /* 80 Euro. CP1252 from here on... */
-		0xe281, /* 81 NA */
-		0x809a, /* 82 */
-		0xe692, /* 83 */
-		0x809e, /* 84 */
-		0x80a6, /* 85 */
-		0x80a0, /* 86 */
-		0x80a1, /* 87 */
-		0xeb86, /* 88 */
-		0x80b0, /* 89 */
-		0xe5a0, /* 8a */
-		0x80b9, /* 8b */
-		0xe592, /* 8c */
-		0xe28d, /* 8d NA */
-		0xe5bd, /* 8e */
-		0xe28f, /* 8f NA */
-		0xe290, /* 90 NA */
-		0x8098, /* 91 */
-		0x8099, /* 92 */
-		0x809c, /* 93 */
-		0x809d, /* 94 */
-		0x80a2, /* 95 */
-		0x8093, /* 96 */
-		0x8094, /* 97 */
-		0xeb9c, /* 98 */
-		0x84a2, /* 99 */
-		0xe5a1, /* 9a */
-		0x80ba, /* 9b */
-		0xe593, /* 9c */
-		0xe29d, /* 9d NA */
-		0xe5be, /* 9e */
-		0xe5b8, /* 9f */
-		0xe2a0, /* a0 */
-		0xe2a1, /* a1 */
-		0xe2a2, /* a2 */
-		0xe2a3, /* a3 */
-		0x82ac  /* a4 ISO-8859-15 Euro. */
-	};
+	gchar *result_part;
+	gsize result_part_len;
+	const gchar *end;
+	gsize invalid_start_pos;
+	GString *result;
+	const gchar *current_start;
 
 	if (len == -1)
+	{
 		len = strlen (text);
+	}
 
-	/* worst case scenario: every byte turns into 3 bytes */
-	res = output = g_malloc ((len * 3) + 1);
-	if (!output)
-		return NULL;
+	end = text + len;
 
-	while (len)
+	/* Find the first position of an invalid sequence. */
+	result_part = g_convert_with_iconv (text, len, converter, &invalid_start_pos, &result_part_len, NULL);
+	if (result_part != NULL)
 	{
-		if (G_LIKELY (*text < 0x80))
+		/* All text converted successfully on the first try. Return it. */
+
+		if (len_out != NULL)
 		{
-			*output = *text;	/* ascii maps directly */
+			*len_out = result_part_len;
 		}
-		else if (*text <= 0xa4)	/* 80-a4 use a lookup table */
+
+		return result_part;
+	}
+
+	/* One or more invalid sequences exist that need to be replaced with the fallback. */
+
+	result = g_string_sized_new (len);
+	current_start = text;
+
+	for (;;)
+	{
+		g_assert (current_start + invalid_start_pos < end);
+
+		/* Convert everything before the position of the invalid sequence. It should be successful. */
+		result_part = g_convert_with_iconv (current_start, invalid_start_pos, converter, &invalid_start_pos, &result_part_len, NULL);
+		g_assert (result_part != NULL);
+		g_string_append_len (result, result_part, result_part_len);
+		g_free (result_part);
+
+		/* Append the fallback */
+		g_string_append (result, fallback);
+
+		/* Now try converting everything after the invalid sequence. */
+		current_start += invalid_start_pos + 1;
+
+		result_part = g_convert_with_iconv (current_start, end - current_start, converter, &invalid_start_pos, &result_part_len, NULL);
+		if (result_part != NULL)
 		{
-			idx = *text - 0x80;
-			if (lowtable[idx] & 0x2000)
-			{
-				*output++ = (lowtable[idx] >> 8) & 0xdf; /* 2 byte utf-8 */
-				*output = lowtable[idx] & 0xff;
-			}
-			else
+			/* The rest of the text converted successfully. Append it and return the whole converted text. */
+
+			g_string_append_len (result, result_part, result_part_len);
+			g_free (result_part);
+
+			if (len_out != NULL)
 			{
-				*output++ = 0xe2;	/* 3 byte utf-8 */
-				*output++ = (lowtable[idx] >> 8) & 0xff;
-				*output = lowtable[idx] & 0xff;
+				*len_out = result->len;
 			}
+
+			return g_string_free (result, FALSE);
 		}
-		else if (*text < 0xc0)
-		{
-			*output++ = 0xc2;
-			*output = *text;
-		}
-		else
-		{
-			*output++ = 0xc3;
-			*output = *text - 0x40;
-		}
-		output++;
-		text++;
-		len--;
-	}
-	*output = 0;	/* terminate */
-	*bytes_written = output - res;
 
-	return res;
+		/* The rest of the text didn't convert successfully. invalid_start_pos has the position of the next invalid sequence. */
+	}
 }
 
-char *
-text_validate (char **text, int *len)
+/**
+ * Replaces any invalid UTF-8 in the given text with the unicode replacement character.
+ */
+gchar *
+text_fixup_invalid_utf8 (const gchar* text, gssize len, gsize *len_out)
 {
-	char *utf;
-	gsize utf_len;
-
-	/* valid utf8? */
-	if (g_utf8_validate (*text, *len, 0))
-		return NULL;
-
-#ifdef WIN32
-	if (GetACP () == 1252) /* our routine is better than iconv's 1252 */
-#else
-	if (prefs.utf8_locale)
-#endif
-		/* fallback to iso-8859-1 */
-		utf = iso_8859_1_to_utf8 (*text, *len, &utf_len);
-	else
+	static GIConv utf8_fixup_converter = NULL;
+	if (utf8_fixup_converter == NULL)
 	{
-		/* fallback to locale */
-		utf = g_locale_to_utf8 (*text, *len, 0, &utf_len, NULL);
-		if (!utf)
-			utf = iso_8859_1_to_utf8 (*text, *len, &utf_len);
+		utf8_fixup_converter = g_iconv_open ("UTF-8", "UTF-8");
 	}
 
-	if (!utf) 
-	{
-		*text = g_strdup ("%INVALID%");
-		*len = 9;
-	} else
-	{
-		*text = utf;
-		*len = utf_len;
-	}
-
-	return utf;
+	return text_convert_invalid (text, len, utf8_fixup_converter, unicode_fallback_string, len_out);
 }
 
 void
 PrintTextTimeStamp (session *sess, char *text, time_t timestamp)
 {
-	char *conv;
-
 	if (!sess)
 	{
 		if (!sess_list)
@@ -902,22 +821,19 @@ PrintTextTimeStamp (session *sess, char *text, time_t timestamp)
 	}
 
 	/* make sure it's valid utf8 */
-	if (text[0] == 0)
+	if (text[0] == '\0')
 	{
-		text = "\n";
-		conv = NULL;
-	} else
+		text = g_strdup ("\n");
+	}
+	else
 	{
-		int len = -1;
-		conv = text_validate ((char **)&text, &len);
+		text = text_fixup_invalid_utf8 (text, -1, NULL);
 	}
 
 	log_write (sess, text, timestamp);
-	scrollback_save (sess, text);
+	scrollback_save (sess, text, timestamp);
 	fe_print_text (sess, text, timestamp, FALSE);
-
-	if (conv)
-		g_free (conv);
+	g_free (text);
 }
 
 void
@@ -1004,7 +920,7 @@ PrintTextTimeStampf (session *sess, time_t timestamp, const char *format, ...)
    Each XP_TE_* signal is hard coded to call text_emit which calls
    display_event which decodes the data
 
-   This means that this system *should be faster* than snprintf because
+   This means that this system *should be faster* than g_snprintf because
    it always 'knows' that format of the string (basically is preparses much
    of the work)
 
@@ -1211,26 +1127,26 @@ static char * const pevt_chanrmlimit_help[] = {
 };
 
 static char * const pevt_chandeop_help[] = {
-	N_("The nick of the person of did the deop'ing"),
+	N_("The nick of the person who did the deop'ing"),
 	N_("The nick of the person who has been deop'ed"),
 };
 static char * const pevt_chandehop_help[] = {
-	N_("The nick of the person of did the dehalfop'ing"),
+	N_("The nick of the person who did the dehalfop'ing"),
 	N_("The nick of the person who has been dehalfop'ed"),
 };
 
 static char * const pevt_chandevoice_help[] = {
-	N_("The nick of the person of did the devoice'ing"),
+	N_("The nick of the person who did the devoice'ing"),
 	N_("The nick of the person who has been devoice'ed"),
 };
 
 static char * const pevt_chanunban_help[] = {
-	N_("The nick of the person of did the unban'ing"),
+	N_("The nick of the person who did the unban'ing"),
 	N_("The ban mask"),
 };
 
 static char * const pevt_chanunquiet_help[] = {
-	N_("The nick of the person of did the unquiet'ing"),
+	N_("The nick of the person who did the unquiet'ing"),
 	N_("The quiet mask"),
 };
 
@@ -1569,14 +1485,13 @@ pevent_load_defaults ()
 
 	for (i = 0; i < NUM_XP; i++)
 	{
-		if (pntevts_text[i])
-			free (pntevts_text[i]);
+		g_free (pntevts_text[i]);
 
 		/* make-te.c sets this 128 flag (DON'T call gettext() flag) */
 		if (te[i].num_args & 128)
-			pntevts_text[i] = strdup (te[i].def);
+			pntevts_text[i] = g_strdup (te[i].def);
 		else
-			pntevts_text[i] = strdup (_(te[i].def));
+			pntevts_text[i] = g_strdup (_(te[i].def));
 	}
 }
 
@@ -1588,19 +1503,18 @@ pevent_make_pntevts ()
 
 	for (i = 0; i < NUM_XP; i++)
 	{
-		if (pntevts[i] != NULL)
-			free (pntevts[i]);
+		g_free (pntevts[i]);
 		if (pevt_build_string (pntevts_text[i], &(pntevts[i]), &m) != 0)
 		{
-			snprintf (out, sizeof (out),
+			g_snprintf (out, sizeof (out),
 						 _("Error parsing event %s.\nLoading default."), te[i].name);
 			fe_message (out, FE_MSG_WARN);
-			free (pntevts_text[i]);
+			g_free (pntevts_text[i]);
 			/* make-te.c sets this 128 flag (DON'T call gettext() flag) */
 			if (te[i].num_args & 128)
-				pntevts_text[i] = strdup (te[i].def);
+				pntevts_text[i] = g_strdup (te[i].def);
 			else
-				pntevts_text[i] = strdup (_(te[i].def));
+				pntevts_text[i] = g_strdup (_(te[i].def));
 			if (pevt_build_string (pntevts_text[i], &(pntevts[i]), &m) != 0)
 			{
 				fprintf (stderr,
@@ -1622,22 +1536,17 @@ pevent_make_pntevts ()
 static void
 pevent_trigger_load (int *i_penum, char **i_text, char **i_snd)
 {
-	int penum = *i_penum, len;
+	int penum = *i_penum;
 	char *text = *i_text, *snd = *i_snd;
 
 	if (penum != -1 && text != NULL)
 	{
-		len = strlen (text) + 1;
-		if (pntevts_text[penum])
-			free (pntevts_text[penum]);
-		pntevts_text[penum] = malloc (len);
-		memcpy (pntevts_text[penum], text, len);
+		g_free (pntevts_text[penum]);
+		pntevts_text[penum] = g_strdup (text);
 	}
 
-	if (text)
-		free (text);
-	if (snd)
-		free (snd);
+	g_free (text);
+	g_free (snd);
 	*i_text = NULL;
 	*i_snd = NULL;
 	*i_penum = 0;
@@ -1690,7 +1599,7 @@ pevent_load (char *filename)
 		close (fd);
 		return 1;
 	}
-	ibuf = malloc (st.st_size);
+	ibuf = g_malloc (st.st_size);
 	read (fd, ibuf, st.st_size);
 	close (fd);
 
@@ -1706,8 +1615,6 @@ pevent_load (char *filename)
 			continue;
 		*ofs = 0;
 		ofs++;
-		/*if (*ofs == 0)
-			continue;*/
 
 		if (strcmp (buf, "event_name") == 0)
 		{
@@ -1717,53 +1624,16 @@ pevent_load (char *filename)
 			continue;
 		} else if (strcmp (buf, "event_text") == 0)
 		{
-			if (text)
-				free (text);
-
-#if 0
-			/* This allows updating of old strings. We don't use new defaults
-				if the user has customized the strings (.e.g a text theme).
-				Hash of the old default is enough to identify and replace it.
-				This only works in English. */
-
-			switch (g_str_hash (ofs))
-			{
-			case 0x526743a4:
-		/* %C08,02 Hostmask                  PRIV NOTI CHAN CTCP INVI UNIG %O */
-				text = strdup (te[XP_TE_IGNOREHEADER].def);
-				break;
-
-			case 0xe91bc9c2:
-		/* %C08,02                                                         %O */
-				text = strdup (te[XP_TE_IGNOREFOOTER].def);
-				break;
-
-			case 0x1fbfdf22:
-		/* -%C10-%C11-%O$tDCC RECV: Cannot open $1 for writing - aborting. */
-				text = strdup (te[XP_TE_DCCFILEERR].def);
-				break;
-
-			default:
-				text = strdup (ofs);
-			}
-#else
-			text = strdup (ofs);
-#endif
-
-			continue;
-		}/* else if (strcmp (buf, "event_sound") == 0)
-		{
-			if (snd)
-				free (snd);
-			snd = strdup (ofs);
+			g_free (text);
+			text = g_strdup (ofs);
 			continue;
-		}*/
+		}
 
 		continue;
 	}
 
 	pevent_trigger_load (&penum, &text, &snd);
-	free (ibuf);
+	g_free (ibuf);
 	return 0;
 }
 
@@ -1777,13 +1647,13 @@ pevent_check_all_loaded ()
 		if (pntevts_text[i] == NULL)
 		{
 			/*printf ("%s\n", te[i].name);
-			snprintf(out, sizeof(out), "The data for event %s failed to load. Reverting to defaults.\nThis may be because a new version of HexChat is loading an old config file.\n\nCheck all print event texts are correct", evtnames[i]);
+			g_snprintf(out, sizeof(out), "The data for event %s failed to load. Reverting to defaults.\nThis may be because a new version of HexChat is loading an old config file.\n\nCheck all print event texts are correct", evtnames[i]);
 			   gtkutil_simpledialog(out); */
 			/* make-te.c sets this 128 flag (DON'T call gettext() flag) */
 			if (te[i].num_args & 128)
-				pntevts_text[i] = strdup (te[i].def);
+				pntevts_text[i] = g_strdup (te[i].def);
 			else
-				pntevts_text[i] = strdup (_(te[i].def));
+				pntevts_text[i] = g_strdup (_(te[i].def));
 		}
 	}
 }
@@ -1808,9 +1678,10 @@ load_text_events ()
 #define ARG_FLAG(argn) (1 << (argn))
 
 void
-format_event (session *sess, int index, char **args, char *o, int sizeofo, unsigned int stripcolor_args)
+format_event (session *sess, int index, char **args, char *o, gsize sizeofo, unsigned int stripcolor_args)
 {
-	int len, oi, ii, numargs;
+	int len, ii, numargs;
+	gsize oi;
 	char *i, *ar, d, a, done_all = FALSE;
 
 	i = pntevts[index];
@@ -1868,19 +1739,10 @@ format_event (session *sess, int index, char **args, char *o, int sizeofo, unsig
 			done_all = TRUE;
 			continue;
 		case 3:
-/*			if (sess->type == SESS_DIALOG)
-			{
-				if (prefs.dialog_indent_nicks)
-					o[oi++] = '\t';
-				else
-					o[oi++] = ' ';
-			} else
-			{*/
-				if (prefs.hex_text_indent)
-					o[oi++] = '\t';
-				else
-					o[oi++] = ' ';
-			/*}*/
+			if (prefs.hex_text_indent)
+				o[oi++] = '\t';
+			else
+				o[oi++] = ' ';
 			break;
 		}
 	}
@@ -1908,7 +1770,7 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 	int oi, ii, max = -1, len, x;
 
 	len = strlen (input);
-	i = malloc (len + 1);
+	i = g_malloc (len + 1);
 	memcpy (i, input, len + 1);
 	check_special_chars (i, TRUE);
 
@@ -1933,14 +1795,14 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 		}
 		if (oi > 0)
 		{
-			s = (struct pevt_stage1 *) malloc (sizeof (struct pevt_stage1));
+			s = g_new (struct pevt_stage1, 1);
 			if (base == NULL)
 				base = s;
 			if (last != NULL)
 				last->next = s;
 			last = s;
 			s->next = NULL;
-			s->data = malloc (oi + sizeof (int) + 1);
+			s->data = g_malloc (oi + sizeof (int) + 1);
 			s->len = oi + sizeof (int) + 1;
 			clen += oi + sizeof (int) + 1;
 			s->data[0] = 0;
@@ -1951,12 +1813,12 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 		if (ii == len)
 		{
 			fe_message ("String ends with a $", FE_MSG_WARN);
-			return 1;
+			goto err;
 		}
 		d = i[ii++];
 		if (d == 'a')
-		{								  /* Hex value */
-			x = 0;
+		{
+			/* Hex value */
 			if (ii == len)
 				goto a_len_error;
 			d = i[ii++];
@@ -1977,24 +1839,24 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 			o[oi++] = x;
 			continue;
 
-		 a_len_error:
+		a_len_error:
 			fe_message ("String ends in $a", FE_MSG_WARN);
-			return 1;
-		 a_range_error:
+			goto err;
+		a_range_error:
 			fe_message ("$a value is greater than 255", FE_MSG_WARN);
-			return 1;
+			goto err;
 		}
 		if (d == 't')
 		{
 			/* Tab - if tabnicks is set then write '\t' else ' ' */
-			s = (struct pevt_stage1 *) malloc (sizeof (struct pevt_stage1));
+			s = g_new (struct pevt_stage1, 1);
 			if (base == NULL)
 				base = s;
 			if (last != NULL)
 				last->next = s;
 			last = s;
 			s->next = NULL;
-			s->data = malloc (1);
+			s->data = g_malloc (1);
 			s->len = 1;
 			clen += 1;
 			s->data[0] = 3;
@@ -2003,21 +1865,21 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 		}
 		if (d < '1' || d > '9')
 		{
-			snprintf (o, sizeof (o), "Error, invalid argument $%c\n", d);
+			g_snprintf (o, sizeof (o), "Error, invalid argument $%c\n", d);
 			fe_message (o, FE_MSG_WARN);
-			return 1;
+			goto err;
 		}
 		d -= '0';
 		if (max < d)
 			max = d;
-		s = (struct pevt_stage1 *) malloc (sizeof (struct pevt_stage1));
+		s = g_new (struct pevt_stage1, 1);
 		if (base == NULL)
 			base = s;
 		if (last != NULL)
 			last->next = s;
 		last = s;
 		s->next = NULL;
-		s->data = malloc (2);
+		s->data = g_malloc (2);
 		s->len = 2;
 		clen += 2;
 		s->data[0] = 1;
@@ -2025,14 +1887,14 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 	}
 	if (oi > 0)
 	{
-		s = (struct pevt_stage1 *) malloc (sizeof (struct pevt_stage1));
+		s = g_new (struct pevt_stage1, 1);
 		if (base == NULL)
 			base = s;
 		if (last != NULL)
 			last->next = s;
 		last = s;
 		s->next = NULL;
-		s->data = malloc (oi + sizeof (int) + 1);
+		s->data = g_malloc (oi + sizeof (int) + 1);
 		s->len = oi + sizeof (int) + 1;
 		clen += oi + sizeof (int) + 1;
 		s->data[0] = 0;
@@ -2040,39 +1902,54 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 		memcpy (&(s->data[1 + sizeof (int)]), o, oi);
 		oi = 0;
 	}
-	s = (struct pevt_stage1 *) malloc (sizeof (struct pevt_stage1));
+	s = g_new (struct pevt_stage1, 1);
 	if (base == NULL)
 		base = s;
 	if (last != NULL)
 		last->next = s;
-	last = s;
 	s->next = NULL;
-	s->data = malloc (1);
+	s->data = g_malloc (1);
 	s->len = 1;
 	clen += 1;
 	s->data[0] = 2;
 
 	oi = 0;
 	s = base;
-	obuf = malloc (clen);
+	obuf = g_malloc (clen);
+
 	while (s)
 	{
 		next = s->next;
 		memcpy (&obuf[oi], s->data, s->len);
 		oi += s->len;
-		free (s->data);
-		free (s);
+		g_free (s->data);
+		g_free (s);
 		s = next;
 	}
 
-	free (i);
+	g_free (i);
 
 	if (max_arg)
 		*max_arg = max;
 	if (output)
 		*output = obuf;
+	else
+		g_free (obuf);
 
 	return 0;
+
+err:
+	while (s)
+	{
+		next = s->next;
+		g_free (s->data);
+		g_free (s);
+		s = next;
+	}
+
+	g_free(i);
+
+	return 1;
 }
 
 
@@ -2107,7 +1984,7 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d,
 
 	if (prefs.hex_text_color_nicks && (index == XP_TE_CHANACTION || index == XP_TE_CHANMSG))
 	{
-		snprintf (tbuf, sizeof (tbuf), "\003%d%s", text_color_of (a), a);
+		g_snprintf (tbuf, sizeof (tbuf), "\003%d%s", text_color_of (a), a);
 		a = tbuf;
 		stripcolor_args &= ~ARG_FLAG(1);	/* don't strip color from this argument */
 	}
@@ -2239,9 +2116,9 @@ pevent_save (char *fn)
 
 	for (i = 0; i < NUM_XP; i++)
 	{
-		write (fd, buf, snprintf (buf, sizeof (buf),
+		write (fd, buf, g_snprintf (buf, sizeof (buf),
 										  "event_name=%s\n", te[i].name));
-		write (fd, buf, snprintf (buf, sizeof (buf),
+		write (fd, buf, g_snprintf (buf, sizeof (buf),
 										  "event_text=%s\n\n", pntevts_text[i]));
 	}
 
@@ -2257,7 +2134,7 @@ char *sound_files[NUM_XP];
 void
 sound_beep (session *sess)
 {
-	if (!prefs.hex_gui_focus_omitalerts || !fe_gui_info (sess, 0) == 1)
+	if (!prefs.hex_gui_focus_omitalerts || fe_gui_info (sess, 0) != 1)
 	{
 		if (sound_files[XP_TE_BEEP] && sound_files[XP_TE_BEEP][0])
 			/* user defined beep _file_ */
@@ -2283,12 +2160,8 @@ sound_play (const char *file, gboolean quiet)
 		return;
 	}
 
-#ifdef WIN32
 	/* check for fullpath */
-	if (file[0] == '\\' || (((file[0] >= 'A' && file[0] <= 'Z') || (file[0] >= 'a' && file[0] <= 'z')) && file[1] == ':'))
-#else
-	if (file[0] == '/')
-#endif
+	if (g_path_is_absolute (file))
 	{
 		wavfile = g_strdup (file);
 	}
@@ -2363,9 +2236,8 @@ sound_load_event (char *evt, char *file)
 
 	if (file[0] && pevent_find (evt, &i) != -1)
 	{
-		if (sound_files[i])
-			free (sound_files[i]);
-		sound_files[i] = strdup (file);
+		g_free (sound_files[i]);
+		sound_files[i] = g_strdup (file);
 	}
 }
 
@@ -2417,9 +2289,9 @@ sound_save ()
 	{
 		if (sound_files[i] && sound_files[i][0])
 		{
-			write (fd, buf, snprintf (buf, sizeof (buf),
+			write (fd, buf, g_snprintf (buf, sizeof (buf),
 											  "event=%s\n", te[i].name));
-			write (fd, buf, snprintf (buf, sizeof (buf),
+			write (fd, buf, g_snprintf (buf, sizeof (buf),
 											  "sound=%s\n\n", sound_files[i]));
 		}
 	}
diff --git a/src/common/text.h b/src/common/text.h
index 9a385167..28fc0c0d 100644
--- a/src/common/text.h
+++ b/src/common/text.h
@@ -57,11 +57,15 @@ void text_emit (int index, session *sess, char *a, char *b, char *c, char *d,
 		time_t timestamp);
 int text_emit_by_name (char *name, session *sess, time_t timestamp,
 					   char *a, char *b, char *c, char *d);
-char *text_validate (char **text, int *len);
+gchar *text_convert_invalid (const gchar* text, gssize len, GIConv converter, const gchar *fallback, gsize *len_out);
+gchar *text_fixup_invalid_utf8 (const gchar* text, gssize len, gsize *len_out);
 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);
+void format_event (session *sess, int index, char **args, char *o, gsize sizeofo, unsigned int stripcolor_args);
 char *text_find_format_string (char *name);
- 
+
+extern const gchar* unicode_fallback_string;
+extern const gchar* arbitrary_encoding_fallback_string;
+
 void sound_play (const char *file, gboolean quiet);
 void sound_play_event (int i);
 void sound_beep (session *);
diff --git a/src/common/tree.c b/src/common/tree.c
index 587d15f0..b9a894d2 100644
--- a/src/common/tree.c
+++ b/src/common/tree.c
@@ -42,7 +42,7 @@ struct _tree
 tree *
 tree_new (tree_cmp_func *cmp, void *data)
 {
-	tree *t = calloc (1, sizeof (tree));
+	tree *t = g_new0 (tree, 1);
 	t->cmp = cmp;
 	t->data = data;
 	return t;
@@ -53,9 +53,8 @@ tree_destroy (tree *t)
 {
 	if (t)
 	{
-		if (t->array)
-			free (t->array);
-		free (t);
+		g_free (t->array);
+		g_free (t);
 	}
 }
 
diff --git a/src/common/tree.h b/src/common/tree.h
index 848f5abf..8cde93ea 100644
--- a/src/common/tree.h
+++ b/src/common/tree.h
@@ -20,6 +20,8 @@
 #ifndef HEXCHAT_TREE_H
 #define HEXCHAT_TREE_H
 
+#include <glib.h>
+
 typedef struct _tree tree;
 
 typedef int (tree_cmp_func) (const void *keya, const void *keyb, void *data);
diff --git a/src/common/url.c b/src/common/url.c
index 1321374f..0354d98c 100644
--- a/src/common/url.c
+++ b/src/common/url.c
@@ -53,7 +53,7 @@ static gboolean match_path (const char *word, int *start, int *end);
 static int
 url_free (char *url, void *data)
 {
-	free (url);
+	g_free (url);
 	return TRUE;
 }
 
@@ -124,13 +124,7 @@ url_add (char *urltext, int len)
 		return;
 	}
 
-	data = malloc (len + 1);
-	if (!data)
-	{
-		return;
-	}
-	memcpy (data, urltext, len);
-	data[len] = 0;
+	data = g_strndup (urltext, len);
 
 	if (data[len - 1] == '.')	/* chop trailing dot */
 	{
@@ -151,7 +145,7 @@ url_add (char *urltext, int len)
 	/* the URL is saved already, only continue if we need the URL grabber too */
 	if (!prefs.hex_url_grabber)
 	{
-		free (data);
+		g_free (data);
 		return;
 	}
 
@@ -163,7 +157,7 @@ url_add (char *urltext, int len)
 
 	if (url_find (data))
 	{
-		free (data);
+		g_free (data);
 		return;
 	}
 
@@ -180,7 +174,7 @@ url_add (char *urltext, int len)
 
 			pos = tree_remove_at_pos (url_tree, 0);
 			g_tree_remove (url_btree, pos);
-			free (pos);
+			g_free (pos);
 		}
 	}
 
@@ -332,7 +326,7 @@ static char *commands[] = {
 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
 
 void
-url_check_line (char *buf, int len)
+url_check_line (char *buf)
 {
 	GRegex *re(void);
 	GMatchInfo *gmi;
@@ -415,7 +409,7 @@ regex_match (const GRegex *re, const char *word, int *start, int *end)
 }
 
 /*	Miscellaneous description --- */
-#define DOMAIN "[_\\pL\\pN][-_\\pL\\pN]*(\\.[-_\\pL\\pN]+)*"
+#define DOMAIN "[_\\pL\\pN\\pS][-_\\pL\\pN\\pS]*(\\.[-_\\pL\\pN\\pS]+)*"
 #define TLD "\\.[\\pL][-\\pL\\pN]*[\\pL]"
 #define IPADDR "[0-9]{1,3}(\\.[0-9]{1,3}){3}"
 #define IPV6GROUP "([0-9a-f]{0,4})"
@@ -429,7 +423,7 @@ regex_match (const GRegex *re, const char *word, int *start, int *end)
 #define OPT_PORT "(" PORT ")?"
 
 static GRegex *
-make_re (char *grist)
+make_re (const char *grist)
 {
 	GRegex *ret;
 	GError *err = NULL;
@@ -587,18 +581,14 @@ re_url (void)
 		
 		if (uri[i].flags & URI_PATH)
 		{
-			char *sep_escaped;
-			
-			sep_escaped = g_regex_escape_string (uri[i].path_sep, 
-							     strlen(uri[i].path_sep));
+			char *sep_escaped = g_regex_escape_string (uri[i].path_sep, strlen(uri[i].path_sep));
 
-			g_string_append_printf(grist_gstr, "(" "%s" PATH ")?",
-					       sep_escaped);
+			g_string_append_printf (grist_gstr, "(" "%s" PATH ")?", sep_escaped);
 
-			g_free(sep_escaped);
+			g_free (sep_escaped);
 		}
 
-		g_string_append(grist_gstr, ")");
+		g_string_append (grist_gstr, ")");
 	}
 
 	grist = g_string_free (grist_gstr, FALSE);
diff --git a/src/common/url.h b/src/common/url.h
index 676f9a6d..1b1deb3d 100644
--- a/src/common/url.h
+++ b/src/common/url.h
@@ -36,6 +36,6 @@ void url_clear (void);
 void url_save_tree (const char *fname, const char *mode, gboolean fullpath);
 int url_last (int *, int *);
 int url_check_word (const char *word);
-void url_check_line (char *buf, int len);
+void url_check_line (char *buf);
 
 #endif
diff --git a/src/common/userlist.c b/src/common/userlist.c
index e08cb857..54ed6f03 100644
--- a/src/common/userlist.c
+++ b/src/common/userlist.c
@@ -29,7 +29,7 @@
 #include "util.h"
 
 
-static int
+int
 nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2)
 {
 	unsigned int access1 = user1->access;
@@ -52,30 +52,12 @@ nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2)
 	return serv->p_cmp (user1->nick, user2->nick);
 }
 
-static int
+int
 nick_cmp_alpha (struct User *user1, struct User *user2, server *serv)
 {
 	return serv->p_cmp (user1->nick, user2->nick);
 }
 
-static int
-nick_cmp (struct User *user1, struct User *user2, server *serv)
-{
-	switch (prefs.hex_gui_ulist_sort)
-	{
-	case 0:
-		return nick_cmp_az_ops (serv, user1, user2);
-	case 1:
-		return serv->p_cmp (user1->nick, user2->nick);
-	case 2:
-		return -1 * nick_cmp_az_ops (serv, user1, user2);
-	case 3:
-		return -1 * serv->p_cmp (user1->nick, user2->nick);
-	default:
-		return -1;
-	}
-}
-
 /*
  insert name in appropriate place in linked list. Returns row number or:
   -1: duplicate
@@ -86,11 +68,9 @@ userlist_insertname (session *sess, struct User *newuser)
 {
 	if (!sess->usertree)
 	{
-		sess->usertree = tree_new ((tree_cmp_func *)nick_cmp, sess->server);
-		sess->usertree_alpha = tree_new ((tree_cmp_func *)nick_cmp_alpha, sess->server);
+		sess->usertree = tree_new ((tree_cmp_func *)nick_cmp_alpha, sess->server);
 	}
 
-	tree_insert (sess->usertree_alpha, newuser);
 	return tree_insert (sess->usertree, newuser);
 }
 
@@ -121,13 +101,12 @@ userlist_set_account (struct session *sess, char *nick, char *account)
 	user = userlist_find (sess, nick);
 	if (user)
 	{
-		if (user->account)
-			free (user->account);
+		g_free (user->account);
 			
 		if (strcmp (account, "*") == 0)
 			user->account = NULL;
 		else
-			user->account = strdup (account);
+			user->account = g_strdup (account);
 			
 		/* gui doesnt currently reflect login status, maybe later
 		fe_userlist_rehash (sess, user); */
@@ -148,14 +127,14 @@ userlist_add_hostname (struct session *sess, char *nick, char *hostname,
 		{
 			if (prefs.hex_gui_ulist_show_hosts)
 				do_rehash = TRUE;
-			user->hostname = strdup (hostname);
+			user->hostname = g_strdup (hostname);
 		}
 		if (!user->realname && realname && *realname)
-			user->realname = strdup (realname);
+			user->realname = g_strdup (realname);
 		if (!user->servername && servername)
-			user->servername = strdup (servername);
+			user->servername = g_strdup (servername);
 		if (!user->account && account && strcmp (account, "0") != 0)
-			user->account = strdup (account);
+			user->account = g_strdup (account);
 		if (away != 0xff)
 		{
 			if (user->away != away)
@@ -175,15 +154,11 @@ userlist_add_hostname (struct session *sess, char *nick, char *hostname,
 static int
 free_user (struct User *user, gpointer data)
 {
-	if (user->realname)
-		free (user->realname);
-	if (user->hostname)
-		free (user->hostname);
-	if (user->servername)
-		free (user->servername);
-	if (user->account)
-		free (user->account);
-	free (user);
+	g_free (user->realname);
+	g_free (user->hostname);
+	g_free (user->servername);
+	g_free (user->account);
+	g_free (user);
 
 	return TRUE;
 }
@@ -193,10 +168,8 @@ userlist_free (session *sess)
 {
 	tree_foreach (sess->usertree, (tree_traverse_func *)free_user, NULL);
 	tree_destroy (sess->usertree);
-	tree_destroy (sess->usertree_alpha);
 
 	sess->usertree = NULL;
-	sess->usertree_alpha = NULL;
 	sess->me = NULL;
 
 	sess->ops = 0;
@@ -224,8 +197,8 @@ userlist_find (struct session *sess, const char *name)
 {
 	int pos;
 
-	if (sess->usertree_alpha)
-		return tree_find (sess->usertree_alpha, name,
+	if (sess->usertree)
+		return tree_find (sess->usertree, name,
 								(tree_cmp_func *)find_cmp, sess->server, &pos);
 
 	return NULL;
@@ -248,7 +221,7 @@ userlist_find_global (struct server *serv, char *name)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 static void
@@ -288,7 +261,7 @@ userlist_update_mode (session *sess, char *name, char mode, char sign)
 
 	/* remove from binary trees, before we loose track of it */
 	tree_remove (sess->usertree, user, &pos);
-	tree_remove (sess->usertree_alpha, user, &pos);
+	fe_userlist_remove (sess, user);
 
 	/* which bit number is affected? */
 	access = mode_access (sess->server, mode, &prefix);
@@ -318,11 +291,8 @@ userlist_update_mode (session *sess, char *name, char mode, char sign)
 	update_counts (sess, user, prefix, level, offset);
 
 	/* insert it back into its new place */
-	tree_insert (sess->usertree_alpha, user);
-	pos = tree_insert (sess->usertree, user);
-
-	/* let GTK move it too */
-	fe_userlist_move (sess, user, pos);
+	tree_insert (sess->usertree, user);
+	fe_userlist_insert (sess, user, FALSE);
 	fe_userlist_numbers (sess);
 }
 
@@ -335,14 +305,12 @@ userlist_change (struct session *sess, char *oldname, char *newname)
 	if (user)
 	{
 		tree_remove (sess->usertree, user, &pos);
-		tree_remove (sess->usertree_alpha, user, &pos);
+		fe_userlist_remove (sess, user);
 
 		safe_strcpy (user->nick, newname, NICKLEN);
 
-		tree_insert (sess->usertree_alpha, user);
-
-		fe_userlist_move (sess, user, tree_insert (sess->usertree, user));
-		fe_userlist_numbers (sess);
+		tree_insert (sess->usertree, user);
+		fe_userlist_insert (sess, user, FALSE);
 
 		return 1;
 	}
@@ -381,7 +349,6 @@ userlist_remove_user (struct session *sess, struct User *user)
 		sess->me = NULL;
 
 	tree_remove (sess->usertree, user, &pos);
-	tree_remove (sess->usertree_alpha, user, &pos);
 	free_user (user, NULL);
 }
 
@@ -397,8 +364,7 @@ userlist_add (struct session *sess, char *name, char *hostname,
 
 	notify_set_online (sess->server, name + prefix_chars, tags_data);
 
-	user = malloc (sizeof (struct User));
-	memset (user, 0, sizeof (struct User));
+	user = g_new0 (struct User, 1);
 
 	user->access = acc;
 
@@ -408,7 +374,7 @@ userlist_add (struct session *sess, char *name, char *hostname,
 
 	/* add it to our linked list */
 	if (hostname)
-		user->hostname = strdup (hostname);
+		user->hostname = g_strdup (hostname);
 	safe_strcpy (user->nick, name + prefix_chars, NICKLEN);
 	/* is it me? */
 	if (!sess->server->p_cmp (user->nick, sess->server->nick))
@@ -417,9 +383,9 @@ userlist_add (struct session *sess, char *name, char *hostname,
 	if (sess->server->have_extjoin)
 	{
 		if (account && *account)
-			user->account = strdup (account);
+			user->account = g_strdup (account);
 		if (realname && *realname)
-			user->realname = strdup (realname);
+			user->realname = g_strdup (realname);
 	}
 
 	row = userlist_insertname (sess, user);
@@ -427,13 +393,10 @@ userlist_add (struct session *sess, char *name, char *hostname,
 	/* duplicate? some broken servers trigger this */
 	if (row == -1)
 	{
-		if (user->hostname)
-			free (user->hostname);
-		if (user->account)
-			free (user->account);
-		if (user->realname)
-			free (user->realname);
-		free (user);
+		g_free (user->hostname);
+		g_free (user->account);
+		g_free (user->realname);
+		g_free (user);
 		return;
 	}
 
@@ -451,7 +414,7 @@ userlist_add (struct session *sess, char *name, char *hostname,
 	if (user->me)
 		sess->me = user;
 
-	fe_userlist_insert (sess, user, row, FALSE);
+	fe_userlist_insert (sess, user, FALSE);
 	fe_userlist_numbers (sess);
 }
 
@@ -465,7 +428,7 @@ rehash_cb (struct User *user, session *sess)
 void
 userlist_rehash (session *sess)
 {
-	tree_foreach (sess->usertree_alpha, (tree_traverse_func *)rehash_cb, sess);
+	tree_foreach (sess->usertree, (tree_traverse_func *)rehash_cb, sess);
 }
 
 static int
@@ -480,7 +443,7 @@ userlist_flat_list (session *sess)
 {
 	GSList *list = NULL;
 
-	tree_foreach (sess->usertree_alpha, (tree_traverse_func *)flat_cb, &list);
+	tree_foreach (sess->usertree, (tree_traverse_func *)flat_cb, &list);
 	return g_slist_reverse (list);
 }
 
@@ -496,6 +459,6 @@ userlist_double_list(session *sess)
 {
 	GList *list = NULL;
 
-	tree_foreach (sess->usertree_alpha, (tree_traverse_func *)double_cb, &list);
+	tree_foreach (sess->usertree, (tree_traverse_func *)double_cb, &list);
 	return list;
 }
diff --git a/src/common/userlist.h b/src/common/userlist.h
index ebf95606..0c53dc71 100644
--- a/src/common/userlist.h
+++ b/src/common/userlist.h
@@ -61,5 +61,7 @@ void userlist_update_mode (session *sess, char *name, char mode, char sign);
 GSList *userlist_flat_list (session *sess);
 GList *userlist_double_list (session *sess);
 void userlist_rehash (session *sess);
+int nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2);
+int nick_cmp_alpha (struct User *user1, struct User *user2, server *serv);
 
 #endif
diff --git a/src/common/util.c b/src/common/util.c
index b5ee1af2..be3dcac2 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -31,7 +31,6 @@
 
 #ifdef WIN32
 #include <sys/timeb.h>
-#include <process.h>
 #include <io.h>
 #include <VersionHelpers.h>
 #else
@@ -41,7 +40,7 @@
 #include <sys/utsname.h>
 #endif
 
-#include "../../config.h"
+#include "config.h"
 #include <fcntl.h>
 #include <errno.h>
 #include "hexchat.h"
@@ -52,9 +51,6 @@
 #if defined (USING_FREEBSD) || defined (__APPLE__)
 #include <sys/sysctl.h>
 #endif
-#ifdef SOCKS
-#include <socks.h>
-#endif
 
 /* SASL mechanisms */
 #ifdef USE_OPENSSL
@@ -67,10 +63,6 @@
 #endif
 #endif
 
-#ifndef HAVE_SNPRINTF
-#define snprintf g_snprintf
-#endif
-
 char *
 file_part (char *file)
 {
@@ -254,11 +246,11 @@ expand_homedir (char *file)
 
 	if (file[0] == '~')
 	{
+		char *slash_pos;
+
 		if (file[1] == '\0' || file[1] == '/')
 			return g_strconcat (g_get_home_dir (), &file[1], NULL);
 
-		char *slash_pos;
-
 		user = g_strdup(file);
 
 		slash_pos = strchr(user, '/');
@@ -370,13 +362,13 @@ strip_hidden_attribute (char *src, char *dst)
 	return len;
 }
 
-#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__)
+#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__) || defined (__CYGWIN__)
 
 static void
 get_cpu_info (double *mhz, int *cpus)
 {
 
-#ifdef USING_LINUX
+#if defined(USING_LINUX) || defined (__CYGWIN__)
 
 	char buf[256];
 	int fh;
@@ -508,7 +500,22 @@ get_sys_str (int with_cpu)
 	static char winver[20];
 	double mhz;
 
-	if (IsWindows8Point1OrGreater ())
+	/* Broken since major bumped to 10, should start to work eventually.
+	 * No, IsWindowsVersionOrGreater (10, 0, 0) doesn't work either.
+	 * TODO: replace with IsWindows10OrGreater() once added to the SDK.
+	 */
+	if (IsWindowsVersionOrGreater (6, 4, 0))
+	{
+		if (IsWindowsServer ())
+		{
+			strcpy (winver, "Server 10");
+		}
+		else
+		{
+			strcpy (winver, "10");
+		}
+	}
+	else if (IsWindows8Point1OrGreater ())
 	{
 		if (IsWindowsServer ())
 		{
@@ -610,7 +617,7 @@ get_sys_str (int with_cpu)
 char *
 get_sys_str (int with_cpu)
 {
-#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__)
+#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__) || defined (__CYGWIN__)
 	double mhz;
 #endif
 	int cpus = 1;
@@ -620,24 +627,24 @@ get_sys_str (int with_cpu)
 	if (buf)
 		return buf;
 
-	buf = malloc (128);
-
 	uname (&un);
 
-#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__)
+#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__) || defined (__CYGWIN__)
 	get_cpu_info (&mhz, &cpus);
 	if (mhz && with_cpu)
 	{
 		double cpuspeed = ( mhz > 1000 ) ? mhz / 1000 : mhz;
 		const char *cpuspeedstr = ( mhz > 1000 ) ? "GHz" : "MHz";
-		snprintf (buf, 128,
-					(cpus == 1) ? "%s %s [%s/%.2f%s]" : "%s %s [%s/%.2f%s/SMP]",
-					un.sysname, un.release, un.machine,
-					cpuspeed, cpuspeedstr);
+		buf = g_strdup_printf (
+			(cpus == 1) ? "%s %s [%s/%.2f%s]" : "%s %s [%s/%.2f%s/SMP]",
+			un.sysname, un.release, un.machine,
+			cpuspeed, cpuspeedstr);
 	}
 	else
+		buf = g_strdup_printf ("%s %s", un.sysname, un.release);
+#else
+	buf = g_strdup_printf ("%s %s", un.sysname, un.release);
 #endif
-		snprintf (buf, 128, "%s %s", un.sysname, un.release);
 
 	return buf;
 }
@@ -1217,80 +1224,6 @@ const unsigned char rfc_tolowertab[] =
 	0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
 };
 
-/*static unsigned char touppertab[] =
-	{ 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
-	0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
-	0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
-	0x1e, 0x1f,
-	' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
-	'*', '+', ',', '-', '.', '/',
-	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-	':', ';', '<', '=', '>', '?',
-	'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
-	'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
-	'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
-	0x5f,
-	'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
-	'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
-	'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
-	0x7f,
-	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
-	0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-	0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
-	0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
-	0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
-	0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
-	0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
-	0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
-	0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
-};*/
-
-/*static int
-rename_utf8 (char *oldname, char *newname)
-{
-	int sav, res;
-	char *fso, *fsn;
-
-	fso = hexchat_filename_from_utf8 (oldname, -1, 0, 0, 0);
-	if (!fso)
-		return FALSE;
-	fsn = hexchat_filename_from_utf8 (newname, -1, 0, 0, 0);
-	if (!fsn)
-	{
-		g_free (fso);
-		return FALSE;
-	}
-
-	res = rename (fso, fsn);
-	sav = errno;
-	g_free (fso);
-	g_free (fsn);
-	errno = sav;
-	return res;
-}
-
-static int
-unlink_utf8 (char *fname)
-{
-	int res;
-	char *fs;
-
-	fs = hexchat_filename_from_utf8 (fname, -1, 0, 0, 0);
-	if (!fs)
-		return FALSE;
-
-	res = unlink (fs);
-	g_free (fs);
-	return res;
-}*/
-
 static gboolean
 file_exists (char *fname)
 {
@@ -1526,7 +1459,7 @@ canonalize_key (char *key)
 }
 
 int
-portable_mode ()
+portable_mode (void)
 {
 #ifdef WIN32
 	if ((_access( "portable-mode", 0 )) != -1)
@@ -1543,7 +1476,7 @@ portable_mode ()
 }
 
 int
-unity_mode ()
+unity_mode (void)
 {
 #ifdef G_OS_UNIX
 	const char *env = g_getenv("XDG_CURRENT_DESKTOP");
@@ -1578,7 +1511,7 @@ parse_dh (char *str, DH **dh_out, unsigned char **secret_out, int *keysize_out)
 {
 	DH *dh;
 	guchar *data, *decoded_data;
-	guchar *secret;
+	guchar *secret = NULL;
 	gsize data_len;
 	guint size;
 	guint16 size16;
@@ -1630,7 +1563,7 @@ parse_dh (char *str, DH **dh_out, unsigned char **secret_out, int *keysize_out)
 	if (!(DH_generate_key (dh)))
 		goto fail;
 
-	secret = (unsigned char*)malloc (DH_size(dh));
+	secret = g_malloc (DH_size (dh));
 	key_size = DH_compute_key (secret, pubkey, dh);
 	if (key_size == -1)
 		goto fail;
@@ -1643,8 +1576,9 @@ parse_dh (char *str, DH **dh_out, unsigned char **secret_out, int *keysize_out)
 	return 1;
 
 fail:
-	if (decoded_data)
-		g_free (decoded_data);
+	g_free (secret);
+	g_free (decoded_data);
+
 	return 0;
 }
 
@@ -1652,7 +1586,7 @@ char *
 encode_sasl_pass_blowfish (char *user, char *pass, char *data)
 {
 	DH *dh;
-	char *response, *ret;
+	char *response, *ret = NULL;
 	unsigned char *secret;
 	unsigned char *encrypted_pass;
 	char *plain_pass;
@@ -1667,11 +1601,9 @@ encode_sasl_pass_blowfish (char *user, char *pass, char *data)
 		return NULL;
 	BF_set_key (&key, key_size, secret);
 
-	encrypted_pass = (guchar*)malloc (pass_len);
-	memset (encrypted_pass, 0, pass_len);
-	plain_pass = (char*)malloc (pass_len);
-	memset (plain_pass, 0, pass_len);
-	memcpy (plain_pass, pass, pass_len);
+	encrypted_pass = g_malloc0 (pass_len);
+	plain_pass = g_malloc0 (pass_len);
+	memcpy (plain_pass, pass, strlen(pass));
 	out_ptr = (char*)encrypted_pass;
 	in_ptr = (char*)plain_pass;
 
@@ -1680,7 +1612,7 @@ encode_sasl_pass_blowfish (char *user, char *pass, char *data)
 
 	/* Create response */
 	length = 2 + BN_num_bytes (dh->pub_key) + pass_len + user_len + 1;
-	response = (char*)malloc (length);
+	response = g_malloc0 (length);
 	out_ptr = response;
 
 	/* our key */
@@ -1699,11 +1631,12 @@ encode_sasl_pass_blowfish (char *user, char *pass, char *data)
 	
 	ret = g_base64_encode ((const guchar*)response, length);
 
-	DH_free (dh);
-	free (plain_pass);
-	free (encrypted_pass);
-	free (secret);
-	free (response);
+	g_free (response);
+
+	DH_free(dh);
+	g_free (plain_pass);
+	g_free (encrypted_pass);
+	g_free (secret);
 
 	return ret;
 }
@@ -1729,10 +1662,8 @@ encode_sasl_pass_aes (char *user, char *pass, char *data)
 	if (!parse_dh (data, &dh, &secret, &key_size))
 		return NULL;
 
-	encrypted_userpass = (guchar*)malloc (userpass_len);
-	memset (encrypted_userpass, 0, userpass_len);
-	plain_userpass = (guchar*)malloc (userpass_len);
-	memset (plain_userpass, 0, userpass_len);
+	encrypted_userpass = g_malloc0 (userpass_len);
+	plain_userpass = g_malloc0 (userpass_len);
 
 	/* create message */
 	/* format of: <username>\0<password>\0<padding> */
@@ -1763,7 +1694,7 @@ encode_sasl_pass_aes (char *user, char *pass, char *data)
 	/* Create response */
 	/* format of:  <size pubkey><pubkey><iv (always 16 bytes)><ciphertext> */
 	length = 2 + key_size + sizeof(iv) + userpass_len;
-	response = (char*)malloc (length);
+	response = g_malloc (length);
 	out_ptr = response;
 
 	/* our key */
@@ -1784,11 +1715,10 @@ encode_sasl_pass_aes (char *user, char *pass, char *data)
 
 end:
 	DH_free (dh);
-	free (plain_userpass);
-	free (encrypted_userpass);
-	free (secret);
-	if (response)
-		free (response);
+	g_free (plain_userpass);
+	g_free (encrypted_userpass);
+	g_free (secret);
+	g_free (response);
 
 	return ret;
 }
@@ -1866,9 +1796,7 @@ challengeauth_response (char *username, char *password, char *challenge)
 		g_string_append_printf (buf, "%02x", (unsigned int) digest[i]);
 	}
 
-	digest = (unsigned char *) g_string_free (buf, FALSE);
-
-	return (char *) digest;
+	return g_string_free (buf, FALSE);
 }
 #endif
 
diff --git a/src/common/util.h b/src/common/util.h
index 5231e56d..2c9f790c 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -73,12 +73,12 @@ 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 unity_mode ();
+int portable_mode (void);
+int unity_mode (void);
 char *encode_sasl_pass_plain (char *user, char *pass);
 char *encode_sasl_pass_blowfish (char *user, char *pass, char *data);
 char *encode_sasl_pass_aes (char *user, char *pass, char *data);
 char *challengeauth_response (char *username, char *password, char *challenge);
 size_t strftime_validated (char *dest, size_t destsize, const char *format, const struct tm *time);
-size_t strftime_utf8 (char *dest, size_t destsize, const char *format, time_t time);
+gsize strftime_utf8 (char *dest, gsize destsize, const char *format, time_t time);
 #endif
diff --git a/src/dirent/dirent-win32.h b/src/dirent/dirent-win32.h
index cf3fe567..d1954c6b 100644
--- a/src/dirent/dirent-win32.h
+++ b/src/dirent/dirent-win32.h
@@ -198,13 +198,13 @@
  * only defined for compatibility.  These macros should always return false
  * on Windows.
  */
-#define	S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
-#define	S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
-#define	S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
-#define	S_ISLNK(mode)  (((mode) & S_IFMT) == S_IFLNK)
-#define	S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
-#define	S_ISCHR(mode)  (((mode) & S_IFMT) == S_IFCHR)
-#define	S_ISBLK(mode)  (((mode) & S_IFMT) == S_IFBLK)
+#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
+#define S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
+#define S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
+#define S_ISLNK(mode)  (((mode) & S_IFMT) == S_IFLNK)
+#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+#define S_ISCHR(mode)  (((mode) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(mode)  (((mode) & S_IFMT) == S_IFBLK)
 
 /* Return the exact length of d_namlen without zero terminator */
 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
@@ -305,6 +305,7 @@ _wopendir(
 {
     _WDIR *dirp = NULL;
     int error;
+    DWORD n;
 
     /* Must have directory name */
     if (dirname == NULL  ||  dirname[0] == '\0') {
@@ -313,73 +314,58 @@ _wopendir(
     }
 
     /* Allocate new _WDIR structure */
-    dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
-    if (dirp != NULL) {
-        DWORD n;
-
-        /* Reset _WDIR structure */
-        dirp->handle = INVALID_HANDLE_VALUE;
-        dirp->patt = NULL;
-        dirp->cached = 0;
-
-        /* Compute the length of full path plus zero terminator */
-        n = GetFullPathNameW (dirname, 0, NULL, NULL);
-
-        /* Allocate room for absolute directory name and search pattern */
-        dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
-        if (dirp->patt) {
-
-            /*
-             * Convert relative directory name to an absolute one.  This
-             * allows rewinddir() to function correctly even when current
-             * working directory is changed between opendir() and rewinddir().
-             */
-            n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
-            if (n > 0) {
-                wchar_t *p;
-
-                /* Append search pattern \* to the directory name */
-                p = dirp->patt + n;
-                if (dirp->patt < p) {
-                    switch (p[-1]) {
-                    case '\\':
-                    case '/':
-                    case ':':
-                        /* Directory ends in path separator, e.g. c:\temp\ */
-                        /*NOP*/;
-                        break;
-
-                    default:
-                        /* Directory name doesn't end in path separator */
-                        *p++ = '\\';
-                    }
-                }
-                *p++ = '*';
-                *p = '\0';
-
-                /* Open directory stream and retrieve the first entry */
-                if (dirent_first (dirp)) {
-                    /* Directory stream opened successfully */
-                    error = 0;
-                } else {
-                    /* Cannot retrieve first entry */
-                    error = 1;
-                    dirent_set_errno (ENOENT);
-                }
-
-            } else {
-                /* Cannot retrieve full path name */
-                dirent_set_errno (ENOENT);
-                error = 1;
+    dirp = (_WDIR*) g_new (struct _WDIR, 1);
+    /* Reset _WDIR structure */
+    dirp->handle = INVALID_HANDLE_VALUE;
+    dirp->patt = NULL;
+    dirp->cached = 0;
+
+    /* Compute the length of full path plus zero terminator */
+    n = GetFullPathNameW (dirname, 0, NULL, NULL);
+
+    /* Allocate room for absolute directory name and search pattern */
+    dirp->patt = g_malloc (sizeof (wchar_t) * n + 16);
+    /*
+    * Convert relative directory name to an absolute one.  This
+    * allows rewinddir() to function correctly even when current
+    * working directory is changed between opendir() and rewinddir().
+    */
+    n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
+    if (n > 0) {
+        wchar_t *p;
+
+        /* Append search pattern \* to the directory name */
+        p = dirp->patt + n;
+        if (dirp->patt < p) {
+            switch (p[-1]) {
+            case '\\':
+            case '/':
+            case ':':
+                /* Directory ends in path separator, e.g. c:\temp\ */
+                /*NOP*/;
+                break;
+
+            default:
+                /* Directory name doesn't end in path separator */
+                *p++ = '\\';
             }
+        }
+        *p++ = '*';
+        *p = '\0';
 
+        /* Open directory stream and retrieve the first entry */
+        if (dirent_first (dirp)) {
+            /* Directory stream opened successfully */
+            error = 0;
         } else {
-            /* Cannot allocate memory for search pattern */
+            /* Cannot retrieve first entry */
             error = 1;
+            dirent_set_errno (ENOENT);
         }
 
     } else {
-        /* Cannot allocate _WDIR structure */
+        /* Cannot retrieve full path name */
+        dirent_set_errno (ENOENT);
         error = 1;
     }
 
@@ -472,13 +458,11 @@ _wclosedir(
         }
 
         /* Release search pattern */
-        if (dirp->patt) {
-            free (dirp->patt);
-            dirp->patt = NULL;
-        }
+        g_free (dirp->patt);
+        dirp->patt = NULL;
 
         /* Release directory structure */
-        free (dirp);
+        g_free (dirp);
         ok = /*success*/0;
 
     } else {
@@ -579,6 +563,8 @@ opendir(
 {
     struct DIR *dirp;
     int error;
+    wchar_t wname[PATH_MAX + 1];
+    size_t n;
 
     /* Must have directory name */
     if (dirname == NULL  ||  dirname[0] == '\0') {
@@ -587,44 +573,36 @@ opendir(
     }
 
     /* Allocate memory for DIR structure */
-    dirp = (DIR*) malloc (sizeof (struct DIR));
-    if (dirp) {
-        wchar_t wname[PATH_MAX + 1];
-        size_t n;
-
-        /* Convert directory name to wide-character string */
-        error = dirent_mbstowcs_s(
-            &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
-        if (!error) {
-
-            /* Open directory stream using wide-character name */
-            dirp->wdirp = _wopendir (wname);
-            if (dirp->wdirp) {
-                /* Directory stream opened */
-                error = 0;
-            } else {
-                /* Failed to open directory stream */
-                error = 1;
-            }
-
+    dirp = (DIR*) g_new (struct DIR, 1);
+
+    /* Convert directory name to wide-character string */
+    error = dirent_mbstowcs_s(
+        &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
+    if (!error) {
+
+        /* Open directory stream using wide-character name */
+        dirp->wdirp = _wopendir (wname);
+        if (dirp->wdirp) {
+            /* Directory stream opened */
+            error = 0;
         } else {
-            /* 
-             * Cannot convert file name to wide-character string.  This
-             * occurs if the string contains invalid multi-byte sequences or
-             * the output buffer is too small to contain the resulting
-             * string.
-             */
+            /* Failed to open directory stream */
             error = 1;
         }
 
     } else {
-        /* Cannot allocate DIR structure */
+        /* 
+            * Cannot convert file name to wide-character string.  This
+            * occurs if the string contains invalid multi-byte sequences or
+            * the output buffer is too small to contain the resulting
+            * string.
+            */
         error = 1;
     }
 
     /* Clean up in case of error */
-    if (error  &&  dirp) {
-        free (dirp);
+    if (error != 0) {
+        g_free (dirp);
         dirp = NULL;
     }
 
@@ -733,14 +711,14 @@ closedir(
     DIR *dirp) 
 {
     int ok;
-    if (dirp) {
+    if (dirp != NULL) {
 
         /* Close wide-character directory stream */
         ok = _wclosedir (dirp->wdirp);
         dirp->wdirp = NULL;
 
         /* Release multi-byte character version */
-        free (dirp);
+        g_free (dirp);
 
     } else {
 
diff --git a/src/fe-gtk/Makefile.am b/src/fe-gtk/Makefile.am
index a8f43ac5..71179853 100644
--- a/src/fe-gtk/Makefile.am
+++ b/src/fe-gtk/Makefile.am
@@ -1,3 +1,6 @@
+
+include $(top_srcdir)/m4/clang-analyze.am
+
 localedir = $(datadir)/locale
 
 bin_PROGRAMS = hexchat
@@ -9,7 +12,7 @@ hexchat_LDADD = ../common/libhexchatcommon.a $(GUI_LIBS)
 EXTRA_DIST = \
 	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 notifygui.h palette.h pixmaps.h \
+	maingui.h menu.h notifygui.h  notifications palette.h pixmaps.h plugin-notification.h \
 	plugin-tray.h plugingui.c plugingui.h rawlog.h sexy-iso-codes.h \
 	sexy-spell-entry.h textgui.h urlgrab.h userlistgui.h xtext.h \
 	../../data/hexchat.gresource.xml
@@ -26,12 +29,29 @@ if HAVE_ISO_CODES
 iso_codes_c = sexy-iso-codes.c
 endif
 
+if USE_LIBNOTIFY
+notify_c = notifications/notification-libnotify.c
+else
+if HAVE_GTK_MAC
+notify_c = notifications/notification-osx.m
+hexchat_LDFLAGS = -framework Foundation
+else
+notify_c = notifications/notification-dummy.c
+endif
+endif
+
 hexchat_SOURCES = 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 notifygui.c palette.c pixmaps.c plugin-tray.c $(plugingui_c) \
-	rawlog.c resources.c servlistgui.c setup.c $(iso_codes_c) \
+	maingui.c notifygui.c $(notify_c) palette.c pixmaps.c plugin-tray.c $(plugingui_c) \
+	plugin-notification.c rawlog.c resources.c servlistgui.c setup.c $(iso_codes_c) \
 	sexy-spell-entry.c textgui.c urlgrab.c userlistgui.c xtext.c
 hexchat_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/common
 
 resources.c: $(top_srcdir)/data/hexchat.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(top_srcdir)/data --generate-dependencies $(top_srcdir)/data/hexchat.gresource.xml)
 	$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(top_srcdir)/data --generate-source $<
+
+if DO_STATIC_ANALYSIS
+analyze_plists = $(hexchat_SOURCES:%.c=%.plist)
+all-local: $(analyze_plists)
+MOSTLYCLEANFILES = $(analyze_plists)
+endif
diff --git a/src/fe-gtk/banlist.c b/src/fe-gtk/banlist.c
index d6f44811..e10aaa67 100644
--- a/src/fe-gtk/banlist.c
+++ b/src/fe-gtk/banlist.c
@@ -491,7 +491,7 @@ banlist_unban_inner (gpointer none, banlist_info *banl, int mode_num)
 	if (!gtk_tree_model_get_iter_first (model, &iter))
 		return 0;
 
-	masks = g_malloc (sizeof (char *) * banl->line_ct);
+	masks = g_new (char *, banl->line_ct);
 	num_sel = 0;
 	do
 	{
@@ -577,17 +577,17 @@ static void
 banlist_add_selected_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
 {
 	GSList **lp = data;
-	GSList *list = NULL;
 	GtkTreeIter *copy;
 
-	if (!lp) return;
-	list = *lp;
-	copy = g_malloc (sizeof (GtkTreeIter));
-	g_return_if_fail (copy != NULL);
+	if (lp == NULL)
+	{
+		return;
+	}
+
+	copy = g_new (GtkTreeIter, 1);
 	*copy = *iter;
 
-	list = g_slist_append (list, copy);
-	*(GSList **)data = list;
+	*lp = g_slist_append (*lp, copy);
 }
 
 static void
@@ -786,14 +786,9 @@ banlist_opengui (struct session *sess)
 		return;
 	}
 
-	if (!sess->res->banlist)
+	if (sess->res->banlist == NULL)
 	{
-		sess->res->banlist = g_malloc0 (sizeof (banlist_info));
-		if (!sess->res->banlist)
-		{
-			fe_message (_("Banlist initialization failed."), FE_MSG_ERROR);
-			return;
-		}
+		sess->res->banlist = g_new0 (banlist_info, 1);
 	}
 	banl = sess->res->banlist;
 	if (banl->window)
diff --git a/src/fe-gtk/chanlist.c b/src/fe-gtk/chanlist.c
index f3a2259d..f6ef46f3 100644
--- a/src/fe-gtk/chanlist.c
+++ b/src/fe-gtk/chanlist.c
@@ -94,7 +94,7 @@ chanlist_update_caption (server *serv)
 {
 	gchar tbuf[256];
 
-	snprintf (tbuf, sizeof tbuf,
+	g_snprintf (tbuf, sizeof tbuf,
 				 _("Displaying %d/%d users on %d/%d channels."),
 				 serv->gui->chanlist_users_shown_count,
 				 serv->gui->chanlist_users_found_count,
@@ -148,7 +148,7 @@ chanlist_data_free (server *serv)
 			data = rows->data;
 			g_free (data->topic);
 			g_free (data->collation_key);
-			free (data);
+			g_free (data);
 		}
 
 		g_slist_free (serv->gui->chanlist_data_stored_rows);
@@ -370,7 +370,7 @@ fe_add_chan_list (server *serv, char *chan, char *users, char *topic)
 	int len = strlen (chan) + 1;
 
 	/* we allocate the struct and channel string in one go */
-	next_row = malloc (sizeof (chanlistrow) + len);
+	next_row = g_malloc (sizeof (chanlistrow) + len);
 	memcpy (((char *)next_row) + sizeof (chanlistrow), chan, len);
 	next_row->topic = strip_color (topic, -1, STRIP_ALL);
 	next_row->collation_key = g_utf8_collate_key (chan, len-1);
@@ -456,7 +456,7 @@ chanlist_join (GtkWidget * wid, server *serv)
 	{
 		if (serv->connected && (strcmp (chan, "*") != 0))
 		{
-			snprintf (tbuf, sizeof (tbuf), "join %s", chan);
+			g_snprintf (tbuf, sizeof (tbuf), "join %s", chan);
 			handle_command (serv->server_session, tbuf, FALSE);
 		} else
 			gdk_beep ();
@@ -482,7 +482,7 @@ chanlist_filereq_done (server *serv, char *file)
 	if (fh == -1)
 		return;
 
-	snprintf (buf, sizeof buf, "HexChat Channel List: %s - %s\n",
+	g_snprintf (buf, sizeof buf, "HexChat Channel List: %s - %s\n",
 				 serv->servername, ctime (&t));
 	write (fh, buf, strlen (buf));
 
@@ -494,7 +494,7 @@ chanlist_filereq_done (server *serv, char *file)
 									  COL_CHANNEL, &chan,
 									  COL_USERS, &users,
 									  COL_TOPIC, &topic, -1);
-			snprintf (buf, sizeof buf, "%-16s %-5d%s\n", chan, users, topic);
+			g_snprintf (buf, sizeof buf, "%-16s %-5d%s\n", chan, users, topic);
 			g_free (chan);
 			g_free (topic);
 			write (fh, buf, strlen (buf));
@@ -717,7 +717,7 @@ chanlist_opengui (server *serv, int do_refresh)
 		return;
 	}
 
-	snprintf (tbuf, sizeof tbuf, _(DISPLAY_NAME": Channel List (%s)"),
+	g_snprintf (tbuf, sizeof tbuf, _(DISPLAY_NAME": Channel List (%s)"),
 				 server_get_network (serv, TRUE));
 
 	serv->gui->chanlist_pending_rows = NULL;
diff --git a/src/fe-gtk/chanview-tabs.c b/src/fe-gtk/chanview-tabs.c
index 8f940c24..5681f9d6 100644
--- a/src/fe-gtk/chanview-tabs.c
+++ b/src/fe-gtk/chanview-tabs.c
@@ -62,12 +62,13 @@ cv_tabs_sizerequest (GtkWidget *viewport, GtkRequisition *requisition, chanview
 static void
 cv_tabs_sizealloc (GtkWidget *widget, GtkAllocation *allocation, chanview *cv)
 {
+	GdkWindow *parent_win;
 	GtkAdjustment *adj;
 	GtkWidget *inner;
 	gint viewport_size;
 
 	inner = ((tabview *)cv)->inner;
-	GdkWindow *parent_win = gtk_widget_get_window (gtk_widget_get_parent (inner));
+	parent_win = gtk_widget_get_window (gtk_widget_get_parent (inner));
 
 	if (cv->vertical)
 	{
@@ -141,7 +142,7 @@ tab_scroll_left_up_clicked (GtkWidget *widget, chanview *cv)
 	gfloat new_value;
 	GtkWidget *inner;
 	GdkWindow *parent_win;
-	gfloat i;
+	gdouble i;
 
 	inner = ((tabview *)cv)->inner;
 	parent_win = gtk_widget_get_window (gtk_widget_get_parent (inner));
@@ -190,7 +191,7 @@ tab_scroll_right_down_clicked (GtkWidget *widget, chanview *cv)
 	gfloat new_value;
 	GtkWidget *inner;
 	GdkWindow *parent_win;
-	gfloat i;
+	gdouble i;
 
 	inner = ((tabview *)cv)->inner;
 	parent_win = gtk_widget_get_window (gtk_widget_get_parent (inner));
diff --git a/src/fe-gtk/chanview.c b/src/fe-gtk/chanview.c
index 4c50d922..e5556d9f 100644
--- a/src/fe-gtk/chanview.c
+++ b/src/fe-gtk/chanview.c
@@ -111,9 +111,8 @@ truncate_tab_name (char *name, int max)
 	if (max > 2 && g_utf8_strlen (name, -1) > max)
 	{
 		/* truncate long channel names */
-		buf = malloc (strlen (name) + 4);
-		strcpy (buf, name);
-		g_utf8_offset_to_pointer (buf, max)[0] = 0;
+		buf = g_malloc (strlen (name) + 4);
+		g_utf8_strncpy (buf, name, max);
 		strcat (buf, "..");
 		return buf;
 	}
@@ -231,7 +230,7 @@ chanview_free_ch (chanview *cv, GtkTreeIter *iter)
 	chan *ch;
 
 	gtk_tree_model_get (GTK_TREE_MODEL (cv->store), iter, COL_CHAN, &ch, -1);
-	free (ch);
+	g_free (ch);
 }
 
 static void
@@ -251,7 +250,7 @@ chanview_destroy (chanview *cv)
 		gtk_widget_destroy (cv->box);
 
 	chanview_destroy_store (cv);
-	free (cv);
+	g_free (cv);
 }
 
 static void
@@ -267,7 +266,7 @@ chanview_new (int type, int trunc_len, gboolean sort, gboolean use_icons,
 {
 	chanview *cv;
 
-	cv = calloc (1, sizeof (chanview));
+	cv = g_new0 (chanview, 1);
 	cv->store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER,
 											  PANGO_TYPE_ATTR_LIST, GDK_TYPE_PIXBUF);
 	cv->style = style;
@@ -368,7 +367,7 @@ chanview_add_real (chanview *cv, char *name, void *family, void *userdata,
 
 	if (!ch)
 	{
-		ch = calloc (1, sizeof (chan));
+		ch = g_new0 (chan, 1);
 		ch->userdata = userdata;
 		ch->family = family;
 		ch->cv = cv;
@@ -401,7 +400,7 @@ chanview_add (chanview *cv, char *name, void *family, void *userdata, gboolean a
 	ret = chanview_add_real (cv, new_name, family, userdata, allow_closure, tag, icon, NULL, NULL);
 
 	if (new_name != name)
-		free (new_name);
+		g_free (new_name);
 
 	return ret;
 }
@@ -492,7 +491,7 @@ chan_rename (chan *ch, char *name, int trunc_len)
 	ch->cv->trunc_len = trunc_len;
 
 	if (new_name != name)
-		free (new_name);
+		g_free (new_name);
 }
 
 /* this thing is overly complicated */
@@ -645,7 +644,7 @@ chan_remove (chan *ch, gboolean force)
 
 	ch->cv->size--;
 	gtk_tree_store_remove (ch->cv->store, &ch->iter);
-	free (ch);
+	g_free (ch);
 	return TRUE;
 }
 
diff --git a/src/fe-gtk/custom-list.c b/src/fe-gtk/custom-list.c
index a954b4a0..f1241947 100644
--- a/src/fe-gtk/custom-list.c
+++ b/src/fe-gtk/custom-list.c
@@ -134,7 +134,6 @@ custom_list_get_type (void)
 		return custom_list_type;
 
 	/* Some boilerplate type registration stuff */
-	if (1)
 	{
 		static const GTypeInfo custom_list_info = {
 			sizeof (CustomListClass),
@@ -154,7 +153,6 @@ custom_list_get_type (void)
 	}
 
 	/* Here we register our GtkTreeModel interface with the type system */
-	if (1)
 	{
 		static const GInterfaceInfo tree_model_info = {
 			(GInterfaceInitFunc) custom_list_tree_model_init,
@@ -167,7 +165,6 @@ custom_list_get_type (void)
 	}
 
 	/* Add GtkTreeSortable interface */
-	if (1)
 	{
 		static const GInterfaceInfo tree_sortable_info = {
 			(GInterfaceInitFunc) custom_list_sortable_init,
@@ -336,7 +333,7 @@ custom_list_get_iter (GtkTreeModel * tree_model,
 	gint n;
 
 	n = gtk_tree_path_get_indices (path)[0];
-	if (n >= custom_list->num_rows || n < 0)
+	if (n < 0 || (guint) n >= custom_list->num_rows)
 		return FALSE;
 
 	record = custom_list->rows[n];
@@ -533,7 +530,7 @@ custom_list_iter_nth_child (GtkTreeModel * tree_model,
 		return FALSE;
 
 	/* special case: if parent == NULL, set iter to n-th top-level row */
-	if (n >= custom_list->num_rows)
+	if (n < 0 || (guint) n >= custom_list->num_rows)
 		return FALSE;
 
 	iter->user_data = custom_list->rows[n];
@@ -730,7 +727,7 @@ custom_list_resort (CustomList * custom_list)
 							 custom_list);
 
 	/* let other objects know about the new order */
-	neworder = malloc (sizeof (gint) * custom_list->num_rows);
+	neworder = g_new (gint, custom_list->num_rows);
 
 	for (i = custom_list->num_rows - 1; i >= 0; i--)
 	{
@@ -747,7 +744,7 @@ custom_list_resort (CustomList * custom_list)
 	gtk_tree_model_rows_reordered (GTK_TREE_MODEL (custom_list), path, NULL,
 											 neworder);
 	gtk_tree_path_free (path);
-	free (neworder);
+	g_free (neworder);
 }
 
 void
diff --git a/src/fe-gtk/custom-list.h b/src/fe-gtk/custom-list.h
index 64f0535f..30a73919 100644
--- a/src/fe-gtk/custom-list.h
+++ b/src/fe-gtk/custom-list.h
@@ -77,10 +77,10 @@ struct _CustomList
 {
 	GObject parent;
 
-	guint num_rows;				  /* number of rows that we have used */
-	guint num_alloc;					/* number of rows allocated */
-	chanlistrow **rows;			  /* a dynamically allocated array of pointers to the
-										   *  CustomRecord structure for each row */
+	guint num_rows;     /* number of rows that we have used */
+	guint num_alloc;    /* number of rows allocated */
+	chanlistrow **rows; /* a dynamically allocated array of pointers to the
+	                     * CustomRecord structure for each row */
 
 	gint n_columns;
 	GType column_types[CUSTOM_LIST_N_COLUMNS];
diff --git a/src/fe-gtk/dccgui.c b/src/fe-gtk/dccgui.c
index 10ec8388..8c9dc8b4 100644
--- a/src/fe-gtk/dccgui.c
+++ b/src/fe-gtk/dccgui.c
@@ -88,7 +88,7 @@ struct my_dcc_send
 {
 	struct session *sess;
 	char *nick;
-	int maxcps;
+	gint64 maxcps;
 	int passive;
 };
 
@@ -105,7 +105,7 @@ static short view_mode;	/* 1=download 2=upload 3=both */
 
 
 static void
-proper_unit (DCC_SIZE size, char *buf, int buf_len)
+proper_unit (guint64 size, char *buf, size_t buf_len)
 {
 	gchar *formatted_str;
 	GFormatSizeFlags format_flags = G_FORMAT_SIZE_DEFAULT;
@@ -117,7 +117,7 @@ proper_unit (DCC_SIZE size, char *buf, int buf_len)
 		format_flags = G_FORMAT_SIZE_IEC_UNITS;
 #endif
 
-	formatted_str = g_format_size_full ((guint64)size, format_flags);
+	formatted_str = g_format_size_full (size, format_flags);
 	g_strlcpy (buf, formatted_str, buf_len);
 
 	g_free (formatted_str);
@@ -130,45 +130,45 @@ dcc_send_filereq_file (struct my_dcc_send *mdc, char *file)
 		dcc_send (mdc->sess, mdc->nick, file, mdc->maxcps, mdc->passive);
 	else
 	{
-		free (mdc->nick);
-		free (mdc);
+		g_free (mdc->nick);
+		g_free (mdc);
 	}
 }
 
 void
 fe_dcc_send_filereq (struct session *sess, char *nick, int maxcps, int passive)
 {
-	char tbuf[128];
-	struct my_dcc_send *mdc;
-	
-	mdc = malloc (sizeof (*mdc));
+	char* tbuf = g_strdup_printf (_("Send file to %s"), nick);
+
+	struct my_dcc_send *mdc = g_new (struct my_dcc_send, 1);
 	mdc->sess = sess;
-	mdc->nick = strdup (nick);
+	mdc->nick = g_strdup (nick);
 	mdc->maxcps = maxcps;
 	mdc->passive = passive;
 
-	snprintf (tbuf, sizeof tbuf, _("Send file to %s"), nick);
 	gtkutil_file_req (tbuf, dcc_send_filereq_file, mdc, prefs.hex_dcc_dir, NULL, FRF_MULTIPLE|FRF_FILTERISINITIAL);
+
+	g_free (tbuf);
 }
 
 static void
 dcc_prepare_row_chat (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
 							 gboolean update_only)
 {
-	static char pos[16], siz[16];
+	static char pos[16], size[16];
 	char *date;
 
 	date = ctime (&dcc->starttime);
 	date[strlen (date) - 1] = 0;	/* remove the \n */
 
 	proper_unit (dcc->pos, pos, sizeof (pos));
-	proper_unit (dcc->size, siz, sizeof (siz));
+	proper_unit (dcc->size, size, sizeof (size));
 
 	gtk_list_store_set (store, iter,
 							  CCOL_STATUS, _(dccstat[dcc->dccstat].name),
 							  CCOL_NICK, dcc->nick,
 							  CCOL_RECV, pos,
-							  CCOL_SENT, siz,
+							  CCOL_SENT, size,
 							  CCOL_START, date,
 							  CCOL_DCC, dcc,
 							  CCOL_COLOR,
@@ -194,13 +194,12 @@ dcc_prepare_row_send (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
 	per = (float) ((dcc->ack * 100.00) / dcc->size);
 	proper_unit (dcc->size, size, sizeof (size));
 	proper_unit (dcc->pos, pos, sizeof (pos));
-	snprintf (kbs, sizeof (kbs), "%.1f", ((float)dcc->cps) / 1024);
-/*	proper_unit (dcc->ack, ack, sizeof (ack));*/
-	snprintf (perc, sizeof (perc), "%.0f%%", per);
+	g_snprintf (kbs, sizeof (kbs), "%.1f", ((float)dcc->cps) / 1024);
+	g_snprintf (perc, sizeof (perc), "%.0f%%", per);
 	if (dcc->cps != 0)
 	{
 		to_go = (dcc->size - dcc->ack) / dcc->cps;
-		snprintf (eta, sizeof (eta), "%.2d:%.2d:%.2d",
+		g_snprintf (eta, sizeof (eta), "%.2d:%.2d:%.2d",
 					 to_go / 3600, (to_go / 60) % 60, to_go % 60);
 	} else
 		strcpy (eta, "--:--:--");
@@ -253,14 +252,14 @@ dcc_prepare_row_recv (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
 		proper_unit (dcc->resumable, pos, sizeof (pos));
 	else
 		proper_unit (dcc->pos, pos, sizeof (pos));
-	snprintf (kbs, sizeof (kbs), "%.1f", ((float)dcc->cps) / 1024);
+	g_snprintf (kbs, sizeof (kbs), "%.1f", ((float)dcc->cps) / 1024);
 	/* percentage recv'ed */
 	per = (float) ((dcc->pos * 100.00) / dcc->size);
-	snprintf (perc, sizeof (perc), "%.0f%%", per);
+	g_snprintf (perc, sizeof (perc), "%.0f%%", per);
 	if (dcc->cps != 0)
 	{
 		to_go = (dcc->size - dcc->pos) / dcc->cps;
-		snprintf (eta, sizeof (eta), "%.2d:%.2d:%.2d",
+		g_snprintf (eta, sizeof (eta), "%.2d:%.2d:%.2d",
 					 to_go / 3600, (to_go / 60) % 60, to_go % 60);
 	} else
 		strcpy (eta, "--:--:--");
@@ -526,7 +525,7 @@ resume_clicked (GtkWidget * wid, gpointer none)
 			fe_message (_("That file is not resumable."), FE_MSG_ERROR);
 			break;
 		case 1:
-			snprintf (buf, sizeof (buf),
+			g_snprintf (buf, sizeof (buf),
 						_(	"Cannot access file: %s\n"
 							"%s.\n"
 							"Resuming not possible."), dcc->destfile,	
@@ -607,7 +606,7 @@ browse_folder (char *dir)
 #else
 	char buf[512];
 
-	snprintf (buf, sizeof (buf), "file://%s", dir);
+	g_snprintf (buf, sizeof (buf), "file://%s", dir);
 	fe_open_url (buf);
 #endif
 }
@@ -640,7 +639,7 @@ dcc_details_populate (struct DCC *dcc)
 		gtk_label_set_text (GTK_LABEL (dccfwin.file_label), dcc->file);
 
 	/* address and port */
-	snprintf (buf, sizeof (buf), "%s : %d", net_ip (dcc->addr), dcc->port);
+	g_snprintf (buf, sizeof (buf), "%s : %d", net_ip (dcc->addr), dcc->port);
 	gtk_label_set_text (GTK_LABEL (dccfwin.address_label), buf);
 }
 
@@ -738,7 +737,7 @@ dcc_detail_label (char *text, GtkWidget *box, int num)
 	char buf[64];
 
 	label = gtk_label_new (NULL);
-	snprintf (buf, sizeof (buf), "<b>%s</b>", text);
+	g_snprintf (buf, sizeof (buf), "<b>%s</b>", text);
 	gtk_label_set_markup (GTK_LABEL (label), buf);
 	gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
 	gtk_table_attach (GTK_TABLE (box), label, 0, 1, 0 + num, 1 + num, GTK_FILL, GTK_FILL, 0, 0);
diff --git a/src/fe-gtk/editlist.c b/src/fe-gtk/editlist.c
index f7e22d52..4b236dc1 100644
--- a/src/fe-gtk/editlist.c
+++ b/src/fe-gtk/editlist.c
@@ -283,6 +283,7 @@ editlist_treeview_new (GtkWidget *box, char *title1, char *title2)
 	view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
 	gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (view), TRUE);
 	gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE);
+	gtk_tree_view_set_reorderable (GTK_TREE_VIEW (view), TRUE);
 	
 	g_signal_connect (G_OBJECT (view), "key_press_event",
 						G_CALLBACK (editlist_keypress), NULL);
@@ -313,7 +314,6 @@ editlist_treeview_new (GtkWidget *box, char *title1, char *title2)
 	gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
 	gtk_tree_view_column_set_resizable (col, TRUE);
 	gtk_tree_view_column_set_min_width (col, 100);
-	col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), CMD_COLUMN);
 
 	gtk_container_add (GTK_CONTAINER (scroll), view);
 	gtk_container_add (GTK_CONTAINER (box), scroll);
diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c
index 4b7d916f..8c163eb7 100644
--- a/src/fe-gtk/fe-gtk.c
+++ b/src/fe-gtk/fe-gtk.c
@@ -52,6 +52,7 @@
 #include "plugin-tray.h"
 #include "urlgrab.h"
 #include "setup.h"
+#include "plugin-notification.h"
 
 #ifdef USE_LIBCANBERRA
 #include <canberra.h>
@@ -224,7 +225,7 @@ fe_args (int argc, char *argv[])
 	/* cuts can. So we have to set the current dir manually, to the path  */
 	/* of the exe. */
 	{
-		char *tmp = strdup (argv[0]);
+		char *tmp = g_strdup (argv[0]);
 		char *sl;
 
 		sl = strrchr (tmp, G_DIR_SEPARATOR);
@@ -233,7 +234,7 @@ fe_args (int argc, char *argv[])
 			*sl = 0;
 			chdir (tmp);
 		}
-		free (tmp);
+		g_free (tmp);
 	}
 #endif
 
@@ -265,7 +266,7 @@ create_input_style (GtkStyle *style)
 	/* fall back */
 	if (pango_font_description_get_size (style->font_desc) == 0)
 	{
-		snprintf (buf, sizeof (buf), _("Failed to open font:\n\n%s"), prefs.hex_text_font);
+		g_snprintf (buf, sizeof (buf), _("Failed to open font:\n\n%s"), prefs.hex_text_font);
 		fe_message (buf, FE_MSG_ERROR);
 		pango_font_description_free (style->font_desc);
 		style->font_desc = pango_font_description_from_string ("sans 11");
@@ -381,6 +382,8 @@ fe_idle (gpointer data)
 {
 	session *sess = sess_list->data;
 
+	plugin_add (sess, NULL, NULL, notification_plugin_init, notification_plugin_deinit, NULL, FALSE);
+
 	plugin_add (sess, NULL, NULL, tray_plugin_init, tray_plugin_deinit, NULL, FALSE);
 
 	if (arg_minimize == 1)
@@ -424,8 +427,7 @@ fe_new_window (session *sess, int focus)
 void
 fe_new_server (struct server *serv)
 {
-	serv->gui = malloc (sizeof (struct server_gui));
-	memset (serv->gui, 0, sizeof (struct server_gui));
+	serv->gui = g_new0 (struct server_gui, 1);
 }
 
 void
@@ -510,18 +512,15 @@ fe_set_topic (session *sess, char *topic, char *stripped_topic)
 	}
 	else
 	{
-		if (sess->res->topic_text)
-		{
-			free (sess->res->topic_text);
-		}
+		g_free (sess->res->topic_text);
 
 		if (prefs.hex_text_stripcolor_topic)
 		{
-			sess->res->topic_text = strdup (stripped_topic);
+			sess->res->topic_text = g_strdup (stripped_topic);
 		}
 		else
 		{
-			sess->res->topic_text = strdup (topic);
+			sess->res->topic_text = g_strdup (topic);
 		}
 	}
 }
@@ -547,9 +546,8 @@ fe_update_mode_entry (session *sess, GtkWidget *entry, char **text, char *new_te
 	{
 		if (sess->gui->is_tab)
 		{
-			if (*text)
-				free (*text);
-			*text = strdup (new_text);
+			g_free (*text);
+			*text = g_strdup (new_text);
 		}
 	}
 }
@@ -721,7 +719,7 @@ fe_lastlog (session *sess, session *lastlog_sess, char *sstr, gtk_xtext_search_f
 		lbuf->search_lnee = strlen (lbuf->search_nee);
 	}
 	lbuf->search_flags = flags;
-	lbuf->search_text = strdup (sstr);
+	lbuf->search_text = g_strdup (sstr);
 	gtk_xtext_lastlog (lbuf, buf);
 }
 
@@ -751,9 +749,9 @@ fe_set_lag (server *serv, long lag)
 	if (per > 1.0)
 		per = 1.0;
 
-	snprintf (lagtext, sizeof (lagtext) - 1, "%s%ld.%lds",
+	g_snprintf (lagtext, sizeof (lagtext) - 1, "%s%ld.%lds",
 			  serv->lag_sent ? "+" : "", lag / 1000, (lag/100) % 10);
-	snprintf (lagtip, sizeof (lagtip) - 1, "Lag: %s%ld.%ld seconds",
+	g_snprintf (lagtip, sizeof (lagtip) - 1, "Lag: %s%ld.%ld seconds",
 				 serv->lag_sent ? "+" : "", lag / 1000, (lag/100) % 10);
 
 	while (list)
@@ -761,9 +759,8 @@ fe_set_lag (server *serv, long lag)
 		sess = list->data;
 		if (sess->server == serv)
 		{
-			if (sess->res->lag_tip)
-				free (sess->res->lag_tip);
-			sess->res->lag_tip = strdup (lagtip);
+			g_free (sess->res->lag_tip);
+			sess->res->lag_tip = g_strdup (lagtip);
 
 			if (!sess->gui->is_tab || current_tab == sess)
 			{
@@ -777,9 +774,8 @@ fe_set_lag (server *serv, long lag)
 			} else
 			{
 				sess->res->lag_value = per;
-				if (sess->res->lag_text)
-					free (sess->res->lag_text);
-				sess->res->lag_text = strdup (lagtext);
+				g_free (sess->res->lag_text);
+				sess->res->lag_text = g_strdup (lagtext);
 			}
 		}
 		list = list->next;
@@ -804,12 +800,11 @@ fe_set_throttle (server *serv)
 		sess = list->data;
 		if (sess->server == serv)
 		{
-			snprintf (tbuf, sizeof (tbuf) - 1, _("%d bytes"), serv->sendq_len);
-			snprintf (tip, sizeof (tip) - 1, _("Network send queue: %d bytes"), serv->sendq_len);
+			g_snprintf (tbuf, sizeof (tbuf) - 1, _("%d bytes"), serv->sendq_len);
+			g_snprintf (tip, sizeof (tip) - 1, _("Network send queue: %d bytes"), serv->sendq_len);
 
-			if (sess->res->queue_tip)
-				free (sess->res->queue_tip);
-			sess->res->queue_tip = strdup (tip);
+			g_free (sess->res->queue_tip);
+			sess->res->queue_tip = g_strdup (tip);
 
 			if (!sess->gui->is_tab || current_tab == sess)
 			{
@@ -823,9 +818,8 @@ fe_set_throttle (server *serv)
 			} else
 			{
 				sess->res->queue_value = per;
-				if (sess->res->queue_text)
-					free (sess->res->queue_text);
-				sess->res->queue_text = strdup (tbuf);
+				g_free (sess->res->queue_text);
+				sess->res->queue_text = g_strdup (tbuf);
 			}
 		}
 		list = list->next;
@@ -882,11 +876,10 @@ fe_confirm (const char *message, void (*yesproc)(void *), void (*noproc)(void *)
 {
 	/* warning, assuming fe_confirm is used by DCC only! */
 	struct DCC *dcc = ud;
-	char *filepath;
 
 	if (dcc->file)
 	{
-		filepath = g_build_filename (prefs.hex_dcc_dir, dcc->file, NULL);
+		char *filepath = g_build_filename (prefs.hex_dcc_dir, dcc->file, NULL);
 		gtkutil_file_req (message, dcc_saveas_cb, ud, filepath, NULL,
 								FRF_WRITE|FRF_NOASKOVERWRITE|FRF_FILTERISINITIAL);
 		g_free (filepath);
@@ -978,9 +971,8 @@ fe_set_inputbox_contents (session *sess, char *text)
 		SPELL_ENTRY_SET_TEXT (sess->gui->input_box, text);
 	} else
 	{
-		if (sess->res->input_text)
-			free (sess->res->input_text);
-		sess->res->input_text = strdup (text);
+		g_free (sess->res->input_text);
+		sess->res->input_text = g_strdup (text);
 	}
 }
 
@@ -1092,9 +1084,9 @@ fe_open_url (const char *url)
 	/* the http:// part's missing, prepend it, otherwise it won't always work */
 	else if (strchr (url, ':') == NULL)
 	{
-		url = g_strdup_printf ("http://%s", url);
-		fe_open_url_inner (url);
-		g_free ((char *)url);
+		uri = g_strdup_printf ("http://%s", url);
+		fe_open_url_inner (uri);
+		g_free (uri);
 	}
 	/* we have a sane URL, send it to the browser untouched */
 	else
diff --git a/src/fe-gtk/fe-gtk.h b/src/fe-gtk/fe-gtk.h
index 17d1ab4d..ab776f63 100644
--- a/src/fe-gtk/fe-gtk.h
+++ b/src/fe-gtk/fe-gtk.h
@@ -20,7 +20,7 @@
 #ifndef HEXCHAT_FE_GTK_H
 #define HEXCHAT_FE_GTK_H
 
-#include "../../config.h"
+#include "config.h"
 
 #define DISPLAY_NAME "HexChat"
 
@@ -39,14 +39,13 @@
 
 #define flag_c flag_wid[0]
 #define flag_n flag_wid[1]
-#define flag_r flag_wid[2]
-#define flag_t flag_wid[3]
-#define flag_i flag_wid[4]
-#define flag_m flag_wid[5]
-#define flag_l flag_wid[6]
-#define flag_k flag_wid[7]
-#define flag_b flag_wid[8]
-#define NUM_FLAG_WIDS 9
+#define flag_t flag_wid[2]
+#define flag_i flag_wid[3]
+#define flag_m flag_wid[4]
+#define flag_l flag_wid[5]
+#define flag_k flag_wid[6]
+#define flag_b flag_wid[7]
+#define NUM_FLAG_WIDS 8
 
 #ifdef HAVE_GTK_MAC
 extern GtkosxApplication *osx_app;
@@ -92,9 +91,9 @@ struct server_gui
 	guint chanlist_channels_shown_count;	/* total number of displayed 
 														   channels */
 
-	int chanlist_maxusers;
-	int chanlist_minusers;
-	int chanlist_minusers_downloaded;	/* used by LIST IRC command */
+	guint32 chanlist_maxusers;
+	guint32 chanlist_minusers;
+	guint32 chanlist_minusers_downloaded;	/* used by LIST IRC command */
 	int chanlist_search_type;		/* 0=simple 1=pattern/wildcard 2=regexp */
 	gboolean chanlist_caption_is_stale;
 };
@@ -108,7 +107,7 @@ typedef struct restore_gui
 	void *tab;			/* (chan *) */
 
 	/* information stored when this tab isn't front-most */
-	void *user_model;	/* for filling the GtkTreeView */
+	GtkListStore *user_model;	/* for filling the GtkTreeView */
 	void *buffer;		/* xtext_Buffer */
 	char *input_text;	/* input text buffer (while not-front tab) */
 	char *topic_text;	/* topic GtkEntry buffer */
diff --git a/src/fe-gtk/fe-gtk.vcxproj b/src/fe-gtk/fe-gtk.vcxproj
index 59ab17c6..401518b4 100644
--- a/src/fe-gtk/fe-gtk.vcxproj
+++ b/src/fe-gtk/fe-gtk.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>Application</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,79 +20,38 @@
     <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>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hexchat</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hexchat</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <!-- WholeProgramOptimization must be turned off for gresource constructors to work, otherwise the .CRT$XCU section is not emitted. -->

+      <WholeProgramOptimization>false</WholeProgramOptimization>

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

-      <AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

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

       <DisableSpecificWarnings>4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

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

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

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

+      <AdditionalDependencies>$(DepLibs);$(HexChatLib)common.lib;%(AdditionalDependencies)</AdditionalDependencies>

       <EntryPointSymbol>mainCRTStartup</EntryPointSymbol>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <!-- WholeProgramOptimization must be turned off for gresource constructors to work, otherwise the .CRT$XCU section is not emitted. -->

+      <WholeProgramOptimization>false</WholeProgramOptimization>

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

-      <AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

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

       <DisableSpecificWarnings>4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

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

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

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

+      <AdditionalDependencies>$(DepLibs);$(HexChatLib)common.lib;%(AdditionalDependencies)</AdditionalDependencies>

       <EntryPointSymbol>mainCRTStartup</EntryPointSymbol>

     </Link>

   </ItemDefinitionGroup>

@@ -99,10 +59,10 @@
     <PreBuildEvent>

       <Command><![CDATA[

 SET SOLUTIONDIR=$(SolutionDir)..\

-powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\src\fe-gtk\hexchat.rc.tt" "$(SolutionDir)..\src\fe-gtk\hexchat.rc.utf8"

+powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\src\fe-gtk\hexchat.rc.tt" "$(HexChatLib)hexchat.rc.utf8"

 REM hexchat.rc needs to be in UCS-2 or Resource Compiler will complain

-powershell "Get-Content -Encoding UTF8 '$(SolutionDir)..\src\fe-gtk\hexchat.rc.utf8' | Out-File '$(SolutionDir)..\src\fe-gtk\hexchat.rc'; Remove-Item '$(SolutionDir)..\src\fe-gtk\hexchat.rc.utf8'"

-"$(DepsRoot)\bin\glib-compile-resources.exe" --generate-source --sourcedir "$(DataDir)" --target "$(ProjectDir)resources.c" "$(DataDir)hexchat.gresource.xml"

+powershell "Get-Content -Encoding UTF8 '$(HexChatLib)hexchat.rc.utf8' | Out-File '$(HexChatLib)hexchat.rc'; Remove-Item '$(HexChatLib)hexchat.rc.utf8'"

+"$(DepsRoot)\bin\glib-compile-resources.exe" --generate-source --sourcedir "$(DataDir)" --target "$(HexChatLib)resources.c" "$(DataDir)hexchat.gresource.xml"

       ]]></Command>

       <Message>Build hexchat.rc and gresource file</Message>

     </PreBuildEvent>

@@ -120,6 +80,7 @@ powershell "Get-Content -Encoding UTF8 '$(SolutionDir)..\src\fe-gtk\hexchat.rc.u
     <ClInclude Include="joind.h" />

     <ClInclude Include="maingui.h" />

     <ClInclude Include="menu.h" />

+    <ClInclude Include="notifications\notification-backend.h" />

     <ClInclude Include="notifygui.h" />

     <ClInclude Include="palette.h" />

     <ClInclude Include="pixmaps.h" />

@@ -150,13 +111,15 @@ powershell "Get-Content -Encoding UTF8 '$(SolutionDir)..\src\fe-gtk\hexchat.rc.u
     <ClCompile Include="joind.c" />

     <ClCompile Include="maingui.c" />

     <ClCompile Include="menu.c" />

+    <ClCompile Include="notifications\notification-windows.c" />

     <ClCompile Include="notifygui.c" />

     <ClCompile Include="palette.c" />

     <ClCompile Include="pixmaps.c" />

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

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

     <ClCompile Include="plugingui.c" />

     <ClCompile Include="rawlog.c" />

-    <ClCompile Include="resources.c" />

+    <ClCompile Include="$(HexChatLib)resources.c" />

     <ClCompile Include="servlistgui.c" />

     <ClCompile Include="setup.c" />

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

@@ -167,11 +130,11 @@ powershell "Get-Content -Encoding UTF8 '$(SolutionDir)..\src\fe-gtk\hexchat.rc.u
     <ClCompile Include="xtext.c" />

   </ItemGroup>

   <ItemGroup>

-    <Manifest Include="hexchat.exe.manifest" />

+    <Manifest Include="..\..\win32\hexchat.exe.manifest" />

   </ItemGroup>

   <ItemGroup>

     <None Include="hexchat.rc.tt" />

-    <ResourceCompile Include="hexchat.rc" />

+    <ResourceCompile Include="$(HexChatLib)hexchat.rc" />

   </ItemGroup>

   <ItemGroup>

     <None Include="..\..\data\icons\hexchat.ico" />

@@ -180,6 +143,4 @@ powershell "Get-Content -Encoding UTF8 '$(SolutionDir)..\src\fe-gtk\hexchat.rc.u
     <Xml Include="..\..\data\hexchat.gresource.xml" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/src/fe-gtk/fe-gtk.vcxproj.filters b/src/fe-gtk/fe-gtk.vcxproj.filters
index 4598b1f2..fe211a2d 100644
--- a/src/fe-gtk/fe-gtk.vcxproj.filters
+++ b/src/fe-gtk/fe-gtk.vcxproj.filters
@@ -93,6 +93,9 @@
     <ClInclude Include="setup.h">

       <Filter>Header Files</Filter>

     </ClInclude>

+    <ClInclude Include="notifications\notification-backend.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

   </ItemGroup>

   <ItemGroup>

     <ClCompile Include="ascii.c">

@@ -179,17 +182,23 @@
     <ClCompile Include="xtext.c">

       <Filter>Source Files</Filter>

     </ClCompile>

-    <ClCompile Include="resources.c">

+    <ClCompile Include="$(HexChatLib)resources.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

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

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="notifications\notification-windows.c">

       <Filter>Source Files</Filter>

     </ClCompile>

   </ItemGroup>

   <ItemGroup>

-    <Manifest Include="hexchat.exe.manifest">

+    <Manifest Include="..\..\win32\hexchat.exe.manifest">

       <Filter>Resource Files</Filter>

     </Manifest>

   </ItemGroup>

   <ItemGroup>

-    <ResourceCompile Include="hexchat.rc">

+    <ResourceCompile Include="$(HexChatLib)hexchat.rc">

       <Filter>Resource Files</Filter>

     </ResourceCompile>

   </ItemGroup>

diff --git a/src/fe-gtk/fkeys.c b/src/fe-gtk/fkeys.c
index 59086a5e..e762d208 100644
--- a/src/fe-gtk/fkeys.c
+++ b/src/fe-gtk/fkeys.c
@@ -198,6 +198,7 @@ static const struct key_action key_actions[KEY_MAX_ACTIONS + 1] = {
 	"ACCEL=Down\nNext Command\nD1!\nD2!\n\n"\
 	"ACCEL=Up\nLast Command\nD1!\nD2!\n\n"\
 	"ACCEL=Tab\nComplete nick/command\nD1!\nD2!\n\n"\
+	"ACCEL=<Shift>ISO_Left_Tab\nComplete nick/command\nD1:Previous\nD2!\n\n"\
 	"ACCEL=space\nCheck For Replace\nD1!\nD2!\n\n"\
 	"ACCEL=Return\nCheck For Replace\nD1!\nD2!\n\n"\
 	"ACCEL=KP_Enter\nCheck For Replace\nD1!\nD2!\n\n"\
@@ -241,10 +242,8 @@ key_free (gpointer data)
 
 	g_return_if_fail (kb != NULL);
 
-	if (kb->data1)
-		g_free (kb->data1);
-	if (kb->data2)
-		g_free (kb->data2);
+	g_free (kb->data1);
+	g_free (kb->data2);
 	g_free (kb);
 }
 
@@ -323,7 +322,7 @@ key_handle_key_press (GtkWidget *wid, GdkEventKey *evt, session *sess)
 		return FALSE;
 	current_sess = sess;
 
-	if (plugin_emit_keypress (sess, evt->state, evt->keyval, evt->length, evt->string))
+	if (plugin_emit_keypress (sess, evt->state, evt->keyval, gdk_keyval_to_unicode (evt->keyval)))
 		return 1;
 
 	/* maybe the plugin closed this tab? */
@@ -567,7 +566,7 @@ key_dialog_save (GtkWidget *wid, gpointer userdata)
 	{
 		do
 		{
-			kb = (struct key_binding *) g_malloc0 (sizeof (struct key_binding));
+			kb = g_new0 (struct key_binding, 1);
 
 			gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, ACCEL_COLUMN, &accel,
 															ACTION_COLUMN, &actiontext,
@@ -598,7 +597,8 @@ key_dialog_save (GtkWidget *wid, gpointer userdata)
 			else
 				keybind_list = g_slist_append (keybind_list, kb);
 
-		} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
+		}
+		while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
 	}
 
 	if (key_save_kbs () == 0)
@@ -666,6 +666,7 @@ key_dialog_treeview_new (GtkWidget *box)
 	view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
 	gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (view), TRUE);
 	gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE);
+	gtk_tree_view_set_reorderable (GTK_TREE_VIEW (view), TRUE);
 
 	g_signal_connect (G_OBJECT (view), "key-press-event",
 					G_CALLBACK (key_dialog_keypress), NULL);
@@ -850,7 +851,7 @@ key_save_kbs (void)
 									 0x180, XOF_DOMODE);
 	if (fd < 0)
 		return 1;
-	write (fd, buf, snprintf (buf, 510, "# HexChat key bindings config file\n\n"));
+	write (fd, buf, g_snprintf (buf, 510, "# HexChat key bindings config file\n\n"));
 
 	while (list)
 	{
@@ -858,17 +859,17 @@ key_save_kbs (void)
 
 		accel_text = gtk_accelerator_name (kb->keyval, kb->mod);
 
-		snprintf (buf, 510, "ACCEL=%s\n%s\n", accel_text, key_actions[kb->action].name);
+		g_snprintf (buf, 510, "ACCEL=%s\n%s\n", accel_text, key_actions[kb->action].name);
 		write (fd, buf, strlen (buf));
 		g_free (accel_text);
 
 		if (kb->data1 && kb->data1[0])
-			write (fd, buf, snprintf (buf, 510, "D1:%s\n", kb->data1));
+			write (fd, buf, g_snprintf (buf, 510, "D1:%s\n", kb->data1));
 		else
 			write (fd, "D1!\n", 4);
 
 		if (kb->data2 && kb->data2[0])
-			write (fd, buf, snprintf (buf, 510, "D2:%s\n", kb->data2));
+			write (fd, buf, g_snprintf (buf, 510, "D2:%s\n", kb->data2));
 		else
 			write (fd, "D2!\n", 4);
 
@@ -946,7 +947,7 @@ key_load_kbs (void)
 	fd = hexchat_open_file ("keybindings.conf", O_RDONLY, 0, 0);
 	if (fd < 0)
 	{
-		ibuf = strdup (default_kb_cfg);
+		ibuf = g_strdup (default_kb_cfg);
 		size = strlen (default_kb_cfg);
 	}
 	else
@@ -957,7 +958,7 @@ key_load_kbs (void)
 			return 1;
 		}
 
-		ibuf = malloc (st.st_size);
+		ibuf = g_malloc(st.st_size);
 		read (fd, ibuf, st.st_size);
 		size = st.st_size;
 		close (fd);
@@ -979,7 +980,7 @@ key_load_kbs (void)
 		switch (state)
 		{
 		case KBSTATE_MOD:
-			kb = (struct key_binding *) g_malloc0 (sizeof (struct key_binding));
+			kb = g_new0 (struct key_binding, 1);
 
 			/* New format */
 			if (strncmp (buf, "ACCEL=", 6) == 0)
@@ -1010,7 +1011,7 @@ key_load_kbs (void)
 			keyval = gdk_keyval_from_name (buf);
 			if (keyval == 0)
 			{
-				free (ibuf);
+				g_free (ibuf);
 				return 2;
 			}
 
@@ -1026,7 +1027,7 @@ key_load_kbs (void)
 
 			if (kb->action == KEY_MAX_ACTIONS + 1)
 			{
-				free (ibuf);
+				g_free (ibuf);
 				return 3;
 			}
 
@@ -1043,7 +1044,7 @@ key_load_kbs (void)
 
 			if (buf[0] != 'D')
 			{
-				free (ibuf);
+				g_free (ibuf);
 				return 4;
 			}
 
@@ -1069,12 +1070,10 @@ key_load_kbs (void)
 				len -= 3;
 				if (state == KBSTATE_DT1)
 				{
-					kb->data1 = g_malloc (len);
-					memcpy (kb->data1, &buf[3], len);
+					kb->data1 = g_strndup (&buf[3], len);
 				} else
 				{
-					kb->data2 = g_malloc (len);
-					memcpy (kb->data2, &buf[3], len);
+					kb->data2 = g_strndup (&buf[3], len);
 				}
 			} else if (buf[2] == '!')
 			{
@@ -1097,12 +1096,12 @@ key_load_kbs (void)
 			continue;
 		}
 	}
-	free (ibuf);
+	g_free (ibuf);
 	return 0;
 
 corrupt_file:
-	free (ibuf);
-	free (kb);
+	g_free (ibuf);
+	g_free (kb);
 	return 5;
 }
 
@@ -1410,9 +1409,6 @@ key_action_tab_clean(void)
 	}
 }
 
-/* Used in the followig completers */
-#define COMP_BUF 2048
-
 /* For use in sorting the user list for completion */
 static int
 talked_recent_cmp (struct User *a, struct User *b)
@@ -1426,16 +1422,31 @@ talked_recent_cmp (struct User *a, struct User *b)
 	return 0;
 }
 
+#define COMP_BUF 2048
+
+static inline glong
+len_to_offset (const char *str, glong len)
+{
+	return g_utf8_pointer_to_offset (str, str + len);
+}
+
+static inline glong
+offset_to_len (const char *str, glong offset)
+{
+	return g_utf8_offset_to_pointer (str, offset) - str;
+}
+
 static int
 key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 							struct session *sess)
 {
-	int len = 0, elen = 0, i = 0, cursor_pos, ent_start = 0, comp = 0, found = 0,
-	    prefix_len, skip_len = 0, is_nick, is_cmd = 0;
-	char buf[COMP_BUF], ent[CHANLEN], *postfix = NULL, *result, *ch;
+	int len = 0, elen = 0, i = 0, cursor_pos, ent_start = 0, comp = 0, prefix_len, skip_len = 0;
+	gboolean is_nick = FALSE, is_cmd = FALSE, found = FALSE, has_nick_prefix = FALSE;
+	char ent[CHANLEN], *postfix = NULL, *result, *ch;
 	GList *list = NULL, *tmp_list = NULL;
 	const char *text;
 	GCompletion *gcomp = NULL;
+	GString *buf;
 
 	/* force the IM Context to reset */
 	SPELL_ENTRY_SET_EDITABLE (t, FALSE);
@@ -1449,8 +1460,6 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 
 	cursor_pos = SPELL_ENTRY_GET_POS (t);
 
-	buf[0] = 0; /* make sure we don't get garbage in the buffer */
-
 	/* handle "nick: " or "nick " or "#channel "*/
 	ch = g_utf8_find_prev_char(text, g_utf8_offset_to_pointer(text,cursor_pos));
 	if (ch && ch[0] == ' ')
@@ -1489,15 +1498,23 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 	if (ent_start == 0 && text[0] == prefs.hex_input_command_char[0])
 	{
 		ent_start++;
-		is_cmd = 1;
+		is_cmd = TRUE;
 	}
-	
+	else if (strchr (sess->server->chantypes, text[ent_start]) == NULL)
+	{
+		is_nick = TRUE;
+		if (strchr (sess->server->nick_prefixes, text[ent_start]) != NULL)
+		{
+			if (ent_start == 0)
+				has_nick_prefix = TRUE;
+			ent_start++;
+		}
+	}
+
 	prefix_len = ent_start;
 	elen = cursor_pos - ent_start;
 
 	g_utf8_strncpy (ent, g_utf8_offset_to_pointer (text, prefix_len), elen);
-
-	is_nick = (ent[0] == '#' || ent[0] == '&' || is_cmd) ? 0 : 1;
 	
 	if (sess->type == SESS_DIALOG && is_nick)
 	{
@@ -1505,7 +1522,7 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 		if (rfc_ncasecmp (sess->channel, ent, elen) == 0)
 		{
 			result =  sess->channel;
-			is_nick = 0;
+			is_nick = FALSE;
 		}
 		else
 			return 2;
@@ -1562,7 +1579,7 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 			{
 				if(rfc_ncasecmp(list->data, ent, elen) == 0)
 				{
-					found = 1;
+					found = TRUE;
 					break;
 				}
 				list = list->next;
@@ -1600,7 +1617,7 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 			old_gcomp.elen = elen;
 
 			/* Get the first nick and put out the data for future nickcompletes */
-			if (prefs.hex_completion_amount && g_list_length (list) <= prefs.hex_completion_amount)
+			if (prefs.hex_completion_amount > 0 && g_list_length (list) <= (guint) prefs.hex_completion_amount)
 			{
 				g_free(result);
 				result = (char*)list->data;
@@ -1610,40 +1627,42 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 				/* bash style completion */
 				if (g_list_next(list) != NULL)
 				{
+					buf = g_string_sized_new (MAX(COMP_BUF, len + NICKLEN));
 					if (strlen (result) > elen) /* the largest common prefix is larger than nick, change the data */
 					{
 						if (prefix_len)
-							g_utf8_strncpy (buf, text, prefix_len);
-						strncat (buf, result, COMP_BUF - prefix_len);
-						cursor_pos = strlen (buf);
+							g_string_append_len (buf, text, offset_to_len (text, prefix_len));
+						g_string_append (buf, result);
+						cursor_pos = buf->len;
 						g_free(result);
 						if (postfix)
 						{
-							strcat (buf, " ");
-							strncat (buf, postfix, COMP_BUF - cursor_pos -1);
+							g_string_append_c (buf, ' ');
+							g_string_append (buf, postfix);
 						}
-						SPELL_ENTRY_SET_TEXT (t, buf);
-						SPELL_ENTRY_SET_POS (t, g_utf8_pointer_to_offset(buf, buf + cursor_pos));
-						buf[0] = 0;
+						SPELL_ENTRY_SET_TEXT (t, buf->str);
+						SPELL_ENTRY_SET_POS (t, len_to_offset (buf->str, cursor_pos));
+						g_string_erase (buf, 0, -1);
 					}
 					else
 						g_free(result);
+
 					while (list)
 					{
-						len = strlen (buf);	/* current buffer */
+						len = buf->len;
 						elen = strlen (list->data);	/* next item to add */
 						if (len + elen + 2 >= COMP_BUF) /* +2 is space + null */
 						{
-							PrintText (sess, buf);
-							buf[0] = 0;
-							len = 0;
+							PrintText (sess, buf->str);
+							g_string_erase (buf, 0, -1);
 						}
-						strcpy (buf + len, (char *) list->data);
-						strcpy (buf + len + elen, " ");
+						g_string_append (buf, (char*)list->data);
+						g_string_append_c (buf, ' ');
 						list = list->next;
 					}
-					PrintText (sess, buf);
+					PrintText (sess, buf->str);
 					g_completion_free(gcomp);
+					g_string_free (buf, TRUE);
 					return 2;
 				}
 				/* Only one matching entry */
@@ -1655,17 +1674,19 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 	
 	if(result)
 	{
+		buf = g_string_sized_new (len + NICKLEN);
 		if (prefix_len)
-			g_utf8_strncpy(buf, text, prefix_len);
-		strncat (buf, result, COMP_BUF - (prefix_len + 3)); /* make sure nicksuffix and space fits */
-		if(!prefix_len && is_nick)
-			strcat (buf, &prefs.hex_completion_suffix[0]);
-		strcat (buf, " ");
-		cursor_pos = strlen (buf);
+			g_string_append_len (buf, text, offset_to_len (text, prefix_len));
+		g_string_append (buf, result);
+		if((!prefix_len || has_nick_prefix) && is_nick && prefs.hex_completion_suffix[0] != '\0')
+			g_string_append_unichar (buf, g_utf8_get_char_validated (prefs.hex_completion_suffix, -1));
+		g_string_append_c (buf, ' ');
+		cursor_pos = buf->len;
 		if (postfix)
-			strncat (buf, postfix, COMP_BUF - cursor_pos - 2);
-		SPELL_ENTRY_SET_TEXT (t, buf);
-		SPELL_ENTRY_SET_POS (t, g_utf8_pointer_to_offset(buf, buf + cursor_pos));
+			g_string_append (buf, postfix);
+		SPELL_ENTRY_SET_TEXT (t, buf->str);
+		SPELL_ENTRY_SET_POS (t, len_to_offset (buf->str, cursor_pos));
+		g_string_free (buf, TRUE);
 	}
 	if (gcomp)
 		g_completion_free(gcomp);
@@ -1794,10 +1815,10 @@ replace_handle (GtkWidget *t)
 			memcpy (outbuf, text, xlen);
 			outbuf[xlen] = 0;
 			if (postfix_pnt == NULL)
-				snprintf (word, sizeof (word), "%s", pop->cmd);
+				g_snprintf (word, sizeof (word), "%s", pop->cmd);
 			else
-				snprintf (word, sizeof (word), "%s%s", pop->cmd, postfix);
-			strcat (outbuf, word);
+				g_snprintf (word, sizeof (word), "%s%s", pop->cmd, postfix);
+			g_strlcat (outbuf, word, sizeof(outbuf));
 			SPELL_ENTRY_SET_TEXT (t, outbuf);
 			SPELL_ENTRY_SET_POS (t, -1);
 			return;
diff --git a/src/fe-gtk/gtkutil.c b/src/fe-gtk/gtkutil.c
index eabe9c75..e2ca1192 100644
--- a/src/fe-gtk/gtkutil.c
+++ b/src/fe-gtk/gtkutil.c
@@ -62,7 +62,7 @@ static void
 gtkutil_file_req_destroy (GtkWidget * wid, struct file_req *freq)
 {
 	freq->callback (freq->userdata, NULL);
-	free (freq);
+	g_free (freq);
 }
 
 static void
@@ -255,7 +255,7 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
 
 	gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), get_xdir (), NULL);
 
-	freq = malloc (sizeof (struct file_req));
+	freq = g_new (struct file_req, 1);
 	freq->dialog = dialog;
 	freq->flags = flags;
 	freq->callback = callback;
diff --git a/src/fe-gtk/gtkutil.h b/src/fe-gtk/gtkutil.h
index 87beed08..9547cb3b 100644
--- a/src/fe-gtk/gtkutil.h
+++ b/src/fe-gtk/gtkutil.h
@@ -33,14 +33,6 @@ GtkWidget *gtkutil_button (GtkWidget *box, char *stock, char *tip, void *callbac
 void gtkutil_label_new (char *text, GtkWidget * box);
 GtkWidget *gtkutil_entry_new (int max, GtkWidget * box, void *callback,
 										gpointer userdata);
-GtkWidget *gtkutil_clist_new (int columns, char *titles[], GtkWidget * box,
-										int policy, void *select_callback,
-										gpointer select_userdata,
-										void *unselect_callback,
-										gpointer unselect_userdata, int selection_mode);
-int gtkutil_clist_selection (GtkWidget * clist);
-int gtkutil_clist_multiple_selection (GtkWidget * clist,
-													int ** rows, const int max_rows);
 void show_and_unfocus (GtkWidget * wid);
 void gtkutil_set_icon (GtkWidget *win);
 GtkWidget *gtkutil_window_new (char *title, char *role, int width, int height, int flags);
diff --git a/src/fe-gtk/hexchat.rc.tt b/src/fe-gtk/hexchat.rc.tt
index 684ddfdb..35b0e6aa 100644
--- a/src/fe-gtk/hexchat.rc.tt
+++ b/src/fe-gtk/hexchat.rc.tt
@@ -1,9 +1,9 @@
 #include <winver.h>

-#include "../../config.h"

+#include "config.h"

 

 #define COMMA_VERSION <#= [string]::Join(',', $versionParts) #>,0

 

-XC_ICON ICON "../../data/icons/hexchat.ico"

+XC_ICON ICON "<#= $env:SOLUTIONDIR -replace '\\', '/' #>data/icons/hexchat.ico"

 

 VS_VERSION_INFO VERSIONINFO

 	FILEVERSION    COMMA_VERSION

@@ -15,6 +15,7 @@ VS_VERSION_INFO VERSIONINFO
 			BEGIN

 				

 				VALUE "FileDescription", "HexChat IRC Client"

+				VALUE "CompanyName", "HexChat"

 				VALUE "ProductName", "HexChat"

 				VALUE "ProductVersion", PACKAGE_VERSION

 				VALUE "FileVersion", PACKAGE_VERSION

diff --git a/src/fe-gtk/joind.c b/src/fe-gtk/joind.c
index 61ce8828..2fdbeb32 100644
--- a/src/fe-gtk/joind.c
+++ b/src/fe-gtk/joind.c
@@ -151,16 +151,16 @@ joind_show_dialog (server *serv)
 	image1 = gtk_image_new_from_stock (GTK_STOCK_NETWORK, GTK_ICON_SIZE_LARGE_TOOLBAR);
 	gtk_widget_show (image1);
 	gtk_box_pack_start (GTK_BOX (hbox1), image1, FALSE, TRUE, 24);
-	gtk_misc_set_alignment (GTK_MISC (image1), 0.5, 0.06);
+	gtk_misc_set_alignment (GTK_MISC (image1), 0.5f, 0.06f);
 
 	vbox2 = gtk_vbox_new (FALSE, 10);
 	gtk_container_set_border_width (GTK_CONTAINER (vbox2), 6);
 	gtk_widget_show (vbox2);
 	gtk_box_pack_start (GTK_BOX (hbox1), vbox2, TRUE, TRUE, 0);
 
-	snprintf (buf2, sizeof (buf2), _("Connection to %s complete."),
+	g_snprintf (buf2, sizeof (buf2), _("Connection to %s complete."),
 				 server_get_network (serv, TRUE));
-	snprintf (buf, sizeof (buf), "\n<b>%s</b>", buf2);
+	g_snprintf (buf, sizeof (buf), "\n<b>%s</b>", buf2);
 	label = gtk_label_new (buf);
 	gtk_widget_show (label);
 	gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
@@ -198,7 +198,7 @@ joind_show_dialog (server *serv)
 	gtk_widget_show (entry1);
 	gtk_box_pack_start (GTK_BOX (hbox2), entry1, TRUE, TRUE, 8);
 
-	snprintf (buf, sizeof (buf), "<small>     %s</small>",
+	g_snprintf (buf, sizeof (buf), "<small>     %s</small>",
 				 _("If you know the name of the channel you want to join, enter it here."));
 	label = gtk_label_new (buf);
 	gtk_widget_show (label);
@@ -210,9 +210,8 @@ joind_show_dialog (server *serv)
 	gtk_widget_show (radiobutton3);
 	gtk_box_pack_start (GTK_BOX (vbox2), 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));
 
-	snprintf (buf, sizeof (buf), "<small>     %s</small>",
+	g_snprintf (buf, sizeof (buf), "<small>     %s</small>",
 				 _("Retrieving the Channel-List may take a minute or two."));
 	label = gtk_label_new (buf);
 	gtk_widget_show (label);
@@ -250,7 +249,6 @@ joind_show_dialog (server *serv)
 		if (g_ascii_strcasecmp(((ircnet*)serv->network)->name, "freenode") == 0)
 		{
 			gtk_entry_set_text (GTK_ENTRY (entry1), "#hexchat");
-			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(radiobutton2), TRUE);
 		}
 
 	gtk_widget_grab_focus (okbutton1);
diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c
index 2d50a98c..d718dba0 100644
--- a/src/fe-gtk/maingui.c
+++ b/src/fe-gtk/maingui.c
@@ -78,7 +78,7 @@ static void mg_link_irctab (session *sess, int focus);
 static session_gui static_mg_gui;
 static session_gui *mg_gui = NULL;	/* the shared irc tab */
 static int ignore_chanmode = FALSE;
-static const char chan_flags[] = { 'c', 'n', 'r', 't', 'i', 'm', 'l', 'k' };
+static const char chan_flags[] = { 'c', 'n', 't', 'i', 'm', 'l', 'k' };
 
 static chan *active_tab = NULL;	/* active tab */
 GtkWidget *parent_window = NULL;			/* the master window */
@@ -312,7 +312,7 @@ mg_inputbox_cb (GtkWidget *igad, session_gui *gui)
 	if (cmd[0] == 0)
 		return;
 
-	cmd = strdup (cmd);
+	cmd = g_strdup (cmd);
 
 	/* avoid recursive loop */
 	ignore = TRUE;
@@ -340,7 +340,7 @@ mg_inputbox_cb (GtkWidget *igad, session_gui *gui)
 	if (sess)
 		handle_multiline (sess, cmd, TRUE, FALSE);
 
-	free (cmd);
+	g_free (cmd);
 }
 
 static gboolean
@@ -393,42 +393,42 @@ fe_set_title (session *sess)
 	switch (type)
 	{
 	case SESS_DIALOG:
-		snprintf (tbuf, sizeof (tbuf), DISPLAY_NAME": %s %s @ %s",
+		g_snprintf (tbuf, sizeof (tbuf), DISPLAY_NAME": %s %s @ %s",
 					 _("Dialog with"), sess->channel, server_get_network (sess->server, TRUE));
 		break;
 	case SESS_SERVER:
-		snprintf (tbuf, sizeof (tbuf), DISPLAY_NAME": %s @ %s",
+		g_snprintf (tbuf, sizeof (tbuf), DISPLAY_NAME": %s @ %s",
 					 sess->server->nick, server_get_network (sess->server, TRUE));
 		break;
 	case SESS_CHANNEL:
 		/* don't display keys in the titlebar */
 		if (prefs.hex_gui_win_modes)
 		{
-			snprintf (tbuf, sizeof (tbuf),
+			g_snprintf (tbuf, sizeof (tbuf),
 						 DISPLAY_NAME": %s @ %s / %s (%s)",
 						 sess->server->nick, server_get_network (sess->server, TRUE),
 						 sess->channel, sess->current_modes ? sess->current_modes : "");
 		}
 		else
 		{
-			snprintf (tbuf, sizeof (tbuf),
+			g_snprintf (tbuf, sizeof (tbuf),
 						 DISPLAY_NAME": %s @ %s / %s",
 						 sess->server->nick, server_get_network (sess->server, TRUE),
 						 sess->channel);
 		}
 		if (prefs.hex_gui_win_ucount)
 		{
-			snprintf (tbuf + strlen (tbuf), 9, " (%d)", sess->total);
+			g_snprintf (tbuf + strlen (tbuf), 9, " (%d)", sess->total);
 		}
 		break;
 	case SESS_NOTICES:
 	case SESS_SNOTICES:
-		snprintf (tbuf, sizeof (tbuf), DISPLAY_NAME": %s @ %s (notices)",
+		g_snprintf (tbuf, sizeof (tbuf), DISPLAY_NAME": %s @ %s (notices)",
 					 sess->server->nick, server_get_network (sess->server, TRUE));
 		break;
 	default:
 	def:
-		snprintf (tbuf, sizeof (tbuf), DISPLAY_NAME);
+		g_snprintf (tbuf, sizeof (tbuf), DISPLAY_NAME);
 		gtk_window_set_title (GTK_WINDOW (sess->gui->window), tbuf);
 		return;
 	}
@@ -557,7 +557,7 @@ static int
 mg_progressbar_update (GtkWidget *bar)
 {
 	static int type = 0;
-	static float pos = 0;
+	static gdouble pos = 0;
 
 	pos += 0.05;
 	if (pos >= 0.99)
@@ -609,14 +609,14 @@ mg_unpopulate (session *sess)
 	gui = sess->gui;
 	res = sess->res;
 
-	res->input_text = strdup (SPELL_ENTRY_GET_TEXT (gui->input_box));
-	res->topic_text = strdup (gtk_entry_get_text (GTK_ENTRY (gui->topic_entry)));
-	res->limit_text = strdup (gtk_entry_get_text (GTK_ENTRY (gui->limit_entry)));
-	res->key_text = strdup (gtk_entry_get_text (GTK_ENTRY (gui->key_entry)));
+	res->input_text = g_strdup (SPELL_ENTRY_GET_TEXT (gui->input_box));
+	res->topic_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->topic_entry)));
+	res->limit_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->limit_entry)));
+	res->key_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->key_entry)));
 	if (gui->laginfo)
-		res->lag_text = strdup (gtk_label_get_text (GTK_LABEL (gui->laginfo)));
+		res->lag_text = g_strdup (gtk_label_get_text (GTK_LABEL (gui->laginfo)));
 	if (gui->throttleinfo)
-		res->queue_text = strdup (gtk_label_get_text (GTK_LABEL (gui->throttleinfo)));
+		res->queue_text = g_strdup (gtk_label_get_text (GTK_LABEL (gui->throttleinfo)));
 
 	for (i = 0; i < NUM_FLAG_WIDS - 1; i++)
 		res->flag_wid_state[i] = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gui->flag_wid[i]));
@@ -645,7 +645,7 @@ mg_restore_label (GtkWidget *label, char **text)
 	if (*text)
 	{
 		gtk_label_set_text (GTK_LABEL (label), *text);
-		free (*text);
+		g_free (*text);
 		*text = NULL;
 	} else
 	{
@@ -659,7 +659,7 @@ mg_restore_entry (GtkWidget *entry, char **text)
 	if (*text)
 	{
 		gtk_entry_set_text (GTK_ENTRY (entry), *text);
-		free (*text);
+		g_free (*text);
 		*text = NULL;
 	} else
 	{
@@ -674,7 +674,7 @@ mg_restore_speller (GtkWidget *entry, char **text)
 	if (*text)
 	{
 		SPELL_ENTRY_SET_TEXT (entry, *text);
-		free (*text);
+		g_free (*text);
 		*text = NULL;
 	} else
 	{
@@ -1096,8 +1096,11 @@ mg_tab_close (session *sess)
 	else
 	{
 		for (i = 0, list = sess_list; list; list = list->next)
-			if (((session *)list->data)->server == sess->server)
+		{
+			session *s = (session*)list->data;
+			if (s->server == sess->server && (s->type == SESS_CHANNEL || s->type == SESS_DIALOG))
 				i++;
+		}
 		dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window), 0,
 						GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL,
 						_("This server still has %d channels or dialogs associated with it. "
@@ -1331,8 +1334,7 @@ mg_close_gen (chan *ch, GtkWidget *box)
 {
 	char *title = g_object_get_data (G_OBJECT (box), "title");
 
-	if (title)
-		free (title);
+	g_free (title);
 	if (!ch)
 		ch = g_object_get_data (G_OBJECT (box), "ch");
 	if (ch)
@@ -1568,7 +1570,7 @@ mg_create_tabmenu (session *sess, GdkEventButton *event, chan *ch)
 	if (sess)
 	{
 		char *name = g_markup_escape_text (sess->channel[0] ? sess->channel : _("<none>"), -1);
-		snprintf (buf, sizeof (buf), "<span foreground=\"#3344cc\"><b>%s</b></span>", name);
+		g_snprintf (buf, sizeof (buf), "<span foreground=\"#3344cc\"><b>%s</b></span>", name);
 		g_free (name);
 
 		item = gtk_menu_item_new_with_label ("");
@@ -1617,7 +1619,7 @@ static gboolean
 mg_tab_contextmenu_cb (chanview *cv, chan *ch, int tag, gpointer ud, GdkEventButton *event)
 {
 	/* middle-click or shift-click to close a tab */
-	if ((event->button == 2 || (event->button == 1 && event->state & STATE_SHIFT))
+	if (((prefs.hex_gui_tab_middleclose && event->button == 2) || (event->button == 1 && event->state & STATE_SHIFT))
 		&& event->type == GDK_BUTTON_PRESS)
 	{
 		mg_xbutton_cb (cv, ch, tag, ud);
@@ -1640,7 +1642,7 @@ mg_dnd_drop_file (session *sess, char *target, char *uri)
 {
 	char *p, *data, *next, *fname;
 
-	p = data = strdup (uri);
+	p = data = g_strdup (uri);
 	while (*p)
 	{
 		next = strchr (p, '\r');
@@ -1652,7 +1654,7 @@ mg_dnd_drop_file (session *sess, char *target, char *uri)
 			if (fname)
 			{
 				/* dcc_send() expects utf-8 */
-				p = hexchat_filename_to_utf8 (fname, -1, 0, 0, 0);
+				p = g_filename_from_utf8 (fname, -1, 0, 0, 0);
 				if (p)
 				{
 					dcc_send (sess, target, p, prefs.hex_dcc_max_send_cps, 0);
@@ -1667,7 +1669,7 @@ mg_dnd_drop_file (session *sess, char *target, char *uri)
 		if (*p == '\n')
 			p++;
 	}
-	free (data);
+	g_free (data);
 
 }
 
@@ -1716,7 +1718,7 @@ mg_add_chan (session *sess)
 	{
 		sess->res->buffer = gtk_xtext_buffer_new (GTK_XTEXT (sess->gui->xtext));
 		gtk_xtext_set_time_stamp (sess->res->buffer, prefs.hex_stamp_text);
-		sess->res->user_model = userlist_create_model ();
+		sess->res->user_model = userlist_create_model (sess);
 	}
 }
 
@@ -1837,7 +1839,7 @@ mg_changui_destroy (session *sess)
 		/* it fixes: Gdk-CRITICAL **: gdk_colormap_get_screen: */
 		/*           assertion `GDK_IS_COLORMAP (cmap)' failed */
 		ret = sess->gui->window;
-		free (sess->gui);
+		g_free (sess->gui);
 		sess->gui = NULL;
 	}
 	return ret;
@@ -1941,7 +1943,7 @@ flagl_hit (GtkWidget * wid, struct session *sess)
 				gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wid), FALSE);
 				return;
 			}
-			snprintf (modes, sizeof (modes), "+l %d", atoi (limit_str));
+			g_snprintf (modes, sizeof (modes), "+l %d", atoi (limit_str));
 			serv->p_mode (serv, sess->channel, modes);
 			serv->p_join_info (serv, sess->channel);
 		}
@@ -1957,7 +1959,7 @@ flagk_hit (GtkWidget * wid, struct session *sess)
 
 	if (serv->connected && sess->channel[0])
 	{
-		snprintf (modes, sizeof (modes), "-k %s", 
+		g_snprintf (modes, sizeof (modes), "-k %s", 
 			  gtk_entry_get_text (GTK_ENTRY (sess->gui->key_entry)));
 
 		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wid)))
@@ -2001,17 +2003,24 @@ mg_flagbutton_cb (GtkWidget *but, char *flag)
 static GtkWidget *
 mg_create_flagbutton (char *tip, GtkWidget *box, char *face)
 {
-	GtkWidget *wid;
+	GtkWidget *btn, *lbl;
+	char label_markup[16];
+
+	g_snprintf (label_markup, sizeof(label_markup), "<tt>%s</tt>", face);
+	lbl = gtk_label_new (NULL);
+	gtk_label_set_markup (GTK_LABEL(lbl), label_markup);
 
-	wid = gtk_toggle_button_new_with_label (face);
-	gtk_widget_set_size_request (wid, 18, 0);
-	gtk_widget_set_tooltip_text (wid, tip);
-	gtk_box_pack_start (GTK_BOX (box), wid, 0, 0, 0);
-	g_signal_connect (G_OBJECT (wid), "toggled",
+	btn = gtk_toggle_button_new ();
+	gtk_widget_set_size_request (btn, -1, 0);
+	gtk_widget_set_tooltip_text (btn, tip);
+	gtk_container_add (GTK_CONTAINER(btn), lbl);
+
+	gtk_box_pack_start (GTK_BOX (box), btn, 0, 0, 0);
+	g_signal_connect (G_OBJECT (btn), "toggled",
 							G_CALLBACK (mg_flagbutton_cb), face);
-	show_and_unfocus (wid);
+	show_and_unfocus (btn);
 
-	return wid;
+	return btn;
 }
 
 static void
@@ -2023,7 +2032,7 @@ mg_key_entry_cb (GtkWidget * igad, gpointer userdata)
 
 	if (serv->connected && sess->channel[0])
 	{
-		snprintf (modes, sizeof (modes), "+k %s",
+		g_snprintf (modes, sizeof (modes), "+k %s",
 				gtk_entry_get_text (GTK_ENTRY (igad)));
 		serv->p_mode (serv, sess->channel, modes);
 		serv->p_join_info (serv, sess->channel);
@@ -2046,7 +2055,7 @@ mg_limit_entry_cb (GtkWidget * igad, gpointer userdata)
 			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sess->gui->flag_l), FALSE);
 			return;
 		}
-		snprintf (modes, sizeof(modes), "+l %d", 
+		g_snprintf (modes, sizeof(modes), "+l %d", 
 				atoi (gtk_entry_get_text (GTK_ENTRY (igad))));
 		serv->p_mode (serv, sess->channel, modes);
 		serv->p_join_info (serv, sess->channel);
@@ -2066,7 +2075,6 @@ mg_create_chanmodebuttons (session_gui *gui, GtkWidget *box)
 {
 	gui->flag_c = mg_create_flagbutton (_("Filter Colors"), box, "c");
 	gui->flag_n = mg_create_flagbutton (_("No outside messages"), box, "n");
-	gui->flag_r = mg_create_flagbutton (_("Registered Only"), box, "r");
 	gui->flag_t = mg_create_flagbutton (_("Topic Protection"), box, "t");
 	gui->flag_i = mg_create_flagbutton (_("Invite Only"), box, "i");
 	gui->flag_m = mg_create_flagbutton (_("Moderated"), box, "m");
@@ -2287,7 +2295,7 @@ mg_word_clicked (GtkWidget *xtext, char *word, GdkEventButton *even)
 	case WORD_EMAIL:
 		word[end] = 0;
 		word += start;
-		tmp = g_strdup_printf("mailto:%s", word + (ispunct (*word)? 1: 0));
+		tmp = g_strdup_printf ("mailto:%s", word + (ispunct (*word) ? 1 : 0));
 		menu_urlmenu (even, tmp);
 		g_free (tmp);
 		break;
@@ -2597,7 +2605,7 @@ mg_change_nick (int cancel, char *text, gpointer userdata)
 
 	if (!cancel)
 	{
-		snprintf (buf, sizeof (buf), "nick %s", text);
+		g_snprintf (buf, sizeof (buf), "nick %s", text);
 		handle_command (current_sess, buf, FALSE);
 	}
 }
@@ -2940,7 +2948,7 @@ mg_create_search(session *sess, GtkWidget *box)
 	gtk_box_pack_start(GTK_BOX(gui->shbox), next, FALSE, FALSE, 0);
 	g_signal_connect(G_OBJECT(next), "clicked", G_CALLBACK(mg_search_handle_next), sess);
 
-	highlight = gtk_check_button_new_with_mnemonic (_("Highlight _all"));
+	highlight = gtk_check_button_new_with_mnemonic (_("_Highlight all"));
 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(highlight), prefs.hex_text_search_highlight_all);
 	gtk_widget_set_can_focus (highlight, FALSE);
 	g_signal_connect (G_OBJECT (highlight), "toggled", G_CALLBACK (search_set_option), &prefs.hex_text_search_highlight_all);
@@ -3165,7 +3173,7 @@ mg_create_topwindow (session *sess)
 		sess->res->buffer = gtk_xtext_buffer_new (GTK_XTEXT (sess->gui->xtext));
 		gtk_xtext_buffer_show (GTK_XTEXT (sess->gui->xtext), sess->res->buffer, TRUE);
 		gtk_xtext_set_time_stamp (sess->res->buffer, prefs.hex_stamp_text);
-		sess->res->user_model = userlist_create_model ();
+		sess->res->user_model = userlist_create_model (sess);
 	}
 
 	userlist_show (sess);
@@ -3332,7 +3340,7 @@ mg_add_generic_tab (char *name, char *title, void *family, GtkWidget *box)
 	ch = chanview_add (mg_gui->chanview, name, NULL, box, TRUE, TAG_UTIL, pix_tree_util);
 	chan_set_color (ch, plain_list);
 	/* FIXME: memory leak */
-	g_object_set_data (G_OBJECT (box), "title", strdup (title));
+	g_object_set_data (G_OBJECT (box), "title", g_strdup (title));
 	g_object_set_data (G_OBJECT (box), "ch", ch);
 
 	if (prefs.hex_gui_tab_newtofront)
@@ -3395,7 +3403,7 @@ fe_clear_channel (session *sess)
 	{
 		if (sess->res->topic_text)
 		{
-			free (sess->res->topic_text);
+			g_free (sess->res->topic_text);
 			sess->res->topic_text = NULL;
 		}
 	}
@@ -3506,32 +3514,26 @@ mg_changui_new (session *sess, restore_gui *res, int tab, int focus)
 {
 	int first_run = FALSE;
 	session_gui *gui;
-	struct User *user = NULL;
 
-	if (!res)
+	if (res == NULL)
 	{
-		res = malloc (sizeof (restore_gui));
-		memset (res, 0, sizeof (restore_gui));
+		res = g_new0 (restore_gui, 1);
 	}
 
 	sess->res = res;
 
-	if (!sess->server->front_session)
+	if (sess->server->front_session == NULL)
+	{
 		sess->server->front_session = sess;
-
-	if (!is_channel (sess->server, sess->channel))
-		user = userlist_find_global (sess->server, sess->channel);
+	}
 
 	if (!tab)
 	{
-		gui = malloc (sizeof (session_gui));
-		memset (gui, 0, sizeof (session_gui));
+		gui = g_new0 (session_gui, 1);
 		gui->is_tab = FALSE;
 		sess->gui = gui;
 		mg_create_topwindow (sess);
 		fe_set_title (sess);
-		if (user && user->hostname)
-			set_topic (sess, user->hostname, user->hostname);
 		return;
 	}
 
@@ -3551,9 +3553,6 @@ mg_changui_new (session *sess, restore_gui *res, int tab, int focus)
 		gui->is_tab = TRUE;
 	}
 
-	if (user && user->hostname)
-		set_topic (sess, user->hostname, user->hostname);
-
 	mg_add_chan (sess);
 
 	if (first_run || (prefs.hex_gui_tab_newtofront == FOCUS_NEW_ONLY_ASKED && focus)
@@ -3631,8 +3630,8 @@ mg_set_title (GtkWidget *vbox, char *title) /* for non-irc tab/window only */
 	old = g_object_get_data (G_OBJECT (vbox), "title");
 	if (old)
 	{
-		g_object_set_data (G_OBJECT (vbox), "title", strdup (title));
-		free (old);
+		g_object_set_data (G_OBJECT (vbox), "title", g_strdup (title));
+		g_free (old);
 	} else
 	{
 		gtk_window_set_title (GTK_WINDOW (vbox), title);
@@ -3650,7 +3649,7 @@ fe_server_callback (server *serv)
 	if (serv->gui->rawlog_window)
 		mg_close_gen (NULL, serv->gui->rawlog_window);
 
-	free (serv->gui);
+	g_free (serv->gui);
 }
 
 /* called when a session is being killed */
@@ -3661,34 +3660,21 @@ fe_session_callback (session *sess)
 	if (sess->res->banlist && sess->res->banlist->window)
 		mg_close_gen (NULL, sess->res->banlist->window);
 
-	if (sess->res->input_text)
-		free (sess->res->input_text);
-
-	if (sess->res->topic_text)
-		free (sess->res->topic_text);
-
-	if (sess->res->limit_text)
-		free (sess->res->limit_text);
-
-	if (sess->res->key_text)
-		free (sess->res->key_text);
-
-	if (sess->res->queue_text)
-		free (sess->res->queue_text);
-	if (sess->res->queue_tip)
-		free (sess->res->queue_tip);
-
-	if (sess->res->lag_text)
-		free (sess->res->lag_text);
-	if (sess->res->lag_tip)
-		free (sess->res->lag_tip);
+	g_free (sess->res->input_text);
+	g_free (sess->res->topic_text);
+	g_free (sess->res->limit_text);
+	g_free (sess->res->key_text);
+	g_free (sess->res->queue_text);
+	g_free (sess->res->queue_tip);
+	g_free (sess->res->lag_text);
+	g_free (sess->res->lag_tip);
 
 	if (sess->gui->bartag)
 		fe_timeout_remove (sess->gui->bartag);
 
 	if (sess->gui != &static_mg_gui)
-		free (sess->gui);
-	free (sess->res);
+		g_free (sess->gui);
+	g_free (sess->res);
 }
 
 /* ===== DRAG AND DROP STUFF ===== */
diff --git a/src/fe-gtk/menu.c b/src/fe-gtk/menu.c
index 945f6360..902af92e 100644
--- a/src/fe-gtk/menu.c
+++ b/src/fe-gtk/menu.c
@@ -137,7 +137,7 @@ nick_command_parse (session *sess, char *cmd, char *nick, char *allnick)
 
 	/* this can't overflow, since popup->cmd is only 256 */
 	len = strlen (cmd) + strlen (nick) + strlen (allnick) + 512;
-	buf = malloc (len);
+	buf = g_malloc (len);
 
 	auto_insert (buf, len, cmd, 0, 0, allnick, sess->channel, "",
 					 server_get_network (sess->server, TRUE), host,
@@ -145,7 +145,7 @@ nick_command_parse (session *sess, char *cmd, char *nick, char *allnick)
 
 	nick_command (sess, buf);
 
-	free (buf);
+	g_free (buf);
 }
 
 /* userlist button has been clicked */
@@ -166,11 +166,12 @@ userlist_button_cb (GtkWidget * button, char *cmd)
 	if (sess->type == SESS_DIALOG)
 	{
 		/* fake a selection */
-		nicks = malloc (sizeof (char *) * 2);
+		nicks = g_new (char *, 2);
 		nicks[0] = g_strdup (sess->channel);
 		nicks[1] = NULL;
 		num_sel = 1;
-	} else
+	}
+	else
 	{
 		/* find number of selected rows */
 		nicks = userlist_selection_list (sess->gui->user_tree, &num_sel);
@@ -178,14 +179,13 @@ userlist_button_cb (GtkWidget * button, char *cmd)
 		{
 			nick_command_parse (sess, cmd, "", "");
 
-			if (nicks)
-				free (nicks);
+			g_free (nicks);
 			return;
 		}
 	}
 
 	/* create "allnicks" string */
-	allnicks = malloc (((NICKLEN + 1) * num_sel) + 1);
+	allnicks = g_malloc (((NICKLEN + 1) * num_sel) + 1);
 	*allnicks = 0;
 
 	i = 0;
@@ -218,8 +218,8 @@ userlist_button_cb (GtkWidget * button, char *cmd)
 		g_free (nicks[num_sel]);
 	}
 
-	free (nicks);
-	free (allnicks);
+	g_free (nicks);
+	g_free (allnicks);
 }
 
 /* a popup-menu-item has been selected */
@@ -393,9 +393,9 @@ toggle_cb (GtkWidget *item, char *pref_name)
 	char buf[256];
 
 	if (GTK_CHECK_MENU_ITEM (item)->active)
-		snprintf (buf, sizeof (buf), "set %s 1", pref_name);
+		g_snprintf (buf, sizeof (buf), "set %s 1", pref_name);
 	else
-		snprintf (buf, sizeof (buf), "set %s 0", pref_name);
+		g_snprintf (buf, sizeof (buf), "set %s 0", pref_name);
 
 	handle_command (current_sess, buf, FALSE);
 }
@@ -403,12 +403,11 @@ toggle_cb (GtkWidget *item, char *pref_name)
 static int
 is_in_path (char *cmd)
 {
-	char *prog = g_strdup (cmd + 1);	/* 1st char is "!" */
-	char *path, *orig;
+	char *orig = g_strdup (cmd + 1);	/* 1st char is "!" */
+	char *prog = orig;
 	char **argv;
 	int argc;
 
-	orig = prog; /* save for free()ing */
 	/* special-case these default entries. */
 	/*                  123456789012345678 */
 	if (strncmp (prog, "gnome-terminal -x ", 18) == 0)
@@ -417,15 +416,14 @@ is_in_path (char *cmd)
 
 	if (g_shell_parse_argv (prog, &argc, &argv, NULL))
 	{
-		path = g_find_program_in_path (argv[0]);
+		char *path = g_find_program_in_path (argv[0]);
+		g_strfreev (argv);
 		if (path)
 		{
 			g_free (path);
 			g_free (orig);
-			g_strfreev (argv);
 			return 1;
 		}
-		g_strfreev (argv);
 	}
 
 	g_free (orig);
@@ -588,7 +586,7 @@ menu_nickinfo_cb (GtkWidget *menu, session *sess)
 		return;
 
 	/* issue a /WHOIS */
-	snprintf (buf, sizeof (buf), "WHOIS %s %s", str_copy, str_copy);
+	g_snprintf (buf, sizeof (buf), "WHOIS %s %s", str_copy, str_copy);
 	handle_command (sess, buf, FALSE);
 	/* and hide the output */
 	sess->server->skip_next_whois = 1;
@@ -614,30 +612,30 @@ menu_create_nickinfo_menu (struct User *user, GtkWidget *submenu)
 
 	/* let the translators tweak this if need be */
 	fmt = _("<tt><b>%-11s</b></tt> %s");
-	snprintf (unknown, sizeof (unknown), "<i>%s</i>", _("Unknown"));
+	g_snprintf (unknown, sizeof (unknown), "<i>%s</i>", _("Unknown"));
 
 	if (user->realname)
 	{
 		real = strip_color (user->realname, -1, STRIP_ALL|STRIP_ESCMARKUP);
-		snprintf (buf, sizeof (buf), fmt, _("Real Name:"), real);
+		g_snprintf (buf, sizeof (buf), fmt, _("Real Name:"), real);
 		g_free (real);
 	} else
 	{
-		snprintf (buf, sizeof (buf), fmt, _("Real Name:"), unknown);
+		g_snprintf (buf, sizeof (buf), fmt, _("Real Name:"), unknown);
 	}
 	item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
 	g_signal_connect (G_OBJECT (item), "activate",
 							G_CALLBACK (copy_to_clipboard_cb), 
 							user->realname ? user->realname : unknown);
 
-	snprintf (buf, sizeof (buf), fmt, _("User:"),
+	g_snprintf (buf, sizeof (buf), fmt, _("User:"),
 				 user->hostname ? user->hostname : unknown);
 	item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
 	g_signal_connect (G_OBJECT (item), "activate",
 							G_CALLBACK (copy_to_clipboard_cb), 
 							user->hostname ? user->hostname : unknown);
 	
-	snprintf (buf, sizeof (buf), fmt, _("Account:"),
+	g_snprintf (buf, sizeof (buf), fmt, _("Account:"),
 				 user->account ? user->account : unknown);
 	item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
 	g_signal_connect (G_OBJECT (item), "activate",
@@ -647,13 +645,13 @@ menu_create_nickinfo_menu (struct User *user, GtkWidget *submenu)
 	users_country = country (user->hostname);
 	if (users_country)
 	{
-		snprintf (buf, sizeof (buf), fmt, _ ("Country:"), users_country);
+		g_snprintf (buf, sizeof (buf), fmt, _ ("Country:"), users_country);
 		item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
 		g_signal_connect (G_OBJECT (item), "activate",
 			G_CALLBACK (copy_to_clipboard_cb), users_country);
 	}
 
-	snprintf (buf, sizeof (buf), fmt, _("Server:"),
+	g_snprintf (buf, sizeof (buf), fmt, _("Server:"),
 				 user->servername ? user->servername : unknown);
 	item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
 	g_signal_connect (G_OBJECT (item), "activate",
@@ -664,12 +662,12 @@ menu_create_nickinfo_menu (struct User *user, GtkWidget *submenu)
 	{
 		char min[96];
 
-		snprintf (min, sizeof (min), _("%u minutes ago"),
+		g_snprintf (min, sizeof (min), _("%u minutes ago"),
 					(unsigned int) ((time (0) - user->lasttalk) / 60));
-		snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), min);
+		g_snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), min);
 	} else
 	{
-		snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), unknown);
+		g_snprintf (buf, sizeof (buf), fmt, _("Last Msg:"), unknown);
 	}
 	menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
 
@@ -679,7 +677,7 @@ menu_create_nickinfo_menu (struct User *user, GtkWidget *submenu)
 		if (away)
 		{
 			char *msg = strip_color (away->message ? away->message : unknown, -1, STRIP_ALL|STRIP_ESCMARKUP);
-			snprintf (buf, sizeof (buf), fmt, _("Away Msg:"), msg);
+			g_snprintf (buf, sizeof (buf), fmt, _("Away Msg:"), msg);
 			g_free (msg);
 			item = menu_quick_item (0, buf, submenu, XCMENU_MARKUP, 0, 0);
 			g_signal_connect (G_OBJECT (item), "activate",
@@ -728,16 +726,15 @@ menu_nickmenu (session *sess, GdkEventButton *event, char *nick, int num_sel)
 	struct User *user;
 	GtkWidget *submenu, *menu = gtk_menu_new ();
 
-	if (str_copy)
-		free (str_copy);
-	str_copy = strdup (nick);
+	g_free (str_copy);
+	str_copy = g_strdup (nick);
 
 	submenu_list = 0;	/* first time through, might not be 0 */
 
 	/* more than 1 nick selected? */
 	if (num_sel > 1)
 	{
-		snprintf (buf, sizeof (buf), _("%d nicks selected."), num_sel);
+		g_snprintf (buf, sizeof (buf), _("%d nicks selected."), num_sel);
 		menu_quick_item (0, buf, menu, 0, 0, 0);
 		menu_quick_item (0, 0, menu, XCMENU_SHADED, 0, 0);
 	} else
@@ -938,7 +935,7 @@ open_url_cb (GtkWidget *item, char *url)
 	char buf[512];
 
 	/* pass this to /URL so it can handle irc:// */
-	snprintf (buf, sizeof (buf), "URL %s", url);
+	g_snprintf (buf, sizeof (buf), "URL %s", url);
 	handle_command (current_sess, buf, FALSE);
 }
 
@@ -948,20 +945,19 @@ menu_urlmenu (GdkEventButton *event, char *url)
 	GtkWidget *menu;
 	char *tmp, *chop;
 
-	if (str_copy)
-		free (str_copy);
-	str_copy = strdup (url);
+	g_free (str_copy);
+	str_copy = g_strdup (url);
 
 	menu = gtk_menu_new ();
 	/* more than 51 chars? Chop it */
 	if (g_utf8_strlen (str_copy, -1) >= 52)
 	{
-		tmp = strdup (str_copy);
+		tmp = g_strdup (str_copy);
 		chop = g_utf8_offset_to_pointer (tmp, 48);
 		chop[0] = chop[1] = chop[2] = '.';
 		chop[3] = 0;
 		menu_quick_item (0, tmp, menu, XCMENU_SHADED, 0, 0);
-		free (tmp);
+		g_free (tmp);
 	} else
 	{
 		menu_quick_item (0, str_copy, menu, XCMENU_SHADED, 0, 0);
@@ -988,7 +984,7 @@ menu_chan_cycle (GtkWidget * menu, char *chan)
 
 	if (current_sess)
 	{
-		snprintf (tbuf, sizeof tbuf, "CYCLE %s", chan);
+		g_snprintf (tbuf, sizeof tbuf, "CYCLE %s", chan);
 		handle_command (current_sess, tbuf, FALSE);
 	}
 }
@@ -1000,7 +996,7 @@ menu_chan_part (GtkWidget * menu, char *chan)
 
 	if (current_sess)
 	{
-		snprintf (tbuf, sizeof tbuf, "part %s", chan);
+		g_snprintf (tbuf, sizeof tbuf, "part %s", chan);
 		handle_command (current_sess, tbuf, FALSE);
 	}
 }
@@ -1012,7 +1008,7 @@ menu_chan_join (GtkWidget * menu, char *chan)
 
 	if (current_sess)
 	{
-		snprintf (tbuf, sizeof tbuf, "join %s", chan);
+		g_snprintf (tbuf, sizeof tbuf, "join %s", chan);
 		handle_command (current_sess, tbuf, FALSE);
 	}
 }
@@ -1026,9 +1022,8 @@ menu_chanmenu (struct session *sess, GdkEventButton * event, char *chan)
 	if (find_channel (sess->server, chan))
 		is_joined = TRUE;
 
-	if (str_copy)
-		free (str_copy);
-	str_copy = strdup (chan);
+	g_free (str_copy);
+	str_copy = g_strdup (chan);
 
 	menu = gtk_menu_new ();
 
@@ -1074,9 +1069,8 @@ menu_addfavoritemenu (server *serv, GtkWidget *menu, char *channel, gboolean ist
 
 	if (channel != str_copy)
 	{
-		if (str_copy)
-			free (str_copy);
-		str_copy = strdup (channel);
+		g_free (str_copy);
+		str_copy = g_strdup (channel);
 	}
 	
 	if (istree)
@@ -1717,7 +1711,7 @@ menu_about (GtkWidget *wid, gpointer sess)
 					"You should have received a copy of the GNU General Public License\n" \
 					"along with this program. If not, see <http://www.gnu.org/licenses/>";
 
-	g_snprintf  (comment, sizeof(comment), "Compiled: "__DATE__"\n"
+	g_snprintf  (comment, sizeof(comment), ""
 #ifdef WIN32
 				"Portable Mode: %s\n"
 				"Build Type: x%d\n"
diff --git a/src/fe-gtk/notifications/notification-backend.h b/src/fe-gtk/notifications/notification-backend.h
new file mode 100644
index 00000000..b60ced4e
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-backend.h
@@ -0,0 +1,27 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef HEXCHAT_PLUGIN_NOTIFICATION_BACKEND_H
+#define HEXCHAT_PLUGIN_NOTIFICATION_BACKEND_H
+
+int notification_backend_supported (void);
+void notification_backend_show (const char *title, const char *text);
+int notification_backend_init (void);
+void notification_backend_deinit (void);
+
+#endif
diff --git a/src/fe-gtk/notifications/notification-dummy.c b/src/fe-gtk/notifications/notification-dummy.c
new file mode 100644
index 00000000..022443bf
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-dummy.c
@@ -0,0 +1,39 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+void
+notification_backend_show (const char *title, const char *text)
+{
+}
+
+int
+notification_backend_init (void)
+{
+	return 0;
+}
+
+void
+notification_backend_deinit (void)
+{
+}
+
+int
+notification_backend_supported (void)
+{
+	return 0;
+}
diff --git a/src/fe-gtk/notifications/notification-libnotify.c b/src/fe-gtk/notifications/notification-libnotify.c
new file mode 100644
index 00000000..94f9679d
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-libnotify.c
@@ -0,0 +1,72 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include <glib.h>
+#include <libnotify/notify.h>
+
+static gboolean strip_markup = FALSE;
+
+void
+notification_backend_show (const char *title, const char *text)
+{
+	NotifyNotification *notification;
+
+	if (strip_markup)
+		text = g_markup_escape_text (text, -1);
+
+	notification = notify_notification_new (title, text, "hexchat");
+	notify_notification_set_hint (notification, "desktop-entry", g_variant_new_string ("hexchat"));
+
+	notify_notification_show (notification, NULL);
+
+	g_object_unref (notification);
+	if (strip_markup)
+		g_free ((char*)text);
+}
+
+int
+notification_backend_init (void)
+{
+	GList* server_caps;
+
+	if (!NOTIFY_CHECK_VERSION (0, 7, 0))
+		return 0;
+
+	if (!notify_init (PACKAGE_NAME))
+		return 0;
+
+	server_caps = notify_get_server_caps ();
+	if (g_list_find_custom (server_caps, "body-markup", (GCompareFunc)g_strcmp0))
+		strip_markup = TRUE;
+	g_list_free_full (server_caps, g_free);
+
+	return 1;
+}
+
+void
+notification_backend_deinit (void)
+{
+	notify_uninit ();
+}
+
+int
+notification_backend_supported (void)
+{
+	return notify_is_initted ();
+}
diff --git a/src/fe-gtk/notifications/notification-osx.m b/src/fe-gtk/notifications/notification-osx.m
new file mode 100644
index 00000000..c9ad72d0
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-osx.m
@@ -0,0 +1,54 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#import <Cocoa/Cocoa.h>
+#include <gtkosxapplication.h>
+
+void
+notification_backend_show (const char *title, const char *text)
+{
+	NSString *str_title = [[NSString alloc] initWithUTF8String:title];
+	NSString *str_text = [[NSString alloc] initWithUTF8String:text];
+
+	NSUserNotification *userNotification = [NSUserNotification new];
+	userNotification.title = str_title;
+	userNotification.informativeText = str_text;
+
+	NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
+	[center scheduleNotification:userNotification];
+
+	[str_title release];
+	[str_text release];
+}
+
+int
+notification_backend_init (void)
+{
+	return 1;
+}
+
+void
+notification_backend_deinit (void)
+{
+}
+
+int
+notification_backend_supported (void)
+{
+	return gtkosx_application_get_bundle_id () != NULL;
+}
diff --git a/src/fe-gtk/notifications/notification-windows.c b/src/fe-gtk/notifications/notification-windows.c
new file mode 100644
index 00000000..3fade306
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-windows.c
@@ -0,0 +1,87 @@
+/* HexChat
+ * Copyright (C) 2015 Arnav Singh.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <gmodule.h>
+
+#include "hexchat.h"
+#include "plugin.h"
+
+#include <Windows.h>
+
+void (*winrt_notification_backend_show) (const char *title, const char *text) = NULL;
+int (*winrt_notification_backend_init) (void) = NULL;
+void (*winrt_notification_backend_deinit) (void) = NULL;
+int (*winrt_notification_backend_supported) (void) = NULL;
+
+void
+notification_backend_show (const char *title, const char *text)
+{
+	if (winrt_notification_backend_show == NULL)
+	{
+		return;
+	}
+
+	winrt_notification_backend_show (title, text);
+}
+
+int
+notification_backend_init (void)
+{
+	UINT original_error_mode;
+	GModule *module;
+
+	/* Temporarily suppress the "DLL could not be loaded" dialog box before trying to load hcnotifications-winrt.dll */
+	original_error_mode = GetErrorMode ();
+	SetErrorMode(SEM_FAILCRITICALERRORS);
+	module = module_load (HEXCHATLIBDIR "\\hcnotifications-winrt.dll");
+	SetErrorMode (original_error_mode);
+
+	if (module == NULL)
+	{
+		return 0;
+	}
+
+	g_module_symbol (module, "notification_backend_show", (gpointer *) &winrt_notification_backend_show);
+	g_module_symbol (module, "notification_backend_init", (gpointer *) &winrt_notification_backend_init);
+	g_module_symbol (module, "notification_backend_deinit", (gpointer *) &winrt_notification_backend_deinit);
+	g_module_symbol (module, "notification_backend_supported", (gpointer *) &winrt_notification_backend_supported);
+
+	return winrt_notification_backend_init ();
+}
+
+void
+notification_backend_deinit (void)
+{
+	if (winrt_notification_backend_deinit == NULL)
+	{
+		return;
+	}
+
+	winrt_notification_backend_deinit ();
+}
+
+int
+notification_backend_supported (void)
+{
+	if (winrt_notification_backend_supported == NULL)
+	{
+		return 0;
+	}
+
+	return winrt_notification_backend_supported ();
+}
diff --git a/src/fe-gtk/notifications/notification-winrt.cpp b/src/fe-gtk/notifications/notification-winrt.cpp
new file mode 100644
index 00000000..663f9c08
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-winrt.cpp
@@ -0,0 +1,100 @@
+/* HexChat
+ * Copyright (c) 2014 Leetsoftwerx
+ *
+ * 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 THE
+ * AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <string>
+#include <codecvt>
+
+#include <roapi.h>
+#include <windows.ui.notifications.h>
+
+using namespace Windows::UI::Notifications;
+using namespace Windows::Data::Xml::Dom;
+
+static ToastNotifier ^ notifier = nullptr;
+
+static std::wstring
+widen(const std::string & to_widen)
+{
+	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
+	return converter.from_bytes(to_widen);
+}
+
+extern "C"
+{
+	__declspec (dllexport) void
+	notification_backend_show (const char *title, const char *text)
+	{
+		try
+		{
+			auto toastTemplate = ToastNotificationManager::GetTemplateContent (ToastTemplateType::ToastText02);
+			auto node_list = toastTemplate->GetElementsByTagName ("text");
+			UINT node_count = node_list->Length;
+
+			auto wtitle = widen (title);
+			node_list->GetAt (0)->AppendChild (
+				toastTemplate->CreateTextNode (Platform::StringReference (wtitle.c_str (), wtitle.size ())));
+
+			auto wtext = widen (text);
+			node_list->GetAt (1)->AppendChild (
+				toastTemplate->CreateTextNode (Platform::StringReference (wtext.c_str (), wtext.size ())));
+
+			// Mute sound, we already play our own
+			auto node = toastTemplate->SelectSingleNode ("/toast");
+			auto audio_elem = toastTemplate->CreateElement ("audio");
+			audio_elem->SetAttribute ("silent", "true");
+			static_cast<XmlElement^>(node)->AppendChild (audio_elem);
+
+			notifier->Show (ref new ToastNotification (toastTemplate));
+		}
+		catch (Platform::Exception ^ ex)
+		{
+		}
+		catch (...)
+		{
+		}
+	}
+
+	__declspec (dllexport) int
+	notification_backend_init (void)
+	{
+		if (!notifier)
+			notifier = ToastNotificationManager::CreateToastNotifier ("HexChat.Desktop.Notify");
+
+		if (FAILED (Windows::Foundation::Initialize (RO_INIT_SINGLETHREADED)))
+			return 0;
+
+		return 1;
+	}
+
+	__declspec (dllexport) 	void
+	notification_backend_deinit (void)
+	{
+		notifier = nullptr;
+		Windows::Foundation::Uninitialize ();
+	}
+
+	__declspec (dllexport) int
+	notification_backend_supported (void)
+	{
+		return 1;
+	}
+}
diff --git a/src/fe-gtk/notifications/notifications-winrt.vcxproj b/src/fe-gtk/notifications/notifications-winrt.vcxproj
new file mode 100644
index 00000000..dcd2a2b7
--- /dev/null
+++ b/src/fe-gtk/notifications/notifications-winrt.vcxproj
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="12.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>

+    <ClCompile Include="notification-winrt.cpp">

+      <CompileAsWinRT>true</CompileAsWinRT>

+    </ClCompile>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{C53145CC-D021-40C9-B97C-0249AB9A43C9}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>notifications-winrt</RootNamespace>

+    <ProjectName>notifications-winrt</ProjectName>

+  </PropertyGroup>

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

+  <PropertyGroup Label="Configuration">

+    <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

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

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

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

+  <PropertyGroup>

+    <TargetName>hcnotifications-winrt</TargetName>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

+  </PropertyGroup>

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

+    <ClCompile>

+      <PreprocessorDefinitions>WIN32;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT;NDEBUG;_WINDOWS;_USRDLL;NOTIFICATIONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <SDLCheck>true</SDLCheck>

+      <AdditionalUsingDirectories>$(VCInstallDir)vcpackages;$(FrameworkSdkDir)References\CommonConfiguration\Neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>

+    </ClCompile>

+    <Link>

+      <AdditionalDependencies>$(DepLibs);mincore.lib;runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <MinimumRequiredVersion>6.03</MinimumRequiredVersion>

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

+    </Link>

+  </ItemDefinitionGroup>

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

+    <ClCompile>

+      <PreprocessorDefinitions>WIN32;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT;NDEBUG;_WINDOWS;_USRDLL;NOTIFICATIONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <SDLCheck>true</SDLCheck>

+      <AdditionalUsingDirectories>$(VCInstallDir)vcpackages;$(FrameworkSdkDir)References\CommonConfiguration\Neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>

+    </ClCompile>

+    <Link>

+      <AdditionalDependencies>$(DepLibs);mincore.lib;runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <MinimumRequiredVersion>6.03</MinimumRequiredVersion>

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

+    </Link>

+  </ItemDefinitionGroup>

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

+</Project>

diff --git a/src/fe-gtk/notifications/notifications-winrt.vcxproj.filters b/src/fe-gtk/notifications/notifications-winrt.vcxproj.filters
new file mode 100644
index 00000000..06f4e558
--- /dev/null
+++ b/src/fe-gtk/notifications/notifications-winrt.vcxproj.filters
@@ -0,0 +1,22 @@
+<?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;hh;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>
+    <ClCompile Include="notification-winrt.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/src/fe-gtk/notifygui.c b/src/fe-gtk/notifygui.c
index 5aa60d0a..ed16f44f 100644
--- a/src/fe-gtk/notifygui.c
+++ b/src/fe-gtk/notifygui.c
@@ -190,11 +190,11 @@ notify_gui_update (void)
 			{
 				lastseenminutes = (int)(time (0) - lastseen) / 60;
 				if (lastseenminutes < 60) 
-					snprintf (agobuf, sizeof (agobuf), _("%d minutes ago"), lastseenminutes);
+					g_snprintf (agobuf, sizeof (agobuf), _("%d minutes ago"), lastseenminutes);
 				else if (lastseenminutes < 120)
-					snprintf (agobuf, sizeof (agobuf), _("An hour ago"));
+					g_snprintf (agobuf, sizeof (agobuf), _("An hour ago"));
 				else
-					snprintf (agobuf, sizeof (agobuf), _("%d hours ago"), lastseenminutes / 60);
+					g_snprintf (agobuf, sizeof (agobuf), _("%d hours ago"), lastseenminutes / 60);
 				seen = agobuf;
 			}
 			if (!valid)	/* create new tree row if required */
@@ -219,7 +219,7 @@ notify_gui_update (void)
 						name = "";
 					server = server_get_network (servnot->server, TRUE);
 
-					snprintf (agobuf, sizeof (agobuf), _("%d minutes ago"), (int)(time (0) - lastseen) / 60);
+					g_snprintf (agobuf, sizeof (agobuf), _("%d minutes ago"), (int)(time (0) - lastseen) / 60);
 					seen = agobuf;
 
 					if (!valid)	/* create new tree row if required */
@@ -380,7 +380,7 @@ fe_notify_ask (char *nick, char *networks)
 	gtk_table_attach_defaults (GTK_TABLE (table), wid, 1, 2, 2, 3);
 
 	label = gtk_label_new (NULL);
-	snprintf (buf, sizeof (buf), "<i><span size=\"smaller\">%s</span></i>", _("Comma separated list of networks is accepted."));
+	g_snprintf (buf, sizeof (buf), "<i><span size=\"smaller\">%s</span></i>", _("Comma separated list of networks is accepted."));
 	gtk_label_set_markup (GTK_LABEL (label), buf);
 	gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 3, 4);
 
diff --git a/src/fe-gtk/palette.c b/src/fe-gtk/palette.c
index 435ba84b..17689756 100644
--- a/src/fe-gtk/palette.c
+++ b/src/fe-gtk/palette.c
@@ -106,45 +106,39 @@ palette_alloc (GtkWidget * widget)
 void
 palette_load (void)
 {
-	int i, j, l, fh;
+	int i, j, fh;
 	char prefname[256];
 	struct stat st;
 	char *cfg;
-	int red, green, blue;
+	guint16 red, green, blue;
 
 	fh = hexchat_open_file ("colors.conf", O_RDONLY, 0, 0);
 	if (fh != -1)
 	{
 		fstat (fh, &st);
-		cfg = malloc (st.st_size + 1);
-		if (cfg)
+		cfg = g_malloc0 (st.st_size + 1);
+		read (fh, cfg, st.st_size);
+
+		/* mIRC colors 0-31 are here */
+		for (i = 0; i < 32; i++)
+		{
+			g_snprintf (prefname, sizeof prefname, "color_%d", i);
+			cfg_get_color (cfg, prefname, &red, &green, &blue);
+			colors[i].red = red;
+			colors[i].green = green;
+			colors[i].blue = blue;
+		}
+
+		/* our special colors are mapped at 256+ */
+		for (i = 256, j = 32; j < MAX_COL+1; i++, j++)
 		{
-			cfg[0] = '\0';
-			l = read (fh, cfg, st.st_size);
-			if (l >= 0)
-				cfg[l] = '\0';
-
-			/* mIRC colors 0-31 are here */
-			for (i = 0; i < 32; i++)
-			{
-				snprintf (prefname, sizeof prefname, "color_%d", i);
-				cfg_get_color (cfg, prefname, &red, &green, &blue);
-				colors[i].red = red;
-				colors[i].green = green;
-				colors[i].blue = blue;
-			}
-
-			/* our special colors are mapped at 256+ */
-			for (i = 256, j = 32; j < MAX_COL+1; i++, j++)
-			{
-				snprintf (prefname, sizeof prefname, "color_%d", i);
-				cfg_get_color (cfg, prefname, &red, &green, &blue);
-				colors[j].red = red;
-				colors[j].green = green;
-				colors[j].blue = blue;
-			}
-			free (cfg);
+			g_snprintf (prefname, sizeof prefname, "color_%d", i);
+			cfg_get_color (cfg, prefname, &red, &green, &blue);
+			colors[j].red = red;
+			colors[j].green = green;
+			colors[j].blue = blue;
 		}
+		g_free (cfg);
 		close (fh);
 	}
 }
@@ -161,14 +155,14 @@ palette_save (void)
 		/* mIRC colors 0-31 are here */
 		for (i = 0; i < 32; i++)
 		{
-			snprintf (prefname, sizeof prefname, "color_%d", i);
+			g_snprintf (prefname, sizeof prefname, "color_%d", i);
 			cfg_put_color (fh, colors[i].red, colors[i].green, colors[i].blue, prefname);
 		}
 
 		/* our special colors are mapped at 256+ */
 		for (i = 256, j = 32; j < MAX_COL+1; i++, j++)
 		{
-			snprintf (prefname, sizeof prefname, "color_%d", i);
+			g_snprintf (prefname, sizeof prefname, "color_%d", i);
 			cfg_put_color (fh, colors[j].red, colors[j].green, colors[j].blue, prefname);
 		}
 
diff --git a/src/fe-gtk/pixmaps.c b/src/fe-gtk/pixmaps.c
index cbec6f71..053afaaf 100644
--- a/src/fe-gtk/pixmaps.c
+++ b/src/fe-gtk/pixmaps.c
@@ -87,10 +87,9 @@ pixmap_load_from_file (char *filename)
 static GdkPixbuf *
 load_pixmap (const char *filename)
 {
-	gchar *path;
 	GdkPixbuf *pixbuf;
 
-	path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "icons" G_DIR_SEPARATOR_S "%s.png", get_xdir (), filename);
+	gchar *path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "icons" G_DIR_SEPARATOR_S "%s.png", get_xdir (), filename);
 	pixbuf = gdk_pixbuf_new_from_file (path, 0);
 	g_free (path);
 
diff --git a/src/fe-gtk/plugin-notification.c b/src/fe-gtk/plugin-notification.c
new file mode 100644
index 00000000..04a64213
--- /dev/null
+++ b/src/fe-gtk/plugin-notification.c
@@ -0,0 +1,215 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include <glib.h>
+
+#include "../common/hexchat-plugin.h"
+#include "../common/inbound.h" /* For alert_match_word() */
+#include "notifications/notification-backend.h"
+
+static hexchat_plugin *ph;
+
+static gboolean
+should_alert (void)
+{
+	int omit_away, omit_focused, omit_tray;
+
+	if (hexchat_get_prefs (ph, "gui_focus_omitalerts", NULL, &omit_focused) == 3 && omit_focused)
+	{
+		const char *status = hexchat_get_info (ph, "win_status");
+
+		if (status && !g_strcmp0 (status, "active"))
+			return FALSE;
+	}
+
+	if (hexchat_get_prefs (ph, "away_omit_alerts", NULL, &omit_away) == 3 && omit_away)
+	{
+		if (hexchat_get_info (ph, "away"))
+			return FALSE;
+	}
+
+	if (hexchat_get_prefs (ph, "gui_tray_quiet", NULL, &omit_tray) == 3 && omit_tray)
+	{
+		int tray_enabled;
+
+		if (hexchat_get_prefs (ph, "gui_tray", NULL, &tray_enabled) == 3 && tray_enabled)
+		{
+			const char *status = hexchat_get_info (ph, "win_status");
+
+			if (status && g_strcmp0 (status, "hidden") != 0)
+				return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+static gboolean
+is_ignored (char *nick)
+{
+	const char *no_hilight;
+
+	if (hexchat_get_prefs (ph, "irc_no_hilight", &no_hilight, NULL) == 1 && no_hilight)
+	{
+		return alert_match_word (nick, (char*)no_hilight);
+	}
+	return FALSE;
+}
+
+static void
+show_notification (const char *title, const char *text)
+{
+	char *stripped_title, *stripped_text;
+
+	/* Strip all colors */
+	stripped_title = hexchat_strip (ph, title, -1, 7);
+	stripped_text = hexchat_strip (ph, text, -1, 7);
+	
+	notification_backend_show (stripped_title, stripped_text);
+
+	hexchat_free (ph, stripped_title);
+	hexchat_free (ph, stripped_text);
+}
+
+static void
+show_notificationf (const char *text, const char *format, ...)
+{
+	va_list args;
+	char *buf;
+
+	va_start (args, format);
+	buf = g_strdup_vprintf (format, args);
+	va_end (args);
+
+	show_notification (buf, text);
+	g_free (buf);
+}
+
+static int
+incoming_hilight_cb (char *word[], gpointer userdata)
+{
+	int hilight;
+
+	if (hexchat_get_prefs (ph, "input_balloon_hilight", NULL, &hilight) == 3 && hilight && should_alert())
+	{
+		show_notificationf (word[2], _("Highlighted message from: %s (%s)"), word[1], hexchat_get_info (ph, "channel"));
+	}
+	return HEXCHAT_EAT_NONE;
+}
+
+static int
+incoming_message_cb (char *word[], gpointer userdata)
+{
+	int message;
+
+	if (hexchat_get_prefs (ph, "input_balloon_chans", NULL, &message) == 3 && message && should_alert ())
+	{
+		show_notificationf (word[2], _("Channel message from: %s (%s)"), word[1], hexchat_get_info (ph, "channel"));
+	}
+	return HEXCHAT_EAT_NONE;
+}
+
+static int
+incoming_priv_cb (char *word[], gpointer userdata)
+{
+	int priv;
+
+	if (hexchat_get_prefs (ph, "input_balloon_priv", NULL, &priv) == 3 && priv && should_alert ())
+	{
+		const char *network = hexchat_get_info (ph, "network");
+		if (!network)
+			network = hexchat_get_info (ph, "server");
+
+		if (userdata != NULL) /* Special event */
+		{
+			if (GPOINTER_TO_INT (userdata) == 3)
+			{
+				if (!is_ignored (word[2]))
+					show_notificationf (word[1], _("File offer from: %s (%s)"), word[2], network);
+			}
+			else if (GPOINTER_TO_INT (userdata) == 2)
+			{
+				if (!is_ignored (word[2]))
+					show_notificationf (word[1], _("Invited to channel by: %s (%s)"), word[2], network);
+			}
+			else
+			{
+				if (!is_ignored (word[1]))
+					show_notificationf (word[2], _("Notice from: %s (%s)"), word[1], network);
+			}
+		}
+		else
+			show_notificationf (word[2], _("Private message from: %s (%s)"), word[1], network);
+	}
+	return HEXCHAT_EAT_NONE;
+}
+
+static int
+tray_cmd_cb (char *word[], char *word_eol[], gpointer userdata)
+{
+	if (word[2] && !g_ascii_strcasecmp (word[2], "-b") && word[3] && word[4])
+	{
+		if (should_alert ())
+			show_notification (word[3], word_eol[4]);
+		return HEXCHAT_EAT_ALL;
+	}
+
+	return HEXCHAT_EAT_NONE;
+}
+
+int
+notification_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
+{
+	if (!notification_backend_init ())
+		return 0;
+
+	ph = plugin_handle;
+	*plugin_name = "";
+	*plugin_desc = "";
+	*plugin_version = "";
+
+	hexchat_hook_print (ph, "Channel Msg Hilight", HEXCHAT_PRI_LOWEST, incoming_hilight_cb, NULL);
+	hexchat_hook_print (ph, "Channel Action Hilight", HEXCHAT_PRI_LOWEST, incoming_hilight_cb, NULL);
+
+	hexchat_hook_print (ph, "Channel Message", HEXCHAT_PRI_LOWEST, incoming_message_cb, NULL);
+	hexchat_hook_print (ph, "Channel Action", HEXCHAT_PRI_LOWEST, incoming_message_cb, NULL);
+	hexchat_hook_print (ph, "Channel Notice", HEXCHAT_PRI_LOWEST, incoming_message_cb, NULL);
+
+	hexchat_hook_print (ph, "Private Message", HEXCHAT_PRI_LOWEST, incoming_priv_cb, NULL);
+	hexchat_hook_print (ph, "Private Message to Dialog", HEXCHAT_PRI_LOWEST, incoming_priv_cb, NULL);
+	hexchat_hook_print (ph, "Private Action", HEXCHAT_PRI_LOWEST, incoming_priv_cb, NULL);
+	hexchat_hook_print (ph, "Private Action to Dialog", HEXCHAT_PRI_LOWEST, incoming_priv_cb, NULL);
+
+	/* Special events treated as priv */
+	hexchat_hook_print (ph, "Notice", HEXCHAT_PRI_LOWEST, incoming_priv_cb, GINT_TO_POINTER (1));
+	hexchat_hook_print (ph, "Invited", HEXCHAT_PRI_LOWEST, incoming_priv_cb, GINT_TO_POINTER (2));
+	hexchat_hook_print (ph, "DCC Offer", HEXCHAT_PRI_LOWEST, incoming_priv_cb, GINT_TO_POINTER (3));
+
+	hexchat_hook_command (ph, "TRAY", HEXCHAT_PRI_HIGH, tray_cmd_cb, NULL, NULL);
+	
+	return 1;
+}
+
+
+int
+notification_plugin_deinit (void)
+{
+	notification_backend_deinit ();
+	return 1;
+}
diff --git a/src/fe-gtk/plugin-notification.h b/src/fe-gtk/plugin-notification.h
new file mode 100644
index 00000000..07ad1609
--- /dev/null
+++ b/src/fe-gtk/plugin-notification.h
@@ -0,0 +1,25 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef HEXCHAT_PLUGIN_NOTIFICATION_H
+#define HEXCHAT_PLUGIN_NOTIFICATION_H
+
+int notification_plugin_init (void *, char **, char **, char **, char *);
+int notification_plugin_deinit (void *);
+
+#endif
diff --git a/src/fe-gtk/plugin-tray.c b/src/fe-gtk/plugin-tray.c
index b3e34c0a..077a7c63 100644
--- a/src/fe-gtk/plugin-tray.c
+++ b/src/fe-gtk/plugin-tray.c
@@ -34,18 +34,6 @@
 #include <unistd.h>
 #endif
 
-#ifdef USE_LIBNOTIFY
-#include <libnotify/notify.h>
-#ifndef NOTIFY_CHECK_VERSION
-#define NOTIFY_CHECK_VERSION(x,y,z) 0
-#endif
-#if NOTIFY_CHECK_VERSION(0,7,0)
-#define XC_NOTIFY_NEW(a,b,c,d) notify_notification_new(a,b,c)
-#else
-#define XC_NOTIFY_NEW(a,b,c,d) notify_notification_new(a,b,c,d)
-#endif
-#endif
-
 typedef enum	/* current icon status */
 {
 	TS_NONE,
@@ -154,82 +142,6 @@ fe_tray_set_tooltip (const char *text)
 		gtk_status_icon_set_tooltip_text (sticon, text);
 }
 
-void
-fe_tray_set_balloon (const char *title, const char *text)
-{
-#ifndef WIN32
-#if 0
-	const char *argv[8];
-	const char *path;
-	char time[16];
-#endif
-	WinStatus ws;
-
-	/* no balloons if the window is focused */
-	ws = tray_get_window_status ();
-	if ((prefs.hex_away_omit_alerts && hexchat_get_info(ph, "away")) ||
-		(prefs.hex_gui_focus_omitalerts && ws == WS_FOCUSED))
-		return;
-
-	/* bit 1 of flags means "no balloons unless hidden/iconified" */
-	if (ws != WS_HIDDEN && prefs.hex_gui_tray_quiet)
-		return;
-
-	/* FIXME: this should close the current balloon */
-	if (!text)
-		return;
-
-#ifdef USE_LIBNOTIFY
-	static int notify_text_strip_flags = STRIP_ALL;
-	NotifyNotification *notification;
-	char *notify_text, *notify_title;
-
-	if (!notify_is_initted())
-	{
-		notify_init(PACKAGE_NAME);
-
-		GList* server_caps = notify_get_server_caps ();
-		if (g_list_find_custom (server_caps, "body-markup", (GCompareFunc)strcmp))
-		{
-			notify_text_strip_flags |= STRIP_ESCMARKUP;
-		}
-		g_list_free_full (server_caps, g_free);
-	}
-
-	notify_text = strip_color (text, -1, notify_text_strip_flags);
-	notify_title = strip_color (title, -1, STRIP_ALL);
-
-	notification = XC_NOTIFY_NEW (notify_title, notify_text, HEXCHATSHAREDIR "/icons/hicolor/scalable/apps/hexchat.svg", NULL);
-
-#if NOTIFY_CHECK_VERSION(0,7,0)
-	notify_notification_set_hint (notification, "desktop-entry", g_variant_new_string ("hexchat"));
-#endif
-
-	g_free ((char *)notify_title);
-	g_free ((char *)notify_text);
-
-	notify_notification_set_timeout (notification, prefs.hex_input_balloon_time*1000);
-	notify_notification_show (notification, NULL);
-
-	g_object_unref (notification);
-#endif
-#endif
-}
-
-static void
-tray_set_balloonf (const char *text, const char *format, ...)
-{
-	va_list args;
-	char *buf;
-
-	va_start (args, format);
-	buf = g_strdup_vprintf (format, args);
-	va_end (args);
-
-	fe_tray_set_balloon (buf, text);
-	g_free (buf);
-}
-
 static void
 tray_set_tipf (const char *format, ...)
 {
@@ -575,26 +487,32 @@ tray_menu_destroy (GtkWidget *menu, gpointer userdata)
 }
 
 #ifdef WIN32
-static void
+static gboolean
 tray_menu_enter_cb (GtkWidget *menu)
 {
 	tray_menu_inactivetime = 0;
+	return FALSE;
 }
 
-static void
+static gboolean
 tray_menu_left_cb (GtkWidget *menu)
 {
 	tray_menu_inactivetime = g_get_real_time ();
+	return FALSE;
 }
 
-static void
+static gboolean
 tray_check_hide (GtkWidget *menu)
 {
 	if (tray_menu_inactivetime && g_get_real_time () - tray_menu_inactivetime  >= 2000000)
 	{
 		tray_menu_destroy (menu, NULL);
+		return G_SOURCE_REMOVE;
 	}
+
+	return G_SOURCE_CONTINUE;
 }
+#endif
 
 static void
 tray_menu_settings (GtkWidget * wid, gpointer none)
@@ -602,7 +520,6 @@ tray_menu_settings (GtkWidget * wid, gpointer none)
 	extern void setup_open (void);
 	setup_open ();
 }
-#endif
 
 static void
 tray_menu_cb (GtkWidget *widget, guint button, guint time, gpointer userdata)
@@ -651,10 +568,9 @@ tray_menu_cb (GtkWidget *widget, guint button, guint time, gpointer userdata)
 		gtk_widget_set_sensitive (item, FALSE);
 
 	menu_add_plugin_items (menu, "\x5$TRAY", NULL);
-#ifdef WIN32
+
 	tray_make_item (menu, NULL, tray_menu_quit_cb, NULL);
 	mg_create_icon_item (_("_Preferences"), GTK_STOCK_PREFERENCES, menu, tray_menu_settings, NULL);
-#endif
 	tray_make_item (menu, NULL, tray_menu_quit_cb, NULL);
 	mg_create_icon_item (_("_Quit"), GTK_STOCK_QUIT, menu, tray_menu_quit_cb, NULL);
 
@@ -669,7 +585,7 @@ tray_menu_cb (GtkWidget *widget, guint button, guint time, gpointer userdata)
 	g_signal_connect (G_OBJECT (menu), "enter-notify-event",
 							G_CALLBACK (tray_menu_enter_cb), NULL);
 
-	tray_menu_timer = g_timeout_add(500, (GSourceFunc) tray_check_hide, menu);
+	tray_menu_timer = g_timeout_add (500, tray_check_hide, menu);
 #endif
 
 	gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL,
@@ -718,10 +634,6 @@ tray_hilight_cb (char *word[], void *userdata)
 								tray_hilight_count, word[1], hexchat_get_info (ph, "channel"));
 	}
 
-	if (prefs.hex_input_balloon_hilight)
-		tray_set_balloonf (word[2], _("Highlighted message from: %s (%s)"),
-								 word[1], hexchat_get_info (ph, "channel"));
-
 	return HEXCHAT_EAT_NONE;
 }
 
@@ -743,10 +655,6 @@ tray_message_cb (char *word[], void *userdata)
 			tray_set_tipf (_(DISPLAY_NAME": %u channel messages."), tray_pub_count);
 	}
 
-	if (prefs.hex_input_balloon_chans)
-		tray_set_balloonf (word[2], _("Channel message from: %s (%s)"),
-								 word[1], hexchat_get_info (ph, "channel"));
-
 	return HEXCHAT_EAT_NONE;
 }
 
@@ -774,10 +682,6 @@ tray_priv (char *from, char *text)
 			tray_set_tipf (_(DISPLAY_NAME": %u private messages, latest from: %s (%s)"),
 								tray_priv_count, from, network);
 	}
-
-	if (prefs.hex_input_balloon_priv)
-		tray_set_balloonf (text, _("Private message from: %s (%s)"),
-								 from, network);
 }
 
 static int
@@ -822,10 +726,6 @@ tray_dcc_cb (char *word[], void *userdata)
 								tray_file_count, word[1], network);
 	}
 
-	if (prefs.hex_input_balloon_priv && (!prefs.hex_away_omit_alerts || tray_find_away_status () != 1))
-		tray_set_balloonf ("", _("File offer from: %s (%s)"),
-								word[1], network);
-
 	return HEXCHAT_EAT_NONE;
 }
 
@@ -904,8 +804,6 @@ tray_plugin_deinit (hexchat_plugin *plugin_handle)
 {
 #ifdef WIN32
 	tray_cleanup ();
-#elif defined(USE_LIBNOTIFY)
-	notify_uninit ();
 #endif
 	return 1;
 }
diff --git a/src/fe-gtk/plugingui.c b/src/fe-gtk/plugingui.c
index 9b3186a6..83e05727 100644
--- a/src/fe-gtk/plugingui.c
+++ b/src/fe-gtk/plugingui.c
@@ -142,23 +142,21 @@ plugingui_load_cb (session *sess, char *file)
 {
 	if (file)
 	{
-		char *buf = malloc (strlen (file) + 9);
+		char *buf;
 
 		if (strchr (file, ' '))
-			sprintf (buf, "LOAD \"%s\"", file);
+			buf = g_strdup_printf ("LOAD \"%s\"", file);
 		else
-			sprintf (buf, "LOAD %s", file);
+			buf = g_strdup_printf ("LOAD %s", file);
 		handle_command (sess, buf, FALSE);
-		free (buf);
+		g_free (buf);
 	}
 }
 
 void
 plugingui_load (void)
 {
-	char *sub_dir;
-
-	sub_dir = g_build_filename (get_xdir(), "addons", NULL);
+	char *sub_dir = g_build_filename (get_xdir(), "addons", NULL);
 
 	gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess,
 							sub_dir, "*."G_MODULE_SUFFIX";*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS);
@@ -175,7 +173,7 @@ plugingui_loadbutton_cb (GtkWidget * wid, gpointer unused)
 static void
 plugingui_unload (GtkWidget * wid, gpointer unused)
 {
-	char *modname, *file, *buf;
+	char *modname, *file;
 	GtkTreeView *view;
 	GtkTreeIter iter;
 	
@@ -188,16 +186,17 @@ plugingui_unload (GtkWidget * wid, gpointer unused)
 	{
 		if (plugin_kill (modname, FALSE) == 2)
 			fe_message (_("That plugin is refusing to unload.\n"), FE_MSG_ERROR);
-	} else
+	}
+	else
 	{
+		char *buf;
 		/* let python.so or perl.so handle it */
-		buf = malloc (strlen (file) + 10);
 		if (strchr (file, ' '))
-			sprintf (buf, "UNLOAD \"%s\"", file);
+			buf = g_strdup_printf ("UNLOAD \"%s\"", file);
 		else
-			sprintf (buf, "UNLOAD %s", file);
+			buf = g_strdup_printf ("UNLOAD %s", file);
 		handle_command (current_sess, buf, FALSE);
-		free (buf);
+		g_free (buf);
 	}
 
 	g_free (modname);
@@ -211,14 +210,14 @@ plugingui_reloadbutton_cb (GtkWidget *wid, GtkTreeView *view)
 
 	if (file)
 	{
-		char *buf = malloc (strlen (file) + 9);
+		char *buf;
 
 		if (strchr (file, ' '))
-			sprintf (buf, "RELOAD \"%s\"", file);
+			buf = g_strdup_printf ("RELOAD \"%s\"", file);
 		else
-			sprintf (buf, "RELOAD %s", file);
+			buf = g_strdup_printf ("RELOAD %s", file);
 		handle_command (current_sess, buf, FALSE);
-		free (buf);
+		g_free (buf);
 		g_free (file);
 	}
 }
diff --git a/src/fe-gtk/rawlog.c b/src/fe-gtk/rawlog.c
index f2527492..1d4bf9fd 100644
--- a/src/fe-gtk/rawlog.c
+++ b/src/fe-gtk/rawlog.c
@@ -109,7 +109,7 @@ open_rawlog (struct server *serv)
 		return;
 	}
 
-	snprintf (tbuf, sizeof tbuf, _(DISPLAY_NAME": Raw Log (%s)"), serv->servername);
+	g_snprintf (tbuf, sizeof tbuf, _(DISPLAY_NAME": Raw Log (%s)"), serv->servername);
 	serv->gui->rawlog_window =
 		mg_create_generic_tab ("RawLog", tbuf, FALSE, TRUE, close_rawlog, serv,
 							 640, 320, &vbox, serv);
@@ -146,7 +146,7 @@ fe_add_rawlog (server *serv, char *text, int len, int outbound)
 {
 	char **split_text;
 	char *new_text;
-	int i;
+	size_t i;
 
 	if (!serv->gui->rawlog_window)
 		return;
@@ -163,7 +163,7 @@ fe_add_rawlog (server *serv, char *text, int len, int outbound)
 		else
 			new_text = g_strconcat ("\0033>>\017 ", split_text[i], NULL);
 
-		gtk_xtext_append (GTK_XTEXT (serv->gui->rawlog_textlist)->buffer, new_text, strlen (new_text));
+		gtk_xtext_append (GTK_XTEXT (serv->gui->rawlog_textlist)->buffer, new_text, strlen (new_text), 0);
 
 		g_free (new_text);
 	}
diff --git a/src/fe-gtk/servlistgui.c b/src/fe-gtk/servlistgui.c
index f43a225a..f7909f72 100644
--- a/src/fe-gtk/servlistgui.c
+++ b/src/fe-gtk/servlistgui.c
@@ -90,7 +90,7 @@ static GtkWidget *servlist_open_edit (GtkWidget *parent, ircnet *net);
 static const char *pages[]=
 {
 	IRC_DEFAULT_CHARSET,
-	"IRC (Latin/Unicode Hybrid)",
+	"CP1252 (Windows-1252)",
 	"ISO-8859-15 (Western Europe)",
 	"ISO-8859-2 (Central Europe)",
 	"ISO-8859-7 (Greek)",
@@ -497,7 +497,7 @@ servlist_addnet_cb (GtkWidget *item, GtkTreeView *treeview)
 	ircnet *net;
 
 	net = servlist_net_add (_("New Network"), "", TRUE);
-	net->encoding = strdup (IRC_DEFAULT_CHARSET);
+	net->encoding = g_strdup (IRC_DEFAULT_CHARSET);
 	servlist_server_add (net, "newserver/6667");
 
 	store = (GtkListStore *)gtk_tree_view_get_model (treeview);
@@ -668,13 +668,12 @@ servlist_favor (GtkWidget *button, gpointer none)
 static void
 servlist_update_from_entry (char **str, GtkWidget *entry)
 {
-	if (*str)
-		free (*str);
+	g_free (*str);
 
 	if (gtk_entry_get_text (GTK_ENTRY (entry))[0] == 0)
 		*str = NULL;
 	else
-		*str = strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+		*str = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
 }
 
 static void
@@ -960,10 +959,10 @@ servlist_savegui (void)
 	if (!rfc_casecmp (nick1, nick2))
 		return 2;
 
-	strcpy (prefs.hex_irc_nick1, nick1);
-	strcpy (prefs.hex_irc_nick2, nick2);
-	strcpy (prefs.hex_irc_nick3, gtk_entry_get_text (GTK_ENTRY (entry_nick3)));
-	strcpy (prefs.hex_irc_user_name, gtk_entry_get_text (GTK_ENTRY (entry_guser)));
+	safe_strcpy (prefs.hex_irc_nick1, nick1, sizeof(prefs.hex_irc_nick1));
+	safe_strcpy (prefs.hex_irc_nick2, nick2, sizeof(prefs.hex_irc_nick2));
+	safe_strcpy (prefs.hex_irc_nick3, gtk_entry_get_text (GTK_ENTRY (entry_nick3)), sizeof(prefs.hex_irc_nick3));
+	safe_strcpy (prefs.hex_irc_user_name, gtk_entry_get_text (GTK_ENTRY (entry_guser)), sizeof(prefs.hex_irc_user_name));
 	sp = strchr (prefs.hex_irc_user_name, ' ');
 	if (sp)
 		sp[0] = 0;	/* spaces will break the login */
@@ -1203,9 +1202,9 @@ servlist_celledit_cb (GtkCellRendererText *cell, gchar *arg1, gchar *arg2,
 		}
 
 		netname = net->name;
-		net->name = strdup (arg2);
+		net->name = g_strdup (arg2);
 		gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, net->name, -1);
-		free (netname);
+		g_free (netname);
 	}
 
 	gtk_tree_path_free (path);
@@ -1311,7 +1310,7 @@ servlist_sanitize_hostname (char *host)
 {
 	char *ret, *c, *e;
 
-	ret = strdup (host);
+	ret = g_strdup (host);
 
 	c = strchr  (ret, ':');
 	e = strrchr (ret, ':');
@@ -1371,7 +1370,7 @@ servlist_editserver_cb (GtkCellRendererText *cell, gchar *name, gchar *newval, g
 		servname = serv->hostname;
 		serv->hostname = servlist_sanitize_hostname (newval);
 		gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, serv->hostname, -1);
-		free (servname);
+		g_free (servname);
 	}
 }
 
@@ -1409,7 +1408,7 @@ servlist_editcommand_cb (GtkCellRendererText *cell, gchar *name, gchar *newval,
 		cmd = entry->command;
 		entry->command = servlist_sanitize_command (newval);
 		gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, entry->command, -1);
-		free (cmd);
+		g_free (cmd);
 	}
 }
 
@@ -1508,9 +1507,8 @@ servlist_combo_cb (GtkEntry *entry, gpointer userdata)
 	if (!selected_net)
 		return;
 
-	if (selected_net->encoding)
-		free (selected_net->encoding);
-	selected_net->encoding = strdup (gtk_entry_get_text (entry));
+	g_free (selected_net->encoding);
+	selected_net->encoding = g_strdup (gtk_entry_get_text (entry));
 }
 
 /* Fills up the network's authentication type so that it's guaranteed to be either NULL or a valid value. */
@@ -1594,7 +1592,6 @@ servlist_create_charsetcombo (void)
 	int i;
 
 	cb = gtk_combo_box_text_new_with_entry ();
-	gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cb), "System default");
 	i = 0;
 	while (pages[i])
 	{
@@ -1602,7 +1599,7 @@ servlist_create_charsetcombo (void)
 		i++;
 	}
 
-	gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN(cb))), selected_net->encoding ? selected_net->encoding : "System default");
+	gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN(cb))), selected_net->encoding ? selected_net->encoding : pages[0]);
 	
 	g_signal_connect (G_OBJECT (gtk_bin_get_child (GTK_BIN (cb))), "changed",
 							G_CALLBACK (servlist_combo_cb), NULL);
@@ -1660,7 +1657,7 @@ bold_label (char *text)
 	char buf[128];
 	GtkWidget *label;
 
-	snprintf (buf, sizeof (buf), "<b>%s</b>", text);
+	g_snprintf (buf, sizeof (buf), "<b>%s</b>", text);
 	label = gtk_label_new (buf);
 	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
 	gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
@@ -1702,7 +1699,7 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
 
 	editwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 	gtk_container_set_border_width (GTK_CONTAINER (editwindow), 4);
-	snprintf (buf, sizeof (buf), _(DISPLAY_NAME": Edit %s"), net->name);
+	g_snprintf (buf, sizeof (buf), _(DISPLAY_NAME": Edit %s"), net->name);
 	gtk_window_set_title (GTK_WINDOW (editwindow), buf);
 	gtk_window_set_default_size (GTK_WINDOW (editwindow), netedit_win_width, netedit_win_height);
 	gtk_window_set_transient_for (GTK_WINDOW (editwindow), GTK_WINDOW (parent));
diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c
index e4372dc9..dc469591 100644
--- a/src/fe-gtk/setup.c
+++ b/src/fe-gtk/setup.c
@@ -36,6 +36,7 @@
 #include "pixmaps.h"
 #include "menu.h"
 #include "plugin-tray.h"
+#include "notifications/notification-backend.h"
 
 #ifdef WIN32
 #include "../common/fe.h"
@@ -314,6 +315,7 @@ static const setting tabs_settings[] =
 	{ST_TOGGLE, N_("Show icons in the channel tree"), P_OFFINTNL(hex_gui_tab_icons), 0, 0, 0},
 	{ST_TOGGLE, N_("Show dotted lines in the channel tree"), P_OFFINTNL(hex_gui_tab_dots), 0, 0, 0},
 	{ST_TOGGLE, N_("Scroll mouse-wheel to change tabs"), P_OFFINTNL (hex_gui_tab_scrollchans), 0, 0, 0},
+	{ST_TOGGLE, N_("Middle click to close tab"), P_OFFINTNL(hex_gui_tab_middleclose), 0, 0, 0},
 	{ST_TOGGLE, N_("Smaller text"), P_OFFINTNL(hex_gui_tab_small), 0, 0, 0},
 	{ST_MENU,	N_("Focus new tabs:"), P_OFFINTNL(hex_gui_tab_newtofront), 0, focusnewtabsmenu, 0},
 	{ST_MENU,	N_("Placement of notices:"), P_OFFINTNL(hex_irc_notice_pos), 0, noticeposmenu, 0},
@@ -396,9 +398,47 @@ static const setting alert_settings[] =
 	{ST_HEADER,	N_("Alerts"),0,0,0},
 
 	{ST_ALERTHEAD},
-#if !defined (WIN32) && !defined (__APPLE__)
-	{ST_3OGGLE, N_("Show tray balloons on:"), 0, 0, (void *)balloonlist, 0},
+
+
+	{ST_3OGGLE, N_("Show notifications on:"), 0, 0, (void *)balloonlist, 0},
+	{ST_3OGGLE, N_("Blink tray icon on:"), 0, 0, (void *)trayblinklist, 0},
+	{ST_3OGGLE, N_("Blink task bar on:"), 0, 0, (void *)taskbarlist, 0},
+#ifdef WIN32
+	{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play the \"Instant Message Notification\" system sound upon the selected events"), (void *)beeplist, 0},
+#else
+#ifdef USE_LIBCANBERRA
+	{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play \"message-new-instant\" from the freedesktop.org sound theme upon the selected events"), (void *)beeplist, 0},
+#else
+	{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play a GTK beep upon the selected events"), (void *)beeplist, 0},
 #endif
+#endif
+
+	{ST_TOGGLE,	N_("Omit alerts when marked as being away"), P_OFFINTNL(hex_away_omit_alerts), 0, 0, 0},
+	{ST_TOGGLE,	N_("Omit alerts while the window is focused"), P_OFFINTNL(hex_gui_focus_omitalerts), 0, 0, 0},
+
+	{ST_HEADER,	N_("Tray Behavior"), 0, 0, 0},
+	{ST_TOGGLE,	N_("Enable system tray icon"), P_OFFINTNL(hex_gui_tray), 0, 0, 4},
+	{ST_TOGGLE,	N_("Minimize to tray"), P_OFFINTNL(hex_gui_tray_minimize), 0, 0, 0},
+	{ST_TOGGLE,	N_("Close to tray"), P_OFFINTNL(hex_gui_tray_close), 0, 0, 0},
+	{ST_TOGGLE,	N_("Automatically mark away/back"), P_OFFINTNL(hex_gui_tray_away), N_("Automatically change status when hiding to tray."), 0, 0},
+	{ST_TOGGLE,	N_("Only show notifications when hidden or iconified"), P_OFFINTNL(hex_gui_tray_quiet), 0, 0, 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(hex_irc_extra_hilight), 0, 0, sizeof prefs.hex_irc_extra_hilight},
+	{ST_ENTRY,	N_("Nick names not to highlight:"), P_OFFSETNL(hex_irc_no_hilight), 0, 0, sizeof prefs.hex_irc_no_hilight},
+	{ST_ENTRY,	N_("Nick names to always highlight:"), P_OFFSETNL(hex_irc_nick_hilight), 0, 0, sizeof prefs.hex_irc_nick_hilight},
+	{ST_LABEL,	N_("Separate multiple words with commas.\nWildcards are accepted.")},
+
+	{ST_END, 0, 0, 0, 0, 0}
+};
+
+static const setting alert_settings_nonotifications[] =
+{
+	{ST_HEADER,	N_("Alerts"),0,0,0},
+
+	{ST_ALERTHEAD},
 	{ST_3OGGLE, N_("Blink tray icon on:"), 0, 0, (void *)trayblinklist, 0},
 #ifdef HAVE_GTK_MAC
 	{ST_3OGGLE, N_("Bounce dock icon on:"), 0, 0, (void *)taskbarlist, 0},
@@ -421,17 +461,10 @@ static const setting alert_settings[] =
 	{ST_TOGGLE,	N_("Omit alerts while the window is focused"), P_OFFINTNL(hex_gui_focus_omitalerts), 0, 0, 0},
 
 	{ST_HEADER,	N_("Tray Behavior"), 0, 0, 0},
-#ifdef WIN32
-	{ST_TOGGLE,	N_("Enable system tray icon"), P_OFFINTNL(hex_gui_tray), 0, 0, 3},
-#else
 	{ST_TOGGLE,	N_("Enable system tray icon"), P_OFFINTNL(hex_gui_tray), 0, 0, 4},
-#endif
 	{ST_TOGGLE,	N_("Minimize to tray"), P_OFFINTNL(hex_gui_tray_minimize), 0, 0, 0},
 	{ST_TOGGLE,	N_("Close to tray"), P_OFFINTNL(hex_gui_tray_close), 0, 0, 0},
 	{ST_TOGGLE,	N_("Automatically mark away/back"), P_OFFINTNL(hex_gui_tray_away), N_("Automatically change status when hiding to tray."), 0, 0},
-#ifndef WIN32
-	{ST_TOGGLE,	N_("Only show tray balloons when hidden or iconified"), P_OFFINTNL(hex_gui_tray_quiet), 0, 0, 0},
-#endif
 
 	{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},
@@ -449,7 +482,7 @@ static const setting alert_settings_unity[] =
 	{ST_HEADER,	N_("Alerts"),0,0,0},
 
 	{ST_ALERTHEAD},
-	{ST_3OGGLE, N_("Show tray balloons on:"), 0, 0, (void *)balloonlist, 0},
+	{ST_3OGGLE, N_("Show notifications on:"), 0, 0, (void *)balloonlist, 0},
 	{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},
 
@@ -467,6 +500,28 @@ static const setting alert_settings_unity[] =
 	{ST_END, 0, 0, 0, 0, 0}
 };
 
+static const setting alert_settings_unityandnonotifications[] =
+{
+	{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_TOGGLE, N_("Omit alerts when marked as being away"), P_OFFINTNL (hex_away_omit_alerts), 0, 0, 0},
+	{ST_TOGGLE, N_("Omit alerts while the window is focused"), P_OFFINTNL (hex_gui_focus_omitalerts), 0, 0, 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 (hex_irc_extra_hilight), 0, 0, sizeof prefs.hex_irc_extra_hilight},
+	{ST_ENTRY, N_("Nick names not to highlight:"), P_OFFSETNL (hex_irc_no_hilight), 0, 0, sizeof prefs.hex_irc_no_hilight},
+	{ST_ENTRY, N_("Nick names to always highlight:"), P_OFFSETNL (hex_irc_nick_hilight), 0, 0, sizeof prefs.hex_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},
@@ -559,9 +614,6 @@ static const char *const proxytypes[] =
 	N_("Socks4"),
 	N_("Socks5"),
 	N_("HTTP"),
-#ifdef USE_MSPROXY
-	N_("MS Proxy (ISA)"),
-#endif
 #ifdef USE_LIBPROXY
 	N_("Auto"),
 #endif
@@ -598,11 +650,7 @@ static const setting network_settings[] =
 	{ST_MENU,	N_("Use proxy for:"), P_OFFINTNL(hex_net_proxy_use), 0, proxyuse, 0},
 
 	{ST_HEADER,	N_("Proxy Authentication"), 0, 0, 0, 0},
-#ifdef USE_MSPROXY
-	{ST_TOGGLE,	N_("Use Authentication (MS Proxy, HTTP or Socks5 only)"), P_OFFINTNL(hex_net_proxy_auth), 0, 0, 0},
-#else
 	{ST_TOGGLE,	N_("Use Authentication (HTTP or Socks5 only)"), P_OFFINTNL(hex_net_proxy_auth), 0, 0, 0},
-#endif
 	{ST_ENTRY,	N_("Username:"), P_OFFSETNL(hex_net_proxy_user), 0, 0, sizeof prefs.hex_net_proxy_user},
 	{ST_ENTRY,	N_("Password:"), P_OFFSETNL(hex_net_proxy_pass), 0, GINT_TO_POINTER(1), sizeof prefs.hex_net_proxy_pass},
 
@@ -630,7 +678,7 @@ setup_headlabel (GtkWidget *tab, int row, int col, char *text)
 	char buf[128];
 	char *sp;
 
-	snprintf (buf, sizeof (buf), "<b><span size=\"smaller\">%s</span></b>", text);
+	g_snprintf (buf, sizeof (buf), "<b><span size=\"smaller\">%s</span></b>", text);
 	sp = strchr (buf + 17, ' ');
 	if (sp)
 		*sp = '\n';
@@ -752,7 +800,7 @@ setup_create_italic_label (char *text)
 	char buf[256];
 
 	label = gtk_label_new (NULL);
-	snprintf (buf, sizeof (buf), "<i><span size=\"smaller\">%s</span></i>", text);
+	g_snprintf (buf, sizeof (buf), "<i><span size=\"smaller\">%s</span></i>", text);
 	gtk_label_set_markup (GTK_LABEL (label), buf);
 	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
 
@@ -1121,8 +1169,8 @@ setup_entry_cb (GtkEntry *entry, setting *set)
 {
 	int size;
 	int pos;
-	int len = gtk_entry_get_text_length (entry);
 	unsigned char *p = (unsigned char*)gtk_entry_get_text (entry);
+	int len = strlen (p);
 
 	/* need to truncate? */
 	if (len >= set->extra)
@@ -1220,9 +1268,9 @@ setup_create_header (GtkWidget *table, int row, char *labeltext)
 	char buf[128];
 
 	if (row == 0)
-		snprintf (buf, sizeof (buf), "<b>%s</b>", _(labeltext));
+		g_snprintf (buf, sizeof (buf), "<b>%s</b>", _(labeltext));
 	else
-		snprintf (buf, sizeof (buf), "\n<b>%s</b>", _(labeltext));
+		g_snprintf (buf, sizeof (buf), "\n<b>%s</b>", _(labeltext));
 
 	label = gtk_label_new (NULL);
 	gtk_label_set_markup (GTK_LABEL (label), buf);
@@ -1683,9 +1731,8 @@ setup_snd_changed_cb (GtkEntry *ent, GtkTreeView *tree)
 		return;
 
 	/* get the new sound file */
-	if (sound_files[n])
-		free (sound_files[n]);
-	sound_files[n] = strdup (gtk_entry_get_text (GTK_ENTRY (ent)));
+	g_free (sound_files[n]);
+	sound_files[n] = g_strdup (gtk_entry_get_text (GTK_ENTRY (ent)));
 
 	/* update the TreeView list */
 	store = (GtkListStore *)gtk_tree_view_get_model (tree);
@@ -1790,7 +1837,7 @@ setup_add_page (const char *title, GtkWidget *book, GtkWidget *tab)
 
 	/* label */
 	label = gtk_label_new (NULL);
-	snprintf (buf, sizeof (buf), "<b><big>%s</big></b>", _(title));
+	g_snprintf (buf, sizeof (buf), "<b><big>%s</big></b>", _(title));
 	gtk_label_set_markup (GTK_LABEL (label), buf);
 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 	gtk_misc_set_padding (GTK_MISC (label), 2, 1);
@@ -1839,10 +1886,18 @@ setup_create_pages (GtkWidget *box)
 
 	setup_add_page (cata[8], book, setup_create_page (general_settings));
 
-	if (unity_mode ())
+	if (unity_mode () && !notification_backend_supported ())
+	{
+		setup_add_page (cata[9], book, setup_create_page (alert_settings_unityandnonotifications));
+	}
+	else if (unity_mode ())
 	{
 		setup_add_page (cata[9], book, setup_create_page (alert_settings_unity));
 	}
+	else if (!notification_backend_supported ())
+	{
+		setup_add_page (cata[9], book, setup_create_page (alert_settings_nonotifications));
+	}
 	else
 	{
 		setup_add_page (cata[9], book, setup_create_page (alert_settings));
@@ -2121,6 +2176,8 @@ setup_apply (struct hexchatprefs *pr)
 		noapply = TRUE;
 	if (DIFF (hex_gui_ulist_style))
 		noapply = TRUE;
+	if (DIFF (hex_gui_ulist_sort))
+		noapply = TRUE;
 
 	if (DIFF (hex_gui_tab_dots))
 		do_layout = TRUE;
@@ -2137,6 +2194,13 @@ setup_apply (struct hexchatprefs *pr)
 						" menu first."),
 						FE_MSG_WARN | FE_MSG_MARKUP);
 
+	/* format cannot be blank, there is already a setting for this */
+	if (pr->hex_stamp_text_format[0] == 0)
+	{
+		pr->hex_stamp_text = 0;
+		strcpy (pr->hex_stamp_text_format, prefs.hex_stamp_text_format);
+	}
+
 	memcpy (&prefs, pr, sizeof (prefs));
 
 #ifdef WIN32
diff --git a/src/fe-gtk/sexy-iso-codes.c b/src/fe-gtk/sexy-iso-codes.c
index e6acb726..06c8cd07 100644
--- a/src/fe-gtk/sexy-iso-codes.c
+++ b/src/fe-gtk/sexy-iso-codes.c
@@ -19,10 +19,11 @@
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
+#include "config.h"
+
 #include "sexy-iso-codes.h"
 #include <libintl.h>
 #include <string.h>
-#include "../../config.h"
 
 #define ISO_639_DOMAIN	"iso_639"
 #define ISO_3166_DOMAIN	"iso_3166"
diff --git a/src/fe-gtk/sexy-spell-entry.c b/src/fe-gtk/sexy-spell-entry.c
index bac1e2b5..f57c7f41 100644
--- a/src/fe-gtk/sexy-spell-entry.c
+++ b/src/fe-gtk/sexy-spell-entry.c
@@ -31,7 +31,12 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "sexy-iso-codes.h"
+
+#ifdef WIN32
+#include "marshal.h"
+#else
 #include "../common/marshal.h"
+#endif
 
 #ifdef WIN32
 #include "../common/typedef.h"
@@ -136,6 +141,8 @@ enum
 };
 static guint signals[LAST_SIGNAL] = {0};
 
+static PangoAttrList *empty_attrs_list = NULL;
+
 static gboolean
 spell_accumulator(GSignalInvocationHint *hint, GValue *return_accu, const GValue *handler_return, gpointer data)
 {
@@ -243,6 +250,11 @@ sexy_spell_entry_class_init(SexySpellEntryClass *klass)
 					   _hexchat_marshal_BOOLEAN__STRING,
 					   G_TYPE_BOOLEAN,
 					   1, G_TYPE_STRING);
+
+	if (empty_attrs_list == NULL)
+	{
+		empty_attrs_list = pango_attr_list_new ();
+	}
 }
 
 static void
@@ -292,7 +304,7 @@ insert_hiddenchar (SexySpellEntry *entry, guint start, guint end)
 	 * is 'hidden' */
 #if 0
 	PangoAttribute *hattr;
-	PangoRectangle *rect = g_malloc (sizeof (PangoRectangle));
+	PangoRectangle *rect = g_new (PangoRectangle, 1);
 
 	rect->x = 0;
 	rect->y = 0;
@@ -758,12 +770,9 @@ sexy_spell_entry_finalize(GObject *obj)
 		pango_attr_list_unref(entry->priv->attr_list);
 	if (entry->priv->dict_hash)
 		g_hash_table_destroy(entry->priv->dict_hash);
-	if (entry->priv->words)
-		g_strfreev(entry->priv->words);
-	if (entry->priv->word_starts)
-		g_free(entry->priv->word_starts);
-	if (entry->priv->word_ends)
-		g_free(entry->priv->word_ends);
+	g_strfreev(entry->priv->words);
+	g_free(entry->priv->word_starts);
+	g_free(entry->priv->word_ends);
 
 	if (have_enchant) {
 		if (entry->priv->broker) {
@@ -1038,7 +1047,7 @@ sexy_spell_entry_recheck_all(SexySpellEntry *entry)
 	{
 		/* Check for attributes */
 		text = gtk_entry_get_text (GTK_ENTRY (entry));
-		text_len = gtk_entry_get_text_length (GTK_ENTRY (entry));
+		text_len = strlen (text);
 		check_attributes (entry, text, text_len);
 	}
 
@@ -1078,7 +1087,14 @@ sexy_spell_entry_expose(GtkWidget *widget, GdkEventExpose *event)
 
 	
 	layout = gtk_entry_get_layout(gtk_entry);
-	pango_layout_set_attributes(layout, entry->priv->attr_list);
+	if (gtk_entry->preedit_length == 0)
+	{
+		pango_layout_set_attributes(layout, entry->priv->attr_list);
+	}
+	else
+	{
+		pango_layout_set_attributes(layout, empty_attrs_list);
+	}
 
 	return GTK_WIDGET_CLASS(parent_class)->expose_event (widget, event);
 }
diff --git a/src/fe-gtk/textgui.c b/src/fe-gtk/textgui.c
index 9956e9c6..b0f2f392 100644
--- a/src/fe-gtk/textgui.c
+++ b/src/fe-gtk/textgui.c
@@ -81,14 +81,14 @@ PrintTextLine (xtext_buffer *xtbuf, unsigned char *text, int len, int indent, ti
 				timet = time (0);
 
 			stamp_size = get_stamp_str (prefs.hex_stamp_text_format, timet, &stamp);
-			new_text = malloc (len + stamp_size + 1);
+			new_text = g_malloc (len + stamp_size + 1);
 			memcpy (new_text, stamp, stamp_size);
 			g_free (stamp);
 			memcpy (new_text + stamp_size, text, len);
-			gtk_xtext_append (xtbuf, new_text, len + stamp_size);
-			free (new_text);
+			gtk_xtext_append (xtbuf, new_text, len + stamp_size, timet);
+			g_free (new_text);
 		} else
-			gtk_xtext_append (xtbuf, text, len);
+			gtk_xtext_append (xtbuf, text, len, timet);
 		return;
 	}
 
@@ -173,13 +173,12 @@ pevent_edited (GtkCellRendererText *render, gchar *pathstr, gchar *new_text, gpo
 	}
 	if (m > (te[sig].num_args & 0x7f))
 	{
-		free (out);
-		out = malloc (4096);
-		snprintf (out, 4096,
-					_("This signal is only passed %d args, $%d is invalid"),
-					te[sig].num_args & 0x7f, m);
+		g_free (out);
+		out = g_strdup_printf (
+			_("This signal is only passed %d args, $%d is invalid"),
+			te[sig].num_args & 0x7f, m);
 		fe_message (out, FE_MSG_WARN);
-		free (out);
+		g_free (out);
 		return;
 	}
 
@@ -188,23 +187,20 @@ pevent_edited (GtkCellRendererText *render, gchar *pathstr, gchar *new_text, gpo
 	gtk_list_store_set (GTK_LIST_STORE (model), &iter, TEXT_COLUMN, new_text, -1);
 	gtk_tree_path_free (path);
 
-	if (pntevts_text[sig])
-		free (pntevts_text[sig]);
-	if (pntevts[sig])
-		free (pntevts[sig]);
+	g_free (pntevts_text[sig]);
+	g_free (pntevts[sig]);
 
-	pntevts_text[sig] = malloc (len + 1);
-	memcpy (pntevts_text[sig], text, len + 1);
+	pntevts_text[sig] = g_strdup (text);
 	pntevts[sig] = out;
 
-	out = malloc (len + 2);
+	out = g_malloc (len + 2);
 	memcpy (out, text, len + 1);
 	out[len] = '\n';
 	out[len + 1] = 0;
 	check_special_chars (out, TRUE);
 
 	PrintTextRaw (xtext->buffer, out, 0, 0);
-	free (out);
+	g_free (out);
 
 	/* Scroll to bottom */
 	gtk_adjustment_set_value (xtext->adj, gtk_adjustment_get_upper (xtext->adj));
@@ -328,14 +324,14 @@ pevent_test_cb (GtkWidget * wid, GtkWidget * twid)
 		text = _(pntevts_text[n]);
 		len = strlen (text);
 
-		out = malloc (len + 2);
+		out = g_malloc (len + 2);
 		memcpy (out, text, len + 1);
 		out[len] = '\n';
 		out[len + 1] = 0;
 		check_special_chars (out, TRUE);
 
 		PrintTextRaw (GTK_XTEXT (twid)->buffer, out, 0, 0);
-		free (out);
+		g_free (out);
 	}
 }
 
diff --git a/src/fe-gtk/userlistgui.c b/src/fe-gtk/userlistgui.c
index 19564ece..d06975ca 100644
--- a/src/fe-gtk/userlistgui.c
+++ b/src/fe-gtk/userlistgui.c
@@ -42,11 +42,11 @@
 
 enum
 {
-	COL_PIX=0,		// GdkPixbuf *
-	COL_NICK=1,		// char *
-	COL_HOST=2,		// char *
-	COL_USER=3,		// struct User *
-	COL_GDKCOLOR=4	// GdkColor *
+	COL_PIX=0,		/* GdkPixbuf * */
+	COL_NICK=1,		/* char * */
+	COL_HOST=2,		/* char * */
+	COL_USER=3,		/* struct User * */
+	COL_GDKCOLOR=4	/* GdkColor * */
 };
 
 
@@ -105,7 +105,7 @@ fe_userlist_numbers (session *sess)
 	{
 		if (sess->total)
 		{
-			snprintf (tbuf, sizeof (tbuf), _("%d ops, %d total"), sess->ops, sess->total);
+			g_snprintf (tbuf, sizeof (tbuf), _("%d ops, %d total"), sess->ops, sess->total);
 			tbuf[sizeof (tbuf) - 1] = 0;
 			gtk_label_set_text (GTK_LABEL (sess->gui->namelistinfo), tbuf);
 		} else
@@ -188,7 +188,7 @@ userlist_selection_list (GtkWidget *widget, int *num_ret)
 	if (num_sel < 1)
 		return NULL;
 
-	nicks = malloc (sizeof (char *) * (num_sel + 1));
+	nicks = g_new (char *, num_sel + 1);
 
 	i = 0;
 	gtk_tree_model_get_iter_first (model, &iter);
@@ -286,7 +286,7 @@ fe_userlist_remove (session *sess, struct User *user)
 	int sel;
 
 	iter = find_row (GTK_TREE_VIEW (sess->gui->user_tree),
-						  sess->res->user_model, user, &sel);
+						  GTK_TREE_MODEL(sess->res->user_model), user, &sel);
 	if (!iter)
 		return 0;
 
@@ -316,7 +316,7 @@ fe_userlist_rehash (session *sess, struct User *user)
 	int nick_color = 0;
 
 	iter = find_row (GTK_TREE_VIEW (sess->gui->user_tree),
-						  sess->res->user_model, user, &sel);
+						  GTK_TREE_MODEL(sess->res->user_model), user, &sel);
 	if (!iter)
 		return;
 
@@ -332,9 +332,9 @@ fe_userlist_rehash (session *sess, struct User *user)
 }
 
 void
-fe_userlist_insert (session *sess, struct User *newuser, int row, int sel)
+fe_userlist_insert (session *sess, struct User *newuser, gboolean sel)
 {
-	GtkTreeModel *model = sess->res->user_model;
+	GtkTreeModel *model = GTK_TREE_MODEL(sess->res->user_model);
 	GdkPixbuf *pix = get_user_icon (sess->server, newuser);
 	GtkTreeIter iter;
 	char *nick;
@@ -348,16 +348,16 @@ fe_userlist_insert (session *sess, struct User *newuser, int row, int sel)
 	nick = newuser->nick;
 	if (!prefs.hex_gui_ulist_icons)
 	{
-		nick = malloc (strlen (newuser->nick) + 2);
+		nick = g_malloc (strlen (newuser->nick) + 2);
 		nick[0] = newuser->prefix[0];
-		if (!nick[0] || nick[0] == ' ')
+		if (nick[0] == '\0' || nick[0] == ' ')
 			strcpy (nick, newuser->nick);
 		else
 			strcpy (nick + 1, newuser->nick);
 		pix = NULL;
 	}
 
-	gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter, row,
+	gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter, 0,
 									COL_PIX, pix,
 									COL_NICK, nick,
 									COL_HOST, newuser->hostname,
@@ -367,7 +367,7 @@ fe_userlist_insert (session *sess, struct User *newuser, int row, int sel)
 
 	if (!prefs.hex_gui_ulist_icons)
 	{
-		free (nick);
+		g_free (nick);
 	}
 
 	/* is it me? */
@@ -377,14 +377,6 @@ fe_userlist_insert (session *sess, struct User *newuser, int row, int sel)
 			mg_set_access_icon (sess->gui, pix, sess->server->is_away);
 	}
 
-#if 0
-	if (prefs.hilitenotify && notify_isnotify (sess, newuser->nick))
-	{
-		gtk_clist_set_foreground ((GtkCList *) sess->gui->user_clist, row,
-										  &colors[prefs.nu_color]);
-	}
-#endif
-
 	/* is it the front-most tab? */
 	if (gtk_tree_view_get_model (GTK_TREE_VIEW (sess->gui->user_tree))
 		 == model)
@@ -396,12 +388,6 @@ fe_userlist_insert (session *sess, struct User *newuser, int row, int sel)
 }
 
 void
-fe_userlist_move (session *sess, struct User *user, int new_row)
-{
-	fe_userlist_insert (sess, user, new_row, fe_userlist_remove (sess, user));
-}
-
-void
 fe_userlist_clear (session *sess)
 {
 	gtk_list_store_clear (sess->res->user_model);
@@ -459,11 +445,67 @@ userlist_dnd_leave (GtkTreeView *widget, GdkDragContext *context, guint ttime)
 	return TRUE;
 }
 
-void *
-userlist_create_model (void)
+static int
+userlist_alpha_cmp (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer userdata)
+{
+	struct User *user_a, *user_b;
+
+	gtk_tree_model_get (model, iter_a, COL_USER, &user_a, -1);
+	gtk_tree_model_get (model, iter_b, COL_USER, &user_b, -1);
+
+	return nick_cmp_alpha (user_a, user_b, ((session*)userdata)->server);
+}
+
+static int
+userlist_ops_cmp (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer userdata)
 {
-	return gtk_list_store_new (5, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING,
+	struct User *user_a, *user_b;
+
+	gtk_tree_model_get (model, iter_a, COL_USER, &user_a, -1);
+	gtk_tree_model_get (model, iter_b, COL_USER, &user_b, -1);
+
+	return nick_cmp_az_ops (((session*)userdata)->server, user_a, user_b);
+}
+
+GtkListStore *
+userlist_create_model (session *sess)
+{
+	GtkListStore *store;
+	GtkTreeIterCompareFunc cmp_func;
+	GtkSortType sort_type;
+
+	store = gtk_list_store_new (5, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING,
 										G_TYPE_POINTER, GDK_TYPE_COLOR);
+
+	switch (prefs.hex_gui_ulist_sort)
+	{
+	case 0:
+		cmp_func = userlist_ops_cmp;
+		sort_type = GTK_SORT_ASCENDING;
+		break;
+	case 1:
+		cmp_func = userlist_alpha_cmp;
+		sort_type = GTK_SORT_ASCENDING;
+		break;
+	case 2:
+		cmp_func = userlist_ops_cmp;
+		sort_type = GTK_SORT_DESCENDING;
+		break;
+	case 3:
+		cmp_func = userlist_alpha_cmp;
+		sort_type = GTK_SORT_DESCENDING;
+		break;
+	default:
+		/* No sorting */
+		gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE(store), NULL, NULL, NULL);
+		return store;
+	}
+
+	gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE(store), cmp_func, sess, NULL);
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
+						GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, sort_type);
+
+	return store;
 }
 
 static void
@@ -525,7 +567,7 @@ userlist_click_cb (GtkWidget *widget, GdkEventButton *event, gpointer userdata)
 				i--;
 				g_free (nicks[i]);
 			}
-			free (nicks);
+			g_free (nicks);
 		}
 		return TRUE;
 	}
@@ -542,13 +584,13 @@ userlist_click_cb (GtkWidget *widget, GdkEventButton *event, gpointer userdata)
 				i--;
 				g_free (nicks[i]);
 			}
-			free (nicks);
+			g_free (nicks);
 			return TRUE;
 		}
 		if (nicks)
 		{
 			g_free (nicks[0]);
-			free (nicks);
+			g_free (nicks);
 		}
 
 		sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
@@ -567,7 +609,7 @@ userlist_click_cb (GtkWidget *widget, GdkEventButton *event, gpointer userdata)
 					i--;
 					g_free (nicks[i]);
 				}
-				free (nicks);
+				g_free (nicks);
 			}
 		} else
 		{
@@ -668,7 +710,7 @@ void
 userlist_show (session *sess)
 {
 	gtk_tree_view_set_model (GTK_TREE_VIEW (sess->gui->user_tree),
-									 sess->res->user_model);
+									 GTK_TREE_MODEL(sess->res->user_model));
 }
 
 void
diff --git a/src/fe-gtk/userlistgui.h b/src/fe-gtk/userlistgui.h
index 993fe8f0..e24f2ebc 100644
--- a/src/fe-gtk/userlistgui.h
+++ b/src/fe-gtk/userlistgui.h
@@ -23,7 +23,7 @@
 void userlist_set_value (GtkWidget *treeview, gfloat val);
 gfloat userlist_get_value (GtkWidget *treeview);
 GtkWidget *userlist_create (GtkWidget *box);
-void *userlist_create_model (void);
+GtkListStore *userlist_create_model (session *sess);
 void userlist_show (session *sess);
 void userlist_select (session *sess, char *name);
 char **userlist_selection_list (GtkWidget *widget, int *num_ret);
diff --git a/src/fe-gtk/xtext.c b/src/fe-gtk/xtext.c
index 6a499f52..6692b360 100644
--- a/src/fe-gtk/xtext.c
+++ b/src/fe-gtk/xtext.c
@@ -31,13 +31,19 @@
 #include <stdlib.h>
 #include <time.h>
 
-#include "../../config.h"
+#include "config.h"
 #include "../common/hexchat.h"
 #include "../common/fe.h"
 #include "../common/util.h"
 #include "../common/hexchatc.h"
 #include "../common/url.h"
+
+#ifdef WIN32
+#include "marshal.h"
+#else
 #include "../common/marshal.h"
+#endif
+
 #include "fe-gtk.h"
 #include "xtext.h"
 #include "fkeys.h"
@@ -484,7 +490,10 @@ gtk_xtext_adjustment_set (xtext_buffer *buf, int fire_signal)
 		adj->page_increment = adj->page_size;
 
 		if (adj->value > adj->upper - adj->page_size)
+		{
+			buf->scrollbar_down = TRUE;
 			adj->value = adj->upper - adj->page_size;
+		}
 
 		if (adj->value < 0)
 			adj->value = 0;
@@ -829,7 +838,6 @@ find_x (GtkXText *xtext, textentry *ent, int x, int subline, int indent)
 	int off, len, wid, mbl, mbw;
 
 	/* Skip to the first chunk of stuff for the subline */
-	list = ent->slp;
 	if (subline > 0)
 	{
 		suboff = GPOINTER_TO_INT (g_slist_nth_data (ent->sublines, subline - 1));
@@ -846,6 +854,8 @@ find_x (GtkXText *xtext, textentry *ent, int x, int subline, int indent)
 		list = ent->slp;
 	} 
 	/* Step to the first character of the subline */
+	if (list == NULL)
+		return 0;
 	meta = list->data;
 	off = meta->off;
 	len = meta->len;
@@ -934,12 +944,12 @@ gtk_xtext_find_x (GtkXText * xtext, int x, textentry * ent, int subline,
 }
 
 static textentry *
-gtk_xtext_find_char (GtkXText * xtext, int x, int y, int *off,
-							int *out_of_bounds, int *ret_subline)
+gtk_xtext_find_char (GtkXText * xtext, int x, int y, int *off, int *out_of_bounds)
 {
 	textentry *ent;
 	int line;
 	int subline;
+	int outofbounds;
 
 	/* Adjust y value for negative rounding, double to int */
 	if (y < 0)
@@ -948,13 +958,12 @@ gtk_xtext_find_char (GtkXText * xtext, int x, int y, int *off,
 	line = (y + xtext->pixel_offset) / xtext->fontsize;
 	ent = gtk_xtext_nth (xtext, line + (int)xtext->adj->value, &subline);
 	if (!ent)
-		return 0;
+		return NULL;
 
 	if (off)
-		*off = gtk_xtext_find_x (xtext, x, ent, subline, line, out_of_bounds);
-
-	if (ret_subline)
-		*ret_subline = subline;
+		*off = gtk_xtext_find_x (xtext, x, ent, subline, line, &outofbounds);
+	if (out_of_bounds)
+		*out_of_bounds = outofbounds;
 
 	return ent;
 }
@@ -1049,14 +1058,14 @@ gtk_xtext_paint (GtkWidget *widget, GdkRectangle *area)
 		return;
 	}
 
-	ent_start = gtk_xtext_find_char (xtext, area->x, area->y, NULL, NULL, NULL);
+	ent_start = gtk_xtext_find_char (xtext, area->x, area->y, NULL, NULL);
 	if (!ent_start)
 	{
 		xtext_draw_bg (xtext, area->x, area->y, area->width, area->height);
 		goto xit;
 	}
 	ent_end = gtk_xtext_find_char (xtext, area->x + area->width,
-											 area->y + area->height, NULL, NULL, NULL);
+											 area->y + area->height, NULL, NULL);
 	if (!ent_end)
 		ent_end = xtext->buffer->text_last;
 
@@ -1244,13 +1253,14 @@ lamejump:
 		}
 	}
 	/* marking upward? */
-	else if (xtext->buffer->last_ent_end == end_ent &&
+	else if (xtext->buffer->last_ent_start != NULL &&
+				xtext->buffer->last_ent_end == end_ent &&
 				xtext->buffer->last_offset_end == end_offset)
 	{
 		ent = end_ent;
 		while (ent)
 		{
-			if (ent == start_ent)
+			if (ent == start_ent && xtext->buffer->last_ent_start)
 			{
 				gtk_xtext_selection_up (xtext, xtext->buffer->last_ent_start, ent, start_offset);
 				/*gtk_xtext_render_ents (xtext, xtext->buffer->last_ent_start, ent);*/
@@ -1299,99 +1309,104 @@ gtk_xtext_selection_draw (GtkXText * xtext, GdkEventMotion * event, gboolean ren
 	textentry *ent;
 	textentry *ent_end;
 	textentry *ent_start;
-	int offset_start;
-	int offset_end;
-	int subline_start;
-	int subline_end;
-	int oob;
-	int marking_up = FALSE;
-	int len_start;
-	int len_end;
+	int offset_start = 0;
+	int offset_end = 0;
+	textentry *low_ent, *high_ent;
+	int low_x, low_y, low_offs;
+	int high_x, high_y, high_offs, high_len;
 
-	ent_start = gtk_xtext_find_char (xtext, xtext->select_start_x, xtext->select_start_y, &offset_start, &oob, &subline_start);
-	ent_end = gtk_xtext_find_char (xtext, xtext->select_end_x, xtext->select_end_y, &offset_end, &oob, &subline_end);
+	if (xtext->buffer->text_first == NULL)
+		return;
 
-	if ((!ent_start || !ent_end) && !xtext->buffer->text_last && xtext->adj->value != xtext->buffer->old_value)
-	{
-		gtk_xtext_render_page (xtext);
+	ent_start = gtk_xtext_find_char (xtext, xtext->select_start_x, xtext->select_start_y, &offset_start, NULL);
+	ent_end = gtk_xtext_find_char (xtext, xtext->select_end_x, xtext->select_end_y, &offset_end, NULL);
+	if (ent_start == NULL && ent_end == NULL)
 		return;
-	}
 
-	if (!ent_start)
+	if	((ent_start != ent_end && xtext->select_start_y > xtext->select_end_y) || /* different entries */
+		(ent_start == ent_end && offset_start > offset_end))	/* same entry, different character offsets */
 	{
-		ent_start = xtext->buffer->text_last;
-		offset_start = ent_start->str_len;
+		/* marking up */
+		low_ent = ent_end;
+		low_x = xtext->select_end_x;
+		low_y = xtext->select_end_y;
+		low_offs = offset_end;
+		high_ent = ent_start;
+		high_x = xtext->select_start_x;
+		high_y = xtext->select_start_y;
+		high_offs = offset_start;
 	}
-
-	if (!ent_end)
+	else
 	{
-		ent_end = xtext->buffer->text_last;
-		offset_end = ent_end->str_len;
+		/* marking down */
+		low_ent = ent_start;
+		low_x = xtext->select_start_x;
+		low_y = xtext->select_start_y;
+		low_offs = offset_start;
+		high_ent = ent_end;
+		high_x = xtext->select_end_x;
+		high_y = xtext->select_end_y;
+		high_offs = offset_end;
 	}
-
-	if ((ent_start != ent_end && xtext->select_start_y > xtext->select_end_y) || /* different entries */
-		(ent_start == ent_end && subline_start > subline_end) || /* different lines */
-		(ent_start == ent_end && subline_start == subline_end && xtext->select_start_x > xtext->select_end_x)) /* marking to the left */
+	if (low_ent == NULL)
+	{
+		low_ent = xtext->buffer->text_first;
+		low_offs = 0;
+	}
+	if (high_ent == NULL)
 	{
-		marking_up = TRUE;
+		high_ent = xtext->buffer->text_last;
+		high_offs = high_ent->str_len;
 	}
 
 	/* word selection */
 	if (xtext->word_select)
 	{
 		/* a word selection cannot be started if the cursor is out of bounds in gtk_xtext_button_press */
-		gtk_xtext_get_word (xtext, xtext->select_start_x, xtext->select_start_y, NULL, &offset_start, &len_start, NULL);
+		gtk_xtext_get_word (xtext, low_x, low_y, NULL, &low_offs, NULL, NULL);
 
 		/* in case the cursor is out of bounds we keep offset_end from gtk_xtext_find_char and fix the length */
-		if (gtk_xtext_get_word (xtext, xtext->select_end_x, xtext->select_end_y, NULL, &offset_end, &len_end, NULL) == NULL)
-			len_end = offset_end == ent_end->str_len? 0: -1; /* -1 for the space, 0 if at the end */
-
-		if (!marking_up)
-			offset_end += len_end;
-		else
-			offset_start += len_start;
+		if (gtk_xtext_get_word (xtext, high_x, high_y, NULL, &high_offs, &high_len, NULL) == NULL)
+			high_len = high_offs == high_ent->str_len? 0: -1; /* -1 for the space, 0 if at the end */
+		high_offs += high_len;
+		if (low_y < 0)
+			low_offs = xtext->buffer->last_offset_start;
+		if (high_y > xtext->buffer->window_height)
+			high_offs = xtext->buffer->last_offset_end;
 	}
 	/* line/ent selection */
 	else if (xtext->line_select)
 	{
-		offset_start = marking_up? ent_start->str_len: 0;
-		offset_end = marking_up? 0: ent_end->str_len;
+		low_offs = 0;
+		high_offs = high_ent->str_len;
 	}
-
-	if (marking_up)
+	/* character selection */
+	else
 	{
-		int temp;
-
-		/* ensure ent_start is above ent_end */
-		if (ent_start != ent_end)
-		{
-			ent = ent_start;
-			ent_start = ent_end;
-			ent_end = ent;
-		}
-
-		/* switch offsets as well */
-		temp = offset_start;
-		offset_start = offset_end;
-		offset_end = temp;
+		if (low_y < 0)
+			low_offs = xtext->buffer->last_offset_start;
+		if (high_y > xtext->buffer->window_height)
+			high_offs = xtext->buffer->last_offset_end;
 	}
 
 	/* set all the old mark_ fields to -1 */
 	gtk_xtext_selection_clear (xtext->buffer);
 
-	/* set the default values */
-	ent_start->mark_end = ent_start->str_len;
-	ent_end->mark_start = 0;
+	low_ent->mark_start = low_offs;
+	low_ent->mark_end = high_offs;
 
-	/* set the calculated values (this overwrites the default values if we're on the same ent) */
-	ent_start->mark_start = offset_start;
-	ent_end->mark_end = offset_end;
-
-	/* set all the mark_ fields of the ents within the selection */
-	if (ent_start != ent_end)
+	if (low_ent != high_ent)
 	{
-		ent = ent_start->next;
-		while (ent && ent != ent_end)
+		low_ent->mark_end = low_ent->str_len;
+		if (high_offs != 0)
+		{
+			high_ent->mark_start = 0;
+			high_ent->mark_end = high_offs;
+		}
+
+		/* set all the mark_ fields of the ents within the selection */
+		ent = low_ent->next;
+		while (ent && ent != high_ent)
 		{
 			ent->mark_start = 0;
 			ent->mark_end = ent->str_len;
@@ -1400,7 +1415,7 @@ gtk_xtext_selection_draw (GtkXText * xtext, GdkEventMotion * event, gboolean ren
 	}
 
 	if (render)
-		gtk_xtext_selection_render (xtext, ent_start, ent_end);
+		gtk_xtext_selection_render (xtext, low_ent, high_ent);
 }
 
 static int
@@ -1532,7 +1547,7 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
 	int out_of_bounds = 0;
 	int len_to_offset = 0;
 
-	ent = gtk_xtext_find_char (xtext, x, y, &offset, &out_of_bounds, NULL);
+	ent = gtk_xtext_find_char (xtext, x, y, &offset, &out_of_bounds);
 	if (ent == NULL || out_of_bounds || offset < 0 || offset >= ent->str_len)
 		return NULL;
 
@@ -1585,11 +1600,11 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
 
 		/* make sure we're not before the start of the match */
 		if (len_to_offset < start)
-			return 0;
+			return NULL;
 
 		/* and not after it */
 		if (len_to_offset - start >= end - start)
-			return 0;
+			return NULL;
 	}
 
 	return word;
@@ -1646,7 +1661,8 @@ gtk_xtext_check_mark_stamp (GtkXText *xtext, GdkModifierType mask)
 {
 	gboolean redraw = FALSE;
 
-	if (mask & STATE_SHIFT || prefs.hex_text_autocopy_stamp)
+	if ((mask & STATE_SHIFT || prefs.hex_text_autocopy_stamp)
+	    && (!prefs.hex_stamp_text || prefs.hex_text_indent))
 	{
 		if (!xtext->mark_stamp)
 		{
@@ -1707,7 +1723,7 @@ gtk_xtext_get_word_adjust (GtkXText *xtext, int x, int y, textentry **word_ent,
 			}
 		}
 	}
-	g_slist_free_full (slp, free);
+	g_slist_free_full (slp, g_free);
 
 	return word_type;
 }
@@ -1853,7 +1869,7 @@ gtk_xtext_set_clip_owner (GtkWidget * xtext, GdkEventButton * event)
 			gtk_selection_owner_set (xtext, GDK_SELECTION_SECONDARY, event ? event->time : GDK_CURRENT_TIME);
 		}
 
-		free (str);
+		g_free (str);
 	}
 }
 
@@ -2107,7 +2123,7 @@ gtk_xtext_selection_get_text (GtkXText *xtext, int *len_ret)
 		return NULL;
 
 	/* now allocate mem and copy buffer */
-	pos = txt = malloc (len);
+	pos = txt = g_malloc (len);
 	ent = buf->last_ent_start;
 	while (ent)
 	{
@@ -2147,10 +2163,11 @@ gtk_xtext_selection_get_text (GtkXText *xtext, int *len_ret)
 		/*stripped = gtk_xtext_conv_color (txt, strlen (txt), &len);*/
 		stripped = txt;
 		len = strlen (txt);
-	} else
+	}
+	else
 	{
 		stripped = gtk_xtext_strip_color (txt, strlen (txt), NULL, &len, NULL, FALSE);
-		free (txt);
+		g_free (txt);
 	}
 
 	*len_ret = len;
@@ -2205,7 +2222,7 @@ gtk_xtext_selection_get (GtkWidget * widget,
 		g_free (new_text);
 	}
 
-	free (stripped);
+	g_free (stripped);
 }
 
 static gboolean
@@ -2360,7 +2377,7 @@ xtext_do_chunk(chunk_t *c)
 	if (c->len1 == 0)
 		return;
 
-	meta = malloc (sizeof *meta);
+	meta = g_new (offlen_t, 1);
 	meta->off = c->off1;
 	meta->len = c->len1;
 	meta->emph = c->emph;
@@ -2383,7 +2400,7 @@ gtk_xtext_strip_color (unsigned char *text, int len, unsigned char *outbuf,
 	int mbl;	/* multi-byte length */
 
 	if (outbuf == NULL)
-		new_str = malloc (len + 2);
+		new_str = g_malloc (len + 2);
 	else
 		new_str = outbuf;
 
@@ -2459,7 +2476,7 @@ bad_utf8:		/* Normal ending sequence, and give up if bad utf8 */
 	if (slpp)
 		*slpp = c.slp;
 	else
-		g_slist_free_full (c.slp, free);
+		g_slist_free_full (c.slp, g_free);
 
 	return new_str;
 }
@@ -2475,7 +2492,7 @@ gtk_xtext_text_width_ent (GtkXText *xtext, textentry *ent)
 
 	if (ent->slp)
 	{
-		g_slist_free_full (ent->slp, free);
+		g_slist_free_full (ent->slp, g_free);
 		ent->slp = NULL;
 	}
 
@@ -2507,7 +2524,7 @@ gtk_xtext_text_width (GtkXText *xtext, unsigned char *text, int len)
 												&new_len, &slp, !xtext->ignore_hidden);
 
 	width =  backend_get_text_width_slp (xtext, new_buf, slp);
-	g_slist_free_full (slp, free);
+	g_slist_free_full (slp, g_free);
 
 	return width;
 }
@@ -3254,7 +3271,7 @@ gtk_xtext_render_stamp (GtkXText * xtext, textentry * ent,
 {
 	textentry tmp_ent;
 	int jo, ji, hs;
-	int xsize, y;
+	int xsize, y, emphasis;
 
 	/* trashing ent here, so make a backup first */
 	memcpy (&tmp_ent, ent, sizeof (tmp_ent));
@@ -3264,7 +3281,7 @@ gtk_xtext_render_stamp (GtkXText * xtext, textentry * ent,
 	xtext->jump_out_offset = 0;
 	xtext->jump_in_offset = 0;
 	xtext->hilight_start = 0xffff;	/* temp disable */
-	int emphasis = 0;
+	emphasis = 0;
 
 	if (xtext->mark_stamp)
 	{
@@ -3530,7 +3547,7 @@ gtk_xtext_save (GtkXText * xtext, int fh)
 											  &newlen, NULL, FALSE);
 		write (fh, buf, newlen);
 		write (fh, "\n", 1);
-		free (buf);
+		g_free (buf);
 		ent = ent->next;
 	}
 }
@@ -3641,7 +3658,7 @@ gtk_xtext_nth (GtkXText *xtext, int line, int *subline)
 					break;
 				lines -= g_slist_length (ent->sublines);
 			}
-			return 0;
+			return NULL;
 		}
 	}
 	/* -- end of optimization -- */
@@ -3656,7 +3673,7 @@ gtk_xtext_nth (GtkXText *xtext, int line, int *subline)
 		}
 		ent = ent->next;
 	}
-	return 0;
+	return NULL;
 }
 
 /* render enta (or an inclusive range enta->entb) */
@@ -3895,10 +3912,10 @@ gtk_xtext_kill_ent (xtext_buffer *buffer, textentry *ent)
 		gtk_xtext_search_textentry_del (buffer, ent);
 	}
 
-	g_slist_free_full (ent->slp, free);
+	g_slist_free_full (ent->slp, g_free);
 	g_slist_free (ent->sublines);
 
-	free (ent);
+	g_free (ent);
 	return visible;
 }
 
@@ -4033,7 +4050,7 @@ gtk_xtext_clear (xtext_buffer *buf, int lines)
 		while (buf->text_first)
 		{
 			next = buf->text_first->next;
-			free (buf->text_first);
+			g_free (buf->text_first);
 			buf->text_first = next;
 		}
 		buf->text_last = NULL;
@@ -4191,7 +4208,6 @@ gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent)
 
 		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)
@@ -4210,7 +4226,7 @@ gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent)
 	}
 
 	/* Common processing --- */
-	g_slist_free_full (slp, free);
+	g_slist_free_full (slp, g_free);
 	return gl;
 }
 
@@ -4639,7 +4655,7 @@ gtk_xtext_append_indent (xtext_buffer *buf,
 	if (right_text[right_len-1] == '\n')
 		right_len--;
 
-	ent = malloc (left_len + right_len + 2 + sizeof (textentry));
+	ent = g_malloc (left_len + right_len + 2 + sizeof (textentry));
 	str = (unsigned char *) ent + sizeof (textentry);
 
 	memcpy (str, left_text, left_len);
@@ -4660,7 +4676,9 @@ gtk_xtext_append_indent (xtext_buffer *buf,
 		space = 0;
 
 	/* do we need to auto adjust the separator position? */
-	if (buf->xtext->auto_indent && ent->indent < MARGIN + space)
+	if (buf->xtext->auto_indent &&
+		 buf->indent < buf->xtext->max_auto_indent &&
+		 ent->indent < MARGIN + space)
 	{
 		tempindent = MARGIN + space + buf->xtext->space_width + left_width;
 
@@ -4681,7 +4699,7 @@ gtk_xtext_append_indent (xtext_buffer *buf,
 }
 
 void
-gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len)
+gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len, time_t stamp)
 {
 	textentry *ent;
 
@@ -4694,7 +4712,7 @@ gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len)
 	if (len >= sizeof (buf->xtext->scratch_buffer))
 		len = sizeof (buf->xtext->scratch_buffer) - 1;
 
-	ent = malloc (len + 1 + sizeof (textentry));
+	ent = g_malloc (len + 1 + sizeof (textentry));
 	ent->str = (unsigned char *) ent + sizeof (textentry);
 	ent->str_len = len;
 	if (len)
@@ -4703,7 +4721,7 @@ gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len)
 	ent->indent = 0;
 	ent->left_len = -1;
 
-	gtk_xtext_append_entry (buf, ent, 0);
+	gtk_xtext_append_entry (buf, ent, stamp);
 }
 
 gboolean
@@ -4738,11 +4756,14 @@ gtk_xtext_lastlog (xtext_buffer *out, xtext_buffer *search_area)
 			}
 			else
 			{
-				gtk_xtext_append (out, ent->str, ent->str_len);
+				gtk_xtext_append (out, ent->str, ent->str_len, 0);
 			}
 
-			out->text_last->stamp = ent->stamp;
-			gtk_xtext_search_textentry_add (out, out->text_last, gl, TRUE);
+			if (out->text_last)
+			{
+				out->text_last->stamp = ent->stamp;
+				gtk_xtext_search_textentry_add (out, out->text_last, gl, TRUE);
+			}
 		}
 		ent = ent->next;
 	}
@@ -4936,6 +4957,7 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
 		if (buf->window_width != w)
 		{
 			buf->window_width = w;
+			buf->window_height = h;
 			gtk_xtext_calc_lines (buf, FALSE);
 			if (buf->scrollbar_down)
 				gtk_adjustment_set_value (xtext->adj, xtext->adj->upper -
@@ -4959,8 +4981,7 @@ gtk_xtext_buffer_new (GtkXText *xtext)
 {
 	xtext_buffer *buf;
 
-	buf = malloc (sizeof (xtext_buffer));
-	memset (buf, 0, sizeof (xtext_buffer));
+	buf = g_new0 (xtext_buffer, 1);
 	buf->old_value = -1;
 	buf->xtext = xtext;
 	buf->scrollbar_down = TRUE;
@@ -4990,9 +5011,9 @@ gtk_xtext_buffer_free (xtext_buffer *buf)
 	while (ent)
 	{
 		next = ent->next;
-		free (ent);
+		g_free (ent);
 		ent = next;
 	}
 
-	free (buf);
+	g_free (buf);
 }
diff --git a/src/fe-gtk/xtext.h b/src/fe-gtk/xtext.h
index 73f5b52d..d6853f9f 100644
--- a/src/fe-gtk/xtext.h
+++ b/src/fe-gtk/xtext.h
@@ -252,7 +252,7 @@ struct _GtkXTextClass
 };
 
 GtkWidget *gtk_xtext_new (GdkColor palette[], int separator);
-void gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len);
+void gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len, time_t stamp);
 void gtk_xtext_append_indent (xtext_buffer *buf,
 										unsigned char *left_text, int left_len,
 										unsigned char *right_text, int right_len,
diff --git a/src/fe-text/fe-text.c b/src/fe-text/fe-text.c
index c8b64ab0..209a3d03 100644
--- a/src/fe-text/fe-text.c
+++ b/src/fe-text/fe-text.c
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -78,7 +80,6 @@ fe_new_window (struct session *sess, int focus)
 {
 	char buf[512];
 
-	sess->gui = malloc (4);
 	current_sess = sess;
 
 	if (!sess->server->front_session)
@@ -92,13 +93,11 @@ fe_new_window (struct session *sess, int focus)
 		return;
 	done_intro = 1;
 
-	snprintf (buf, sizeof (buf),
+	g_snprintf (buf, sizeof (buf),
 				"\n"
 				" \017HexChat-Text \00310"PACKAGE_VERSION"\n"
-				" \017Running on \00310%s \017glib \00310%d.%d.%d\n"
-				" \017This binary compiled \00310"__DATE__"\017\n",
-				get_sys_str (1),
-				glib_major_version, glib_minor_version, glib_micro_version);
+				" \017Running on \00310%s\n",
+				get_sys_str (1));
 	fe_print_text (sess, buf, 0, FALSE);
 
 	fe_print_text (sess, "\n\nCompiled in Features\0032:\017 "
@@ -111,9 +110,6 @@ fe_new_window (struct session *sess, int focus)
 #ifdef USE_OPENSSL
 	"OpenSSL "
 #endif
-#ifdef USE_IPV6
-	"IPv6"
-#endif
 	"\n\n", 0, FALSE);
 	fflush (stdout);
 }
@@ -140,7 +136,7 @@ timecat (char *buf, time_t stamp)
 
 /* 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 */
+/*                               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 };
 
 void
@@ -151,7 +147,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
 	char num[8];
 	int reverse = 0, under = 0, bold = 0,
 		comma, k, i = 0, j = 0, len = strlen (text);
-	unsigned char *newtext = malloc (len + 1024);
+	unsigned char *newtext = g_malloc (len + 1024);
 
 	if (prefs.hex_stamp_text)
 	{
@@ -207,7 +203,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
 						else
 							col = 30;
 						mirc = atoi (num);
-						mirc = colconv[mirc];
+						mirc = colconv[mirc % G_N_ELEMENTS(colconv)];
 						if (mirc > 9)
 						{
 							mirc += 50;
@@ -308,7 +304,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
 
 	newtext[j] = 0;
 	write (STDOUT_FILENO, newtext, j);
-	free (newtext);
+	g_free (newtext);
 }
 #else
 /* The win32 version for cmd.exe */
@@ -319,7 +315,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
 	int dotime = FALSE;
 	int comma, k, i = 0, j = 0, len = strlen (text);
 
-	unsigned char *newtext = malloc (len + 1024);
+	unsigned char *newtext = g_malloc (len + 1024);
 
 	if (prefs.hex_stamp_text)
 	{
@@ -403,7 +399,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
 
 	newtext[j] = 0;
 	write (STDOUT_FILENO, newtext, j);
-	free (newtext);
+	g_free (newtext);
 }
 #endif
 
@@ -508,14 +504,14 @@ fe_args (int argc, char *argv[])
 	{
 #ifdef WIN32
 		/* see the chdir() below */
-		char *sl, *exe = strdup (argv[0]);
+		char *sl, *exe = g_strdup (argv[0]);
 		sl = strrchr (exe, '\\');
 		if (sl)
 		{
 			*sl = 0;
 			printf ("%s\\plugins\n", exe);
 		}
-		free (exe);
+		g_free (exe);
 #else
 		printf ("%s\n", HEXCHATLIBDIR);
 #endif
@@ -530,8 +526,7 @@ fe_args (int argc, char *argv[])
 
 	if (arg_cfgdir)	/* we want filesystem encoding */
 	{
-		if (xdir)
-			g_free (xdir);
+		g_free (xdir);
 		xdir = strdup (arg_cfgdir);
 		if (xdir[strlen (xdir) - 1] == '/')
 			xdir[strlen (xdir) - 1] = 0;
@@ -583,7 +578,6 @@ fe_exit (void)
 void
 fe_new_server (struct server *serv)
 {
-	serv->gui = malloc (4);
 }
 
 void
@@ -682,7 +676,7 @@ fe_progressbar_end (struct server *serv)
 {
 }
 void
-fe_userlist_insert (struct session *sess, struct User *newuser, int row, int sel)
+fe_userlist_insert (struct session *sess, struct User *newuser, gboolean sel)
 {
 }
 int
@@ -695,10 +689,6 @@ fe_userlist_rehash (struct session *sess, struct User *user)
 {
 }
 void
-fe_userlist_move (struct session *sess, struct User *user, int new_row)
-{
-}
-void
 fe_userlist_numbers (struct session *sess)
 {
 }
@@ -910,7 +900,6 @@ void fe_tray_set_flash (const char *filename1, const char *filename2, int timeou
 void fe_tray_set_file (const char *filename){}
 void fe_tray_set_icon (feicon icon){}
 void fe_tray_set_tooltip (const char *text){}
-void fe_tray_set_balloon (const char *title, const char *text){}
 void fe_userlist_update (session *sess, struct User *user){}
 void
 fe_open_chan_list (server *serv, char *filter, int do_refresh)
diff --git a/src/fe-text/fe-text.vcxproj b/src/fe-text/fe-text.vcxproj
index c59c57bc..1da7e733 100644
--- a/src/fe-text/fe-text.vcxproj
+++ b/src/fe-text/fe-text.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>Application</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,77 +20,38 @@
     <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>

-  </PropertyGroup>

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

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hexchat-text</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hexchat-text</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

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

-      <AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

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

     </ClCompile>

     <Link>

       <SubSystem>Console</SubSystem>

       <GenerateDebugInformation>true</GenerateDebugInformation>

       <EnableCOMDATFolding>true</EnableCOMDATFolding>

       <OptimizeReferences>true</OptimizeReferences>

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

+      <AdditionalDependencies>$(DepLibs);$(HexChatLib)common.lib;%(AdditionalDependencies)</AdditionalDependencies>

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

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

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

-      <AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

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

     </ClCompile>

     <Link>

       <SubSystem>Console</SubSystem>

       <GenerateDebugInformation>true</GenerateDebugInformation>

       <EnableCOMDATFolding>true</EnableCOMDATFolding>

       <OptimizeReferences>true</OptimizeReferences>

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

+      <AdditionalDependencies>$(DepLibs);$(HexChatLib)common.lib;%(AdditionalDependencies)</AdditionalDependencies>

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

     </Link>

   </ItemDefinitionGroup>

@@ -100,6 +62,4 @@
     <ClCompile Include="fe-text.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/src/htm/htm.csproj b/src/htm/htm.csproj
index eea953d2..d56f2188 100644
--- a/src/htm/htm.csproj
+++ b/src/htm/htm.csproj
@@ -61,22 +61,13 @@
   </PropertyGroup>

   <PropertyGroup />

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

+    <PlatformTarget>x64</PlatformTarget>

+    <DebugType>pdbonly</DebugType>

+    <Optimize>true</Optimize>

     <OutputPath>..\..\..\hexchat-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="System" />

diff --git a/src/libenchant_win8/libenchant_win8.def b/src/libenchant_win8/libenchant_win8.def
new file mode 100644
index 00000000..cf367651
--- /dev/null
+++ b/src/libenchant_win8/libenchant_win8.def
@@ -0,0 +1,2 @@
+EXPORTS 

+init_enchant_provider  

diff --git a/src/libenchant_win8/libenchant_win8.vcxproj b/src/libenchant_win8/libenchant_win8.vcxproj
new file mode 100644
index 00000000..aab7acc8
--- /dev/null
+++ b/src/libenchant_win8/libenchant_win8.vcxproj
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="12.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>{BF0EBC16-68AD-4CD1-864C-5B56836EBE2A}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>libenchant_win8</RootNamespace>

+  </PropertyGroup>

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

+  <PropertyGroup Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <PlatformToolset>v120</PlatformToolset>

+  </PropertyGroup>

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

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

+  <ImportGroup Label="PropertySheets">

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

+  </ImportGroup>

+  <PropertyGroup>

+    <OutDir>$(HexChatRel)lib\enchant\</OutDir>

+    <TargetName>libenchant_win8</TargetName>

+  </PropertyGroup>

+  <ItemDefinitionGroup>

+    <ClCompile>

+      <AdditionalIncludeDirectories>..\common;$(HexChatLib);$(DepsRoot)\include\enchant;$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

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

+      <ModuleDefinitionFile>libenchant_win8.def</ModuleDefinitionFile>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClCompile Include="win8_provider.cpp" />

+  </ItemGroup>

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

+</Project>

diff --git a/src/libenchant_win8/libenchant_win8.vcxproj.filters b/src/libenchant_win8/libenchant_win8.vcxproj.filters
new file mode 100644
index 00000000..ff2f3024
--- /dev/null
+++ b/src/libenchant_win8/libenchant_win8.vcxproj.filters
@@ -0,0 +1,22 @@
+<?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;hh;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>

+    <ClCompile Include="win8_provider.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+</Project>

diff --git a/src/libenchant_win8/win8_provider.cpp b/src/libenchant_win8/win8_provider.cpp
new file mode 100644
index 00000000..73f16610
--- /dev/null
+++ b/src/libenchant_win8/win8_provider.cpp
@@ -0,0 +1,293 @@
+/* HexChat
+ * Copyright (c) 2015 Patrick Griffis
+ *
+ * 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 THE
+ * AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "config.h"
+
+#include <Spellcheck.h>
+#include <glib.h>
+
+#include "typedef.h" // for ssize_t
+#include <enchant-provider.h>
+
+ENCHANT_PLUGIN_DECLARE ("win8")
+
+/* --------- Utils ----------*/
+
+static char *
+utf16_to_utf8 (const wchar_t * const str, gboolean from_bcp47)
+{
+	char *utf8 = g_utf16_to_utf8 ((gunichar2*)str, -1, nullptr, nullptr, nullptr);
+	if (utf8 && from_bcp47)
+	{
+		char *p = utf8;
+		/* bcp47 tags use syntax "en-US" while the myspell versions are "en_US" */
+		while (*p)
+		{
+			if (*p == '-')
+				*p = '_';
+			p++;
+		}
+	}
+	return utf8;
+}
+
+static wchar_t *
+utf8_to_utf16 (const char * const str, size_t len, gboolean to_bcp47)
+{
+	wchar_t *utf16 = (wchar_t*)g_utf8_to_utf16 (str, len, nullptr, nullptr, nullptr);
+	if (utf16 && to_bcp47)
+	{
+		wchar_t *p = utf16;
+		/* bcp47 tags use syntax "en-US" while the myspell versions are "en_US" */
+		while (*p)
+		{
+			if (*p == L'_')
+				*p = L'-';
+			p++;
+		}
+	}
+	return utf16;
+}
+
+static char **
+enumstring_to_chararray (IEnumString *strings, size_t *out_len, gboolean from_bcp47)
+{
+	char **chars = g_new (char*, 256); /* Hopefully large enough */
+	LPOLESTR wstr = nullptr;
+	size_t i = 0;
+
+	while (SUCCEEDED (strings->Next (1, &wstr, nullptr)) && i < 256 && wstr)
+	{
+		char *str = utf16_to_utf8 (wstr, from_bcp47);
+		if (str)
+		{
+			chars[i] = str;
+			i++;
+		}
+		CoTaskMemFree (wstr);
+	}
+	chars[i] = nullptr;
+	strings->Release ();
+
+	*out_len = i;
+	return chars;
+}
+
+/* ---------- Dict ------------ */
+
+static void
+win8_dict_add_to_personal (EnchantDict *dict, const char *const word, size_t len)
+{
+	auto checker = static_cast<ISpellChecker*>(dict->user_data);
+	wchar_t *wword = utf8_to_utf16 (word, len, FALSE);
+
+	checker->Add (wword);
+	g_free (wword);
+}
+
+static void
+win8_dict_add_to_session (EnchantDict *dict, const char *const word, size_t len)
+{
+	auto checker = static_cast<ISpellChecker*>(dict->user_data);
+	wchar_t *wword = utf8_to_utf16 (word, len, FALSE);
+
+	checker->Ignore (wword);
+	g_free (wword);
+}
+
+static int
+win8_dict_check (EnchantDict *dict, const char *const word, size_t len)
+{
+	auto checker = static_cast<ISpellChecker*>(dict->user_data);
+	wchar_t *wword = utf8_to_utf16 (word, len, FALSE);
+	IEnumSpellingError *errors;
+	ISpellingError *error = nullptr;
+	HRESULT hr;
+
+	hr = checker->Check (wword, &errors);
+	g_free (wword);
+
+	if (FAILED (hr))
+		return -1; /* Error */
+
+	if (errors->Next (&error) == S_OK)
+	{
+		error->Release ();
+		errors->Release ();
+		return 1; /* Spelling Issue */
+	}
+	else
+	{
+		errors->Release ();
+		return 0; /* Correct */
+	}
+}
+
+static char **
+win8_dict_suggest (EnchantDict *dict, const char *const word, size_t len, size_t *out_n_suggs)
+{
+	auto checker = static_cast<ISpellChecker*>(dict->user_data);
+	wchar_t *wword = utf8_to_utf16 (word, len, FALSE);
+	IEnumString *suggestions;
+	HRESULT hr;
+
+	hr = checker->Suggest (wword, &suggestions);
+	g_free (wword);
+
+	if (FAILED (hr))
+	{
+		*out_n_suggs = 0;
+		return nullptr;
+	}
+
+	return enumstring_to_chararray (suggestions, out_n_suggs, FALSE);
+}
+
+/* ---------- Provider ------------ */
+
+static EnchantDict *
+win8_provider_request_dict (EnchantProvider *provider, const char *const tag)
+{
+	auto factory = static_cast<ISpellCheckerFactory*>(provider->user_data);
+	ISpellChecker *checker;
+	EnchantDict *dict;
+	wchar_t *wtag = utf8_to_utf16 (tag, -1, TRUE);
+	HRESULT hr;
+
+	hr = factory->CreateSpellChecker (wtag, &checker);
+	g_free (wtag);
+
+	if (FAILED (hr))
+		return nullptr;
+
+	dict = g_new0 (EnchantDict, 1);
+	dict->suggest = win8_dict_suggest;
+	dict->check = win8_dict_check;
+	dict->add_to_personal = win8_dict_add_to_personal;
+	dict->add_to_exclude = win8_dict_add_to_personal; /* Basically the same */
+	dict->add_to_session = win8_dict_add_to_session;
+
+	dict->user_data = checker;
+
+	return dict;
+}
+
+static void
+win8_provider_dispose_dict (EnchantProvider *provider, EnchantDict *dict)
+{
+	if (dict)
+	{
+		auto checker = static_cast<ISpellChecker*>(dict->user_data);
+
+		checker->Release ();
+		g_free (dict);
+	}
+}
+
+static int
+win8_provider_dictionary_exists (EnchantProvider *provider, const char *const tag)
+{
+	auto factory = static_cast<ISpellCheckerFactory*>(provider->user_data);
+	wchar_t *wtag = utf8_to_utf16 (tag, -1, TRUE);
+
+	BOOL is_supported = FALSE;
+	factory->IsSupported (wtag, &is_supported);
+
+	g_free (wtag);
+	return is_supported;
+}
+
+
+static char **
+win8_provider_list_dicts (EnchantProvider *provider, size_t *out_n_dicts)
+{
+	auto factory = static_cast<ISpellCheckerFactory*>(provider->user_data);
+	IEnumString *dicts;
+
+	if (FAILED(factory->get_SupportedLanguages (&dicts)))
+	{
+		*out_n_dicts = 0;
+		return nullptr;
+	}
+
+	return enumstring_to_chararray (dicts, out_n_dicts, TRUE);
+}
+
+static void
+win8_provider_free_string_list (EnchantProvider *provider, char **str_list)
+{
+	g_strfreev (str_list);
+}
+
+static void
+win8_provider_dispose (EnchantProvider *provider)
+{
+	if (provider)
+	{
+		auto factory = static_cast<ISpellCheckerFactory*>(provider->user_data);
+
+		factory->Release();
+		g_free (provider);
+	}
+}
+
+static const char *
+win8_provider_identify (EnchantProvider *provider)
+{
+	return "win8";
+}
+
+static const char *
+win8_provider_describe (EnchantProvider *provider)
+{
+	return "Windows 8 SpellCheck Provider";
+}
+
+extern "C"
+{
+
+EnchantProvider *
+init_enchant_provider (void)
+{
+	EnchantProvider *provider;
+	ISpellCheckerFactory *factory;
+
+	if (FAILED (CoCreateInstance (__uuidof(SpellCheckerFactory), nullptr,
+				CLSCTX_INPROC_SERVER, IID_PPV_ARGS (&factory))))
+		return nullptr;
+
+	provider = g_new0 (EnchantProvider, 1);
+	provider->dispose = win8_provider_dispose;
+	provider->request_dict = win8_provider_request_dict;
+	provider->dispose_dict = win8_provider_dispose_dict;
+	provider->dictionary_exists = win8_provider_dictionary_exists;
+	provider->identify = win8_provider_identify;
+	provider->describe = win8_provider_describe;
+	provider->list_dicts = win8_provider_list_dicts;
+	provider->free_string_list = win8_provider_free_string_list;
+
+	provider->user_data = factory;
+
+	return provider;
+}
+
+}
diff --git a/win32/config.h.tt b/win32/config.h.tt
index 77da3b38..ad518964 100644
--- a/win32/config.h.tt
+++ b/win32/config.h.tt
@@ -2,7 +2,6 @@
 #define ENABLE_NLS
 #define USE_PLUGIN
 #define USE_OPENSSL
-#define USE_IPV6
 #define HAVE_ISO_CODES
 #define ISO_CODES_PREFIX ".\\"
 #define ISO_CODES_LOCALEDIR LOCALEDIR
@@ -13,6 +12,3 @@
 #define OLD_PERL
 #define GETTEXT_PACKAGE "hexchat"
 #define PACKAGE_TARNAME "hexchat-<#= [string]::Join('.', $versionParts) #>"
-#ifndef USE_IPV6
-#define socklen_t int
-#endif
diff --git a/win32/copy/copy.vcxproj b/win32/copy/copy.vcxproj
index d0c1150b..557ca702 100644
--- a/win32/copy/copy.vcxproj
+++ b/win32/copy/copy.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>Application</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -18,73 +19,65 @@
     <RootNamespace>copy</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>

-  </PropertyGroup>

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

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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="..\hexchat.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="..\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <ClCompile>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-    </ClCompile>

-    <Link>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-    </Link>

-    <PreBuildEvent>

-      <Command>$(HexChatCopy)</Command>

-    </PreBuildEvent>

-  </ItemDefinitionGroup>

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

-    <ClCompile>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-    </ClCompile>

-    <Link>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-    </Link>

-    <PreBuildEvent>

-      <Command>$(HexChatCopy)</Command>

-    </PreBuildEvent>

-  </ItemDefinitionGroup>

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

+  <Import Project="..\hexchat.props" />

   <ItemGroup>

+    <None Include="$(DepsRoot)\bin\cert.pem" />

+    <None Include="$(DepsRoot)\bin\atk-1.0.dll" />

+    <None Include="$(DepsRoot)\bin\cairo.dll" />

+    <None Include="$(DepsRoot)\bin\fontconfig.dll" />

+    <None Include="$(DepsRoot)\bin\gdk_pixbuf-2.0.dll" />

+    <None Include="$(DepsRoot)\bin\gdk-win32-2.0.dll" />

+    <None Include="$(DepsRoot)\bin\gio-2.0.dll" />

+    <None Include="$(DepsRoot)\bin\glib-2.0.dll" />

+    <None Include="$(DepsRoot)\bin\gmodule-2.0.dll" />

+    <None Include="$(DepsRoot)\bin\gobject-2.0.dll" />

+    <None Include="$(DepsRoot)\bin\gspawn-win$(PlatformArchitecture)-helper.exe" />

+    <None Include="$(DepsRoot)\bin\gspawn-win$(PlatformArchitecture)-helper-console.exe" />

+    <None Include="$(DepsRoot)\bin\gthread-2.0.dll" />

+    <None Include="$(DepsRoot)\bin\gtk-win32-2.0.dll" />

+    <None Include="$(DepsRoot)\bin\harfbuzz.dll" />

+    <None Include="$(DepsRoot)\bin\iconv.dll" />

+    <None Include="$(DepsRoot)\bin\libeay32.dll" />

+    <None Include="$(DepsRoot)\bin\libenchant.dll" />

+    <None Include="$(DepsRoot)\bin\libintl.dll" />

+    <None Include="$(DepsRoot)\bin\libpng16.dll" />

+    <None Include="$(DepsRoot)\bin\libxml2.dll" />

+    <None Include="$(DepsRoot)\bin\pango-1.0.dll" />

+    <None Include="$(DepsRoot)\bin\pangocairo-1.0.dll" />

+    <None Include="$(DepsRoot)\bin\pangoft2-1.0.dll" />

+    <None Include="$(DepsRoot)\bin\pangowin32-1.0.dll" />

+    <None Include="$(DepsRoot)\bin\pixman-1.dll" />

+    <None Include="$(DepsRoot)\bin\ssleay32.dll" />

+    <None Include="$(DepsRoot)\bin\zlib1.dll" />

+    <None Include="$(WinSparklePath)\WinSparkle.dll" />

+    <None Include="$(HexChatBin)thememan.exe" />

     <None Include="changelog.url" />

     <None Include="readme.url" />

-    <None Include="share\xml\iso-codes\iso_3166.xml" />

-    <None Include="share\xml\iso-codes\iso_639.xml" />

+

+    <Engines Include="$(DepsRoot)\lib\gtk-2.0\i686-pc-vs10\engines\**\*" />

+

+    <Share Include="share\**\*" />

+

+    <DepsRootDocs Include="$(DepsRoot)\share\doc\**\*" />

+

+    <Locale Include="$(HexChatBin)locale\**\*;$(DepsRoot)\share\locale\**\*" />

+

+    <MSWindowsTheme Include="$(DepsRoot)\share\themes\MS-Windows\**\*" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
+  <Target Name="Build">

+    <Copy SourceFiles="@(None)" DestinationFolder="$(HexChatRel)" />

+    <Copy SourceFiles="@(Engines)" DestinationFiles="@(Engines->'$(HexChatRel)\lib\gtk-2.0\i686-pc-vs10\engines\%(RecursiveDir)%(Filename)%(Extension)')" />

+    <Copy SourceFiles="@(Share)" DestinationFiles="@(Share->'$(HexChatRel)\share\%(RecursiveDir)%(Filename)%(Extension)')" />

+    <Copy SourceFiles="@(DepsRootDocs)" DestinationFiles="@(DepsRootDocs->'$(HexChatRel)\share\doc\%(RecursiveDir)%(Filename)%(Extension)')" />

+    <Copy SourceFiles="..\..\COPYING" DestinationFolder="$(HexChatRel)\share\doc\hexchat" />

+    <Copy SourceFiles="$(WinSparklePath)\COPYING" DestinationFolder="$(HexChatRel)\share\doc\WinSparkle" />

+    <Copy SourceFiles="$(DepsRoot)\lib\enchant\libenchant_myspell.dll" DestinationFolder="$(HexChatRel)\lib\enchant" />

+    <Copy SourceFiles="@(Locale)" DestinationFiles="@(Locale->'$(HexChatRel)\share\locale\%(RecursiveDir)%(Filename)%(Extension)')" />

+    <Copy SourceFiles="@(MSWindowsTheme)" DestinationFiles="@(MSWindowsTheme->'$(HexChatRel)\share\themes\MS-Windows\%(RecursiveDir)%(Filename)%(Extension)')" />

+

+    <WriteLinesToFile File="$(HexChatRel)portable-mode" Lines="2" Overwrite="true" />

+  </Target>

+</Project>

diff --git a/win32/copy/copy.vcxproj.filters b/win32/copy/copy.vcxproj.filters
index af2be024..695b5c78 100644
--- a/win32/copy/copy.vcxproj.filters
+++ b/win32/copy/copy.vcxproj.filters
@@ -1,52 +1,3 @@
 <?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>{e02a8c67-767c-4c6e-a854-81fae08cf4da}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Resource Files\etc">

-      <UniqueIdentifier>{503881c0-011d-443b-a373-4bfe125dcfa6}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Resource Files\share">

-      <UniqueIdentifier>{4316433a-2a8e-48f7-9020-e1f4de0d23d1}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Resource Files\etc\gtk-2.0">

-      <UniqueIdentifier>{832ebebc-ab71-4bf6-9f3a-02ec748f7c14}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Resource Files\share\xml">

-      <UniqueIdentifier>{9a881586-aed2-4f80-ba84-e521e6785566}</UniqueIdentifier>

-    </Filter>

-    <Filter Include="Resource Files\share\xml\iso-codes">

-      <UniqueIdentifier>{c825f724-0618-4160-97b7-12d6e0f2bc7b}</UniqueIdentifier>

-    </Filter>

-  </ItemGroup>

-  <ItemGroup>

-    <None Include="etc\download.png">

-      <Filter>Resource Files\etc</Filter>

-    </None>

-    <None Include="etc\gtkpref.png">

-      <Filter>Resource Files\etc</Filter>

-    </None>

-    <None Include="etc\music.png">

-      <Filter>Resource Files\etc</Filter>

-    </None>

-    <None Include="etc\system.png">

-      <Filter>Resource Files\etc</Filter>

-    </None>

-    <None Include="etc\gtk-2.0\gtkrc">

-      <Filter>Resource Files\etc\gtk-2.0</Filter>

-    </None>

-    <None Include="share\xml\iso-codes\iso_639.xml">

-      <Filter>Resource Files\share\xml\iso-codes</Filter>

-    </None>

-    <None Include="share\xml\iso-codes\iso_3166.xml">

-      <Filter>Resource Files\share\xml\iso-codes</Filter>

-    </None>

-    <None Include="readme.url">

-      <Filter>Resource Files</Filter>

-    </None>

-    <None Include="changelog.url">

-      <Filter>Resource Files</Filter>

-    </None>

-  </ItemGroup>

 </Project>
\ No newline at end of file
diff --git a/win32/ext/nss-wdk/build-x64.bat b/win32/ext/nss-wdk/build-x64.bat
deleted file mode 100644
index 96bb0422..00000000
--- a/win32/ext/nss-wdk/build-x64.bat
+++ /dev/null
@@ -1,13 +0,0 @@
-@echo off
-set WDK_ROOT=c:\WinDDK\7600.16385.1
-set INCLUDE=%WDK_ROOT%\inc\api;%WDK_ROOT%\inc\crt;%WDK_ROOT%\inc\ddk
-set LIB=%WDK_ROOT%\lib\wnet\amd64;%WDK_ROOT%\lib\Crt\amd64
-set PATH=%PROGRAMFILES(X86)%\Microsoft Visual Studio 10.0\VC\bin\amd64;%PROGRAMFILES(X86)%\Microsoft SDKs\Windows\v7.0A\Bin\x64;c:\mozilla-build\msys\bin;c:\mozilla-build\moztools-x64\bin
-set BUILD_OPT=1
-set USE_64=1
-set WINDDK_BUILD=1
-cd mozilla\security\nss
-make nss_build_all
-cd ..\..\..
-echo.Finished!
-pause
diff --git a/win32/ext/nss-wdk/build-x86.bat b/win32/ext/nss-wdk/build-x86.bat
deleted file mode 100644
index c6d4868e..00000000
--- a/win32/ext/nss-wdk/build-x86.bat
+++ /dev/null
@@ -1,13 +0,0 @@
-@echo off
-set WDK_ROOT=c:\WinDDK\7600.16385.1
-set INCLUDE=%WDK_ROOT%\inc\api;%WDK_ROOT%\inc\crt
-set LIB=%WDK_ROOT%\lib\wxp\i386;%WDK_ROOT%\lib\Crt\i386
-set PATH=%PROGRAMFILES(X86)%\Microsoft Visual Studio 10.0\VC\bin;%PROGRAMFILES(X86)%\Microsoft Visual Studio 10.0\Common7\IDE;%PROGRAMFILES(X86)%\Microsoft SDKs\Windows\v7.0A\Bin;c:\mozilla-build\msys\bin;c:\mozilla-build\moztools\bin
-set BUILD_OPT=1
-set USE_64=
-set WINDDK_BUILD=1
-cd mozilla\security\nss
-make nss_build_all
-cd ..\..\..
-echo.Finished!
-pause
diff --git a/win32/ext/nss-wdk/nss-wdk.patch b/win32/ext/nss-wdk/nss-wdk.patch
deleted file mode 100644
index 7d663491..00000000
--- a/win32/ext/nss-wdk/nss-wdk.patch
+++ /dev/null
@@ -1,257 +0,0 @@
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/dbm/include/mcom_db.h nss-3.13.6/mozilla/dbm/include/mcom_db.h
---- nss-3.13.6.orig/mozilla/dbm/include/mcom_db.h	2009-06-05 01:18:50 +0200
-+++ nss-3.13.6/mozilla/dbm/include/mcom_db.h	2012-10-06 00:54:22 +0200
-@@ -40,6 +40,15 @@
- #define off_t long
- #endif
- 
-+#ifdef WINDDK_BUILD
-+#ifndef stat
-+#define stat _stat
-+#endif
-+#ifndef getpid
-+#define getpid GetCurrentProcessId
-+#endif
-+#endif
-+
- #ifndef macintosh
- #include <sys/types.h>
- #endif
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/dbm/src/mktemp.c nss-3.13.6/mozilla/dbm/src/mktemp.c
---- nss-3.13.6.orig/mozilla/dbm/src/mktemp.c	2009-06-05 01:19:31 +0200
-+++ nss-3.13.6/mozilla/dbm/src/mktemp.c	2012-10-06 00:54:22 +0200
-@@ -45,13 +45,13 @@
- #include <ctype.h>
- #include "mcom_db.h"
- 
--#ifndef _WINDOWS
--#include <unistd.h>
--#endif
--
- #ifdef _WINDOWS
-+#ifndef WINDDK_BUILD
- #include <process.h>
-+#endif
- #include "winfile.h"
-+#else
-+#include <unistd.h>
- #endif
- 
- static int _gettemp(char *path, register int *doopen, int extraFlags);
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/nsprpub/config/config.mk nss-3.13.6/mozilla/nsprpub/config/config.mk
---- nss-3.13.6.orig/mozilla/nsprpub/config/config.mk	2012-03-06 14:13:38 +0100
-+++ nss-3.13.6/mozilla/nsprpub/config/config.mk	2012-10-06 00:54:22 +0200
-@@ -132,6 +132,15 @@
- DEFINES += -DMOZ_UNICODE
- endif
- 
-+ifdef WINDDK_BUILD
-+OS_CFLAGS += -DWINDDK_BUILD
-+ifdef USE_64
-+OS_LIBS += msvcrt_win2003.obj
-+else
-+OS_LIBS += msvcrt_winxp.obj
-+endif
-+endif
-+
- ####################################################################
- #
- # Configuration for the release process
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/nsprpub/pr/src/Makefile.in nss-3.13.6/mozilla/nsprpub/pr/src/Makefile.in
---- nss-3.13.6.orig/mozilla/nsprpub/pr/src/Makefile.in	2012-03-06 14:13:59 +0100
-+++ nss-3.13.6/mozilla/nsprpub/pr/src/Makefile.in	2012-10-06 00:54:22 +0200
-@@ -170,9 +170,17 @@
- ifdef NS_USE_GCC
- OS_LIBS		= -ladvapi32 -lwsock32 -lwinmm
- else
-+ifdef WINDDK_BUILD
-+ifdef USE_64
-+OS_LIBS = advapi32.lib wsock32.lib winmm.lib msvcrt_win2003.obj
-+else
-+OS_LIBS = advapi32.lib wsock32.lib winmm.lib msvcrt_winxp.obj
-+endif
-+else
- OS_LIBS		= advapi32.lib wsock32.lib winmm.lib
- endif
- endif
-+endif
- 
- ifeq ($(OS_ARCH),WINCE)
- OS_LIBS		= ws2.lib
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/nsprpub/pr/src/md/windows/ntmisc.c nss-3.13.6/mozilla/nsprpub/pr/src/md/windows/ntmisc.c
---- nss-3.13.6.orig/mozilla/nsprpub/pr/src/md/windows/ntmisc.c	2012-03-06 14:14:17 +0100
-+++ nss-3.13.6/mozilla/nsprpub/pr/src/md/windows/ntmisc.c	2012-10-06 00:54:22 +0200
-@@ -593,7 +593,11 @@
-      */
-     hasFdInheritBuffer = (attr && attr->fdInheritBuffer);
-     if ((envp == NULL) && hasFdInheritBuffer) {
-+#ifdef WINDDK_BUILD
-+        envp = getenv;
-+#else
-         envp = environ;
-+#endif
-     }
- 
-     if (envp != NULL) {
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/security/coreconf/WIN32.mk nss-3.13.6/mozilla/security/coreconf/WIN32.mk
---- nss-3.13.6.orig/mozilla/security/coreconf/WIN32.mk	2011-09-14 19:59:43 +0200
-+++ nss-3.13.6/mozilla/security/coreconf/WIN32.mk	2012-10-06 00:54:22 +0200
-@@ -146,6 +146,14 @@
-     OS_CFLAGS += -W3 -nologo -D_CRT_SECURE_NO_WARNINGS \
- 		 -D_CRT_NONSTDC_NO_WARNINGS
-     OS_DLLFLAGS += -nologo -DLL -SUBSYSTEM:WINDOWS
-+    ifdef WINDDK_BUILD
-+        OS_CFLAGS += -DWINDDK_BUILD
-+        ifdef USE_64
-+            OS_LIBS += msvcrt_win2003.obj
-+        else
-+            OS_LIBS += msvcrt_winxp.obj
-+        endif
-+    endif
-     ifeq ($(_MSC_VER),$(_MSC_VER_6))
-     ifndef MOZ_DEBUG_SYMBOLS
- 	OS_DLLFLAGS += -PDB:NONE
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/security/coreconf/arch.mk nss-3.13.6/mozilla/security/coreconf/arch.mk
---- nss-3.13.6.orig/mozilla/security/coreconf/arch.mk	2009-06-05 04:14:49 +0200
-+++ nss-3.13.6/mozilla/security/coreconf/arch.mk	2012-10-06 00:54:22 +0200
-@@ -268,7 +268,15 @@
- # the uname.exe in the MSYS toolkit.
- #
- ifeq (MINGW32_NT,$(findstring MINGW32_NT,$(OS_ARCH)))
--    OS_RELEASE := $(patsubst MINGW32_NT-%,%,$(OS_ARCH))
-+    ifdef WINDDK_BUILD
-+        ifdef USE_64
-+            OS_RELEASE := 5.2
-+        else
-+            OS_RELEASE := 5.1
-+        endif
-+    else
-+        OS_RELEASE := $(patsubst MINGW32_NT-%,%,$(OS_ARCH))
-+    endif
-     OS_ARCH = WINNT
-     USE_MSYS = 1
-     ifndef CPU_ARCH
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/security/nss/cmd/platlibs.mk nss-3.13.6/mozilla/security/nss/cmd/platlibs.mk
---- nss-3.13.6.orig/mozilla/security/nss/cmd/platlibs.mk	2010-06-12 02:58:33 +0200
-+++ nss-3.13.6/mozilla/security/nss/cmd/platlibs.mk	2012-10-06 00:54:22 +0200
-@@ -249,3 +249,11 @@
- endif
- 
- JAR_LIBS = $(DIST)/lib/$(LIB_PREFIX)jar.$(LIB_SUFFIX)
-+
-+ifdef WINDDK_BUILD
-+ifdef USE_64
-+OS_LIBS += msvcrt_win2003.obj
-+else
-+OS_LIBS += msvcrt_winxp.obj
-+endif
-+endif
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/security/nss/cmd/selfserv/selfserv.c nss-3.13.6/mozilla/security/nss/cmd/selfserv/selfserv.c
---- nss-3.13.6.orig/mozilla/security/nss/cmd/selfserv/selfserv.c	2012-03-01 19:38:24 +0100
-+++ nss-3.13.6/mozilla/security/nss/cmd/selfserv/selfserv.c	2012-10-06 00:54:22 +0200
-@@ -51,8 +51,13 @@
- #endif
- 
- #if defined(_WINDOWS)
-+#ifdef WINDDK_BUILD
-+#include <windows.h>
-+#define getpid GetCurrentProcessId
-+#else
- #include <process.h>	/* for getpid() */
- #endif
-+#endif
- 
- #include <signal.h>
- #include <stdlib.h>
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/security/nss/lib/freebl/mpi/mpcpucache.c nss-3.13.6/mozilla/security/nss/lib/freebl/mpi/mpcpucache.c
---- nss-3.13.6.orig/mozilla/security/nss/lib/freebl/mpi/mpcpucache.c	2011-09-30 18:07:16 +0200
-+++ nss-3.13.6/mozilla/security/nss/lib/freebl/mpi/mpcpucache.c	2012-10-06 00:54:22 +0200
-@@ -80,7 +80,11 @@
- 
- #elif defined(_MSC_VER)
- 
-+#ifdef WINDDK_BUILD
-+#include <ntddk.h>
-+#else
- #include <intrin.h>
-+#endif
- 
- void freebl_cpuid(unsigned long op, unsigned long *eax, 
-            unsigned long *ebx, unsigned long *ecx, 
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/security/nss/lib/freebl/win_rand.c nss-3.13.6/mozilla/security/nss/lib/freebl/win_rand.c
---- nss-3.13.6.orig/mozilla/security/nss/lib/freebl/win_rand.c	2011-01-06 20:00:52 +0100
-+++ nss-3.13.6/mozilla/security/nss/lib/freebl/win_rand.c	2012-10-06 00:54:22 +0200
-@@ -50,6 +50,13 @@
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif
-+
-+#ifdef WINDDK_BUILD
-+#ifndef stat
-+#define stat _stat
-+#endif
-+#endif
-+
- #include <stdio.h>
- #include "prio.h"
- #include "prerror.h"
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/security/nss/lib/softoken/legacydb/config.mk nss-3.13.6/mozilla/security/nss/lib/softoken/legacydb/config.mk
---- nss-3.13.6.orig/mozilla/security/nss/lib/softoken/legacydb/config.mk	2011-11-06 00:01:08 +0100
-+++ nss-3.13.6/mozilla/security/nss/lib/softoken/legacydb/config.mk	2012-10-06 00:54:22 +0200
-@@ -95,3 +95,11 @@
- ifeq ($(OS_TARGET),WINCE)
- DEFINES += -DDBM_USING_NSPR
- endif
-+
-+ifdef WINDDK_BUILD
-+ifdef USE_64
-+OS_LIBS += msvcrt_win2003.obj
-+else
-+OS_LIBS += msvcrt_winxp.obj
-+endif
-+endif
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/security/nss/lib/sqlite/sqlite3.c nss-3.13.6/mozilla/security/nss/lib/sqlite/sqlite3.c
---- nss-3.13.6.orig/mozilla/security/nss/lib/sqlite/sqlite3.c	2010-01-08 06:42:38 +0100
-+++ nss-3.13.6/mozilla/security/nss/lib/sqlite/sqlite3.c	2012-10-06 00:54:22 +0200
-@@ -10980,7 +10980,8 @@
- ** localtime_s().
- */
- #if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
--     defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
-+     defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE) && \
-+     !defined(WINDDK_BUILD)
- #define HAVE_LOCALTIME_S 1
- #endif
- 
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/security/nss/lib/ssl/sslimpl.h nss-3.13.6/mozilla/security/nss/lib/ssl/sslimpl.h
---- nss-3.13.6.orig/mozilla/security/nss/lib/ssl/sslimpl.h	2012-02-15 22:52:08 +0100
-+++ nss-3.13.6/mozilla/security/nss/lib/ssl/sslimpl.h	2012-10-06 00:54:22 +0200
-@@ -1657,8 +1657,13 @@
- #elif defined(_WIN32_WCE)
- #define SSL_GETPID GetCurrentProcessId
- #elif defined(WIN32)
-+#ifdef WINDDK_BUILD
-+#include <windows.h>
-+#define SSL_GETPID GetCurrentProcessId
-+#else
- extern int __cdecl _getpid(void);
- #define SSL_GETPID _getpid
-+#endif
- #else
- #define SSL_GETPID() 0
- #endif
-diff -ruN --strip-trailing-cr nss-3.13.6.orig/mozilla/security/nss/lib/zlib/config.mk nss-3.13.6/mozilla/security/nss/lib/zlib/config.mk
---- nss-3.13.6.orig/mozilla/security/nss/lib/zlib/config.mk	2009-11-07 02:13:10 +0100
-+++ nss-3.13.6/mozilla/security/nss/lib/zlib/config.mk	2012-10-06 00:54:22 +0200
-@@ -46,3 +46,11 @@
- PROGRAM        =
- 
- EXTRA_LIBS     = $(LIBRARY)
-+
-+ifdef WINDDK_BUILD
-+ifdef USE_64
-+OS_LIBS += msvcrt_win2003.obj
-+else
-+OS_LIBS += msvcrt_winxp.obj
-+endif
-+endif
diff --git a/src/fe-gtk/hexchat.exe.manifest b/win32/hexchat.exe.manifest
index 39c4eb4c..1ea11920 100644
--- a/src/fe-gtk/hexchat.exe.manifest
+++ b/win32/hexchat.exe.manifest
@@ -19,4 +19,14 @@
       />
     </dependentAssembly>
   </dependency>
-</assembly>
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!--This Id value indicates the application supports Windows 7 functionality-->
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <!--This Id value indicates the application supports Windows 8 functionality-->
+      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+      <!--This Id value indicates the application supports Windows 8.1 functionality-->
+      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+    </application>
+  </compatibility>
+</assembly>
\ No newline at end of file
diff --git a/win32/hexchat.props b/win32/hexchat.props
index 8af53c79..b8ee2446 100644
--- a/win32/hexchat.props
+++ b/win32/hexchat.props
@@ -1,17 +1,16 @@
 <?xml version="1.0" encoding="utf-8"?>

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

-	<ImportGroup Label="PropertySheets" />

-

 	<PropertyGroup Label="UserMacros">

 

 		<!-- SPECIFY YOUR DEPENDENCY DIRECTORIES HERE -->

 

-		<YourDepsPath>c:\mozilla-build\hexchat\gtk</YourDepsPath>

-		<YourGendefPath>c:\mozilla-build\gendef</YourGendefPath>

-		<YourMsgfmtPath>c:\mozilla-build\msgfmt</YourMsgfmtPath>

-		<YourPerlPath>c:\mozilla-build\perl-5.20</YourPerlPath>

-		<YourPython2Path>c:\mozilla-build\python-2.7</YourPython2Path>

-		<YourPython3Path>c:\mozilla-build\python-3.4</YourPython3Path>

+		<YourDepsPath>c:\gtk-build\gtk</YourDepsPath>

+		<YourGendefPath>c:\gtk-build\gendef</YourGendefPath>

+		<YourMsgfmtPath>c:\gtk-build\msgfmt</YourMsgfmtPath>

+		<YourPerlPath>c:\gtk-build\perl-5.20</YourPerlPath>

+		<YourPython2Path>c:\gtk-build\python-2.7</YourPython2Path>

+		<YourPython3Path>c:\gtk-build\python-3.4</YourPython3Path>

+		<YourWinSparklePath>c:\gtk-build\WinSparkle</YourWinSparklePath>

 

 		<!-- YOU SHOULDN'T TOUCH ANYTHING BELOW -->

 

@@ -21,9 +20,9 @@
 		<DepsRoot>$(YourDepsPath)\$(PlatformName)</DepsRoot>

 		<GendefPath>$(YourGendefPath)</GendefPath>

 		<MsgfmtPath>$(YourMsgfmtPath)</MsgfmtPath>

+		<WinSparklePath>$(YourWinSparklePath)\$(PlatformName)</WinSparklePath>

 		<PerlPath>$(YourPerlPath)\$(PlatformName)</PerlPath>

 		<PerlLib>perl520</PerlLib>

-		<PerlOutput>hcperl</PerlOutput>

 		<Python2Path>$(YourPython2Path)\$(PlatformName)</Python2Path>

 		<Python2Lib>python27</Python2Lib>

 		<Python2Output>hcpython2</Python2Output>

@@ -37,79 +36,49 @@
 		<HexChatBuild>$(SolutionDir)..\..\hexchat-build</HexChatBuild>

 		<HexChatBin>$(HexChatBuild)\$(PlatformName)\bin\</HexChatBin>

 		<HexChatObj>$(HexChatBuild)\$(PlatformName)\obj\</HexChatObj>

-		<HexChatRel>$(HexChatBuild)\$(PlatformName)\rel</HexChatRel>

-		<HexChatCopy>

-rmdir /q /s "$(HexChatRel)"

-mkdir "$(HexChatRel)"

-echo 2&gt; portable-mode

-move portable-mode "$(HexChatRel)"

-copy changelog.url "$(HexChatRel)"

-copy readme.url "$(HexChatRel)"

-copy "$(DepsRoot)\bin\cert.pem" "$(HexChatRel)"

-copy "$(HexChatBin)hexchat.exe" "$(HexChatRel)"

-copy "$(HexChatBin)hexchat-text.exe" "$(HexChatRel)"

-copy "$(HexChatBin)thememan.exe" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\atk-1.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\cairo.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\fontconfig.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\gdk_pixbuf-2.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\gdk-win32-2.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\gio-2.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\glib-2.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\gmodule-2.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\gobject-2.0.dll" "$(HexChatRel)

-copy "$(DepsRoot)\bin\gthread-2.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\gtk-win32-2.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\harfbuzz.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\iconv.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\libeay32.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\libenchant.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\libintl.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\libpng16.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\libxml2.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\pango-1.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\pangocairo-1.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\pangoft2-1.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\pangowin32-1.0.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\pixman-1.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\ssleay32.dll" "$(HexChatRel)"

-copy "$(DepsRoot)\bin\zlib1.dll" "$(HexChatRel)"

-xcopy /q /s /i "$(DepsRoot)\lib\gtk-2.0\i686-pc-vs10\engines" "$(HexChatRel)\lib\gtk-2.0\i686-pc-vs10\engines"

-xcopy /q /s /i share "$(HexChatRel)\share"

-xcopy /q /s /i "..\..\COPYING" "$(HexChatRel)\share\doc\hexchat\"

-xcopy /q /s /i "$(DepsRoot)\share\doc" "$(HexChatRel)\share\doc"

-xcopy /q /s /i "$(DepsRoot)\share\themes\MS-Windows" "$(HexChatRel)\share\themes\MS-Windows"

-xcopy /q /s /i "$(DepsRoot)\lib\enchant\libenchant_myspell.dll" "$(HexChatRel)\lib\enchant\"

-xcopy /q /s /i "$(HexChatBin)hcchecksum.dll" "$(HexChatRel)\plugins\"

-copy "$(HexChatBin)hcdoat.dll" "$(HexChatRel)\plugins"

-copy "$(HexChatBin)hcexec.dll" "$(HexChatRel)\plugins"

-copy "$(HexChatBin)hcfishlim.dll" "$(HexChatRel)\plugins"

-copy "$(HexChatBin)hcmpcinfo.dll" "$(HexChatRel)\plugins"

-copy "$(HexChatBin)hcperl.dll" "$(HexChatRel)\plugins"

-copy "$(HexChatBin)hcpython2.dll" "$(HexChatRel)\plugins"

-copy "$(HexChatBin)hcpython3.dll" "$(HexChatRel)\plugins"

-copy "$(HexChatBin)hcupd.dll" "$(HexChatRel)\plugins"

-copy "$(HexChatBin)hcwinamp.dll" "$(HexChatRel)\plugins"

-copy "$(HexChatBin)hcsysinfo.dll" "$(HexChatRel)\plugins"

-xcopy /q /s /i "$(HexChatBin)locale" "$(HexChatRel)\share\locale"

-xcopy /q /s /i "$(DepsRoot)\share\locale" "$(HexChatRel)\share\locale"

-		</HexChatCopy>

-		<IsccPath Condition="'$(Platform)'=='Win32'">"%PROGRAMFILES%\Inno Setup 5\iscc.exe"</IsccPath>

-		<IsccPath Condition="'$(Platform)'=='x64'">"%PROGRAMFILES(x86)%\Inno Setup 5\iscc.exe"</IsccPath>

+		<HexChatLib>$(HexChatBuild)\$(PlatformName)\lib\</HexChatLib>

+		<HexChatPdb>$(HexChatBuild)\$(PlatformName)\pdb\</HexChatPdb>

+		<HexChatRel>$(HexChatBuild)\$(PlatformName)\rel\</HexChatRel>

+		<IsccPath>"$(MSBuildExtensionsPath32)\..\Inno Setup 5\iscc.exe"</IsccPath>

+	</PropertyGroup>

+

+	<PropertyGroup>

+		<LinkIncremental>false</LinkIncremental>

+		<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+		<UseDebugLibraries>false</UseDebugLibraries>

+		<WholeProgramOptimization>true</WholeProgramOptimization>

+		<CharacterSet>MultiByte</CharacterSet>

 	</PropertyGroup>

 

 	<ItemDefinitionGroup>

 		<ClCompile>

 			<WarningLevel>Level3</WarningLevel>

+			<PrecompiledHeader>NotUsing</PrecompiledHeader>

 			<DisableSpecificWarnings>4996</DisableSpecificWarnings>

-			<AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions> 

-			<WholeProgramOptimization>false</WholeProgramOptimization>

+			<AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions>

+			<WholeProgramOptimization>true</WholeProgramOptimization>

 			<!-- UNCOMMENT ONLY ONE -->

 			<!--Optimization>Disabled</Optimization-->

 			<Optimization>MaxSpeed</Optimization>

 			<!--Optimization>MinSpace</Optimization-->

 			<!--Optimization>Full</Optimization-->

+			<FunctionLevelLinking>true</FunctionLevelLinking>

+			<IntrinsicFunctions>true</IntrinsicFunctions>

+			<MultiProcessorCompilation>true</MultiProcessorCompilation>

+			<PreProcessorDefinitions>NTDDI_VERSION=NTDDI_WIN8;_WIN32_WINNT=_WIN32_WINNT_WIN8;%(PreProcessorDefinitions)</PreProcessorDefinitions>

 		</ClCompile>

+		<Lib>

+			<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>

+		</Lib>

+		<Link>

+			<ImportLibrary>$(HexChatLib)$(TargetName).lib</ImportLibrary>

+			<ProgramDatabaseFile>$(HexChatPdb)$(TargetName).pdb</ProgramDatabaseFile>

+			<SubSystem>Windows</SubSystem>

+			<GenerateDebugInformation>true</GenerateDebugInformation>

+			<EnableCOMDATFolding>true</EnableCOMDATFolding>

+			<OptimizeReferences>true</OptimizeReferences>

+			<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>

+		</Link>

 	</ItemDefinitionGroup>

 

 	<ItemGroup />

diff --git a/win32/hexchat.sln b/win32/hexchat.sln
index 03b75c5d..272c96df 100644
--- a/win32/hexchat.sln
+++ b/win32/hexchat.sln
@@ -1,7 +1,7 @@
 

 Microsoft Visual Studio Solution File, Format Version 12.00

 # Visual Studio 2013

-VisualStudioVersion = 12.0.21005.1

+VisualStudioVersion = 12.0.30501.0

 MinimumVisualStudioVersion = 10.0.40219.1

 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "..\src\common\common.vcxproj", "{87554B59-006C-4D94-9714-897B27067BA3}"

 	ProjectSection(ProjectDependencies) = postProject

@@ -78,28 +78,31 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nls", "nls\nls.vcxproj", "{
 EndProject

 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "copy", "copy\copy.vcxproj", "{C9B735E4-75BC-45AC-A5E3-39A6D076F912}"

 	ProjectSection(ProjectDependencies) = postProject

+		{B10A2C41-344C-43E0-A32D-B9587C198D8B} = {B10A2C41-344C-43E0-A32D-B9587C198D8B}

+		{DE87FFCA-9606-4116-B747-062D88A56A28} = {DE87FFCA-9606-4116-B747-062D88A56A28}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer", "installer\installer.vcxproj", "{5A0F4962-E670-4DA2-9E45-52CC47F26E2F}"

+	ProjectSection(ProjectDependencies) = postProject

 		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF} = {C2321A03-0BA7-45B3-8740-ABD82B36B0BF}

 		{19C52A0A-A790-409E-A28A-9745FF990F5C} = {19C52A0A-A790-409E-A28A-9745FF990F5C}

+		{BF0EBC16-68AD-4CD1-864C-5B56836EBE2A} = {BF0EBC16-68AD-4CD1-864C-5B56836EBE2A}

 		{4980AF24-9D42-427D-A8E6-0DF3B97C455D} = {4980AF24-9D42-427D-A8E6-0DF3B97C455D}

 		{17E4BE39-76F7-4A06-AD21-EFD0C5091F76} = {17E4BE39-76F7-4A06-AD21-EFD0C5091F76}

 		{B10A2C41-344C-43E0-A32D-B9587C198D8B} = {B10A2C41-344C-43E0-A32D-B9587C198D8B}

 		{461DC24A-A410-4171-8C02-CCDBF3702C2A} = {461DC24A-A410-4171-8C02-CCDBF3702C2A}

 		{E93E1255-95D1-4B08-8FDF-B53CC6A21280} = {E93E1255-95D1-4B08-8FDF-B53CC6A21280}

-		{87554B59-006C-4D94-9714-897B27067BA3} = {87554B59-006C-4D94-9714-897B27067BA3}

+		{A7D7CE59-2A31-48AE-BED2-A9828E241832} = {A7D7CE59-2A31-48AE-BED2-A9828E241832}

 		{5EF7F47D-D09C-43C4-BF64-B28B11A0FF91} = {5EF7F47D-D09C-43C4-BF64-B28B11A0FF91}

 		{6C0CA980-97C5-427A-BE61-5BCECAFABBDA} = {6C0CA980-97C5-427A-BE61-5BCECAFABBDA}

 		{B0E36D93-CA2A-49FE-9EB9-9C96C6016EEC} = {B0E36D93-CA2A-49FE-9EB9-9C96C6016EEC}

 		{E78C0D9A-798E-4BF6-B0CC-6FECB8CA2FCE} = {E78C0D9A-798E-4BF6-B0CC-6FECB8CA2FCE}

 		{E4BDB4C8-2335-415A-ACEE-BA88B19BFE82} = {E4BDB4C8-2335-415A-ACEE-BA88B19BFE82}

 		{DE87FFCA-9606-4116-B747-062D88A56A28} = {DE87FFCA-9606-4116-B747-062D88A56A28}

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9} = {C53145CC-D021-40C9-B97C-0249AB9A43C9}

 		{D90BC3E3-1341-4849-9354-5F40489D39D1} = {D90BC3E3-1341-4849-9354-5F40489D39D1}

-		{3C4F42FC-292A-420B-B63D-C03DFBDD8E4E} = {3C4F42FC-292A-420B-B63D-C03DFBDD8E4E}

-	EndProjectSection

-EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer", "installer\installer.vcxproj", "{5A0F4962-E670-4DA2-9E45-52CC47F26E2F}"

-	ProjectSection(ProjectDependencies) = postProject

-		{87554B59-006C-4D94-9714-897B27067BA3} = {87554B59-006C-4D94-9714-897B27067BA3}

 		{C9B735E4-75BC-45AC-A5E3-39A6D076F912} = {C9B735E4-75BC-45AC-A5E3-39A6D076F912}

+		{3C4F42FC-292A-420B-B63D-C03DFBDD8E4E} = {3C4F42FC-292A-420B-B63D-C03DFBDD8E4E}

 	EndProjectSection

 EndProject

 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "htm", "..\src\htm\htm.csproj", "{DE87FFCA-9606-4116-B747-062D88A56A28}"

@@ -119,6 +122,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python3", "..\plugins\pytho
 		{87554B59-006C-4D94-9714-897B27067BA3} = {87554B59-006C-4D94-9714-897B27067BA3}

 	EndProjectSection

 EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "notifications-winrt", "..\src\fe-gtk\notifications\notifications-winrt.vcxproj", "{C53145CC-D021-40C9-B97C-0249AB9A43C9}"

+EndProject

+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "external", "external", "{021EC1D0-FF67-4700-9AB2-EAABF1159C09}"

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libenchant_win8", "..\src\libenchant_win8\libenchant_win8.vcxproj", "{BF0EBC16-68AD-4CD1-864C-5B56836EBE2A}"

+	ProjectSection(ProjectDependencies) = postProject

+		{87554B59-006C-4D94-9714-897B27067BA3} = {87554B59-006C-4D94-9714-897B27067BA3}

+	EndProjectSection

+EndProject

 Global

 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

 		Release|Win32 = Release|Win32

@@ -201,16 +213,23 @@ Global
 		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF}.Release|Win32.Build.0 = Release|Win32

 		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF}.Release|x64.ActiveCfg = Release|x64

 		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF}.Release|x64.Build.0 = Release|x64

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9}.Release|Win32.ActiveCfg = Release|Win32

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9}.Release|Win32.Build.0 = Release|Win32

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9}.Release|x64.ActiveCfg = Release|x64

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9}.Release|x64.Build.0 = Release|x64

+		{BF0EBC16-68AD-4CD1-864C-5B56836EBE2A}.Release|Win32.ActiveCfg = Release|Win32

+		{BF0EBC16-68AD-4CD1-864C-5B56836EBE2A}.Release|Win32.Build.0 = Release|Win32

+		{BF0EBC16-68AD-4CD1-864C-5B56836EBE2A}.Release|x64.ActiveCfg = Release|x64

+		{BF0EBC16-68AD-4CD1-864C-5B56836EBE2A}.Release|x64.Build.0 = Release|x64

 	EndGlobalSection

 	GlobalSection(SolutionProperties) = preSolution

 		HideSolutionNode = FALSE

 	EndGlobalSection

 	GlobalSection(NestedProjects) = preSolution

+		{87554B59-006C-4D94-9714-897B27067BA3} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

 		{E4BDB4C8-2335-415A-ACEE-BA88B19BFE82} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

 		{E93E1255-95D1-4B08-8FDF-B53CC6A21280} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

-		{87554B59-006C-4D94-9714-897B27067BA3} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

-		{DE87FFCA-9606-4116-B747-062D88A56A28} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

-		{A7D7CE59-2A31-48AE-BED2-A9828E241832} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

+		{19C52A0A-A790-409E-A28A-9745FF990F5C} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

 		{4980AF24-9D42-427D-A8E6-0DF3B97C455D} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

 		{5EF7F47D-D09C-43C4-BF64-B28B11A0FF91} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

 		{17E4BE39-76F7-4A06-AD21-EFD0C5091F76} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

@@ -219,11 +238,14 @@ Global
 		{461DC24A-A410-4171-8C02-CCDBF3702C2A} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

 		{E78C0D9A-798E-4BF6-B0CC-6FECB8CA2FCE} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

 		{6C0CA980-97C5-427A-BE61-5BCECAFABBDA} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

-		{19C52A0A-A790-409E-A28A-9745FF990F5C} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

-		{D90BC3E3-1341-4849-9354-5F40489D39D1} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

-		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

 		{B10A2C41-344C-43E0-A32D-B9587C198D8B} = {0FD996A7-464F-4981-8380-3DCA3A244A13}

 		{C9B735E4-75BC-45AC-A5E3-39A6D076F912} = {0FD996A7-464F-4981-8380-3DCA3A244A13}

 		{5A0F4962-E670-4DA2-9E45-52CC47F26E2F} = {0FD996A7-464F-4981-8380-3DCA3A244A13}

+		{DE87FFCA-9606-4116-B747-062D88A56A28} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

+		{A7D7CE59-2A31-48AE-BED2-A9828E241832} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

+		{D90BC3E3-1341-4849-9354-5F40489D39D1} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

+		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

+		{BF0EBC16-68AD-4CD1-864C-5B56836EBE2A} = {021EC1D0-FF67-4700-9AB2-EAABF1159C09}

 	EndGlobalSection

 EndGlobal

diff --git a/win32/installer/hexchat.iss.tt b/win32/installer/hexchat.iss.tt
index 0ccf2097..6c71de12 100644
--- a/win32/installer/hexchat.iss.tt
+++ b/win32/installer/hexchat.iss.tt
@@ -124,6 +124,13 @@ Source: "gio-2.0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 Source: "glib-2.0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 Source: "gmodule-2.0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 Source: "gobject-2.0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
+#if APPARCH == "x64"
+Source: "gspawn-win64-helper.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
+Source: "gspawn-win64-helper-console.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
+#else
+Source: "gspawn-win32-helper.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
+Source: "gspawn-win32-helper-console.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
+#endif
 Source: "gthread-2.0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 Source: "gtk-win32-2.0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 Source: "harfbuzz.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
@@ -141,7 +148,9 @@ Source: "pixman-1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 Source: "ssleay32.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 Source: "zlib1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 
-Source: "lib\enchant\libenchant_myspell.dll"; DestDir: "{app}\lib\enchant"; Flags: ignoreversion; Components: libs
+Source: "plugins\hcnotifications-winrt.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: libs
+
+Source: "lib\enchant\*"; DestDir: "{app}\lib\enchant"; Flags: ignoreversion; Components: libs
 
 Source: "lib\gtk-2.0\i686-pc-vs10\engines\*"; DestDir: "{app}\lib\gtk-2.0\i686-pc-vs10\engines"; Flags: ignoreversion; Components: libs
 
@@ -153,6 +162,7 @@ Source: "share\music.png"; DestDir: "{app}\share"; Flags: ignoreversion; Compone
 Source: "plugins\hcmpcinfo.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: plugins\mpcinfo
 Source: "share\download.png"; DestDir: "{app}\share"; Flags: ignoreversion; Components: plugins\upd
 Source: "plugins\hcupd.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: plugins\upd
+Source: "WinSparkle.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: plugins\upd
 Source: "plugins\hcwinamp.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: plugins\winamp
 Source: "share\system.png"; DestDir: "{app}\share"; Flags: ignoreversion; Components: plugins\sysinfo
 Source: "plugins\hcsysinfo.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: plugins\sysinfo
@@ -166,7 +176,7 @@ Source: "hexchat-text.exe"; DestDir: "{app}"; Flags: ignoreversion; Components:
 Source: "thememan.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: xtm
 
 [Icons]
-Name: "{group}\HexChat"; Filename: "{app}\hexchat.exe"; Tasks: not portable
+Name: "{group}\HexChat"; Filename: "{app}\hexchat.exe"; AppUserModelID: "HexChat.Desktop.Notify"; Tasks: not portable
 Name: "{group}\HexChat Safe Mode"; Filename: "{app}\hexchat.exe"; Parameters: "--no-auto --no-plugins"; Tasks: not portable
 Name: "{group}\HexChat ChangeLog"; Filename: "{app}\changelog.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 165; Tasks: not portable
 Name: "{group}\HexChat ReadMe"; Filename: "{app}\readme.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 23; Tasks: not portable
@@ -220,8 +230,16 @@ end;
 
 /////////////////////////////////////////////////////////////////////
 function CheckSpellInstall(): Boolean;
+var
+	Version: TWindowsVersion;
 begin
-	Result := DirExists(ExpandConstant('{localappdata}') + '\enchant');;
+	GetWindowsVersionEx(Version);
+
+	// Windows 8 or greater has built in spell check.
+	if Version.NTPlatform and (Version.Major > 6) or ((Version.Major = 6) and (Version.Minor > 1)) then
+		Result := True
+	else
+		Result := DirExists(ExpandConstant('{localappdata}') + '\enchant\myspell');
 end;
 
 /////////////////////////////////////////////////////////////////////
@@ -250,18 +268,18 @@ begin
 	begin
 
 #if APPARCH == "x64"
-		REDIST := 'http://dl.hexchat.net/misc/vcredist_2013_x64.exe';
-		PERL := 'http://dl.hexchat.net/misc/perl/Perl%205.20.0%20x64.msi';
+		REDIST := 'https://dl.hexchat.net/misc/vcredist_2013_x64.exe';
+		PERL := 'https://dl.hexchat.net/misc/perl/Perl%205.20.0%20x64.msi';
 		PY2 := 'http://python.org/ftp/python/2.7.8/python-2.7.8.amd64.msi';
 		PY3 := 'http://python.org/ftp/python/3.4.1/python-3.4.1.amd64.msi';
 #else
-		REDIST := 'http://dl.hexchat.net/misc/vcredist_2013_x86.exe';
-		PERL := 'http://dl.hexchat.net/misc/perl/Perl%205.20.0%20x86.msi';
+		REDIST := 'https://dl.hexchat.net/misc/vcredist_2013_x86.exe';
+		PERL := 'https://dl.hexchat.net/misc/perl/Perl%205.20.0%20x86.msi';
 		PY2 := 'http://python.org/ftp/python/2.7.8/python-2.7.8.msi';
 		PY3 := 'http://python.org/ftp/python/3.4.1/python-3.4.1.msi';
 #endif
-		DOTNET := 'http://dl.hexchat.net/misc/dotnet_40.exe';
-		SPELL := 'http://dl.hexchat.net/hexchat/HexChat%20Spelling%20Dictionaries%20r2.exe';
+		DOTNET := 'https://dl.hexchat.net/misc/dotnet_40.exe';
+		SPELL := 'https://dl.hexchat.net/hexchat/HexChat%20Spelling%20Dictionaries%20r2.exe';
 
 		if not CheckVCInstall() then
 			idpAddFile(REDIST, ExpandConstant('{tmp}\vcredist.exe'));
diff --git a/win32/installer/installer.vcxproj b/win32/installer/installer.vcxproj
index a3d546c9..713411a5 100644
--- a/win32/installer/installer.vcxproj
+++ b/win32/installer/installer.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>Application</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -18,42 +19,14 @@
     <RootNamespace>installer</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>

-  </PropertyGroup>

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

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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="..\hexchat.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="..\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

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

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

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

+  <Import Project="..\hexchat.props" />

+  <PropertyGroup>

+    <OutDir>$(HexChatRel)</OutDir>

   </PropertyGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">

     <ClCompile>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

     </ClCompile>

     <Link>

       <GenerateDebugInformation>true</GenerateDebugInformation>

@@ -64,10 +37,8 @@
       <Command>

       <![CDATA[

 SET SOLUTIONDIR=$(SolutionDir)..\

-powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\win32\installer\hexchat.iss.tt" "$(SolutionDir)..\win32\installer\hexchat.iss"

-del "$(OutDir)hexchat.iss"

-type hexchat.iss >> "$(OutDir)hexchat.iss"

-$(IsccPath) /dPROJECTDIR="$(ProjectDir)" /dAPPARCH="$(Platform)" "$(OutDir)hexchat.iss"

+powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\win32\installer\hexchat.iss.tt" "$(HexChatBin)hexchat.iss"

+$(IsccPath) /dPROJECTDIR="$(ProjectDir)" /dAPPARCH="$(Platform)" "$(HexChatBin)hexchat.iss"

       ]]>

       </Command>

     </PreBuildEvent>

@@ -78,6 +49,4 @@ $(IsccPath) /dPROJECTDIR="$(ProjectDir)" /dAPPARCH="$(Platform)" "$(OutDir)hexch
     <None Include="hexchat.iss" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

 </Project>

diff --git a/win32/nls/nls.vcxproj b/win32/nls/nls.vcxproj
index 928fb225..36977f3c 100644
--- a/win32/nls/nls.vcxproj
+++ b/win32/nls/nls.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>Application</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -18,68 +19,13 @@
     <RootNamespace>nls</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>

-  </PropertyGroup>

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

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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="..\hexchat.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="..\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup 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="..\hexchat.props" />

+  <PropertyGroup>

     <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

   </PropertyGroup>

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

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

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

-    <ClCompile>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-    </ClCompile>

-    <Link>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-    </Link>

-    <PreBuildEvent>

-      <Command>cd ..\..\po

-rmdir /q /s "$(OutDir)\locale"

-mkdir "$(OutDir)\locale"

-for %%A in (*.po) do (

-mkdir "$(OutDir)\locale\%%~nA\LC_MESSAGES"

-"$(MsgfmtPath)\msgfmt" -co "$(OutDir)\locale\%%~nA\LC_MESSAGES\hexchat.mo" %%A

-)</Command>

-    </PreBuildEvent>

-  </ItemDefinitionGroup>

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

-    <ClCompile>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-    </ClCompile>

-    <Link>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-    </Link>

+  <ItemDefinitionGroup>

     <PreBuildEvent>

       <Command>cd ..\..\po

 rmdir /q /s "$(OutDir)\locale"

@@ -93,6 +39,4 @@ mkdir "$(OutDir)\locale\%%~nA\LC_MESSAGES"
   <ItemGroup>

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/win32/version.txt b/win32/version.txt
index 5cc82157..d332044b 100644
--- a/win32/version.txt
+++ b/win32/version.txt
@@ -1 +1 @@
-2.10.1
\ No newline at end of file
+2.10.2
\ No newline at end of file
diff --git a/win32/wdkpt/vs2010/Microsoft.Cpp.Win32.WDK7.props b/win32/wdkpt/vs2010/Microsoft.Cpp.Win32.WDK7.props
deleted file mode 100644
index 41e4baae..00000000
--- a/win32/wdkpt/vs2010/Microsoft.Cpp.Win32.WDK7.props
+++ /dev/null
@@ -1,68 +0,0 @@
-<!--

-***********************************************************************************************

-Microsoft.Cpp.Win32.v100.props

-

-WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have

-          created a backup copy.  Incorrect changes to this file will make it

-          impossible to load or build your projects from the command-line or the IDE.

-

-Copyright (C) Microsoft Corporation. All rights reserved.

-***********************************************************************************************

--->

-

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

-  <Import Project="$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v100\ImportBefore\*.props" Condition="Exists('$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v100\ImportBefore')" />

-

-  <PropertyGroup>

-    <PlatformToolsetVersion>100</PlatformToolsetVersion>

-

-    <WDKInstallDir>$(SystemDrive)\WinDDK\7600.16385.1</WDKInstallDir>

-

-    <VCInstallDir>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir)</VCInstallDir>

-    <VCInstallDir Condition="'$(VCInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir)</VCInstallDir>

-    <VCInstallDir Condition="'$(VCInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VC@ProductDir)</VCInstallDir>

-    <VCInstallDir Condition="'$(VCInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VC@ProductDir)</VCInstallDir>

-

-    <VSInstallDir>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir)</VSInstallDir>

-    <VSInstallDir Condition="'$(VSInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir)</VSInstallDir>

-    <VSInstallDir Condition="'$(VSInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VS@ProductDir)</VSInstallDir>

-    <VSInstallDir Condition="'$(VSInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VS@ProductDir)</VSInstallDir>

-

-    <WindowsSdkDir Condition="'$(UseEnv)' != 'true'">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder)</WindowsSdkDir>

-    <WindowsSdkDir Condition="'$(WindowsSdkDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder)</WindowsSdkDir>

-

-    <FrameworkDir Condition="'$(UseEnv)' != 'true'">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework@InstallRoot)</FrameworkDir>

-    <FrameworkDir Condition="'$(FrameworkDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework@InstallRoot)</FrameworkDir>

-

-    <FrameworkSdkDir Condition="'$(UseEnv)' != 'true'">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder)</FrameworkSdkDir>

-    <FrameworkSdkDir Condition="'$(FrameworkSdkDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder)</FrameworkSdkDir>

-

-    <FrameworkVersion Condition="'$(UseEnv)' != 'true'">v4.0</FrameworkVersion>

-    <Framework35Version Condition="'$(UseEnv)' != 'true'">v3.5</Framework35Version>

-

-    <ExecutablePath Condition="'$(ExecutablePath)' == ''">$(VCInstallDir)bin;$(WindowsSdkDir)bin\NETFX 4.0 Tools;$(WindowsSdkDir)bin;$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(FrameworkSDKDir)\bin;$(MSBuildToolsPath32);$(VSInstallDir);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH);</ExecutablePath>

-    <IncludePath>$(WDKInstallDir)\inc\api;$(WDKInstallDir)\inc\crt;$(WDKInstallDir)\inc\api\crt\stl70;$(WDKInstallDir)\inc\mfc42;$(WDKInstallDir)\inc\ddk;$(WDKInstallDir)\inc\api\dao360;</IncludePath>

-    <LibraryPath>$(WDKInstallDir)\lib\wxp\i386;$(WDKInstallDir)\lib\Crt\i386;$(WDKInstallDir)\lib\Mfc\i386;$(WDKInstallDir)\lib\ATL\i386</LibraryPath>

-    <SourcePath Condition="'$(SourcePath)' == ''">$(VCInstallDir)atlmfc\src\mfc;$(VCInstallDir)atlmfc\src\mfcm;$(VCInstallDir)atlmfc\src\atl;$(VCInstallDir)crt\src;</SourcePath>

-    <NativeExecutablePath Condition="'$(NativeExecutablePath)' == ''">$(ExecutablePath)</NativeExecutablePath>

-  </PropertyGroup>

-

-  <ItemDefinitionGroup>

-    <Link>

-      <AdditionalDependencies>msvcrt_winxp.obj;%(AdditionalDependencies)</AdditionalDependencies>

-    </Link>

-    <ResourceCompile>

-      <SuppressStartupBanner Condition="'%(ResourceCompile.SuppressStartupBanner)' == ''">true</SuppressStartupBanner>

-    </ResourceCompile>

-    <ManifestResourceCompile>

-      <SuppressStartupBanner Condition="'%(ManifestResourceCompile.SuppressStartupBanner)'==''">true</SuppressStartupBanner>

-    </ManifestResourceCompile>

-    <Manifest>

-      <EnableDPIAwareness Condition="'$(EnableDPIAwareness)' == '' AND '$(UseOfMFC)' == 'static'">true</EnableDPIAwareness>

-      <EnableDPIAwareness Condition="'$(EnableDPIAwareness)' == '' AND '$(UseOfMFC)' == 'dynamic'">true</EnableDPIAwareness>

-      <EnableDPIAwareness Condition="'$(EnableDPIAwareness)' == '' AND '$(UseOfMFC)' != 'static' AND '$(UseOfMFC)' != 'dynamic'">false</EnableDPIAwareness>

-    </Manifest>

-  </ItemDefinitionGroup>

-

-  <Import Project="$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v100\ImportAfter\*.props" Condition="Exists('$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v100\ImportAfter')" />

-</Project>

diff --git a/win32/wdkpt/vs2010/Microsoft.Cpp.Win32.WDK7.targets b/win32/wdkpt/vs2010/Microsoft.Cpp.Win32.WDK7.targets
deleted file mode 100644
index f68a78bc..00000000
--- a/win32/wdkpt/vs2010/Microsoft.Cpp.Win32.WDK7.targets
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--

-***********************************************************************************************

-Microsoft.Cpp.Win32.v100.targets

-

-WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have

-          created a backup copy.  Incorrect changes to this file will make it

-          impossible to load or build your projects from the command-line or the IDE.

-

-This file defines the steps/targets required to build Visual C++ (version 10.0) projects 

-specifically on x86 platforms.

-

-Copyright (C) Microsoft Corporation. All rights reserved.

-***********************************************************************************************

--->

-

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

-  <Import Project="$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v100\ImportBefore\*.targets" Condition="Exists('$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v100\ImportBefore')" />

-

-  <Import Project="$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v100\ImportAfter\*.targets" Condition="Exists('$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v100\ImportAfter')" />

-</Project>

diff --git a/win32/wdkpt/vs2010/Microsoft.Cpp.x64.WDK7.props b/win32/wdkpt/vs2010/Microsoft.Cpp.x64.WDK7.props
deleted file mode 100644
index 7f72f8e2..00000000
--- a/win32/wdkpt/vs2010/Microsoft.Cpp.x64.WDK7.props
+++ /dev/null
@@ -1,68 +0,0 @@
-<!--

-***********************************************************************************************

-Microsoft.Cpp.x64.v100.props

-

-WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have

-          created a backup copy.  Incorrect changes to this file will make it

-          impossible to load or build your projects from the command-line or the IDE.

-

-Copyright (C) Microsoft Corporation. All rights reserved.

-***********************************************************************************************

--->

-

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

-  <Import Project="$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v100\ImportBefore\*.props" Condition="Exists('$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v100\ImportBefore')" />

-

-  <PropertyGroup>

-    <PlatformToolsetVersion>100</PlatformToolsetVersion>

-

-    <WDKInstallDir>$(SystemDrive)\WinDDK\7600.16385.1</WDKInstallDir>

-

-	<VCInstallDir>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir)</VCInstallDir>

-    <VCInstallDir Condition="'$(VCInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir)</VCInstallDir>

-    <VCInstallDir Condition="'$(VCInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VC@ProductDir)</VCInstallDir>

-    <VCInstallDir Condition="'$(VCInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VC@ProductDir)</VCInstallDir>

-

-    <VSInstallDir>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir)</VSInstallDir>

-    <VSInstallDir Condition="'$(VSInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir)</VSInstallDir>

-    <VSInstallDir Condition="'$(VSInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VS@ProductDir)</VSInstallDir>

-    <VSInstallDir Condition="'$(VSInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VS@ProductDir)</VSInstallDir>

-

-    <WindowsSdkDir Condition="'$(UseEnv)' != 'true'">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder)</WindowsSdkDir>

-    <WindowsSdkDir Condition="'$(WindowsSdkDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder)</WindowsSdkDir>

-

-    <FrameworkDir Condition="'$(UseEnv)' != 'true'">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework@InstallRoot)</FrameworkDir>

-    <FrameworkDir Condition="'$(FrameworkDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework@InstallRoot)</FrameworkDir>

-

-    <FrameworkSdkDir Condition="'$(UseEnv)' != 'true'">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder)</FrameworkSdkDir>

-    <FrameworkSdkDir Condition="'$(FrameworkSdkDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder)</FrameworkSdkDir>

-

-    <FrameworkVersion Condition="'$(UseEnv)' != 'true'">v4.0</FrameworkVersion>

-    <Framework35Version Condition="'$(UseEnv)' != 'true'">v3.5</Framework35Version>

-

-    <ExecutablePath Condition="'$(ExecutablePath)' == ''">$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSdkDir)bin\NETFX 4.0 Tools;$(WindowsSdkDir)bin;$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(FrameworkSDKDir)\bin;$(FrameworkSDKDir)\lib\win64;$(MSBuildToolsPath32);$(FxCopDir);$(PATH);</ExecutablePath>

-    <IncludePath>$(WDKInstallDir)\inc\api;$(WDKInstallDir)\inc\crt;$(WDKInstallDir)\inc\api\crt\stl70;$(WDKInstallDir)\inc\mfc42;$(WDKInstallDir)\inc\ddk;$(WDKInstallDir)\inc\api\dao360;</IncludePath>

-    <LibraryPath>$(WDKInstallDir)\lib\wnet\amd64;$(WDKInstallDir)\lib\Crt\amd64;$(WDKInstallDir)\lib\Mfc\amd64;$(WDKInstallDir)\lib\ATL\amd64;</LibraryPath>

-    <SourcePath Condition="'$(SourcePath)' == ''">$(VCInstallDir)atlmfc\src\mfc;$(VCInstallDir)atlmfc\src\mfcm;$(VCInstallDir)atlmfc\src\atl;$(VCInstallDir)crt\src;</SourcePath>

-    <NativeExecutablePath Condition="'$(NativeExecutablePath)' == ''">$(VCInstallDir)bin\AMD64;$(VCInstallDir)VCPackages;$(WindowsSdkDir)bin\NETFX 4.0 Tools\x64;$(WindowsSdkDir)bin\NETFX 4.0 Tools;$(WindowsSdkDir)bin\x64;$(WindowsSdkDir)bin\win64\x64;$(WindowsSdkDir)bin;$(MSBuildToolsPath);$(PATH);</NativeExecutablePath>

-  </PropertyGroup>

-

-  <ItemDefinitionGroup>

-    <Link>

-      <AdditionalDependencies>msvcrt_win2003.obj;%(AdditionalDependencies)</AdditionalDependencies>

-    </Link>

-    <ResourceCompile>

-      <SuppressStartupBanner Condition="'%(ResourceCompile.SuppressStartupBanner)' == ''">true</SuppressStartupBanner>

-    </ResourceCompile>

-    <ManifestResourceCompile>

-      <SuppressStartupBanner Condition="'%(ManifestResourceCompile.SuppressStartupBanner)'==''">true</SuppressStartupBanner>

-    </ManifestResourceCompile>

-    <Manifest>

-      <EnableDPIAwareness Condition="'$(EnableDPIAwareness)' == '' AND '$(UseOfMFC)' == 'static'">true</EnableDPIAwareness>

-      <EnableDPIAwareness Condition="'$(EnableDPIAwareness)' == '' AND '$(UseOfMFC)' == 'dynamic'">true</EnableDPIAwareness>

-      <EnableDPIAwareness Condition="'$(EnableDPIAwareness)' == '' AND '$(UseOfMFC)' != 'static' AND '$(UseOfMFC)' != 'dynamic'">false</EnableDPIAwareness>

-    </Manifest>

-  </ItemDefinitionGroup>

-

-  <Import Project="$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v100\ImportAfter\*.props" Condition="Exists('$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v100\ImportAfter')" />

-</Project>

diff --git a/win32/wdkpt/vs2010/Microsoft.Cpp.x64.WDK7.targets b/win32/wdkpt/vs2010/Microsoft.Cpp.x64.WDK7.targets
deleted file mode 100644
index fa6651e1..00000000
--- a/win32/wdkpt/vs2010/Microsoft.Cpp.x64.WDK7.targets
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--

-***********************************************************************************************

-Microsoft.Cpp.x64.v100.targets

-

-WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have

-          created a backup copy.  Incorrect changes to this file will make it

-          impossible to load or build your projects from the command-line or the IDE.

-

-This file defines the steps/targets required to build Visual C++ (version 10.0) projects 

-specifically on X64 platforms.

-

-Copyright (C) Microsoft Corporation. All rights reserved.

-***********************************************************************************************

--->

-

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

-  <Import Project="$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v100\ImportBefore\*.targets" Condition="Exists('$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v100\ImportBefore')" />

-

-  <Import Project="$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v100\ImportAfter\*.targets" Condition="Exists('$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v100\ImportAfter')" />

-</Project>

diff --git a/win32/wdkpt/vs2010/wdkpt.aip b/win32/wdkpt/vs2010/wdkpt.aip
deleted file mode 100644
index 38502e5e..00000000
--- a/win32/wdkpt/vs2010/wdkpt.aip
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

-<DOCUMENT Type="Advanced Installer" CreateVersion="9.2" version="9.5" Modules="simple" RootPath="." Language="en" Id="{F800981F-A57B-40E4-91FE-3C228741E1AD}">

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiValidationComponent">

-    <ROW Table="File" Column="Sequence" MinValue="1" MaxValue="32767" Description="Sequence with respect to the media images; order must track cabinet order." Options="0" ColumnType="2" ColumnIndex="7" ColumnSize="2" MsiKey="File#Sequence"/>

-    <ROW Table="Media" Column="LastSequence" MinValue="0" MaxValue="32767" Description="File sequence number for the last file for this media." Options="0" ColumnType="2" ColumnIndex="1" ColumnSize="2" MsiKey="Media#LastSequence"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">

-    <ROW Property="ALLUSERS" Value="2" MultiBuildValue="DefaultBuild:1"/>

-    <ROW Property="ARPCOMMENTS" Value="This installer database contains the logic and data required to install [|ProductName]." ValueLocId="*"/>

-    <ROW Property="ARPHELPLINK" Value="http://www.hexchat.org/developers/wdk-platform-toolset"/>

-    <ROW Property="ARPURLINFOABOUT" Value="http://www.hexchat.org/developers/wdk-platform-toolset"/>

-    <ROW Property="ARPURLUPDATEINFO" Value="http://www.hexchat.org/developers/wdk-platform-toolset"/>

-    <ROW Property="Manufacturer" Value="HexChat" ValueLocId="*"/>

-    <ROW Property="ProductCode" Value="1033:{6C7B98A1-9E15-4756-9FCA-0566ED776BE3} " Type="16"/>

-    <ROW Property="ProductLanguage" Value="1033"/>

-    <ROW Property="ProductName" Value="Visual Studio 2010 Windows Driver Kit Platform Toolset" ValueLocId="*"/>

-    <ROW Property="ProductVersion" Value="1.1" Type="32"/>

-    <ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>

-    <ROW Property="UpgradeCode" Value="{1947FE78-21A1-4B81-99CE-E07AAEE6077D}"/>

-    <ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>

-    <ROW Property="WindowsType9XDisplay" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">

-    <ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1"/>

-    <ROW Directory="MSBuild_Dir" Directory_Parent="ProgramFilesFolder" DefaultDir="MSBuild"/>

-    <ROW Directory="Microsoft.Cpp_Dir" Directory_Parent="MSBuild_Dir" DefaultDir="Micros~1.Cpp|Microsoft.Cpp"/>

-    <ROW Directory="PlatformToolsets_1_Dir" Directory_Parent="x64_Dir" DefaultDir="Platfo~1|PlatformToolsets"/>

-    <ROW Directory="PlatformToolsets_Dir" Directory_Parent="Win32_Dir" DefaultDir="Platfo~1|PlatformToolsets"/>

-    <ROW Directory="Platforms_Dir" Directory_Parent="v4.0_Dir" DefaultDir="Platfo~1|Platforms"/>

-    <ROW Directory="ProgramFilesFolder" Directory_Parent="TARGETDIR" DefaultDir="Progra~1|ProgramFilesFolder" IsPseudoRoot="1"/>

-    <ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>

-    <ROW Directory="WDK7_1_Dir" Directory_Parent="PlatformToolsets_1_Dir" DefaultDir="WDK7"/>

-    <ROW Directory="WDK7_Dir" Directory_Parent="PlatformToolsets_Dir" DefaultDir="WDK7"/>

-    <ROW Directory="Win32_Dir" Directory_Parent="Platforms_Dir" DefaultDir="Win32"/>

-    <ROW Directory="v4.0_Dir" Directory_Parent="Microsoft.Cpp_Dir" DefaultDir="v4.0"/>

-    <ROW Directory="x64_Dir" Directory_Parent="Platforms_Dir" DefaultDir="x64"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">

-    <ROW Component="Microsoft.Cpp.Win32.WDK7.props" ComponentId="{3EA16365-3C7E-4F84-A326-C7F28B33F487}" Directory_="WDK7_Dir" Attributes="0" KeyPath="Microsoft.Cpp.Win32.WDK7.props" Type="0"/>

-    <ROW Component="Microsoft.Cpp.x64.WDK7.props" ComponentId="{50DB333C-5D3E-4A14-80B9-BA1D727BD220}" Directory_="WDK7_1_Dir" Attributes="0" KeyPath="Microsoft.Cpp.x64.WDK7.props" Type="0"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">

-    <ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="Microsoft.Cpp.Win32.WDK7.props Microsoft.Cpp.x64.WDK7.props"/>

-    <ATTRIBUTE name="CurrentFeature" value="MainFeature"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">

-    <ROW File="Microsoft.Cpp.Win32.WDK7.props" Component_="Microsoft.Cpp.Win32.WDK7.props" FileName="Micros~1.pro|Microsoft.Cpp.Win32.WDK7.props" Attributes="0" SourcePath="Microsoft.Cpp.Win32.WDK7.props" SelfReg="false" NextFile="Microsoft.Cpp.Win32.WDK7.targets"/>

-    <ROW File="Microsoft.Cpp.Win32.WDK7.targets" Component_="Microsoft.Cpp.Win32.WDK7.props" FileName="Micros~1.tar|Microsoft.Cpp.Win32.WDK7.targets" Attributes="0" SourcePath="Microsoft.Cpp.Win32.WDK7.targets" SelfReg="false" NextFile="Microsoft.Cpp.x64.WDK7.props"/>

-    <ROW File="Microsoft.Cpp.x64.WDK7.props" Component_="Microsoft.Cpp.x64.WDK7.props" FileName="Micros~1.pro|Microsoft.Cpp.x64.WDK7.props" Attributes="0" SourcePath="Microsoft.Cpp.x64.WDK7.props" SelfReg="false" NextFile="Microsoft.Cpp.x64.WDK7.targets"/>

-    <ROW File="Microsoft.Cpp.x64.WDK7.targets" Component_="Microsoft.Cpp.x64.WDK7.props" FileName="Micros~1.tar|Microsoft.Cpp.x64.WDK7.targets" Attributes="0" SourcePath="Microsoft.Cpp.x64.WDK7.targets" SelfReg="false"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">

-    <ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="." PackageFileName="Visual Studio 2010 Windows Driver Kit Platform Toolset 1.1" Languages="en" InstallationType="4" UseLargeSchema="true"/>

-    <ATTRIBUTE name="CurrentBuild" value="DefaultBuild"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">

-    <ROW Path="&lt;AI_DICTS&gt;ui.ail"/>

-    <ROW Path="&lt;AI_DICTS&gt;ui_en.ail"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">

-    <ROW Fragment="CommonUI.aip" Path="&lt;AI_FRAGS&gt;CommonUI.aip"/>

-    <ROW Fragment="MaintenanceTypeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceTypeDlg.aip"/>

-    <ROW Fragment="MaintenanceWelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceWelcomeDlg.aip"/>

-    <ROW Fragment="SequenceDialogs.aip" Path="&lt;AI_THEMES&gt;classic\fragments\SequenceDialogs.aip"/>

-    <ROW Fragment="Sequences.aip" Path="&lt;AI_FRAGS&gt;Sequences.aip"/>

-    <ROW Fragment="StaticUIStrings.aip" Path="&lt;AI_FRAGS&gt;StaticUIStrings.aip"/>

-    <ROW Fragment="UI.aip" Path="&lt;AI_THEMES&gt;classic\fragments\UI.aip"/>

-    <ROW Fragment="Validation.aip" Path="&lt;AI_FRAGS&gt;Validation.aip"/>

-    <ROW Fragment="VerifyRemoveDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRemoveDlg.aip"/>

-    <ROW Fragment="VerifyRepairDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRepairDlg.aip"/>

-    <ROW Fragment="WelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\WelcomeDlg.aip"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">

-    <ROW Name="aicustact.dll" SourcePath="&lt;AI_CUSTACTS&gt;aicustact.dll"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiControlComponent">

-    <ATTRIBUTE name="FixedSizeBitmaps" value="0"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiControlEventComponent">

-    <ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL" Ordering="1"/>

-    <ROW Dialog_="MaintenanceWelcomeDlg" Control_="Next" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="99"/>

-    <ROW Dialog_="CustomizeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_MAINT" Ordering="101"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_INSTALL" Ordering="197"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL" Ordering="201"/>

-    <ROW Dialog_="CustomizeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="1"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_MAINT" Ordering="198"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="202"/>

-    <ROW Dialog_="MaintenanceTypeDlg" Control_="ChangeButton" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="501"/>

-    <ROW Dialog_="MaintenanceTypeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceWelcomeDlg" Condition="AI_MAINT" Ordering="1"/>

-    <ROW Dialog_="MaintenanceTypeDlg" Control_="RemoveButton" Event="NewDialog" Argument="VerifyRemoveDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="601"/>

-    <ROW Dialog_="VerifyRemoveDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="1"/>

-    <ROW Dialog_="MaintenanceTypeDlg" Control_="RepairButton" Event="NewDialog" Argument="VerifyRepairDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="601"/>

-    <ROW Dialog_="VerifyRepairDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="1"/>

-    <ROW Dialog_="VerifyRepairDlg" Control_="Repair" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="399"/>

-    <ROW Dialog_="VerifyRemoveDlg" Control_="Remove" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="299"/>

-    <ROW Dialog_="PatchWelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_PATCH" Ordering="201"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_PATCH" Ordering="199"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="203"/>

-    <ROW Dialog_="ResumeDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_RESUME" Ordering="299"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">

-    <ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>

-    <ROW Action="AI_InstallModeCheck" Type="1" Source="aicustact.dll" Target="UpdateInstallMode" WithoutSeq="true"/>

-    <ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>

-    <ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>

-    <ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>

-    <ROW Action="AI_ResolveLocalizedCredentials" Type="1" Source="aicustact.dll" Target="GetLocalizedCredentials"/>

-    <ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>

-    <ROW Action="AI_STORE_LOCATION" Type="51" Source="ARPINSTALLLOCATION" Target="[APPDIR]"/>

-    <ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]"/>

-    <ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]"/>

-    <ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent">

-    <ROW Action="AI_DOWNGRADE" Condition="AI_NEWERPRODUCTFOUND AND (UILevel &lt;&gt; 5)" Sequence="210"/>

-    <ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>

-    <ROW Action="AI_STORE_LOCATION" Condition="(Not Installed) OR REINSTALL" Sequence="1501"/>

-    <ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1399"/>

-    <ROW Action="AI_ResolveKnownFolders" Sequence="52"/>

-    <ROW Action="AI_ResolveLocalizedCredentials" Sequence="51"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">

-    <ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>

-    <ROW Action="AI_ResolveKnownFolders" Sequence="52"/>

-    <ROW Action="AI_ResolveLocalizedCredentials" Sequence="51"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">

-    <ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]" DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">

-    <ATTRIBUTE name="UsedTheme" value="classic"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiUpgradeComponent">

-    <ROW UpgradeCode="[|UpgradeCode]" VersionMax="[|ProductVersion]" Attributes="1025" ActionProperty="OLDPRODUCTS"/>

-    <ROW UpgradeCode="[|UpgradeCode]" VersionMin="[|ProductVersion]" Attributes="2" ActionProperty="AI_NEWERPRODUCTFOUND"/>

-  </COMPONENT>

-</DOCUMENT>

diff --git a/win32/wdkpt/vs2012/Microsoft.Cpp.Win32.WDK7.props b/win32/wdkpt/vs2012/Microsoft.Cpp.Win32.WDK7.props
deleted file mode 100644
index 8a9fe767..00000000
--- a/win32/wdkpt/vs2012/Microsoft.Cpp.Win32.WDK7.props
+++ /dev/null
@@ -1,52 +0,0 @@
-<!--

-***********************************************************************************************

-Microsoft.Cpp.Win32.v110.props

-

-WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have

-          created a backup copy.  Incorrect changes to this file will make it

-          impossible to load or build your projects from the command-line or the IDE.

-

-Copyright (C) Microsoft Corporation. All rights reserved.

-***********************************************************************************************

--->

-

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

-  <Import Project="$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v110\ImportBefore\*.props" Condition="Exists('$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v110\ImportBefore')" />

-

-  <PropertyGroup>

-    <WDKInstallDir>$(SystemDrive)\WinDDK\7600.16385.1</WDKInstallDir>

-    <!-- Required for enabling Team Build for packaging Windows Store app projects -->

-    <OutDirWasSpecified Condition=" '$(OutDir)'!='' AND '$(OutDirWasSpecified)'=='' ">true</OutDirWasSpecified>

-    <OutDirWasSpecified Condition=" '$(OutDir)'=='' AND '$(OutDirWasSpecified)'=='' ">false</OutDirWasSpecified>

-

-    <IntDir Condition="'$(IntDir)'=='' AND '$(IntermediateOutputPath)'!=''">$(IntermediateOutputPath)</IntDir>

-    <IntDir Condition="'$(IntDir)'=='' AND '$(IntermediateOutputPath)'==''">$(Configuration)\</IntDir>

-    <OutDir Condition="'$(OutDir)'=='' AND '$(SolutionDir)' != ''">$(SolutionDir)$(Configuration)\</OutDir>

-    <OutDir Condition="'$(OutDir)'=='' AND '$(SolutionDir)' == ''">$(IntDir)</OutDir>

-  </PropertyGroup>

-  

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

-

-  <PropertyGroup>

-    <ExecutablePath Condition="'$(ExecutablePath)' == ''">$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(VSInstallDir);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH);</ExecutablePath>

-    <IncludePath>$(WDKInstallDir)\inc\api;$(WDKInstallDir)\inc\crt;$(WDKInstallDir)\inc\api\crt\stl70;$(WDKInstallDir)\inc\mfc42;$(WDKInstallDir)\inc\ddk;$(WDKInstallDir)\inc\api\dao360;</IncludePath>

-    <ReferencePath Condition="'$(ReferencePath)' == ''">$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib</ReferencePath>

-    <LibraryPath>$(WDKInstallDir)\lib\wxp\i386;$(WDKInstallDir)\lib\Crt\i386;$(WDKInstallDir)\lib\Mfc\i386;$(WDKInstallDir)\lib\ATL\i386</LibraryPath>

-    <LibraryWPath Condition="'$(LibraryWPath)' == ''">$(WindowsSDK_MetadataPath)</LibraryWPath>

-    <SourcePath Condition="'$(SourcePath)' == ''">$(VCInstallDir)atlmfc\src\mfc;$(VCInstallDir)atlmfc\src\mfcm;$(VCInstallDir)atlmfc\src\atl;$(VCInstallDir)crt\src;</SourcePath>

-    <ExcludePath Condition="'$(ExcludePath)' == ''">$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);$(MSBuildToolsPath32);$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;</ExcludePath>

-    <NativeExecutablePath Condition="'$(NativeExecutablePath)' == ''">$(ExecutablePath)</NativeExecutablePath>

-    <DebugCppRuntimeFilesPath Condition="'$(DebugCppRuntimeFilesPath)' == ''">$(VCInstallDir)redist\Debug_NonRedist\x86</DebugCppRuntimeFilesPath>

-  </PropertyGroup>

-

-  <ItemDefinitionGroup>

-    <Link>

-      <AdditionalDependencies>msvcrt_winxp.obj;%(AdditionalDependencies)</AdditionalDependencies>

-      <MinimumRequiredVersion>5.1</MinimumRequiredVersion>

-    </Link>

-  </ItemDefinitionGroup>

-

-  <Import Project="$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v110\ImportAfter\*.props" Condition="Exists('$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v110\ImportAfter')" />

-

-  <Import Project="$(VCTargetsPath)\Platforms\Win32\Microsoft.Cpp.Win32.Common.props" />

-</Project>

diff --git a/win32/wdkpt/vs2012/Microsoft.Cpp.Win32.WDK7.targets b/win32/wdkpt/vs2012/Microsoft.Cpp.Win32.WDK7.targets
deleted file mode 100644
index 3f50fc93..00000000
--- a/win32/wdkpt/vs2012/Microsoft.Cpp.Win32.WDK7.targets
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--

-***********************************************************************************************

-Microsoft.Cpp.Win32.v110.targets

-

-WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have

-          created a backup copy.  Incorrect changes to this file will make it

-          impossible to load or build your projects from the command-line or the IDE.

-

-This file defines the steps/targets required to build Visual C++ (version 11.0) projects

-specifically on x86 platforms.

-

-Copyright (C) Microsoft Corporation. All rights reserved.

-***********************************************************************************************

--->

-

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

-  <Import Project="$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v110\ImportBefore\*.targets" Condition="Exists('$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v110\ImportBefore')" />

-  <Import Project="$(VCTargetsPath)\Microsoft.CppCommon.targets" />

-  <Import Project="$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v110\ImportAfter\*.targets" Condition="Exists('$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\v110\ImportAfter')" />

-</Project>

diff --git a/win32/wdkpt/vs2012/Microsoft.Cpp.x64.WDK7.props b/win32/wdkpt/vs2012/Microsoft.Cpp.x64.WDK7.props
deleted file mode 100644
index 9d7825c0..00000000
--- a/win32/wdkpt/vs2012/Microsoft.Cpp.x64.WDK7.props
+++ /dev/null
@@ -1,52 +0,0 @@
-<!--

-***********************************************************************************************

-Microsoft.Cpp.x64.v110.props

-

-WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have

-          created a backup copy.  Incorrect changes to this file will make it

-          impossible to load or build your projects from the command-line or the IDE.

-

-Copyright (C) Microsoft Corporation. All rights reserved.

-***********************************************************************************************

--->

-

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

-  <Import Project="$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v110\ImportBefore\*.props" Condition="Exists('$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v110\ImportBefore')" />

-

-  <PropertyGroup>

-    <WDKInstallDir>$(SystemDrive)\WinDDK\7600.16385.1</WDKInstallDir>

-    <!-- Required for enabling Team Build for packaging Windows Store app projects -->

-    <OutDirWasSpecified Condition=" '$(OutDir)'!='' AND '$(OutDirWasSpecified)'=='' ">true</OutDirWasSpecified>

-    <OutDirWasSpecified Condition=" '$(OutDir)'=='' AND '$(OutDirWasSpecified)'=='' ">false</OutDirWasSpecified>

-

-    <IntDir Condition="'$(IntDir)'=='' AND '$(IntermediateOutputPath)'!=''">$(IntermediateOutputPath)</IntDir>

-    <IntDir Condition="'$(IntDir)'=='' AND '$(IntermediateOutputPath)'==''">$(Platform)\$(Configuration)\</IntDir>

-    <OutDir Condition="'$(OutDir)'=='' AND '$(SolutionDir)' == ''">$(IntDir)</OutDir>

-    <OutDir Condition="'$(OutDir)'=='' AND '$(SolutionDir)' != ''">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>

-  </PropertyGroup>

-

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

-

-  <PropertyGroup>

-    <ExecutablePath Condition="'$(ExecutablePath)' == ''">$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH);</ExecutablePath>

-    <IncludePath>$(WDKInstallDir)\inc\api;$(WDKInstallDir)\inc\crt;$(WDKInstallDir)\inc\api\crt\stl70;$(WDKInstallDir)\inc\mfc42;$(WDKInstallDir)\inc\ddk;$(WDKInstallDir)\inc\api\dao360;</IncludePath>

-    <ReferencePath Condition="'$(ReferencePath)' == ''">$(VCInstallDir)atlmfc\lib\amd64;$(VCInstallDir)lib\amd64;</ReferencePath>

-    <LibraryPath>$(WDKInstallDir)\lib\wnet\amd64;$(WDKInstallDir)\lib\Crt\amd64;$(WDKInstallDir)\lib\Mfc\amd64;$(WDKInstallDir)\lib\ATL\amd64;</LibraryPath>

-    <LibraryWPath Condition="'$(LibraryWPath)' == ''">$(WindowsSDK_MetadataPath)</LibraryWPath>

-    <SourcePath Condition="'$(SourcePath)' == ''">$(VCInstallDir)atlmfc\src\mfc;$(VCInstallDir)atlmfc\src\mfcm;$(VCInstallDir)atlmfc\src\atl;$(VCInstallDir)crt\src;</SourcePath>

-    <ExcludePath Condition="'$(ExcludePath)' == ''">$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);$(MSBuildToolsPath);$(MSBuildToolsPath32);$(VCInstallDir)atlmfc\lib\amd64;$(VCInstallDir)lib\amd64;</ExcludePath>

-    <NativeExecutablePath Condition="'$(NativeExecutablePath)' == ''">$(VCInstallDir)bin\AMD64;$(VCInstallDir)VCPackages;$(WindowsSDK_ExecutablePath_x64);$(WindowsSDK_ExecutablePath_x86);$(MSBuildToolsPath);$(PATH);</NativeExecutablePath>

-    <DebugCppRuntimeFilesPath Condition="'$(DebugCppRuntimeFilesPath)' == ''">$(VCInstallDir)redist\Debug_NonRedist\x64</DebugCppRuntimeFilesPath>	

-  </PropertyGroup>

-

-  <ItemDefinitionGroup>

-    <Link>

-      <AdditionalDependencies>msvcrt_win2003.obj;%(AdditionalDependencies)</AdditionalDependencies>

-      <MinimumRequiredVersion>5.2</MinimumRequiredVersion>

-    </Link>

-  </ItemDefinitionGroup>

-

-  <Import Project="$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v110\ImportAfter\*.props" Condition="Exists('$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v110\ImportAfter')" />

-

-  <Import Project="$(VCTargetsPath)\Platforms\x64\Microsoft.Cpp.x64.Common.props" />

-</Project>

diff --git a/win32/wdkpt/vs2012/Microsoft.Cpp.x64.WDK7.targets b/win32/wdkpt/vs2012/Microsoft.Cpp.x64.WDK7.targets
deleted file mode 100644
index 2c6271c8..00000000
--- a/win32/wdkpt/vs2012/Microsoft.Cpp.x64.WDK7.targets
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--

-***********************************************************************************************

-Microsoft.Cpp.x64.v110.targets

-

-WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have

-          created a backup copy.  Incorrect changes to this file will make it

-          impossible to load or build your projects from the command-line or the IDE.

-

-This file defines the steps/targets required to build Visual C++ (version 11.0) projects

-specifically on X64 platforms.

-

-Copyright (C) Microsoft Corporation. All rights reserved.

-***********************************************************************************************

--->

-

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

-  <Import Project="$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v110\ImportBefore\*.targets" Condition="Exists('$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v110\ImportBefore')" />

-  <Import Project="$(VCTargetsPath)\Microsoft.CppCommon.targets" />

-  <Import Project="$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v110\ImportAfter\*.targets" Condition="Exists('$(VCTargetsPath)\Platforms\x64\PlatformToolsets\v110\ImportAfter')" />

-</Project>

diff --git a/win32/wdkpt/vs2012/wdkpt.aip b/win32/wdkpt/vs2012/wdkpt.aip
deleted file mode 100644
index b6763d29..00000000
--- a/win32/wdkpt/vs2012/wdkpt.aip
+++ /dev/null
@@ -1,138 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

-<DOCUMENT Type="Advanced Installer" CreateVersion="9.2" version="9.5" Modules="simple" RootPath="." Language="en" Id="{F800981F-A57B-40E4-91FE-3C228741E1AD}">

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiValidationComponent">

-    <ROW Table="File" Column="Sequence" MinValue="1" MaxValue="32767" Description="Sequence with respect to the media images; order must track cabinet order." Options="0" ColumnType="2" ColumnIndex="7" ColumnSize="2" MsiKey="File#Sequence"/>

-    <ROW Table="Media" Column="LastSequence" MinValue="0" MaxValue="32767" Description="File sequence number for the last file for this media." Options="0" ColumnType="2" ColumnIndex="1" ColumnSize="2" MsiKey="Media#LastSequence"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">

-    <ROW Property="ALLUSERS" Value="2" MultiBuildValue="DefaultBuild:1"/>

-    <ROW Property="ARPCOMMENTS" Value="This installer database contains the logic and data required to install [|ProductName]." ValueLocId="*"/>

-    <ROW Property="ARPHELPLINK" Value="http://www.hexchat.org/developers/wdk-platform-toolset"/>

-    <ROW Property="ARPURLINFOABOUT" Value="http://www.hexchat.org/developers/wdk-platform-toolset"/>

-    <ROW Property="ARPURLUPDATEINFO" Value="http://www.hexchat.org/developers/wdk-platform-toolset"/>

-    <ROW Property="Manufacturer" Value="HexChat" ValueLocId="*"/>

-    <ROW Property="ProductCode" Value="1033:{2EE972A9-9913-48AF-B0D7-BF76215BE858} " Type="16"/>

-    <ROW Property="ProductLanguage" Value="1033"/>

-    <ROW Property="ProductName" Value="Visual Studio 2012 Windows Driver Kit Platform Toolset" ValueLocId="*"/>

-    <ROW Property="ProductVersion" Value="1.2" Type="32"/>

-    <ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>

-    <ROW Property="UpgradeCode" Value="{A569B016-AF0C-4D04-8EF8-0144088E92D0}"/>

-    <ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>

-    <ROW Property="WindowsType9XDisplay" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">

-    <ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1"/>

-    <ROW Directory="MSBuild_Dir" Directory_Parent="ProgramFilesFolder" DefaultDir="MSBuild"/>

-    <ROW Directory="Microsoft.Cpp_Dir" Directory_Parent="MSBuild_Dir" DefaultDir="Micros~1.Cpp|Microsoft.Cpp"/>

-    <ROW Directory="PlatformToolsets_1_Dir" Directory_Parent="x64_Dir" DefaultDir="Platfo~1|PlatformToolsets"/>

-    <ROW Directory="PlatformToolsets_Dir" Directory_Parent="Win32_Dir" DefaultDir="Platfo~1|PlatformToolsets"/>

-    <ROW Directory="Platforms_Dir" Directory_Parent="V110_Dir" DefaultDir="Platfo~1|Platforms"/>

-    <ROW Directory="ProgramFilesFolder" Directory_Parent="TARGETDIR" DefaultDir="Progra~1|ProgramFilesFolder" IsPseudoRoot="1"/>

-    <ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>

-    <ROW Directory="V110_Dir" Directory_Parent="v4.0_Dir" DefaultDir="V110"/>

-    <ROW Directory="WDK7_1_Dir" Directory_Parent="PlatformToolsets_1_Dir" DefaultDir="WDK7"/>

-    <ROW Directory="WDK7_Dir" Directory_Parent="PlatformToolsets_Dir" DefaultDir="WDK7"/>

-    <ROW Directory="Win32_Dir" Directory_Parent="Platforms_Dir" DefaultDir="Win32"/>

-    <ROW Directory="v4.0_Dir" Directory_Parent="Microsoft.Cpp_Dir" DefaultDir="v4.0"/>

-    <ROW Directory="x64_Dir" Directory_Parent="Platforms_Dir" DefaultDir="x64"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">

-    <ROW Component="Microsoft.Cpp.Win32.WDK7.props" ComponentId="{3EA16365-3C7E-4F84-A326-C7F28B33F487}" Directory_="WDK7_Dir" Attributes="0" KeyPath="Microsoft.Cpp.Win32.WDK7.props" Type="0"/>

-    <ROW Component="Microsoft.Cpp.x64.WDK7.props" ComponentId="{50DB333C-5D3E-4A14-80B9-BA1D727BD220}" Directory_="WDK7_1_Dir" Attributes="0" KeyPath="Microsoft.Cpp.x64.WDK7.props" Type="0"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">

-    <ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="Microsoft.Cpp.Win32.WDK7.props Microsoft.Cpp.x64.WDK7.props"/>

-    <ATTRIBUTE name="CurrentFeature" value="MainFeature"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">

-    <ROW File="Microsoft.Cpp.Win32.WDK7.props" Component_="Microsoft.Cpp.Win32.WDK7.props" FileName="Micros~1.pro|Microsoft.Cpp.Win32.WDK7.props" Attributes="0" SourcePath="Microsoft.Cpp.Win32.WDK7.props" SelfReg="false" NextFile="Microsoft.Cpp.Win32.WDK7.targets"/>

-    <ROW File="Microsoft.Cpp.Win32.WDK7.targets" Component_="Microsoft.Cpp.Win32.WDK7.props" FileName="Micros~1.tar|Microsoft.Cpp.Win32.WDK7.targets" Attributes="0" SourcePath="Microsoft.Cpp.Win32.WDK7.targets" SelfReg="false" NextFile="Microsoft.Cpp.x64.WDK7.props"/>

-    <ROW File="Microsoft.Cpp.x64.WDK7.props" Component_="Microsoft.Cpp.x64.WDK7.props" FileName="Micros~1.pro|Microsoft.Cpp.x64.WDK7.props" Attributes="0" SourcePath="Microsoft.Cpp.x64.WDK7.props" SelfReg="false" NextFile="Microsoft.Cpp.x64.WDK7.targets"/>

-    <ROW File="Microsoft.Cpp.x64.WDK7.targets" Component_="Microsoft.Cpp.x64.WDK7.props" FileName="Micros~1.tar|Microsoft.Cpp.x64.WDK7.targets" Attributes="0" SourcePath="Microsoft.Cpp.x64.WDK7.targets" SelfReg="false"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">

-    <ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="." PackageFileName="Visual Studio 2012 Windows Driver Kit Platform Toolset 1.2" Languages="en" InstallationType="4" UseLargeSchema="true"/>

-    <ATTRIBUTE name="CurrentBuild" value="DefaultBuild"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">

-    <ROW Path="&lt;AI_DICTS&gt;ui.ail"/>

-    <ROW Path="&lt;AI_DICTS&gt;ui_en.ail"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">

-    <ROW Fragment="CommonUI.aip" Path="&lt;AI_FRAGS&gt;CommonUI.aip"/>

-    <ROW Fragment="MaintenanceTypeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceTypeDlg.aip"/>

-    <ROW Fragment="MaintenanceWelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceWelcomeDlg.aip"/>

-    <ROW Fragment="SequenceDialogs.aip" Path="&lt;AI_THEMES&gt;classic\fragments\SequenceDialogs.aip"/>

-    <ROW Fragment="Sequences.aip" Path="&lt;AI_FRAGS&gt;Sequences.aip"/>

-    <ROW Fragment="StaticUIStrings.aip" Path="&lt;AI_FRAGS&gt;StaticUIStrings.aip"/>

-    <ROW Fragment="UI.aip" Path="&lt;AI_THEMES&gt;classic\fragments\UI.aip"/>

-    <ROW Fragment="Validation.aip" Path="&lt;AI_FRAGS&gt;Validation.aip"/>

-    <ROW Fragment="VerifyRemoveDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRemoveDlg.aip"/>

-    <ROW Fragment="VerifyRepairDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRepairDlg.aip"/>

-    <ROW Fragment="WelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\WelcomeDlg.aip"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">

-    <ROW Name="aicustact.dll" SourcePath="&lt;AI_CUSTACTS&gt;aicustact.dll"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiControlComponent">

-    <ATTRIBUTE name="FixedSizeBitmaps" value="0"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiControlEventComponent">

-    <ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL" Ordering="1"/>

-    <ROW Dialog_="MaintenanceWelcomeDlg" Control_="Next" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="99"/>

-    <ROW Dialog_="CustomizeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_MAINT" Ordering="101"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_INSTALL" Ordering="197"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL" Ordering="201"/>

-    <ROW Dialog_="CustomizeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="1"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_MAINT" Ordering="198"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="202"/>

-    <ROW Dialog_="MaintenanceTypeDlg" Control_="ChangeButton" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="501"/>

-    <ROW Dialog_="MaintenanceTypeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceWelcomeDlg" Condition="AI_MAINT" Ordering="1"/>

-    <ROW Dialog_="MaintenanceTypeDlg" Control_="RemoveButton" Event="NewDialog" Argument="VerifyRemoveDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="601"/>

-    <ROW Dialog_="VerifyRemoveDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="1"/>

-    <ROW Dialog_="MaintenanceTypeDlg" Control_="RepairButton" Event="NewDialog" Argument="VerifyRepairDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="601"/>

-    <ROW Dialog_="VerifyRepairDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="1"/>

-    <ROW Dialog_="VerifyRepairDlg" Control_="Repair" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="399"/>

-    <ROW Dialog_="VerifyRemoveDlg" Control_="Remove" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="299"/>

-    <ROW Dialog_="PatchWelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_PATCH" Ordering="201"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_PATCH" Ordering="199"/>

-    <ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="203"/>

-    <ROW Dialog_="ResumeDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_RESUME" Ordering="299"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">

-    <ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>

-    <ROW Action="AI_InstallModeCheck" Type="1" Source="aicustact.dll" Target="UpdateInstallMode" WithoutSeq="true"/>

-    <ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>

-    <ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>

-    <ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>

-    <ROW Action="AI_ResolveLocalizedCredentials" Type="1" Source="aicustact.dll" Target="GetLocalizedCredentials"/>

-    <ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>

-    <ROW Action="AI_STORE_LOCATION" Type="51" Source="ARPINSTALLLOCATION" Target="[APPDIR]"/>

-    <ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]"/>

-    <ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]"/>

-    <ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent">

-    <ROW Action="AI_DOWNGRADE" Condition="AI_NEWERPRODUCTFOUND AND (UILevel &lt;&gt; 5)" Sequence="210"/>

-    <ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>

-    <ROW Action="AI_STORE_LOCATION" Condition="(Not Installed) OR REINSTALL" Sequence="1501"/>

-    <ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1399"/>

-    <ROW Action="AI_ResolveKnownFolders" Sequence="52"/>

-    <ROW Action="AI_ResolveLocalizedCredentials" Sequence="51"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">

-    <ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>

-    <ROW Action="AI_ResolveKnownFolders" Sequence="52"/>

-    <ROW Action="AI_ResolveLocalizedCredentials" Sequence="51"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">

-    <ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]" DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">

-    <ATTRIBUTE name="UsedTheme" value="classic"/>

-  </COMPONENT>

-  <COMPONENT cid="caphyon.advinst.msicomp.MsiUpgradeComponent">

-    <ROW UpgradeCode="[|UpgradeCode]" VersionMax="[|ProductVersion]" Attributes="1025" ActionProperty="OLDPRODUCTS"/>

-    <ROW UpgradeCode="[|UpgradeCode]" VersionMin="[|ProductVersion]" Attributes="2" ActionProperty="AI_NEWERPRODUCTFOUND"/>

-  </COMPONENT>

-</DOCUMENT>