changeset 11003:2b772e7094ef

[gaim-migrate @ 12858] Kevin Stange made this patch to remove the win32 flashing from the gaim core and put it the winprefs plugin. He also cleaned up the winprefs plugin quite a bit. Blame him if it doesn't work ;) committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Sat, 11 Jun 2005 23:29:56 +0000
parents bf03a5271395
children a3d3729a9130
files plugins/ChangeLog.API plugins/perl/common/ConvWindow.xs plugins/win32/winprefs/winprefs.c src/conversation.c src/conversation.h src/gtkconv.c src/server.c src/win32/win32dep.c src/win32/win32dep.h
diffstat 9 files changed, 336 insertions(+), 376 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/ChangeLog.API	Sat Jun 11 22:30:08 2005 +0000
+++ b/plugins/ChangeLog.API	Sat Jun 11 23:29:56 2005 +0000
@@ -54,6 +54,9 @@
 	           or not the file is binary
 	* Added:   gaim_buddy_icon_get_type, can be used to attempt to
 	           determine the file type of a given buddy icon.
+	* Removed: Window flashing support in the core: gaim_conv_window_flash,
+	           and flash UI operation for conversations.  Use signal
+	           "received-im-msg" or similar.
 
 	Signals:
 	* Changed: "received-im-msg" and "received-chat-msg" to match, both
--- a/plugins/perl/common/ConvWindow.xs	Sat Jun 11 22:30:08 2005 +0000
+++ b/plugins/perl/common/ConvWindow.xs	Sat Jun 11 23:29:56 2005 +0000
@@ -25,10 +25,6 @@
 gaim_conv_window_raise(win)
 	Gaim::ConvWindow win
 
-void
-gaim_conv_window_flash(win)
-	Gaim::ConvWindow win
-
 int
 gaim_conv_window_add_conversation(win, conv)
 	Gaim::ConvWindow win
--- a/plugins/win32/winprefs/winprefs.c	Sat Jun 11 22:30:08 2005 +0000
+++ b/plugins/win32/winprefs/winprefs.c	Sat Jun 11 23:29:56 2005 +0000
@@ -1,40 +1,42 @@
 /*
  * gaim - WinGaim Options Plugin
  *
- * File: winprefs.c
- * Date: December 12, 2002
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
  *
- * copyright (c) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
- *
- * 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
+ * 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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * you should have received a copy of the gnu general public license
- * along with this program; if not, write to the free software
- * foundation, inc., 59 temple place, suite 330, boston, ma  02111-1307  usa
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
+
 #include <gdk/gdkwin32.h>
 
 #include "internal.h"
 
 #include "core.h"
+#include "debug.h"
 #include "prefs.h"
-#include "debug.h"
 #include "signals.h"
 #include "version.h"
 
+#include "gtkappbar.h"
+#include "gtkblist.h"
+#include "gtkconv.h"
 #include "gtkplugin.h"
+#include "gtkprefs.h"
 #include "gtkutils.h"
-#include "gtkblist.h"
-#include "gtkappbar.h"
 
 /*
  *  MACROS & DEFINES
@@ -44,88 +46,97 @@
 /*
  *  LOCALS
  */
-static const char *OPT_WINPREFS_DBLIST_DOCKABLE =      "/plugins/gtk/win32/winprefs/dblist_dockable";
-static const char *OPT_WINPREFS_DBLIST_DOCKED =        "/plugins/gtk/win32/winprefs/dblist_docked";
-static const char *OPT_WINPREFS_DBLIST_HEIGHT =        "/plugins/gtk/win32/winprefs/dblist_height";
-static const char *OPT_WINPREFS_DBLIST_SIDE =          "/plugins/gtk/win32/winprefs/dblist_side";
-static const char *OPT_WINPREFS_DBLIST_ON_TOP =        "/plugins/gtk/win32/winprefs/dblist_on_top";
-static const char *OPT_WINPREFS_BLIST_ON_TOP =         "/plugins/gtk/win32/winprefs/blist_on_top";
-static const char *OPT_WINPREFS_IM_BLINK =             "/plugins/gtk/win32/winprefs/im_blink";
+static const char *PREF_DBLIST_DOCKABLE = "/plugins/gtk/win32/winprefs/dblist_dockable";
+static const char *PREF_DBLIST_DOCKED =   "/plugins/gtk/win32/winprefs/dblist_docked";
+static const char *PREF_DBLIST_HEIGHT =   "/plugins/gtk/win32/winprefs/dblist_height";
+static const char *PREF_DBLIST_SIDE =     "/plugins/gtk/win32/winprefs/dblist_side";
+static const char *PREF_BLIST_ON_TOP =    "/plugins/gtk/win32/winprefs/blist_on_top";
+static const char *PREF_IM_BLINK =        "/plugins/gtk/win32/winprefs/im_blink";
+/* Deprecated */
+static const char *PREF_DBLIST_ON_TOP =   "/plugins/gtk/win32/winprefs/dblist_on_top";
 
-static GaimPlugin *plugin_id = NULL;
+static GaimPlugin *handle = NULL;
 static GtkAppBar *blist_ab = NULL;
 static GtkWidget *blist = NULL;
 
