changeset 12694:ebed1bbedb04

[gaim-migrate @ 15037] SF Patch #1386297 from Lucio Maciel "Add per pounce options, to pounce only when away/not available. Add pounce when receive a new im message (received-im-msg signal) Fix (pounce != GAIM_POUNCE_NONE) in gaim_pounce_set_events()" I changed this patch so that you can't create a pounce that sends an IM in response to receiving an IM. Auto-reply is messy. I also cleaned up some little things that were bothering me in the pounce dialog. committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Tue, 03 Jan 2006 11:42:51 +0000
parents 07d6cc1b5a98
children 0bc110c7ab91
files COPYRIGHT plugins/ChangeLog.API src/gtkpounce.c src/pounce.c src/pounce.h
diffstat 5 files changed, 218 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Tue Jan 03 09:05:14 2006 +0000
+++ b/COPYRIGHT	Tue Jan 03 11:42:51 2006 +0000
@@ -146,6 +146,7 @@
 Uli Luckas
 Matthew Luckie
 Mike Lundy
+Lucio Maciel
 Brian Macke
 Paolo Maggi
 Willian T. Mahan
--- a/plugins/ChangeLog.API	Tue Jan 03 09:05:14 2006 +0000
+++ b/plugins/ChangeLog.API	Tue Jan 03 11:42:51 2006 +0000
@@ -84,6 +84,7 @@
 	* GaimPluginProtocolInfo: Added offline_message
 	* GaimPluginProtocolInfo: Added whiteboard_prpl_ops
 	* GaimPluginProtocolInfo: Added media_prpl_ops
+	* gaim_pounce_new(): Added option argument for pounce options
 
 	Removed:
 	* gaim_gtk_sound_{get,set}_mute() (replaced by the /gaim/gtk/sound/mute
@@ -129,7 +130,6 @@
 	* GaimConvImFlags and GaimConvChatFlags; use GaimMessageFlags instead
 	* cb and user_data from the ops in GaimNotifyUiOps: This is now handled
 	  by the notify API in the core.
-	* conversation-switching signal has been removed.
 
 	Added:
 	* gaim_prefs_disconnect_by_handle()
@@ -190,6 +190,10 @@
 	* gaim_gtk_pounces_manager_show()
 	* gaim_gtk_pounces_manager_hide()
 	* gaim_gtk_pounce_editor_show()
+	* GAIM_POUNCE_MESSAGE_RECEIVED
+	* GaimPounceOption
+	* gaim_pounce_set_options()
+	* gaim_pounce_set_options()
 	* GAIM_STOCK_CONNECT, GAIM_STOCK_DISCONNECT
 	* GAIM_STOCK_PLUGIN
 	* gaim_account_request_add: Notifies the user that they were added to
@@ -259,6 +263,7 @@
 	* "buddy-unidle": replaced by buddy-idle-changed
 	* "buddy-icon-cached": replaced by buddy-icon-changed
 	* "conversation-drag-end": replaced by "conversation-dragging"
+	* "conversation-switching"
 
 version 1.5.0 (8/11/2005):
 	* Added: gaim_xfer_conversation_write
--- a/src/gtkpounce.c	Tue Jan 03 09:05:14 2006 +0000
+++ b/src/gtkpounce.c	Tue Jan 03 11:42:51 2006 +0000
@@ -66,11 +66,14 @@
 	/* The window */
 	GtkWidget *window;
 
-	/* Pounce Who */
+	/* Pounce on Whom */
 	GtkWidget *account_menu;
 	GtkWidget *buddy_entry;
 
-	/* Pounce When */
+	/* Pounce options */
+	GtkWidget *on_away;
+
+	/* Pounce When Buddy... */
 	GtkWidget *signon;
 	GtkWidget *signoff;
 	GtkWidget *away;
@@ -79,8 +82,9 @@
 	GtkWidget *idle_return;
 	GtkWidget *typing;
 	GtkWidget *stop_typing;
+	GtkWidget *message_recv;
 
-	/* Pounce Action */
+	/* Action */
 	GtkWidget *open_win;
 	GtkWidget *popup;
 	GtkWidget *send_msg;
@@ -244,7 +248,8 @@
 {
 	const char *name;
 	const char *message, *command, *sound;
-	GaimPounceEvent events = GAIM_POUNCE_NONE;
+	GaimPounceEvent events   = GAIM_POUNCE_NONE;
+	GaimPounceOption options = GAIM_POUNCE_OPTION_NONE;
 
 	name = gtk_entry_get_text(GTK_ENTRY(dialog->buddy_entry));
 
@@ -255,6 +260,10 @@
 		return;
 	}
 
+	/* Options */
+	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->on_away)))
+		options |= GAIM_POUNCE_OPTION_AWAY;
+
 	/* Events */
 	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->signon)))
 		events |= GAIM_POUNCE_SIGNON;
