changeset 3392:5a5df7968b6e

[gaim-migrate @ 3411] Another notify.c fix from deryni. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Sun, 11 Aug 2002 06:43:23 +0000
parents 412d1035d666
children 2a34734f6a0d
files plugins/notify.c
diffstat 1 files changed, 182 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/notify.c	Sun Aug 11 06:42:17 2002 +0000
+++ b/plugins/notify.c	Sun Aug 11 06:43:23 2002 +0000
@@ -1,8 +1,15 @@
-/* Reworked by Etan Reisner
+/* Rewritten by Etan Reisner <deryni@eden.rutgers.edu>
  *
  * Added config dialog
  * Added control over notification method
  * Added control over when to release notification
+ *
+ * Thanks to Carles Pina i Estany <carles@pinux.info>
+ *   for count of new messages option
+ */
+
+/* if my flash messages patch gets merged in can use cnv->local
+ * to notify on new messages also
  */
 
 #define GAIM_PLUGINS
@@ -12,29 +19,37 @@
 #include <string.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
-#include <X11/Xatom.h>	
+#include <X11/Xatom.h>
 #include <gdk/gdkx.h>
 
-guint choice;
-#define REMOVE_FOCUS	0x00000001
-#define REMOVE_TYPE		0x00000002
+guint choice = 1;
+#define NOTIFY_FOCUS		0x00000001
+#define NOTIFY_TYPE			0x00000002
+#define NOTIFY_IN_FOCUS	0x00000004
 
-guint method;
-#define METHOD_STRING	0x00000001
-#define METHOD_QUOTE	0x00000002
-#define METHOD_URGENT	0x00000004
+guint method = 1;
+#define METHOD_STRING		0x00000001
+#define METHOD_QUOTE		0x00000002
+#define METHOD_URGENT		0x00000004
+#define METHOD_COUNT		0x00000008
 
 void *handle;
+/* I really don't like this but I was having trouble getting any
+ * other way of removing the signal callbacks to work and not crash gaim
+ */
+GtkWidget *really_evil_hack;
+/*  GHashTable *hash = NULL; */
 GtkWidget *Dialog = NULL;
-GtkWidget *Click, *Focus, *Type;
-GtkWidget *String, *Quote, *Urgent, *Entry;
-gchar *title_string;
+GtkWidget *Click, *Focus, *Type, *InFocus;
+GtkWidget *String, *Count, *Quote, *Urgent, *Entry;
+gchar *title_string = "(*) ";
 
 /* predefine some functions, less warnings */
 void options(GtkWidget *widget, gpointer data);
 void un_star(GtkWidget *widget, gpointer data);
 void un_star_window(GtkWidget *widget, gpointer data);
 void string_remove(GtkWidget *widget);
+void count_remove(GtkWidget *widget);
 void quote_remove(GtkWidget *widget);
 void urgent_remove(struct conversation *c);
 
@@ -45,6 +60,7 @@
 	char *me = g_strdup(normalize(gc->username));
 	int revert_to_return;
 	Window focus_return;