-/*
- *  PROTOS
- */
-static void blist_create_cb(GaimBuddyList *blist, void *data);
+/* flash info */
+
+struct _WGAIM_FLASH_INFO {
+	guint t_handle;
+	guint sig_handler;
+};
+
+enum {
+	BLIST_TOP_NEVER = 0,
+	BLIST_TOP_ALWAYS,
+	BLIST_TOP_DOCKED,
+};
+
+typedef struct _WGAIM_FLASH_INFO WGAIM_FLASH_INFO;
+
+typedef BOOL (CALLBACK* LPFNFLASHWINDOWEX)(PFLASHWINFO);
+
+static LPFNFLASHWINDOWEX MyFlashWindowEx = NULL;
 
 /*
  *  CODE
  */
 
-/* UTIL */
-
-static GtkWidget *wgaim_button(const char *text, GtkWidget *page) {
-        GtkWidget *button;
-	button = gtk_check_button_new_with_mnemonic(text);
-        gtk_box_pack_start(GTK_BOX(page), button, FALSE, FALSE, 0);
-	gtk_widget_show(button);
-        return button;
-}
-
 /* BLIST DOCKING */
 
 static void blist_save_state() {
-        if(blist_ab) {
-                if(gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_DOCKABLE) && blist_ab->docked) {
-                        gaim_prefs_set_int(OPT_WINPREFS_DBLIST_HEIGHT, blist_ab->undocked_height);
-                        gaim_prefs_set_int(OPT_WINPREFS_DBLIST_SIDE, blist_ab->side);
-                        gaim_prefs_set_bool(OPT_WINPREFS_DBLIST_DOCKED, blist_ab->docked);
-                }
-                else
-                        gaim_prefs_set_bool(OPT_WINPREFS_DBLIST_DOCKED, FALSE);
-        }
+	if(blist_ab) {
+		if(gaim_prefs_get_bool(PREF_DBLIST_DOCKABLE) && blist_ab->docked) {
+			gaim_prefs_set_int(PREF_DBLIST_HEIGHT, blist_ab->undocked_height);
+			gaim_prefs_set_int(PREF_DBLIST_SIDE, blist_ab->side);
+			gaim_prefs_set_bool(PREF_DBLIST_DOCKED, blist_ab->docked);
+		} else
+			gaim_prefs_set_bool(PREF_DBLIST_DOCKED, FALSE);
+	}
 }
 
 static void blist_set_ontop(gboolean val) {
-        if(!blist)
-                return;
-        if(val)
-                SetWindowPos(GDK_WINDOW_HWND(blist->window), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
-        else
-                SetWindowPos(GDK_WINDOW_HWND(blist->window), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+	if (!blist)
+		return;
+
+	if (val == TRUE)
+		SetWindowPos(GDK_WINDOW_HWND(blist->window), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+	else
+		SetWindowPos(GDK_WINDOW_HWND(blist->window), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
 }
 
 static void blist_dock_cb(gboolean val) {
-        if(val) {
-                gaim_debug_info(WINPREFS_PLUGIN_ID, "Blist Docking..\n");
-                if(gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_ON_TOP))
-                        blist_set_ontop(TRUE);
-        }
-        else {
-                gaim_debug_info(WINPREFS_PLUGIN_ID, "Blist Undocking..\n");
-                if(gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_ON_TOP) &&
-                   !gaim_prefs_get_bool(OPT_WINPREFS_BLIST_ON_TOP))
-                        blist_set_ontop(FALSE);
-        }
+	if (val == TRUE) {
+		gaim_debug_info(WINPREFS_PLUGIN_ID, "Blist Docking..\n");
+		if (gaim_prefs_get_int(PREF_BLIST_ON_TOP) != BLIST_TOP_NEVER)
+			blist_set_ontop(TRUE);
+	} else {
+		gaim_debug_info(WINPREFS_PLUGIN_ID, "Blist Undocking..\n");
+		if (gaim_prefs_get_int(PREF_BLIST_ON_TOP) == BLIST_TOP_ALWAYS)
+			blist_set_ontop(TRUE);
+		else
+			blist_set_ontop(FALSE);
+	}
 }
 
 static void blist_set_dockable(gboolean val) {
-        if(val) {
-                if(!blist_ab && blist) {
-                        blist_ab = gtk_appbar_add(blist);
-                        gtk_appbar_add_dock_cb(blist_ab, blist_dock_cb);
-                }
-        }
-        else {
-                if(gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_ON_TOP) &&
-                   !gaim_prefs_get_bool(OPT_WINPREFS_BLIST_ON_TOP))
-                        blist_set_ontop(FALSE);
-                gtk_appbar_remove(blist_ab);
-                blist_ab = NULL;
-        }
+	if (val == TRUE) {
+		if (blist_ab == NULL && blist != NULL) {
+			blist_ab = gtk_appbar_add(blist);
+			gtk_appbar_add_dock_cb(blist_ab, blist_dock_cb);
+		}
+	} else {
+		if (blist_ab != NULL) {
+			gtk_appbar_remove(blist_ab);
+			blist_ab = NULL;
+		}
+
+		if (gaim_prefs_get_int(PREF_BLIST_ON_TOP) == BLIST_TOP_ALWAYS)
+			blist_set_ontop(TRUE);
+		else
+			blist_set_ontop(FALSE);
+	}
 }
 
 /* PLUGIN CALLBACKS */
@@ -133,9 +144,9 @@
 /* We need this because the blist destroy cb won't be called before the
    plugin is unloaded, when quitting */
 static void gaim_quit_cb() {
-        gaim_debug_info(WINPREFS_PLUGIN_ID, "gaim_quit_cb: removing appbar\n");
-        blist_save_state();
-        blist_set_dockable(FALSE);
+	gaim_debug_info(WINPREFS_PLUGIN_ID, "gaim_quit_cb: removing appbar\n");
+	blist_save_state();
+	blist_set_dockable(FALSE);
 }
 
 static void blist_create_cb(GaimBuddyList *gaim_blist, void *data) {
@@ -143,31 +154,32 @@
 
 	blist = GAIM_GTK_BLIST(gaim_blist)->window;
 
-        if(gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_DOCKABLE)) {
-                blist_set_dockable(TRUE);
-                if(gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_DOCKED)) {
-                        blist_ab->undocked_height = gaim_prefs_get_int(OPT_WINPREFS_DBLIST_HEIGHT);
-                        gtk_appbar_dock(blist_ab,
-                                        gaim_prefs_get_int(OPT_WINPREFS_DBLIST_SIDE));
-                        if(gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_ON_TOP))
-                                blist_set_ontop(TRUE);
-                }
-        }
-        if(gaim_prefs_get_bool(OPT_WINPREFS_BLIST_ON_TOP)) {
-                blist_set_ontop(TRUE);
-        }
+	if (gaim_prefs_get_bool(PREF_DBLIST_DOCKABLE)) {
+		blist_set_dockable(TRUE);
+		if (gaim_prefs_get_bool(PREF_DBLIST_DOCKED)) {
+			blist_ab->undocked_height = gaim_prefs_get_int(PREF_DBLIST_HEIGHT);
+			gtk_appbar_dock(blist_ab,
+							gaim_prefs_get_int(PREF_DBLIST_SIDE));
+			if (gaim_prefs_get_int(PREF_BLIST_ON_TOP) == BLIST_TOP_DOCKED)
+				blist_set_ontop(TRUE);
+		}
+	}
+
+	if (gaim_prefs_get_int(PREF_BLIST_ON_TOP) == BLIST_TOP_ALWAYS)
+		blist_set_ontop(TRUE);
+
 }
 
 /* AUTOSTART */
 
 static int open_run_key(PHKEY phKey, REGSAM samDesired) {
-        /* First try current user key (for WinNT & Win2k +), fall back to local machine */
-        if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, 
-					 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 
-					 0,  samDesired,  phKey));
-	else if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
-					      "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 
-					      0,  samDesired,  phKey));
+	/* First try current user key (for WinNT & Win2k +), fall back to local machine */
+	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
+					"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
+					0,  samDesired,  phKey));
+	else if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+					"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
+					0,  samDesired,  phKey));
 	else {
 		gaim_debug_error(WINPREFS_PLUGIN_ID, "open_run_key: Could not open key for writing value\n");
 		return 0;
@@ -177,188 +189,251 @@
 
 /* WIN PREFS GENERAL */
 
-static void winprefs_set_autostart(GtkWidget *w) {
-        HKEY hKey;
+static void
+winprefs_set_autostart(GtkWidget *w)
+{
+	HKEY hKey;
+
+	if (!open_run_key(&hKey, KEY_SET_VALUE))
+		return;
+	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) {
+		char buffer[1024];
+		DWORD size;
+
+		if ((size = GetModuleFileName(wgaim_hinstance(),
+									  (LPBYTE)buffer, sizeof(buffer)))==0) {
+			gaim_debug_error(WINPREFS_PLUGIN_ID, "GetModuleFileName Error.. Could not set Gaim autostart.\n");
+			RegCloseKey(hKey);
+			return;
+		}
+
+		/* Now set value of new key */
+		if (ERROR_SUCCESS != RegSetValueEx(hKey, "Gaim", 0, REG_SZ, buffer, size))
+			gaim_debug_error(WINPREFS_PLUGIN_ID, "Could not set registry key value\n");
+	} else {
+		if (ERROR_SUCCESS != RegDeleteValue(hKey, "Gaim"))
+			gaim_debug_error(WINPREFS_PLUGIN_ID, "Could not delete registry key value\n");
+	}
+	RegCloseKey(hKey);
+}
 
-        if(!open_run_key(&hKey, KEY_SET_VALUE))
-                return;
-        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) {
-                char buffer[1024];
-                DWORD size;
-                
-                if((size = GetModuleFileName(wgaim_hinstance(),
-                                             (LPBYTE)buffer,
-                                             sizeof(buffer)))==0) {
-                        gaim_debug_error(WINPREFS_PLUGIN_ID, "GetModuleFileName Error.. Could not set Gaim autostart.\n");
-                        RegCloseKey(hKey);
-                        return;
-                }
-                /* Now set value of new key */
-                if(ERROR_SUCCESS != RegSetValueEx(hKey,
-                                                  "Gaim",
-                                                  0,
-                                                  REG_SZ,
-                                                  buffer,
-                                                  size))
-                        gaim_debug_error(WINPREFS_PLUGIN_ID, "Could not set registry key value\n");
-        }
-        else {
-                if(ERROR_SUCCESS != RegDeleteValue(hKey, "Gaim"))
-                        gaim_debug_error(WINPREFS_PLUGIN_ID, "Could not delete registry key value\n");
-        }
-        RegCloseKey(hKey);
+static void
+winprefs_set_blist_dockable (const char *pref, GaimPrefType type,
+		gpointer value, gpointer user_data)
+{
+	blist_set_dockable(GPOINTER_TO_INT(value));
+}
+
+static void
+winprefs_set_blist_ontop (const char *pref, GaimPrefType type,
+		gpointer value, gpointer user_data)
+{
+	gint setting = gaim_prefs_get_int(PREF_BLIST_ON_TOP);
+	if ((setting == BLIST_TOP_DOCKED && blist_ab && blist_ab->docked)
+		|| setting == BLIST_TOP_ALWAYS)
+		blist_set_ontop(TRUE);
+	else
+		blist_set_ontop(FALSE);
+}
+
+static void load_winver_specific_procs (void) {
+	/* Used for Win98+ and WinNT5+ */
+	MyFlashWindowEx = (LPFNFLASHWINDOWEX)wgaim_find_and_loadproc("user32.dll", "FlashWindowEx" );
+}
+
+/* Window flasher */
+static gboolean flash_window_cb (gpointer data) {
+	FlashWindow((HWND)data, TRUE);
+	return TRUE;
 }
 
