libpurple/conversationtypes.c

branch
soc.2013.gobjectification
changeset 34651
88c104a20f4b
parent 34649
4a0ec0fff2e1
child 34663
cf9e572853b2
equal deleted inserted replaced
34650:fcc35d976057 34651:88c104a20f4b
17 * 17 *
18 * You should have received a copy of the GNU General Public License 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 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 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 */ 21 */
22 #include "internal.h"
22 #include "conversationtypes.h" 23 #include "conversationtypes.h"
24 #include "dbus-maybe.h"
25 #include "debug.h"
26 #include "enums.h"
23 27
24 #define SEND_TYPED_TIMEOUT_SECONDS 5 28 #define SEND_TYPED_TIMEOUT_SECONDS 5
25 29
26 #define PURPLE_CHAT_CONVERSATION_GET_PRIVATE(obj) \ 30 #define PURPLE_CHAT_CONVERSATION_GET_PRIVATE(obj) \
27 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CHAT_CONVERSATION, PurpleChatConversationPrivate)) 31 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CHAT_CONVERSATION, PurpleChatConversationPrivate))
44 /** 48 /**
45 * Data specific to Chats. 49 * Data specific to Chats.
46 */ 50 */
47 struct _PurpleChatConversationPrivate 51 struct _PurpleChatConversationPrivate
48 { 52 {
53 GList *in_room; /**< The users in the room.
54 * @deprecated Will be removed in 3.0.0 TODO
55 */
49 GList *ignored; /**< Ignored users. */ 56 GList *ignored; /**< Ignored users. */
50 char *who; /**< The person who set the topic. */ 57 char *who; /**< The person who set the topic. */
51 char *topic; /**< The topic. */ 58 char *topic; /**< The topic. */
52 int id; /**< The chat ID. */ 59 int id; /**< The chat ID. */
53 char *nick; /**< Your nick in this chat. */ 60 char *nick; /**< Your nick in this chat. */
56 GHashTable *users; /**< Hash table of the users in the room. */ 63 GHashTable *users; /**< Hash table of the users in the room. */
57 }; 64 };
58 65
59 /* Chat Property enums */ 66 /* Chat Property enums */
60 enum { 67 enum {
61 PROP_0, 68 CHAT_PROP_0,
62 PROP_TOPIC_WHO, 69 CHAT_PROP_TOPIC_WHO,
63 PROP_TOPIC, 70 CHAT_PROP_TOPIC,
64 PROP_CHAT_ID, 71 CHAT_PROP_ID,
65 PROP_NICK, 72 CHAT_PROP_NICK,
66 PROP_LEFT, 73 CHAT_PROP_LEFT,
67 PROP_LAST 74 CHAT_PROP_LAST
68 }; 75 };
69 76
70 /** 77 /**
71 * Data specific to Instant Messages. 78 * Data specific to Instant Messages.
72 */ 79 */
80 PurpleBuddyIcon *icon; /**< The buddy icon. */ 87 PurpleBuddyIcon *icon; /**< The buddy icon. */
81 }; 88 };
82 89
83 /* IM Property enums */ 90 /* IM Property enums */
84 enum { 91 enum {
85 PROP_0, 92 IM_PROP_0,
86 PROP_TYPING_STATE, 93 IM_PROP_TYPING_STATE,
87 PROP_ICON, 94 IM_PROP_ICON,
88 PROP_LAST 95 IM_PROP_LAST
89 }; 96 };
90 97
91 /** 98 /**
92 * Data for "Chat Buddies" 99 * Data for "Chat Buddies"
93 */ 100 */
94 struct _PurpleChatConversationBuddyPrivate 101 struct _PurpleChatConversationBuddyPrivate
95 { 102 {
103 /** The chat */
104 PurpleChatConversation *chat;
105
96 /** The chat participant's name in the chat. */ 106 /** The chat participant's name in the chat. */
97 char *name; 107 char *name;
98 108
99 /** The chat participant's alias, if known; @a NULL otherwise. */ 109 /** The chat participant's alias, if known; @a NULL otherwise. */
100 char *alias; 110 char *alias;
128 gpointer ui_data; 138 gpointer ui_data;
129 }; 139 };
130 140
131 /* Chat Buddy Property enums */ 141 /* Chat Buddy Property enums */
132 enum { 142 enum {
133 PROP_0, 143 CB_PROP_0,
134 PROP_NAME, 144 CB_PROP_CHAT,
135 PROP_ALIAS, 145 CB_PROP_NAME,
136 PROP_BUDDY, 146 CB_PROP_ALIAS,
137 PROP_FLAGS, 147 CB_PROP_BUDDY,
138 PROP_LAST 148 CB_PROP_FLAGS,
149 CB_PROP_LAST
139 }; 150 };
140 151
141 static PurpleConversationClass *parent_class; 152 static PurpleConversationClass *im_parent_class;
142 static GObjectClass *cb_parent_class; 153 static PurpleConversationClass *chat_parent_class;
154 static GObjectClass *cb_parent_class;
155
156 static int purple_chat_conversation_buddy_compare(PurpleChatConversationBuddy *a,
157 PurpleChatConversationBuddy *b);
143 158
144 /************************************************************************** 159 /**************************************************************************
145 * IM Conversation API 160 * IM Conversation API
146 **************************************************************************/ 161 **************************************************************************/
147 static gboolean 162 static gboolean
148 reset_typing_cb(gpointer data) 163 reset_typing_cb(gpointer data)
149 { 164 {
150 PurpleConversation *c = (PurpleConversation *)data; 165 PurpleIMConversation *im = (PurpleIMConversation *)data;
151 PurpleIMConversationPrivate *priv;
152
153 im = PURPLE_IM_CONVERSATION_GET_PRIVATE(c);
154 166
155 purple_im_conversation_set_typing_state(im, PURPLE_IM_CONVERSATION_NOT_TYPING); 167 purple_im_conversation_set_typing_state(im, PURPLE_IM_CONVERSATION_NOT_TYPING);
156 purple_im_conversation_stop_typing_timeout(im); 168 purple_im_conversation_stop_typing_timeout(im);
157 169
158 return FALSE; 170 return FALSE;
159 } 171 }
160 172
161 static gboolean 173 static gboolean
162 send_typed_cb(gpointer data) 174 send_typed_cb(gpointer data)
163 { 175 {
164 PurpleConversation *conv = (PurpleConversation *)data; 176 PurpleIMConversation *im = (PurpleIMConversation *)data;
165 PurpleConnection *gc; 177 PurpleConnection *gc;
166 const char *name; 178 const char *name;
167 179
168 g_return_val_if_fail(conv != NULL, FALSE); 180 g_return_val_if_fail(im != NULL, FALSE);
169 181
170 gc = purple_conversation_get_connection(conv); 182 gc = purple_conversation_get_connection(PURPLE_CONVERSATION(im));
171 name = purple_conversation_get_name(conv); 183 name = purple_conversation_get_name(PURPLE_CONVERSATION(im));
172 184
173 if (gc != NULL && name != NULL) { 185 if (gc != NULL && name != NULL) {
174 /* We set this to 1 so that PURPLE_IM_CONVERSATION_TYPING will be sent 186 /* We set this to 1 so that PURPLE_IM_CONVERSATION_TYPING will be sent
175 * if the Purple user types anything else. 187 * if the Purple user types anything else.
176 */ 188 */
177 purple_im_conversation_set_type_again(PURPLE_IM_CONVERSATION_GET_PRIVATE(conv), 1); 189 purple_im_conversation_set_type_again(im, 1);
178 190
179 serv_send_typing(gc, name, PURPLE_IM_CONVERSATION_TYPED); 191 serv_send_typing(gc, name, PURPLE_IM_CONVERSATION_TYPED);
180 192
181 purple_debug(PURPLE_DEBUG_MISC, "conversation", "typed...\n"); 193 purple_debug(PURPLE_DEBUG_MISC, "conversation", "typed...\n");
182 } 194 }
185 } 197 }
186 198
187 void 199 void
188 purple_im_conversation_set_icon(PurpleIMConversation *im, PurpleBuddyIcon *icon) 200 purple_im_conversation_set_icon(PurpleIMConversation *im, PurpleBuddyIcon *icon)
189 { 201 {
190 g_return_if_fail(im != NULL); 202 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
203
204 g_return_if_fail(priv != NULL);
191 205
192 if (priv->icon != icon) 206 if (priv->icon != icon)
193 { 207 {
194 purple_buddy_icon_unref(priv->icon); 208 purple_buddy_icon_unref(priv->icon);
195 209
196 priv->icon = (icon == NULL ? NULL : purple_buddy_icon_ref(icon)); 210 priv->icon = (icon == NULL ? NULL : purple_buddy_icon_ref(icon));
197 } 211 }
198 212
199 purple_conversation_update(purple_im_conversation_get_conversation(im), 213 purple_conversation_update(PURPLE_CONVERSATION(im),
200 PURPLE_CONVERSATION_UPDATE_ICON); 214 PURPLE_CONVERSATION_UPDATE_ICON);
201 } 215 }
202 216
203 PurpleBuddyIcon * 217 PurpleBuddyIcon *
204 purple_im_conversation_get_icon(const PurpleIMConversation *im) 218 purple_im_conversation_get_icon(const PurpleIMConversation *im)
205 { 219 {
206 g_return_val_if_fail(im != NULL, NULL); 220 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
221
222 g_return_val_if_fail(priv != NULL, NULL);
207 223
208 return priv->icon; 224 return priv->icon;
209 } 225 }
210 226
211 void 227 void
212 purple_im_conversation_set_typing_state(PurpleIMConversation *im, PurpleIMConversationTypingState state) 228 purple_im_conversation_set_typing_state(PurpleIMConversation *im, PurpleIMConversationTypingState state)
213 { 229 {
214 g_return_if_fail(im != NULL); 230 PurpleAccount *account;
231 const char *name;
232 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
233
234 g_return_if_fail(priv != NULL);
235
236 name = purple_conversation_get_name(PURPLE_CONVERSATION(im));
237 account = purple_conversation_get_account(PURPLE_CONVERSATION(im));
215 238
216 if (priv->typing_state != state) 239 if (priv->typing_state != state)
217 { 240 {
218 priv->typing_state = state; 241 priv->typing_state = state;
219 242
220 switch (state) 243 switch (state)
221 { 244 {
222 case PURPLE_IM_CONVERSATION_TYPING: 245 case PURPLE_IM_CONVERSATION_TYPING:
223 purple_signal_emit(purple_conversations_get_handle(), 246 purple_signal_emit(purple_conversations_get_handle(),
224 "buddy-typing", priv->priv->account, priv->priv->name); 247 "buddy-typing", account, name);
225 break; 248 break;
226 case PURPLE_IM_CONVERSATION_TYPED: 249 case PURPLE_IM_CONVERSATION_TYPED:
227 purple_signal_emit(purple_conversations_get_handle(), 250 purple_signal_emit(purple_conversations_get_handle(),
228 "buddy-typed", priv->priv->account, priv->priv->name); 251 "buddy-typed", account, name);
229 break; 252 break;
230 case PURPLE_IM_CONVERSATION_NOT_TYPING: 253 case PURPLE_IM_CONVERSATION_NOT_TYPING:
231 purple_signal_emit(purple_conversations_get_handle(), 254 purple_signal_emit(purple_conversations_get_handle(),
232 "buddy-typing-stopped", priv->priv->account, priv->priv->name); 255 "buddy-typing-stopped", account, name);
233 break; 256 break;
234 } 257 }
235 258
236 purple_im_conversation_update_typing(im); 259 purple_im_conversation_update_typing(im);
237 } 260 }
238 } 261 }
239 262
240 PurpleIMConversationTypingState 263 PurpleIMConversationTypingState
241 purple_im_conversation_get_typing_state(const PurpleIMConversation *im) 264 purple_im_conversation_get_typing_state(const PurpleIMConversation *im)
242 { 265 {
243 g_return_val_if_fail(im != NULL, 0); 266 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
267
268 g_return_val_if_fail(priv != NULL, 0);
244 269
245 return priv->typing_state; 270 return priv->typing_state;
246 } 271 }
247 272
248 void 273 void
249 purple_im_conversation_start_typing_timeout(PurpleIMConversation *im, int timeout) 274 purple_im_conversation_start_typing_timeout(PurpleIMConversation *im, int timeout)
250 { 275 {
251 PurpleConversation *conv; 276 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
252 277
253 g_return_if_fail(im != NULL); 278 g_return_if_fail(priv != NULL);
254 279
255 if (priv->typing_timeout > 0) 280 if (priv->typing_timeout > 0)
256 purple_im_conversation_stop_typing_timeout(im); 281 purple_im_conversation_stop_typing_timeout(im);
257 282
258 conv = purple_im_conversation_get_conversation(im); 283 priv->typing_timeout = purple_timeout_add_seconds(timeout, reset_typing_cb, im);
259
260 priv->typing_timeout = purple_timeout_add_seconds(timeout, reset_typing_cb, conv);
261 } 284 }
262 285
263 void 286 void
264 purple_im_conversation_stop_typing_timeout(PurpleIMConversation *im) 287 purple_im_conversation_stop_typing_timeout(PurpleIMConversation *im)
265 { 288 {
266 g_return_if_fail(im != NULL); 289 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
290
291 g_return_if_fail(priv != NULL);
267 292
268 if (priv->typing_timeout == 0) 293 if (priv->typing_timeout == 0)
269 return; 294 return;
270 295
271 purple_timeout_remove(priv->typing_timeout); 296 purple_timeout_remove(priv->typing_timeout);
273 } 298 }
274 299
275 guint 300 guint
276 purple_im_conversation_get_typing_timeout(const PurpleIMConversation *im) 301 purple_im_conversation_get_typing_timeout(const PurpleIMConversation *im)
277 { 302 {
278 g_return_val_if_fail(im != NULL, 0); 303 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
304
305 g_return_val_if_fail(priv != NULL, 0);
279 306
280 return priv->typing_timeout; 307 return priv->typing_timeout;
281 } 308 }
282 309
283 void 310 void
284 purple_im_conversation_set_type_again(PurpleIMConversation *im, unsigned int val) 311 purple_im_conversation_set_type_again(PurpleIMConversation *im, unsigned int val)
285 { 312 {
286 g_return_if_fail(im != NULL); 313 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
314
315 g_return_if_fail(priv != NULL);
287 316
288 if (val == 0) 317 if (val == 0)
289 priv->type_again = 0; 318 priv->type_again = 0;
290 else 319 else
291 priv->type_again = time(NULL) + val; 320 priv->type_again = time(NULL) + val;
292 } 321 }
293 322
294 time_t 323 time_t
295 purple_im_conversation_get_type_again(const PurpleIMConversation *im) 324 purple_im_conversation_get_type_again(const PurpleIMConversation *im)
296 { 325 {
297 g_return_val_if_fail(im != NULL, 0); 326 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
327
328 g_return_val_if_fail(priv != NULL, 0);
298 329
299 return priv->type_again; 330 return priv->type_again;
300 } 331 }
301 332
302 void 333 void
303 purple_im_conversation_start_send_typed_timeout(PurpleIMConversation *im) 334 purple_im_conversation_start_send_typed_timeout(PurpleIMConversation *im)
304 { 335 {
305 g_return_if_fail(im != NULL); 336 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
337
338 g_return_if_fail(priv != NULL);
306 339
307 priv->send_typed_timeout = purple_timeout_add_seconds(SEND_TYPED_TIMEOUT_SECONDS, 340 priv->send_typed_timeout = purple_timeout_add_seconds(SEND_TYPED_TIMEOUT_SECONDS,
308 send_typed_cb, 341 send_typed_cb, im);
309 purple_im_conversation_get_conversation(im));
310 } 342 }
311 343
312 void 344 void
313 purple_im_conversation_stop_send_typed_timeout(PurpleIMConversation *im) 345 purple_im_conversation_stop_send_typed_timeout(PurpleIMConversation *im)
314 { 346 {
315 g_return_if_fail(im != NULL); 347 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
348
349 g_return_if_fail(priv != NULL);
316 350
317 if (priv->send_typed_timeout == 0) 351 if (priv->send_typed_timeout == 0)
318 return; 352 return;
319 353
320 purple_timeout_remove(priv->send_typed_timeout); 354 purple_timeout_remove(priv->send_typed_timeout);
322 } 356 }
323 357
324 guint 358 guint
325 purple_im_conversation_get_send_typed_timeout(const PurpleIMConversation *im) 359 purple_im_conversation_get_send_typed_timeout(const PurpleIMConversation *im)
326 { 360 {
327 g_return_val_if_fail(im != NULL, 0); 361 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
362
363 g_return_val_if_fail(priv != NULL, 0);
328 364
329 return priv->send_typed_timeout; 365 return priv->send_typed_timeout;
330 } 366 }
331 367
332 void 368 void
333 purple_im_conversation_update_typing(PurpleIMConversation *im) 369 purple_im_conversation_update_typing(PurpleIMConversation *im)
334 { 370 {
335 g_return_if_fail(im != NULL); 371 g_return_if_fail(im != NULL);
336 372
337 purple_conversation_update(purple_im_conversation_get_conversation(im), 373 purple_conversation_update(PURPLE_CONVERSATION(im),
338 PURPLE_CONVERSATION_UPDATE_TYPING); 374 PURPLE_CONVERSATION_UPDATE_TYPING);
339 } 375 }
340 376
341 static void 377 static void
342 im_conversation_write_message(PurpleIMConversation *im, const char *who, const char *message, 378 im_conversation_write_message(PurpleConversation *conv, const char *who, const char *message,
343 PurpleMessageFlags flags, time_t mtime) 379 PurpleMessageFlags flags, time_t mtime)
344 { 380 {
345 PurpleConversation *c; 381 PurpleConversationUiOps *ops;
346 382
347 g_return_if_fail(im != NULL); 383 g_return_if_fail(conv != NULL);
348 g_return_if_fail(message != NULL); 384 g_return_if_fail(message != NULL);
349 385
350 c = purple_im_conversation_get_conversation(im); 386 ops = purple_conversation_get_ui_ops(conv);
351 387
352 if ((flags & PURPLE_MESSAGE_RECV) == PURPLE_MESSAGE_RECV) { 388 if ((flags & PURPLE_MESSAGE_RECV) == PURPLE_MESSAGE_RECV) {
353 purple_im_conversation_set_typing_state(im, PURPLE_IM_CONVERSATION_NOT_TYPING); 389 purple_im_conversation_set_typing_state(PURPLE_IM_CONVERSATION(conv),
390 PURPLE_IM_CONVERSATION_NOT_TYPING);
354 } 391 }
355 392
356 /* Pass this on to either the ops structure or the default write func. */ 393 /* Pass this on to either the ops structure or the default write func. */
357 if (c->ui_ops != NULL && c->ui_ops->write_im != NULL) 394 if (ops != NULL && ops->write_im != NULL)
358 c->ui_ops->write_im(c, who, message, flags, mtime); 395 ops->write_im(PURPLE_IM_CONVERSATION(conv), who, message, flags, mtime);
359 else 396 else
360 purple_conversation_write(c, who, message, flags, mtime); 397 purple_conversation_write(conv, who, message, flags, mtime);
361 }
362
363 static void
364 im_conversation_send_message(PurpleIMConversation *im, const char *message, PurpleMessageFlags flags)
365 {
366 g_return_if_fail(im != NULL);
367 g_return_if_fail(message != NULL);
368
369 common_send(purple_im_conversation_get_conversation(im), message, flags);
370 } 398 }
371 399
372 /************************************************************************** 400 /**************************************************************************
373 * GObject code for IMs 401 * GObject code for IMs
374 **************************************************************************/ 402 **************************************************************************/
375 403
376 /* GObject Property names */ 404 /* GObject Property names */
377 #define PROP_TYPING_STATE_S "typing-state" 405 #define IM_PROP_TYPING_STATE_S "typing-state"
378 #define PROP_ICON_S "icon" 406 #define IM_PROP_ICON_S "icon"
379 407
380 /* Set method for GObject properties */ 408 /* Set method for GObject properties */
381 static void 409 static void
382 purple_im_conversation_set_property(GObject *obj, guint param_id, const GValue *value, 410 purple_im_conversation_set_property(GObject *obj, guint param_id, const GValue *value,
383 GParamSpec *pspec) 411 GParamSpec *pspec)
384 { 412 {
385 PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj); 413 PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj);
386 414
387 switch (param_id) { 415 switch (param_id) {
388 case PROP_TYPING_STATE: 416 case IM_PROP_TYPING_STATE:
389 purple_im_conversation_set_typing_state(im, g_value_get_enum(value)); 417 purple_im_conversation_set_typing_state(im, g_value_get_enum(value));
390 break; 418 break;
391 case PROP_ICON: 419 case IM_PROP_ICON:
392 #warning TODO: change get_pointer to get_object if PurpleBuddyIcon is a GObject 420 #warning TODO: change get_pointer to get_object if PurpleBuddyIcon is a GObject
393 purple_im_conversation_set_icon(chat, g_value_get_pointer(value)); 421 purple_im_conversation_set_icon(im, g_value_get_pointer(value));
394 break; 422 break;
395 default: 423 default:
396 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); 424 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
397 break; 425 break;
398 } 426 }
399 } 427 }
400 428
401 /* Get method for GObject properties */ 429 /* Get method for GObject properties */
402 static void 430 static void
403 purple_chat_conversation_get_property(GObject *obj, guint param_id, GValue *value, 431 purple_im_conversation_get_property(GObject *obj, guint param_id, GValue *value,
404 GParamSpec *pspec) 432 GParamSpec *pspec)
405 { 433 {
406 PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj); 434 PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj);
407 435
408 switch (param_id) { 436 switch (param_id) {
409 case PROP_TYPING_STATE: 437 case IM_PROP_TYPING_STATE:
410 g_value_set_enum(value, purple_im_conversation_get_typing_state(chat); 438 g_value_set_enum(value, purple_im_conversation_get_typing_state(im));
411 break; 439 break;
412 case PROP_ICON: 440 case IM_PROP_ICON:
413 #warning TODO: change set_pointer to set_object if PurpleBuddyIcon is a GObject 441 #warning TODO: change set_pointer to set_object if PurpleBuddyIcon is a GObject
414 g_value_set_pointer(value, purple_im_conversation_get_icon(im); 442 g_value_set_pointer(value, purple_im_conversation_get_icon(im));
415 break; 443 break;
416 default: 444 default:
417 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); 445 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
418 break; 446 break;
419 } 447 }
422 /* GObject dispose function */ 450 /* GObject dispose function */
423 static void 451 static void
424 purple_im_conversation_dispose(GObject *object) 452 purple_im_conversation_dispose(GObject *object)
425 { 453 {
426 PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object); 454 PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object);
427 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); 455 PurpleConnection *gc = purple_conversation_get_connection(PURPLE_CONVERSATION(im));
456 PurplePluginProtocolInfo *prpl_info = NULL;
457 const char *name = purple_conversation_get_name(PURPLE_CONVERSATION(im));
428 458
429 if (gc != NULL) 459 if (gc != NULL)
430 { 460 {
431 /* Still connected */ 461 /* Still connected */
432 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); 462 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
436 466
437 if (gc && prpl_info->convo_closed != NULL) 467 if (gc && prpl_info->convo_closed != NULL)
438 prpl_info->convo_closed(gc, name); 468 prpl_info->convo_closed(gc, name);
439 } 469 }
440 470
441 purple_im_conversation_stop_typing_timeout(priv->u.im); 471 purple_im_conversation_stop_typing_timeout(im);
442 purple_im_conversation_stop_send_typed_timeout(priv->u.im); 472 purple_im_conversation_stop_send_typed_timeout(im);
443 473
444 parent_class->dispose(object); 474 G_OBJECT_CLASS(im_parent_class)->dispose(object);
445 } 475 }
446 476
447 /* GObject finalize function */ 477 /* GObject finalize function */
448 static void 478 static void
449 purple_im_conversation_finalize(GObject *object) 479 purple_im_conversation_finalize(GObject *object)
450 { 480 {
451 PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object); 481 PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object);
452 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); 482 PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im);
453 483
454 purple_buddy_icon_unref(priv->u.im->icon); 484 purple_buddy_icon_unref(priv->icon);
455 485
456 g_free(priv->u.im); 486 G_OBJECT_CLASS(im_parent_class)->finalize(object);
457
458 parent_class->finalize(object);
459 } 487 }
460 488
461 /* Class initializer function */ 489 /* Class initializer function */
462 static void purple_im_conversation_class_init(PurpleIMConversationClass *klass) 490 static void purple_im_conversation_class_init(PurpleIMConversationClass *klass)
463 { 491 {
464 GObjectClass *obj_class = G_OBJECT_CLASS(klass); 492 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
465 493
466 parent_class = g_type_class_peek_parent(klass); 494 im_parent_class = g_type_class_peek_parent(klass);
467 495
468 obj_class->dispose = purple_im_conversation_dispose; 496 obj_class->dispose = purple_im_conversation_dispose;
469 obj_class->finalize = purple_im_conversation_finalize; 497 obj_class->finalize = purple_im_conversation_finalize;
470 498
471 /* Setup properties */ 499 /* Setup properties */
472 obj_class->get_property = purple_im_conversation_get_property; 500 obj_class->get_property = purple_im_conversation_get_property;
473 obj_class->set_property = purple_im_conversation_set_property; 501 obj_class->set_property = purple_im_conversation_set_property;
474 502
475 parent_class->write_message = im_conversation_write_message; 503 im_parent_class->write_message = im_conversation_write_message;
476 parent_class->send_message = im_conversation_send_message; 504
477 505 g_object_class_install_property(obj_class, IM_PROP_TYPING_STATE,
478 g_object_class_install_property(obj_class, PROP_TYPING_STATE, 506 g_param_spec_enum(IM_PROP_TYPING_STATE_S, _("Typing state"),
479 g_param_spec_enum(PROP_TYPING_STATE_S, _("Typing state"),
480 _("Status of the user's typing of a message."), 507 _("Status of the user's typing of a message."),
481 PURPLE_TYPE_IM_CONVERSATION_TYPING_STATE, 508 PURPLE_TYPE_IM_CONVERSATION_TYPING_STATE,
482 PURPLE_IM_CONVERSATION_NOT_TYPING, G_PARAM_READWRITE) 509 PURPLE_IM_CONVERSATION_NOT_TYPING, G_PARAM_READWRITE)
483 ); 510 );
484 511
485 #warning TODO: change spec_pointer to spec_object if PurpleBuddyIcon is a GObject 512 #warning TODO: change spec_pointer to spec_object if PurpleBuddyIcon is a GObject
486 g_object_class_install_property(obj_class, PROP_ICON, 513 g_object_class_install_property(obj_class, IM_PROP_ICON,
487 g_param_spec_pointer(PROP_ICON_S, _("Buddy icon"), 514 g_param_spec_pointer(IM_PROP_ICON_S, _("Buddy icon"),
488 _("The buddy icon for the IM."), 515 _("The buddy icon for the IM."),
489 G_PARAM_READWRITE) 516 G_PARAM_READWRITE)
490 ); 517 );
491 518
492 g_type_class_add_private(klass, sizeof(PurpleIMConversationPrivate)); 519 g_type_class_add_private(klass, sizeof(PurpleIMConversationPrivate));
521 548
522 PurpleIMConversation * 549 PurpleIMConversation *
523 purple_im_conversation_new(PurpleAccount *account, const char *name) 550 purple_im_conversation_new(PurpleAccount *account, const char *name)
524 { 551 {
525 PurpleIMConversation *im; 552 PurpleIMConversation *im;
553 PurpleConversation *conv;
526 PurpleConnection *gc; 554 PurpleConnection *gc;
527 PurpleConversationUiOps *ops; 555 PurpleConversationUiOps *ops;
528 PurpleBuddyIcon *icon; 556 PurpleBuddyIcon *icon;
529 557
530 g_return_val_if_fail(account != NULL, NULL); 558 g_return_val_if_fail(account != NULL, NULL);
531 g_return_val_if_fail(name != NULL, NULL); 559 g_return_val_if_fail(name != NULL, NULL);
532 560
533 /* Check if this conversation already exists. */ 561 /* Check if this conversation already exists. */
534 if ((im = purple_conversations_find_im_with_account(type, name, account)) != NULL) 562 if ((im = purple_conversations_find_im_with_account(name, account)) != NULL)
535 return im; 563 return im;
536 564
537 gc = purple_account_get_connection(account); 565 gc = purple_account_get_connection(account);
538 g_return_val_if_fail(gc != NULL, NULL); 566 g_return_val_if_fail(gc != NULL, NULL);
539 567
544 "account", account, 572 "account", account,
545 "name", name, 573 "name", name,
546 "title", name, 574 "title", name,
547 NULL); 575 NULL);
548 576
577 conv = PURPLE_CONVERSATION(im);
578
549 /* copy features from the connection. */ 579 /* copy features from the connection. */
550 purple_conversation_set_features(PURPLE_CONVERSATION(im), 580 purple_conversation_set_features(conv,
551 purple_connection_get_flags(gc)); 581 purple_connection_get_flags(gc));
552 582
553 purple_conversations_add(PURPLE_CONVERSATION(im)); 583 purple_conversations_add(conv);
554 if ((icon = purple_buddy_icons_find(account, name))) 584 if ((icon = purple_buddy_icons_find(account, name)))
555 { 585 {
556 purple_im_conversation_set_icon(im, icon); 586 purple_im_conversation_set_icon(im, icon);
557 /* purple_im_conversation_set_icon refs the icon. */ 587 /* purple_im_conversation_set_icon refs the icon. */
558 purple_buddy_icon_unref(icon); 588 purple_buddy_icon_unref(icon);
559 } 589 }
560 590
561 if (purple_prefs_get_bool("/purple/logging/log_ims")) 591 if (purple_prefs_get_bool("/purple/logging/log_ims"))
562 { 592 purple_conversation_set_logging(conv, TRUE);
563 purple_conversation_set_logging(PURPLE_CONVERSATION(im), TRUE);
564 open_log(conv);
565 }
566 593
567 /* Auto-set the title. */ 594 /* Auto-set the title. */
568 purple_conversation_autoset_title(PURPLE_CONVERSATION(im)); 595 purple_conversation_autoset_title(conv);
569 596
570 /* Don't move this.. it needs to be one of the last things done otherwise 597 /* Don't move this.. it needs to be one of the last things done otherwise
571 * it causes mysterious crashes on my system. 598 * it causes mysterious crashes on my system.
572 * -- Gary 599 * -- Gary
573 */ 600 */
574 ops = purple_conversations_get_ui_ops(); 601 ops = purple_conversations_get_ui_ops();
575 purple_conversation_set_ui_ops(PURPLE_CONVERSATION(im), ops); 602 purple_conversation_set_ui_ops(conv, ops);
576 if (ops != NULL && ops->create_conversation != NULL) 603 if (ops != NULL && ops->create_conversation != NULL)
577 ops->create_conversation(PURPLE_CONVERSATION(im)); 604 ops->create_conversation(conv);
578 605
579 purple_signal_emit(purple_conversations_get_handle(), 606 purple_signal_emit(purple_conversations_get_handle(),
580 "conversation-created", im); /* TODO im-created */ 607 "conversation-created", im); /* TODO im-created */
581 608
582 return im; 609 return im;
583 } 610 }
584 611
585 /************************************************************************** 612 /**************************************************************************
586 * Chat Conversation API 613 * Chat Conversation API
587 **************************************************************************/ 614 **************************************************************************/
588 PurpleConversation * 615 static guint
589 purple_chat_conversation_get_conversation(const PurpleChatConversation *chat) 616 _purple_conversation_user_hash(gconstpointer data)
590 { 617 {
591 g_return_val_if_fail(chat != NULL, NULL); 618 const gchar *name = data;
592 619 gchar *collated;
593 return priv->conv; 620 guint hash;
621
622 collated = g_utf8_collate_key(name, -1);
623 hash = g_str_hash(collated);
624 g_free(collated);
625 return hash;
626 }
627
628 static gboolean
629 _purple_conversation_user_equal(gconstpointer a, gconstpointer b)
630 {
631 return !g_utf8_collate(a, b);
594 } 632 }
595 633
596 GList * 634 GList *
597 purple_chat_conversation_get_users(const PurpleChatConversation *chat) 635 purple_chat_conversation_get_users(const PurpleChatConversation *chat)
598 { 636 {
599 g_return_val_if_fail(chat != NULL, NULL); 637 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
638
639 g_return_val_if_fail(priv != NULL, NULL);
600 640
601 return priv->in_room; 641 return priv->in_room;
602 } 642 }
603 643
604 void 644 void
605 purple_chat_conversation_ignore(PurpleChatConversation *chat, const char *name) 645 purple_chat_conversation_ignore(PurpleChatConversation *chat, const char *name)
606 { 646 {
607 g_return_if_fail(chat != NULL); 647 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
648
649 g_return_if_fail(priv != NULL);
608 g_return_if_fail(name != NULL); 650 g_return_if_fail(name != NULL);
609 651
610 /* Make sure the user isn't already ignored. */ 652 /* Make sure the user isn't already ignored. */
611 if (purple_chat_conversation_is_ignored_user(chat, name)) 653 if (purple_chat_conversation_is_ignored_user(chat, name))
612 return; 654 return;
617 659
618 void 660 void
619 purple_chat_conversation_unignore(PurpleChatConversation *chat, const char *name) 661 purple_chat_conversation_unignore(PurpleChatConversation *chat, const char *name)
620 { 662 {
621 GList *item; 663 GList *item;
622 664 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
623 g_return_if_fail(chat != NULL); 665
666 g_return_if_fail(priv != NULL);
624 g_return_if_fail(name != NULL); 667 g_return_if_fail(name != NULL);
625 668
626 /* Make sure the user is actually ignored. */ 669 /* Make sure the user is actually ignored. */
627 if (!purple_chat_conversation_is_ignored_user(chat, name)) 670 if (!purple_chat_conversation_is_ignored_user(chat, name))
628 return; 671 return;
638 } 681 }
639 682
640 GList * 683 GList *
641 purple_chat_conversation_set_ignored(PurpleChatConversation *chat, GList *ignored) 684 purple_chat_conversation_set_ignored(PurpleChatConversation *chat, GList *ignored)
642 { 685 {
643 g_return_val_if_fail(chat != NULL, NULL); 686 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
687
688 g_return_val_if_fail(priv != NULL, NULL);
644 689
645 priv->ignored = ignored; 690 priv->ignored = ignored;
646
647 return ignored; 691 return ignored;
648 } 692 }
649 693
650 GList * 694 GList *
651 purple_chat_conversation_get_ignored(const PurpleChatConversation *chat) 695 purple_chat_conversation_get_ignored(const PurpleChatConversation *chat)
652 { 696 {
653 g_return_val_if_fail(chat != NULL, NULL); 697 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
698
699 g_return_val_if_fail(priv != NULL, NULL);
654 700
655 return priv->ignored; 701 return priv->ignored;
656 } 702 }
657 703
658 const char * 704 const char *
695 } 741 }
696 742
697 void 743 void
698 purple_chat_conversation_set_topic(PurpleChatConversation *chat, const char *who, const char *topic) 744 purple_chat_conversation_set_topic(PurpleChatConversation *chat, const char *who, const char *topic)
699 { 745 {
700 g_return_if_fail(chat != NULL); 746 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
747
748 g_return_if_fail(priv != NULL);
701 749
702 g_free(priv->who); 750 g_free(priv->who);
703 g_free(priv->topic); 751 g_free(priv->topic);
704 752
705 priv->who = g_strdup(who); 753 priv->who = g_strdup(who);
706 priv->topic = g_strdup(topic); 754 priv->topic = g_strdup(topic);
707 755
708 purple_conversation_update(purple_chat_conversation_get_conversation(chat), 756 purple_conversation_update(PURPLE_CONVERSATION(chat),
709 PURPLE_CONVERSATION_UPDATE_TOPIC); 757 PURPLE_CONVERSATION_UPDATE_TOPIC);
710 758
711 purple_signal_emit(purple_conversations_get_handle(), "chat-topic-changed", 759 purple_signal_emit(purple_conversations_get_handle(), "chat-topic-changed",
712 priv->conv, priv->who, priv->topic); 760 chat, priv->who, priv->topic);
713 } 761 }
714 762
715 const char * 763 const char *
716 purple_chat_conversation_get_topic(const PurpleChatConversation *chat) 764 purple_chat_conversation_get_topic(const PurpleChatConversation *chat)
717 { 765 {
718 g_return_val_if_fail(chat != NULL, NULL); 766 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
767
768 g_return_val_if_fail(priv != NULL, NULL);
719 769
720 return priv->topic; 770 return priv->topic;
721 } 771 }
722 772
723 const char * 773 const char *
724 purple_chat_conversation_get_topic_who(const PurpleChatConversation *chat) 774 purple_chat_conversation_get_topic_who(const PurpleChatConversation *chat)
725 { 775 {
726 g_return_val_if_fail(chat != NULL, NULL); 776 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
777
778 g_return_val_if_fail(priv != NULL, NULL);
727 779
728 return priv->who; 780 return priv->who;
729 } 781 }
730 782
731 void 783 void
732 purple_chat_conversation_set_id(PurpleChatConversation *chat, int id) 784 purple_chat_conversation_set_id(PurpleChatConversation *chat, int id)
733 { 785 {
734 g_return_if_fail(chat != NULL); 786 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
787
788 g_return_if_fail(priv != NULL);
735 789
736 priv->id = id; 790 priv->id = id;
737 } 791 }
738 792
739 int 793 int
740 purple_chat_conversation_get_id(const PurpleChatConversation *chat) 794 purple_chat_conversation_get_id(const PurpleChatConversation *chat)
741 { 795 {
742 g_return_val_if_fail(chat != NULL, -1); 796 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
797
798 g_return_val_if_fail(priv != NULL, -1);
743 799
744 return priv->id; 800 return priv->id;
745 } 801 }
746 802
747 static void 803 static void
748 chat_conversation_write_message(PurpleChatConversation *chat, const char *who, const char *message, 804 chat_conversation_write_message(PurpleConversation *conv, const char *who, const char *message,
749 PurpleMessageFlags flags, time_t mtime) 805 PurpleMessageFlags flags, time_t mtime)
750 { 806 {
751 PurpleAccount *account; 807 PurpleAccount *account;
752 PurpleConversation *conv; 808 PurpleConversationUiOps *ops;
753 PurpleConnection *gc; 809 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv);
754 810
755 g_return_if_fail(chat != NULL); 811 g_return_if_fail(priv != NULL);
756 g_return_if_fail(who != NULL); 812 g_return_if_fail(who != NULL);
757 g_return_if_fail(message != NULL); 813 g_return_if_fail(message != NULL);
758 814
759 conv = purple_chat_conversation_get_conversation(chat); 815 account = purple_conversation_get_account(conv);
760 gc = purple_conversation_get_connection(conv);
761 account = purple_connection_get_account(gc);
762 816
763 /* Don't display this if the person who wrote it is ignored. */ 817 /* Don't display this if the person who wrote it is ignored. */
764 if (purple_chat_conversation_is_ignored_user(chat, who)) 818 if (purple_chat_conversation_is_ignored_user(PURPLE_CHAT_CONVERSATION(conv), who))
765 return; 819 return;
766 820
767 if (!(flags & PURPLE_MESSAGE_WHISPER)) { 821 if (!(flags & PURPLE_MESSAGE_WHISPER)) {
768 const char *str; 822 const char *str;
769 823
777 if (purple_utf8_has_word(message, priv->nick)) 831 if (purple_utf8_has_word(message, priv->nick))
778 flags |= PURPLE_MESSAGE_NICK; 832 flags |= PURPLE_MESSAGE_NICK;
779 } 833 }
780 } 834 }
781 835
836 ops = purple_conversation_get_ui_ops(conv);
837
782 /* Pass this on to either the ops structure or the default write func. */ 838 /* Pass this on to either the ops structure or the default write func. */
783 if (priv->ui_ops != NULL && priv->ui_ops->write_chat != NULL) 839 if (ops != NULL && ops->write_chat != NULL)
784 priv->ui_ops->write_chat(conv, who, message, flags, mtime); 840 ops->write_chat(PURPLE_CHAT_CONVERSATION(conv), who, message, flags, mtime);
785 else 841 else
786 purple_conversation_write(conv, who, message, flags, mtime); 842 purple_conversation_write(conv, who, message, flags, mtime);
787 }
788
789 static void
790 chat_conversation_send_message(PurpleChatConversation *chat, const char *message, PurpleMessageFlags flags)
791 {
792 g_return_if_fail(chat != NULL);
793 g_return_if_fail(message != NULL);
794
795 common_send(purple_chat_conversation_get_conversation(chat), message, flags);
796 } 843 }
797 844
798 void 845 void
799 purple_chat_conversation_add_user(PurpleChatConversation *chat, const char *user, 846 purple_chat_conversation_add_user(PurpleChatConversation *chat, const char *user,
800 const char *extra_msg, PurpleChatConversationBuddyFlags flags, 847 const char *extra_msg, PurpleChatConversationBuddyFlags flags,
816 GList *flags, gboolean new_arrivals) 863 GList *flags, gboolean new_arrivals)
817 { 864 {
818 PurpleConversation *conv; 865 PurpleConversation *conv;
819 PurpleConversationUiOps *ops; 866 PurpleConversationUiOps *ops;
820 PurpleChatConversationBuddy *cbuddy; 867 PurpleChatConversationBuddy *cbuddy;
868 PurpleChatConversationPrivate *priv;
869 PurpleAccount *account;
821 PurpleConnection *gc; 870 PurpleConnection *gc;
822 PurplePluginProtocolInfo *prpl_info; 871 PurplePluginProtocolInfo *prpl_info;
823 GList *ul, *fl; 872 GList *ul, *fl;
824 GList *cbuddies = NULL; 873 GList *cbuddies = NULL;
825 874
826 g_return_if_fail(chat != NULL); 875 priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
876
877 g_return_if_fail(priv != NULL);
827 g_return_if_fail(users != NULL); 878 g_return_if_fail(users != NULL);
828 879
829 conv = purple_chat_conversation_get_conversation(chat); 880 conv = PURPLE_CONVERSATION(chat);
830 ops = purple_conversation_get_ui_ops(conv); 881 ops = purple_conversation_get_ui_ops(conv);
831 882
883 account = purple_conversation_get_account(conv);
832 gc = purple_conversation_get_connection(conv); 884 gc = purple_conversation_get_connection(conv);
833 g_return_if_fail(gc != NULL); 885 g_return_if_fail(gc != NULL);
834 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); 886 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
835 g_return_if_fail(prpl_info != NULL); 887 g_return_if_fail(prpl_info != NULL);
836 888
842 gboolean quiet; 894 gboolean quiet;
843 PurpleChatConversationBuddyFlags flag = GPOINTER_TO_INT(fl->data); 895 PurpleChatConversationBuddyFlags flag = GPOINTER_TO_INT(fl->data);
844 const char *extra_msg = (extra_msgs ? extra_msgs->data : NULL); 896 const char *extra_msg = (extra_msgs ? extra_msgs->data : NULL);
845 897
846 if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { 898 if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
847 if (purple_strequal(priv->nick, purple_normalize(priv->account, user))) { 899 if (purple_strequal(priv->nick, purple_normalize(account, user))) {
848 const char *alias2 = purple_account_get_private_alias(priv->account); 900 const char *alias2 = purple_account_get_private_alias(account);
849 if (alias2 != NULL) 901 if (alias2 != NULL)
850 alias = alias2; 902 alias = alias2;
851 else 903 else
852 { 904 {
853 const char *display_name = purple_connection_get_display_name(gc); 905 const char *display_name = purple_connection_get_display_name(gc);
860 alias = purple_buddy_get_contact_alias(buddy); 912 alias = purple_buddy_get_contact_alias(buddy);
861 } 913 }
862 } 914 }
863 915
864 quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(), 916 quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(),
865 "chat-buddy-joining", conv, user, flag)) || 917 "chat-buddy-joining", chat, user, flag)) ||
866 purple_chat_conversation_is_ignored_user(chat, user); 918 purple_chat_conversation_is_ignored_user(chat, user);
867 919
868 cbuddy = purple_chat_conversation_buddy_new(user, alias, flag); 920 cbuddy = purple_chat_conversation_buddy_new(chat, user, alias, flag);
869 cbuddy->buddy = purple_find_buddy(priv->account, user) != NULL; 921 purple_chat_conversation_buddy_set_buddy(cbuddy, purple_find_buddy(account, user) != NULL);
870 922
871 priv->in_room = g_list_prepend(priv->in_room, cbuddy); 923 priv->in_room = g_list_prepend(priv->in_room, cbuddy);
872 g_hash_table_replace(priv->users, g_strdup(cbuddy->name), cbuddy); 924 g_hash_table_replace(priv->users,
925 g_strdup(purple_chat_conversation_buddy_get_name(cbuddy)), cbuddy);
873 926
874 cbuddies = g_list_prepend(cbuddies, cbuddy); 927 cbuddies = g_list_prepend(cbuddies, cbuddy);
875 928
876 if (!quiet && new_arrivals) { 929 if (!quiet && new_arrivals) {
877 char *alias_esc = g_markup_escape_text(alias, -1); 930 char *alias_esc = g_markup_escape_text(alias, -1);
892 time(NULL)); 945 time(NULL));
893 g_free(tmp); 946 g_free(tmp);
894 } 947 }
895 948
896 purple_signal_emit(purple_conversations_get_handle(), 949 purple_signal_emit(purple_conversations_get_handle(),
897 "chat-buddy-joined", conv, user, flag, new_arrivals); 950 "chat-buddy-joined", chat, user, flag, new_arrivals);
898 ul = ul->next; 951 ul = ul->next;
899 fl = fl->next; 952 fl = fl->next;
900 if (extra_msgs != NULL) 953 if (extra_msgs != NULL)
901 extra_msgs = extra_msgs->next; 954 extra_msgs = extra_msgs->next;
902 } 955 }
903 956
904 cbuddies = g_list_sort(cbuddies, (GCompareFunc)purple_chat_conversation_buddy_compare); 957 cbuddies = g_list_sort(cbuddies, (GCompareFunc)purple_chat_conversation_buddy_compare);
905 958
906 if (ops != NULL && ops->chat_add_users != NULL) 959 if (ops != NULL && ops->chat_add_users != NULL)
907 ops->chat_add_users(conv, cbuddies, new_arrivals); 960 ops->chat_add_users(chat, cbuddies, new_arrivals);
908 961
909 g_list_free(cbuddies); 962 g_list_free(cbuddies);
910 } 963 }
911 964
912 void 965 void
913 purple_chat_conversation_rename_user(PurpleChatConversation *chat, const char *old_user, 966 purple_chat_conversation_rename_user(PurpleChatConversation *chat, const char *old_user,
914 const char *new_user) 967 const char *new_user)
915 { 968 {
916 PurpleConversation *conv; 969 PurpleConversation *conv;
917 PurpleConversationUiOps *ops; 970 PurpleConversationUiOps *ops;
971 PurpleAccount *account;
918 PurpleConnection *gc; 972 PurpleConnection *gc;
919 PurplePluginProtocolInfo *prpl_info; 973 PurplePluginProtocolInfo *prpl_info;
920 PurpleChatConversationBuddy *cb; 974 PurpleChatConversationBuddy *cb;
921 PurpleChatConversationBuddyFlags flags; 975 PurpleChatConversationBuddyFlags flags;
976 PurpleChatConversationPrivate *priv;
922 const char *new_alias = new_user; 977 const char *new_alias = new_user;
923 char tmp[BUF_LONG]; 978 char tmp[BUF_LONG];
924 gboolean is_me = FALSE; 979 gboolean is_me = FALSE;
925 980
926 g_return_if_fail(chat != NULL); 981 priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
982
983 g_return_if_fail(priv != NULL);
927 g_return_if_fail(old_user != NULL); 984 g_return_if_fail(old_user != NULL);
928 g_return_if_fail(new_user != NULL); 985 g_return_if_fail(new_user != NULL);
929 986
930 conv = purple_chat_conversation_get_conversation(chat); 987 conv = PURPLE_CONVERSATION(chat);
931 ops = purple_conversation_get_ui_ops(conv); 988 ops = purple_conversation_get_ui_ops(conv);
989 account = purple_conversation_get_account(conv);
932 990
933 gc = purple_conversation_get_connection(conv); 991 gc = purple_conversation_get_connection(conv);
934 g_return_if_fail(gc != NULL); 992 g_return_if_fail(gc != NULL);
935 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); 993 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
936 g_return_if_fail(prpl_info != NULL); 994 g_return_if_fail(prpl_info != NULL);
937 995
938 if (purple_strequal(priv->nick, purple_normalize(priv->account, old_user))) { 996 if (purple_strequal(priv->nick, purple_normalize(account, old_user))) {
939 const char *alias; 997 const char *alias;
940 998
941 /* Note this for later. */ 999 /* Note this for later. */
942 is_me = TRUE; 1000 is_me = TRUE;
943 1001
944 if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { 1002 if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
945 alias = purple_account_get_private_alias(priv->account); 1003 alias = purple_account_get_private_alias(account);
946 if (alias != NULL) 1004 if (alias != NULL)
947 new_alias = alias; 1005 new_alias = alias;
948 else 1006 else
949 { 1007 {
950 const char *display_name = purple_connection_get_display_name(gc); 1008 const char *display_name = purple_connection_get_display_name(gc);
956 PurpleBuddy *buddy; 1014 PurpleBuddy *buddy;
957 if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) 1015 if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL)
958 new_alias = purple_buddy_get_contact_alias(buddy); 1016 new_alias = purple_buddy_get_contact_alias(buddy);
959 } 1017 }
960 1018
961 flags = purple_chat_conversation_user_get_flags(chat, old_user); 1019 flags = purple_chat_conversation_buddy_get_flags(purple_chat_conversation_find_buddy(chat, old_user));
962 cb = purple_chat_conversation_buddy_new(new_user, new_alias, flags); 1020 cb = purple_chat_conversation_buddy_new(chat, new_user, new_alias, flags);
963 cb->buddy = purple_find_buddy(priv->account, new_user) != NULL; 1021 purple_chat_conversation_buddy_set_buddy(cb, purple_find_buddy(account, new_user) != NULL);
964 1022
965 priv->in_room = g_list_prepend(priv->in_room, cb); 1023 priv->in_room = g_list_prepend(priv->in_room, cb);
966 g_hash_table_replace(priv->users, g_strdup(cb->name), cb); 1024 g_hash_table_replace(priv->users,
1025 g_strdup(purple_chat_conversation_buddy_get_name(cb)), cb);
967 1026
968 if (ops != NULL && ops->chat_rename_user != NULL) 1027 if (ops != NULL && ops->chat_rename_user != NULL)
969 ops->chat_rename_user(conv, old_user, new_user, new_alias); 1028 ops->chat_rename_user(chat, old_user, new_user, new_alias);
970 1029
971 cb = purple_chat_conversation_find_buddy(chat, old_user); 1030 cb = purple_chat_conversation_find_buddy(chat, old_user);
972 1031
973 if (cb) { 1032 if (cb) {
974 priv->in_room = g_list_remove(priv->in_room, cb); 1033 priv->in_room = g_list_remove(priv->in_room, cb);
975 g_hash_table_remove(priv->users, cb->name); 1034 g_hash_table_remove(priv->users, purple_chat_conversation_buddy_get_name(cb));
976 purple_chat_conversation_buddy_destroy(cb); 1035 g_object_unref(cb);
977 } 1036 }
978 1037
979 if (purple_chat_conversation_is_ignored_user(chat, old_user)) { 1038 if (purple_chat_conversation_is_ignored_user(chat, old_user)) {
980 purple_chat_conversation_unignore(chat, old_user); 1039 purple_chat_conversation_unignore(chat, old_user);
981 purple_chat_conversation_ignore(chat, new_user); 1040 purple_chat_conversation_ignore(chat, new_user);
1039 PurpleConversation *conv; 1098 PurpleConversation *conv;
1040 PurpleConnection *gc; 1099 PurpleConnection *gc;
1041 PurplePluginProtocolInfo *prpl_info; 1100 PurplePluginProtocolInfo *prpl_info;
1042 PurpleConversationUiOps *ops; 1101 PurpleConversationUiOps *ops;
1043 PurpleChatConversationBuddy *cb; 1102 PurpleChatConversationBuddy *cb;
1103 PurpleChatConversationPrivate *priv;
1044 GList *l; 1104 GList *l;
1045 gboolean quiet; 1105 gboolean quiet;
1046 1106
1047 g_return_if_fail(chat != NULL); 1107 priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
1108
1109 g_return_if_fail(priv != NULL);
1048 g_return_if_fail(users != NULL); 1110 g_return_if_fail(users != NULL);
1049 1111
1050 conv = purple_chat_conversation_get_conversation(chat); 1112 conv = PURPLE_CONVERSATION(chat);
1051 1113
1052 gc = purple_conversation_get_connection(conv); 1114 gc = purple_conversation_get_connection(conv);
1053 g_return_if_fail(gc != NULL); 1115 g_return_if_fail(gc != NULL);
1054 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); 1116 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1055 g_return_if_fail(prpl_info != NULL); 1117 g_return_if_fail(prpl_info != NULL);
1057 ops = purple_conversation_get_ui_ops(conv); 1119 ops = purple_conversation_get_ui_ops(conv);
1058 1120
1059 for (l = users; l != NULL; l = l->next) { 1121 for (l = users; l != NULL; l = l->next) {
1060 const char *user = (const char *)l->data; 1122 const char *user = (const char *)l->data;
1061 quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(), 1123 quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(),
1062 "chat-buddy-leaving", conv, user, reason)) | 1124 "chat-buddy-leaving", chat, user, reason)) |
1063 purple_chat_conversation_is_ignored_user(chat, user); 1125 purple_chat_conversation_is_ignored_user(chat, user);
1064 1126
1065 cb = purple_chat_conversation_find_buddy(chat, user); 1127 cb = purple_chat_conversation_find_buddy(chat, user);
1066 1128
1067 if (cb) { 1129 if (cb) {
1068 priv->in_room = g_list_remove(priv->in_room, cb); 1130 priv->in_room = g_list_remove(priv->in_room, cb);
1069 g_hash_table_remove(priv->users, cb->name); 1131 g_hash_table_remove(priv->users, purple_chat_conversation_buddy_get_name(cb));
1070 purple_chat_conversation_buddy_destroy(cb); 1132 g_object_unref(cb);
1071 } 1133 }
1072 1134
1073 /* NOTE: Don't remove them from ignored in case they re-enter. */ 1135 /* NOTE: Don't remove them from ignored in case they re-enter. */
1074 1136
1075 if (!quiet) { 1137 if (!quiet) {
1105 purple_signal_emit(purple_conversations_get_handle(), "chat-buddy-left", 1167 purple_signal_emit(purple_conversations_get_handle(), "chat-buddy-left",
1106 conv, user, reason); 1168 conv, user, reason);
1107 } 1169 }
1108 1170
1109 if (ops != NULL && ops->chat_remove_users != NULL) 1171 if (ops != NULL && ops->chat_remove_users != NULL)
1110 ops->chat_remove_users(conv, users); 1172 ops->chat_remove_users(chat, users);
1111 } 1173 }
1112 1174
1113 void 1175 void
1114 purple_chat_conversation_clear_users(PurpleChatConversation *chat) 1176 purple_chat_conversation_clear_users(PurpleChatConversation *chat)
1115 { 1177 {
1116 PurpleConversation *conv;
1117 PurpleConversationUiOps *ops; 1178 PurpleConversationUiOps *ops;
1118 GList *users; 1179 GList *users;
1119 GList *l; 1180 GList *l;
1120 GList *names = NULL; 1181 GList *names = NULL;
1121 1182 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
1122 g_return_if_fail(chat != NULL); 1183
1123 1184 g_return_if_fail(priv != NULL);
1124 conv = purple_chat_conversation_get_conversation(chat); 1185
1125 ops = purple_conversation_get_ui_ops(conv); 1186 ops = purple_conversation_get_ui_ops(PURPLE_CONVERSATION(chat));
1126 users = priv->in_room; 1187 users = priv->in_room;
1127 1188
1128 if (ops != NULL && ops->chat_remove_users != NULL) { 1189 if (ops != NULL && ops->chat_remove_users != NULL) {
1129 for (l = users; l; l = l->next) { 1190 for (l = users; l; l = l->next) {
1130 PurpleChatConversationBuddy *cb = l->data; 1191 PurpleChatConversationBuddy *cb = l->data;
1131 names = g_list_prepend(names, cb->name); 1192 names = g_list_prepend(names,
1193 (gchar *) purple_chat_conversation_buddy_get_name(cb));
1132 } 1194 }
1133 ops->chat_remove_users(conv, names); 1195 ops->chat_remove_users(chat, names);
1134 g_list_free(names); 1196 g_list_free(names);
1135 } 1197 }
1136 1198
1137 for (l = users; l; l = l->next) 1199 for (l = users; l; l = l->next)
1138 { 1200 {
1139 PurpleChatConversationBuddy *cb = l->data; 1201 PurpleChatConversationBuddy *cb = l->data;
1202 const char *name = purple_chat_conversation_buddy_get_name(cb);
1140 1203
1141 purple_signal_emit(purple_conversations_get_handle(), 1204 purple_signal_emit(purple_conversations_get_handle(),
1142 "chat-buddy-leaving", conv, cb->name, NULL); 1205 "chat-buddy-leaving", chat, name, NULL);
1143 purple_signal_emit(purple_conversations_get_handle(), 1206 purple_signal_emit(purple_conversations_get_handle(),
1144 "chat-buddy-left", conv, cb->name, NULL); 1207 "chat-buddy-left", chat, name, NULL);
1145 1208
1146 purple_chat_conversation_buddy_destroy(cb); 1209 g_object_unref(cb);
1147 } 1210 }
1148 1211
1149 g_hash_table_remove_all(priv->users); 1212 g_hash_table_remove_all(priv->users);
1150 1213
1151 g_list_free(users); 1214 g_list_free(users);
1152 priv->in_room = NULL; 1215 priv->in_room = NULL;
1153 } 1216 }
1154 1217
1155 void purple_chat_conversation_set_nick(PurpleChatConversation *chat, const char *nick) { 1218 void purple_chat_conversation_set_nick(PurpleChatConversation *chat, const char *nick) {
1156 g_return_if_fail(chat != NULL); 1219 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
1157 1220
1158 g_free(chat->nick); 1221 g_return_if_fail(priv != NULL);
1159 chat->nick = g_strdup(purple_normalize(chat->priv->account, nick)); 1222
1223 g_free(priv->nick);
1224 priv->nick = g_strdup(purple_normalize(
1225 purple_conversation_get_account(PURPLE_CONVERSATION(chat)), nick));
1160 } 1226 }
1161 1227
1162 const char *purple_chat_conversation_get_nick(PurpleChatConversation *chat) { 1228 const char *purple_chat_conversation_get_nick(PurpleChatConversation *chat) {
1163 g_return_val_if_fail(chat != NULL, NULL); 1229 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
1164 1230
1165 return chat->nick; 1231 g_return_val_if_fail(priv != NULL, NULL);
1232
1233 return priv->nick;
1166 } 1234 }
1167 1235
1168 static void 1236 static void
1169 invite_user_to_chat(gpointer data, PurpleRequestFields *fields) 1237 invite_user_to_chat(gpointer data, PurpleRequestFields *fields)
1170 { 1238 {
1171 PurpleConversation *conv; 1239 PurpleConversation *conv;
1172 PurpleChatConversationPrivate *priv; 1240 PurpleChatConversationPrivate *priv;
1173 const char *user, *message; 1241 const char *user, *message;
1174 1242
1175 conv = data; 1243 conv = data;
1176 chat = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv); 1244 priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv);
1177 user = purple_request_fields_get_string(fields, "screenname"); 1245 user = purple_request_fields_get_string(fields, "screenname");
1178 message = purple_request_fields_get_string(fields, "message"); 1246 message = purple_request_fields_get_string(fields, "message");
1179 1247
1180 serv_chat_invite(purple_conversation_get_connection(conv), chat->id, message, user); 1248 serv_chat_invite(purple_conversation_get_connection(conv), priv->id, message, user);
1181 } 1249 }
1182 1250
1183 void purple_chat_conversation_invite_user(PurpleChatConversation *chat, const char *user, 1251 void purple_chat_conversation_invite_user(PurpleChatConversation *chat, const char *user,
1184 const char *message, gboolean confirm) 1252 const char *message, gboolean confirm)
1185 { 1253 {
1186 PurpleAccount *account; 1254 PurpleAccount *account;
1187 PurpleConversation *conv;
1188 PurpleRequestFields *fields; 1255 PurpleRequestFields *fields;
1189 PurpleRequestFieldGroup *group; 1256 PurpleRequestFieldGroup *group;
1190 PurpleRequestField *field; 1257 PurpleRequestField *field;
1191 1258
1192 g_return_if_fail(chat); 1259 g_return_if_fail(chat != NULL);
1193 1260
1194 if (!user || !*user || !message || !*message) 1261 if (!user || !*user || !message || !*message)
1195 confirm = TRUE; 1262 confirm = TRUE;
1196 1263
1197 conv = chat->conv; 1264 account = purple_conversation_get_account(PURPLE_CONVERSATION(chat));
1198 account = priv->account;
1199 1265
1200 if (!confirm) { 1266 if (!confirm) {
1201 serv_chat_invite(purple_account_get_connection(account), 1267 serv_chat_invite(purple_account_get_connection(account),
1202 purple_chat_conversation_get_id(chat), message, user); 1268 purple_chat_conversation_get_id(chat), message, user);
1203 return; 1269 return;
1213 purple_request_field_set_type_hint(field, "screenname"); 1279 purple_request_field_set_type_hint(field, "screenname");
1214 1280
1215 field = purple_request_field_string_new("message", _("Message"), message, FALSE); 1281 field = purple_request_field_string_new("message", _("Message"), message, FALSE);
1216 purple_request_field_group_add_field(group, field); 1282 purple_request_field_group_add_field(group, field);
1217 1283
1218 purple_request_fields(conv, _("Invite to chat"), NULL, 1284 purple_request_fields(chat, _("Invite to chat"), NULL,
1219 _("Please enter the name of the user you wish to invite, " 1285 _("Please enter the name of the user you wish to invite, "
1220 "along with an optional invite message."), 1286 "along with an optional invite message."),
1221 fields, 1287 fields,
1222 _("Invite"), G_CALLBACK(invite_user_to_chat), 1288 _("Invite"), G_CALLBACK(invite_user_to_chat),
1223 _("Cancel"), NULL, 1289 _("Cancel"), NULL,
1224 account, user, conv, 1290 account, user, PURPLE_CONVERSATION(chat),
1225 conv); 1291 chat);
1226 } 1292 }
1227 1293
1228 gboolean 1294 gboolean
1229 purple_chat_conversation_find_user(PurpleChatConversation *chat, const char *user) 1295 purple_chat_conversation_has_user(PurpleChatConversation *chat, const char *user)
1230 { 1296 {
1231 g_return_val_if_fail(chat != NULL, FALSE); 1297 g_return_val_if_fail(chat != NULL, FALSE);
1232 g_return_val_if_fail(user != NULL, FALSE); 1298 g_return_val_if_fail(user != NULL, FALSE);
1233 1299
1234 return (purple_chat_conversation_find_buddy(chat, user) != NULL); 1300 return (purple_chat_conversation_find_buddy(chat, user) != NULL);
1235 } 1301 }
1236 1302
1237 void 1303 void
1238 purple_chat_conversation_user_set_flags(PurpleChatConversation *chat, const char *user,
1239 PurpleChatConversationBuddyFlags flags)
1240 {
1241 PurpleConversation *conv;
1242 PurpleConversationUiOps *ops;
1243 PurpleChatConversationBuddy *cb;
1244 PurpleChatConversationBuddyFlags oldflags;
1245
1246 g_return_if_fail(chat != NULL);
1247 g_return_if_fail(user != NULL);
1248
1249 cb = purple_chat_conversation_find_buddy(chat, user);
1250
1251 if (!cb)
1252 return;
1253
1254 if (flags == cb->flags)
1255 return;
1256
1257 oldflags = cb->flags;
1258 cb->flags = flags;
1259
1260 conv = purple_chat_conversation_get_conversation(chat);
1261 ops = purple_conversation_get_ui_ops(conv);
1262
1263 if (ops != NULL && ops->chat_update_user != NULL)
1264 ops->chat_update_user(conv, user);
1265
1266 purple_signal_emit(purple_conversations_get_handle(),
1267 "chat-buddy-flags", conv, user, oldflags, flags);
1268 }
1269
1270 PurpleChatConversationBuddyFlags
1271 purple_chat_conversation_user_get_flags(PurpleChatConversation *chat, const char *user)
1272 {
1273 PurpleChatConversationBuddy *cb;
1274
1275 g_return_val_if_fail(chat != NULL, 0);
1276 g_return_val_if_fail(user != NULL, 0);
1277
1278 cb = purple_chat_conversation_find_buddy(chat, user);
1279
1280 if (!cb)
1281 return PURPLE_CHAT_CONVERSATION_BUDDY_NONE;
1282
1283 return cb->flags;
1284 }
1285
1286 void
1287 purple_chat_conversation_leave(PurpleChatConversation *chat) 1304 purple_chat_conversation_leave(PurpleChatConversation *chat)
1288 { 1305 {
1289 g_return_if_fail(chat != NULL); 1306 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
1307
1308 g_return_if_fail(priv != NULL);
1290 1309
1291 priv->left = TRUE; 1310 priv->left = TRUE;
1292 purple_conversation_update(priv->conv, PURPLE_CONVERSATION_UPDATE_CHATLEFT); 1311 purple_conversation_update(PURPLE_CONVERSATION(chat), PURPLE_CONVERSATION_UPDATE_CHATLEFT);
1293 } 1312 }
1294 1313
1295 gboolean 1314 gboolean
1296 purple_chat_conversation_has_left(PurpleChatConversation *chat) 1315 purple_chat_conversation_has_left(PurpleChatConversation *chat)
1297 { 1316 {
1298 g_return_val_if_fail(chat != NULL, TRUE); 1317 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
1318
1319 g_return_val_if_fail(priv != NULL, TRUE);
1299 1320
1300 return priv->left; 1321 return priv->left;
1301 } 1322 }
1302 1323
1303 static void 1324 static void
1304 purple_chat_conversation_cleanup_for_rejoin(PurpleChatConversation *chat) 1325 chat_conversation_cleanup_for_rejoin(PurpleChatConversation *chat)
1305 { 1326 {
1306 const char *disp; 1327 const char *disp;
1307 PurpleAccount *account; 1328 PurpleAccount *account;
1308 PurpleConnection *gc; 1329 PurpleConnection *gc;
1330 PurpleConversation *conv = PURPLE_CONVERSATION(chat);
1331 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
1309 1332
1310 account = purple_conversation_get_account(conv); 1333 account = purple_conversation_get_account(conv);
1311 1334
1312 purple_conversation_close_logs(conv); 1335 purple_conversation_close_logs(conv);
1313 open_log(conv); 1336 purple_conversation_set_logging(conv, TRUE);
1314 1337
1315 gc = purple_account_get_connection(account); 1338 gc = purple_account_get_connection(account);
1316 1339
1317 if ((disp = purple_connection_get_display_name(gc)) != NULL) 1340 if ((disp = purple_connection_get_display_name(gc)) != NULL)
1318 purple_chat_conversation_set_nick(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv), disp); 1341 purple_chat_conversation_set_nick(chat, disp);
1319 else 1342 else
1320 { 1343 {
1321 purple_chat_conversation_set_nick(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv), 1344 purple_chat_conversation_set_nick(chat,
1322 purple_account_get_username(account)); 1345 purple_account_get_username(account));
1323 } 1346 }
1324 1347
1325 purple_chat_conversation_clear_users(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv)); 1348 purple_chat_conversation_clear_users(chat);
1326 purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv), NULL, NULL); 1349 purple_chat_conversation_set_topic(chat, NULL, NULL);
1327 PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv)->left = FALSE; 1350 priv->left = FALSE;
1328 1351
1329 purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_CHATLEFT); 1352 purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_CHATLEFT);
1330 } 1353 }
1331 1354
1332 PurpleChatConversationBuddy * 1355 PurpleChatConversationBuddy *
1333 purple_chat_conversation_find_buddy(PurpleChatConversation *chat, const char *name) 1356 purple_chat_conversation_find_buddy(PurpleChatConversation *chat, const char *name)
1334 { 1357 {
1335 g_return_val_if_fail(chat != NULL, NULL); 1358 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
1359
1360 g_return_val_if_fail(priv != NULL, NULL);
1336 g_return_val_if_fail(name != NULL, NULL); 1361 g_return_val_if_fail(name != NULL, NULL);
1337 1362
1338 return g_hash_table_lookup(priv->users, name); 1363 return g_hash_table_lookup(priv->users, name);
1339 } 1364 }
1340 1365
1341 /************************************************************************** 1366 /**************************************************************************
1342 * GObject code for chats 1367 * GObject code for chats
1343 **************************************************************************/ 1368 **************************************************************************/
1344 1369
1345 /* GObject Property names */ 1370 /* GObject Property names */
1346 #define PROP_TOPIC_WHO_S "topic-who" 1371 #define CHAT_PROP_TOPIC_WHO_S "topic-who"
1347 #define PROP_TOPIC_S "topic" 1372 #define CHAT_PROP_TOPIC_S "topic"
1348 #define PROP_CHAT_ID_S "chat-id" 1373 #define CHAT_PROP_ID_S "chat-id"
1349 #define PROP_NICK_S "nick" 1374 #define CHAT_PROP_NICK_S "nick"
1350 #define PROP_LEFT_S "left" 1375 #define CHAT_PROP_LEFT_S "left"
1351 1376
1352 /* Set method for GObject properties */ 1377 /* Set method for GObject properties */
1353 static void 1378 static void
1354 purple_chat_conversation_set_property(GObject *obj, guint param_id, const GValue *value, 1379 purple_chat_conversation_set_property(GObject *obj, guint param_id, const GValue *value,
1355 GParamSpec *pspec) 1380 GParamSpec *pspec)
1356 { 1381 {
1357 PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(obj); 1382 PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(obj);
1358 1383
1359 switch (param_id) { 1384 switch (param_id) {
1360 case PROP_CHAT_ID: 1385 case CHAT_PROP_ID:
1361 purple_chat_conversation_set_id(chat, g_value_get_int(value)); 1386 purple_chat_conversation_set_id(chat, g_value_get_int(value));
1362 break; 1387 break;
1363 case PROP_NICK: 1388 case CHAT_PROP_NICK:
1364 purple_chat_conversation_set_nick(chat, g_value_get_string(value)); 1389 purple_chat_conversation_set_nick(chat, g_value_get_string(value));
1365 break; 1390 break;
1366 case PROP_LEFT: 1391 case CHAT_PROP_LEFT:
1367 { 1392 {
1368 gboolean left = g_value_get_boolean(value); 1393 gboolean left = g_value_get_boolean(value);
1369 if (left == TRUE) 1394 if (left == TRUE)
1370 purple_chat_conversation_leave(chat, left); 1395 purple_chat_conversation_leave(chat);
1371 } 1396 }
1372 break; 1397 break;
1373 default: 1398 default:
1374 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); 1399 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
1375 break; 1400 break;
1382 GParamSpec *pspec) 1407 GParamSpec *pspec)
1383 { 1408 {
1384 PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(obj); 1409 PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(obj);
1385 1410
1386 switch (param_id) { 1411 switch (param_id) {
1387 case PROP_TOPIC_WHO: 1412 case CHAT_PROP_TOPIC_WHO:
1388 g_value_set_string(value, purple_chat_conversation_get_topic_who(chat); 1413 g_value_set_string(value, purple_chat_conversation_get_topic_who(chat));
1389 break; 1414 break;
1390 case PROP_TOPIC: 1415 case CHAT_PROP_TOPIC:
1391 g_value_set_string(value, purple_chat_conversation_get_topic(chat); 1416 g_value_set_string(value, purple_chat_conversation_get_topic(chat));
1392 break; 1417 break;
1393 case PROP_CHAT_ID: 1418 case CHAT_PROP_ID:
1394 g_value_set_int(value, purple_chat_conversation_get_id(chat); 1419 g_value_set_int(value, purple_chat_conversation_get_id(chat));
1395 break; 1420 break;
1396 case PROP_NICK: 1421 case CHAT_PROP_NICK:
1397 g_value_set_string(value, purple_chat_conversation_get_nick(chat); 1422 g_value_set_string(value, purple_chat_conversation_get_nick(chat));
1398 break; 1423 break;
1399 case PROP_LEFT: 1424 case CHAT_PROP_LEFT:
1400 g_value_set_boolean(value, purple_chat_conversation_has_left(chat); 1425 g_value_set_boolean(value, purple_chat_conversation_has_left(chat));
1401 break; 1426 break;
1402 default: 1427 default:
1403 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); 1428 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
1404 break; 1429 break;
1405 } 1430 }
1406 } 1431 }
1407 1432
1408 /* GObject initialization function */ 1433 /* GObject initialization function */
1409 static void purple_chat_conversation_init(GTypeInstance *instance, gpointer klass) 1434 static void purple_chat_conversation_init(GTypeInstance *instance, gpointer klass)
1410 { 1435 {
1411 PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(instance); 1436 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(instance);
1412 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(im);
1413 1437
1414 priv->users = g_hash_table_new_full(_purple_conversation_user_hash, 1438 priv->users = g_hash_table_new_full(_purple_conversation_user_hash,
1415 _purple_conversation_user_equal, g_free, NULL); 1439 _purple_conversation_user_equal, g_free, NULL);
1416 } 1440 }
1417 1441
1418 /* GObject dispose function */ 1442 /* GObject dispose function */
1419 static void 1443 static void
1420 purple_chat_conversation_dispose(GObject *object) 1444 purple_chat_conversation_dispose(GObject *object)
1421 { 1445 {
1422 PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(object); 1446 PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(object);
1423 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); 1447 PurpleConnection *gc = purple_conversation_get_connection(PURPLE_CONVERSATION(chat));
1424 1448
1425 if (gc != NULL) 1449 if (gc != NULL)
1426 { 1450 {
1427 /* Still connected */ 1451 /* Still connected */
1428 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); 1452 int chat_id = purple_chat_conversation_get_id(chat);
1429
1430 int chat_id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv));
1431 #if 0 1453 #if 0
1432 /* 1454 /*
1433 * This is unfortunately necessary, because calling 1455 * This is unfortunately necessary, because calling
1434 * serv_chat_leave() calls this purple_conversation_destroy(), 1456 * serv_chat_leave() calls this purple_conversation_destroy(),
1435 * which leads to two calls here.. We can't just return after 1457 * which leads to two calls here.. We can't just return after
1457 * Instead of all of that, lets just close the window when 1479 * Instead of all of that, lets just close the window when
1458 * the user tells us to, and let the prpl deal with the 1480 * the user tells us to, and let the prpl deal with the
1459 * internals on it's own time. Don't do this if the prpl already 1481 * internals on it's own time. Don't do this if the prpl already
1460 * knows it left the chat. 1482 * knows it left the chat.
1461 */ 1483 */
1462 if (!purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv))) 1484 if (!purple_chat_conversation_has_left(chat))
1463 serv_chat_leave(gc, chat_id); 1485 serv_chat_leave(gc, chat_id);
1464 1486
1465 /* 1487 /*
1466 * If they didn't call serv_got_chat_left by now, it's too late. 1488 * If they didn't call serv_got_chat_left by now, it's too late.
1467 * So we better do it for them before we destroy the thing. 1489 * So we better do it for them before we destroy the thing.
1468 */ 1490 */
1469 if (!purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv))) 1491 if (!purple_chat_conversation_has_left(chat))
1470 serv_got_chat_left(gc, chat_id); 1492 serv_got_chat_left(gc, chat_id);
1471 } 1493 }
1472 1494
1473 parent_class->dispose(object); 1495 G_OBJECT_CLASS(chat_parent_class)->dispose(object);
1474 } 1496 }
1475 1497
1476 /* GObject finalize function */ 1498 /* GObject finalize function */
1477 static void 1499 static void
1478 purple_chat_conversation_finalize(GObject *object) 1500 purple_chat_conversation_finalize(GObject *object)
1479 { 1501 {
1480 PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(object); 1502 PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(object);
1481 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); 1503 PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat);
1482 1504
1483 g_hash_table_destroy(priv->u.chat->users); 1505 g_hash_table_destroy(priv->users);
1484 1506
1485 g_list_foreach(priv->u.chat->in_room, (GFunc)purple_chat_conversation_buddy_destroy, NULL); 1507 g_list_foreach(priv->in_room, (GFunc)g_object_unref, NULL);
1486 g_list_free(priv->u.chat->in_room); 1508 g_list_free(priv->in_room);
1487 1509
1488 g_list_foreach(priv->u.chat->ignored, (GFunc)g_free, NULL); 1510 g_list_foreach(priv->ignored, (GFunc)g_free, NULL);
1489 g_list_free(priv->u.chat->ignored); 1511 g_list_free(priv->ignored);
1490 1512
1491 g_free(priv->u.chat->who); 1513 g_free(priv->who);
1492 g_free(priv->u.chat->topic); 1514 g_free(priv->topic);
1493 g_free(priv->u.chat->nick); 1515 g_free(priv->nick);
1494 g_free(priv->u.chat); 1516
1495 1517 G_OBJECT_CLASS(chat_parent_class)->finalize(object);
1496 parent_class->finalize(object);
1497 } 1518 }
1498 1519
1499 /* Class initializer function */ 1520 /* Class initializer function */
1500 static void purple_chat_conversation_class_init(PurpleChatConversationClass *klass) 1521 static void purple_chat_conversation_class_init(PurpleChatConversationClass *klass)
1501 { 1522 {
1502 GObjectClass *obj_class = G_OBJECT_CLASS(klass); 1523 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
1503 1524
1504 parent_class = g_type_class_peek_parent(klass); 1525 chat_parent_class = g_type_class_peek_parent(klass);
1505 1526
1506 obj_class->dispose = purple_chat_conversation_dispose; 1527 obj_class->dispose = purple_chat_conversation_dispose;
1507 obj_class->finalize = purple_chat_conversation_finalize; 1528 obj_class->finalize = purple_chat_conversation_finalize;
1508 1529
1509 /* Setup properties */ 1530 /* Setup properties */
1510 obj_class->get_property = purple_chat_conversation_get_property; 1531 obj_class->get_property = purple_chat_conversation_get_property;
1511 obj_class->set_property = purple_chat_conversation_set_property; 1532 obj_class->set_property = purple_chat_conversation_set_property;
1512 1533
1513 parent_class->write_message = chat_conversation_write_message; 1534 chat_parent_class->write_message = chat_conversation_write_message;
1514 parent_class->send_message = chat_conversation_send_message; 1535
1515 1536 g_object_class_install_property(obj_class, CHAT_PROP_TOPIC_WHO,
1516 g_object_class_install_property(obj_class, PROP_TOPIC_WHO, 1537 g_param_spec_string(CHAT_PROP_TOPIC_WHO_S, _("Who set topic"),
1517 g_param_spec_string(PROP_TOPIC_WHO_S, _("Who set topic"),
1518 _("Who set the chat topic."), NULL, 1538 _("Who set the chat topic."), NULL,
1519 G_PARAM_READONLY) 1539 G_PARAM_READABLE)
1520 ); 1540 );
1521 1541
1522 g_object_class_install_property(obj_class, PROP_TOPIC, 1542 g_object_class_install_property(obj_class, CHAT_PROP_TOPIC,
1523 g_param_spec_string(PROP_TOPIC_S, _("Topic"), 1543 g_param_spec_string(CHAT_PROP_TOPIC_S, _("Topic"),
1524 _("Topic of the chat."), NULL, 1544 _("Topic of the chat."), NULL,
1525 G_PARAM_READONLY) 1545 G_PARAM_READABLE)
1526 ); 1546 );
1527 1547
1528 g_object_class_install_property(obj_class, PROP_CHAT_ID, 1548 g_object_class_install_property(obj_class, CHAT_PROP_ID,
1529 g_param_spec_int(PROP_CHAT_ID_S, _("Chat ID"), 1549 g_param_spec_int(CHAT_PROP_ID_S, _("Chat ID"),
1530 _("The ID of the chat."), G_MININT, G_MAXINT, 0, 1550 _("The ID of the chat."), G_MININT, G_MAXINT, 0,
1531 G_PARAM_READWRITE) 1551 G_PARAM_READWRITE)
1532 ); 1552 );
1533 1553
1534 g_object_class_install_property(obj_class, PROP_NICK, 1554 g_object_class_install_property(obj_class, CHAT_PROP_NICK,
1535 g_param_spec_string(PROP_NICK_S, _("Nickname"), 1555 g_param_spec_string(CHAT_PROP_NICK_S, _("Nickname"),
1536 _("The nickname of the user in a chat."), NULL, 1556 _("The nickname of the user in a chat."), NULL,
1537 G_PARAM_READWRITE) 1557 G_PARAM_READWRITE)
1538 ); 1558 );
1539 1559
1540 g_object_class_install_property(obj_class, PROP_LEFT, 1560 g_object_class_install_property(obj_class, CHAT_PROP_LEFT,
1541 g_param_spec_boolean(PROP_LEFT_S, _("Left the chat"), 1561 g_param_spec_boolean(CHAT_PROP_LEFT_S, _("Left the chat"),
1542 _("Whether the user has left the chat."), FALSE, 1562 _("Whether the user has left the chat."), FALSE,
1543 G_PARAM_READWRITE) 1563 G_PARAM_READWRITE)
1544 ); 1564 );
1545 1565
1546 g_type_class_add_private(klass, sizeof(PurpleChatConversationPrivate)); 1566 g_type_class_add_private(klass, sizeof(PurpleChatConversationPrivate));
1575 1595
1576 PurpleChatConversation * 1596 PurpleChatConversation *
1577 purple_chat_conversation_new(PurpleAccount *account, const char *name) 1597 purple_chat_conversation_new(PurpleAccount *account, const char *name)
1578 { 1598 {
1579 PurpleChatConversation *chat; 1599 PurpleChatConversation *chat;
1600 PurpleConversation *conv;
1580 PurpleConnection *gc; 1601 PurpleConnection *gc;
1581 PurpleConversationUiOps *ops; 1602 PurpleConversationUiOps *ops;
1582 const char *disp; 1603 const char *disp;
1583 1604
1584 g_return_val_if_fail(account != NULL, NULL); 1605 g_return_val_if_fail(account != NULL, NULL);
1599 * purple_conversation_new need to fall-through to creating a new 1620 * purple_conversation_new need to fall-through to creating a new
1600 * chat. 1621 * chat.
1601 * TODO 3.0.0: Remove this workaround and mandate unique names. 1622 * TODO 3.0.0: Remove this workaround and mandate unique names.
1602 */ 1623 */
1603 1624
1604 purple_chat_conversation_cleanup_for_rejoin(chat); 1625 chat_conversation_cleanup_for_rejoin(chat);
1605 return chat; 1626 return chat;
1606 } 1627 }
1607 } 1628 }
1608 1629
1609 gc = purple_account_get_connection(account); 1630 gc = purple_account_get_connection(account);
1616 "account", account, 1637 "account", account,
1617 "name", name, 1638 "name", name,
1618 "title", name, 1639 "title", name,
1619 NULL); 1640 NULL);
1620 1641
1642 conv = PURPLE_CONVERSATION(chat);
1643
1621 /* copy features from the connection. */ 1644 /* copy features from the connection. */
1622 purple_conversation_set_features(PURPLE_CONVERSATION(chat), 1645 purple_conversation_set_features(conv,
1623 purple_connection_get_flags(gc)); 1646 purple_connection_get_flags(gc));
1624 1647
1625 purple_conversations_add(chat); 1648 purple_conversations_add(conv);
1626 1649
1627 if ((disp = purple_connection_get_display_name(purple_account_get_connection(account)))) 1650 if ((disp = purple_connection_get_display_name(purple_account_get_connection(account))))
1628 purple_chat_conversation_set_nick(chat, disp); 1651 purple_chat_conversation_set_nick(chat, disp);
1629 else 1652 else
1630 purple_chat_conversation_set_nick(chat, 1653 purple_chat_conversation_set_nick(chat,
1631 purple_account_get_username(account)); 1654 purple_account_get_username(account));
1632 1655
1633 if (purple_prefs_get_bool("/purple/logging/log_chats")) 1656 if (purple_prefs_get_bool("/purple/logging/log_chats"))
1634 { 1657 purple_conversation_set_logging(conv, TRUE);
1635 purple_conversation_set_logging(PURPLE_CONVERSATION(chat), TRUE);
1636 open_log(conv);
1637 }
1638 1658
1639 /* Auto-set the title. */ 1659 /* Auto-set the title. */
1640 purple_conversation_autoset_title(PURPLE_CONVERSATION(chat)); 1660 purple_conversation_autoset_title(conv);
1641 1661
1642 /* Don't move this.. it needs to be one of the last things done otherwise 1662 /* Don't move this.. it needs to be one of the last things done otherwise
1643 * it causes mysterious crashes on my system. 1663 * it causes mysterious crashes on my system.
1644 * -- Gary 1664 * -- Gary
1645 */ 1665 */
1646 ops = purple_conversations_get_ui_ops(); 1666 ops = purple_conversations_get_ui_ops();
1647 purple_conversation_set_ui_ops(PURPLE_CONVERSATION(im), ops); 1667 purple_conversation_set_ui_ops(PURPLE_CONVERSATION(chat), ops);
1648 if (ops != NULL && ops->create_conversation != NULL) 1668 if (ops != NULL && ops->create_conversation != NULL)
1649 ops->create_conversation(PURPLE_CONVERSATION(chat)); 1669 ops->create_conversation(conv);
1650 1670
1651 purple_signal_emit(purple_conversations_get_handle(), 1671 purple_signal_emit(purple_conversations_get_handle(),
1652 "conversation-created", chat); /* TODO chat-created */ 1672 "conversation-created", chat); /* TODO chat-created */
1653 1673
1654 return chat; 1674 return chat;
1659 **************************************************************************/ 1679 **************************************************************************/
1660 static int 1680 static int
1661 purple_chat_conversation_buddy_compare(PurpleChatConversationBuddy *a, PurpleChatConversationBuddy *b) 1681 purple_chat_conversation_buddy_compare(PurpleChatConversationBuddy *a, PurpleChatConversationBuddy *b)
1662 { 1682 {
1663 PurpleChatConversationBuddyFlags f1 = 0, f2 = 0; 1683 PurpleChatConversationBuddyFlags f1 = 0, f2 = 0;
1684 PurpleChatConversationBuddyPrivate *priva, *privb;
1664 char *user1 = NULL, *user2 = NULL; 1685 char *user1 = NULL, *user2 = NULL;
1665 gint ret = 0; 1686 gint ret = 0;
1666 1687
1667 if (a) { 1688 priva = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(a);
1668 f1 = a->flags; 1689 privb = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(b);
1669 if (a->alias_key) 1690
1670 user1 = a->alias_key; 1691 if (priva) {
1671 else if (a->name) 1692 f1 = priva->flags;
1672 user1 = a->name; 1693 if (priva->alias_key)
1673 } 1694 user1 = priva->alias_key;
1674 1695 else if (priva->name)
1675 if (b) { 1696 user1 = priva->name;
1676 f2 = b->flags; 1697 }
1677 if (b->alias_key) 1698
1678 user2 = b->alias_key; 1699 if (privb) {
1679 else if (b->name) 1700 f2 = privb->flags;
1680 user2 = b->name; 1701 if (privb->alias_key)
1702 user2 = privb->alias_key;
1703 else if (privb->name)
1704 user2 = privb->name;
1681 } 1705 }
1682 1706
1683 if (user1 == NULL || user2 == NULL) { 1707 if (user1 == NULL || user2 == NULL) {
1684 if (!(user1 == NULL && user2 == NULL)) 1708 if (!(user1 == NULL && user2 == NULL))
1685 ret = (user1 == NULL) ? -1: 1; 1709 ret = (user1 == NULL) ? -1: 1;
1686 } else if (f1 != f2) { 1710 } else if (f1 != f2) {
1687 /* sort more important users first */ 1711 /* sort more important users first */
1688 ret = (f1 > f2) ? -1 : 1; 1712 ret = (f1 > f2) ? -1 : 1;
1689 } else if (a->buddy != b->buddy) { 1713 } else if (priva->buddy != privb->buddy) {
1690 ret = a->buddy ? -1 : 1; 1714 ret = priva->buddy ? -1 : 1;
1691 } else { 1715 } else {
1692 ret = purple_utf8_strcasecmp(user1, user2); 1716 ret = purple_utf8_strcasecmp(user1, user2);
1693 } 1717 }
1694 1718
1695 return ret; 1719 return ret;
1696 } 1720 }
1697 1721
1698 const char * 1722 const char *
1699 purple_chat_conversation_buddy_get_alias(const PurpleChatConversationBuddy *cb) 1723 purple_chat_conversation_buddy_get_alias(const PurpleChatConversationBuddy *cb)
1700 { 1724 {
1701 g_return_val_if_fail(cb != NULL, NULL); 1725 PurpleChatConversationBuddyPrivate *priv;
1702 1726 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1703 return cb->alias; 1727
1728 g_return_val_if_fail(priv != NULL, NULL);
1729
1730 return priv->alias;
1704 } 1731 }
1705 1732
1706 const char * 1733 const char *
1707 purple_chat_conversation_buddy_get_name(const PurpleChatConversationBuddy *cb) 1734 purple_chat_conversation_buddy_get_name(const PurpleChatConversationBuddy *cb)
1708 { 1735 {
1709 g_return_val_if_fail(cb != NULL, NULL); 1736 PurpleChatConversationBuddyPrivate *priv;
1710 1737 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1711 return cb->name; 1738
1739 g_return_val_if_fail(priv != NULL, NULL);
1740
1741 return priv->name;
1742 }
1743
1744 void
1745 purple_chat_conversation_buddy_set_flags(PurpleChatConversationBuddy *cb,
1746 PurpleChatConversationBuddyFlags flags)
1747 {
1748 PurpleConversationUiOps *ops;
1749 PurpleChatConversationBuddyFlags oldflags;
1750 PurpleChatConversationBuddyPrivate *priv;
1751 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1752
1753 g_return_if_fail(priv != NULL);
1754
1755 if (flags == priv->flags)
1756 return;
1757
1758 oldflags = priv->flags;
1759 priv->flags = flags;
1760
1761 ops = purple_conversation_get_ui_ops(PURPLE_CONVERSATION(priv->chat));
1762
1763 if (ops != NULL && ops->chat_update_user != NULL)
1764 ops->chat_update_user(cb);
1765
1766 purple_signal_emit(purple_conversations_get_handle(),
1767 "chat-buddy-flags", priv->chat, priv->name, oldflags, flags); /* TODO use ChatBuddy object */
1712 } 1768 }
1713 1769
1714 PurpleChatConversationBuddyFlags 1770 PurpleChatConversationBuddyFlags
1715 purple_chat_conversation_buddy_get_flags(const PurpleChatConversationBuddy *cb) 1771 purple_chat_conversation_buddy_get_flags(const PurpleChatConversationBuddy *cb)
1716 { 1772 {
1717 g_return_val_if_fail(cb != NULL, PURPLE_CHAT_CONVERSATION_BUDDY_NONE); 1773 PurpleChatConversationBuddyPrivate *priv;
1718 1774 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1719 return cb->flags; 1775
1776 g_return_val_if_fail(priv != NULL, PURPLE_CHAT_CONVERSATION_BUDDY_NONE);
1777
1778 return priv->flags;
1720 } 1779 }
1721 1780
1722 const char * 1781 const char *
1723 purple_chat_conversation_buddy_get_attribute(PurpleChatConversationBuddy *cb, const char *key) 1782 purple_chat_conversation_buddy_get_attribute(PurpleChatConversationBuddy *cb, const char *key)
1724 { 1783 {
1725 g_return_val_if_fail(cb != NULL, NULL); 1784 PurpleChatConversationBuddyPrivate *priv;
1785 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1786
1787 g_return_val_if_fail(priv != NULL, NULL);
1726 g_return_val_if_fail(key != NULL, NULL); 1788 g_return_val_if_fail(key != NULL, NULL);
1727 1789
1728 return g_hash_table_lookup(cb->attributes, key); 1790 return g_hash_table_lookup(priv->attributes, key);
1729 } 1791 }
1730 1792
1731 static void 1793 static void
1732 append_attribute_key(gpointer key, gpointer value, gpointer user_data) 1794 append_attribute_key(gpointer key, gpointer value, gpointer user_data)
1733 { 1795 {
1737 1799
1738 GList * 1800 GList *
1739 purple_chat_conversation_buddy_get_attribute_keys(PurpleChatConversationBuddy *cb) 1801 purple_chat_conversation_buddy_get_attribute_keys(PurpleChatConversationBuddy *cb)
1740 { 1802 {
1741 GList *keys = NULL; 1803 GList *keys = NULL;
1804 PurpleChatConversationBuddyPrivate *priv;
1805 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1742 1806
1743 g_return_val_if_fail(cb != NULL, NULL); 1807 g_return_val_if_fail(priv != NULL, NULL);
1744 1808
1745 g_hash_table_foreach(cb->attributes, (GHFunc)append_attribute_key, &keys); 1809 g_hash_table_foreach(priv->attributes, (GHFunc)append_attribute_key, &keys);
1746 1810
1747 return keys; 1811 return keys;
1748 } 1812 }
1749 1813
1750 void 1814 void
1751 purple_chat_conversation_buddy_set_attribute(PurpleChatConversation *chat, PurpleChatConversationBuddy *cb, const char *key, const char *value) 1815 purple_chat_conversation_buddy_set_attribute(PurpleChatConversationBuddy *cb,
1752 { 1816 PurpleChatConversation *chat, const char *key, const char *value)
1753 PurpleConversation *conv; 1817 {
1754 PurpleConversationUiOps *ops; 1818 PurpleConversationUiOps *ops;
1755 1819 PurpleChatConversationBuddyPrivate *priv;
1756 g_return_if_fail(cb != NULL); 1820 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1821
1822 g_return_if_fail(priv != NULL);
1757 g_return_if_fail(key != NULL); 1823 g_return_if_fail(key != NULL);
1758 g_return_if_fail(value != NULL); 1824 g_return_if_fail(value != NULL);
1759 1825
1760 g_hash_table_replace(cb->attributes, g_strdup(key), g_strdup(value)); 1826 g_hash_table_replace(priv->attributes, g_strdup(key), g_strdup(value));
1761 1827
1762 conv = purple_chat_conversation_get_conversation(chat); 1828 ops = purple_conversation_get_ui_ops(PURPLE_CONVERSATION(chat));
1763 ops = purple_conversation_get_ui_ops(conv); 1829
1764
1765 if (ops != NULL && ops->chat_update_user != NULL) 1830 if (ops != NULL && ops->chat_update_user != NULL)
1766 ops->chat_update_user(conv, cb->name); 1831 ops->chat_update_user(cb);
1767 } 1832 }
1768 1833
1769 void 1834 void
1770 purple_chat_conversation_buddy_set_attributes(PurpleChatConversation *chat, PurpleChatConversationBuddy *cb, GList *keys, GList *values) 1835 purple_chat_conversation_buddy_set_attributes(PurpleChatConversationBuddy *cb,
1771 { 1836 PurpleChatConversation *chat, GList *keys, GList *values)
1772 PurpleConversation *conv; 1837 {
1773 PurpleConversationUiOps *ops; 1838 PurpleConversationUiOps *ops;
1774 1839 PurpleChatConversationBuddyPrivate *priv;
1775 g_return_if_fail(cb != NULL); 1840 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1841
1842 g_return_if_fail(priv != NULL);
1776 g_return_if_fail(keys != NULL); 1843 g_return_if_fail(keys != NULL);
1777 g_return_if_fail(values != NULL); 1844 g_return_if_fail(values != NULL);
1778 1845
1779 while (keys != NULL && values != NULL) { 1846 while (keys != NULL && values != NULL) {
1780 g_hash_table_replace(cb->attributes, g_strdup(keys->data), g_strdup(values->data)); 1847 g_hash_table_replace(priv->attributes, g_strdup(keys->data), g_strdup(values->data));
1781 keys = g_list_next(keys); 1848 keys = g_list_next(keys);
1782 values = g_list_next(values); 1849 values = g_list_next(values);
1783 } 1850 }
1784 1851
1785 conv = purple_chat_conversation_get_conversation(chat); 1852 ops = purple_conversation_get_ui_ops(PURPLE_CONVERSATION(chat));
1786 ops = purple_conversation_get_ui_ops(conv); 1853
1787
1788 if (ops != NULL && ops->chat_update_user != NULL) 1854 if (ops != NULL && ops->chat_update_user != NULL)
1789 ops->chat_update_user(conv, cb->name); 1855 ops->chat_update_user(cb);
1790 } 1856 }
1791 1857
1792 void purple_chat_conversation_buddy_set_ui_data(PurpleChatConversationBuddy *cb, gpointer ui_data) 1858 void
1793 { 1859 purple_chat_conversation_buddy_set_ui_data(PurpleChatConversationBuddy *cb, gpointer ui_data)
1794 g_return_if_fail(cb != NULL); 1860 {
1795 1861 PurpleChatConversationBuddyPrivate *priv;
1796 cb->ui_data = ui_data; 1862 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1797 } 1863
1798 1864 g_return_if_fail(priv != NULL);
1799 gpointer purple_chat_conversation_buddy_get_ui_data(const PurpleChatConversationBuddy *cb) 1865
1800 { 1866 priv->ui_data = ui_data;
1801 g_return_val_if_fail(cb != NULL, NULL); 1867 }
1802 1868
1803 return cb->ui_data; 1869 gpointer
1804 } 1870 purple_chat_conversation_buddy_get_ui_data(const PurpleChatConversationBuddy *cb)
1805 1871 {
1806 gboolean purple_chat_conversation_buddy_is_buddy(const PurpleChatConversationBuddy *cb) 1872 PurpleChatConversationBuddyPrivate *priv;
1807 { 1873 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1808 g_return_val_if_fail(cb != NULL, FALSE); 1874
1809 1875 g_return_val_if_fail(priv != NULL, NULL);
1810 return cb->buddy; 1876
1877 return priv->ui_data;
1878 }
1879
1880 void
1881 purple_chat_conversation_buddy_set_chat(PurpleChatConversationBuddy *cb,
1882 PurpleChatConversation *chat)
1883 {
1884 PurpleChatConversationBuddyPrivate *priv;
1885 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1886
1887 g_return_if_fail(priv != NULL);
1888
1889 priv->chat = chat;
1890 }
1891
1892 PurpleChatConversation *
1893 purple_chat_conversation_buddy_get_chat(const PurpleChatConversationBuddy *cb)
1894 {
1895 PurpleChatConversationBuddyPrivate *priv;
1896 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1897
1898 g_return_val_if_fail(priv != NULL, NULL);
1899
1900 return priv->chat;
1901 }
1902
1903 void
1904 purple_chat_conversation_buddy_set_buddy(const PurpleChatConversationBuddy *cb,
1905 gboolean buddy)
1906 {
1907 PurpleChatConversationBuddyPrivate *priv;
1908 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1909
1910 g_return_if_fail(priv != NULL);
1911
1912 priv->buddy = buddy;
1913 }
1914
1915 gboolean
1916 purple_chat_conversation_buddy_is_buddy(const PurpleChatConversationBuddy *cb)
1917 {
1918 PurpleChatConversationBuddyPrivate *priv;
1919 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1920
1921 g_return_val_if_fail(priv != NULL, FALSE);
1922
1923 return priv->buddy;
1811 } 1924 }
1812 1925
1813 /************************************************************************** 1926 /**************************************************************************
1814 * GObject code for chat buddy 1927 * GObject code for chat buddy
1815 **************************************************************************/ 1928 **************************************************************************/
1816 1929
1817 /* GObject Property names */ 1930 /* GObject Property names */
1818 #define PROP_NAME_S "name" 1931 #define CB_PROP_CHAT_S "chat"
1819 #define PROP_ALIAS_S "alias" 1932 #define CB_PROP_NAME_S "name"
1820 #define PROP_BUDDY_S "buddy" 1933 #define CB_PROP_ALIAS_S "alias"
1821 #define PROP_FLAGS_S "flags" 1934 #define CB_PROP_BUDDY_S "buddy"
1935 #define CB_PROP_FLAGS_S "flags"
1822 1936
1823 /* Set method for GObject properties */ 1937 /* Set method for GObject properties */
1824 static void 1938 static void
1825 purple_chat_conversation_buddy_set_property(GObject *obj, guint param_id, const GValue *value, 1939 purple_chat_conversation_buddy_set_property(GObject *obj, guint param_id, const GValue *value,
1826 GParamSpec *pspec) 1940 GParamSpec *pspec)
1827 { 1941 {
1828 PurpleChatConversationBuddy *cb = PURPLE_CHAT_CONVERSATION_BUDDY(obj); 1942 PurpleChatConversationBuddy *cb = PURPLE_CHAT_CONVERSATION_BUDDY(obj);
1829 PurpleChatConversationBuddyPrivate *priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb); 1943 PurpleChatConversationBuddyPrivate *priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(cb);
1830 1944
1831 switch (param_id) { 1945 switch (param_id) {
1832 case PROP_NAME: 1946 case CB_PROP_CHAT:
1947 purple_chat_conversation_buddy_set_chat(cb, g_value_get_object(value));
1948 break;
1949 case CB_PROP_NAME:
1833 g_free(priv->name); 1950 g_free(priv->name);
1834 priv->name = g_strdup(g_value_get_string(value)); 1951 priv->name = g_strdup(g_value_get_string(value));
1835 break; 1952 break;
1836 case PROP_ALIAS: 1953 case CB_PROP_ALIAS:
1837 g_free(priv->alias); 1954 g_free(priv->alias);
1838 priv->alias = g_strdup(g_value_get_string(value)); 1955 priv->alias = g_strdup(g_value_get_string(value));
1839 break; 1956 break;
1840 case PROP_BUDDY: 1957 case CB_PROP_BUDDY:
1841 priv->buddy = g_value_get_boolean(value); 1958 priv->buddy = g_value_get_boolean(value);
1842 break; 1959 break;
1843 case PROP_FLAGS: 1960 case CB_PROP_FLAGS:
1844 priv->flags = g_value_get_flags(value); 1961 purple_chat_conversation_buddy_set_flags(cb, g_value_get_flags(value));
1845 break; 1962 break;
1846 default: 1963 default:
1847 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); 1964 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
1848 break; 1965 break;
1849 } 1966 }
1855 GParamSpec *pspec) 1972 GParamSpec *pspec)
1856 { 1973 {
1857 PurpleChatConversationBuddy *cb = PURPLE_CHAT_CONVERSATION_BUDDY(obj); 1974 PurpleChatConversationBuddy *cb = PURPLE_CHAT_CONVERSATION_BUDDY(obj);
1858 1975
1859 switch (param_id) { 1976 switch (param_id) {
1860 case PROP_NAME: 1977 case CB_PROP_CHAT:
1978 g_value_set_object(value, purple_chat_conversation_buddy_get_chat(cb));
1979 break;
1980 case CB_PROP_NAME:
1861 g_value_set_string(value, purple_chat_conversation_buddy_get_name(cb)); 1981 g_value_set_string(value, purple_chat_conversation_buddy_get_name(cb));
1862 break; 1982 break;
1863 case PROP_ALIAS: 1983 case CB_PROP_ALIAS:
1864 g_value_set_string(value, purple_chat_conversation_buddy_get_alias(cb)); 1984 g_value_set_string(value, purple_chat_conversation_buddy_get_alias(cb));
1865 break; 1985 break;
1866 case PROP_BUDDY: 1986 case CB_PROP_BUDDY:
1867 g_value_set_boolean(value, purple_chat_conversation_buddy_is_buddy(cb)); 1987 g_value_set_boolean(value, purple_chat_conversation_buddy_is_buddy(cb));
1868 break; 1988 break;
1869 case PROP_FLAGS: 1989 case CB_PROP_FLAGS:
1870 g_value_set_flags(value, purple_chat_conversation_buddy_get_flags(cb)); 1990 g_value_set_flags(value, purple_chat_conversation_buddy_get_flags(cb));
1871 break; 1991 break;
1872 default: 1992 default:
1873 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); 1993 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
1874 break; 1994 break;
1876 } 1996 }
1877 1997
1878 /* GObject initialization function */ 1998 /* GObject initialization function */
1879 static void purple_chat_conversation_buddy_init(GTypeInstance *instance, gpointer klass) 1999 static void purple_chat_conversation_buddy_init(GTypeInstance *instance, gpointer klass)
1880 { 2000 {
1881 cb->attributes = g_hash_table_new_full(g_str_hash, g_str_equal, 2001 PurpleChatConversationBuddyPrivate *priv;
2002 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(instance);
2003
2004 priv->attributes = g_hash_table_new_full(g_str_hash, g_str_equal,
1882 g_free, g_free); 2005 g_free, g_free);
1883 } 2006 }
1884 2007
1885 /* GObject dispose function */ 2008 /* GObject dispose function */
1886 static void 2009 static void
1887 purple_chat_conversation_buddy_dispose(GObject *object) 2010 purple_chat_conversation_buddy_dispose(GObject *object)
1888 { 2011 {
2012 PurpleChatConversationBuddy *cb = PURPLE_CHAT_CONVERSATION_BUDDY(object);
2013
1889 purple_signal_emit(purple_conversations_get_handle(), 2014 purple_signal_emit(purple_conversations_get_handle(),
1890 "deleting-chat-buddy", cb); 2015 "deleting-chat-buddy", cb);
1891 PURPLE_DBUS_UNREGISTER_POINTER(cb); 2016 PURPLE_DBUS_UNREGISTER_POINTER(cb);
1892 2017
1893 cb_parent_class->dispose(object); 2018 cb_parent_class->dispose(object);
1895 2020
1896 /* GObject finalize function */ 2021 /* GObject finalize function */
1897 static void 2022 static void
1898 purple_chat_conversation_buddy_finalize(GObject *object) 2023 purple_chat_conversation_buddy_finalize(GObject *object)
1899 { 2024 {
1900 g_free(cb->alias); 2025 PurpleChatConversationBuddyPrivate *priv;
1901 g_free(cb->alias_key); 2026 priv = PURPLE_CHAT_CONVERSATION_BUDDY_GET_PRIVATE(object);
1902 g_free(cb->name); 2027
1903 g_hash_table_destroy(cb->attributes); 2028 g_free(priv->alias);
2029 g_free(priv->alias_key);
2030 g_free(priv->name);
2031 g_hash_table_destroy(priv->attributes);
1904 2032
1905 cb_parent_class->finalize(object); 2033 cb_parent_class->finalize(object);
1906 } 2034 }
1907 2035
1908 /* Class initializer function */ 2036 /* Class initializer function */
1917 2045
1918 /* Setup properties */ 2046 /* Setup properties */
1919 obj_class->get_property = purple_chat_conversation_buddy_get_property; 2047 obj_class->get_property = purple_chat_conversation_buddy_get_property;
1920 obj_class->set_property = purple_chat_conversation_buddy_set_property; 2048 obj_class->set_property = purple_chat_conversation_buddy_set_property;
1921 2049
1922 g_object_class_install_property(obj_class, PROP_NAME, 2050 g_object_class_install_property(obj_class, CB_PROP_CHAT,
1923 g_param_spec_string(PROP_NAME_S, _("Name"), 2051 g_param_spec_object(CB_PROP_CHAT_S, _("Chat"),
2052 _("The chat the buddy belongs to."), PURPLE_TYPE_CHAT_CONVERSATION,
2053 G_PARAM_READWRITE | G_PARAM_CONSTRUCT)
2054 );
2055
2056 g_object_class_install_property(obj_class, CB_PROP_NAME,
2057 g_param_spec_string(CB_PROP_NAME_S, _("Name"),
1924 _("Name of the chat buddy."), NULL, 2058 _("Name of the chat buddy."), NULL,
1925 G_PARAM_READWRITE) 2059 G_PARAM_READWRITE)
1926 ); 2060 );
1927 2061
1928 g_object_class_install_property(obj_class, PROP_ALIAS, 2062 g_object_class_install_property(obj_class, CB_PROP_ALIAS,
1929 g_param_spec_string(PROP_ALIAS_S, _("Alias"), 2063 g_param_spec_string(CB_PROP_ALIAS_S, _("Alias"),
1930 _("Alias of the chat buddy."), NULL, 2064 _("Alias of the chat buddy."), NULL,
1931 G_PARAM_READWRITE) 2065 G_PARAM_READWRITE)
1932 ); 2066 );
1933 2067
1934 g_object_class_install_property(obj_class, PROP_BUDDY, 2068 g_object_class_install_property(obj_class, CB_PROP_BUDDY,
1935 g_param_spec_boolean(PROP_BUDDY_S, _("Is buddy"), 2069 g_param_spec_boolean(CB_PROP_BUDDY_S, _("Is buddy"),
1936 _("Whether the chat buddy is in the buddy list."), FALSE, 2070 _("Whether the chat buddy is in the buddy list."), FALSE,
1937 G_PARAM_READWRITE) 2071 G_PARAM_READWRITE)
1938 ); 2072 );
1939 2073
1940 g_object_class_install_property(obj_class, PROP_FLAGS, 2074 g_object_class_install_property(obj_class, CB_PROP_FLAGS,
1941 g_param_spec_flags(PROP_FLAGS_S, _("Buddy flags"), 2075 g_param_spec_flags(CB_PROP_FLAGS_S, _("Buddy flags"),
1942 _("The flags for the chat buddy."), 2076 _("The flags for the chat buddy."),
1943 PURPLE_TYPE_CHAT_CONVERSATION_BUDDY_FLAGS, 2077 PURPLE_TYPE_CHAT_CONVERSATION_BUDDY_FLAGS,
1944 PURPLE_CHAT_CONVERSATION_BUDDY_NONE, G_PARAM_READWRITE) 2078 PURPLE_CHAT_CONVERSATION_BUDDY_NONE, G_PARAM_READWRITE)
1945 ); 2079 );
1946 2080
1973 2107
1974 return type; 2108 return type;
1975 } 2109 }
1976 2110
1977 PurpleChatConversationBuddy * 2111 PurpleChatConversationBuddy *
1978 purple_chat_conversation_buddy_new(const char *name, const char *alias, PurpleChatConversationBuddyFlags flags) 2112 purple_chat_conversation_buddy_new(PurpleChatConversation *chat, const char *name,
2113 const char *alias, PurpleChatConversationBuddyFlags flags)
1979 { 2114 {
1980 PurpleChatConversationBuddy *cb; 2115 PurpleChatConversationBuddy *cb;
1981 2116
2117 g_return_val_if_fail(chat != NULL, NULL);
1982 g_return_val_if_fail(name != NULL, NULL); 2118 g_return_val_if_fail(name != NULL, NULL);
1983 2119
1984 cb = g_object_new(PURPLE_TYPE_CHAT_CONVERSATION_BUDDY, 2120 cb = g_object_new(PURPLE_TYPE_CHAT_CONVERSATION_BUDDY,
2121 "chat", chat,
1985 "name", name, 2122 "name", name,
1986 "alias", alias, 2123 "alias", alias,
1987 "flags", flags, 2124 "flags", flags,
1988 NULL); 2125 NULL);
1989 2126

mercurial