summary refs log tree commit diff stats
path: root/src/fe-gtk
diff options
context:
space:
mode:
Diffstat (limited to 'src/fe-gtk')
-rw-r--r--src/fe-gtk/Makefile.am4
-rw-r--r--src/fe-gtk/about.c162
-rw-r--r--src/fe-gtk/about.h25
-rw-r--r--src/fe-gtk/chanlist.c1
-rw-r--r--src/fe-gtk/dccgui.c74
-rw-r--r--src/fe-gtk/fe-gtk.c23
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj2
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj.filters6
-rw-r--r--src/fe-gtk/fkeys.c32
-rw-r--r--src/fe-gtk/gtkutil.c123
-rw-r--r--src/fe-gtk/gtkutil.h8
-rw-r--r--src/fe-gtk/joind.c8
-rw-r--r--src/fe-gtk/maingui.c6
-rw-r--r--src/fe-gtk/menu.c57
-rw-r--r--src/fe-gtk/notifygui.c1
-rw-r--r--src/fe-gtk/plugingui.c53
-rw-r--r--src/fe-gtk/servlistgui.c18
-rw-r--r--src/fe-gtk/setup.c31
-rw-r--r--src/fe-gtk/urlgrab.c2
-rw-r--r--src/fe-gtk/xtext.c47
20 files changed, 342 insertions, 341 deletions
diff --git a/src/fe-gtk/Makefile.am b/src/fe-gtk/Makefile.am
index 1890edbf..24098ace 100644
--- a/src/fe-gtk/Makefile.am
+++ b/src/fe-gtk/Makefile.am
@@ -7,7 +7,7 @@ AM_CPPFLAGS = $(GUI_CFLAGS) -DLOCALEDIR=\"$(localedir)\"
 hexchat_LDADD = ../common/libhexchatcommon.a $(GUI_LIBS)
 
 EXTRA_DIST = \
-	about.h ascii.h banlist.h chanlist.h chanview.h chanview-tabs.c \
+	ascii.h banlist.h chanlist.h chanview.h chanview-tabs.c \
 	chanview-tree.c custom-list.h editlist.h fe-gtk.h fkeys.h gtkutil.h joind.h \
 	maingui.h menu.h mmx_cmod.S mmx_cmod.h notifygui.h palette.h pixmaps.h \
 	plugin-tray.h plugingui.c plugingui.h rawlog.h sexy-iso-codes.h \
@@ -26,7 +26,7 @@ sexy_spell = \
 	sexy-iso-codes.c sexy-marshal.c sexy-spell-entry.c
 endif
 
-hexchat_SOURCES = about.c ascii.c banlist.c chanlist.c chanview.c custom-list.c \
+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 $(mmx_cmod_S) notifygui.c palette.c pixmaps.c plugin-tray.c $(plugingui_c) \
 	rawlog.c servlistgui.c setup.c $(sexy_spell) textgui.c \
