gobjectification.conversation: af477e6f: Add msg-send, msg-receive and msg-write ...

sadrul at pidgin.im sadrul at pidgin.im
Sat Jul 24 23:10:43 EDT 2010


----------------------------------------------------------------------
Revision: af477e6f7be8d5d99d9e9b469c61262a1507bf49
Parent:   12901a85801f8916a18a8e9d8d555da7a7ff5efe
Author:   sadrul at pidgin.im
Date:     07/24/10 21:43:36
Branch:   im.pidgin.gobjectification.conversation
URL: http://d.pidgin.im/viewmtn/revision/info/af477e6f7be8d5d99d9e9b469c61262a1507bf49

Changelog: 

Add msg-send, msg-receive and msg-write signals, and some skeleton code.

serv_send_im is removed. purple_conversation_send should be used instead.
serv_got_im is also removed, purple_im_new_with_receive should be used
instead.

Changes against parent 12901a85801f8916a18a8e9d8d555da7a7ff5efe

  patched  libpurple/conversation/conv-im.c
  patched  libpurple/conversation/conv-im.h
  patched  libpurple/conversation/conv-muc.c
  patched  libpurple/conversation/conv-muc.h
  patched  libpurple/conversation/conv.c
  patched  libpurple/conversation/conv.h
  patched  libpurple/conversation.c
  patched  libpurple/server.c
  patched  libpurple/server.h

-------------- next part --------------
============================================================
--- libpurple/server.c	77e0f2206e6927255953149830be6cf429c7dd6d
+++ libpurple/server.c	2552ab3acd76f509b0621c6d5d3ec06b95443797
@@ -23,6 +23,8 @@
 
 /* This file is the fullcrap */
 
+#define purple_conversations_get_handle() NULL		/* No ... *this* is */
+
 #include "internal.h"
 #include "blist.h"
 #include "conversation.h"
@@ -117,6 +119,7 @@ get_last_auto_response(PurpleConnection 
 	return lar;
 }
 
