summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--plugins/lua/lua.c15
-rw-r--r--src/common/cfgfiles.c128
-rw-r--r--src/common/cfgfiles.h6
-rw-r--r--src/common/dcc.c36
-rw-r--r--src/common/hexchat.c12
-rw-r--r--src/common/hexchat.h2
-rw-r--r--src/common/plugin.c115
-rw-r--r--src/common/server.c12
-rw-r--r--src/common/servlist.c20
-rw-r--r--src/common/text.c329
-rw-r--r--src/common/util.c80
-rw-r--r--src/common/util.h3
-rw-r--r--src/fe-gtk/fe-gtk.c87
-rw-r--r--src/fe-gtk/fkeys.c16
-rw-r--r--src/fe-gtk/gtkutil.c190
-rw-r--r--src/fe-gtk/menu.c4
-rw-r--r--src/fe-gtk/pixmaps.c2
-rw-r--r--src/fe-gtk/plugingui.c16
-rw-r--r--src/fe-gtk/setup.c6
-rw-r--r--src/fe-gtk/urlgrab.c2
-rw-r--r--src/fe-text/fe-text.c10
21 files changed, 371 insertions, 720 deletions
diff --git a/plugins/lua/lua.c b/plugins/lua/lua.c
index fb624e47..fd3926f5 100644
--- a/plugins/lua/lua.c
+++ b/plugins/lua/lua.c
@@ -429,7 +429,7 @@ lxc_autoload_from_path(const char *path)
 						strerror(errno));
 					break;
 				}
-				sprintf(file, "%s/%s", path, ent->d_name);
+				sprintf(file, "%s" G_DIR_SEPARATOR_S "%s", path, ent->d_name);
 				(void)lxc_load_file((const char *)file);
 				free(file);
 			}
@@ -510,22 +510,19 @@ static int lxc_cb_load(char *word[], char *word_eol[], void *userdata)
 
  	len = strlen(word[2]);
 	if (len > 4 && strcasecmp (".lua", word[2] + len - 4) == 0) {
-#ifdef WIN32
-		if (strrchr(word[2], '\\') != NULL)
-#else
-		if (strrchr(word[2], '/') != NULL)
-#endif
+		if (strrchr(word[2], G_DIR_SEPARATOR) != NULL)
 			strncpy(file, word[2], PATH_MAX);
-		else {
+		else
+		{
 			if (stat(word[2], st) == 0)
 			{
 				xdir = getcwd (buf, PATH_MAX);
-				snprintf (file, PATH_MAX, "%s/%s", xdir, word[2]);
+				snprintf (file, PATH_MAX, "%s" G_DIR_SEPARATOR_S "%s", xdir, word[2]);
 			}
 			else
 			{
 				xdir = hexchat_get_info (ph, "hexchatdirfs");
-				snprintf (file, PATH_MAX, "%s/addons/%s", xdir, word[2]);
+				snprintf (file, PATH_MAX, "%s" G_DIR_SEPARATOR_S "addons" G_DIR_SEPARATOR_S "%s", xdir, word[2]);
 			}
 		}
 
diff --git a/src/common/cfgfiles.c b/src/common/cfgfiles.c
index 16a3e473..83876688 100644
--- a/src/common/cfgfiles.c
+++ b/src/common/cfgfiles.c
@@ -106,28 +106,30 @@ list_load_from_data (GSList ** list, char *ibuf, int size)
 void
 list_loadconf (char *file, GSList ** list, char *defaultconf)
 {
-	char filebuf[256];
+	char *filebuf;
 	char *ibuf;
-	int fh;
+	int fd;
 	struct stat st;
 
-	snprintf (filebuf, sizeof (filebuf), "%s/%s", get_xdir_fs (), file);
-	fh = open (filebuf, O_RDONLY | OFLAGS);
-	if (fh == -1)
+	filebuf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", get_xdir (), file);
+	fd = g_open (filebuf, O_RDONLY | OFLAGS, 0);
+	g_free (filebuf);
+
+	if (fd == -1)
 	{
 		if (defaultconf)
 			list_load_from_data (list, defaultconf, strlen (defaultconf));
 		return;
 	}
-	if (fstat (fh, &st) != 0)
+	if (fstat (fd, &st) != 0)
 	{
 		perror ("fstat");
 		abort ();
 	}
 
 	ibuf = malloc (st.st_size);
-	read (fh, ibuf, st.st_size);
-	close (fh);
+	read (fd, ibuf, st.st_size);
+	close (fd);
 
 	list_load_from_data (list, ibuf, st.st_size);
 
@@ -280,8 +282,7 @@ cfg_get_int (char *cfg, char *var)
 	return atoi (str);
 }
 
-char *xdir_fs = NULL;	/* file system encoding */
-char *xdir_utf = NULL;	/* utf-8 encoding */
+char *xdir = NULL;	/* utf-8 encoding */
 
 #ifdef WIN32
 
@@ -311,65 +312,51 @@ get_reg_str (const char *sub, const char *name, char *out, DWORD len)
 }
 
 char *
-get_xdir_fs (void)
+get_xdir (void)
 {
-	if (!xdir_fs)
+	if (!xdir)
 	{
 			char out[256];
 
 			if (portable_mode () || !get_reg_str ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "AppData", out, sizeof (out)))
 			{
-				xdir_fs = ".\\config";
+				xdir = ".\\config";
 			}
 			else
 			{
-				xdir_fs = g_strdup_printf ("%s\\" "HexChat", out);
+				xdir = g_strdup_printf ("%s\\" "HexChat", out);
 			}
 	}
 
-	return xdir_fs;
+	return xdir;
 }
 
 #else
 
 char *
-get_xdir_fs (void)
+get_xdir (void)
 {
-	if (!xdir_fs)
-		xdir_fs = g_strdup_printf ("%s/.config/" HEXCHAT_DIR, g_get_home_dir ());
+	if (!xdir)
+		xdir = g_strdup_printf ("%s/.config/" HEXCHAT_DIR, g_get_home_dir ());
 
-	return xdir_fs;
+	return xdir;
 }
 
 #endif	/* !WIN32 */
 
-char *
-get_xdir_utf8 (void)
-{
-	if (!xdir_utf)	/* never free this, keep it for program life time */
-		xdir_utf = hexchat_filename_to_utf8 (get_xdir_fs (), -1, 0, 0, 0);
-
-	return xdir_utf;
-}
-
 static void
 check_prefs_dir (void)
 {
-	char *dir = get_xdir_fs ();
-	static char *msg = NULL;
+	char *dir = get_xdir ();
+	char *msg;
 
-	if (access (dir, F_OK) != 0)
+	if (g_access (dir, F_OK) != 0)
 	{
-#ifdef WIN32
-		if (mkdir (dir) != 0)
-#else
-		if (mkdir (dir, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
-#endif
+		if (g_mkdir (dir, 0700) != 0)
 		{
-			msg = malloc (strlen (get_xdir_fs ()) + 15);
-			sprintf (msg, "Cannot create %s", get_xdir_fs ());
+			msg = g_strdup_printf ("Cannot create %s", get_xdir ());
 			fe_message (msg, FE_MSG_ERROR);
-			free (msg);
+			g_free (msg);
 		}
 	}
 }
@@ -377,12 +364,11 @@ check_prefs_dir (void)
 static char *
 default_file (void)
 {
-	static char *dfile = 0;
+	static char *dfile = NULL;
 
 	if (!dfile)
 	{
-		dfile = malloc (strlen (get_xdir_fs ()) + 14);
-		sprintf (dfile, "%s/hexchat.conf", get_xdir_fs ());
+		dfile = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "hexchat.conf", get_xdir ());
 	}
 	return dfile;
 }
@@ -762,14 +748,14 @@ load_config (void)
 #ifdef WIN32
 	if (portable_mode () || !get_reg_str ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Personal", out, sizeof (out)))
 	{
-		snprintf (prefs.hex_dcc_dir, sizeof (prefs.hex_dcc_dir), "%s\\downloads", get_xdir_utf8 ());
+		snprintf (prefs.hex_dcc_dir, sizeof (prefs.hex_dcc_dir), "%s\\downloads", get_xdir ());
 	}
 	else
 	{
 		snprintf (prefs.hex_dcc_dir, sizeof (prefs.hex_dcc_dir), "%s\\Downloads", out);
 	}
 #else
-	snprintf (prefs.hex_dcc_dir, sizeof (prefs.hex_dcc_dir), "%s/downloads", get_xdir_utf8 ());
+	snprintf (prefs.hex_dcc_dir, sizeof (prefs.hex_dcc_dir), "%s/downloads", get_xdir ());
 #endif
 	strcpy (prefs.hex_dnsprogram, "host");
 	strcpy (prefs.hex_gui_ulist_doubleclick, "QUERY %s");
@@ -785,11 +771,7 @@ load_config (void)
 	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);
-#ifdef WIN32
-	strcpy (prefs.hex_sound_dir, "./sounds");
-#else
-	snprintf (prefs.hex_sound_dir, sizeof (prefs.hex_sound_dir), "%s/sounds", get_xdir_utf8 ());
-#endif
+	snprintf (prefs.hex_sound_dir, sizeof (prefs.hex_sound_dir), "%s" G_DIR_SEPARATOR_S "sounds", get_xdir ());
 	strcpy (prefs.hex_stamp_log_format, "%b %d %H:%M:%S ");
 	strcpy (prefs.hex_stamp_text_format, "[%H:%M:%S] ");
 #ifdef WIN32
@@ -816,16 +798,8 @@ load_config (void)
 	g_free ((char *)username);
 	g_free ((char *)realname);
 
-	fh = open (default_file (), OFLAGS | O_RDONLY);
-	if (fh != -1)
+	if (g_file_get_contents (default_file (), &cfg, NULL, NULL))
 	{
-		fstat (fh, &st);
-		cfg = malloc (st.st_size + 1);
-		cfg[0] = '\0';
-		i = read (fh, cfg, st.st_size);
-		if (i >= 0)
-			cfg[i] = '\0';					/* make sure cfg is NULL terminated */
-		close (fh);
 		i = 0;
 		do
 		{
@@ -846,7 +820,7 @@ load_config (void)
 		}
 		while (vars[i].name);
 
-		free (cfg);
+		g_free (cfg);
 
 	} else
 	{
@@ -859,8 +833,8 @@ load_config (void)
 #endif
 #endif /* !WIN32 */
 
-		mkdir_utf8 (prefs.hex_dcc_dir);
-		mkdir_utf8 (prefs.hex_dcc_completed_dir);
+		g_mkdir (prefs.hex_dcc_dir, 0700);
+		g_mkdir (prefs.hex_dcc_completed_dir, 0700);
 	}
 	if (prefs.hex_gui_win_height < 138)
 		prefs.hex_gui_win_height = 138;
@@ -1175,31 +1149,45 @@ 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)
 {
-	char buf[1024];
+	char *buf;
+	int fd;
 
 	if (xof_flags & XOF_FULLPATH)
 	{
 		if (xof_flags & XOF_DOMODE)
-			return open (file, flags | OFLAGS, mode);
+			return g_open (file, flags | OFLAGS, mode);
 		else
-			return open (file, flags | OFLAGS);
+			return g_open (file, flags | OFLAGS, 0);
 	}
 
-	snprintf (buf, sizeof (buf), "%s/%s", get_xdir_fs (), file);
+	buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", get_xdir (), file);
+
 	if (xof_flags & XOF_DOMODE)
-		return open (buf, flags | OFLAGS, mode);
+	{
+		fd = g_open (buf, flags | OFLAGS, mode);
+	}
 	else
-		return open (buf, flags | OFLAGS);
+	{
+		fd = g_open (buf, flags | OFLAGS, 0);
+	}
+
+	g_free (buf);
+
+	return fd;
 }
 
 FILE *
 hexchat_fopen_file (const char *file, const char *mode, int xof_flags)
 {
-	char buf[1024];
+	char *buf;
+	FILE *fh;
 
 	if (xof_flags & XOF_FULLPATH)
 		return fopen (file, mode);
 
-	snprintf (buf, sizeof (buf), "%s/%s", get_xdir_fs (), file);
-	return fopen (buf, mode);
+	buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", get_xdir (), file);
+	fh = g_fopen (buf, mode);
+	g_free (buf);
+
+	return fh;
 }