@@ -280,6 +289,9 @@
 	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->stop_typing)))
 		events |= GAIM_POUNCE_TYPING_STOPPED;
 
+	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->message_recv)))
+		events |= GAIM_POUNCE_MESSAGE_RECEIVED;
+
 	/* Data fields */
 	message = gtk_entry_get_text(GTK_ENTRY(dialog->send_msg_entry));
 	command = gtk_entry_get_text(GTK_ENTRY(dialog->exec_cmd_entry));
@@ -292,10 +304,11 @@
 	if (dialog->pounce == NULL)
 	{
 		dialog->pounce = gaim_pounce_new(GAIM_GTK_UI, dialog->account,
-										 name, events);
+										 name, events, options);
 	}
 	else {
 		gaim_pounce_set_events(dialog->pounce, events);
+		gaim_pounce_set_options(dialog->pounce, options);
 		gaim_pounce_set_pouncer(dialog->pounce, dialog->account);
 		gaim_pounce_set_pouncee(dialog->pounce, name);
 	}
@@ -357,6 +370,16 @@
 }
 
 static void
+message_recv_toggle(GtkButton *message_recv, GtkWidget *send_msg)
+{
+	gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(message_recv));
+
+	gtk_widget_set_sensitive(send_msg, !active);
+	if (active)
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(send_msg), FALSE);
+}
+
+static void
 pounce_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y,
 				GtkSelectionData *sd, guint info, guint t, gpointer data)
 {
@@ -489,8 +512,8 @@
 	vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE);
 	gtk_box_pack_start(GTK_BOX(vbox1), vbox2, TRUE, TRUE, 0);
 
-	/* Create the "Pounce Who" frame. */
-	frame = gaim_gtk_make_frame(vbox2, _("Pounce Who"));
+	/* Create the "Pounce on Whom" frame. */
+	frame = gaim_gtk_make_frame(vbox2, _("Pounce on Whom"));
 
 	/* Account: */
 	hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE);
@@ -540,7 +563,7 @@
 		gtk_entry_set_text(GTK_ENTRY(dialog->buddy_entry), name);
 	}
 
-	/* Create the "Pounce When" frame. */
+	/* Create the "Pounce When Buddy..." frame. */
 	frame = gaim_gtk_make_frame(vbox2, _("Pounce When Buddy..."));
 
 	table = gtk_table_new(2, 4, FALSE);
@@ -564,22 +587,26 @@
 		gtk_check_button_new_with_mnemonic(_("Starts _typing"));
 	dialog->stop_typing =
 		gtk_check_button_new_with_mnemonic(_("Stops t_yping"));
+	dialog->message_recv =
+		gtk_check_button_new_with_mnemonic(_("Sends a _message"));
 