+	int c, length;
 
 	if (!strcmp(me, normalize(*who))) {
 		g_free(me);
@@ -64,23 +80,36 @@
 
 	XGetInputFocus(GDK_WINDOW_XDISPLAY(cnv->window->window), &focus_return, &revert_to_return);
 
-	if (focus_return != GDK_WINDOW_XWINDOW(cnv->window->window)) {
+	if ((choice & NOTIFY_IN_FOCUS) || focus_return != GDK_WINDOW_XWINDOW(cnv->window->window)) {
 		if (method & METHOD_STRING) {
-			g_snprintf(buf, sizeof(buf), "%s", win->title);
+			strncpy(buf, win->title, sizeof(buf));
 			if (!strstr(buf, title_string)) {
-				g_snprintf(buf, sizeof(buf), "%s %s", title_string, win->title);
+				g_snprintf(buf, sizeof(buf), "%s%s", title_string, win->title);
 				gtk_window_set_title(win, buf);
 			}
 		}
+		if (method & METHOD_COUNT) {
+			strncpy(buf, win->title, sizeof(buf));
+			c = counter(buf, &length);
+			if (!c) {
+				g_snprintf(buf, sizeof(buf), "[1] %s", win->title);
+			}
+			else if (!g_strncasecmp(buf, "[", 1)) {
+				g_snprintf(buf, sizeof(buf), "[%d] %s", c+1, &win->title[3+length]);
+			}
+			gtk_window_set_title(win, buf);
+		}
 		if (method & METHOD_QUOTE) {
-			g_snprintf(buf, sizeof(buf), "%s", win->title);
+			strncpy(buf, win->title, sizeof(buf));
 			if (g_strncasecmp(buf, "\"", 1)) {
 				g_snprintf(buf, sizeof(buf), "\"%s\"", win->title);
 				gtk_window_set_title(win, buf);
 			}
 		}
 		if (method & METHOD_URGENT) {
-		/* do it the gdk way for windows compatibility(?) if I can figure it out */
+			/* do it the gdk way for windows compatibility(?) if I can figure it out */
+			/* Sean says this is a bad thing, and I should try using gtk_property_get first */
+			/* I'll want to pay attention to note on dev.gnome.org though */
 /*  		gdk_property_change(win->window, WM_HINTS, WM_HINTS, 32, GDK_PROP_MODE_REPLACE, XUrgencyHint, 1); */
 			XWMHints *hints = XGetWMHints(GDK_WINDOW_XDISPLAY(cnv->window->window), GDK_WINDOW_XWINDOW(cnv->window->window));
 			hints->flags |= XUrgencyHint;
@@ -96,9 +125,11 @@
 	struct conversation *c = find_conversation(who);
 
 	if (method & METHOD_QUOTE)
-		string_remove(c->window);
+		quote_remove(c->window);
+	if (method & METHOD_COUNT)
+		count_remove(c->window);
 	if (method & METHOD_STRING)
-		quote_remove(c->window);
+		string_remove(c->window);
 	if (method & METHOD_URGENT)
 		urgent_remove(c);
 	return 0;
@@ -107,34 +138,34 @@
 int new_conv(char *who) {
 	struct conversation *c = find_conversation(who);
 
-	if (choice & REMOVE_FOCUS) {
-		gtk_signal_connect(GTK_OBJECT(c->window), "focus-in-event", GTK_SIGNAL_FUNC(un_star), NULL);
+/*  	g_hash_table_insert(hash, who, GINT_TO_POINTER(choice)); */
+
+	if (choice & NOTIFY_FOCUS) {
+		gtk_signal_connect_while_alive(GTK_OBJECT(c->window), "focus-in-event", GTK_SIGNAL_FUNC(un_star), NULL, GTK_OBJECT(really_evil_hack));
 		gtk_object_set_user_data(GTK_OBJECT(c->window), c);
 	}
 	else {
-		gtk_signal_connect(GTK_OBJECT(c->window), "button_press_event", GTK_SIGNAL_FUNC(un_star), NULL);
+		gtk_signal_connect_while_alive(GTK_OBJECT(c->window), "button_press_event", GTK_SIGNAL_FUNC(un_star), NULL, GTK_OBJECT(really_evil_hack));
 		gtk_object_set_user_data(GTK_OBJECT(c->window), c);
-		gtk_signal_connect(GTK_OBJECT(c->text), "button_press_event", GTK_SIGNAL_FUNC(un_star_window), NULL);
+		gtk_signal_connect_while_alive(GTK_OBJECT(c->text), "button_press_event", GTK_SIGNAL_FUNC(un_star_window), NULL, GTK_OBJECT(really_evil_hack));
 		gtk_object_set_user_data(GTK_OBJECT(c->text), c);
-		gtk_signal_connect(GTK_OBJECT(c->entry), "button_press_event", GTK_SIGNAL_FUNC(un_star_window), NULL);
+		gtk_signal_connect_while_alive(GTK_OBJECT(c->entry), "button_press_event", GTK_SIGNAL_FUNC(un_star_window), NULL, GTK_OBJECT(really_evil_hack));
 		gtk_object_set_user_data(GTK_OBJECT(c->entry), c);
-/*  		gtk_signal_connect(GTK_OBJECT(c->text), "button_press_event", GTK_SIGNAL_FUNC(un_star_window), c); */
-/*  		gtk_signal_connect(GTK_OBJECT(c->entry), "button_press_event", GTK_SIGNAL_FUNC(un_star_window), c); */
 	}
 
-	if (choice & REMOVE_TYPE) {
-		gtk_signal_connect(GTK_OBJECT(c->entry), "key-press-event", GTK_SIGNAL_FUNC(un_star_window), NULL);
+	if (choice & NOTIFY_TYPE) {
+		gtk_signal_connect_while_alive(GTK_OBJECT(c->entry), "key-press-event", GTK_SIGNAL_FUNC(un_star_window), NULL, GTK_OBJECT(really_evil_hack));
 		gtk_object_set_user_data(GTK_OBJECT(c->entry), (gpointer) c);
-/*  		gtk_signal_connect(GTK_OBJECT(c->entry), "key-press-event", GTK_SIGNAL_FUNC(un_star_window), c); */
 	}
 }
 
 void un_star(GtkWidget *widget, gpointer data) {
 	struct conversation *c = gtk_object_get_user_data(GTK_OBJECT(widget));
-/*  	struct conversation *c = data; */
 
 	if (method & METHOD_QUOTE)
 		quote_remove(widget);
+	if (method & METHOD_COUNT)
+		count_remove(widget);
 	if (method & METHOD_STRING)
 		string_remove(widget);
 	if (method & METHOD_URGENT)
@@ -148,11 +179,35 @@
 	un_star(parent, data);
 }
 
+/* This function returns the number in [ ]'s or 0 */
+int counter (char *buf, int *length) {
+	char temp[256];
+	int i = 1;
+	*length = 0;
+
+/*  	if (buf[0] != '[') */
+/*  		return (0); */
+
+	while (isdigit(buf[i]) && i<sizeof(buf)) {
+		temp[i-1] = buf[i];
+		(*length)++;
+		i++;
+	}
+	temp[i] = '\0';
+	
+	if (buf[i] != ']') {
+		*length = 0;
+		return (0);
+	}
+
+	return (atoi(temp));
+}
+
 void string_remove(GtkWidget *widget) {
 	char buf[256];
 	GtkWindow *win = GTK_WINDOW(widget);
 
-	g_snprintf(buf, sizeof(buf), "%s", win->title);
+	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);
@@ -160,11 +215,25 @@
 	return;
 }
 
+void count_remove(GtkWidget *widget) {
+	char buf[256];
+	GtkWindow *win = GTK_WINDOW(widget);
+	int length;
+
+	strncpy(buf, win->title, sizeof(buf));
+	if (!g_strncasecmp(buf, "[", 1)) {
+		counter(buf, &length);
+		g_snprintf(buf, sizeof(buf), "%s", &win->title[3+length]);
+		gtk_window_set_title(win, buf);
+	}
+	return;
+}
+
 void quote_remove(GtkWidget *widget) {
 	char buf[256];
 	GtkWindow *win = GTK_WINDOW(widget);
 
-	g_snprintf(buf, sizeof(buf), "%s", win->title);
+	strncpy(buf, win->title, sizeof(buf));
 	if (!g_strncasecmp(buf, "\"", 1)) {
 		g_snprintf(buf, strlen(buf) - 1, "%s", &win->title[1]);
 		gtk_window_set_title(win, buf);
@@ -183,20 +252,18 @@
 }
 
 void save_notify_prefs() {
-	char *buf;
+	gchar buf[1000];
 	FILE *fp;
 
-	buf = malloc(1000);
 	snprintf(buf, 1000, "%s/.gaim/.notify", getenv("HOME"));
 	if (!(fp = fopen(buf, "w"))) {
 		do_error_dialog(_("Unable to write to config file"), _("Notify plugin"));
 		return;
 	}
-	free(buf);
 
-	fprintf(fp, "CHOICE=%d\n", choice);
-	fprintf(fp, "METHOD=%d\n", method);
-	fprintf(fp, "STRING=%s\n", title_string);
+	fprintf(fp, "%d=CHOICE\n", choice);
+	fprintf(fp, "%d=METHOD\n", method);
+	fprintf(fp, "%s=STRING\n", title_string);
 	fclose(fp);
 }
 
@@ -212,13 +279,15 @@
 	while (fgets(buf, 1000, fp) != NULL) {
 		parsed = g_strsplit(g_strchomp(buf), "=", 2);
 		if (parsed[0] && parsed[1]) {
-			if (!strcmp(parsed[0], "CHOICE"))
-				choice = atoi(parsed[1]);
-			if (!strcmp(parsed[0], "METHOD"))
-				method = atoi(parsed[1]);
-			if (!strcmp(parsed[0], "STRING"))
-				title_string = parsed[1];
+			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;
@@ -228,9 +297,9 @@
 	gint option = GPOINTER_TO_INT(data);
 
 	if (option == 0)
-		choice ^= REMOVE_FOCUS;
+		choice ^= NOTIFY_FOCUS;
 	else if (option == 1)
-		choice ^= REMOVE_TYPE;
+		choice ^= NOTIFY_TYPE;
 	else if (option == 2) {
 		method ^= METHOD_STRING;
 		if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
@@ -242,14 +311,18 @@
 		method ^= METHOD_QUOTE;
 	else if (option == 4)
 		method ^= METHOD_URGENT;
+	else if (option == 5)
+		choice ^= NOTIFY_IN_FOCUS;
+	else if (option == 6)
+		method ^= METHOD_COUNT;
 }
 
 void setup_buttons() {
-	if (choice & REMOVE_FOCUS)
+	if (choice & NOTIFY_FOCUS)
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Focus), TRUE);
 	else
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Click), TRUE);
-	if (choice & REMOVE_TYPE)
+	if (choice & NOTIFY_TYPE)
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Type), TRUE);
 	else
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Type), FALSE);
@@ -265,6 +338,12 @@
 	if (method & METHOD_URGENT)
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Urgent), TRUE);
 