diff --git a/src/common/cfgfiles.h b/src/common/cfgfiles.h
index d32dbb67..e55befe5 100644
--- a/src/common/cfgfiles.h
+++ b/src/common/cfgfiles.h
@@ -5,8 +5,7 @@
 
 #include "hexchat.h"
 
-extern char *xdir_fs;
-extern char *xdir_utf;
+extern char *xdir;
 
 char *cfg_get_str (char *cfg, const char *var, char *dest, int dest_len);
 int cfg_get_bool (char *var);
@@ -15,8 +14,7 @@ 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);
-char *get_xdir_fs (void);
-char *get_xdir_utf8 (void);
+char *get_xdir (void);
 void load_config (void);
 int save_config (void);
 void list_free (GSList ** list);
diff --git a/src/common/dcc.c b/src/common/dcc.c
index 4386e0a8..cdee4249 100644
--- a/src/common/dcc.c
+++ b/src/common/dcc.c
@@ -45,9 +45,6 @@
 #include <unistd.h>
 #endif
 
-#include <glib.h>
-#include <glib/gstdio.h>
-
 #include "hexchat.h"
 #include "util.h"
 #include "fe.h"
@@ -401,7 +398,7 @@ dcc_close (struct DCC *dcc, int dccstat, int destroy)
 			if(dcc->type == TYPE_RECV)
 			{			
 				/* mgl: change this to handle the case where dccwithnick is set */
-				move_file_utf8 (prefs.hex_dcc_dir, prefs.hex_dcc_completed_dir, 
+				move_file (prefs.hex_dcc_dir, prefs.hex_dcc_completed_dir, 
 									 file_part (dcc->destfile), prefs.hex_dcc_permissions);
 			}
 
@@ -696,7 +693,7 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 	{
 
 		/* try to create the download dir (even if it exists, no harm) */
-		mkdir_utf8 (prefs.hex_dcc_dir);
+		g_mkdir (prefs.hex_dcc_dir, 0700);
 
 		if (dcc->resumable)
 		{
@@ -1773,18 +1770,15 @@ void
 dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 {
 	char outbuf[512];
-	struct stat st;
+	GStatBuf st;
 	struct DCC *dcc;
-	char *file_fs;
 
-	/* this is utf8 */
 	file = expand_homedir (file);
 
 	if (!recursive && (strchr (file, '*') || strchr (file, '?')))
 	{
 		char path[256];
 		char wild[256];
-		char *path_fs;	/* local filesystem encoding */
 
 		safe_strcpy (wild, file_part (file), sizeof (wild));
 		path_part (file, path, sizeof (path));
@@ -1797,15 +1791,9 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 
 		free (file);
 
-		/* for_files() will use opendir, so we need local FS encoding */
-		path_fs = hexchat_filename_from_utf8 (path, -1, 0, 0, 0);
-		if (path_fs)
-		{
-			recursive = TRUE;
-			for_files (path_fs, wild, dcc_send_wild);
-			recursive = FALSE;
-			g_free (path_fs);
-		}
+		recursive = TRUE;
+		for_files (path, wild, dcc_send_wild);
+		recursive = FALSE;
 
 		return;
 	}
@@ -1816,10 +1804,7 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 	dcc->file = file;
 	dcc->maxcps = maxcps;
 
-	/* get the local filesystem encoding */
-	file_fs = hexchat_filename_from_utf8 (file, -1, 0, 0, 0);
-
-	if (stat (file_fs, &st) != -1)
+	if (g_stat (file, &st) != -1)
 	{
 
 #ifndef USE_DCC64
@@ -1830,7 +1815,7 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 		}
 #endif
 
-		if (!(*file_part (file_fs)) || S_ISDIR (st.st_mode) || st.st_size < 1)
+		if (!(*file_part (file)) || S_ISDIR (st.st_mode) || st.st_size < 1)
 		{
 			PrintText (sess, "Cannot send directories or empty files.\n");
 			goto xit;
@@ -1841,10 +1826,10 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 		dcc->dccstat = STAT_QUEUED;
 		dcc->size = st.st_size;
 		dcc->type = TYPE_SEND;
-		dcc->fp = g_open (file_fs, OFLAGS | O_RDONLY, 0);
+		dcc->fp = g_open (file, OFLAGS | O_RDONLY, 0);
 		if (dcc->fp != -1)
 		{
-			g_free (file_fs);
+			g_free (file);
 			if (passive || dcc_listen_init (dcc, sess))
 			{
 				char havespaces = 0;
@@ -1898,7 +1883,6 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 	PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
 	PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
 xit:
-	g_free (file_fs);
 	dcc_close (dcc, 0, TRUE);
 }
 
diff --git a/src/common/hexchat.c b/src/common/hexchat.c
index d8207fb0..ea564a54 100644
--- a/src/common/hexchat.c
+++ b/src/common/hexchat.c
@@ -303,7 +303,7 @@ static void
 irc_init (session *sess)
 {
 	static int done_init = FALSE;
-	char buf[512];
+	char *buf;
 
 	if (done_init)
 		return;
@@ -330,9 +330,10 @@ irc_init (session *sess)
 
 	if (arg_url != NULL)
 	{
-		snprintf (buf, sizeof (buf), "server %s", arg_url);
-		handle_command (sess, buf, FALSE);
+		buf = g_strdup_printf ("server %s", arg_url);
 		g_free (arg_url);	/* from GOption */
+		handle_command (sess, buf, FALSE);
+		g_free (buf);
 	}
 
 	if (arg_command != NULL)
@@ -340,9 +341,10 @@ irc_init (session *sess)
 		g_free (arg_command);
 	}
 
-	/* load -e ~/.xchat2/startup.txt */
-	snprintf (buf, sizeof (buf), "%s/%s", get_xdir_fs (), "startup.txt");
+	/* load -e <xdir>/startup.txt */
+	buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "startup.txt", get_xdir ());
 	load_perform_file (sess, buf);
+	g_free (buf);
 }
 
 static session *
diff --git a/src/common/hexchat.h b/src/common/hexchat.h
index 673309bd..5a187d3a 100644
--- a/src/common/hexchat.h
+++ b/src/common/hexchat.h
@@ -5,6 +5,8 @@
 #endif
 
 #include <glib.h>
+#include <glib/gstdio.h>
+
 #include <time.h>			/* need time_t */
 
 #ifndef HEXCHAT_H
diff --git a/src/common/plugin.c b/src/common/plugin.c
index 62b83ae1..d4081968 100644
--- a/src/common/plugin.c
+++ b/src/common/plugin.c
@@ -458,48 +458,43 @@ plugin_auto_load_cb (char *filename)
 void
 plugin_auto_load (session *sess)
 {
-	/* let's do it the Perl way */
-	const char *xdir;
 	char *sub_dir;
 	ps = sess;
 
-	xdir = get_xdir_fs ();
-	sub_dir = malloc (strlen (xdir) + 8);
-	strcpy (sub_dir, xdir);
-	strcat (sub_dir, "/addons");
+	sub_dir = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "addons", get_xdir ());
 
 #ifdef WIN32
 	/* a long list of bundled plugins that should be loaded automatically,
 	 * user plugins should go to <config>, leave Program Files alone! */
-	for_files ("./plugins", "hcchecksum.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcdns.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcdoat.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcexec.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcfishlim.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hchextray.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hclua.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcmpcinfo.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcperl.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcpython.dll", plugin_auto_load_cb);
-	/* for_files ("./plugins", "hcsasl.dll", plugin_auto_load_cb); we have this built-in */
-	for_files ("./plugins", "hctcl.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcupd.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcwinamp.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcsysinfo.dll", plugin_auto_load_cb);
-	for_files ("./plugins", "hcwmpa.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcchecksum.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcdns.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcdoat.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcexec.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcfishlim.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hchextray.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hclua.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcmpcinfo.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcperl.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcpython.dll", plugin_auto_load_cb);
+	/* for_files (".\\plugins", "hcsasl.dll", plugin_auto_load_cb); we have this built-in */
+	for_files (".\\plugins", "hctcl.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcupd.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcwinamp.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcsysinfo.dll", plugin_auto_load_cb);
+	for_files (".\\plugins", "hcwmpa.dll", plugin_auto_load_cb);
 
 	for_files (sub_dir, "*.dll", plugin_auto_load_cb);
 #else
 #if defined(__hpux)
-	for_files (HEXCHATLIBDIR"/plugins", "*.sl", plugin_auto_load_cb);
+	for_files (HEXCHATLIBDIR "/plugins", "*.sl", plugin_auto_load_cb);
 	for_files (sub_dir, "*.sl", plugin_auto_load_cb);
 #else
-	for_files (HEXCHATLIBDIR"/plugins", "*.so", plugin_auto_load_cb);
+	for_files (HEXCHATLIBDIR "/plugins", "*.so", plugin_auto_load_cb);
 	for_files (sub_dir, "*.so", plugin_auto_load_cb);
 #endif
 #endif
 
-	free (sub_dir);
+	g_free (sub_dir);
 }
 
 #endif
@@ -1056,11 +1051,11 @@ hexchat_get_info (hexchat_plugin *ph, const char *id)
 
 	case 0xdd9b1abd:	/* xchatdir */
 	case 0x9a70daba:	/* hexchatdir */
-		return get_xdir_utf8 ();
+		return get_xdir ();
 
 	case 0xe33f6c4a:	/* xchatdirfs */
 	case 0xc1a52107:	/* hexchatdirfs */
-		return get_xdir_fs ();
+		return get_xdir ();
 	}
 
 	sess = ph->context;
@@ -1632,46 +1627,56 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
 	FILE *fpIn;
 	int fhOut;
 	int prevSetting;
-	char confname[64];
-	char confname_tmp[69];
-	char buffer[512];		/* the same as in cfg_put_str */
-	char buffer_tmp[512];
+	char *confname;
+	char *confname_tmp;
+	char *buffer;
+	char *buffer_tmp;
+	char line_buffer[512];		/* the same as in cfg_put_str */
 	char *canon;
 
 	canon = g_strdup (pl->name);
 	canonalize_key (canon);
-	sprintf (confname, "addon_%s.conf", canon);
+	confname = g_strdup_printf ("addon_%s.conf", canon);
 	g_free (canon);
-	sprintf (confname_tmp, "%s.new", confname);
+	confname_tmp = g_strdup_printf ("%s.new", confname);
 
 	fhOut = hexchat_open_file (confname_tmp, O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
 	fpIn = hexchat_fopen_file (confname, "r", 0);
 
 	if (fhOut == -1)		/* unable to save, abort */
 	{
+		g_free (confname);
+		g_free (confname_tmp);
 		return 0;
 	}
 	else if (fpIn == NULL)	/* no previous config file, no parsing */
 	{
 		if (mode)
 		{
-			sprintf (buffer, "%s = %s\n", var, value);
+			buffer = g_strdup_printf ("%s = %s\n", var, value);
 			write (fhOut, buffer, strlen (buffer));
+			g_free (buffer);
 			close (fhOut);
 
-			sprintf (buffer, "%s/%s", get_xdir_fs (), confname);
-			sprintf (buffer_tmp, "%s/%s", get_xdir_fs (), confname_tmp);
+			buffer = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", get_xdir (), confname);
+			g_free (confname);
+			buffer_tmp = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", get_xdir (), confname_tmp);
+			g_free (confname_tmp);
 
 #ifdef WIN32
-			unlink (buffer);
+			g_unlink (buffer);
 #endif
 
-			if (rename (buffer_tmp, buffer) == 0)
+			if (g_rename (buffer_tmp, buffer) == 0)
 			{
+				g_free (buffer);
+				g_free (buffer_tmp);
 				return 1;
 			}
 			else
 			{
+				g_free (buffer);
+				g_free (buffer_tmp);
 				return 0;
 			}
 		}
@@ -1679,6 +1684,8 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
 		{
 			/* mode = 0, we want to delete but the config file and thus the given setting does not exist, we're ready */
 			close (fhOut);
+			g_free (confname);
+			g_free (confname_tmp);
 			return 1;
 		}
 	}
@@ -1686,54 +1693,64 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
 	{
 		prevSetting = 0;
 
-		while (fscanf (fpIn, " %[^\n]", &buffer) != EOF)	/* read whole lines including whitespaces */
+		while (fscanf (fpIn, " %[^\n]", &line_buffer) != EOF)	/* read whole lines including whitespaces */
 		{
-			sprintf (buffer_tmp, "%s ", var);				/* add one space, this way it works against var - var2 checks too */
+			buffer_tmp = g_strdup_printf ("%s ", var);	/* add one space, this way it works against var - var2 checks too */
 
-			if (strncmp (buffer_tmp, buffer, strlen (var) + 1) == 0)	/* given setting already exists */
+			if (strncmp (buffer_tmp, line_buffer, strlen (var) + 1) == 0)	/* given setting already exists */
 			{
 				if (mode)									/* overwrite the existing matching setting if we are in save mode */
 				{
-					sprintf (buffer, "%s = %s\n", var, value);
+					buffer = g_strdup_printf ("%s = %s\n", var, value);
 				}
 				else										/* erase the setting in delete mode */
 				{
-					strcpy (buffer, "");
+					buffer = g_strdup ("");
 				}
 
 				prevSetting = 1;
 			}
 			else
 			{
-				strcat (buffer, "\n");						/* preserve the existing different settings */
+				buffer = g_strdup_printf ("%s\n", line_buffer);	/* preserve the existing different settings */
 			}
 
 			write (fhOut, buffer, strlen (buffer));
+
+			g_free (buffer);
+			g_free (buffer_tmp);
 		}
 
 		fclose (fpIn);
 
 		if (!prevSetting && mode)	/* var doesn't exist currently, append if we're in save mode */
 		{
-			sprintf (buffer, "%s = %s\n", var, value);
+			buffer = g_strdup_printf ("%s = %s\n", var, value);
 			write (fhOut, buffer, strlen (buffer));
+			g_free (buffer);
 		}
 
 		close (fhOut);
 
-		sprintf (buffer, "%s/%s", get_xdir_fs (), confname);
-		sprintf (buffer_tmp, "%s/%s", get_xdir_fs (), confname_tmp);
+		buffer = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", get_xdir (), confname);
+		g_free (confname);
+		buffer_tmp = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", get_xdir (), confname_tmp);
+		g_free (confname_tmp);
 
 #ifdef WIN32
-		unlink (buffer);
+		g_unlink (buffer);
 #endif
 
-		if (rename (buffer_tmp, buffer) == 0)
+		if (g_rename (buffer_tmp, buffer) == 0)
 		{
+			g_free (buffer);
+			g_free (buffer_tmp);
 			return 1;
 		}
 		else
 		{
+			g_free (buffer);
+			g_free (buffer_tmp);
 			return 0;
 		}
 	}
diff --git a/src/common/server.c b/src/common/server.c
index 2bb133b1..6c4b3543 100644
--- a/src/common/server.c
+++ b/src/common/server.c
@@ -1718,21 +1718,21 @@ server_connect (server *serv, char *hostname, int port, int no_login)
 #ifdef USE_OPENSSL
 	if (serv->use_ssl)
 	{
-		char cert_file[256];
+		char *cert_file;
 
 		/* first try network specific cert/key */
-		snprintf (cert_file, sizeof (cert_file), "%s/%s.pem",
-					 get_xdir_fs (), server_get_network (serv, TRUE));
+		cert_file = g_strdup_printf ("%s" 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)
 			SSL_CTX_use_PrivateKey_file (ctx, cert_file, SSL_FILETYPE_PEM);
 		else
 		{
-			/* if that doesn't exist, try ~/.xchat2/client.pem */
-			snprintf (cert_file, sizeof (cert_file), "%s/%s.pem",
-						 get_xdir_fs (), "client");
+			/* if that doesn't exist, try <xdir>/client.pem */
+			cert_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "client.pem", get_xdir ());
 			if (SSL_CTX_use_certificate_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
 				SSL_CTX_use_PrivateKey_file (ctx, cert_file, SSL_FILETYPE_PEM);
 		}
+		g_free (cert_file);
 	}
 #endif
 
diff --git a/src/common/servlist.c b/src/common/servlist.c
index f3697c2c..c42c371d 100644
--- a/src/common/servlist.c
+++ b/src/common/servlist.c
@@ -1159,7 +1159,7 @@ int
 servlist_save (void)
 {
 	FILE *fp;
-	char buf[256];
+	char *buf;
 	ircnet *net;
 	ircserver *serv;
 	GSList *list;
@@ -1167,20 +1167,27 @@ servlist_save (void)
 #ifndef WIN32
 	int first = FALSE;
 
-	snprintf (buf, sizeof (buf), "%s/servlist_.conf", get_xdir_fs ());
-	if (access (buf, F_OK) != 0)
+	buf = g_strdup_printf ("%s/servlist_.conf", get_xdir ());
+	if (g_access (buf, F_OK) != 0)
 		first = TRUE;
 #endif
 
 	fp = hexchat_fopen_file ("servlist_.conf", "w", 0);
 	if (!fp)
+	{
+#ifndef WIN32
+		g_free (buf);
+#endif
 		return FALSE;
+	}
 
 #ifndef WIN32
 	if (first)
-		chmod (buf, 0600);
+		g_chmod (buf, 0600);
+
+	g_free (buf);
 #endif
-	fprintf (fp, "v="PACKAGE_VERSION"\n\n");
+	fprintf (fp, "v=" PACKAGE_VERSION "\n\n");
 
 	list = network_list;
 	while (list)
@@ -1210,9 +1217,10 @@ servlist_save (void)
 			fprintf (fp, "E=%s\n", net->encoding);
 			if (!servlist_check_encoding (net->encoding))
 			{
-				snprintf (buf, sizeof (buf), _("Warning: \"%s\" character set is unknown. No conversion will be applied for network %s."),
+				buf = g_strdup_printf (_("Warning: \"%s\" character set is unknown. No conversion will be applied for network %s."),
 							 net->encoding, net->name);
 				fe_message (buf, FE_MSG_WARN);
+				g_free (buf);
 			}
 		}
 
diff --git a/src/common/text.c b/src/common/text.c
index 6d69b08c..19bcf2fc 100644
--- a/src/common/text.c
+++ b/src/common/text.c
@@ -56,24 +56,24 @@ struct pevt_stage1
 };
 
 
-static void mkdir_p (char *dir);
+static void mkdir_p (char *filename);
 static char *log_create_filename (char *channame);
 
-
 static char *
-scrollback_get_filename (session *sess, char *buf, int max)
+scrollback_get_filename (session *sess)
 {
-	char *net, *chan;
+	char *net, *chan, *buf;
 
 	net = server_get_network (sess->server, FALSE);
 	if (!net)
 		return NULL;
 
-	snprintf (buf, max, "%s/scrollback/%s/%s.txt", get_xdir_fs (), net, "");
+	buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "scrollback" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s.txt", get_xdir (), net, "");
 	mkdir_p (buf);
+	g_free (buf);
 
 	chan = log_create_filename (sess->channel);
-	snprintf (buf, max, "%s/scrollback/%s/%s.txt", get_xdir_fs (), net, chan);
+	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);
 	free (chan);
 
 	return buf;
@@ -126,44 +126,12 @@ scrollback_close (session *sess)
 	}
 }
 
-static char *
-file_to_buffer (char *file, int *len)
-{
-	int fh;
-	char *buf;
-	struct stat st;
-
-	fh = open (file, O_RDONLY | OFLAGS);
-	if (fh == -1)
-		return NULL;
-
-	fstat (fh, &st);
-
-	buf = malloc (st.st_size);
-	if (!buf)
-	{
-		close (fh);
-		return NULL;
-	}
-
-	if (read (fh, buf, st.st_size) != st.st_size)
-	{
-		free (buf);
-		close (fh);
-		return NULL;
-	}
-
-	*len = st.st_size;
-	close (fh);
-	return buf;
-}
-
 /* shrink the file to roughly prefs.hex_text_max_lines */
 
 static void
 scrollback_shrink (session *sess)
 {
-	char file[1024];
+	char *file;
 	char *buf;
 	int fh;
 	int lines;
@@ -175,12 +143,17 @@ scrollback_shrink (session *sess)
 	sess->scrollwritten = 0;
 	lines = 0;
 
-	if (scrollback_get_filename (sess, file, sizeof (file)) == NULL)
+	if ((file = scrollback_get_filename (sess)) == NULL)
+	{
+		g_free (file);
 		return;
+	}
 
-	buf = file_to_buffer (file, &len);
-	if (!buf)
+	if (!g_file_get_contents (file, &buf, &len, NULL))
+	{
+		g_free (file);
 		return;
+	}
 
 	/* count all lines */
 	p = buf;
@@ -191,7 +164,8 @@ scrollback_shrink (session *sess)
 		p++;
 	}
 
-	fh = open (file, O_CREAT | O_TRUNC | O_APPEND | O_WRONLY, 0644);
+	fh = g_open (file, O_CREAT | O_TRUNC | O_APPEND | O_WRONLY, 0644);
+	g_free (file);
 	if (fh == -1)
 	{
 		free (buf);
@@ -223,7 +197,7 @@ scrollback_shrink (session *sess)
 static void
 scrollback_save (session *sess, char *text)
 {
-	char buf[512 * 4];
+	char *buf;
 	time_t stamp;
 	int len;
 
@@ -243,19 +217,22 @@ scrollback_save (session *sess, char *text)
 
 	if (sess->scrollfd == -1)
 	{
-		if (scrollback_get_filename (sess, buf, sizeof (buf)) == NULL)
+		if ((buf = scrollback_get_filename (sess)) == NULL)
 			return;
 
-		sess->scrollfd = open (buf, O_CREAT | O_APPEND | O_WRONLY, 0644);
+		sess->scrollfd = g_open (buf, O_CREAT | O_APPEND | O_WRONLY, 0644);
+		g_free (buf);
 		if (sess->scrollfd == -1)
 			return;
 	}
 
 	stamp = time (0);
 	if (sizeof (stamp) == 4)	/* gcc will optimize one of these out */
-		write (sess->scrollfd, buf, snprintf (buf, sizeof (buf), "T %d ", (int)stamp));
+		buf = g_strdup_printf ("T %d", (int) stamp);
 	else
-		write (sess->scrollfd, buf, snprintf (buf, sizeof (buf), "T %"G_GINT64_FORMAT" ", (gint64)stamp));
+		buf = g_strdup_printf ("T %" G_GINT64_FORMAT " ", (gint64)stamp);
+	write (sess->scrollfd, buf, strlen (buf));
+	g_free (buf);
 
 	len = strlen (text);
 	write (sess->scrollfd, text, len);
@@ -273,17 +250,15 @@ void
 scrollback_load (session *sess)
 {
 	int fh;
-	char buf[512 * 4];
+	char *buf;
+	char line_buf[512 * 4];
 	char *text;
 	time_t stamp;
 	int lines;
+	GIOChannel *io;
+	GError* io_err;
 
-#ifdef WIN32
-#if 0
-	char *cleaned_text;
-	int cleaned_len;
-#endif
-#else
+#ifndef WIN32
 	char *map, *end_map;
 	struct stat statbuf;
 	const char *begin, *eol;
@@ -300,129 +275,96 @@ scrollback_load (session *sess)
 			return;
 	}
 
-	if (scrollback_get_filename (sess, buf, sizeof (buf)) == NULL)
+	if ((buf = scrollback_get_filename (sess)) == NULL)
 		return;
 
-	fh = open (buf, O_RDONLY | OFLAGS);
+	fh = g_open (buf, O_RDONLY | OFLAGS, 0);
+	g_free (buf);
 	if (fh == -1)
 		return;
 
 #ifndef WIN32
-	if (fstat (fh, &statbuf) < 0)
-		return;
-
-	map = mmap (NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fh, 0);
-	if (map == MAP_FAILED)
-		return;
-
-	end_map = map + statbuf.st_size;
+	io = g_io_channel_unix_new (fh);
+#else
+	io = g_io_channel_win32_new_fd (fh);
+#endif
 
 	lines = 0;
-	begin = map;
-	while (begin < end_map)
+
+	while (1)
 	{
 		int n_bytes;
+		GIOStatus io_status;
 
-		eol = memchr (begin, '\n', end_map - begin);
-
-		if (!eol)
-			eol = end_map;
-
-		n_bytes = MIN (eol - begin, sizeof (buf) - 1);
-
-		strncpy (buf, begin, n_bytes);
-
-		buf[n_bytes] = 0;
-
-		if (buf[0] == 'T')
+		io_status = g_io_channel_read_line (io, &buf, &n_bytes, NULL, &io_err);
+		
+		if (io_status == G_IO_STATUS_NORMAL)
 		{
-			if (sizeof (time_t) == 4)
-				stamp = strtoul (buf + 2, NULL, 10);
-			else
-				stamp = strtoull (buf + 2, NULL, 10); /* just incase time_t is 64 bits */
-			text = strchr (buf + 3, ' ');
-			if (text)
-			{
-				if (prefs.hex_text_stripcolor_replay)
-				{
-					text = strip_color (text + 1, -1, STRIP_COLOR);
-				}
-				fe_print_text (sess, text, stamp);
-				if (prefs.hex_text_stripcolor_replay)
-				{
-					g_free (text);
-				}
-			}
-			lines++;
-		}
-
-		begin = eol + 1;
-	}
+			char *buf_tmp;
 
-	sess->scrollwritten = lines;
+			n_bytes--;
+			buf_tmp = buf;
+			buf = g_strndup (buf_tmp, n_bytes);
+			g_free (buf_tmp);
 
-	if (lines)
-	{
-		text = ctime (&stamp);
-		text[24] = 0;	/* get rid of the \n */
-		snprintf (buf, sizeof (buf), "\n*\t%s %s\n\n", _("Loaded log from"), text);
-		fe_print_text (sess, buf, 0);
-		/*EMIT_SIGNAL (XP_TE_GENMSG, sess, "*", buf, NULL, NULL, NULL, 0);*/
-	}
-
-	munmap (map, statbuf.st_size);
-#else
-	lines = 0;
-	while (waitline (fh, buf, sizeof buf, FALSE) != -1)
-	{
-		if (buf[0] == 'T')
-		{
-			if (sizeof (time_t) == 4)
-				stamp = strtoul (buf + 2, NULL, 10);
-			else
-				stamp = strtoull (buf + 2, NULL, 10); /* just incase time_t is 64 bits */
-			text = strchr (buf + 3, ' ');
-			if (text)
+			if (buf[0] == 'T')
 			{
-				if (prefs.hex_text_stripcolor_replay)
+				if (sizeof (time_t) == 4)
+					stamp = strtoul (buf + 2, NULL, 10);
+				else
+					stamp = strtoull (buf + 2, NULL, 10); /* in case time_t is 64 bits */
+				text = strchr (buf + 3, ' ');
+				if (text)
 				{
-					text = strip_color (text + 1, -1, STRIP_COLOR);
-				}
+					if (prefs.hex_text_stripcolor_replay)
+					{
+						text = strip_color (text + 1, -1, STRIP_COLOR);
+					}
+#ifdef WIN32
 #if 0
-				cleaned_text = text_replace_non_bmp (text, -1, &cleaned_len);
-				if (cleaned_text != NULL)
-				{
+					cleaned_text = text_replace_non_bmp (text, -1, &cleaned_len);
+					if (cleaned_text != NULL)
+					{
+						if (prefs.hex_text_stripcolor_replay)
+						{
+							g_free (text);
+						}
+						text = cleaned_text;
+					}
+#endif
+					text_replace_non_bmp2 (text);
+#endif
+					fe_print_text (sess, text, stamp);
 					if (prefs.hex_text_stripcolor_replay)
 					{
 						g_free (text);
 					}
-					text = cleaned_text;
-				}
-#endif
-				text_replace_non_bmp2 (text);
-				fe_print_text (sess, text, stamp);
-				if (prefs.hex_text_stripcolor_replay)
-				{
-					g_free (text);
 				}
+				lines++;
 			}
-			lines++;
+
+			g_free (buf);
 		}
+
+		else
+			break;
 	}
 
+	g_io_channel_unref (io);
+	g_io_channel_shutdown (io, TRUE, NULL);
+	close (fh);
+
 	sess->scrollwritten = lines;
 
 	if (lines)
 	{
 		text = ctime (&stamp);
 		text[24] = 0;	/* get rid of the \n */
-		snprintf (buf, sizeof (buf), "\n*\t%s %s\n\n", _("Loaded log from"), text);
+		buf = g_strdup_printf ("\n*\t%s %s\n\n", _("Loaded log from"), text);
 		fe_print_text (sess, buf, 0);
+		g_free (buf);
 		/*EMIT_SIGNAL (XP_TE_GENMSG, sess, "*", buf, NULL, NULL, NULL, 0);*/
 	}
-#endif
-
-	close (fh);
 }
 
 void
@@ -443,32 +385,15 @@ log_close (session *sess)
 }
 
 static void
-mkdir_p (char *dir)	/* like "mkdir -p" from a shell, FS encoding */
+mkdir_p (char *filename)
 {
-	char *start = dir;
+	char *dirname;
+	
+	dirname = g_path_get_dirname (filename);
 
-	/* the whole thing already exists? */
-	if (access (dir, F_OK) == 0)
-		return;
+	g_mkdir_with_parents (dirname, 0700);
 
-	while (*dir)
-	{
-#ifdef WIN32
-		if (dir != start && (*dir == '/' || *dir == '\\'))
-#else
-		if (dir != start && *dir == '/')
-#endif
-		{
-			*dir = 0;
-#ifdef WIN32
-			mkdir (start);
-#else
-			mkdir (start, S_IRUSR | S_IWUSR | S_IXUSR);
-#endif
-			*dir = '/';
-		}
-		dir++;
-	}
+	g_free (dirname);
 }
 
 static char *
@@ -643,19 +568,13 @@ log_create_pathname (char *servname, char *channame, char *netname)
 	}
 	else	/* relative path */
 	{
-		snprintf (fname, sizeof (fname), "%s/logs/%s", get_xdir_utf8 (), fnametime);
+		snprintf (fname, sizeof (fname), "%s" G_DIR_SEPARATOR_S "logs" G_DIR_SEPARATOR_S "%s", get_xdir (), fnametime);
 	}
 