+#if 0
 int serv_send_im(PurpleConnection *gc, const char *name, const char *message,
 				 PurpleMessageFlags flags)
 {
@@ -165,6 +168,7 @@ int serv_send_im(PurpleConnection *gc, c
 
 	return val;
 }
+#endif
 
 void serv_get_info(PurpleConnection *gc, const char *name)
 {
@@ -484,7 +488,7 @@ void serv_chat_invite(PurpleConnection *
 	PurpleConversation *conv;
 	char *buffy = message && *message ? g_strdup(message) : NULL;
 
-	conv = purple_find_chat(gc, id);
+	conv = purple_conversations_find_muc(gc, id);
 
 	if(conv == NULL)
 		return;
@@ -552,6 +556,7 @@ int serv_chat_send(PurpleConnection *gc,
 	return -EINVAL;
 }
 
+#if 0
 /*
  * woo. i'm actually going to comment this function. isn't that fun. make
  * sure to follow along, kids
@@ -696,6 +701,7 @@ void serv_got_im(PurpleConnection *gc, c
 
 	g_free(name);
 }
+#endif
 
 void serv_got_typing(PurpleConnection *gc, const char *name, int timeout,
 					 PurpleTypingState state) {
============================================================
--- libpurple/conversation.c	6a1826fb6833a914e1a3e208e66d1ee88a1bdccb
+++ libpurple/conversation.c	9761e4c1e29225c5b290df3b312b2f99fce96b5c
@@ -782,29 +782,6 @@ purple_conversation_set_account(PurpleCo
 	purple_conversation_update(conv, PURPLE_CONV_UPDATE_ACCOUNT);
 }
 
-PurpleAccount *
-purple_conversation_get_account(const PurpleConversation *conv)
-{
-	g_return_val_if_fail(conv != NULL, NULL);
-
-	return conv->account;
-}
-
-PurpleConnection *
-purple_conversation_get_gc(const PurpleConversation *conv)
-{
-	PurpleAccount *account;
-
-	g_return_val_if_fail(conv != NULL, NULL);
-
-	account = purple_conversation_get_account(conv);
-
-	if (account == NULL)
-		return NULL;
-
-	return purple_account_get_connection(account);
-}
-
 void
 purple_conversation_set_title(PurpleConversation *conv, const char *title)
 {
@@ -889,14 +866,6 @@ purple_conversation_set_name(PurpleConve
 	purple_conversation_autoset_title(conv);
 }
 
-const char *
-purple_conversation_get_name(const PurpleConversation *conv)
-{
-	g_return_val_if_fail(conv != NULL, NULL);
-
-	return conv->name;
-}
-
 PurpleBuddy *
 purple_conversation_find_buddy(const PurpleConversation *conv)
 {
@@ -1039,124 +1008,6 @@ purple_find_conversation_with_account(Pu
 	return c;
 }
 
-void
-purple_conversation_write(PurpleConversation *conv, const char *who,
-						const char *message, PurpleMessageFlags flags,
-						time_t mtime)
-{
-	PurplePluginProtocolInfo *prpl_info = NULL;
-	PurpleConnection *gc = NULL;
-	PurpleAccount *account;
-	PurpleConversationUiOps *ops;
-	const char *alias;
-	char *displayed = NULL;
-	PurpleBuddy *b;
-	int plugin_return;
-	PurpleConversationType type;
-	/* int logging_font_options = 0; */
-
-	g_return_if_fail(conv    != NULL);
-	g_return_if_fail(message != NULL);
-
-	ops = purple_conversation_get_ui_ops(conv);
-
-	account = purple_conversation_get_account(conv);
-	type = purple_conversation_get_type(conv);
-
-	if (account != NULL)
-		gc = purple_account_get_connection(account);
-
-#warning I think commenting this breaks unnamed chats
-#if 0
-	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT &&
-		(gc != NULL && !g_slist_find(gc->buddy_chats, conv)))
-		return;
-#endif
-
-	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM &&
-		!g_list_find(purple_get_conversations(), conv))
-		return;
-
-	displayed = g_strdup(message);
-
-	if (who == NULL || *who == '\0')
-		who = purple_conversation_get_name(conv);
-	alias = who;
-
-	plugin_return =
-		GPOINTER_TO_INT(purple_signal_emit_return_1(
-			purple_conversations_get_handle(),
-			(type == PURPLE_CONV_TYPE_IM ? "writing-im-msg" : "writing-chat-msg"),
-			account, who, &displayed, conv, flags));
-
-	if (displayed == NULL)
-		return;
-
-	if (plugin_return) {
-		g_free(displayed);
-		return;
-	}
-
-	if (account != NULL) {
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account)));
-
-		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM ||
-			!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
-
-			if (flags & PURPLE_MESSAGE_SEND) {
-				b = purple_find_buddy(account,
-							purple_account_get_username(account));
-
-				if (purple_account_get_alias(account) != NULL)
-					alias = purple_account_get_alias(account);
-				else if (b != NULL && !purple_strequal(purple_buddy_get_name(b), purple_buddy_get_contact_alias(b)))
-					alias = purple_buddy_get_contact_alias(b);
-				else if (purple_connection_get_display_name(gc) != NULL)
-					alias = purple_connection_get_display_name(gc);
-				else
-					alias = purple_account_get_username(account);
-			}
-			else
-			{
-				b = purple_find_buddy(account, who);
-
-				if (b != NULL)
-					alias = purple_buddy_get_contact_alias(b);
-			}
-		}
-	}
-
-	if (!(flags & PURPLE_MESSAGE_NO_LOG) && purple_conversation_is_logging(conv)) {
-		GList *log;
-
-		if (conv->logs == NULL)
-			open_log(conv);
-
-		log = conv->logs;
-		while (log != NULL) {
-			purple_log_write((PurpleLog *)log->data, flags, alias, mtime, displayed);
-			log = log->next;
-		}
-	}
-
-	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-		if ((flags & PURPLE_MESSAGE_RECV) == PURPLE_MESSAGE_RECV) {
-			purple_conv_im_set_typing_state(PURPLE_CONV_IM(conv), PURPLE_NOT_TYPING);
-		}
-	}
-
-	if (ops && ops->write_conv)
-		ops->write_conv(conv, who, alias, displayed, flags, mtime);
-
-	add_message_to_history(conv, who, alias, message, flags, mtime);
-
-	purple_signal_emit(purple_conversations_get_handle(),
-		(type == PURPLE_CONV_TYPE_IM ? "wrote-im-msg" : "wrote-chat-msg"),
-		account, who, displayed, conv, flags);
-
-	g_free(displayed);
-}
-
 gboolean
 purple_conversation_has_focus(PurpleConversation *conv)
 {
@@ -1200,30 +1051,6 @@ void
 }
 
 void