diff --git a/src/fe-gtk/about.c b/src/fe-gtk/about.c
deleted file mode 100644
index c47fba4f..00000000
--- a/src/fe-gtk/about.c
+++ /dev/null
@@ -1,162 +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
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "fe-gtk.h"
-
-#ifdef USE_XLIB
-#include <gdk/gdkx.h>
-#endif
-
-#include "../common/hexchat.h"
-#include "../common/util.h"
-#include "../common/hexchatc.h"
-#include "palette.h"
-#include "pixmaps.h"
-#include "gtkutil.h"
-#include "about.h"
-
-static GtkWidget *about = 0;
-
-static int
-about_close (void)
-{
-	about = 0;
-	return 0;
-}
-
-void
-menu_about (GtkWidget * wid, gpointer sess)
-{
-	GtkWidget *vbox;									/* the main vertical box inside the about dialog */
-	GtkWidget *hbox_main;								/* horizontal box for containing text on the left and logo on the right */
-	GtkWidget *vbox_logo;								/* vertical box for our logo */
-	GtkWidget *vbox_text;								/* vertical box for text */
-	GtkWidget *label_title;								/* label for the main title */
-	GtkWidget *label_subtitle;							/* label for the subtitle */
-	GtkWidget *label_info;								/* for the informative text */
-	GtkWidget *label_copyright;							/* for copyright notices */
-	GdkColor color;										/* color buffer for our nice paintings */
-	char buf[512];										/* text buffer for the labels */
-	const char *locale = NULL;
-	extern GtkWindow *parent_window;					/* maingui.c */
-
-	if (about)
-	{
-		gtk_window_present (GTK_WINDOW (about));
-		return;
-	}
-
-	/* general about dialog initialization */
-	about = gtk_dialog_new ();
-	gtk_window_set_position (GTK_WINDOW (about), GTK_WIN_POS_CENTER_ON_PARENT);
-	gtk_window_set_resizable (GTK_WINDOW (about), FALSE);
-	gtk_window_set_title (GTK_WINDOW (about), _("About "DISPLAY_NAME));
-	if (parent_window)
-	{
-		gtk_window_set_transient_for (GTK_WINDOW (about), parent_window);
-	}
-	g_signal_connect (G_OBJECT (about), "destroy", G_CALLBACK (about_close), 0);
-	vbox = GTK_DIALOG (about)->vbox;
-
-	/* main horizontal box, text on the left, logo on the right */
-	hbox_main = gtk_hbox_new (FALSE, 0);
-	gtk_container_add (GTK_CONTAINER (vbox), GTK_WIDGET (hbox_main));
-
-	/* textbox on the left */
-	vbox_text = gtk_vbox_new (FALSE, 0);
-	gtk_box_pack_start (GTK_BOX (hbox_main), vbox_text, 0, 0, 5);
-
-	/* label for title */
-	snprintf (buf, sizeof (buf), "<span size=\"x-large\"><b>"DISPLAY_NAME"</b></span>");
-	label_title = gtk_label_new (NULL);
-	gtk_misc_set_alignment (GTK_MISC (label_title), 0, 0);
-	gtk_box_pack_start (GTK_BOX (vbox_text), label_title, 0, 0, 10);
-	color.red   = 0xd7d7;
-	color.green = 0x4343;
-	color.blue  = 0x0404;
-	gtk_widget_modify_fg (label_title, GTK_STATE_NORMAL, &color);
-	gtk_label_set_markup (GTK_LABEL (label_title), buf);
-
-	/* label for subtitle */
-	snprintf (buf, sizeof (buf), "%s", _("<b>A multiplatform IRC Client</b>"));
-	label_subtitle = gtk_label_new (NULL);
-	gtk_misc_set_alignment (GTK_MISC (label_subtitle), 0, 0);
-	gtk_box_pack_start (GTK_BOX (vbox_text), label_subtitle, 0, 0, 10);
-	color.red   = 0x5555;
-	color.green = 0x5555;
-	color.blue  = 0x5555;
-	gtk_widget_modify_fg (label_subtitle, GTK_STATE_NORMAL, &color);
-	gtk_label_set_markup (GTK_LABEL (label_subtitle), buf);
-
-	/* label for additional info */
-	g_get_charset (&locale);
-	(snprintf) (buf, sizeof (buf),
-				"<b>Version:</b> "PACKAGE_VERSION"\n"
-				"<b>Compiled:</b> "__DATE__"\n"
-#ifdef WIN32
-				"<b>Portable Mode:</b> %s\n"
-				"<b>Build Type:</b> x%d\n"
-#endif
-				"<b>OS:</b> %s\n"
-				"<b>Charset:</b> %s",
-#ifdef WIN32
-				(portable_mode () ? "Yes" : "No"),
-				get_cpu_arch (),
-#endif
-				get_sys_str (0),
-				locale);
-
-	label_info = gtk_label_new (NULL);
-	gtk_misc_set_alignment (GTK_MISC (label_info), 0, 0);
-	gtk_box_pack_start (GTK_BOX (vbox_text), label_info, 0, 0, 10);
-	gtk_label_set_selectable (GTK_LABEL (label_info), TRUE);
-	gtk_label_set_markup (GTK_LABEL (label_info), buf);
-
-	/* label for copyright notices */
-	snprintf (buf, sizeof (buf), "<small>\302\251 1998-2010 Peter \305\275elezn\303\275\n\302\251 2009-2013 Berke Viktor</small>");
-	label_copyright = gtk_label_new (NULL);
-	gtk_misc_set_alignment (GTK_MISC (label_copyright), 0, 0);
-	gtk_box_pack_start (GTK_BOX (vbox_text), label_copyright, 0, 0, 10);
-	gtk_label_set_markup (GTK_LABEL (label_copyright), buf);
-
-	/* imagebox on the right */
-	vbox_logo = gtk_vbox_new (FALSE, 0);
-	gtk_box_pack_start (GTK_BOX (hbox_main), vbox_logo, 0, 0, 10);
-
-	/* the actual image */
-	wid = gtk_image_new_from_pixbuf (pix_hexchat);
-	gtk_box_pack_start (GTK_BOX (vbox_logo), wid, 0, 0, 10);
-
-	/* our close button on the bottom right */
-	wid = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
-	GTK_WIDGET_SET_FLAGS (GTK_WIDGET (wid), GTK_CAN_DEFAULT);
-	gtk_box_pack_end (GTK_BOX (GTK_DIALOG (about)->action_area), wid, 0, 0, 0);
-	gtk_widget_grab_default (wid);
-	g_signal_connect (G_OBJECT (wid), "clicked", G_CALLBACK (gtkutil_destroy), about);
-
-	/* pure white background for the whole about widget*/
-	color.red = color.green = color.blue = 0xffff;
-	gtk_widget_modify_bg (about, GTK_STATE_NORMAL, &color);
-
-	/* show off! */
-	gtk_widget_show_all (about);
-}
diff --git a/src/fe-gtk/about.h b/src/fe-gtk/about.h
deleted file mode 100644
index b4d5cb34..00000000
--- a/src/fe-gtk/about.h
+++ /dev/null
@@ -1,25 +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
- */
-
-#ifndef HEXCHAT_ABOUT_H
-#define HEXCHAT_ABOUT_H
-
-void menu_about (GtkWidget * wid, gpointer sess);
-
-#endif
diff --git a/src/fe-gtk/chanlist.c b/src/fe-gtk/chanlist.c
index 0f0307b7..d0e0ea40 100644
--- a/src/fe-gtk/chanlist.c
+++ b/src/fe-gtk/chanlist.c
@@ -747,6 +747,7 @@ chanlist_opengui (server *serv, int do_refresh)
 	serv->gui->chanlist_window =
 		mg_create_generic_tab ("ChanList", tbuf, FALSE, TRUE, chanlist_closegui,
 								serv, 640, 480, &vbox, serv);
+	gtkutil_destroy_on_esc (serv->gui->chanlist_window);
 
 	gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
 	gtk_box_set_spacing (GTK_BOX (vbox), 12);
diff --git a/src/fe-gtk/dccgui.c b/src/fe-gtk/dccgui.c
index 24d3bcbf..a3c2619a 100644
--- a/src/fe-gtk/dccgui.c
+++ b/src/fe-gtk/dccgui.c
@@ -78,6 +78,7 @@ struct dccwindow
 	GtkWidget *accept_button;
 	GtkWidget *resume_button;
 	GtkWidget *open_button;
+	GtkWidget *clear_button; /* clears aborted and completed requests */	
 
 	GtkWidget *file_label;
 	GtkWidget *address_label;
@@ -380,6 +381,50 @@ dcc_append (struct DCC *dcc, GtkListStore *store, gboolean prepend)
 		dcc_prepare_row_send (dcc, store, &iter, FALSE);
 }
 