-	/* now we need it in FileSystem encoding */
-	fs = hexchat_filename_from_utf8 (fname, -1, 0, 0, 0);
-
 	/* create all the subdirectories */
-	if (fs)
-	{
-		mkdir_p (fs);
-	}
+	mkdir_p (fname);
 
-	return fs;
+	return g_strdup(fname);
 }
 
 static int
@@ -671,9 +590,9 @@ log_open_file (char *servname, char *channame, char *netname)
 		return -1;
 
 #ifdef WIN32
-	fd = open (file, O_CREAT | O_APPEND | O_WRONLY, S_IREAD|S_IWRITE);
+	fd = g_open (file, O_CREAT | O_APPEND | O_WRONLY, S_IREAD|S_IWRITE);
 #else
-	fd = open (file, O_CREAT | O_APPEND | O_WRONLY, 0644);
+	fd = g_open (file, O_CREAT | O_APPEND | O_WRONLY, 0644);
 #endif
 	g_free (file);
 
@@ -698,12 +617,14 @@ log_open (session *sess)
 
 	if (!log_error && sess->logfd == -1)
 	{
-		char message[512];
+		char *message;
 
-		snprintf (message, sizeof (message), _("* Can't open log file(s) for writing. Check the\npermissions on %s"),
+		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)));
 
 		fe_message (message, FE_MSG_WAIT | FE_MSG_ERROR);