-	gtk_table_attach(GTK_TABLE(table), dialog->signon,      0, 1, 0, 1,
+	gtk_table_attach(GTK_TABLE(table), dialog->signon,       0, 1, 0, 1,
 					 GTK_FILL, 0, 0, 0);
-	gtk_table_attach(GTK_TABLE(table), dialog->signoff,     1, 2, 0, 1,
+	gtk_table_attach(GTK_TABLE(table), dialog->signoff,      1, 2, 0, 1,
 					 GTK_FILL, 0, 0, 0);
-	gtk_table_attach(GTK_TABLE(table), dialog->away,        0, 1, 1, 2,
+	gtk_table_attach(GTK_TABLE(table), dialog->away,         0, 1, 1, 2,
 					 GTK_FILL, 0, 0, 0);
-	gtk_table_attach(GTK_TABLE(table), dialog->away_return, 1, 2, 1, 2,
+	gtk_table_attach(GTK_TABLE(table), dialog->away_return,  1, 2, 1, 2,
 					 GTK_FILL, 0, 0, 0);
-	gtk_table_attach(GTK_TABLE(table), dialog->idle,        0, 1, 2, 3,
+	gtk_table_attach(GTK_TABLE(table), dialog->idle,         0, 1, 2, 3,
+					 GTK_FILL, 0, 0, 0);
+	gtk_table_attach(GTK_TABLE(table), dialog->idle_return,  1, 2, 2, 3,
 					 GTK_FILL, 0, 0, 0);
-	gtk_table_attach(GTK_TABLE(table), dialog->idle_return, 1, 2, 2, 3,
+	gtk_table_attach(GTK_TABLE(table), dialog->typing,       0, 1, 3, 4,
 					 GTK_FILL, 0, 0, 0);
-	gtk_table_attach(GTK_TABLE(table), dialog->typing,      0, 1, 3, 4,
+	gtk_table_attach(GTK_TABLE(table), dialog->stop_typing,  1, 2, 3, 4,
 					 GTK_FILL, 0, 0, 0);
-	gtk_table_attach(GTK_TABLE(table), dialog->stop_typing, 1, 2, 3, 5,
+	gtk_table_attach(GTK_TABLE(table), dialog->message_recv, 0, 1, 4, 5,
 					 GTK_FILL, 0, 0, 0);
 
 	gtk_widget_show(dialog->signon);
@@ -590,9 +617,10 @@
 	gtk_widget_show(dialog->idle_return);
 	gtk_widget_show(dialog->typing);
 	gtk_widget_show(dialog->stop_typing);
+	gtk_widget_show(dialog->message_recv);
 
-	/* Create the "Pounce Action" frame. */
-	frame = gaim_gtk_make_frame(vbox2, _("Pounce Action"));
+	/* Create the "Action" frame. */
+	frame = gaim_gtk_make_frame(vbox2, _("Action"));
 
 	table = gtk_table_new(3, 5, FALSE);
 	gtk_container_add(GTK_CONTAINER(frame), table);
@@ -617,12 +645,25 @@
 	dialog->play_sound_browse = gtk_button_new_with_mnemonic(_("Br_owse..."));
 	dialog->play_sound_test   = gtk_button_new_with_mnemonic(_("Pre_view"));
 
-	gtk_widget_set_sensitive(dialog->send_msg_entry,   FALSE);
-	gtk_widget_set_sensitive(dialog->exec_cmd_entry,   FALSE);
-	gtk_widget_set_sensitive(dialog->exec_cmd_browse, FALSE);
-	gtk_widget_set_sensitive(dialog->play_sound_entry, FALSE);
-	gtk_widget_set_sensitive(dialog->play_sound_browse,   FALSE);
-	gtk_widget_set_sensitive(dialog->play_sound_test, FALSE);
+	gtk_widget_set_sensitive(dialog->send_msg_entry,    FALSE);
+	gtk_widget_set_sensitive(dialog->exec_cmd_entry,    FALSE);
+	gtk_widget_set_sensitive(dialog->exec_cmd_browse,   FALSE);
+	gtk_widget_set_sensitive(dialog->play_sound_entry,  FALSE);
+	gtk_widget_set_sensitive(dialog->play_sound_browse, FALSE);
+	gtk_widget_set_sensitive(dialog->play_sound_test,   FALSE);
+
+	sg = gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL);
+	gtk_size_group_add_widget(sg, dialog->open_win);
+	gtk_size_group_add_widget(sg, dialog->popup);
+	gtk_size_group_add_widget(sg, dialog->send_msg);
+	gtk_size_group_add_widget(sg, dialog->send_msg_entry);
+	gtk_size_group_add_widget(sg, dialog->exec_cmd);
+	gtk_size_group_add_widget(sg, dialog->exec_cmd_entry);
+	gtk_size_group_add_widget(sg, dialog->exec_cmd_browse);
+	gtk_size_group_add_widget(sg, dialog->play_sound);
+	gtk_size_group_add_widget(sg, dialog->play_sound_entry);
+	gtk_size_group_add_widget(sg, dialog->play_sound_browse);
+	gtk_size_group_add_widget(sg, dialog->play_sound_test);
 
 	gtk_table_attach(GTK_TABLE(table), dialog->open_win,         0, 1, 0, 1,
 					 GTK_FILL, 0, 0, 0);
@@ -647,6 +688,8 @@
 	gtk_table_attach(GTK_TABLE(table), dialog->play_sound_test, 3, 4, 4, 5,
 					 GTK_FILL | GTK_EXPAND, 0, 0, 0);
 
+	gtk_table_set_row_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE / 2);
+
 	gtk_widget_show(dialog->open_win);
 	gtk_widget_show(dialog->popup);
 	gtk_widget_show(dialog->send_msg);
@@ -659,6 +702,10 @@
 	gtk_widget_show(dialog->play_sound_browse);
 	gtk_widget_show(dialog->play_sound_test);
 
+	g_signal_connect(G_OBJECT(dialog->message_recv), "clicked",
+					 G_CALLBACK(message_recv_toggle),
+					 dialog->send_msg);
+
 	g_signal_connect(G_OBJECT(dialog->send_msg), "clicked",
 					 G_CALLBACK(gaim_gtk_toggle_sensitive),
 					 dialog->send_msg_entry);
@@ -696,11 +743,26 @@
 	g_signal_connect(G_OBJECT(dialog->play_sound_entry), "activate",
 					 G_CALLBACK(save_pounce_cb), dialog);
 
-	/* Now the last part, where we have the Save checkbox */
+	/* Create the "Options" frame. */
+	frame = gaim_gtk_make_frame(vbox2, _("Options"));
+
+	table = gtk_table_new(2, 1, FALSE);
+	gtk_container_add(GTK_CONTAINER(frame), table);
+	gtk_table_set_col_spacings(GTK_TABLE(table), GAIM_HIG_BORDER);
+	gtk_widget_show(table);
+
+	dialog->on_away =
+		gtk_check_button_new_with_mnemonic(_("P_ounce only when my status is not available"));
+	gtk_table_attach(GTK_TABLE(table), dialog->on_away, 0, 1, 0, 1,
+					 GTK_FILL, 0, 0, 0);
+
 	dialog->save_pounce = gtk_check_button_new_with_mnemonic(
 		_("_Recurring"));
+	gtk_table_attach(GTK_TABLE(table), dialog->save_pounce, 0, 1, 1, 2,
+					 GTK_FILL, 0, 0, 0);
 
-	gtk_box_pack_start(GTK_BOX(vbox2), dialog->save_pounce, FALSE, FALSE, 0);
+	gtk_widget_show(dialog->on_away);
+	gtk_widget_show(dialog->save_pounce);
 
 	/* Now the button box! */
 	bbox = gtk_hbutton_box_new();
@@ -760,9 +822,14 @@
 	/* Set the values of stuff. */
 	if (cur_pounce != NULL)
 	{
-		GaimPounceEvent events = gaim_pounce_get_events(cur_pounce);
+		GaimPounceEvent events   = gaim_pounce_get_events(cur_pounce);
+		GaimPounceOption options = gaim_pounce_get_options(cur_pounce);
 		const char *value;
 
+		/* Options */
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->on_away),
+									(options & GAIM_POUNCE_OPTION_AWAY));
+
 		/* Events */
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->signon),
 									(events & GAIM_POUNCE_SIGNON));
@@ -780,6 +847,8 @@
 									(events & GAIM_POUNCE_TYPING));
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->stop_typing),
 									(events & GAIM_POUNCE_TYPING_STOPPED));
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->message_recv),
+									(events & GAIM_POUNCE_MESSAGE_RECEIVED));
 
 		/* Actions */
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->open_win),
@@ -1357,6 +1426,8 @@
 				   _("%s has become idle (%s)") :
 				   (events & GAIM_POUNCE_AWAY) ?
 				   _("%s has gone away. (%s)") :