-static void winprefs_set_blist_dockable(GtkWidget *w, GtkWidget *w1) {
-        gaim_prefs_set_bool(OPT_WINPREFS_DBLIST_DOCKABLE, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)));
-        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) {
-                blist_set_dockable(TRUE);
-                gtk_widget_set_sensitive(w1, TRUE);
-        }
-        else {
-                blist_set_dockable(FALSE);
-                gtk_widget_set_sensitive(w1, FALSE);
-        }
+static int
+halt_flash_filter (GtkWidget *widget, GdkEventFocus *event, gpointer data)
+{
+ 	if (MyFlashWindowEx) {
+		HWND hWnd = data;
+		FLASHWINFO info;
+
+		if (!IsWindow(hWnd))
+			return 0;
+
+		memset(&info, 0, sizeof(FLASHWINFO));
+		info.cbSize = sizeof(FLASHWINFO);
+		info.hwnd = hWnd;
+		info.dwFlags = FLASHW_STOP;
+		info.dwTimeout = 0;
+		MyFlashWindowEx(&info);
+
+	} else {
+		WGAIM_FLASH_INFO *finfo = data;
+		/* Stop flashing and remove filter */
+		gaim_debug(GAIM_DEBUG_INFO, "wgaim", "Removing timeout\n");
+		gaim_timeout_remove(finfo->t_handle);
+		gaim_debug(GAIM_DEBUG_INFO, "wgaim", "Disconnecting signal handler\n");
+		g_signal_handler_disconnect(G_OBJECT(widget),finfo->sig_handler);
+		gaim_debug(GAIM_DEBUG_INFO, "wgaim", "done\n");
+		g_free(finfo);
+	}
+	return 0;
 }
 