+
+		g_free (message);
 		log_error = TRUE;
 	}
 }
@@ -2376,9 +2297,8 @@ sound_find_command (void)
 void
 sound_play (const char *file, gboolean quiet)
 {
-	char buf[512];
-	char wavfile[512];
-	char *file_fs;
+	char *buf;
+	char *wavfile;
 	char *cmd;
 #if 0
 	LPSTR lpRes;
@@ -2390,34 +2310,27 @@ sound_play (const char *file, gboolean quiet)
 		return;
 
 #ifdef WIN32
-	/* check for fullpath, windows style */
-	if (strlen (file) > 3 &&
-		 file[1] == ':' && (file[2] == '\\' || file[2] == '/') )
-	{
-		strncpy (wavfile, file, sizeof (wavfile));
-	} else
-#endif
+	/* 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
 	{
-		snprintf (wavfile, sizeof (wavfile), "%s/%s", prefs.hex_sound_dir, file);
-	} else
+		wavfile = g_strdup (file);
+	}
+	else
 	{
-		strncpy (wavfile, file, sizeof (wavfile));
+		wavfile = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", prefs.hex_sound_dir, file);
 	}
-	wavfile[sizeof (wavfile) - 1] = 0;	/* ensure termination */
 
-	file_fs = hexchat_filename_from_utf8 (wavfile, -1, 0, 0, 0);
-	if (!file_fs)
-		return;
-
-	if (access (file_fs, R_OK) == 0)
+	if (g_access (wavfile, R_OK) == 0)
 	{
 		cmd = sound_find_command ();
 
 #ifdef WIN32
 		if (cmd == NULL || strcmp (cmd, "esdplay") == 0)
 		{
-			PlaySound (file_fs, NULL, SND_NODEFAULT|SND_FILENAME|SND_ASYNC);
+			PlaySound (wavfile, NULL, SND_NODEFAULT|SND_FILENAME|SND_ASYNC);
 #if 0			/* this would require the wav file to be added to the executable as resource */
 			hResInfo = FindResource (NULL, file_fs, "WAVE");
 			if (hResInfo != NULL)
@@ -2439,33 +2352,33 @@ sound_play (const char *file, gboolean quiet)
 				}
 			}
 #endif
-		} else
+		}
+		else
 #endif
 		{
 			if (cmd)
 			{
-				if (strchr (file_fs, ' '))
-					snprintf (buf, sizeof (buf), "%s \"%s\"", cmd, file_fs);
-				else
-					snprintf (buf, sizeof (buf), "%s %s", cmd, file_fs);
-				buf[sizeof (buf) - 1] = '\0';
+				buf = g_strdup_printf ("%s \"%s\"", cmd, wavfile);
 				hexchat_exec (buf);
+				g_free (buf);
 			}
 		}
 
 		if (cmd)
 			g_free (cmd);
 