-purple_conv_im_set_icon(PurpleConvIm *im, PurpleBuddyIcon *icon)
-{
-	g_return_if_fail(im != NULL);
-
-	if (im->icon != icon)
-	{
-		purple_buddy_icon_unref(im->icon);
-
-		im->icon = (icon == NULL ? NULL : purple_buddy_icon_ref(icon));
-	}
-
-	purple_conversation_update(purple_conv_im_get_conversation(im),
-							 PURPLE_CONV_UPDATE_ICON);
-}
-
-PurpleBuddyIcon *
-purple_conv_im_get_icon(const PurpleConvIm *im)
-{
-	g_return_val_if_fail(im != NULL, NULL);
-
-	return im->icon;
-}
-
-void
 purple_conv_im_set_typing_state(PurpleConvIm *im, PurpleTypingState state)
 {
 	g_return_if_fail(im != NULL);
@@ -1356,24 +1183,6 @@ void
 }
 
 void
-purple_conv_im_write(PurpleConvIm *im, const char *who, const char *message,
-			  PurpleMessageFlags flags, time_t mtime)
-{
-	PurpleConversation *c;
-
-	g_return_if_fail(im != NULL);
-	g_return_if_fail(message != NULL);
-
-	c = purple_conv_im_get_conversation(im);
-
-	/* Pass this on to either the ops structure or the default write func. */
-	if (c->ui_ops != NULL && c->ui_ops->write_im != NULL)
-		c->ui_ops->write_im(c, who, message, flags, mtime);
-	else
-		purple_conversation_write(c, who, message, flags, mtime);
-}
-
-void
 purple_conv_im_send(PurpleConvIm *im, const char *message)
 {
 	purple_conv_im_send_with_flags(im, message, 0);
============================================================
--- libpurple/conversation/conv.h	ab68f4cdf147fc2c4308b364de044119170a8ad9
+++ libpurple/conversation/conv.h	2a6546cdb9115d52de39a62aa731b14404af4493
@@ -27,6 +27,8 @@
 #ifndef _PURPLE_CONVERSATION_H_
 #define _PURPLE_CONVERSATION_H_
 
+#include "buddyicon.h"
+
 G_BEGIN_DECLS
 
 #define PURPLE_TYPE_CONVERSATION purple_conversation_get_type()
@@ -59,6 +61,9 @@ struct _PurpleConversationClass
 struct _PurpleConversationClass
 {
 	PurpleObjectClass parent_class;
+
+	gboolean (*send)(PurpleConversation *conv, PurpleMessage *msg);
+	gboolean (*receive)(PurpleConversation *conv, PurpleMessage *msg);
 };
 
 GType purple_conversation_get_type (void);
@@ -256,29 +261,6 @@ void *purple_conversation_get_ui_data(Pu
 #endif
 
 /**
- * Returns the specified conversation's purple_account.
- *
- * This purple_account represents the user using purple, not the person the user
- * is having a conversation/chat/flame with.
- *
- * @param conv The conversation.
- *
- * @return The conversation's purple_account.
- */
-PurpleAccount *purple_conversation_get_account(const PurpleConversation *conv);
-
-/**
- * Returns the specified conversation's purple_connection.
- *
- * This is the same as purple_conversation_get_user(conv)->gc.
- *
- * @param conv The conversation.
- *
- * @return The conversation's purple_connection.
- */
-PurpleConnection *purple_conversation_get_gc(const PurpleConversation *conv);
-
-/**
  * Sets the specified conversation's title.
  *
  * @param conv  The conversation.
@@ -1077,6 +1059,7 @@ const char *purple_conv_chat_get_nick(Pu
 const char *purple_conv_chat_get_nick(PurpleConvChat *chat);
 #endif
 
+#if 0
 /**
  * Finds a chat with the specified chat ID.
  *
@@ -1087,7 +1070,6 @@ PurpleConversation *purple_find_chat(con
  */
 PurpleConversation *purple_find_chat(const PurpleConnection *gc, int id);
 
-#if 0
 /**
  * Lets the core know we left a chat, without destroying it.
  * Called from serv_got_chat_left().
@@ -1203,12 +1185,14 @@ gboolean purple_conversation_do_command(
 /**************************************************************************/
 /*@{*/
 
+#if 0
 /**
  * Returns the conversation subsystem handle.
  *
  * @return The conversation subsystem handle.
  */
 void *purple_conversations_get_handle(void);
+#endif
 
 /**
  * Initializes the conversation subsystem.
@@ -1267,6 +1251,8 @@ void purple_conversation_set_icon(Purple
 
 void purple_conversation_set_icon(PurpleConversation *conv, PurpleBuddyIcon *icon);
 
+PurpleBuddyIcon *purple_conversation_get_icon(PurpleConversation *conv);
+
 void purple_conversation_update(PurpleConversation *conv, PurpleConversationUpdate update);
 
 PurpleTypingState purple_conversation_get_typing_state(PurpleConversation *conv);
@@ -1283,6 +1269,45 @@ void purple_conversation_write(PurpleCon
 
 void purple_conversation_write(PurpleConversation *conv, PurpleMessage *msg);
 
+void purple_conversation_write_message(PurpleConversation *conv, const char *message,
+		PurpleMessageFlags flag);
+
+void purple_conversation_present(PurpleConversation *conv);
+
+void purple_conversation_send_confirm(PurpleConversation *conv, const char *message);
+
+/**
+ * Returns the specified conversation's purple_account.
+ *
+ * This purple_account represents the user using purple, not the person the user
+ * is having a conversation/chat/flame with.
+ *
+ * @param conv The conversation.
+ *
+ * @return The conversation's purple_account.
+ */
+PurpleAccount *purple_conversation_get_account(const PurpleConversation *conv);
+
+/**
+ * Returns the specified conversation's purple_connection.
+ *
+ * This is the same as purple_conversation_get_user(conv)->gc.
+ *
+ * @param conv The conversation.
+ *
+ * @return The conversation's purple_connection.
+ */
+PurpleConnection *purple_conversation_get_connection(const PurpleConversation *conv);
+
+/** Returns a PurpleMessage object if the message was sent successfully. If there was
+ * an error, returns NULL. */
+PurpleMessage * purple_conversation_send(PurpleConversation *conv, const char *message, PurpleMessageFlags flags);
+
+/** Returns TRUE if the message was successfully received, and FALSE otherwise (i.e. if
+ * some plugin decides the block the message, e.g. when the user is ignored etc.)
+ */
+gboolean purple_conversation_receive(PurpleConversation *conv, PurpleMessage *msg);
+
 #ifdef __cplusplus
 }
 #endif
============================================================
--- libpurple/server.h	378604ab6158441b1ea1d8e9f89375a10bcbd928
+++ libpurple/server.h	79b516516c3455a36c0d2a3e169604971b8d27c2
@@ -56,7 +56,9 @@ void serv_move_buddy(PurpleBuddy *, Purp
 unsigned int serv_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state);
 
 void serv_move_buddy(PurpleBuddy *, PurpleGroup *, PurpleGroup *);
+#if 0
 int  serv_send_im(PurpleConnection *, const char *, const char *, PurpleMessageFlags flags);
+#endif
 
 /** Get information about an account's attention commands, from the prpl.
  *
@@ -141,8 +143,10 @@ void serv_got_typing_stopped(PurpleConne
  */
 void serv_got_typing_stopped(PurpleConnection *gc, const char *name);
 
+#if 0
 void serv_got_im(PurpleConnection *gc, const char *who, const char *msg,
 				 PurpleMessageFlags flags, time_t mtime);
+#endif
 
 /**
  * @param data The hash function should be g_str_hash() and the equal
============================================================
--- libpurple/conversation/conv-im.c	ce5c5be6f3893e2c4d15907a77cf38a1c42ea21f
+++ libpurple/conversation/conv-im.c	e480931cc71cf1f32564794dde2ec84bc73ea328
@@ -27,6 +27,7 @@
 #include "internal.h"
 
 #include "conversation/conv-im.h"
+#include "prpl.h"
 
 enum
 {
@@ -42,6 +43,7 @@ struct _PurpleIMPrivate
 
 struct _PurpleIMPrivate
 {
+	int dummy;
 };
 
 static void
@@ -78,6 +80,48 @@ purple_im_get_property(GObject *obj, gui
 	}
 }
 
+static gboolean
+purple_im_send(PurpleConversation *conv, PurpleMessage *msg)
+{
+	PurpleConnection *gc = purple_conversation_get_connection(conv);
+	PurplePlugin *prpl = NULL;
+	PurplePluginProtocolInfo *prpl_info = NULL;
+	int val;
+
+	prpl = purple_connection_get_prpl(gc);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if (!prpl_info->send_im) {
+		g_warning("The PRPL should've had a send_im!\n");
+		return FALSE;
+	}
+
+	val = prpl_info->send_im(gc, purple_conversation_get_name(conv),
+			purple_message_get_message(msg),
+			purple_message_get_flags(msg));
+
+	if (val < 0) {
+		/* TODO: Make the error status available to UI/client. */
+		return FALSE;
+	}
+
+	if (val == 0) {
+		purple_message_set_flags(msg,
+				purple_message_get_flags(msg) | PURPLE_MESSAGE_INVISIBLE);
+	}
+
+	/* TODO: Reset auto-reply */
+
+	return TRUE;
+}
+
+static gboolean
+purple_im_receive(PurpleConversation *conv, PurpleMessage *msg)
+{
+	/* TODO: Setup auto-reply if applicable */
+	return TRUE;
+}
+
 static void
 purple_im_class_init (PurpleIMClass *klass)
 {
@@ -90,6 +134,9 @@ purple_im_class_init (PurpleIMClass *kla
 
 	object_class->get_property = purple_im_get_property;
 	object_class->set_property = purple_im_set_property;
+
+	PURPLE_CONVERSATION_CLASS(klass)->send = purple_im_send;
+	PURPLE_CONVERSATION_CLASS(klass)->receive = purple_im_receive;
 }
 
 static void
@@ -98,11 +145,13 @@ PurpleIM*
 }
 
 PurpleIM*