-static void winprefs_set_blist_ontop(GtkWidget *w) {
-        gaim_prefs_set_bool(OPT_WINPREFS_BLIST_ON_TOP, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)));
+/* FlashWindowEx is only supported by Win98+ and WinNT5+. If it's
+   not supported we do it our own way */
+static void
+wgaim_conv_im_blink (GaimAccount *account, char *sender, char *message, int flags)
+{
+	if (gaim_prefs_get_bool(PREF_IM_BLINK) == FALSE)
+		return;
+
+	GaimConversation *conv = gaim_find_conversation_with_account(GAIM_CONV_IM, sender, account);
+	if (conv == NULL) {
+	  gaim_debug_info("winprefs", "gar!\n");
+	  return;
+	}
+	GaimConvWindow *win = gaim_conversation_get_window(conv);
+	if (win == NULL) {
+	  gaim_debug_info("winprefs", "gar2!\n");
+	  return;
+	}
+	GtkWidget *window = GAIM_GTK_WINDOW(win)->window;
 
-        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) {
-                blist_set_ontop(TRUE);
-        }
-        else {
-                if(!(gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_DOCKABLE) &&
-                     gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_ON_TOP) &&
-                     (blist_ab && blist_ab->docked)))
-                        blist_set_ontop(FALSE);
-        }
+	if (MyFlashWindowEx) {
+		FLASHWINFO info;
+		if (GetForegroundWindow() == GDK_WINDOW_HWND(window->window))
+			return;
+
+		memset(&info, 0, sizeof(FLASHWINFO));
+		info.cbSize = sizeof(FLASHWINFO);
+		info.hwnd = GDK_WINDOW_HWND(window->window);
+		info.dwFlags = FLASHW_ALL | FLASHW_TIMER;
+		info.dwTimeout = 0;
+		MyFlashWindowEx(&info);
+		/* Stop flashing when window receives focus */
+		g_signal_connect(G_OBJECT(window), "focus-in-event",
+						 G_CALLBACK(halt_flash_filter), info.hwnd);
+	} else {
+		WGAIM_FLASH_INFO *finfo = g_new0(WGAIM_FLASH_INFO, 1);
+
+		/* Start Flashing window */
+		finfo->t_handle = gaim_timeout_add(1000, flash_window_cb,
+										   GDK_WINDOW_HWND(window->window));
+		finfo->sig_handler = g_signal_connect(G_OBJECT(window),
+									"focus-in-event",
+									G_CALLBACK(halt_flash_filter), finfo);
+	}
 }
 