-	} else
+	}
+	else
 	{
 		if (!quiet)
 		{
-			snprintf (buf, sizeof (buf), _("Cannot read sound file:\n%s"), wavfile);
+			buf = g_strdup_printf (_("Cannot read sound file:\n%s"), wavfile);
 			fe_message (buf, FE_MSG_ERROR);
+			g_free (buf);
 		}
 	}
 
-	g_free (file_fs);
+	g_free (wavfile);
 }
 
 void
diff --git a/src/common/util.c b/src/common/util.c
index e81486b4..d23a1d44 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -451,7 +451,7 @@ expand_homedir (char *file)
 		return ret;
 	}
 #endif
-	return strdup (file);
+	return g_strdup (file);
 }
 
 gchar *
@@ -924,7 +924,7 @@ for_files (char *dirname, char *mask, void callback (char *file))
 				if (match (mask, ent->d_name))
 				{
 					buf = malloc (strlen (dirname) + strlen (ent->d_name) + 2);
-					sprintf (buf, "%s/%s", dirname, ent->d_name);
+					sprintf (buf, "%s" G_DIR_SEPARATOR_S "%s", dirname, ent->d_name);
 					callback (buf);
 					free (buf);
 				}
@@ -1601,20 +1601,9 @@ unlink_utf8 (char *fname)
 }*/
 
 static gboolean