+/* Returns aborted and completed transfers. */
+static GSList *
+dcc_get_completed (void)
+{
+	struct DCC *dcc;
+	GtkTreeIter iter;
+	GtkTreeModel *model;	
+	GSList *completed = NULL;
+
+	model = GTK_TREE_MODEL (dccfwin.store);
+	if (gtk_tree_model_get_iter_first (model, &iter))
+	{
+		do
+		{
+			gtk_tree_model_get (model, &iter, COL_DCC, &dcc, -1);
+			if (is_dcc_completed (dcc))
+				completed = g_slist_prepend (completed, dcc);
+				
+		} while (gtk_tree_model_iter_next (model, &iter));
+	}
+
+	return completed;
+}
+
+static gboolean
+dcc_completed_transfer_exists (void)
+{
+	gboolean exist;
+	GSList *comp_list;
+	
+	comp_list = dcc_get_completed (); 
+	exist = comp_list != NULL;
+	
+	g_slist_free (comp_list);	
+	return exist;
+}
+
+static void
+update_clear_button_sensitivity (void)
+{
+	gboolean sensitive = dcc_completed_transfer_exists ();
+	gtk_widget_set_sensitive (dccfwin.clear_button, sensitive);
+}
+
 static void
 dcc_fill_window (int flags)
 {
@@ -426,6 +471,8 @@ dcc_fill_window (int flags)
 		gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dccfwin.store), &iter);
 		gtk_tree_selection_select_iter (dccfwin.sel, &iter);
 	}
+	
+	update_clear_button_sensitivity ();
 }
 
 /* return list of selected DCCs */
@@ -511,6 +558,9 @@ abort_clicked (GtkWidget * wid, gpointer none)
 		dcc_abort (dcc->serv->front_session, dcc);
 	}
 	g_slist_free (start);
+	
+	/* Enable the clear button if it wasn't already enabled */
+	update_clear_button_sensitivity ();
 }
 
 static void
@@ -530,6 +580,27 @@ accept_clicked (GtkWidget * wid, gpointer none)
 }
 
 static void
+clear_completed (GtkWidget * wid, gpointer none)
+{
+	struct DCC *dcc;
+	GSList *completed;
+
+	/* Make a new list of only the completed items and abort each item.
+	 * A new list is made because calling dcc_abort removes items from the original list,
+	 * making it impossible to iterate over that list directly.
+	*/
+	for (completed = dcc_get_completed (); completed; completed = completed->next)
+	{
+		dcc = completed->data;
+		dcc_abort (dcc->serv->front_session, dcc);
+	}
+
+	/* The data was freed by dcc_close */
+	g_slist_free (completed);
+	update_clear_button_sensitivity ();
+}
+
+static void
 browse_folder (char *dir)
 {
 #ifdef WIN32
@@ -812,6 +883,7 @@ fe_dcc_open_recv_win (int passive)
 	dccfwin.abort_button = gtkutil_button (bbox, GTK_STOCK_CANCEL, 0, abort_clicked, 0, _("Abort"));
 	dccfwin.accept_button = gtkutil_button (bbox, GTK_STOCK_APPLY, 0, accept_clicked, 0, _("Accept"));
 	dccfwin.resume_button = gtkutil_button (bbox, GTK_STOCK_REFRESH, 0, resume_clicked, 0, _("Resume"));
+	dccfwin.clear_button = gtkutil_button (bbox, GTK_STOCK_CLEAR, 0, clear_completed, 0, _("Clear"));
 	dccfwin.open_button = gtkutil_button (bbox, 0, 0, browse_dcc_folder, 0, _("Open Folder..."));
 	gtk_widget_set_sensitive (dccfwin.accept_button, FALSE);
 	gtk_widget_set_sensitive (dccfwin.resume_button, FALSE);
@@ -1055,6 +1127,8 @@ fe_dcc_update (struct DCC *dcc)
 	default:
 		dcc_update_chat (dcc);
 	}
+
+	update_clear_button_sensitivity ();
 }
 
 void
diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c
index c8a80369..3469569e 100644
--- a/src/fe-gtk/fe-gtk.c
+++ b/src/fe-gtk/fe-gtk.c
@@ -220,26 +220,26 @@ fe_args (int argc, char *argv[])
 
 	if (arg_show_version)
 	{
+		buffer = g_strdup_printf ("%s %s", PACKAGE_NAME, PACKAGE_VERSION);
 #ifdef WIN32
-		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_NAME" "PACKAGE_VERSION"\n");
+		puts (buffer);
 #endif
+		g_free (buffer);
 
 		return 0;
 	}
 
 	if (arg_show_autoload)
 	{
-		buffer = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "addons\n", get_xdir ());
+		buffer = g_strdup_printf ("%s%caddons%c", get_xdir(), G_DIR_SEPARATOR, G_DIR_SEPARATOR);
 #ifdef WIN32
 		gtk_init (&argc, &argv);
 		create_msg_dialog ("Plugin/Script Auto-load Directory", buffer);
 #else
-		printf (buffer);
+		puts (buffer);
 #endif
 		g_free (buffer);
 
@@ -248,12 +248,12 @@ fe_args (int argc, char *argv[])
 
 	if (arg_show_config)
 	{
-		buffer = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "\n", get_xdir ());
+		buffer = g_strdup_printf ("%s%c", get_xdir(), G_DIR_SEPARATOR);
 #ifdef WIN32
 		gtk_init (&argc, &argv);
 		create_msg_dialog ("User Config Directory", buffer);
 #else
-		printf (buffer);
+		puts (buffer);
 #endif
 		g_free (buffer);
 
@@ -908,10 +908,15 @@ 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)
-		gtkutil_file_req (message, dcc_saveas_cb, ud, dcc->file, NULL,
-								FRF_WRITE|FRF_NOASKOVERWRITE);
+	{
+		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);
+	}
 }
 
 int
diff --git a/src/fe-gtk/fe-gtk.vcxproj b/src/fe-gtk/fe-gtk.vcxproj
index 405b5207..1bdc7fef 100644
--- a/src/fe-gtk/fe-gtk.vcxproj
+++ b/src/fe-gtk/fe-gtk.vcxproj
@@ -98,7 +98,6 @@
     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

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

     <ClInclude Include="ascii.h" />

     <ClInclude Include="banlist.h" />

     <ClInclude Include="chanlist.h" />