-static void winprefs_set_dblist_ontop(GtkWidget *w) {
-        gaim_prefs_set_bool(OPT_WINPREFS_DBLIST_ON_TOP, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)));
-        if(blist && blist_ab) {
-                if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) {
-                        if(blist_ab->docked)
-                                blist_set_ontop(TRUE);
-                }
-                else if(!gaim_prefs_get_bool(OPT_WINPREFS_BLIST_ON_TOP))
-                        blist_set_ontop(FALSE);
-        }
-}
-
-static void winprefs_set_im_blink(GtkWidget *w) {
-        gaim_prefs_set_bool(OPT_WINPREFS_IM_BLINK, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)));
-        wgaim_conv_im_blink_state(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)));
-}
 
 /*
  *  EXPORTED FUNCTIONS
  */
 
 gboolean plugin_load(GaimPlugin *plugin) {
-        plugin_id = plugin;
+	/* Find out how to go blinky */
+	load_winver_specific_procs();
 
-        /* blist docking init */
+	handle = plugin;
+
+	/* blist docking init */
 	if (gaim_get_blist() && GAIM_GTK_BLIST(gaim_get_blist()) && GAIM_GTK_BLIST(gaim_get_blist())->window) {
 		blist_create_cb(gaim_get_blist(), NULL);
-	} else {
-		gaim_signal_connect(gaim_gtk_blist_get_handle(), "gtkblist-created", plugin_id, GAIM_CALLBACK(blist_create_cb), NULL);
 	}
 
-        wgaim_conv_im_blink_state(gaim_prefs_get_bool(OPT_WINPREFS_IM_BLINK));
+	/* This really shouldn't happen anymore generally, but if for some strange
+	   reason, the blist is recreated, we need to set it up again. */
+	gaim_signal_connect(gaim_gtk_blist_get_handle(), "gtkblist-created", plugin, GAIM_CALLBACK(blist_create_cb), NULL);
+
+	gaim_signal_connect(gaim_conversations_get_handle(), "received-im-msg", plugin, GAIM_CALLBACK(wgaim_conv_im_blink), NULL);
 
-        gaim_signal_connect((void*)gaim_get_core(), "quitting", plugin, GAIM_CALLBACK(gaim_quit_cb), NULL);
+	gaim_signal_connect((void*)gaim_get_core(), "quitting", plugin, GAIM_CALLBACK(gaim_quit_cb), NULL);
 
-        return TRUE;
+	gaim_prefs_connect_callback(handle, PREF_BLIST_ON_TOP,
+								winprefs_set_blist_ontop, NULL);
+	gaim_prefs_connect_callback(handle, PREF_DBLIST_DOCKABLE,
+								winprefs_set_blist_dockable, NULL);
+
+	return TRUE;
 }
 
 gboolean plugin_unload(GaimPlugin *plugin) {
-        blist_set_dockable(FALSE);
-        wgaim_conv_im_blink_state(TRUE);
-        return TRUE;
+	blist_set_dockable(FALSE);
+	blist_set_ontop(FALSE);
+	return TRUE;
 }
 
 static GtkWidget* get_config_frame(GaimPlugin *plugin) {
 	GtkWidget *ret;
+	GtkWidget *vbox;
 	GtkWidget *button;
-        GtkWidget *dbutton;
-	GtkWidget *vbox;
-        char* gtk_version = NULL;
-        HKEY hKey = HKEY_CURRENT_USER;
+	char* gtk_version = NULL;
+	HKEY hKey = HKEY_CURRENT_USER;
 
 	ret = gtk_vbox_new(FALSE, 18);
 	gtk_container_set_border_width (GTK_CONTAINER (ret), 12);
 
-        while(hKey) {
-                char version[25];
-                DWORD vlen = 25;
-                if(wgaim_read_reg_string(hKey, "SOFTWARE\\GTK\\2.0", "Version", (LPBYTE)&version, &vlen)) {
-                        char revision[25];
-                        DWORD rlen = 25;
-                        gboolean gotrev = FALSE;
-                        if(wgaim_read_reg_string(hKey, "SOFTWARE\\GTK\\2.0", "Revision", (LPBYTE)&revision, &rlen)) {
-                                revision[0] = g_ascii_toupper(revision[0]);
-                                revision[1] = '\0';
-                                gotrev = TRUE;
-                        }
-                        gtk_version = g_strdup_printf("%s%s%s", 
-                                                      version, 
-                                                      gotrev?" Revision ":"", 
-                                                      gotrev?revision:"");
-                        hKey = 0;
-                }
-                if(hKey == HKEY_CURRENT_USER)
-                        hKey = HKEY_LOCAL_MACHINE;
-                else if(hKey == HKEY_LOCAL_MACHINE)
-                        hKey = 0;
-        }
+	while(hKey) {
+		char version[25];
+		DWORD vlen = 25;
+		if(wgaim_read_reg_string(hKey, "SOFTWARE\\GTK\\2.0", "Version", (LPBYTE)&version, &vlen)) {
+			char revision[25];
+			DWORD rlen = 25;
+			gboolean gotrev = FALSE;
+			if(wgaim_read_reg_string(hKey, "SOFTWARE\\GTK\\2.0", "Revision", (LPBYTE)&revision, &rlen)) {
+				revision[0] = g_ascii_toupper(revision[0]);
+				revision[1] = '\0';
+				gotrev = TRUE;
+			}
+			gtk_version = g_strdup_printf("%s%s%s", version,
+										  (gotrev ? " Revision " : ""),
+										  (gotrev ? revision : ""));
+			hKey = 0;
+		}
+		if(hKey == HKEY_CURRENT_USER)
+			hKey = HKEY_LOCAL_MACHINE;
+		else if(hKey == HKEY_LOCAL_MACHINE)
+			hKey = 0;
+	}
 
-        /* Display Installed GTK+ Runtime Version */
-        if(gtk_version) {
-                GtkWidget *label;
-                vbox = gaim_gtk_make_frame(ret, _("GTK+ Runtime Version"));
-                label = gtk_label_new(gtk_version);
-                gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
-                gtk_widget_show(label);
-                g_free(gtk_version);
-        }
+	/* Display Installed GTK+ Runtime Version */
+	if(gtk_version) {
+		GtkWidget *label;
+		vbox = gaim_gtk_make_frame(ret, _("GTK+ Runtime Version"));
+		label = gtk_label_new(gtk_version);
+		gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+		gtk_widget_show(label);
+		g_free(gtk_version);
+	}
 
-        /* Autostart */
+	/* Autostart */
 	vbox = gaim_gtk_make_frame (ret, _("Startup"));
-	button = wgaim_button(_("_Start Gaim on Windows startup"), vbox);
+	button = gtk_check_button_new_with_mnemonic(_("_Start Gaim on Windows startup"));
+	gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
 	if(open_run_key(&hKey, KEY_QUERY_VALUE)) {
 		if(ERROR_SUCCESS == RegQueryValueEx(hKey, "Gaim", 0, NULL, NULL, NULL)) {
 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
 		}
 	}
-	gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(winprefs_set_autostart), NULL);
-
-        /* Buddy List */
-	vbox = gaim_gtk_make_frame (ret, _("Buddy List"));
-        button = wgaim_button(_("_Dockable Buddy List"), vbox);
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_DOCKABLE));
+	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(winprefs_set_autostart), NULL);
+	gtk_widget_show(button);
 