-file_exists_utf8 (char *fname)
+file_exists (char *fname)
 {
-	int res;
-	char *fs;
-
-	fs = hexchat_filename_from_utf8 (fname, -1, 0, 0, 0);
-	if (!fs)
-		return FALSE;
-
-	res = access (fs, F_OK);
-	g_free (fs);
-	if (res == 0)
-		return TRUE;
-	return FALSE;
+	return (g_access (fname, F_OK) == 0) ? TRUE : FALSE;
 }
 
 static gboolean
@@ -1681,79 +1670,48 @@ copy_file (char *dl_src, char *dl_dest, int permissions)	/* FS encoding */
 	return ok;
 }
 
-/* Takes care of moving a file from a temporary download location to a completed location. Now in UTF-8. */
+/* Takes care of moving a file from a temporary download location to a completed location. */
 void
-move_file_utf8 (char *src_dir, char *dst_dir, char *fname, int dccpermissions)
+move_file (char *src_dir, char *dst_dir, char *fname, int dccpermissions)
 {
-	char src[4096];
-	char dst[4096];
+	char *src;
+	char *dst;
 	int res, i;
-	char *src_fs;	/* FileSystem encoding */
-	char *dst_fs;
 
 	/* if dcc_dir and dcc_completed_dir are the same then we are done */
 	if (0 == strcmp (src_dir, dst_dir) ||
 		 0 == dst_dir[0])
 		return;			/* Already in "completed dir" */
 
-	snprintf (src, sizeof (src), "%s/%s", src_dir, fname);
-	snprintf (dst, sizeof (dst), "%s/%s", dst_dir, fname);
+	src = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", src_dir, fname);
+	dst = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", dst_dir, fname);
 
 	/* already exists in completed dir? Append a number */
-	if (file_exists_utf8 (dst))
+	if (file_exists (dst))
 	{
 		for (i = 0; ; i++)
 		{
-			snprintf (dst, sizeof (dst), "%s/%s.%d", dst_dir, fname, i);
-			if (!file_exists_utf8 (dst))
+			g_free (dst);
+			dst = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.%d", dst_dir, fname, i);
+			if (!file_exists (dst))
 				break;
 		}
 	}
 
-	/* convert UTF-8 to filesystem encoding */
-	src_fs = hexchat_filename_from_utf8 (src, -1, 0, 0, 0);
-	if (!src_fs)
-		return;
-	dst_fs = hexchat_filename_from_utf8 (dst, -1, 0, 0, 0);
-	if (!dst_fs)
-	{
-		g_free (src_fs);
-		return;
-	}
-
 	/* first try a simple rename move */
-	res = rename (src_fs, dst_fs);
+	res = g_rename (src, dst);
 
 	if (res == -1 && (errno == EXDEV || errno == EPERM))
 	{
 		/* link failed because either the two paths aren't on the */
 		/* same filesystem or the filesystem doesn't support hard */
 		/* links, so we have to do a copy. */
-		if (copy_file (src_fs, dst_fs, dccpermissions))
-			unlink (src_fs);
+		if (copy_file (src, dst, dccpermissions))
+			g_unlink (src);
 	}
 
-	g_free (dst_fs);
-	g_free (src_fs);
-}
-
-int
-mkdir_utf8 (char *dir)
-{
-	int ret;
-
-	dir = hexchat_filename_from_utf8 (dir, -1, 0, 0, 0);
-	if (!dir)
-		return -1;
-
-#ifdef WIN32
-	ret = mkdir (dir);
-#else
-	ret = mkdir (dir, S_IRUSR | S_IWUSR | S_IXUSR);
-#endif
-	g_free (dir);
-
-	return ret;
+	g_free (dst);
+	g_free (src);
 }
 
 /* separates a string according to a 'sep' char, then calls the callback
diff --git a/src/common/util.h b/src/common/util.h
index 0ff32227..8114cbc7 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -52,8 +52,7 @@ int find_font (const char *fontname);
 #define waitline2(source,buf,size) waitline(serv->childread,buf,size,0)
 #endif
 unsigned long make_ping_time (void);
-void move_file_utf8 (char *src_dir, char *dst_dir, char *fname, int dccpermissions);
-int mkdir_utf8 (char *dir);
+void move_file (char *src_dir, char *dst_dir, char *fname, int dccpermissions);
 int token_foreach (char *str, char sep, int (*callback) (char *str, void *ud), void *ud);
 guint32 str_hash (const char *key);
 guint32 str_ihash (const unsigned char *key);
diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c
index 8d6577a6..d1f23002 100644
--- a/src/fe-gtk/fe-gtk.c
+++ b/src/fe-gtk/fe-gtk.c
@@ -162,7 +162,6 @@ fe_args (int argc, char *argv[])
 	GError *error = NULL;
 	GOptionContext *context;
 #ifdef WIN32
-#define ARGBUF_SIZE 2048
 	char *buffer;
 #endif
 
@@ -187,35 +186,26 @@ fe_args (int argc, char *argv[])
 		{
 			if (strstr (error->message, "--help-all") != NULL)
 			{
-				buffer = (char*) malloc (ARGBUF_SIZE);
-				if (snprintf (buffer, ARGBUF_SIZE, g_option_context_get_help (context, FALSE, NULL)))
-				{
-					gtk_init (&argc, &argv);
-					create_msg_dialog ("Long Help", buffer);
-				}
-				free (buffer);
+				buffer = g_strdup_printf (g_option_context_get_help (context, FALSE, NULL));
+				gtk_init (&argc, &argv);
+				create_msg_dialog ("Long Help", buffer);
+				g_free (buffer);
 				return 0;
 			}
 			else if (strstr (error->message, "--help") != NULL || strstr (error->message, "-?") != NULL)
 			{
-				buffer = (char*) malloc (ARGBUF_SIZE);
-				if (snprintf (buffer, ARGBUF_SIZE, g_option_context_get_help (context, TRUE, NULL)))
-				{
-					gtk_init (&argc, &argv);
-					create_msg_dialog ("Help", buffer);
-				}
-				free (buffer);
+				buffer = g_strdup_printf (g_option_context_get_help (context, TRUE, NULL));
+				gtk_init (&argc, &argv);
+				create_msg_dialog ("Help", buffer);
+				g_free (buffer);
 				return 0;
 			}
 			else 
 			{
-				buffer = (char*) malloc (ARGBUF_SIZE);
-				if (snprintf (buffer, ARGBUF_SIZE, "%s\n", error->message))
-				{
-					gtk_init (&argc, &argv);
-					create_msg_dialog ("Error", buffer);
-				}
-				free (buffer);
+				buffer = g_strdup_printf ("%s\n", error->message);
+				gtk_init (&argc, &argv);
+				create_msg_dialog ("Error", buffer);
+				g_free (buffer);
 				return 1;
 			}
 		}
@@ -234,13 +224,10 @@ fe_args (int argc, char *argv[])
 	if (arg_show_version)
 	{
 #ifdef WIN32
-		buffer = (char*) malloc (ARGBUF_SIZE);
-		if (snprintf (buffer, ARGBUF_SIZE, DISPLAY_NAME" "PACKAGE_VERSION"\n"))
-		{
-			gtk_init (&argc, &argv);
-			create_msg_dialog ("Version Information", buffer);
-		}
-		free (buffer);
+		buffer = g_strdup_printf (DISPLAY_NAME " " PACKAGE_VERSION "\n");
+		gtk_init (&argc, &argv);
+		create_msg_dialog ("Version Information", buffer);
+		g_free (buffer);
 #else
 		printf (PACKAGE_TARNAME" "PACKAGE_VERSION"\n");
 #endif
@@ -253,25 +240,20 @@ fe_args (int argc, char *argv[])
 		/* see the chdir() below */
 		char *sl, *exe = strdup (argv[0]);
 		sl = strrchr (exe, '\\');