@@ -129,7 +128,6 @@
     <ClInclude Include="xtext.h" />

   </ItemGroup>

   <ItemGroup>

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

     <ClCompile Include="ascii.c" />

     <ClCompile Include="banlist.c" />

     <ClCompile Include="chanlist.c" />

diff --git a/src/fe-gtk/fe-gtk.vcxproj.filters b/src/fe-gtk/fe-gtk.vcxproj.filters
index 0f1f8203..424f7564 100644
--- a/src/fe-gtk/fe-gtk.vcxproj.filters
+++ b/src/fe-gtk/fe-gtk.vcxproj.filters
@@ -15,9 +15,6 @@
     </Filter>

   </ItemGroup>

   <ItemGroup>

-    <ClInclude Include="about.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

     <ClInclude Include="ascii.h">

       <Filter>Header Files</Filter>

     </ClInclude>

@@ -104,9 +101,6 @@
     </ClInclude>

   </ItemGroup>

   <ItemGroup>

-    <ClCompile Include="about.c">

-      <Filter>Source Files</Filter>

-    </ClCompile>

     <ClCompile Include="ascii.c">

       <Filter>Source Files</Filter>

     </ClCompile>

diff --git a/src/fe-gtk/fkeys.c b/src/fe-gtk/fkeys.c
index 8a9a13c2..ba9599e1 100644
--- a/src/fe-gtk/fkeys.c
+++ b/src/fe-gtk/fkeys.c
@@ -148,7 +148,7 @@ static const struct key_action key_actions[KEY_MAX_ACTIONS + 1] = {
 	{key_action_insert, "Insert in Buffer",
 	 N_("The \002Insert in Buffer\002 command will insert the contents of Data 1 into the entry where the key sequence was pressed at the current cursor position")},
 	{key_action_scroll_page, "Scroll Page",
-	 N_("The \002Scroll Page\002 command scrolls the text widget up or down one page or one line. Set Data 1 to either Up, Down, +1 or -1.")},
+	 N_("The \002Scroll Page\002 command scrolls the text widget up or down one page or one line. Set Data 1 to either Top, Bottom, Up, Down, +1 or -1.")},
 	{key_action_set_buffer, "Set Buffer",
 	 N_("The \002Set Buffer\002 command sets the entry where the key sequence was entered to the contents of Data 1")},
 	{key_action_history_up, "Last Command",
@@ -395,6 +395,8 @@ key_load_defaults ()
 		"S\nNext\nChange Selected Nick\nD1!\nD2!\n\n"\
 		"S\nPrior\nChange Selected Nick\nD1:Up\nD2!\n\n"\
 		"None\nNext\nScroll Page\nD1:Down\nD2!\n\n"\
+		"C\nHome\nScroll Page\nD1:Top\nD2!\n\n"\
+		"C\nEnd\nScroll Page\nD1:Bottom\nD2!\n\n"\
 		"None\nPrior\nScroll Page\nD1:Up\nD2!\n\n"\
 		"S\nDown\nScroll Page\nD1:+1\nD2!\n\n"\
 		"S\nUp\nScroll Page\nD1:-1\nD2!\n\n"\
@@ -1279,13 +1281,19 @@ key_action_scroll_page (GtkWidget * wid, GdkEventKey * evt, char *d1,
 {
 	int value, end;
 	GtkAdjustment *adj;
-	enum scroll_type { PAGE_UP, PAGE_DOWN, LINE_UP, LINE_DOWN };
+	enum scroll_type { PAGE_TOP, PAGE_BOTTOM, PAGE_UP, PAGE_DOWN, LINE_UP, LINE_DOWN };
 	int type = PAGE_DOWN;
 
 	if (d1)
 	{
-		if (!g_ascii_strcasecmp (d1, "up"))
+		if (!g_ascii_strcasecmp (d1, "top"))
+			type = PAGE_TOP;
+		else if (!g_ascii_strcasecmp (d1, "bottom"))
+			type = PAGE_BOTTOM;
+		else if (!g_ascii_strcasecmp (d1, "up"))
 			type = PAGE_UP;
+		else if (!g_ascii_strcasecmp (d1, "down"))
+			type = PAGE_DOWN;
 		else if (!g_ascii_strcasecmp (d1, "+1"))
 			type = LINE_DOWN;
 		else if (!g_ascii_strcasecmp (d1, "-1"))
@@ -1300,21 +1308,29 @@ key_action_scroll_page (GtkWidget * wid, GdkEventKey * evt, char *d1,
 
 	switch (type)
 	{
-	case LINE_UP:
-		value = adj->value - 1.0;
+	case PAGE_TOP:
+		value = 0;
 		break;
 
-	case LINE_DOWN:
-		value = adj->value + 1.0;
+	case PAGE_BOTTOM:
+		value = end;
 		break;
 
 	case PAGE_UP:
 		value = adj->value - (adj->page_size - 1);
 		break;
 
-	default:	/* PAGE_DOWN */
+	case PAGE_DOWN:
 		value = adj->value + (adj->page_size - 1);
 		break;
+
+	case LINE_UP:
+		value = adj->value - 1.0;
+		break;
+
+	case LINE_DOWN:
+		value = adj->value + 1.0;
+		break;
 	}
 
 	if (value < 0)
diff --git a/src/fe-gtk/gtkutil.c b/src/fe-gtk/gtkutil.c
index 11206e02..985a2f78 100644
--- a/src/fe-gtk/gtkutil.c
+++ b/src/fe-gtk/gtkutil.c
@@ -51,7 +51,6 @@
 
 extern void path_part (char *file, char *path, int pathlen);
 
-
 struct file_req
 {
 	GtkWidget *dialog;
@@ -69,9 +68,6 @@ struct file_req
 #endif
 };
 
-static char last_dir[256] = "";
-
-
 static void
 gtkutil_file_req_destroy (GtkWidget * wid, struct file_req *freq)
 {
@@ -84,13 +80,14 @@ gtkutil_check_file (char *file, struct file_req *freq)
 {
 	struct stat st;
 	int axs = FALSE;
+	char temp[256];
 
-	path_part (file, last_dir, sizeof (last_dir));
+	path_part (file, temp, sizeof (temp));
 
 	/* check if the file is readable or writable */
 	if (freq->flags & FRF_WRITE)
 	{
-		if (access (last_dir, W_OK) == 0)
+		if (access (temp, W_OK) == 0)
 			axs = TRUE;
 	} else
 	{
@@ -179,60 +176,6 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
 	char *token;
 	char *tokenbuffer;
 
-#if 0	/* native file dialogs */
-#ifdef WIN32
-	if (!(flags & FRF_WRITE))
-	{
-		freq = malloc (sizeof (struct file_req));
-		freq->th = thread_new ();
-		freq->flags = 0;
-		freq->multiple = (flags & FRF_MULTIPLE);
-		freq->callback = callback;
-		freq->userdata = userdata;
-		freq->title = g_locale_from_utf8 (title, -1, 0, 0, 0);
-		if (!filter)
-		{
-			freq->filter =	"All files\0*.*\0"
-							"Executables\0*.exe\0"
-							"ZIP files\0*.zip\0\0";
-		}
-		else
-		{
-			freq->filter = filter;
-		}
-
-		thread_start (freq->th, win32_thread, freq);
-		fe_input_add (freq->th->pipe_fd[0], FIA_FD|FIA_READ, win32_read_thread, freq);
-
-		return;
-
-	}
-	
-	else {
-		freq = malloc (sizeof (struct file_req));
-		freq->th = thread_new ();
-		freq->flags = 0;
-		freq->multiple = (flags & FRF_MULTIPLE);
-		freq->callback = callback;
-		freq->userdata = userdata;
-		freq->title = g_locale_from_utf8 (title, -1, 0, 0, 0);
-		if (!filter)
-		{
-			freq->filter = "All files\0*.*\0\0";
-		}
-		else
-		{
-			freq->filter = filter;
-		}
-
-		thread_start (freq->th, win32_thread2, freq);
-		fe_input_add (freq->th->pipe_fd[0], FIA_FD|FIA_READ, win32_read_thread, freq);
-
-	return;
-	}
-#endif
-#endif
-
 	if (flags & FRF_WRITE)
 	{
 		dialog = gtk_file_chooser_dialog_new (title, NULL,
@@ -240,13 +183,6 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
 												GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 												GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
 												NULL);
-		if (filter && filter[0])	/* filter becomes initial name when saving */
-		{
-			char temp[1024];
-			path_part (filter, temp, sizeof (temp));
-			gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), temp);
-			gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), file_part (filter));
-		}
 
 		if (!(flags & FRF_NOASKOVERWRITE))
 			gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
@@ -257,41 +193,28 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
 												GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 												GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
 												NULL);
-	if (flags & FRF_MULTIPLE)
-		gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
-	if (last_dir[0])
-		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 (), NULL);
-	if (flags & FRF_CHOOSEFOLDER)
-	{
-		gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
-		gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), filter);
-	}
-	else
+
+	if (filter && filter[0] && (flags & FRF_FILTERISINITIAL))
 	{
-		if (filter && (flags & FRF_FILTERISINITIAL))
-		{
-			gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), filter);
-		}
-		/* With DCC, we can't rely on filter as initial folder since filter already contains
-		 * the filename upon DCC RECV. Thus we have no better option than to check for the message
-		 * which will be the title of the window. For DCC it always contains the "offering" word.
-		 * This method is really ugly but it works so we'll stick with it for now.
-		 */
-		else if (strstr (title, "offering") != NULL)
+		if (flags & FRF_WRITE)
 		{
-			gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), prefs.hex_dcc_dir);
+			char temp[1024];
+			path_part (filter, temp, sizeof (temp));
+			gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), temp);
+			gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), file_part (filter));
 		}