-purple_im_new (const PurpleAccount *account, const char *who)
+purple_im_new (PurpleAccount *account, const char *who)
 {
 	PurpleIM *im;
 
-	/* TODO: First, look for an existing IM */
+	im = PURPLE_IM(purple_conversations_find(PURPLE_TYPE_IM, account, who));
+	if (im)
+		return im;
 
 	im = g_object_new (PURPLE_TYPE_IM,
 			"account", account,
@@ -114,3 +163,50 @@ purple_im_new (const PurpleAccount *acco
 	return im;
 }
 
+/** Returns an IM initiated by a received message. The idea behind having this instead
+ * of simply using purple_im_new and purple_conversation_receive is that if an incoming
+ * message (that would create a new conversation) is blocked for some reason, then we
+ * don't want the conversation to actually exist. So we create a temporary IM
+ * conversation, do purple_conversation_receive, and if that fails, destroy the new IM.
+ * Plugins that want to block incoming messages should be listening to MSG_RECV signal,
+ * and block the message from the callback. Since the 'new' signal is emitted only
+ * after the message has been accepted, the client wouldn't create a UI for the
+ * temporary conversation in case the message has been blocked.
+ *
+ * The caveat is that the MSG_RECV callback won't have this conversation in the list
+ * from purple_conversations_list, since that list is populated by the 'new' callback.
+ *
+ * One interesting note: plugins like bot-sentry can do purple_conversation_send in
+ * the MSG_RECV callbacks.
+ */
+PurpleIM *
+purple_im_new_with_receive(PurpleAccount *account, PurpleMessage *msg)
+{
+	PurpleIM *im;
+	const char *who = purple_message_get_sender(msg);
+	gboolean newim = FALSE;
+
+	im = PURPLE_IM(purple_conversations_find(PURPLE_TYPE_IM, account, who));
+
+	if (!im) {
+		newim = TRUE;
+		im = g_object_new (PURPLE_TYPE_IM,
+				"account", account,
+				"name", who,
+				NULL);
+	}
+
+	if (!purple_conversation_receive(PURPLE_CONVERSATION(im), msg)) {
+		if (newim)
+			g_object_unref(G_OBJECT(im));
+		return NULL;
+	}
+
+	if (newim)
+		g_signal_emit_by_name(G_OBJECT(im), "new");
+
+	purple_conversation_write(PURPLE_CONVERSATION(im), msg);
+
+	return im;
+}
+
============================================================
--- libpurple/conversation/conv-im.h	ad0d567073ce0eb8df1e85488aad3f012269057f
+++ libpurple/conversation/conv-im.h	cb3f8b5298041d86ae3854725f746a3597ad485e
@@ -60,8 +60,10 @@ GType purple_im_get_type (void);
 
 GType purple_im_get_type (void);
 
-PurpleIM* purple_im_new (const PurpleAccount *account, const char *who);
+PurpleIM* purple_im_new (PurpleAccount *account, const char *who);
 
+PurpleIM * purple_im_new_with_receive(PurpleAccount *account, PurpleMessage *msg);
+
 G_END_DECLS
 
 #endif
============================================================
--- libpurple/conversation/conv-muc.c	33889b3ed38777a411002aaa4496e99cc828b9a5
+++ libpurple/conversation/conv-muc.c	140b668930d82ec779b2a341cb1e292956b6c226
@@ -22,8 +22,10 @@
 
 #include "conv-muc.h"
 
+/** GObject stuff {{{ */
 enum
 {
+	PROP_0,
 	PROP_TOPIC,
 	PROP_TOPIC_USER,
 	PROP_TOPIC_TIME,
@@ -135,6 +137,8 @@ purple_muc_init (PurpleMUC *self)
 {
 }
 
+/* }}} */
+
 PurpleMUC*
 purple_muc_new (PurpleAccount *account, const char *name)
 {
@@ -170,3 +174,50 @@ purple_muc_get_nick(PurpleMUC *muc)
 	return NULL;
 }
 
+const char *
+purple_muc_get_topic(PurpleMUC *muc)
+{
+	/* TODO: */
+	return NULL;
+}
+
+void
+purple_muc_set_topic(PurpleMUC *muc, const char *who, const char *topic, time_t when)
+{
+	/* TODO: */
+}
+
+void
+purple_muc_add_user(PurpleMUC *muc, const char *user,
+						const char *extra_msg, int flags,
+						gboolean new_arrival)
+{
+	/* TODO: */
+}
+
+void
+purple_muc_remove_user(PurpleMUC *muc, const char *user, const char *reason)
+{
+	/* TODO: */
+}
+
+void
+purple_muc_add_users(PurpleMUC *muc, GList *users, GList *extra_msgs,
+						 GList *flags, gboolean new_arrivals)
+{
+	/* TODO: */
+}
+
+void
+purple_muc_user_set_flags(PurpleMUC *muc, const char *user, int flags)
+{
+	/* TODO: */
+}
+
+int
+purple_muc_user_get_flags(PurpleMUC *muc, const char *user)
+{
+	/* TODO: */
+	return 0;
+}
+
============================================================
--- libpurple/conversation/conv-muc.h	fc1dede8e31464c2478b47b68fb80e202fd82d58
+++ libpurple/conversation/conv-muc.h	d6ee7cc1732863deba8a14994fe880f405d48005
@@ -70,6 +70,24 @@ const char * purple_muc_get_nick(PurpleM
 
 const char * purple_muc_get_nick(PurpleMUC *muc);
 
+const char * purple_muc_get_topic(PurpleMUC *muc);
+
+void purple_muc_set_topic(PurpleMUC *muc, const char *who, const char *topic, time_t when);
+
+void purple_muc_add_user(PurpleMUC *muc, const char *user,
+						const char *extra_msg, int flags,
+						gboolean new_arrival);
+
+void purple_muc_remove_user(PurpleMUC *muc, const char *user, const char *reason);
+
+void purple_muc_add_users(PurpleMUC *muc, GList *users, GList *extra_msgs,
+						 GList *flags, gboolean new_arrivals);
+
+void purple_muc_user_set_flags(PurpleMUC *muc, const char *user,
+							  int flags);
+
+int purple_muc_user_get_flags(PurpleMUC *muc, const char *user);
+
 G_END_DECLS
 
 #endif
============================================================
--- libpurple/conversation/conv.c	1007b49cd34e14c97458dcc0f4ebc1c90cceb45b
+++ libpurple/conversation/conv.c	d243a11fbf2f2a1858e74f0163b526c9ab17c76f
@@ -21,18 +21,25 @@
 #include "internal.h"
 
 #include "conversation/conv.h"
+#include "marshallers.h"
+#include "gsignal.h"
 
 /** GObject stuff {{{ */
 enum
 {
+	PROP_0,
 	PROP_ACCOUNT,
-	PROP_NAME
+	PROP_NAME,
+	PROP_BUDDY_ICON,
+	PROP_TYPING_STATE,
+	PROP_LAST
 };
 
 enum
 {
 	SIG_MSG_RECEIVE,
 	SIG_MSG_SEND,
+	SIG_MSG_WRITE,
 	SIG_LAST
 };
 
@@ -47,8 +54,9 @@ struct _PurpleConversationPrivate
 
 struct _PurpleConversationPrivate
 {
-    PurpleAccount *account;
+	PurpleAccount *account;
 	char *name;
+	PurpleBuddyIcon *icon;
 };
 
 static void
@@ -65,6 +73,9 @@ purple_conversation_get_property (GObjec
 		case PROP_NAME:
 			g_value_set_string(value, priv->name);
 			break;
+		case PROP_BUDDY_ICON:
+			g_value_set_pointer(value, priv->icon);	/* XXX: */
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 	}
@@ -85,6 +96,9 @@ purple_conversation_set_property (GObjec
 			g_free(priv->name);
 			priv->name = g_strdup(g_value_get_string(value));
 			break;
+		case PROP_BUDDY_ICON:
+			purple_conversation_set_icon(conv, g_value_get_pointer(value)); /* XXX: */
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 	}
@@ -125,6 +139,38 @@ purple_conversation_class_init (PurpleCo
 				_("The name of the conversation."), NULL,
 				G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 		/* Should we allow changing the name once it's been created? */
+
+	g_object_class_install_property(object_class, PROP_BUDDY_ICON,
+			g_param_spec_pointer("icon", _("Buddy icon"),
+				_("The icon for this conversation."),
+				G_PARAM_READWRITE));	/* XXX: */
+
+
+	/* XXX: Should PurpleMessage be a boxed type? If so, make sure we use the
+	 * proper marshaller etc. in the following signals. */
+
+	signals[SIG_MSG_WRITE] = g_signal_new("msg-write", G_TYPE_FROM_CLASS(klass),
+			0, 0,
+			NULL, NULL,
+			purple_smarshal_VOID__POINTER,
+			G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+	/* The signal callbacks should return TRUE if the message has been processed
+	 * (i.e. if a plugin wants to block the message from being sent, then it would
+	 * return TRUE from the callback).
+	 */
+	signals[SIG_MSG_SEND] = g_signal_new("msg-send", G_TYPE_FROM_CLASS(klass),
+			0, 0,
+			purple_signal_boolean_accumulator, NULL,
+			purple_smarshal_BOOLEAN__POINTER,
+			G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+
+	/* Same as for SIG_MSG_SEND */
+	signals[SIG_MSG_RECEIVE] = g_signal_new("msg-receive", G_TYPE_FROM_CLASS(klass),
+			0, 0,
+			purple_signal_boolean_accumulator, NULL,
+			purple_smarshal_BOOLEAN__POINTER,
+			G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
 }
 
 static void
@@ -134,14 +180,7 @@ purple_conversation_init (PurpleConversa
 
 /* }}} */
 
-
 void
-purple_conversation_set_icon(PurpleConversation *conv, PurpleBuddyIcon *icon)
-{
-	/* TODO: */
-}
-
-void
 purple_conversation_update(PurpleConversation *conv, PurpleConversationUpdate update)
 {
 	/* TODO: */
@@ -187,6 +226,142 @@ purple_conversation_write(PurpleConversa
 void
 purple_conversation_write(PurpleConversation *conv, PurpleMessage *msg)
 {
+	/* TODO: If alias is not set in msg, set it */
+	g_signal_emit(G_OBJECT(conv), signals[SIG_MSG_WRITE], 0, msg);
+
+	/* TODO: Add msg to history */
+
+	/* TODO: Do something about logging the message */
+}
+
+void
+purple_conversation_write_message(PurpleConversation *conv, const char *message,
+		PurpleMessageFlags flag)
+{
+	PurpleMessage *msg = purple_message_new(NULL, NULL, message, flag, time(NULL));
+	purple_conversation_write(conv, msg);
+}
+
+const char *
+purple_conversation_get_name(const PurpleConversation *conv)
+{
+	PurpleConversationPrivate *priv = GET_PRIVATE(conv);
+	g_return_val_if_fail(priv, NULL);
+
+	return priv->name;
+}
+
+PurpleAccount *
+purple_conversation_get_account(const PurpleConversation *conv)
+{
+	PurpleConversationPrivate *priv = GET_PRIVATE(conv);
+	g_return_val_if_fail(priv, NULL);
+
+	return priv->account;
+}
+
+PurpleConnection *
+purple_conversation_get_connection(const PurpleConversation *conv)
+{
+	PurpleAccount *account = purple_conversation_get_account(conv);
+	g_return_val_if_fail(account, NULL);
+
+	return purple_account_get_connection(account);
+}
+
+void
+purple_conversation_set_icon(PurpleConversation *conv, PurpleBuddyIcon *icon)
+{
+	PurpleConversationPrivate *priv = GET_PRIVATE(conv);
+	g_return_if_fail(priv);
+
+	if (priv->icon)
+		purple_buddy_icon_unref(priv->icon);
+
+	priv->icon = icon ? purple_buddy_icon_ref(icon) : NULL;
+	g_object_notify(G_OBJECT(conv), "icon");
+}
+
+PurpleBuddyIcon *
+purple_conversation_get_icon(PurpleConversation *conv)
+{
+	PurpleConversationPrivate *priv = GET_PRIVATE(conv);
+	g_return_val_if_fail(priv, NULL);
+
+	return priv->icon;
+}
+
+void
+purple_conversation_autoset_title(PurpleConversation *conv)
+{
 	/* TODO: */
 }
 
+void
+purple_conversation_present(PurpleConversation *conv)
+{
+	/* TODO: */
+}
+
+void
+purple_conversation_send_confirm(PurpleConversation *conv, const char *message)
+{
+	/* TODO: */
+}
+
+PurpleMessage *
+purple_conversation_send(PurpleConversation *conv, const char *message, PurpleMessageFlags flags)
+{
+	PurpleConnection *gc;
+	PurpleMessage *msg;
+	gboolean processed = FALSE;
+
+	gc = purple_conversation_get_connection(conv);
+
+	if (!gc || !PURPLE_CONNECTION_IS_CONNECTED(gc))
+		return NULL;
+
+	msg = purple_message_new(NULL, NULL, message,
+			flags | PURPLE_MESSAGE_SEND, time(NULL));
+	g_signal_emit(G_OBJECT(conv), signals[SIG_MSG_SEND], 0, msg, &processed);
+	if (processed) {
+		purple_message_free(msg);
+		return NULL;
+	}
+
+	if (!PURPLE_CONVERSATION_GET_CLASS(conv)->send(conv, msg)) {
+		purple_message_free(msg);
+		return NULL;
+	}
+
+	/* Reset typing notification. */
+	if (purple_conversation_get_send_typed_timeout(conv))
+		purple_conversation_stop_send_typed_timeout(conv);
+
+	return msg;
+}
+
+gboolean
+purple_conversation_receive(PurpleConversation *conv, PurpleMessage *msg)
+{
+	PurpleAccount *account;
+	gboolean processed = FALSE;
+
+	account = purple_conversation_get_account(conv);
+	if (!purple_privacy_check(account, purple_message_get_sender(msg))) {
+		/* TODO: emit a signal */
+		return FALSE;
+	}
+
+	g_signal_emit(G_OBJECT(conv), signals[SIG_MSG_RECEIVE], 0, msg, &processed);
+	if (processed) {
+		return FALSE;
+	}
+
+	if (!PURPLE_CONVERSATION_GET_CLASS(conv)->receive(conv, msg)) {
+		return FALSE;
+	}
+
+	return TRUE;
+}
+


More information about the Commits mailing list