-		buffer = (char*) malloc (ARGBUF_SIZE);
 		if (sl)
 		{
 			*sl = 0;
-			if (snprintf (buffer, ARGBUF_SIZE, "%s\\plugins\n", exe))
-			{
-				gtk_init (&argc, &argv);
-				create_msg_dialog ("Plugin Auto-load Directory", buffer);
-			}
+			buffer = g_strdup_printf ("%s\\plugins\n", exe);
+			gtk_init (&argc, &argv);
+			create_msg_dialog ("Plugin Auto-load Directory", buffer);
 		}
 		else
 		{
-			if (snprintf (buffer, ARGBUF_SIZE, ".\\plugins\n"))
-			{
-				gtk_init (&argc, &argv);
-				create_msg_dialog ("Plugin Auto-load Directory", buffer);
-			}
+			buffer = g_strdup(".\\plugins\n");
+			gtk_init (&argc, &argv);
+			create_msg_dialog ("Plugin Auto-load Directory", buffer);
 		}
-		free (buffer);
+		g_free (buffer);
 #else
 		printf ("%s\n", HEXCHATLIBDIR"/plugins");
 #endif
@@ -281,15 +263,12 @@ fe_args (int argc, char *argv[])
 	if (arg_show_config)
 	{
 #ifdef WIN32
-		buffer = (char*) malloc (ARGBUF_SIZE);
-		if (snprintf (buffer, ARGBUF_SIZE, "%s\n", get_xdir_fs ()))
-		{
-			gtk_init (&argc, &argv);
-			create_msg_dialog ("User Config Directory", buffer);
-		}
-		free (buffer);
+		buffer = g_strdup_printf ("%s\n", get_xdir ());
+		gtk_init (&argc, &argv);
+		create_msg_dialog ("User Config Directory", buffer);
+		g_free (buffer);
 #else
-		printf ("%s\n", get_xdir_fs ());
+		printf ("%s\n", get_xdir ());
 #endif
 		return 0;
 	}
@@ -313,12 +292,14 @@ fe_args (int argc, char *argv[])
 	}
 #endif
 
-	if (arg_cfgdir)	/* we want filesystem encoding */
+	if (arg_cfgdir)
 	{
-		xdir_fs = strdup (arg_cfgdir);
-		if (xdir_fs[strlen (xdir_fs) - 1] == '/')
+		if (xdir)
+			g_free (xdir);
+		xdir = strdup (arg_cfgdir);
+		if (xdir[strlen (xdir) - 1] == '/')
 		{
-			xdir_fs[strlen (xdir_fs) - 1] = 0;
+			xdir[strlen (xdir) - 1] = 0;
 		}
 		g_free (arg_cfgdir);
 	}
diff --git a/src/fe-gtk/fkeys.c b/src/fe-gtk/fkeys.c
index f86a59f8..4e0cd4a3 100644
--- a/src/fe-gtk/fkeys.c
+++ b/src/fe-gtk/fkeys.c
@@ -1019,8 +1019,8 @@ key_load_kbs (char *filename)
 				free (ibuf);
 				ibuf = malloc (1024);
 				snprintf (ibuf, 1024,
-							 _("Unknown keyname %s in key bindings config file\nLoad aborted, please fix %s/keybindings.conf\n"),
-							 buf, get_xdir_utf8 ());
+							 _("Unknown keyname %s in key bindings config file\nLoad aborted, please fix %s" G_DIR_SEPARATOR_S "keybindings.conf\n"),
+							 buf, get_xdir ());
 				fe_message (ibuf, FE_MSG_ERROR);
 				free (ibuf);
 				return 2;
@@ -1057,8 +1057,8 @@ key_load_kbs (char *filename)
 				free (ibuf);
 				ibuf = malloc (1024);
 				snprintf (ibuf, 1024,
-							 _("Unknown action %s in key bindings config file\nLoad aborted, Please fix %s/keybindings\n"),
-							 buf, get_xdir_utf8 ());
+							 _("Unknown action %s in key bindings config file\nLoad aborted, Please fix %s" G_DIR_SEPARATOR_S "keybindings\n"),
+							 buf, get_xdir ());
 				fe_message (ibuf, FE_MSG_ERROR);
 				free (ibuf);
 				return 3;
@@ -1078,8 +1078,8 @@ key_load_kbs (char *filename)
 				free (ibuf);
 				ibuf = malloc (1024);
 				snprintf (ibuf, 1024,
-							 _("Expecting Data line (beginning Dx{:|!}) but got:\n%s\n\nLoad aborted, Please fix %s/keybindings\n"),
-							 buf, get_xdir_utf8 ());
+							 _("Expecting Data line (beginning Dx{:|!}) but got:\n%s\n\nLoad aborted, Please fix %s" G_DIR_SEPARATOR_S "keybindings\n"),
+							 buf, get_xdir ());
 				fe_message (ibuf, FE_MSG_ERROR);
 				free (ibuf);
 				return 4;
@@ -1148,8 +1148,8 @@ key_load_kbs (char *filename)
 		abort ();*/
 	snprintf (ibuf, 1024,
 						_("Key bindings config file is corrupt, load aborted\n"
-								 "Please fix %s/keybindings.conf\n"),
-						 get_xdir_utf8 ());
+								 "Please fix %s" G_DIR_SEPARATOR_S "keybindings.conf\n"),
+						 get_xdir ());
 	fe_message (ibuf, FE_MSG_ERROR);
 	free (ibuf);
 	return 5;
diff --git a/src/fe-gtk/gtkutil.c b/src/fe-gtk/gtkutil.c
index e44c3d59..fa88ac79 100644
--- a/src/fe-gtk/gtkutil.c
+++ b/src/fe-gtk/gtkutil.c
@@ -186,192 +186,6 @@ gtkutil_file_req_response (GtkWidget *dialog, gint res, struct file_req *freq)
 	}
 }
 