-		/* by default, open the config folder */
 		else
-		{
-			gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), get_xdir ());
-		}
+			gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), filter);
 	}
+	else if (!(flags & FRF_RECENTLYUSED))
+		gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), get_xdir ());
 
-	if (flags & FRF_EXTENSIONS && extensions != NULL)
+	if (flags & FRF_MULTIPLE)
+		gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
+	if (flags & FRF_CHOOSEFOLDER)
+		gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+
+	if ((flags & FRF_EXTENSIONS || flags & FRF_MIMETYPES) && extensions != NULL)
 	{
 		filefilter = gtk_file_filter_new ();
 		tokenbuffer = g_strdup (extensions);
@@ -299,7 +222,10 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
 
 		while (token != NULL)
 		{
-			gtk_file_filter_add_pattern (filefilter, token);
+			if (flags & FRF_EXTENSIONS)
+				gtk_file_filter_add_pattern (filefilter, token);
+			else
+				gtk_file_filter_add_mime_type (filefilter, token);
 			token = strtok (NULL, ";");
 		}
 
@@ -307,6 +233,8 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
 		gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filefilter);
 	}
 
+	gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), get_xdir (), NULL);
+
 	freq = malloc (sizeof (struct file_req));
 	freq->dialog = dialog;
 	freq->flags = flags;
@@ -678,6 +606,7 @@ gtkutil_window_new (char *title, char *role, int width, int height, int flags)
 	{
 		gtk_window_set_type_hint (GTK_WINDOW (win), GDK_WINDOW_TYPE_HINT_DIALOG);
 		gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_window));
+		gtk_window_set_destroy_with_parent (GTK_WINDOW (win), TRUE);
 	}
 
 	return win;
diff --git a/src/fe-gtk/gtkutil.h b/src/fe-gtk/gtkutil.h
index e3f59a29..2ecbe3c2 100644
--- a/src/fe-gtk/gtkutil.h
+++ b/src/fe-gtk/gtkutil.h
@@ -21,16 +21,10 @@
 #define HEXCHAT_GTKUTIL_H
 
 #include <gtk/gtk.h>
+#include "../common/fe.h"
 
 typedef void (*filereqcallback) (void *, char *file);
 