+	if (choice & NOTIFY_IN_FOCUS)
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(InFocus), TRUE);
+
+	if (method & METHOD_COUNT)
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Count), TRUE);
+
 	return;
 }
 
@@ -286,6 +365,9 @@
 char *gaim_plugin_init(GModule *hndl) {
 	handle = hndl;
 
+	really_evil_hack = gtk_label_new("");
+/*  	hash = g_hash_table_new(g_str_hash, g_int_equal); */
+
 	load_notify_prefs();
 
 	gaim_signal_connect(handle, event_im_recv, received_im, NULL);
@@ -295,6 +377,30 @@
 	return NULL;
 }
 
+void gaim_plugin_remove() {
+	GList *c = conversations;
+	guint options;
+
+	gtk_widget_destroy(really_evil_hack);
+
+	while (c) {
+		struct conversation *cnv = (struct conversation *)c->data;
+/*  		if (options = GPOINTER_TO_INT(g_hash_table_lookup(hash, cnv->name))) { */
+			un_star(cnv->window, NULL);
+/*  			if (options & REMOVE_FOCUS) */
+/*  				gtk_signal_disconnect_by_func(GTK_OBJECT(cnv->window), GTK_SIGNAL_FUNC(un_star), NULL); */
+/*  			else { */
+/*  				gtk_signal_disconnect_by_func(GTK_OBJECT(cnv->window), GTK_SIGNAL_FUNC(un_star), NULL); */
+/*  				gtk_signal_disconnect_by_func(GTK_OBJECT(cnv->text), GTK_SIGNAL_FUNC(un_star_window), NULL); */
+/*  				gtk_signal_disconnect_by_func(GTK_OBJECT(cnv->entry), GTK_SIGNAL_FUNC(un_star_window), NULL); */
+/*  			} */
+/*  			if (options & REMOVE_TYPE) */
+/*  				gtk_signal_disconnect_by_func(GTK_OBJECT(cnv->entry), GTK_SIGNAL_FUNC(un_star_window), NULL); */
+/*  		} */
+			c = c->next;
+	}
+}
+
 char *name() {
 	return "Visual Notification";
 }