-#if 0	/* native file dialogs */
-#ifdef WIN32
-static int
-win32_openfile (char *file_buf, int file_buf_len, char *title_text, char *filter,
-			   int multiple)
-{
-	OPENFILENAME o;
-
-	memset (&o, 0, sizeof (o));
-
-	o.lStructSize = sizeof (o);
-	o.lpstrFilter = filter;
-	o.lpstrFile = file_buf;
-	o.nMaxFile = file_buf_len;
-	o.lpstrTitle = title_text;
-	o.Flags = 0x02000000 | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
-				OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_LONGNAMES | OFN_NONETWORKBUTTON;
-	if (multiple)
-	{
-		o.Flags |= OFN_ALLOWMULTISELECT;
-	}
-
-	return GetOpenFileName (&o);
-}
-
-static int
-win32_savefile (char *file_buf, int file_buf_len, char *title_text, char *filter,
-               int multiple)
-{
-	/* we need the filter to get the default filename. it is from fe-gtk.c (fe_confirm);
-	 * but that filter is actually the whole filename, so apply an empty filter and all good.
-	 * in win32_thread2 we copy the filter ( = the filename) after the last dir into our
-	 * LPTSTR file buffer to make it actually work. the docs for this amazingly retard api:
-	 *
-	 * http://msdn.microsoft.com/en-us/library/ms646839%28VS.85%29.aspx
-	 */
-
-	OPENFILENAME o;
-
-	memset (&o, 0, sizeof (o));
-
-	o.lStructSize = sizeof (o);
-	o.lpstrFilter = "All files\0*.*\0\0";
-	o.lpstrFile = file_buf;
-	o.nMaxFile = file_buf_len;
-	o.lpstrTitle = title_text;
-	o.Flags = 0x02000000 | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
-				OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_LONGNAMES | OFN_NONETWORKBUTTON;
-	if (multiple)
-	{
-		o.Flags |= OFN_ALLOWMULTISELECT;
-	}
-
-	return GetSaveFileName (&o);
-}
-
-static void *
-win32_thread (struct file_req *freq)
-{
-	char buf[1024 + 32];
-	char file[1024];
-
-	memset (file, 0, sizeof (file));
-	safe_strcpy (file, last_dir, sizeof (file));
-
-	if (win32_openfile (file, sizeof (file), freq->title, freq->filter, freq->multiple))
-	{
-		if (freq->multiple)
-		{
-			char *f = file;
-
-			if (f[strlen (f) + 1] == 0)	/* only selected one file */
-			{
-				snprintf (buf, sizeof (buf), "1\n%s\n", file);
-				write (freq->th->pipe_fd[1], buf, strlen (buf));
-			} else
-			{
-				f += strlen (f) + 1; /* skip first, it's only the dir */
-				while (f[0])
-				{
-					snprintf (buf, sizeof (buf), "1\n%s\\%s\n", /*dir!*/file, f);
-					write (freq->th->pipe_fd[1], buf, strlen (buf));
-					f += strlen (f) + 1;
-				}
-			}
-
-		} else
-		{
-			snprintf (buf, sizeof (buf), "1\n%s\n", file);
-			write (freq->th->pipe_fd[1], buf, strlen (buf));
-		}
-	}
-
-	write (freq->th->pipe_fd[1], "0\n", 2);
-	Sleep (2000);
-
-	return NULL;
-}
-
-static void *
-win32_thread2 (struct file_req *freq)
-{
-	char buf[1024 + 32];
-	char file[1024];
-
-	memset (file, 0, sizeof (file));
-	safe_strcpy (file, last_dir, sizeof (file));
-	safe_strcpy (file, freq->filter, sizeof (file));
-
-	if (win32_savefile (file, sizeof (file), freq->title, NULL, freq->multiple))
-	{
-		if (freq->multiple)
-		{
-			char *f = file;
-
-			if (f[strlen (f) + 1] == 0)    /* only selected one file */
-			{
-				snprintf (buf, sizeof (buf), "1\n%s\n", file);
-				write (freq->th->pipe_fd[1], buf, strlen (buf));
-			} else
-			{
-				f += strlen (f) + 1; /* skip first, it's only the dir */
-				while (f[0])
-				{
-					snprintf (buf, sizeof (buf), "1\n%s\\%s\n", /*dir!*/file, f);
-					write (freq->th->pipe_fd[1], buf, strlen (buf));
-					f += strlen (f) + 1;
-				}
-			}
-
-		} else
-		{
-			snprintf (buf, sizeof (buf), "1\n%s\n", file);
-			write (freq->th->pipe_fd[1], buf, strlen (buf));
-		}
-	}
-
-	write (freq->th->pipe_fd[1], "0\n", 2);
-	Sleep (2000);
-
-	return NULL;
-}
-
-static gboolean
-win32_close_pipe (int fd)
-{
-	close (fd);
-	return 0;
-}
-
-static gboolean
-win32_read_thread (GIOChannel *source, GIOCondition cond, struct file_req *freq)
-{
-	char buf[512];
-	char *file;
-
-	waitline2 (source, buf, sizeof buf);
-
-	switch (buf[0])
-	{
-	case '0':	/* filedialog has closed */
-		freq->callback (freq->userdata, NULL);
-		break;
-
-	case '1':	/* got a filename! */
-		waitline2 (source, buf, sizeof buf);
-		file = g_filename_to_utf8 (buf, -1, 0, 0, 0);
-		freq->callback (freq->userdata, file);
-		g_free (file);
-		return TRUE;
-	}
-
-	/* it doesn't work to close them here, because of the weird
-		way giowin32 works. We must _return_ before closing them */
-	g_timeout_add(3000, (GSourceFunc)win32_close_pipe, freq->th->pipe_fd[0]);
-	g_timeout_add(2000, (GSourceFunc)win32_close_pipe, freq->th->pipe_fd[1]);
-
-	g_free (freq->title);
-	free (freq->th);
-	free (freq);
-
-	return FALSE;
-}
-#endif
-#endif	/* native file dialogs */
-
 void
 gtkutil_file_req (const char *title, void *callback, void *userdata, char *filter, char *extensions,
 						int flags)
@@ -467,7 +281,7 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
 		gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), last_dir);
 	if (flags & FRF_ADDFOLDER)
 		gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog),
-														  get_xdir_fs (), NULL);
+														  get_xdir (), NULL);
 	if (flags & FRF_CHOOSEFOLDER)
 	{
 		gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
@@ -491,7 +305,7 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
 		/* by default, open the config folder */
 		else
 		{
-			gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), get_xdir_fs ());
+			gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), get_xdir ());
 		}
 	}
 
diff --git a/src/fe-gtk/menu.c b/src/fe-gtk/menu.c
index 8b25f4ed..dbdd1997 100644
--- a/src/fe-gtk/menu.c
+++ b/src/fe-gtk/menu.c
@@ -286,8 +286,8 @@ menu_quick_item (char *cmd, char *label, GtkWidget * menu, int flags,
 				img = gtk_image_new_from_file (icon);
 			else
 			{
-				/* try relative to ~/.xchat2 */
-				path = g_strdup_printf ("%s/%s", get_xdir_fs (), icon);
+				/* try relative to <xdir> */
+				path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", get_xdir (), icon);
 				if (access (path, R_OK) == 0)
 					img = gtk_image_new_from_file (path);
 				else
diff --git a/src/fe-gtk/pixmaps.c b/src/fe-gtk/pixmaps.c
index 1a5add8c..f1b39b02 100644
--- a/src/fe-gtk/pixmaps.c
+++ b/src/fe-gtk/pixmaps.c
@@ -105,7 +105,7 @@ load_pixmap (const char *filename, const char *name, int has_inline)
 	gchar *path;
 	GdkPixbuf *pixbuf;
 
-	path = g_strdup_printf ("%s/icons/%s.png", get_xdir_utf8 (), filename);
+	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/plugingui.c b/src/fe-gtk/plugingui.c
index a488b19e..e344c336 100644
--- a/src/fe-gtk/plugingui.c
+++ b/src/fe-gtk/plugingui.c
@@ -147,30 +147,18 @@ plugingui_load_cb (session *sess, char *file)
 void
 plugingui_load (void)
 {
-	/* let's do it the Perl way */
-	const char *xdir;
 	char *sub_dir;
 
-	xdir = get_xdir_utf8 ();
-	sub_dir = malloc (strlen (xdir) + 8);
-	strcpy (sub_dir, xdir);
-	strcat (sub_dir, "/addons");
+	sub_dir = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "addons", get_xdir());
 
 	gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess,
-#if 0	/* native file dialogs */
-#ifdef WIN32
-							"Plugins and Scripts\0*.dll;*.lua;*.pl;*.py;*.tcl\0"
-							"All files\0*.*\0\0", 0);
-#else
-#endif
-#endif	/* native file dialogs */
 #ifdef WIN32
 							sub_dir, "*.dll;*.lua;*.pl;*.py;*.tcl", FRF_ADDFOLDER|FRF_FILTERISINITIAL|FRF_EXTENSIONS);
 #else
 							sub_dir, "*.so;*.lua;*.pl;*.py;*.tcl", FRF_ADDFOLDER|FRF_FILTERISINITIAL|FRF_EXTENSIONS);
 #endif
 
-	free (sub_dir);
+	g_free (sub_dir);
 }
 
 static void
diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c
index 2e5281f7..d3964557 100644
--- a/src/fe-gtk/setup.c
+++ b/src/fe-gtk/setup.c
@@ -1245,7 +1245,7 @@ setup_create_frame (GtkWidget **left, GtkWidget *box)
 static void
 open_data_cb (GtkWidget *button, gpointer data)
 {
-	fe_open_url (get_xdir_utf8 ());
+	fe_open_url (get_xdir ());
 }
 
 static GtkWidget *
@@ -2135,8 +2135,8 @@ setup_apply_real (int new_pix, int do_ulist, int do_layout)
 	unslash (prefs.hex_dcc_dir);
 	unslash (prefs.hex_dcc_completed_dir);
 
-	mkdir_utf8 (prefs.hex_dcc_dir);
-	mkdir_utf8 (prefs.hex_dcc_completed_dir);
+	g_mkdir (prefs.hex_dcc_dir, 0700);
+	g_mkdir (prefs.hex_dcc_completed_dir, 0700);
 
 	if (new_pix)
 	{
diff --git a/src/fe-gtk/urlgrab.c b/src/fe-gtk/urlgrab.c
index 68d796eb..89ea374f 100644
--- a/src/fe-gtk/urlgrab.c
+++ b/src/fe-gtk/urlgrab.c
@@ -147,7 +147,7 @@ static void
 url_button_save (void)
 {
 	gtkutil_file_req (_("Select an output filename"),
-							url_save_callback, NULL, get_xdir_utf8 (), NULL, FRF_WRITE|FRF_FILTERISINITIAL);
+							url_save_callback, NULL, get_xdir (), NULL, FRF_WRITE|FRF_FILTERISINITIAL);
 }
 
 void
diff --git a/src/fe-text/fe-text.c b/src/fe-text/fe-text.c
index 19749a65..c553d9f3 100644
--- a/src/fe-text/fe-text.c
+++ b/src/fe-text/fe-text.c
@@ -513,15 +513,17 @@ fe_args (int argc, char *argv[])
 
 	if (arg_show_config)
 	{
-		printf ("%s\n", get_xdir_fs ());
+		printf ("%s\n", get_xdir ());
 		return 0;
 	}
 
 	if (arg_cfgdir)	/* we want filesystem encoding */
 	{
-		xdir_fs = strdup (arg_cfgdir);
-		if (xdir_fs[strlen (xdir_fs) - 1] == '/')
-			xdir_fs[strlen (xdir_fs) - 1] = 0;
+		if (xdir)
+			g_free (xdir);
+		xdir = strdup (arg_cfgdir);
+		if (xdir[strlen (xdir) - 1] == '/')
+			xdir[strlen (xdir) - 1] = 0;
 		g_free (arg_cfgdir);
 	}