+				   (events & GAIM_POUNCE_MESSAGE_RECEIVED) ?
+				   _("%s has sent you a message. (%s)") :
 				   _("Unknown pounce event. Please report this!"),
 				   alias, gaim_account_get_protocol_name(account));
 
--- a/src/pounce.c	Tue Jan 03 09:05:14 2006 +0000
+++ b/src/pounce.c	Tue Jan 03 11:42:51 2006 +0000
@@ -37,11 +37,13 @@
 
 	GaimPounce *pounce;
 	GaimPounceEvent events;
+	GaimPounceOption options;
 
 	char *ui_name;
 	char *pouncee;
 	char *protocol_id;
 	char *event_type;
+	char *option_type;
 	char *action_name;
 	char *param_name;
 	char *account_name;
@@ -152,15 +154,26 @@
 	xmlnode_set_attrib(child, "type", type);
 }
 
+static void
+add_option_to_xmlnode(xmlnode *node, const char *type)
+{
+	xmlnode *child;
+
+	child = xmlnode_new_child(node, "option");
+	xmlnode_set_attrib(child, "type", type);
+}
+
 static xmlnode *
 pounce_to_xmlnode(GaimPounce *pounce)
 {
 	xmlnode *node, *child;
 	GaimAccount *pouncer;
 	GaimPounceEvent events;
+	GaimPounceOption options;
 
 	pouncer = gaim_pounce_get_pouncer(pounce);
 	events  = gaim_pounce_get_events(pounce);
+	options = gaim_pounce_get_options(pounce);
 
 	node = xmlnode_new("pounce");
 	xmlnode_set_attrib(node, "ui", pounce->ui_type);
@@ -172,6 +185,11 @@
 	child = xmlnode_new_child(node, "pouncee");
 	xmlnode_insert_data(child, gaim_pounce_get_pouncee(pounce), -1);
 
+	/* Write pounce options */
+	child = xmlnode_new_child(node, "options");
+	if (options & GAIM_POUNCE_OPTION_AWAY)
+		add_option_to_xmlnode(child, "on-away");
+
 	/* Write pounce events */
 	child = xmlnode_new_child(node, "events");
 	if (events & GAIM_POUNCE_SIGNON)
@@ -190,6 +208,8 @@
 		add_event_to_xmlnode(child, "start-typing");
 	if (events & GAIM_POUNCE_TYPING_STOPPED)
 		add_event_to_xmlnode(child, "stop-typing");
+	if (events & GAIM_POUNCE_MESSAGE_RECEIVED)
+		add_event_to_xmlnode(child, "message-received");
 
 	/* Write pounce actions */
 	child = xmlnode_new_child(node, "actions");
@@ -271,6 +291,7 @@
 	if (data->pouncee      != NULL) g_free(data->pouncee);
 	if (data->protocol_id  != NULL) g_free(data->protocol_id);
 	if (data->event_type   != NULL) g_free(data->event_type);
+	if (data->option_type  != NULL) g_free(data->option_type);
 	if (data->action_name  != NULL) g_free(data->action_name);
 	if (data->param_name   != NULL) g_free(data->param_name);
 	if (data->account_name != NULL) g_free(data->account_name);
@@ -323,6 +344,16 @@
 		else
 			data->protocol_id = g_strdup(protocol_id);
 	}