@@ -307,14 +413,13 @@
 void gaim_plugin_config() {
 	GtkWidget *dialog_vbox;
 	GtkWidget *button, *label;
-	GtkWidget *box, *box2, *box3, *frame;
+	GtkWidget *box, *box2, *box3, *box4, *frame;
 
 	if (Dialog)
 		return;
 
 	/* main config dialog */
 	Dialog = gtk_dialog_new();
-/*  	gtk_widget_set_usize(Dialog, 275, -1); */
 	gtk_window_set_title(GTK_WINDOW(Dialog), "Notify plugin configuration");
 	gtk_window_set_policy(GTK_WINDOW(Dialog), FALSE, FALSE, TRUE);
 	gtk_signal_connect(GTK_OBJECT(Dialog), "destroy", GTK_SIGNAL_FUNC(close_dialog), GINT_TO_POINTER(-1));
@@ -335,13 +440,20 @@
   gtk_widget_set_usize(button, 80, -2);
   gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(close_dialog), GINT_TO_POINTER(1));
 
+	/* warning label */
+	label = gtk_label_new(_("Changes in notification removal options take effect only on new conversation windows"));
+	gtk_box_pack_start(GTK_BOX(dialog_vbox), label, FALSE, FALSE, 1);
+
 	/* main hbox */
 	box = gtk_hbox_new(FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(dialog_vbox), box, FALSE, FALSE, 0);
 