-#define FRF_WRITE 1
-#define FRF_MULTIPLE 2
-#define FRF_ADDFOLDER 4
-#define FRF_CHOOSEFOLDER 8
-#define FRF_FILTERISINITIAL 16
-#define FRF_NOASKOVERWRITE 32
-
 void gtkutil_file_req (const char *title, void *callback, void *userdata, char *filter, char *extensions, int flags);
 void gtkutil_destroy (GtkWidget * igad, GtkWidget * dgad);
 void gtkutil_destroy_on_esc (GtkWidget *win);
diff --git a/src/fe-gtk/joind.c b/src/fe-gtk/joind.c
index b58d662a..55d62e3b 100644
--- a/src/fe-gtk/joind.c
+++ b/src/fe-gtk/joind.c
@@ -34,6 +34,7 @@
 #include "../common/hexchat.h"
 #include "../common/hexchatc.h"
 #include "../common/server.h"
+#include "../common/servlist.h"
 #include "../common/fe.h"
 #include "fe-gtk.h"
 #include "chanlist.h"
@@ -241,6 +242,13 @@ joind_show_dialog (server *serv)
 							G_CALLBACK (joind_radio2_cb), serv);
 	g_signal_connect (G_OBJECT (okbutton1), "clicked",
 							G_CALLBACK (joind_ok_cb), serv);
+							
+	if (serv->network)
+		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);
 	gtk_widget_show_all (dialog1);
diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c
index 91bc9d6f..fd0ee6f1 100644
--- a/src/fe-gtk/maingui.c
+++ b/src/fe-gtk/maingui.c
@@ -2106,8 +2106,8 @@ mg_create_chanmodebuttons (session_gui *gui, GtkWidget *box)
 	gui->flag_k = mg_create_flagbutton (_("Keyword"), box, "K");
 	gui->key_entry = gtk_entry_new ();
 	gtk_widget_set_name (gui->key_entry, "hexchat-inputbox");
-	gtk_entry_set_max_length (GTK_ENTRY (gui->key_entry), 16);
-	gtk_widget_set_size_request (gui->key_entry, 30, -1);
+	gtk_entry_set_max_length (GTK_ENTRY (gui->key_entry), 23);
+	gtk_widget_set_size_request (gui->key_entry, 115, -1);
 	gtk_box_pack_start (GTK_BOX (box), gui->key_entry, 0, 0, 0);
 	g_signal_connect (G_OBJECT (gui->key_entry), "activate",
 							G_CALLBACK (mg_key_entry_cb), NULL);
@@ -2310,6 +2310,8 @@ mg_word_clicked (GtkWidget *xtext, char *word, GdkEventButton *even)
 		menu_nickmenu (sess, even, word, FALSE);
 		break;
 	case WORD_CHANNEL:
+		word[end] = 0;
+		word += start;
 		menu_chanmenu (sess, even, word);
 		break;
 	case WORD_EMAIL:
diff --git a/src/fe-gtk/menu.c b/src/fe-gtk/menu.c
index dd3223a1..8d87f84e 100644
--- a/src/fe-gtk/menu.c
+++ b/src/fe-gtk/menu.c
@@ -43,7 +43,6 @@
 #include "../common/notify.h"
 #include "../common/util.h"
 #include "xtext.h"
-#include "about.h"
 #include "ascii.h"
 #include "banlist.h"
 #include "chanlist.h"
@@ -1621,6 +1620,62 @@ menu_metres_both (GtkWidget *item, gpointer none)
 	}
 }
 