+	else if (!strcmp(element_name, "option")) {
+		const char *type = g_hash_table_lookup(atts, "type");
+
+		if (type == NULL) {
+			gaim_debug(GAIM_DEBUG_ERROR, "pounce",
+					   "Unset 'type' parameter for option!\n");
+		}
+		else
+			data->option_type = g_strdup(type);
+	}
 	else if (!strcmp(element_name, "event")) {
 		const char *type = g_hash_table_lookup(atts, "type");
 
@@ -377,6 +408,13 @@
 		g_free(data->pouncee);
 		data->pouncee = g_strdup(buffer);
 	}
+	else if (!strcmp(element_name, "option")) {
+		if (!strcmp(data->option_type, "on-away"))
+			data->options |= GAIM_POUNCE_OPTION_AWAY;
+		
+		g_free(data->option_type);
+		data->option_type = NULL;
+	}
 	else if (!strcmp(element_name, "event")) {
 		if (!strcmp(data->event_type, "sign-on"))
 			data->events |= GAIM_POUNCE_SIGNON;
@@ -394,6 +432,8 @@
 			data->events |= GAIM_POUNCE_TYPING;
 		else if (!strcmp(data->event_type, "stop-typing"))
 			data->events |= GAIM_POUNCE_TYPING_STOPPED;
+		else if (!strcmp(data->event_type, "message-received"))
+			data->events |= GAIM_POUNCE_MESSAGE_RECEIVED;
 
 		g_free(data->event_type);
 		data->event_type = NULL;
@@ -442,7 +482,8 @@
 					   data->pouncee);
 
 			data->pounce = gaim_pounce_new(data->ui_name, account,
-										   data->pouncee, data->events);
+										   data->pouncee, data->events,
+										   data->options);
 		}
 
 		g_free(data->pouncee);