+	box4 = gtk_vbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(box), box4, FALSE, FALSE, 0);
+
 	/* un-notify choices */
 	frame = gtk_frame_new(_("Remove notification when:"));
-	gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(box4), frame, FALSE, FALSE, 0);
 
 	box2 = gtk_vbox_new(FALSE, 0);
 	gtk_container_add(GTK_CONTAINER(frame), box2);
@@ -371,10 +483,7 @@
 
 	Entry = gtk_entry_new_with_max_length(7);
 	gtk_box_pack_start(GTK_BOX(box3), Entry, FALSE, FALSE, 0);
-	if (!title_string)
-		gtk_entry_set_text(GTK_ENTRY(Entry), "(*) ");
-	else
-		gtk_entry_set_text(GTK_ENTRY(Entry), title_string);
+	gtk_entry_set_text(GTK_ENTRY(Entry), title_string);
 
 	Quote = gtk_check_button_new_with_label(_("Quote window title."));
 	gtk_box_pack_start(GTK_BOX(box2), Quote, FALSE, FALSE, 0);
@@ -382,6 +491,22 @@
 	Urgent = gtk_check_button_new_with_label(_("Send URGENT to window manager."));
 	gtk_box_pack_start(GTK_BOX(box2), Urgent, FALSE, FALSE, 0);
 
+	label = gtk_label_new(_("Function oddly with tabs:"));
+	gtk_box_pack_start(GTK_BOX(box2), label, FALSE, FALSE, 0);
+
+	Count = gtk_check_button_new_with_label(_("Insert count of new messages into window title"));
+	gtk_box_pack_start(GTK_BOX(box2), Count, FALSE, FALSE, 0);
+
+	/* general options */
+	frame = gtk_frame_new(_("General Options"));
+	gtk_box_pack_start(GTK_BOX(box4), frame, FALSE, FALSE, 0);
+
+	box = gtk_vbox_new(FALSE, 0);
+	gtk_container_add(GTK_CONTAINER(frame), box);
+
+	InFocus = gtk_check_button_new_with_label(_("Notify even when window is in focus"));
+	gtk_box_pack_start(GTK_BOX(box), InFocus, FALSE, FALSE, 0);
+
 	/* setup buttons, then attach signals */
 	setup_buttons();
 	gtk_signal_connect(GTK_OBJECT(Focus), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(0));
@@ -389,6 +514,8 @@
 	gtk_signal_connect(GTK_OBJECT(String), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(2));
 	gtk_signal_connect(GTK_OBJECT(Quote), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(3));
 	gtk_signal_connect(GTK_OBJECT(Urgent), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(4));
+	gtk_signal_connect(GTK_OBJECT(InFocus), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(5));
+	gtk_signal_connect(GTK_OBJECT(Count), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(6));
 
 	gtk_widget_show_all(Dialog);
 }