-        /* Docked Blist On Top */
-        dbutton = wgaim_button(_("Docked _Buddy List is always on top"), vbox);
-        gtk_signal_connect(GTK_OBJECT(dbutton), "clicked", GTK_SIGNAL_FUNC(winprefs_set_dblist_ontop), NULL);
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dbutton), gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_ON_TOP));
-        if(!gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_DOCKABLE))
-                gtk_widget_set_sensitive(GTK_WIDGET(dbutton), FALSE);
+	/* Buddy List */
+	vbox = gaim_gtk_make_frame (ret, _("Buddy List"));
+	gaim_gtk_prefs_checkbox(_("_Dockable Buddy List"),
+							PREF_DBLIST_DOCKABLE, vbox);
 
-        /* Connect cb for Dockable option.. passing dblist on top button */
-        gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(winprefs_set_blist_dockable), dbutton);
+	/* Blist On Top */
+	gaim_gtk_prefs_dropdown(vbox, _("_Keep Buddy List window on top:"),
+							GAIM_PREF_INT, PREF_BLIST_ON_TOP,
+							_("Never"),             BLIST_TOP_NEVER,
+							_("Always"),            BLIST_TOP_ALWAYS,
+							/* XXX: Did this ever work? */
+							_("Only when docked"),  BLIST_TOP_DOCKED,
+							NULL);
 
-        /* Blist On Top */
-        button = wgaim_button(_("_Keep Buddy List window on top"), vbox);
-        gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(winprefs_set_blist_ontop), NULL);
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), gaim_prefs_get_bool(OPT_WINPREFS_BLIST_ON_TOP));
-
-        /* Conversations */
+	/* Conversations */
 	vbox = gaim_gtk_make_frame (ret, _("Conversations"));
-        button = wgaim_button(_("_Flash Window when messages are received"), vbox);
-        gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(winprefs_set_im_blink), NULL);
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), gaim_prefs_get_bool(OPT_WINPREFS_IM_BLINK));
+	gaim_gtk_prefs_checkbox(_("_Flash window when messages are received"),
+							PREF_IM_BLINK, vbox);
 
 	gtk_widget_show_all(ret);
 	return ret;
@@ -383,7 +458,7 @@
 	N_("WinGaim Options"),
 	VERSION,
 	N_("Options specific to Windows Gaim."),
-	N_("Options specific to Windows Gaim."),
+	N_("Provides options specific to Windows Gaim, such as buddy list docking and conversation flashing."),
 	"Herman Bloggs <hermanator12002@yahoo.com>",
 	GAIM_WEBSITE,
 	plugin_load,