@@ -453,13 +494,15 @@
 			gaim_pounce_set_save(data->pounce, TRUE);
 	}
 	else if (!strcmp(element_name, "pounce")) {
-		data->pounce = NULL;
-		data->events = 0;
+		data->pounce  = NULL;
+		data->events  = 0;
+		data->options = 0;
 
 		if (data->ui_name      != NULL) g_free(data->ui_name);
 		if (data->pouncee      != NULL) g_free(data->pouncee);
 		if (data->protocol_id  != NULL) g_free(data->protocol_id);
 		if (data->event_type   != NULL) g_free(data->event_type);
+		if (data->option_type  != NULL) g_free(data->option_type);
 		if (data->action_name  != NULL) g_free(data->action_name);
 		if (data->param_name   != NULL) g_free(data->param_name);
 		if (data->account_name != NULL) g_free(data->account_name);
@@ -468,6 +511,7 @@
 		data->pounce       = NULL;
 		data->protocol_id  = NULL;
 		data->event_type   = NULL;
+		data->option_type  = NULL;
 		data->action_name  = NULL;
 		data->param_name   = NULL;
 		data->account_name = NULL;
@@ -563,7 +607,8 @@
 
 GaimPounce *
 gaim_pounce_new(const char *ui_type, GaimAccount *pouncer,
-				const char *pouncee, GaimPounceEvent event)
+				const char *pouncee, GaimPounceEvent event,
+				GaimPounceOption option)
 {
 	GaimPounce *pounce;
 	GaimPounceHandler *handler;
@@ -579,6 +624,7 @@
 	pounce->pouncer  = pouncer;
 	pounce->pouncee  = g_strdup(pouncee);
 	pounce->events   = event;
+	pounce->options  = option;
 
 	pounce->actions  = g_hash_table_new_full(g_str_hash, g_str_equal,
 											 g_free, free_action_data);
@@ -643,7 +689,7 @@
 gaim_pounce_set_events(GaimPounce *pounce, GaimPounceEvent events)
 {
 	g_return_if_fail(pounce != NULL);
-	g_return_if_fail(pounce != GAIM_POUNCE_NONE);
+	g_return_if_fail(events != GAIM_POUNCE_NONE);
 
 	pounce->events = events;
 
@@ -651,6 +697,16 @@
 }
 
 void
+gaim_pounce_set_options(GaimPounce *pounce, GaimPounceOption options)
+{
+	g_return_if_fail(pounce  != NULL);
+
+	pounce->options = options;
+
+	schedule_pounces_save();
+}
+
+void
 gaim_pounce_set_pouncer(GaimPounce *pounce, GaimAccount *pouncer)
 {
 	g_return_if_fail(pounce  != NULL);
@@ -767,6 +823,14 @@
 	return pounce->events;
 }
 
+GaimPounceOption
+gaim_pounce_get_options(const GaimPounce *pounce)
+{
+	g_return_val_if_fail(pounce != NULL, GAIM_POUNCE_OPTION_NONE);
+
+	return pounce->options;
+}
+
 GaimAccount *
 gaim_pounce_get_pouncer(const GaimPounce *pounce)
 {
@@ -837,6 +901,7 @@
 {
 	GaimPounce *pounce;
 	GaimPounceHandler *handler;
+	GaimPresence *presence;
 	GList *l, *l_next;
 	char *norm_pouncee;
 
@@ -851,10 +916,15 @@
 		pounce = (GaimPounce *)l->data;
 		l_next = l->next;
 
+		presence = gaim_account_get_presence(pouncer);
+
 		if ((gaim_pounce_get_events(pounce) & events) &&
 			(gaim_pounce_get_pouncer(pounce) == pouncer) &&
 			!gaim_utf8_strcasecmp(gaim_normalize(pouncer, gaim_pounce_get_pouncee(pounce)),
-								  norm_pouncee))
+								  norm_pouncee) &&
+			(pounce->options == GAIM_POUNCE_OPTION_NONE ||
+			 (pounce->options & GAIM_POUNCE_OPTION_AWAY && 
+			  !gaim_presence_is_available(presence))))
 		{
 			handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
 
@@ -999,6 +1069,12 @@
 	}
 }
 
