Fix an incorrect call to soup_message_set_request.
[pidgin-git.git] / libpurple / conversations.c
blobb7af7136ec0ef62b00460dfaff71744b0d564f16
1 /*
2 * purple
4 * Purple is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
22 #include "internal.h"
23 #include "conversations.h"
25 static GList *conversations = NULL;
26 static GList *ims = NULL;
27 static GList *chats = NULL;
28 static PurpleConversationUiOps *default_ops = NULL;
31 * A hash table used for efficient lookups of conversations by name.
32 * struct _purple_hconv => PurpleConversation*
34 static GHashTable *conversation_cache = NULL;
36 struct _purple_hconv {
37 gboolean im;
38 char *name;
39 PurpleAccount *account;
42 static guint
43 _purple_conversations_hconv_hash(struct _purple_hconv *hc)
45 return g_str_hash(hc->name) ^ hc->im ^ g_direct_hash(hc->account);
48 static guint
49 _purple_conversations_hconv_equal(struct _purple_hconv *hc1, struct _purple_hconv *hc2)
51 return (hc1->im == hc2->im &&
52 hc1->account == hc2->account &&
53 g_str_equal(hc1->name, hc2->name));
56 static void
57 _purple_conversations_hconv_free_key(struct _purple_hconv *hc)
59 g_free(hc->name);
60 g_free(hc);
63 void
64 purple_conversations_add(PurpleConversation *conv)
66 PurpleAccount *account;
67 struct _purple_hconv *hc;
69 g_return_if_fail(conv != NULL);
71 if (g_list_find(conversations, conv) != NULL)
72 return;
74 conversations = g_list_prepend(conversations, conv);
76 if (PURPLE_IS_IM_CONVERSATION(conv))
77 ims = g_list_prepend(ims, conv);
78 else
79 chats = g_list_prepend(chats, conv);
81 account = purple_conversation_get_account(conv);
83 hc = g_new(struct _purple_hconv, 1);
84 hc->name = g_strdup(purple_normalize(account,
85 purple_conversation_get_name(conv)));
86 hc->account = account;
87 hc->im = PURPLE_IS_IM_CONVERSATION(conv);
89 g_hash_table_insert(conversation_cache, hc, conv);
92 void
93 purple_conversations_remove(PurpleConversation *conv)
95 PurpleAccount *account;
96 struct _purple_hconv hc;
98 g_return_if_fail(conv != NULL);
100 conversations = g_list_remove(conversations, conv);
102 if (PURPLE_IS_IM_CONVERSATION(conv))
103 ims = g_list_remove(ims, conv);
104 else
105 chats = g_list_remove(chats, conv);
107 account = purple_conversation_get_account(conv);
109 hc.name = (gchar *)purple_normalize(account,
110 purple_conversation_get_name(conv));
111 hc.account = account;
112 hc.im = PURPLE_IS_IM_CONVERSATION(conv);
114 g_hash_table_remove(conversation_cache, &hc);
117 void
118 _purple_conversations_update_cache(PurpleConversation *conv, const char *name,
119 PurpleAccount *account)
121 PurpleAccount *old_account;
122 struct _purple_hconv *hc;
124 g_return_if_fail(conv != NULL);
125 g_return_if_fail(account != NULL || name != NULL);
127 old_account = purple_conversation_get_account(conv);
129 hc = g_new(struct _purple_hconv, 1);
130 hc->im = PURPLE_IS_IM_CONVERSATION(conv);
131 hc->account = old_account;
132 hc->name = (gchar *)purple_normalize(old_account,
133 purple_conversation_get_name(conv));
135 g_hash_table_remove(conversation_cache, hc);
137 if (account)
138 hc->account = account;
139 if (name)
140 hc->name = g_strdup(purple_normalize(hc->account, name));
142 g_hash_table_insert(conversation_cache, hc, conv);
145 GList *
146 purple_conversations_get_all(void)
148 return conversations;
151 GList *
152 purple_conversations_get_ims(void)
154 return ims;
157 GList *
158 purple_conversations_get_chats(void)
160 return chats;
163 PurpleConversation *
164 purple_conversations_find_with_account(const char *name,
165 PurpleAccount *account)
167 PurpleConversation *c = NULL;
168 struct _purple_hconv hc;
170 g_return_val_if_fail(name != NULL, NULL);
172 hc.name = (gchar *)purple_normalize(account, name);
173 hc.account = account;
175 hc.im = TRUE;
176 c = g_hash_table_lookup(conversation_cache, &hc);
177 if (!c) {
178 hc.im = FALSE;
179 c = g_hash_table_lookup(conversation_cache, &hc);
182 return c;
185 PurpleIMConversation *
186 purple_conversations_find_im_with_account(const char *name,
187 PurpleAccount *account)
189 PurpleIMConversation *im = NULL;
190 struct _purple_hconv hc;
192 g_return_val_if_fail(name != NULL, NULL);
194 hc.name = (gchar *)purple_normalize(account, name);
195 hc.account = account;
196 hc.im = TRUE;
198 im = g_hash_table_lookup(conversation_cache, &hc);
200 return im;
203 PurpleChatConversation *
204 purple_conversations_find_chat_with_account(const char *name,
205 PurpleAccount *account)
207 PurpleChatConversation *c = NULL;
208 struct _purple_hconv hc;
210 g_return_val_if_fail(name != NULL, NULL);
212 hc.name = (gchar *)purple_normalize(account, name);
213 hc.account = account;
214 hc.im = FALSE;
216 c = g_hash_table_lookup(conversation_cache, &hc);
218 return c;
221 PurpleChatConversation *
222 purple_conversations_find_chat(const PurpleConnection *gc, int id)
224 GList *l;
225 PurpleChatConversation *chat;
227 for (l = purple_conversations_get_chats(); l != NULL; l = l->next) {
228 chat = (PurpleChatConversation *)l->data;
230 if (purple_chat_conversation_get_id(chat) == id &&
231 purple_conversation_get_connection(PURPLE_CONVERSATION(chat)) == gc)
232 return chat;
235 return NULL;
238 void
239 purple_conversations_set_ui_ops(PurpleConversationUiOps *ops)
241 default_ops = ops;
244 PurpleConversationUiOps *
245 purple_conversations_get_ui_ops(void)
247 return default_ops;
250 void *
251 purple_conversations_get_handle(void)
253 static int handle;
255 return &handle;
258 void
259 purple_conversations_init(void)
261 void *handle = purple_conversations_get_handle();
263 conversation_cache = g_hash_table_new_full((GHashFunc)_purple_conversations_hconv_hash,
264 (GEqualFunc)_purple_conversations_hconv_equal,
265 (GDestroyNotify)_purple_conversations_hconv_free_key, NULL);
267 /**********************************************************************
268 * Register preferences
269 **********************************************************************/
271 /* Conversations */
272 purple_prefs_add_none("/purple/conversations");
274 /* Conversations -> Chat */
275 purple_prefs_add_none("/purple/conversations/chat");
276 purple_prefs_add_bool("/purple/conversations/chat/show_nick_change", TRUE);
278 /* Conversations -> IM */
279 purple_prefs_add_none("/purple/conversations/im");
280 purple_prefs_add_bool("/purple/conversations/im/send_typing", TRUE);
283 /**********************************************************************
284 * Register signals
285 **********************************************************************/
286 purple_signal_register(handle, "writing-im-msg",
287 purple_marshal_BOOLEAN__POINTER_POINTER, G_TYPE_BOOLEAN, 2,
288 PURPLE_TYPE_IM_CONVERSATION, PURPLE_TYPE_MESSAGE);
290 purple_signal_register(handle, "wrote-im-msg",
291 purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
292 PURPLE_TYPE_IM_CONVERSATION, PURPLE_TYPE_MESSAGE);
294 purple_signal_register(handle, "sent-attention",
295 purple_marshal_VOID__POINTER_POINTER_POINTER_UINT,
296 G_TYPE_NONE, 4, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING,
297 PURPLE_TYPE_CONVERSATION, G_TYPE_UINT);
299 purple_signal_register(handle, "got-attention",
300 purple_marshal_VOID__POINTER_POINTER_POINTER_UINT,
301 G_TYPE_NONE, 4, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING,
302 PURPLE_TYPE_CONVERSATION, G_TYPE_UINT);
304 purple_signal_register(handle, "sending-im-msg",
305 purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE,
306 2, PURPLE_TYPE_ACCOUNT, PURPLE_TYPE_MESSAGE);
308 purple_signal_register(handle, "sent-im-msg",
309 purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE,
310 2, PURPLE_TYPE_ACCOUNT, PURPLE_TYPE_MESSAGE);
312 purple_signal_register(handle, "receiving-im-msg",
313 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER,
314 G_TYPE_BOOLEAN, 5, PURPLE_TYPE_ACCOUNT,
315 G_TYPE_POINTER, /* pointer to a string */
316 G_TYPE_POINTER, /* pointer to a string */
317 PURPLE_TYPE_IM_CONVERSATION,
318 G_TYPE_POINTER); /* pointer to a string */
320 purple_signal_register(handle, "received-im-msg",
321 purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT,
322 G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING,
323 G_TYPE_STRING, PURPLE_TYPE_IM_CONVERSATION, G_TYPE_UINT);
325 purple_signal_register(handle, "blocked-im-msg",
326 purple_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT,
327 G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING,
328 G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT);
330 purple_signal_register(handle, "writing-chat-msg",
331 purple_marshal_BOOLEAN__POINTER_POINTER, G_TYPE_BOOLEAN, 2,
332 PURPLE_TYPE_IM_CONVERSATION, PURPLE_TYPE_MESSAGE);
334 purple_signal_register(handle, "wrote-chat-msg",
335 purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
336 PURPLE_TYPE_IM_CONVERSATION, PURPLE_TYPE_MESSAGE);
338 purple_signal_register(handle, "sending-chat-msg",
339 purple_marshal_VOID__POINTER_POINTER_UINT, G_TYPE_NONE,
340 3, PURPLE_TYPE_ACCOUNT, PURPLE_TYPE_MESSAGE, G_TYPE_UINT);
342 purple_signal_register(handle, "sent-chat-msg",
343 purple_marshal_VOID__POINTER_POINTER_UINT, G_TYPE_NONE,
344 3, PURPLE_TYPE_ACCOUNT, PURPLE_TYPE_MESSAGE, G_TYPE_UINT);
346 purple_signal_register(handle, "receiving-chat-msg",
347 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER,
348 G_TYPE_BOOLEAN, 5, PURPLE_TYPE_ACCOUNT,
349 G_TYPE_POINTER, /* pointer to a string */
350 G_TYPE_POINTER, /* pointer to a string */
351 PURPLE_TYPE_CHAT_CONVERSATION,
352 G_TYPE_POINTER); /* pointer to an unsigned int */
354 purple_signal_register(handle, "received-chat-msg",
355 purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT,
356 G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING,
357 G_TYPE_STRING, PURPLE_TYPE_CHAT_CONVERSATION, G_TYPE_UINT);
359 purple_signal_register(handle, "conversation-created",
360 purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
361 PURPLE_TYPE_CONVERSATION);
363 purple_signal_register(handle, "conversation-updated",
364 purple_marshal_VOID__POINTER_UINT, G_TYPE_NONE, 2,
365 PURPLE_TYPE_CONVERSATION, G_TYPE_UINT);
367 purple_signal_register(handle, "deleting-conversation",
368 purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
369 PURPLE_TYPE_CONVERSATION);
371 purple_signal_register(handle, "buddy-typing",
372 purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
373 PURPLE_TYPE_ACCOUNT, G_TYPE_STRING);
375 purple_signal_register(handle, "buddy-typed",
376 purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
377 PURPLE_TYPE_ACCOUNT, G_TYPE_STRING);
379 purple_signal_register(handle, "buddy-typing-stopped",
380 purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
381 PURPLE_TYPE_ACCOUNT, G_TYPE_STRING);
383 purple_signal_register(handle, "chat-user-joining",
384 purple_marshal_BOOLEAN__POINTER_POINTER_UINT,
385 G_TYPE_BOOLEAN, 3, PURPLE_TYPE_CHAT_CONVERSATION,
386 G_TYPE_STRING, G_TYPE_UINT);
388 purple_signal_register(handle, "chat-user-joined",
389 purple_marshal_VOID__POINTER_POINTER_UINT_UINT,
390 G_TYPE_NONE, 4, PURPLE_TYPE_CHAT_CONVERSATION,
391 G_TYPE_STRING, G_TYPE_UINT, G_TYPE_BOOLEAN);
393 purple_signal_register(handle, "chat-user-flags",
394 purple_marshal_VOID__POINTER_UINT_UINT, G_TYPE_NONE, 3,
395 PURPLE_TYPE_CHAT_USER, G_TYPE_UINT, G_TYPE_UINT);
397 purple_signal_register(handle, "chat-user-leaving",
398 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER,
399 G_TYPE_BOOLEAN, 3, PURPLE_TYPE_CHAT_CONVERSATION,
400 G_TYPE_STRING, G_TYPE_STRING);
402 purple_signal_register(handle, "chat-user-left",
403 purple_marshal_VOID__POINTER_POINTER_POINTER,
404 G_TYPE_NONE, 3, PURPLE_TYPE_CHAT_CONVERSATION,
405 G_TYPE_STRING, G_TYPE_STRING);
407 purple_signal_register(handle, "deleting-chat-user",
408 purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
409 PURPLE_TYPE_CHAT_USER);
411 purple_signal_register(handle, "chat-inviting-user",
412 purple_marshal_VOID__POINTER_POINTER_POINTER,
413 G_TYPE_NONE, 3, PURPLE_TYPE_CHAT_CONVERSATION,
414 G_TYPE_STRING,
415 G_TYPE_POINTER); /* pointer to a string */
417 purple_signal_register(handle, "chat-invited-user",
418 purple_marshal_VOID__POINTER_POINTER_POINTER,
419 G_TYPE_NONE, 3, PURPLE_TYPE_CHAT_CONVERSATION,
420 G_TYPE_STRING, G_TYPE_STRING);
422 purple_signal_register(handle, "chat-invited",
423 purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER,
424 G_TYPE_INT, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING,
425 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
427 purple_signal_register(handle, "chat-invite-blocked",
428 purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER,
429 G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING,
430 G_TYPE_STRING, G_TYPE_STRING,
431 G_TYPE_POINTER); /* (GHashTable *) */
433 purple_signal_register(handle, "chat-joined",
434 purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
435 PURPLE_TYPE_CHAT_CONVERSATION);
437 purple_signal_register(handle, "chat-join-failed",
438 purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
439 PURPLE_TYPE_CONNECTION, G_TYPE_POINTER);
441 purple_signal_register(handle, "chat-left",
442 purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
443 PURPLE_TYPE_CHAT_CONVERSATION);
445 purple_signal_register(handle, "chat-topic-changed",
446 purple_marshal_VOID__POINTER_POINTER_POINTER,
447 G_TYPE_NONE, 3, PURPLE_TYPE_CHAT_CONVERSATION,
448 G_TYPE_STRING, G_TYPE_STRING);
450 purple_signal_register(handle, "cleared-message-history",
451 purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
452 PURPLE_TYPE_CONVERSATION);
454 purple_signal_register(handle, "conversation-extended-menu",
455 purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
456 PURPLE_TYPE_CONVERSATION,
457 G_TYPE_POINTER); /* (GList **) */
460 void
461 purple_conversations_uninit(void)
463 while (conversations)
464 g_object_unref(G_OBJECT(conversations->data));
466 g_hash_table_destroy(conversation_cache);
467 purple_signals_unregister_by_instance(purple_conversations_get_handle());