@@ -398,15 +473,27 @@
 static void
 init_plugin(GaimPlugin *plugin)
 {
+        gaim_prefs_add_none("/plugins/gtk");
         gaim_prefs_add_none("/plugins/gtk/win32");
         gaim_prefs_add_none("/plugins/gtk/win32/winprefs");
-        gaim_prefs_add_bool(OPT_WINPREFS_DBLIST_DOCKABLE, FALSE);
-        gaim_prefs_add_bool(OPT_WINPREFS_DBLIST_DOCKED, FALSE);
-        gaim_prefs_add_int(OPT_WINPREFS_DBLIST_HEIGHT, 0);
-        gaim_prefs_add_int(OPT_WINPREFS_DBLIST_SIDE, 0);
-        gaim_prefs_add_bool(OPT_WINPREFS_DBLIST_ON_TOP, FALSE);
-        gaim_prefs_add_bool(OPT_WINPREFS_BLIST_ON_TOP, FALSE);
-        gaim_prefs_add_bool(OPT_WINPREFS_IM_BLINK, TRUE);
+        gaim_prefs_add_bool(PREF_DBLIST_DOCKABLE, FALSE);
+        gaim_prefs_add_bool(PREF_DBLIST_DOCKED, FALSE);
+        gaim_prefs_add_int(PREF_DBLIST_HEIGHT, 0);
+        gaim_prefs_add_int(PREF_DBLIST_SIDE, 0);
+        gaim_prefs_add_bool(PREF_IM_BLINK, TRUE);
+
+		/* Convert old preferences */
+		if (gaim_prefs_exists(PREF_DBLIST_ON_TOP)) {
+			gint blist_top = BLIST_TOP_NEVER;
+			if (gaim_prefs_get_bool(PREF_BLIST_ON_TOP))
+				blist_top = BLIST_TOP_ALWAYS;
+			else if (gaim_prefs_get_bool(PREF_DBLIST_ON_TOP))
+				blist_top = BLIST_TOP_DOCKED;
+			gaim_prefs_remove(PREF_BLIST_ON_TOP);
+			gaim_prefs_remove(PREF_DBLIST_ON_TOP);
+			gaim_prefs_add_int(PREF_BLIST_ON_TOP, blist_top);
+		} else
+			gaim_prefs_add_int(PREF_BLIST_ON_TOP, BLIST_TOP_NEVER);
 }
 
 GAIM_INIT_PLUGIN(winprefs, init_plugin, info)
--- a/src/conversation.c	Sat Jun 11 22:30:08 2005 +0000
+++ b/src/conversation.c	Sat Jun 11 23:29:56 2005 +0000
@@ -367,21 +367,6 @@
 	ops->raise(win);
 }
 
