# HG changeset patch # User Mark Doliner # Date 1059107452 0 # Node ID 511003c993025e3798307dc0d5b4901f7385598d # Parent 0e60f9b2e6ebb1fad866f30ded5218d8f56df181 [gaim-migrate @ 6801] Notify plugin. It seems to work pretty well for me. One thing I did notice, it doesn't really handle getting IMs from different people very well. It makes a different counter in title of the IM for each person, and then only updates the most recently added one. I also didn't try chat stuff at all, but I need to go to sleep pretty soon. Pretty much all of the changes were done by Brian Tarricon, I just renamed a few things and did a few other patent-pending actions. committer: Tailor Script diff -r 0e60f9b2e6eb -r 511003c99302 ChangeLog --- a/ChangeLog Thu Jul 24 22:35:26 2003 +0000 +++ b/ChangeLog Fri Jul 25 04:30:52 2003 +0000 @@ -1,6 +1,7 @@ Gaim: The Pimpin' Penguin IM Clone that's good for the soul! version 0.67 + * Brought back the message notifiation plugin (Brian Tarricone) * Various bug fixes (larne from irc, Tim Ringenbach, Bjoern Voigt, Paul A (darkrain)) * British English "translation" updated (Sam Halliday) diff -r 0e60f9b2e6eb -r 511003c99302 plugins/Makefile.am --- a/plugins/Makefile.am Thu Jul 24 22:35:26 2003 +0000 +++ b/plugins/Makefile.am Fri Jul 25 04:30:52 2003 +0000 @@ -9,43 +9,47 @@ plugindir = $(libdir)/gaim autorecon_la_LDFLAGS = -module -avoid-version +history_la_LDFLAGS = -module -avoid-version iconaway_la_LDFLAGS = -module -avoid-version -#notify_la_LDFLAGS = -module -avoid-version +idle_la_LDFLAGS = -module -avoid-version +notify_la_LDFLAGS = -module -avoid-version spellchk_la_LDFLAGS = -module -avoid-version -history_la_LDFLAGS = -module -avoid-version +statenotify_la_LDFLAGS = -module -avoid-version timestamp_la_LDFLAGS = -module -avoid-version -idle_la_LDFLAGS = -module -avoid-version -statenotify_la_LDFLAGS = -module -avoid-version if PLUGINS plugin_LTLIBRARIES = \ autorecon.la \ + history.la \ iconaway.la \ + idle.la \ + notify.la \ spellchk.la \ - history.la \ - timestamp.la \ - idle.la \ - statenotify.la - -# notify.la + statenotify.la \ + timestamp.la autorecon_la_SOURCES = autorecon.c +history_la_SOURCES = history.c iconaway_la_SOURCES = iconaway.c -#notify_la_SOURCES = notify.c +idle_la_SOURCES = idle.c +notify_la_SOURCES = notify.c spellchk_la_SOURCES = spellchk.c -history_la_SOURCES = history.c +statenotify_la_SOURCES = statenotify.c timestamp_la_SOURCES = timestamp.c -idle_la_SOURCES = idle.c -statenotify_la_SOURCES = statenotify.c endif # PLUGINS EXTRA_DIST = \ ChangeLog PERL-HOWTO HOWTO SIGNALS \ - filectl.c mailchk.c gtik.c \ - raw.c events.c simple.c \ - gaim.pl fortuneprofile.pl + filectl.c \ + mailchk.c \ + gtik.c \ + raw.c \ + events.c \ + simple.c \ + gaim.pl \ + fortuneprofile.pl AM_CPPFLAGS = \ -I$(top_srcdir)/src \ diff -r 0e60f9b2e6eb -r 511003c99302 plugins/notify.c --- a/plugins/notify.c Thu Jul 24 22:35:26 2003 +0000 +++ b/plugins/notify.c Fri Jul 25 04:30:52 2003 +0000 @@ -1,26 +1,70 @@ -/* Rewritten by Etan Reisner +/* + * Gaim buddy notification plugin. + * + * Copyright (C) 2000-2001, Eric Warmenhoven (original code) + * Copyright (C) 2002, Etan Reisner (rewritten code) + * Copyright (C) 2003, Christian Hammond (update for changed API) + * Copyright (C) 2003, Brian Tarricon (mostly rewritten) + * Copyright (C) 2003, Mark Doliner (minor cleanup) + * + * 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. * - * Added config dialog - * Added control over notification method - * Added control over when to release notification - * - * Added option to get notification for chats also - * Cleaned up code - * Added option to notify on click as it's own option - * rather then as what happens when on focus isn't clicked - * Added apply button to change the denotification methods for - * open conversation windows - * Fixed apply to conversations, count now keeps count across applies - * Fixed(?) memory leak, and in the process fixed some stupidities - * Hit enter when done editing the title string entry box to save it + * 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 + * + */ + +/* + * From Etan, 2002: + * -Added config dialog + * -Added control over notification method + * -Added control over when to release notification + * + * -Added option to get notification for chats also + * -Cleaned up code + * -Added option to notify on click as it's own option + * rather then as what happens when on focus isn't clicked + * -Added apply button to change the denotification methods for + * open conversation windows + * -Fixed apply to conversations, count now keeps count across applies + * -Fixed(?) memory leak, and in the process fixed some stupidities + * -Hit enter when done editing the title string entry box to save it * * Thanks to Carles Pina i Estany * for count of new messages option + * + * From Brian, 20 July 2003: + * -Use new xml prefs + * -Better handling of notification states tracking + * -Better pref change handling + * -Fixed a possible memleak and possible crash (rare) + * -Use gtk_window_get_title() rather than gtkwin->title + * -Other random fixes and cleanups */ -#include "config.h" +#include "internal.h" + +#include "conversation.h" +#include "debug.h" +#include "notify.h" +#include "prefs.h" -#include "gaim.h" +#include "gtkconv.h" +#include "gtkplugin.h" +#include "gtkutils.h" + + +#include "gtkplugin.h" + #include #include #include @@ -29,332 +73,396 @@ #include #include #include -#include "gtkplugin.h" - -#define NOTIFY_PLUGIN_ID "gtk-notify" +#include -guint type = 1; -#define TYPE_IM 0x00000001 -#define TYPE_CHAT 0x00000002 +#define NOTIFY_PLUGIN_ID "gtk-x11-notify" -guint choice = 1; -#define NOTIFY_FOCUS 0x00000001 -#define NOTIFY_TYPE 0x00000002 -#define NOTIFY_IN_FOCUS 0x00000004 -#define NOTIFY_CLICK 0x00000008 +#define OPT_TYPE_IM ((guint)0x00000001) +#define OPT_TYPE_CHAT ((guint)0x00000002) +#define OPT_NOTIFY_FOCUS ((guint)0x00000004) +#define OPT_NOTIFY_TYPE ((guint)0x00000008) +#define OPT_NOTIFY_IN_FOCUS ((guint)0x00000010) +#define OPT_NOTIFY_CLICK ((guint)0x00000020) +#define OPT_METHOD_STRING ((guint)0x00000040) +#define OPT_METHOD_QUOTE ((guint)0x00000080) +#define OPT_METHOD_URGENT ((guint)0x00000100) +#define OPT_METHOD_COUNT ((guint)0x00000200) +#define OPT_METHOD_STRING_CHNG ((guint)0x00000400) +#define STATE_IS_NOTIFIED ((guint)0x80000000) -guint method = 1; -#define METHOD_STRING 0x00000001 -#define METHOD_QUOTE 0x00000002 -#define METHOD_URGENT 0x00000004 -#define METHOD_COUNT 0x00000008 +#define TITLE_STR_BUFSIZE 256 + +#define GDATASTR "notify-plugin-opts" +#define GDATASTRCNT "notify-plugin-count" static GaimPlugin *my_plugin = NULL; -void *handle; -GtkWidget *Entry; -gchar *title_string; -int Number = 0; +static guint notify_opts = 0; +static gchar title_string[TITLE_STR_BUFSIZE+1]; + +/* notification set/unset */ +static int notify(GaimConversation *c); +static void unnotify(GaimConversation *c); +static int unnotify_cb(GtkWidget *widget, gpointer data); + +/* gtk widget callbacks for prefs panel */ +static void options_toggle_cb(GtkWidget *widget, gpointer data); +static gboolean options_settitle_cb(GtkWidget *w, GdkEventFocus *evt, GtkWidget *entry); +static void options_toggle_title_cb(GtkWidget *w, GtkWidget *entry); +static void apply_options(int opt_chng); + +/* string functions */ +static void string_add(GtkWidget *widget); +static void string_remove(GtkWidget *widget); -/* predefine some functions, less warnings */ -void options(GtkWidget *widget, gpointer data); -/* this returns an int so that typing events don't get stopped here */ -int un_star(GtkWidget *widget, gpointer data); -int counter (char *buf, int *length); -/*string functions */ -void string_add(GtkWidget *widget); -gboolean string_remove(GtkWidget *widget); /* count functions */ -void count_add(GtkWidget *widget, int number); -gboolean count_remove(GtkWidget *widget); +static void count_add(GtkWidget *widget); +static void count_remove(GtkWidget *widget); + /* quote functions */ -void quote_add(GtkWidget *widget); -gboolean quote_remove(GtkWidget *widget); +static void quote_add(GtkWidget *widget); +static void quote_remove(GtkWidget *widget); + /* urgent functions */ -void urgent_add(GaimConversation *c); -gboolean urgent_remove(GaimConversation *c); +static void urgent_add(GaimConversation *c); +static void urgent_remove(GaimConversation *c); -int notify(GaimConversation *cnv) { +/****************************************/ +/* Begin doing stuff below this line... */ +/****************************************/ + +static int notify(GaimConversation *c) { GaimGtkWindow *gtkwin; Window focus_return; int revert_to_return; - - gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(cnv)); - - XGetInputFocus(GDK_WINDOW_XDISPLAY(gtkwin->window->window), &focus_return, &revert_to_return); - - if ((choice & NOTIFY_IN_FOCUS) || - focus_return != GDK_WINDOW_XWINDOW(gtkwin->window->window)) { - if (method & METHOD_STRING) - string_add(gtkwin->window); - if (method & METHOD_COUNT) - count_add(gtkwin->window, 0); - if (method & METHOD_QUOTE) - quote_add(gtkwin->window); - if (method & METHOD_URGENT) - urgent_add(cnv); - } - return 0; -} - -guint unnotify(GaimConversation *c, gboolean clean) { - GaimGtkWindow *gtkwin; - guint option = 0; + guint opts; + gint count; gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); - /* The top level ifs check whether we are either cleaning all methods, - * or whether we have that method is currently selected. - * If we do then they are cleaned - * - * The second level ifs check if we removed something, - * and if that method is currently selected. - * If we did and it is then set option so that it can be re-added */ - if (clean || (method & METHOD_QUOTE)) - if (quote_remove(gtkwin->window) && (method & METHOD_QUOTE)) - option ^= METHOD_QUOTE; + /* increment message counter */ + count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkwin->window), GDATASTRCNT)); + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTRCNT, GINT_TO_POINTER(count+1)); + + /* if we aren't doing notifications for this type of convo, bail */ + if (((gaim_conversation_get_type(c) == GAIM_CONV_IM) && !(notify_opts & OPT_TYPE_IM)) || + ((gaim_conversation_get_type(c) == GAIM_CONV_CHAT) && !(notify_opts & OPT_TYPE_CHAT))) + return 0; + + XGetInputFocus(GDK_WINDOW_XDISPLAY(gtkwin->window->window), &focus_return, &revert_to_return); - if (clean || (method & METHOD_COUNT)) - if (count_remove(gtkwin->window) && (method & METHOD_COUNT)) - option ^= METHOD_COUNT; + if ((notify_opts & OPT_NOTIFY_IN_FOCUS) || + (focus_return != GDK_WINDOW_XWINDOW(gtkwin->window->window))) { + if (notify_opts & OPT_METHOD_STRING) + string_add(gtkwin->window); + if (notify_opts & OPT_METHOD_COUNT) + count_add(gtkwin->window); + if (notify_opts & OPT_METHOD_QUOTE) + quote_add(gtkwin->window); + if (notify_opts & OPT_METHOD_URGENT) + urgent_add(c); + } - if (clean || (method & METHOD_STRING)) - if (string_remove(gtkwin->window) && (method & METHOD_STRING)) - option ^= METHOD_STRING; + opts = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkwin->window), GDATASTR)); + opts |= STATE_IS_NOTIFIED; + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTR, GINT_TO_POINTER(opts)); - if (clean || (method & METHOD_URGENT)) - if (urgent_remove(c) && (method & METHOD_URGENT)) - option ^= METHOD_URGENT; - - return option; + return 0; } -void chat_recv_im(struct gaim_connection *gc, int id, char **who, char **text) { +static void unnotify(GaimConversation *c) { + GaimGtkWindow *gtkwin; + + gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); + + urgent_remove(c); + quote_remove(GTK_WIDGET(gtkwin->window)); + count_remove(GTK_WIDGET(gtkwin->window)); + string_remove(GTK_WIDGET(gtkwin->window)); + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTR, GINT_TO_POINTER((guint)0)); + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTRCNT, GINT_TO_POINTER((guint)0)); +} + +static int unnotify_cb(GtkWidget *widget, gpointer data) { + GaimConversation *c = g_object_get_data(G_OBJECT(widget), "user_data"); + + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "in unnotify_cb()\n"); + + if (c) + urgent_remove(c); + quote_remove(widget); + count_remove(widget); + string_remove(widget); + g_object_set_data(G_OBJECT(widget), GDATASTR, GINT_TO_POINTER((guint)0)); + g_object_set_data(G_OBJECT(widget), GDATASTRCNT, GINT_TO_POINTER((guint)0)); + + return 0; +} + +static void chat_recv_im(GaimConnection *gc, int id, char **who, char **text) { GaimConversation *c = gaim_find_chat(gc, id); - if (c && (type & TYPE_CHAT)) + if (c) notify(c); return; } -void chat_sent_im(struct gaim_connection *gc, int id, char **text) { +static void chat_sent_im(GaimConnection *gc, int id, char **text) { GaimConversation *c = gaim_find_chat(gc, id); - if (c && (type & TYPE_CHAT)) - unnotify(c, FALSE); + if (c) + unnotify(c); return; } -int im_recv_im(struct gaim_connection *gc, char **who, char **what, void *m) { +static int im_recv_im(GaimConnection *gc, char **who, char **what, void *m) { GaimConversation *c = gaim_find_conversation(*who); - if (c && (type & TYPE_IM)) + if (c) notify(c); return 0; } -int im_sent_im(struct gaim_connection *gc, char *who, char **what, void *m) { +static int im_sent_im(GaimConnection *gc, char *who, char **what, void *m) { GaimConversation *c = gaim_find_conversation(who); - if (c && (type & TYPE_IM)) - unnotify(c, FALSE); + if (c) + unnotify(c); return 0; } -int attach_signals(GaimConversation *c) { +static int attach_signals(GaimConversation *c) { GaimGtkConversation *gtkconv; GaimGtkWindow *gtkwin; gtkconv = GAIM_GTK_CONVERSATION(c); gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); - if (choice & NOTIFY_FOCUS) { - g_signal_connect(G_OBJECT(gtkwin->window), "focus-in-event", G_CALLBACK(un_star), NULL); + if (notify_opts & OPT_NOTIFY_FOCUS) { + g_signal_connect(G_OBJECT(gtkwin->window), "focus-in-event", G_CALLBACK(unnotify_cb), NULL); } - if (choice & NOTIFY_CLICK) { - g_signal_connect(G_OBJECT(gtkwin->window), "button_press_event", G_CALLBACK(un_star), NULL); - - g_signal_connect_swapped(G_OBJECT(gtkconv->imhtml), "button_press_event", G_CALLBACK(un_star), G_OBJECT(gtkwin->window)); - - g_signal_connect_swapped(G_OBJECT(gtkconv->entry), "button_press_event", G_CALLBACK(un_star), G_OBJECT(gtkwin->window)); + if (notify_opts & OPT_NOTIFY_CLICK) { + g_signal_connect(G_OBJECT(gtkwin->window), "button_press_event", G_CALLBACK(unnotify_cb), NULL); + g_signal_connect_swapped(G_OBJECT(gtkconv->imhtml), "button_press_event", G_CALLBACK(unnotify_cb), G_OBJECT(gtkwin->window)); + g_signal_connect_swapped(G_OBJECT(gtkconv->entry), "button_press_event", G_CALLBACK(unnotify_cb), G_OBJECT(gtkwin->window)); } - if (choice & NOTIFY_TYPE) { - g_signal_connect_swapped(G_OBJECT(gtkconv->entry), "key-press-event", G_CALLBACK(un_star), G_OBJECT(gtkwin->window)); + if (notify_opts & OPT_NOTIFY_TYPE) { + g_signal_connect_swapped(G_OBJECT(gtkconv->entry), "key-press-event", G_CALLBACK(unnotify_cb), G_OBJECT(gtkwin->window)); } - g_object_set_data(G_OBJECT(gtkwin->window), "user_data", c); - g_object_set_data(G_OBJECT(gtkwin->window), "notify_data", GUINT_TO_POINTER(choice)); return 0; } -void detach_signals(GaimConversation *c) { +static void detach_signals(GaimConversation *c) { GaimGtkConversation *gtkconv; GaimGtkWindow *gtkwin; - guint options; gtkconv = GAIM_GTK_CONVERSATION(c); gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); - options = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(gtkwin->window), "notify_data")); - - if (options & NOTIFY_FOCUS) { - g_signal_handlers_disconnect_by_func(G_OBJECT(gtkwin->window), un_star, NULL); - } - if (options & NOTIFY_CLICK) { - g_signal_handlers_disconnect_by_func(G_OBJECT(gtkwin->window), un_star, NULL); - g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->imhtml), un_star, gtkwin->window); - g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry), un_star, gtkwin->window); + if (notify_opts & OPT_NOTIFY_FOCUS) { + g_signal_handlers_disconnect_by_func(G_OBJECT(gtkwin->window), unnotify_cb, NULL); } - if (options & NOTIFY_TYPE) { - g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry), un_star, gtkwin->window); + if (notify_opts & OPT_NOTIFY_CLICK) { + g_signal_handlers_disconnect_by_func(G_OBJECT(gtkwin->window), unnotify_cb, NULL); + g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->imhtml), unnotify_cb, gtkwin->window); + g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry), unnotify_cb, gtkwin->window); + } + + if (notify_opts & OPT_NOTIFY_TYPE) { + g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry), unnotify_cb, gtkwin->window); } } -void new_conv(char *who) { +static void new_conv(char *who) { GaimConversation *c = gaim_find_conversation(who); + GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); - if (c && (type & TYPE_IM)) + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTR, GINT_TO_POINTER((guint)0)); + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTRCNT, GINT_TO_POINTER((guint)0)); + + if (c && (notify_opts & OPT_TYPE_IM)) attach_signals(c); } -void chat_join(struct gaim_connection *gc, int id, char *room) { +static void chat_join(GaimConnection *gc, int id, char *room) { GaimConversation *c = gaim_find_chat(gc, id); + GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); - if (c && (type & TYPE_CHAT)) + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTR, GINT_TO_POINTER((guint)0)); + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTRCNT, GINT_TO_POINTER((guint)0)); + + if (c && (notify_opts & OPT_TYPE_CHAT)) attach_signals(c); } -int un_star(GtkWidget *widget, gpointer data) { - GaimConversation *c = g_object_get_data(G_OBJECT(widget), "user_data"); +static void string_add(GtkWidget *widget) { + GtkWindow *win = GTK_WINDOW(widget); + gchar newtitle[256]; + const gchar *curtitle = gtk_window_get_title(win); + guint opts = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), GDATASTR)); + + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "string_add(): opts=0x%04x\n", opts); + + if (opts & OPT_METHOD_STRING) + return; - if (method & METHOD_QUOTE) - quote_remove(widget); - if (method & METHOD_COUNT) - count_remove(widget); - if (method & METHOD_STRING) - string_remove(widget); - if (c && method & METHOD_URGENT) - urgent_remove(c); - return 0; + if (!strstr(curtitle, title_string)) { + if (opts & OPT_METHOD_COUNT) { + char *p = strchr(curtitle, ']'); + int len1; + if (!p) + return; + len1 = p-curtitle+2; + memcpy(newtitle, curtitle, len1); + strncpy(newtitle+len1, title_string, sizeof(newtitle)-len1); + strncpy(newtitle+len1+strlen(title_string), curtitle+len1, + sizeof(newtitle)-len1-strlen(title_string)); + } else if (opts & OPT_METHOD_QUOTE) { + g_snprintf(newtitle, sizeof(newtitle), "\"%s%s", title_string, curtitle+1); + } else { + g_snprintf(newtitle, sizeof(newtitle), "%s%s", title_string, curtitle); + } + gtk_window_set_title(win, newtitle); + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "added string to window title\n"); + } + + opts |= OPT_METHOD_STRING; + g_object_set_data(G_OBJECT(widget), GDATASTR, GINT_TO_POINTER(opts)); } -/* This function returns the number in [ ]'s or 0 - and sets *length to the number of digits in that number */ -int counter (char *buf, int *length) { - char temp[256]; - int i = 0; - int j = 0; - *length = 0; +static void string_remove(GtkWidget *widget) { + GtkWindow *win = GTK_WINDOW(widget); + gchar newtitle[256]; + const gchar *curtitle; + guint opts = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), GDATASTR)); - /* Don't assume buf[0]=='[' */ - while( buf[i++] != '[' && ititle, sizeof(buf)); - if (!strstr(buf, title_string)) { - g_snprintf(buf, sizeof(buf), "%s%s", title_string, win->title); - gtk_window_set_title(win, buf); - } -} - -gboolean string_remove(GtkWidget *widget) { - char buf[256]; - GtkWindow *win = GTK_WINDOW(widget); - - strncpy(buf, win->title, sizeof(buf)); - if (strstr(buf, title_string)) { - g_snprintf(buf, sizeof(buf), "%s", &win->title[strlen(title_string)]); - gtk_window_set_title(win, buf); - return TRUE; - } - return FALSE; + if (strstr(curtitle, title_string)) { + if (opts & OPT_METHOD_COUNT) { + char *p = strchr(curtitle, ']'); + int len1; + if (!p) + return; + len1 = p-curtitle+2; + memcpy(newtitle, curtitle, len1); + strncpy(newtitle+len1, curtitle+len1+strlen(title_string), sizeof(newtitle)-len1); + } else if (opts & OPT_METHOD_QUOTE) { + g_snprintf(newtitle, sizeof(newtitle), "\"%s", curtitle+strlen(title_string)+1); + } else + strncpy(newtitle, curtitle+strlen(title_string), sizeof(newtitle)); + } + + gtk_window_set_title(win, newtitle); + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "removed string from window title (title now %s)\n", newtitle); } -void count_add(GtkWidget *widget, int number) { - char buf[256]; - int c, length; +static void count_add(GtkWidget *widget) { GtkWindow *win = GTK_WINDOW(widget); + char newtitle[256]; + const gchar *curtitle; + guint opts = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), GDATASTR)); + gint curcount = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), GDATASTRCNT)); - strncpy(buf, win->title, sizeof(buf)); - c = counter(buf, &length); + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "count_add(): opts=0x%04x\n", opts); + + if (curcount>0 && (opts & OPT_METHOD_COUNT)) + count_remove(widget); - if (number) { - /* This might cause problems in the future. - I'm pretty sure if count_add is called after quote_add - and number!=0, then this will have problems dealing with - the quotation marks. */ - g_snprintf(buf, sizeof(buf), "[%d] %s", number, win->title); - } else if (!c) { - g_snprintf(buf, sizeof(buf), "[1] %s", win->title); - } else if (buf[0] == '[' || buf[1] == '[' ) { - /* This has to be so complicated in order to account for METHOD_QUOTE */ - g_snprintf(buf, sizeof(buf), "[%d] %s", c+1, &win->title[ ((method & METHOD_QUOTE) ? 4 : 3)+length ]); - if( buf[ strlen(buf)-1 ] == '"' ) - buf[ strlen(buf)-1 ] = '\0'; - } - gtk_window_set_title(win, buf); + curtitle = gtk_window_get_title(win); + if (opts & OPT_METHOD_QUOTE) + g_snprintf(newtitle, sizeof(newtitle), "\"[%d] %s", curcount, curtitle+1); + else + g_snprintf(newtitle, sizeof(newtitle), "[%d] %s", curcount, curtitle); + gtk_window_set_title(win, newtitle); + + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "added count of %d to window\n", curcount); + + opts |= OPT_METHOD_COUNT; + g_object_set_data(G_OBJECT(widget), GDATASTR, GINT_TO_POINTER(opts)); } -gboolean count_remove(GtkWidget *widget) { - char buf[256]; +static void count_remove(GtkWidget *widget) { GtkWindow *win = GTK_WINDOW(widget); - int length; + char newtitle[256], *p; + const gchar *curtitle; + guint opts = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), GDATASTR)); + + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "count_remove(): opts=0x%04x\n", opts); + + if (!(opts & OPT_METHOD_COUNT)) + return; + + curtitle = gtk_window_get_title(win); - strncpy(buf, win->title, sizeof(buf)); - if (buf[0] == '[') { - Number = counter(buf, &length); - g_snprintf(buf, sizeof(buf), "%s", &win->title[3+length]); - gtk_window_set_title(win, buf); - return TRUE; + p = strchr(curtitle, ']'); + + if (p) { + if (opts & OPT_METHOD_QUOTE) + g_snprintf(newtitle, sizeof(newtitle), "\"%s", p+2); + else + g_snprintf(newtitle, sizeof(newtitle), p+2); + gtk_window_set_title(win, newtitle); + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "removed count from title (title now %s)\n", newtitle); } - return FALSE; + + opts &= ~OPT_METHOD_COUNT; + g_object_set_data(G_OBJECT(widget), GDATASTR, GINT_TO_POINTER(opts)); } -void quote_add(GtkWidget *widget) { - char buf[256]; +static void quote_add(GtkWidget *widget) { GtkWindow *win = GTK_WINDOW(widget); + char newtitle[256]; + const gchar *curtitle = gtk_window_get_title(win); + guint opts = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), GDATASTR)); + + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "quote_add(): opts=0x%04x\n", opts); - strncpy(buf, win->title, sizeof(buf)); - if (buf[0] != '\"') { - g_snprintf(buf, sizeof(buf), "\"%s\"", win->title); - gtk_window_set_title(win, buf); + if (opts & OPT_METHOD_QUOTE) + return; + + if (*curtitle != '\"') { + g_snprintf(newtitle, sizeof(newtitle), "\"%s\"", curtitle); + gtk_window_set_title(win, newtitle); + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "quoted title\n"); } + + opts |= OPT_METHOD_QUOTE; + g_object_set_data(G_OBJECT(widget), GDATASTR, GINT_TO_POINTER(opts)); } -gboolean quote_remove(GtkWidget *widget) { - char buf[256]; +static void quote_remove(GtkWidget *widget) { GtkWindow *win = GTK_WINDOW(widget); + char newtitle[512]; + const gchar *curtitle = gtk_window_get_title(win); + guint opts = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), GDATASTR)); + + gaim_debug(GAIM_DEBUG_INFO, "notify.c", "quote_remove(): opts=0x%04x\n", opts); - strncpy(buf, win->title, sizeof(buf)); - if (buf[0] == '\"') { - g_snprintf(buf, strlen(buf) - 1, "%s", &win->title[1]); - gtk_window_set_title(win, buf); - return TRUE; - } - return FALSE; + if (!(opts & OPT_METHOD_QUOTE)) + return; + + if (*curtitle == '\"' && strlen(curtitle)-2window->window), GDK_WINDOW_XWINDOW(gtkwin->window->window)); + + if (hints->flags & XUrgencyHint) { + hints->flags &= ~XUrgencyHint; + XSetWMHints(GDK_WINDOW_XDISPLAY(gtkwin->window->window), GDK_WINDOW_XWINDOW(gtkwin->window->window), hints); + } + XFree(hints); + } else { if (gaim_conversation_get_type(c) == GAIM_CONV_CHAT) { GaimConversation *c = (GaimConversation *)gaim_get_chats()->data; GaimGtkWindow *gtkwin; @@ -389,11 +507,8 @@ if (hints->flags & XUrgencyHint) { hints->flags &= ~XUrgencyHint; XSetWMHints(GDK_WINDOW_XDISPLAY(gtkwin->window->window), GDK_WINDOW_XWINDOW(gtkwin->window->window), hints); - XFree(hints); - return TRUE; } XFree(hints); - return FALSE; } else { GaimConversation *c; GaimGtkWindow *gtkwin; @@ -408,156 +523,166 @@ if (hints->flags & XUrgencyHint) { hints->flags &= ~XUrgencyHint; XSetWMHints(GDK_WINDOW_XDISPLAY(gtkwin->window->window), GDK_WINDOW_XWINDOW(gtkwin->window->window), hints); - XFree(hints); - return TRUE; } XFree(hints); - return FALSE; } - } else { - GaimGtkWindow *gtkwin; - XWMHints *hints; - - gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); - hints = XGetWMHints(GDK_WINDOW_XDISPLAY(gtkwin->window->window), GDK_WINDOW_XWINDOW(gtkwin->window->window)); - - if (hints->flags & XUrgencyHint) { - hints->flags &= ~XUrgencyHint; - XSetWMHints(GDK_WINDOW_XDISPLAY(gtkwin->window->window), GDK_WINDOW_XWINDOW(gtkwin->window->window), hints); - XFree(hints); - return TRUE; - } - XFree(hints); - return FALSE; } } -void save_notify_prefs() { - gchar buf[1000]; - FILE *fp; +static void save_notify_prefs() { + gaim_prefs_set_bool("/plugins/gtk/X11/notify/notify_im", notify_opts & OPT_TYPE_IM); + gaim_prefs_set_bool("/plugins/gtk/X11/notify/notify_chat", notify_opts & OPT_TYPE_CHAT); + gaim_prefs_set_bool("/plugins/gtk/X11/notify/notify_in_focus", notify_opts & OPT_NOTIFY_IN_FOCUS); + gaim_prefs_set_bool("/plugins/gtk/X11/notify/notify_focus", notify_opts & OPT_NOTIFY_FOCUS); + gaim_prefs_set_bool("/plugins/gtk/X11/notify/notify_click", notify_opts & OPT_NOTIFY_CLICK); + gaim_prefs_set_bool("/plugins/gtk/X11/notify/notify_type", notify_opts & OPT_NOTIFY_TYPE); + gaim_prefs_set_bool("/plugins/gtk/X11/notify/method_string", notify_opts & OPT_METHOD_STRING); + gaim_prefs_set_bool("/plugins/gtk/X11/notify/method_quote", notify_opts & OPT_METHOD_QUOTE); + gaim_prefs_set_bool("/plugins/gtk/X11/notify/method_urgent", notify_opts & OPT_METHOD_URGENT); + gaim_prefs_set_bool("/plugins/gtk/X11/notify/method_count", notify_opts & OPT_METHOD_COUNT); - snprintf(buf, 1000, "%s/.gaim/.notify", getenv("HOME")); - if (!(fp = fopen(buf, "w"))) { - gaim_notify_error(my_plugin, NULL, - _("Unable to write to config file"), - _("Notify plugin")); - return; - } - - fprintf(fp, "%d=TYPE\n", type); - fprintf(fp, "%d=CHOICE\n", choice); - fprintf(fp, "%d=METHOD\n", method); - fprintf(fp, "%s=STRING\n", title_string); - fclose(fp); + gaim_prefs_set_string("/plugins/gtk/X11/notify/title_string", title_string); } -void load_notify_prefs() { - gchar buf[1000]; - gchar **parsed; - FILE *fp; - - g_snprintf(buf, sizeof(buf), "%s/.gaim/.notify", getenv("HOME")); - if (!(fp = fopen(buf, "r"))) - return; +static void load_notify_prefs() { + notify_opts = 0; + + notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_im") ? OPT_TYPE_IM : 0); + notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_chat") ? OPT_TYPE_CHAT : 0); + notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_in_focus") ? OPT_NOTIFY_IN_FOCUS : 0); + notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_focus") ? OPT_NOTIFY_FOCUS : 0); + notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_click") ? OPT_NOTIFY_CLICK : 0); + notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_type") ? OPT_NOTIFY_TYPE : 0); + notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_string") ? OPT_METHOD_STRING : 0); + notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_quote") ? OPT_METHOD_QUOTE : 0); + notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_urgent") ? OPT_METHOD_URGENT : 0); + notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_count") ? OPT_METHOD_COUNT : 0); - while (fgets(buf, 1000, fp) != NULL) { - parsed = g_strsplit(g_strchomp(buf), "=", 2); - if (parsed[0] && parsed[1]) { - if (!strcmp(parsed[1], "TYPE")) - type = atoi(parsed[0]); - if (!strcmp(parsed[1], "CHOICE")) - choice = atoi(parsed[0]); - if (!strcmp(parsed[1], "METHOD")) - method = atoi(parsed[0]); - if (!strcmp(parsed[1], "STRING")) { - if (title_string != NULL) - g_free(title_string); - title_string = g_strdup(parsed[0]); - } - } - g_strfreev(parsed); - } - fclose(fp); - return; + strncpy(title_string, gaim_prefs_get_string("/plugins/gtk/X11/notify/title_string"), TITLE_STR_BUFSIZE); } -void options(GtkWidget *widget, gpointer data) { +static void options_toggle_cb(GtkWidget *w, gpointer data) { gint option = GPOINTER_TO_INT(data); - if (option == 0) - choice ^= NOTIFY_FOCUS; - else if (option == 1) - choice ^= NOTIFY_CLICK; - else if (option == 2) - choice ^= NOTIFY_TYPE; - else if (option == 3) { - method ^= METHOD_STRING; - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) - gtk_widget_set_sensitive(Entry, TRUE); - else - gtk_widget_set_sensitive(Entry, FALSE); + notify_opts ^= option; + + /* save prefs and re-notify the windows */ + save_notify_prefs(); + apply_options(option); +} + +static gboolean options_settitle_cb(GtkWidget *w, GdkEventFocus *evt, GtkWidget *entry) { + GList *cnv = gaim_get_conversations(); + + /* first we have to kill all the old strings */ + while (cnv) { + GaimConversation *c = (GaimConversation *)cnv->data; + GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); + string_remove(gtkwin->window); + cnv = cnv->next; } - else if (option == 4) - method ^= METHOD_QUOTE; - else if (option == 5) - method ^= METHOD_URGENT; - else if (option == 6) - choice ^= NOTIFY_IN_FOCUS; - else if (option == 7) - method ^= METHOD_COUNT; - else if (option == 8) - type ^= TYPE_IM; - else if (option == 9) - type ^= TYPE_CHAT; - else if (option == 10) { - /* I made an option for this as at least a way to have it save correctly - * I'd much rather there were better ways, and I don't want to save this - * no matter which pref is changed, that's too much of a hack */ - if (title_string != NULL) { - g_free(title_string); - title_string = g_strdup(gtk_entry_get_text(GTK_ENTRY(Entry))); - } - } + + g_snprintf(title_string, sizeof(title_string), gtk_entry_get_text(GTK_ENTRY(entry))); + + /* save prefs and re-notify the windows */ + save_notify_prefs(); + apply_options(OPT_METHOD_STRING_CHNG); + + return FALSE; +} + +static void options_toggle_title_cb(GtkWidget *w, GtkWidget *entry) { + notify_opts ^= OPT_METHOD_STRING; + + if (notify_opts & OPT_METHOD_STRING) + gtk_widget_set_sensitive(entry, TRUE); + else + gtk_widget_set_sensitive(entry, FALSE); save_notify_prefs(); + apply_options(OPT_METHOD_STRING); } -void apply_options(GtkWidget *widget, gpointer data) { +static void apply_options(int opt_chng) { GList *cnv = gaim_get_conversations(); + /* option-setting handlers should have cleared out all window notifications */ + while (cnv) { - guint notification; - GaimConversation *c = (GaimConversation *) cnv->data; - GaimGtkConversation *gtkconv; - GaimGtkWindow *gtkwin; - guint options = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(c->window), "notify_data")); + GaimConversation *c = (GaimConversation *)cnv->data; + GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); + guint opts = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkwin->window), GDATASTR)); - gtkconv = GAIM_GTK_CONVERSATION(c); - gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); - - if (options & NOTIFY_FOCUS) - g_signal_handlers_disconnect_by_func(G_OBJECT(gtkwin->window), un_star, NULL); - - /* remove old notification signals */ + /* kill signals */ detach_signals(c); - /* clean off all notification markings */ - notification = unnotify(c, TRUE); - - /* re-add appropriate notification methods cleaned above */ - if (notification & METHOD_STRING) /* re-add string */ - string_add(gtkwin->window); - if (notification & METHOD_QUOTE) /* re-add quote */ - quote_add(gtkwin->window); - if (notification & METHOD_COUNT) /* re-add count */ - count_add(gtkwin->window, Number); - if (notification & METHOD_URGENT) /* re-add urgent */ - urgent_add(c); + /* + * do a full notify if the option that changed was an OPT_TYPE_* + * either notify if it was enabled, or unnotify if it was disabled + */ + if (opt_chng==OPT_TYPE_IM || opt_chng==OPT_TYPE_CHAT) { + if ((gaim_conversation_get_type(c)==GAIM_CONV_IM && (notify_opts & OPT_TYPE_IM)) || + (gaim_conversation_get_type(c)==GAIM_CONV_CHAT && (notify_opts & OPT_TYPE_CHAT))) { + Window focus_return; + int revert_to_return; + + XGetInputFocus(GDK_WINDOW_XDISPLAY(gtkwin->window->window), + &focus_return, &revert_to_return); + if ((notify_opts & OPT_NOTIFY_IN_FOCUS) || + focus_return != GDK_WINDOW_XWINDOW(gtkwin->window->window)) { + if (notify_opts & OPT_METHOD_STRING) + string_add(gtkwin->window); + if (notify_opts & OPT_METHOD_COUNT) + count_add(gtkwin->window); + if (notify_opts & OPT_METHOD_QUOTE) + quote_add(gtkwin->window); + if (notify_opts & OPT_METHOD_URGENT) + urgent_add(c); + } + } else { + //don't simply call unnotify(), because that will kill the msg counter + urgent_remove(c); + quote_remove(gtkwin->window); + count_remove(gtkwin->window); + string_remove(gtkwin->window); + } + } else if (opts & STATE_IS_NOTIFIED) { + //add/remove the status that was changed + switch(opt_chng) { + case OPT_METHOD_COUNT: + if (notify_opts & OPT_METHOD_COUNT) + count_add(gtkwin->window); + else + count_remove(gtkwin->window); + break; + case OPT_METHOD_QUOTE: + if (notify_opts & OPT_METHOD_QUOTE) + quote_add(gtkwin->window); + else + quote_remove(gtkwin->window); + break; + case OPT_METHOD_STRING: + if (notify_opts & OPT_METHOD_STRING) + string_add(gtkwin->window); + else + string_remove(gtkwin->window); + break; + case OPT_METHOD_URGENT: + if (notify_opts & OPT_METHOD_URGENT) + urgent_add(c); + else + urgent_remove(c); + break; + case OPT_METHOD_STRING_CHNG: + string_add(gtkwin->window); + break; + } + } /* attach new unnotification signals */ - attach_signals(c); + attach_signals(c); - cnv = cnv->next; + cnv = cnv->next; } } @@ -565,86 +690,96 @@ get_config_frame(GaimPlugin *plugin) { GtkWidget *ret; + GtkWidget *frame; GtkWidget *vbox, *hbox; - GtkWidget *toggle, *button; + GtkWidget *toggle, *entry; + ret = gtk_vbox_new(FALSE, 18); - gtk_container_set_border_width (GTK_CONTAINER (ret), 12); + gtk_container_set_border_width(GTK_CONTAINER (ret), 12); - vbox = gaim_gtk_make_frame(ret, _("Notify For")); + /*---------- "Notify For" ----------*/ + frame = gaim_gtk_make_frame(ret, _("Notify For")); + vbox = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(frame), vbox); + toggle = gtk_check_button_new_with_mnemonic(_("_IM windows")); gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), type & TYPE_IM); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options), GINT_TO_POINTER(8)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), notify_opts & OPT_TYPE_IM); + g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options_toggle_cb), GINT_TO_POINTER(OPT_TYPE_IM)); toggle = gtk_check_button_new_with_mnemonic(_("_Chat windows")); gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), type & TYPE_CHAT); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options), GINT_TO_POINTER(9)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), notify_opts & OPT_TYPE_CHAT); + g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options_toggle_cb), GINT_TO_POINTER(OPT_TYPE_CHAT)); - /*--------------*/ - vbox = gaim_gtk_make_frame(ret, _("Notification Methods")); + /*---------- "Notification Methods" ----------*/ + frame = gaim_gtk_make_frame(ret, _("Notification Methods")); + vbox = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(frame), vbox); + hbox = gtk_hbox_new(FALSE, 18); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - toggle = gtk_check_button_new_with_mnemonic(_("Prepend _string into window title (hit enter to save):")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), method & METHOD_STRING); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options), GINT_TO_POINTER(3)); + toggle = gtk_check_button_new_with_mnemonic(_("Prepend _string into window title:")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), notify_opts & OPT_METHOD_STRING); gtk_box_pack_start(GTK_BOX(hbox), toggle, FALSE, FALSE, 0); - Entry = gtk_entry_new(); - gtk_entry_set_max_length(GTK_ENTRY(Entry), 10); - gtk_widget_set_sensitive(GTK_WIDGET(Entry), method & METHOD_STRING); - gtk_box_pack_start(GTK_BOX(hbox), Entry, FALSE, FALSE, 0); - gtk_entry_set_text(GTK_ENTRY(Entry), title_string); - g_signal_connect(G_OBJECT(Entry), "activate", G_CALLBACK(options), GINT_TO_POINTER(10)); + entry = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0); + gtk_entry_set_max_length(GTK_ENTRY(entry), 10); + gtk_widget_set_sensitive(GTK_WIDGET(entry), notify_opts & OPT_METHOD_STRING); + gtk_entry_set_text(GTK_ENTRY(entry), title_string); + g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options_toggle_title_cb), entry); + g_signal_connect(G_OBJECT(entry), "focus-out-event", G_CALLBACK(options_settitle_cb), entry); - toggle = gtk_check_button_new_with_mnemonic(_("_Quote window title")); - gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), method & METHOD_QUOTE); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options), GINT_TO_POINTER(4)); + toggle = gtk_check_button_new_with_mnemonic(_("_Quote window title")); + gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), notify_opts & OPT_METHOD_QUOTE); + g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options_toggle_cb), GINT_TO_POINTER(OPT_METHOD_QUOTE)); - toggle = gtk_check_button_new_with_mnemonic(_("Set Window Manager \"_URGENT\" Hint")); - gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), method & METHOD_URGENT); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options), GINT_TO_POINTER(5)); + toggle = gtk_check_button_new_with_mnemonic(_("Set Window Manager \"_URGENT\" Hint")); + gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), notify_opts & OPT_METHOD_URGENT); + g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options_toggle_cb), GINT_TO_POINTER(OPT_METHOD_URGENT)); - toggle = gtk_check_button_new_with_mnemonic(_("Insert c_ount of new messages into window title")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), method & METHOD_COUNT); - gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options), GINT_TO_POINTER(7)); + toggle = gtk_check_button_new_with_mnemonic(_("Insert c_ount of new messages into window title")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), notify_opts & OPT_METHOD_COUNT); + gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options_toggle_cb), GINT_TO_POINTER(OPT_METHOD_COUNT)); - toggle = gtk_check_button_new_with_mnemonic(_("_Notify even if conversation is in focus")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), choice & NOTIFY_IN_FOCUS); - gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options), GINT_TO_POINTER(6)); + toggle = gtk_check_button_new_with_mnemonic(_("_Notify even if conversation is in focus")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), notify_opts & OPT_NOTIFY_IN_FOCUS); + gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options_toggle_cb), GINT_TO_POINTER(OPT_NOTIFY_IN_FOCUS)); - /*--------------*/ - vbox = gaim_gtk_make_frame(ret, _("Notification Removal")); - toggle = gtk_check_button_new_with_mnemonic(_("Remove when conversation window gains _focus")); - gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), choice & NOTIFY_FOCUS); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options), GINT_TO_POINTER(0)); + /*---------- "Notification Methods" ----------*/ + frame = gaim_gtk_make_frame(ret, _("Notification Removal")); + vbox = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(frame), vbox); - toggle = gtk_check_button_new_with_mnemonic(_("Remove when conversation window _receives click")); - gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), choice & NOTIFY_CLICK); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options), GINT_TO_POINTER(1)); + toggle = gtk_check_button_new_with_mnemonic(_("Remove when conversation window gains _focus")); + gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), notify_opts & OPT_NOTIFY_FOCUS); + g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options_toggle_cb), GINT_TO_POINTER(OPT_NOTIFY_FOCUS)); - toggle = gtk_check_button_new_with_mnemonic(_("Remove when _typing in conversation window")); - gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), choice & NOTIFY_TYPE); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options), GINT_TO_POINTER(2)); + toggle = gtk_check_button_new_with_mnemonic(_("Remove when conversation window _receives click")); + gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), notify_opts & OPT_NOTIFY_CLICK); + g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options_toggle_cb), GINT_TO_POINTER(OPT_NOTIFY_CLICK)); - button = gtk_button_new_with_mnemonic(_("Appl_y")); - gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 5); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(apply_options), NULL); + toggle = gtk_check_button_new_with_mnemonic(_("Remove when _typing in conversation window")); + gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), notify_opts & OPT_NOTIFY_TYPE); + g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(options_toggle_cb), GINT_TO_POINTER(OPT_NOTIFY_TYPE)); - gtk_widget_show_all(ret); - return ret; + gtk_widget_show_all(ret); + return ret; } static gboolean plugin_load(GaimPlugin *plugin) { - title_string = g_strdup("(*) "); + GList *cnv = gaim_get_conversations(); + + my_plugin = plugin; load_notify_prefs(); @@ -655,28 +790,39 @@ gaim_signal_connect(plugin, event_new_conversation, new_conv, NULL); gaim_signal_connect(plugin, event_chat_join, chat_join, NULL); + while (cnv) { + GaimConversation *c = (GaimConversation *)cnv->data; + GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); + + /* attach signals */ + attach_signals(c); + /* zero out data */ + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTR, GINT_TO_POINTER((guint)0)); + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTRCNT, GINT_TO_POINTER((guint)0)); + + cnv = cnv->next; + } + return TRUE; } static gboolean plugin_unload(GaimPlugin *plugin) { - GList *c = gaim_get_conversations(); + GList *cnv = gaim_get_conversations(); - while (c) { - GaimConversation *cnv = (GaimConversation *)c->data; - GaimGtkWindow *gtkwin; - - gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(cnv)); + while (cnv) { + GaimConversation *c = (GaimConversation *)cnv->data; + GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(gaim_conversation_get_window(c)); - detach_signals(cnv); - un_star(gtkwin->window, NULL); + /* kill signals */ + detach_signals(c); + /* zero out data */ + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTR, GINT_TO_POINTER((guint)0)); + g_object_set_data(G_OBJECT(gtkwin->window), GDATASTRCNT, GINT_TO_POINTER((guint)0)); - c = c->next; + cnv = cnv->next; } - - /* this might be a hack I'm not sure, I don't think so but... */ - g_free(title_string); return TRUE; } @@ -702,7 +848,8 @@ N_("Provides a variety of ways of notifying you of unread messages."), /** description */ N_("Provides a variety of ways of notifying you of unread messages."), - "Etan Reisner ", /**< author */ + "Etan Reisner \n\t\t\tBrian Tarricone * Some code copyright (C) 1998-1999, Mark Spencer - * Some code copyright (C) 2001-2003, Mark Doliner + * Some code copyright (C) 1999-2001, Eric Warmenhoven + * Some code copyright (C) 2001-2003, Sean Egan + * Some code copyright (C) 2001-2003, Mark Doliner + * + * Most libfaim code copyright (C) 1998-2001 Adam Fritzler + * Some libfaim code copyright (C) 2001-2003 Mark Doliner * * 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