view plugins/win32/winprefs/winprefs.c @ 7694:6a9acef3b867

[gaim-migrate @ 8339] Committing this now so that I don't accidentally destroy it again. We're going WYSIWYG, folks. This is the beginning of it. Don't bother trying to tell me what doesn't work yet. This is just a sneak-peek. Bold, Italics, and Underline work fairly well. The toggle buttons in the tooltips won't necessarily be accurate yet, and things will get screwed up if you say, start typing, make something bold, then go back to before where you started typing and type there. It'll all be fixed eventually. NOTE: I am not liable for any sexual arousal caused by using this code committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Tue, 02 Dec 2003 07:33:42 +0000
parents bf630f7dfdcd
children d7b8eb1f0a18
line wrap: on
line source

/*
 * gaim - WinGaim Options Plugin
 *
 * File: winprefs.c
 * Date: December 12, 2002
 * Description: Gaim Plugin interface
 *
 * 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
 * (at your option) any later version.
 *
 * this program is distributed in the hope that it will be useful,
 * but without any warranty; without even the implied warranty of
 * merchantability or fitness for a particular purpose.  see the
 * gnu general public license for more details.
 *
 * you should have received a copy of the gnu general public license
 * along with this program; if not, write to the free software
 * foundation, inc., 59 temple place, suite 330, boston, ma  02111-1307  usa
 *
 */
#include <windows.h>
#include <winreg.h>
#include <winerror.h>
#include <gdk/gdkwin32.h>

#include "internal.h"
#include "gtkinternal.h"

#include "core.h"
#include "prefs.h"
#include "debug.h"

#include "gtkplugin.h"
#include "gtkutils.h"
#include "gtkblist.h"
#include "gtkappbar.h"
#include "signals.h"

/*
 *  MACROS & DEFINES
 */
#define WINPREFS_PLUGIN_ID               "gtk-win-prefs"

/*
 *  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 GaimPlugin *plugin_id = NULL;
static GtkAppBar *blist_ab = NULL;
static GtkWidget *blist = NULL;

/*
 *  PROTOS
 */
static void blist_create_cb();

/*
 *  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);
        }
}

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);
}

static void blist_dock_cb(gboolean val) {
        if(val) {
                gaim_debug(GAIM_DEBUG_INFO, "winprefs", "Blist Docking..\n");
                if(gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_ON_TOP))
                        blist_set_ontop(TRUE);
        }
        else {
                gaim_debug(GAIM_DEBUG_INFO, "winprefs", "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);
        }
}

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;
        }
}

/* PLUGIN CALLBACKS */

/* 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(GAIM_DEBUG_INFO, WINPREFS_PLUGIN_ID, "gaim_quit_cb: removing appbar\n");
        blist_save_state();
        blist_set_dockable(FALSE);
}

/* Needed when the last account is signed off.. and we get the login window */
static void blist_destroy_cb() {
        gaim_debug(GAIM_DEBUG_INFO, "winprefs", "blist_destroy_cb\n");
        blist_save_state();
        blist_set_dockable(FALSE);
        gaim_signal_connect((void*)gaim_connections_get_handle(), "signed-on", plugin_id, GAIM_CALLBACK(blist_create_cb), NULL);
}

static gboolean blist_create_cb_remove(gpointer data) {
        gaim_signal_disconnect(gaim_connections_get_handle(), "signed-on", plugin_id, GAIM_CALLBACK(blist_create_cb));
        return FALSE;
}

static void blist_create_cb() {
        gaim_debug(GAIM_DEBUG_INFO, WINPREFS_PLUGIN_ID, "event_signon\n");

        blist = GAIM_GTK_BLIST(gaim_get_blist())->window;
        g_signal_connect(blist, "destroy", blist_destroy_cb, NULL);

        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);
        }
        /* removing here will cause a crash when going to next cb
           in the gaim signal cb loop.. so process delayed. */
        g_idle_add(blist_create_cb_remove, NULL);
}

/* 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));
	else {
		gaim_debug(GAIM_DEBUG_ERROR, WINPREFS_PLUGIN_ID, "open_run_key: Could not open key for writing value\n");
		return 0;
	}
	return 1;
}

/* WIN PREFS GENERAL */

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(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(GAIM_DEBUG_ERROR, WINPREFS_PLUGIN_ID, "Could not set registry key value\n");
        }
        else {
                if(ERROR_SUCCESS != RegDeleteValue(hKey, "Gaim"))
                        gaim_debug(GAIM_DEBUG_ERROR, WINPREFS_PLUGIN_ID, "Could not delete registry key value\n");
        }
        RegCloseKey(hKey);
}

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 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)));

        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);
        }
}

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;

        /* blist docking init */
        if(gaim_get_blist() && GAIM_GTK_BLIST(gaim_get_blist())) {
                blist = GAIM_GTK_BLIST(gaim_get_blist())->window;
                /* Set Dockable */
                if(gaim_prefs_get_bool(OPT_WINPREFS_DBLIST_DOCKABLE))
                        blist_set_dockable(TRUE);
                /* Set On top */
                if(gaim_prefs_get_bool(OPT_WINPREFS_BLIST_ON_TOP))
                        blist_set_ontop(TRUE);
                g_signal_connect(blist, "destroy", blist_destroy_cb, NULL);
        }
        else
                gaim_signal_connect((void*)gaim_connections_get_handle(), "signed-on", plugin_id, GAIM_CALLBACK(blist_create_cb), NULL);

        wgaim_conv_im_blink_state(gaim_prefs_get_bool(OPT_WINPREFS_IM_BLINK));

        gaim_signal_connect((void*)gaim_get_core(), "quitting", plugin, GAIM_CALLBACK(gaim_quit_cb), NULL);

        return TRUE;
}

gboolean plugin_unload(GaimPlugin *plugin) {
        blist_set_dockable(FALSE);
        wgaim_conv_im_blink_state(TRUE);
        return TRUE;
}

static GtkWidget* get_config_frame(GaimPlugin *plugin) {
	GtkWidget *ret;
	GtkWidget *button;
        GtkWidget *dbutton;
	GtkWidget *vbox;
        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;
        }

        /* 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 */
	vbox = gaim_gtk_make_frame (ret, _("Startup"));
	button = wgaim_button(_("_Start Gaim on Windows startup"), vbox);
	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));

        /* 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);

        /* 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 */
        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 */
	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));

	gtk_widget_show_all(ret);
	return ret;
}

static GaimGtkPluginUiInfo ui_info =
{
	get_config_frame
};

static GaimPluginInfo info =
{
	2,
	GAIM_PLUGIN_STANDARD,
	GAIM_GTK_PLUGIN_TYPE,
	0,
	NULL,
	GAIM_PRIORITY_DEFAULT,
	WINPREFS_PLUGIN_ID,
	N_("WinGaim Options"),
	VERSION,
	N_("Options specific to Windows Gaim."),
	N_("Options specific to Windows Gaim."),
	"Herman Bloggs <hermanator12002@yahoo.com>",
	GAIM_WEBSITE,
	plugin_load,
	plugin_unload,
	NULL,
	&ui_info,
	NULL
};

static void
init_plugin(GaimPlugin *plugin)
{
        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_INIT_PLUGIN(winprefs, init_plugin, info)