-void
-gaim_conv_window_flash(GaimConvWindow *win)
-{
-	GaimConvWindowUiOps *ops;
-
-	g_return_if_fail(win != NULL);
-
-	ops = gaim_conv_window_get_ui_ops(win);
-
-	if (ops == NULL || ops->flash == NULL)
-		return;
-
-	ops->flash(win);
-}
-
 gboolean
 gaim_conv_window_has_focus(GaimConvWindow *win)
 {
--- a/src/conversation.h	Sat Jun 11 22:30:08 2005 +0000
+++ b/src/conversation.h	Sat Jun 11 23:29:56 2005 +0000
@@ -160,7 +160,6 @@
 	void (*show)(GaimConvWindow *win);
 	void (*hide)(GaimConvWindow *win);
 	void (*raise)(GaimConvWindow *win);
-	void (*flash)(GaimConvWindow *win);
 
 	void (*switch_conversation)(GaimConvWindow *win, GaimConversation *conv);
 	void (*add_conversation)(GaimConvWindow *win, GaimConversation *conv);
@@ -361,13 +360,6 @@
 void gaim_conv_window_raise(GaimConvWindow *win);
 
 /**
- * Causes the window to flash for IM notification, if the UI supports this.
- *
- * @param win The window.
- */
-void gaim_conv_window_flash(GaimConvWindow *win);
-
-/**
  * Sets the specified window's UI window operations structure.
  *
  * @param win The window.
--- a/src/gtkconv.c	Sat Jun 11 22:30:08 2005 +0000
+++ b/src/gtkconv.c	Sat Jun 11 23:29:56 2005 +0000
@@ -4297,16 +4297,6 @@
 }
 
 static void
-gaim_gtk_flash(GaimConvWindow *win)
-{
-#ifdef _WIN32
-	GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(win);
-
-	wgaim_conv_im_blink(gtkwin->window);
-#endif
-}
-
-static void
 gaim_gtk_switch_conversation(GaimConvWindow *win, GaimConversation *conv)
 {
 	GaimGtkWindow *gtkwin;
@@ -4654,7 +4644,6 @@
 	gaim_gtk_show,
 	gaim_gtk_hide,
 	gaim_gtk_raise,
-	gaim_gtk_flash,
 	gaim_gtk_switch_conversation,
 	gaim_gtk_add_conversation,
 	gaim_gtk_remove_conversation,
--- a/src/server.c	Sat Jun 11 22:30:08 2005 +0000
+++ b/src/server.c	Sat Jun 11 23:29:56 2005 +0000
@@ -771,7 +771,6 @@
 				cnv = gaim_conversation_new(GAIM_CONV_IM, account, name);
 
 			gaim_conv_im_write(GAIM_CONV_IM(cnv), NULL, message, msgflags, mtime);
-			gaim_conv_window_flash(gaim_conversation_get_window(cnv));
 		}
 
 		/*
@@ -892,7 +891,6 @@
 				cnv = gaim_conversation_new(GAIM_CONV_IM, gc->account, name);
 
 			gaim_conv_im_write(GAIM_CONV_IM(cnv), NULL, message, msgflags, mtime);
-			gaim_conv_window_flash(gaim_conversation_get_window(cnv));
 #if 0
 		}
 #endif
--- a/src/win32/win32dep.c	Sat Jun 11 22:30:08 2005 +0000
+++ b/src/win32/win32dep.c	Sat Jun 11 23:29:56 2005 +0000
@@ -72,15 +72,6 @@
     SHGFP_TYPE_DEFAULT  = 1,   // default value, may not exist
 } SHGFP_TYPE;
 
-/* flash info */
-typedef BOOL (CALLBACK* LPFNFLASHWINDOWEX)(PFLASHWINFO);
-
-struct _WGAIM_FLASH_INFO {
-	guint t_handle;
-	guint sig_handler;
-};
-typedef struct _WGAIM_FLASH_INFO WGAIM_FLASH_INFO;
-
 /*
  * LOCALS
  */
@@ -88,7 +79,6 @@
 static char install_dir[MAXPATHLEN];
 static char lib_dir[MAXPATHLEN];
 static char locale_dir[MAXPATHLEN];
-static gboolean blink_turned_on = TRUE;
 
 /*
  *  GLOBALS
@@ -99,7 +89,6 @@
 /*
  *  PROTOS
  */
-LPFNFLASHWINDOWEX MyFlashWindowEx = NULL;
 
 FARPROC wgaim_find_and_loadproc(char*, char*);
 extern void wgaim_gtkspell_init();
@@ -109,44 +98,6 @@
  *  STATIC CODE
  */
 
-/* Window flasher */
-static gboolean flash_window_cb(gpointer data) {
-	FlashWindow((HWND)data, TRUE);
-	return TRUE;
-}
-
-static int halt_flash_filter(GtkWidget *widget, GdkEventFocus *event, gpointer data) {
-        if(MyFlashWindowEx) {
-                HWND hWnd = data;
-                FLASHWINFO info;
-
-                if(!IsWindow(hWnd))
-                        return 0;
-                memset(&info, 0, sizeof(FLASHWINFO));
-		info.cbSize = sizeof(FLASHWINFO);
-		info.hwnd = hWnd;
-		info.dwFlags = FLASHW_STOP;
-		info.dwTimeout = 0;
-		MyFlashWindowEx(&info);
-        }
-        else {
-                WGAIM_FLASH_INFO *finfo = data;        
-                /* Stop flashing and remove filter */
-                gaim_debug(GAIM_DEBUG_INFO, "wgaim", "Removing timeout\n");
-                gaim_timeout_remove(finfo->t_handle);
-                gaim_debug(GAIM_DEBUG_INFO, "wgaim", "Disconnecting signal handler\n");
-                g_signal_handler_disconnect(G_OBJECT(widget),finfo->sig_handler);
-                gaim_debug(GAIM_DEBUG_INFO, "wgaim", "done\n");
-                g_free(finfo);
-        }
-	return 0;
-}
-
-static void load_winver_specific_procs(void) {
-	/* Used for Win98+ and WinNT5+ */
-	MyFlashWindowEx = (LPFNFLASHWINDOWEX)wgaim_find_and_loadproc("user32.dll", "FlashWindowEx" );
-}
-
 static void wgaim_debug_print(GaimDebugLevel level, const char *category, const char *format, va_list args) {
 	char *str = NULL;
 	if (args != NULL) {
@@ -332,43 +283,6 @@
         return ret;
 }
 
-/* FlashWindowEx is only supported by Win98+ and WinNT5+. If its
-   not supported we do it our own way */
-void wgaim_conv_im_blink(GtkWidget *window) {
-        if(!blink_turned_on)
-                return;
-	if(MyFlashWindowEx) {
-		FLASHWINFO info;
-                if(GetForegroundWindow() == GDK_WINDOW_HWND(window->window))
-                        return;
-                memset(&info, 0, sizeof(FLASHWINFO));
-		info.cbSize = sizeof(FLASHWINFO);
-		info.hwnd = GDK_WINDOW_HWND(window->window);
-		info.dwFlags = FLASHW_ALL | FLASHW_TIMER;
-		info.dwTimeout = 0;
-		MyFlashWindowEx(&info);
-                /* Stop flashing when window receives focus */
-                g_signal_connect(G_OBJECT(window), 
-                                 "focus-in-event", 
-                                 G_CALLBACK(halt_flash_filter), info.hwnd);
-	}
-	else {
-		WGAIM_FLASH_INFO *finfo = g_new0(WGAIM_FLASH_INFO, 1);
-
-		/* Start Flashing window */
-		finfo->t_handle = gaim_timeout_add(1000, 
-						flash_window_cb, 
-						GDK_WINDOW_HWND(window->window));
-		finfo->sig_handler = g_signal_connect(G_OBJECT(window), 
-						      "focus-in-event", 
-						      G_CALLBACK(halt_flash_filter), finfo);
-	}
-}
-
-void wgaim_conv_im_blink_state(gboolean val) {
-        blink_turned_on = val;
-}
-
 int wgaim_gz_decompress(const char* in, const char* out) {
 	gzFile fin;
 	FILE *fout;
@@ -466,8 +380,6 @@
 
 	gaimexe_hInstance = hint;
 
-	load_winver_specific_procs();
-
 	/* Winsock init */
 	wVersionRequested = MAKEWORD( 2, 2 );
 	WSAStartup( wVersionRequested, &wsaData );
--- a/src/win32/win32dep.h	Sat Jun 11 22:30:08 2005 +0000
+++ b/src/win32/win32dep.h	Sat Jun 11 23:29:56 2005 +0000
@@ -49,8 +49,6 @@
 extern char*     wgaim_locale_dir(void);
 extern char*     wgaim_data_dir(void);
 /* UI related */
-extern void      wgaim_conv_im_blink(GtkWidget*);
-extern void      wgaim_conv_im_blink_state(gboolean val);
 extern void      wgaim_gtk_window_move(GtkWindow *window, gint x, gint y);
 /* Utility */
 extern int       wgaim_gz_decompress(const char* in, const char* out);