+static void
+received_message_cb(GaimAccount *account, const char *name, void *data)
+{
+	gaim_pounce_execute(account, name, GAIM_POUNCE_MESSAGE_RECEIVED);
+}
+
 void *
 gaim_pounces_get_handle(void)
 {
@@ -1032,6 +1108,9 @@
 						handle, GAIM_CALLBACK(buddy_typing_cb), NULL);
 	gaim_signal_connect(conv_handle, "buddy-typing-stopped",
 						handle, GAIM_CALLBACK(buddy_typing_cb), NULL);
+
+	gaim_signal_connect(conv_handle, "received-im-msg",
+						handle, GAIM_CALLBACK(received_message_cb), NULL);
 }
 
 void
--- a/src/pounce.h	Tue Jan 03 09:05:14 2006 +0000
+++ b/src/pounce.h	Tue Jan 03 11:42:51 2006 +0000
@@ -43,10 +43,17 @@
 	GAIM_POUNCE_IDLE           = 0x10, /**< The buddy became idle.        */
 	GAIM_POUNCE_IDLE_RETURN    = 0x20, /**< The buddy is no longer idle.  */
 	GAIM_POUNCE_TYPING         = 0x40, /**< The buddy started typing.     */
-	GAIM_POUNCE_TYPING_STOPPED = 0x80  /**< The buddy stopped typing.     */
+	GAIM_POUNCE_TYPING_STOPPED = 0x80, /**< The buddy stopped typing.     */
+	GAIM_POUNCE_MESSAGE_RECEIVED = 0x100 /**< The buddy sent a message    */
 
 } GaimPounceEvent;
 
+typedef enum
+{
+	GAIM_POUNCE_OPTION_NONE		= 0x00, /**< No Option                */
+	GAIM_POUNCE_OPTION_AWAY		= 0x01  /**< Pounce only when away    */
+} GaimPounceOption;
+
 /** A pounce callback. */
 typedef void (*GaimPounceCb)(GaimPounce *, GaimPounceEvent, void *);
 
@@ -63,6 +70,7 @@
 	char *ui_type;                /**< The type of UI.            */
 
 	GaimPounceEvent events;       /**< The event(s) to pounce on. */
+	GaimPounceOption options;     /**< The pounce options         */
 	GaimAccount *pouncer;         /**< The user who is pouncing.  */
 
 	char *pouncee;                /**< The buddy to pounce on.    */
@@ -94,7 +102,8 @@
  * @return The new buddy pounce structure.
  */
 GaimPounce *gaim_pounce_new(const char *ui_type, GaimAccount *pouncer,
-							const char *pouncee, GaimPounceEvent event);
+							const char *pouncee, GaimPounceEvent event,
+							GaimPounceOption option);
 
 /**
  * Destroys a buddy pounce.
@@ -119,6 +128,14 @@
 void gaim_pounce_set_events(GaimPounce *pounce, GaimPounceEvent events);
 
 /**
+ * Sets the options for a pounce.
+ *
+ * @param pounce  The buddy pounce.
+ * @param options The options for the pounce.
+ */
+void gaim_pounce_set_options(GaimPounce *pounce, GaimPounceOption options);
+
+/**
  * Sets the account that will do the pouncing.
  *
  * @param pounce  The buddy pounce.
@@ -191,6 +208,15 @@
 GaimPounceEvent gaim_pounce_get_events(const GaimPounce *pounce);
 
 /**
+ * Returns the options for a pounce.
+ *
+ * @param pounce The buddy pounce.
+ *
+ * @return The options for the pounce.
+ */
+GaimPounceOption gaim_pounce_get_options(const GaimPounce *pounce);
+
+/**
  * Returns the account that will do the pouncing.
  *
  * @param pounce The buddy pounce.