+static void
+about_dialog_close (GtkDialog *dialog, int response, gpointer data)
+{
+	gtk_widget_destroy (GTK_WIDGET(dialog));
+}
+
+static gboolean
+about_dialog_openurl (GtkAboutDialog *dialog, char *uri, gpointer data)
+{
+	fe_open_url (uri);
+	return TRUE;
+}
+
+static void
+menu_about (GtkWidget *wid, gpointer sess)
+{
+	GtkAboutDialog *dialog = GTK_ABOUT_DIALOG(gtk_about_dialog_new());
+	char comment[512];
+	char *license = "This program is free software; you can redistribute it and/or modify\n" \
+					"it under the terms of the GNU General Public License as published by\n" \
+					"the Free Software Foundation; version 2.\n\n" \
+					"This program is distributed in the hope that it will be useful,\n" \
+					"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" \
+					"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" \
+					"GNU General Public License for more details.\n\n" \
+					"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"
+#ifdef WIN32
+				"Portable Mode: %s\n"
+				"Build Type: x%d\n"
+#endif
+				"OS: %s",
+#ifdef WIN32
+				(portable_mode () ? "Yes" : "No"),
+				get_cpu_arch (),
+#endif
+				get_sys_str (0));
+
+	gtk_about_dialog_set_name (dialog, DISPLAY_NAME);
+	gtk_about_dialog_set_version (dialog, PACKAGE_VERSION);
+	gtk_about_dialog_set_license (dialog, license); /* gtk3 can use GTK_LICENSE_GPL_2_0 */
+	gtk_about_dialog_set_website (dialog, "http://hexchat.github.io");
+	gtk_about_dialog_set_website_label (dialog, "Website");
+	gtk_about_dialog_set_logo (dialog, pix_hexchat);
+	gtk_about_dialog_set_copyright (dialog, "\302\251 1998-2010 Peter \305\275elezn\303\275\n\302\251 2009-2013 Berke Viktor");
+	gtk_about_dialog_set_comments (dialog, comment);
+
+	gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(parent_window));
+	g_signal_connect (G_OBJECT(dialog), "response", G_CALLBACK(about_dialog_close), NULL);
+	g_signal_connect (G_OBJECT(dialog), "activate-link", G_CALLBACK(about_dialog_openurl), NULL);
+	
+	gtk_widget_show_all (GTK_WIDGET(dialog));
+}
+
 static struct mymenu mymenu[] = {
 	{N_("He_xChat"), 0, 0, M_NEWMENU, 0, 0, 1},
 	{N_("Network Li_st..."), menu_open_server_list, (char *)&pix_book, M_MENUPIX, 0, 0, 1, GDK_s},
diff --git a/src/fe-gtk/notifygui.c b/src/fe-gtk/notifygui.c
index 872fb7ed..c0282ade 100644
--- a/src/fe-gtk/notifygui.c
+++ b/src/fe-gtk/notifygui.c
@@ -60,6 +60,7 @@ static void
 notify_closegui (void)
 {
 	notify_window = 0;
+	notify_save ();
 }
 
 /* Need this to be able to set the foreground colour property of a row
diff --git a/src/fe-gtk/plugingui.c b/src/fe-gtk/plugingui.c
index c7193837..c6d90e2f 100644
--- a/src/fe-gtk/plugingui.c
+++ b/src/fe-gtk/plugingui.c
@@ -72,6 +72,31 @@ plugingui_treeview_new (GtkWidget *box)
 	return view;
 }
 
+static char *
+plugingui_getfilename (GtkTreeView *view)
+{
+	GtkTreeModel *model;
+	GtkTreeSelection *sel;
+	GtkTreeIter iter;
+	GValue file;
+	char *str;
+
+	memset (&file, 0, sizeof (file));
+
+	sel = gtk_tree_view_get_selection (view);
+	if (gtk_tree_selection_get_selected (sel, &model, &iter))
+	{
+		gtk_tree_model_get_value (model, &iter, FILE_COLUMN, &file);
+
+		str = g_value_dup_string (&file);
+		g_value_unset (&file);
+
+		return str;
+	}
+
+	return NULL;
+}
+
 static void
 plugingui_close (GtkWidget * wid, gpointer a)
 {
@@ -137,9 +162,9 @@ plugingui_load (void)
 
 	gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess,
 #ifdef WIN32
-							sub_dir, "*.dll;*.lua;*.pl;*.py;*.tcl;*.js", FRF_ADDFOLDER|FRF_FILTERISINITIAL|FRF_EXTENSIONS);
+							sub_dir, "*.dll;*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS);
 #else
-							sub_dir, "*.so;*.lua;*.pl;*.py;*.tcl;*.js", FRF_ADDFOLDER|FRF_FILTERISINITIAL|FRF_EXTENSIONS);
+							sub_dir, "*.so;*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS);
 #endif
 
 	g_free (sub_dir);
@@ -193,6 +218,25 @@ plugingui_unload (GtkWidget * wid, gpointer unused)
 	g_free (file);
 }
 
+static void
+plugingui_reloadbutton_cb (GtkWidget *wid, GtkTreeView *view)
+{
+	char *file = plugingui_getfilename(view);
+
+	if (file)
+	{
+		char *buf = malloc (strlen (file) + 9);
+
+		if (strchr (file, ' '))
+			sprintf (buf, "RELOAD \"%s\"", file);
+		else
+			sprintf (buf, "RELOAD %s", file);
+		handle_command (current_sess, buf, FALSE);
+		free (buf);
+		g_free (file);
+	}
+}
+
 void
 plugingui_open (void)
 {
@@ -223,7 +267,10 @@ plugingui_open (void)
 	                plugingui_loadbutton_cb, NULL, _("_Load..."));
 
 	gtkutil_button (hbox, GTK_STOCK_DELETE, NULL,
-	                plugingui_unload, NULL, _("_UnLoad"));
+	                plugingui_unload, NULL, _("_Unload"));
+
+	gtkutil_button (hbox, GTK_STOCK_REFRESH, NULL,
+	                plugingui_reloadbutton_cb, view, _("_Reload"));
 
 	fe_pluginlist_update ();
 
diff --git a/src/fe-gtk/servlistgui.c b/src/fe-gtk/servlistgui.c
index 94cb209f..ef5b57cd 100644
--- a/src/fe-gtk/servlistgui.c
+++ b/src/fe-gtk/servlistgui.c
@@ -120,10 +120,15 @@ static int login_types_conf[] =
 {
 	LOGIN_DEFAULT,			/* default entry - we don't use this but it makes indexing consistent with login_types[] so it's nice */
 	LOGIN_SASL,
+#ifdef USE_OPENSSL
+	LOGIN_SASLEXTERNAL,
+#endif
 	LOGIN_PASS,
 	LOGIN_MSG_NICKSERV,
 	LOGIN_NICKSERV,
+#ifdef USE_OPENSSL
 	LOGIN_CHALLENGEAUTH,
+#endif
 	LOGIN_CUSTOM
 #if 0
 	LOGIN_NS,
@@ -136,10 +141,15 @@ static const char *login_types[]=
 {
 	"Default",
 	"SASL (username + password)",
+#ifdef USE_OPENSSL
+	"SASL EXTERNAL (cert)",
+#endif
 	"Server Password (/PASS password)",
 	"NickServ (/MSG NickServ + password)",
 	"NickServ (/NICKSERV + password)",
+#ifdef USE_OPENSSL
 	"Challenge Auth (username + password)",
+#endif
 	"Custom... (connect commands)",
 #if 0
 	"NickServ (/NS + password)",
@@ -1513,6 +1523,12 @@ servlist_logintypecombo_cb (GtkComboBox *cb, gpointer *userdata)
 	{
 		gtk_notebook_set_current_page (GTK_NOTEBOOK (userdata), 2);		/* FIXME avoid hardcoding? */
 	}
+	
+	/* EXTERNAL uses a cert, not a pass */
+	if (login_types_conf[index] == LOGIN_SASLEXTERNAL)
+		gtk_widget_set_sensitive (edit_entry_pass, FALSE);
+	else
+		gtk_widget_set_sensitive (edit_entry_pass, TRUE);
 }
 
 
@@ -1816,6 +1832,8 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
 
 	edit_entry_pass = servlist_create_entry (table3, _("Password:"), 11, net->pass, 0, _("Password used for login. If in doubt, leave blank."));
 	gtk_entry_set_visibility (GTK_ENTRY (edit_entry_pass), FALSE);
+	if (selected_net && selected_net->logintype == LOGIN_SASLEXTERNAL)
+		gtk_widget_set_sensitive (edit_entry_pass, FALSE);
 
 	label34 = gtk_label_new (_("Character set:"));
 	gtk_table_attach (GTK_TABLE (table3), label34, 0, 1, 12, 13, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), SERVLIST_X_PADDING, SERVLIST_Y_PADDING);
diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c
index 2d46b95f..8b3a43e5 100644
--- a/src/fe-gtk/setup.c
+++ b/src/fe-gtk/setup.c
@@ -426,7 +426,11 @@ static const setting alert_settings[] =
 #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},
@@ -1059,7 +1063,19 @@ setup_filereq_cb (GtkWidget *entry, char *file)
 static void
 setup_browsefile_cb (GtkWidget *button, GtkWidget *entry)
 {
-	gtkutil_file_req (_("Select an Image File"), setup_filereq_cb, entry, NULL, NULL, 0);
+	/* used for background image only */
+	char *filter;
+	int filter_type;
+
+#ifdef WIN32
+	filter = "*png;*.tiff;*.gif;*.jpeg;*.jpg";
+	filter_type = FRF_EXTENSIONS;
+#else
+	filter = "image/*";
+	filter_type = FRF_MIMETYPES;
+#endif
+	gtkutil_file_req (_("Select an Image File"), setup_filereq_cb,
+					entry, NULL, filter, filter_type|FRF_RECENTLYUSED);
 }
 
 static void
@@ -1659,7 +1675,18 @@ static void
 setup_snd_browse_cb (GtkWidget *button, GtkEntry *entry)
 {
 	char *sounds_dir = g_build_filename (get_xdir (), HEXCHAT_SOUND_DIR, NULL);
-	gtkutil_file_req (_("Select a sound file"), setup_snd_filereq_cb, entry, sounds_dir, NULL, FRF_FILTERISINITIAL);
+	char *filter = NULL;
+	int filter_type;
+#ifdef WIN32 /* win32 only supports wav, others could support anything */
+	filter = "*.wav";
+	filter_type = FRF_EXTENSIONS;
+#else
+	filter = "audio/*";
+	filter_type = FRF_MIMETYPES;
+#endif
+
+	gtkutil_file_req (_("Select a sound file"), setup_snd_filereq_cb, entry,
+						sounds_dir, filter, FRF_FILTERISINITIAL|filter_type);
 	g_free (sounds_dir);
 }
 
diff --git a/src/fe-gtk/urlgrab.c b/src/fe-gtk/urlgrab.c
index cefa51c8..79a6d5f5 100644
--- a/src/fe-gtk/urlgrab.c
+++ b/src/fe-gtk/urlgrab.c
@@ -146,7 +146,7 @@ static void
 url_button_save (void)
 {
 	gtkutil_file_req (_("Select an output filename"),
-							url_save_callback, NULL, get_xdir (), NULL, FRF_WRITE|FRF_FILTERISINITIAL);
+							url_save_callback, NULL, NULL, NULL, FRF_WRITE);
 }
 
 void
diff --git a/src/fe-gtk/xtext.c b/src/fe-gtk/xtext.c
index 7582f82c..3d2ae7ae 100644
--- a/src/fe-gtk/xtext.c
+++ b/src/fe-gtk/xtext.c
@@ -1901,10 +1901,10 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
 {
 	textentry *ent;
 	int offset;
-	unsigned char *str;
 	unsigned char *word;
 	int len;
 	int out_of_bounds = 0;
+	int len_to_offset = 0;
 
 	ent = gtk_xtext_find_char (xtext, x, y, &offset, &out_of_bounds);
 	if (!ent)
@@ -1921,25 +1921,25 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
 
 	/*offset--;*/	/* FIXME: not all chars are 1 byte */
 
-	str = ent->str + offset;
+	word = ent->str + offset;
 
-	while (!is_del (*str) && str != ent->str)
-		str--;
-	word = str + 1;
+	while (!is_del (*word) && word != ent->str)
+	{
+		word--;
+		len_to_offset++;
+	}
+	word++;
+	len_to_offset--;
+
+	/* remove color characters from the length */
+	gtk_xtext_strip_color (word, len_to_offset, xtext->scratch_buffer, &len_to_offset, NULL, slp, FALSE);
 
 	len = 0;
-	str = word;
-	while (!is_del (*str) && len != ent->str_len)
-	{
-		str++;
+	while (!is_del (word[len]) && len != ent->str_len)
 		len++;
-	}
 
 	if (len > 0 && word[len-1]=='.')
-	{
 		len--;
-		str--;
-	}
 
 	if (ret_ent)
 		*ret_ent = ent;
@@ -1948,7 +1948,24 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
 	if (ret_len)
 		*ret_len = len;		/* Length before stripping */
 
-	return gtk_xtext_strip_color (word, len, xtext->scratch_buffer, NULL, NULL, slp, FALSE);
+	word = gtk_xtext_strip_color (word, len, xtext->scratch_buffer, NULL, NULL, slp, FALSE);
+
+	/* avoid turning the cursor into a hand for non-url part of the word */
+	if (xtext->urlcheck_function (GTK_WIDGET (xtext), word))
+	{
+		int start, end;
+		url_last (&start, &end);
+
+		/* make sure we're not before the start of the match */
+		if (len_to_offset < start)
+			return 0;
+
+		/* and not after it */
+		if (len_to_offset - start >= end - start)
+			return 0;
+	}
+
+	return word;
 }
 
 #ifdef MOTION_MONITOR
@@ -2139,6 +2156,7 @@ gtk_xtext_motion_notify (GtkWidget * widget, GdkEventMotion * event)
 			{
 				gdk_window_set_cursor (GTK_WIDGET (xtext)->window,
 										  		xtext->resize_cursor);
+				xtext->cursor_hand = FALSE;
 				xtext->cursor_resize = TRUE;
 			}
 			return FALSE;
@@ -2161,6 +2179,7 @@ gtk_xtext_motion_notify (GtkWidget * widget, GdkEventMotion * event)
 				gdk_window_set_cursor (GTK_WIDGET (xtext)->window,
 										  		xtext->hand_cursor);
 				xtext->cursor_hand = TRUE;
+				xtext->cursor_resize = FALSE;
 			}
 
 			/* un-render the old hilight */