4 * Purple is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 #include "glibcompat.h"
25 #include "buddylist.h"
27 #include "conversation.h"
35 #include "smiley-list.h"
38 typedef struct _PurpleConversationPrivate PurpleConversationPrivate
;
40 /* General private data for a conversation */
41 struct _PurpleConversationPrivate
43 PurpleAccount
*account
; /* The user using this conversation. */
45 char *name
; /* The name of the conversation. */
46 char *title
; /* The window title. */
48 gboolean logging
; /* The status of logging. */
50 GList
*logs
; /* This conversation's logs */
52 PurpleConversationUiOps
*ui_ops
; /* UI-specific operations. */
54 PurpleConnectionFlags features
; /* The supported features */
55 GList
*message_history
; /* Message history, as a GList of PurpleMessages */
57 PurpleE2eeState
*e2ee_state
; /* End-to-end encryption state. */
59 /* The list of remote smileys. This should be per-buddy (PurpleBuddy),
60 * but we don't have any class for people not on our buddy
61 * list (PurpleDude?). So, if we have one, we should switch to it. */
62 PurpleSmileyList
*remote_smileys
;
65 /* GObject Property enums */
77 static GParamSpec
*properties
[PROP_LAST
];
79 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(PurpleConversation
, purple_conversation
,
83 common_send(PurpleConversation
*conv
, const char *message
, PurpleMessageFlags msgflags
)
85 PurpleAccount
*account
;
87 PurpleConversationPrivate
*priv
=
88 purple_conversation_get_instance_private(conv
);
90 char *displayed
= NULL
;
97 account
= purple_conversation_get_account(conv
);
98 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
100 gc
= purple_account_get_connection(account
);
101 g_return_if_fail(PURPLE_IS_CONNECTION(gc
));
103 /* Always linkfy the text for display, unless we're
104 * explicitly asked to do otheriwse*/
105 if (!(msgflags
& PURPLE_MESSAGE_INVISIBLE
)) {
106 if(msgflags
& PURPLE_MESSAGE_NO_LINKIFY
)
107 displayed
= g_strdup(message
);
109 displayed
= purple_markup_linkify(message
);
112 if (displayed
&& (priv
->features
& PURPLE_CONNECTION_FLAG_HTML
) &&
113 !(msgflags
& PURPLE_MESSAGE_RAW
)) {
118 msgflags
|= PURPLE_MESSAGE_SEND
;
120 if (PURPLE_IS_IM_CONVERSATION(conv
)) {
121 msg
= purple_message_new_outgoing(
122 purple_conversation_get_name(conv
), sent
, msgflags
);
124 purple_signal_emit(purple_conversations_get_handle(), "sending-im-msg",
127 if (!purple_message_is_empty(msg
)) {
129 err
= purple_serv_send_im(gc
, msg
);
131 if ((err
> 0) && (displayed
!= NULL
)) {
132 /* revert the contents in case sending-im-msg changed it */
133 purple_message_set_contents(msg
, displayed
);
134 purple_conversation_write_message(conv
, msg
);
137 purple_signal_emit(purple_conversations_get_handle(),
138 "sent-im-msg", account
, msg
);
141 else if (PURPLE_IS_CHAT_CONVERSATION(conv
)) {
142 int id
= purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv
));
144 msg
= purple_message_new_outgoing(NULL
, sent
, msgflags
);
146 purple_signal_emit(purple_conversations_get_handle(),
147 "sending-chat-msg", account
, msg
, id
);
149 if (!purple_message_is_empty(msg
)) {
150 err
= purple_serv_chat_send(gc
, id
, msg
);
152 purple_signal_emit(purple_conversations_get_handle(),
153 "sent-chat-msg", account
, msg
, id
);
161 who
= purple_conversation_get_name(conv
);
164 msg
= _("Unable to send message: The message is too large.");
166 if (!purple_conversation_present_error(who
, account
, msg
)) {
167 char *msg2
= g_strdup_printf(_("Unable to send message to %s."), who
);
168 purple_notify_error(gc
, NULL
, msg2
,
169 _("The message is too large."),
170 purple_request_cpar_from_connection(gc
));
174 else if (err
== -ENOTCONN
) {
175 purple_debug(PURPLE_DEBUG_ERROR
, "conversation",
176 "Not yet connected.\n");
179 msg
= _("Unable to send message.");
181 if (!purple_conversation_present_error(who
, account
, msg
)) {
182 char *msg2
= g_strdup_printf(_("Unable to send message to %s."), who
);
183 purple_notify_error(gc
, NULL
, msg2
, NULL
,
184 purple_request_cpar_from_connection(gc
));
193 /**************************************************************************
195 **************************************************************************/
197 purple_conversation_present(PurpleConversation
*conv
) {
198 PurpleConversationUiOps
*ops
;
200 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
202 ops
= purple_conversation_get_ui_ops(conv
);
203 if(ops
&& ops
->present
)
208 purple_conversation_set_features(PurpleConversation
*conv
, PurpleConnectionFlags features
)
210 PurpleConversationPrivate
*priv
= NULL
;
212 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
214 priv
= purple_conversation_get_instance_private(conv
);
215 priv
->features
= features
;
217 g_object_notify_by_pspec(G_OBJECT(conv
), properties
[PROP_FEATURES
]);
219 purple_conversation_update(conv
, PURPLE_CONVERSATION_UPDATE_FEATURES
);
222 PurpleConnectionFlags
223 purple_conversation_get_features(PurpleConversation
*conv
)
225 PurpleConversationPrivate
*priv
= NULL
;
227 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), 0);
229 priv
= purple_conversation_get_instance_private(conv
);
230 return priv
->features
;
233 static PurpleConversationUiOps
*
234 purple_conversation_ui_ops_copy(PurpleConversationUiOps
*ops
)
236 PurpleConversationUiOps
*ops_new
;
238 g_return_val_if_fail(ops
!= NULL
, NULL
);
240 ops_new
= g_new(PurpleConversationUiOps
, 1);
247 purple_conversation_ui_ops_get_type(void)
249 static GType type
= 0;
252 type
= g_boxed_type_register_static("PurpleConversationUiOps",
253 (GBoxedCopyFunc
)purple_conversation_ui_ops_copy
,
254 (GBoxedFreeFunc
)g_free
);
261 purple_conversation_set_ui_ops(PurpleConversation
*conv
,
262 PurpleConversationUiOps
*ops
)
264 PurpleConversationPrivate
*priv
= NULL
;
266 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
267 priv
= purple_conversation_get_instance_private(conv
);
269 if (priv
->ui_ops
== ops
)
272 if (priv
->ui_ops
!= NULL
&& priv
->ui_ops
->destroy_conversation
!= NULL
)
273 priv
->ui_ops
->destroy_conversation(conv
);
278 PurpleConversationUiOps
*
279 purple_conversation_get_ui_ops(PurpleConversation
*conv
)
281 PurpleConversationPrivate
*priv
= NULL
;
283 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
285 priv
= purple_conversation_get_instance_private(conv
);
290 purple_conversation_set_account(PurpleConversation
*conv
, PurpleAccount
*account
)
292 PurpleConversationPrivate
*priv
= NULL
;
294 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
295 priv
= purple_conversation_get_instance_private(conv
);
297 if (account
== purple_conversation_get_account(conv
))
300 _purple_conversations_update_cache(conv
, NULL
, account
);
301 priv
->account
= account
;
303 g_object_notify_by_pspec(G_OBJECT(conv
), properties
[PROP_ACCOUNT
]);
305 purple_conversation_update(conv
, PURPLE_CONVERSATION_UPDATE_ACCOUNT
);
309 purple_conversation_get_account(PurpleConversation
*conv
)
311 PurpleConversationPrivate
*priv
= NULL
;
313 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
315 priv
= purple_conversation_get_instance_private(conv
);
316 return priv
->account
;
320 purple_conversation_get_connection(PurpleConversation
*conv
)
322 PurpleAccount
*account
;
324 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
326 account
= purple_conversation_get_account(conv
);
331 return purple_account_get_connection(account
);
335 purple_conversation_set_title(PurpleConversation
*conv
, const char *title
)
337 PurpleConversationPrivate
*priv
= NULL
;
339 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
340 g_return_if_fail(title
!= NULL
);
342 priv
= purple_conversation_get_instance_private(conv
);
344 priv
->title
= g_strdup(title
);
346 if (!g_object_get_data(G_OBJECT(conv
), "is-finalizing"))
347 g_object_notify_by_pspec(G_OBJECT(conv
), properties
[PROP_TITLE
]);
349 purple_conversation_update(conv
, PURPLE_CONVERSATION_UPDATE_TITLE
);
353 purple_conversation_get_title(PurpleConversation
*conv
)
355 PurpleConversationPrivate
*priv
= NULL
;
357 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
359 priv
= purple_conversation_get_instance_private(conv
);
364 purple_conversation_autoset_title(PurpleConversation
*conv
)
366 PurpleAccount
*account
;
369 const char *text
= NULL
, *name
;
371 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
373 account
= purple_conversation_get_account(conv
);
374 name
= purple_conversation_get_name(conv
);
376 if (PURPLE_IS_IM_CONVERSATION(conv
)) {
377 if (account
&& ((b
= purple_blist_find_buddy(account
, name
)) != NULL
))
378 text
= purple_buddy_get_contact_alias(b
);
379 } else if (PURPLE_IS_CHAT_CONVERSATION(conv
)) {
380 if (account
&& ((chat
= purple_blist_find_chat(account
, name
)) != NULL
))
381 text
= purple_chat_get_name(chat
);
387 purple_conversation_set_title(conv
, text
);
391 purple_conversation_set_name(PurpleConversation
*conv
, const char *name
)
393 PurpleConversationPrivate
*priv
= NULL
;
395 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
396 priv
= purple_conversation_get_instance_private(conv
);
398 _purple_conversations_update_cache(conv
, name
, NULL
);
401 priv
->name
= g_strdup(name
);
403 g_object_notify_by_pspec(G_OBJECT(conv
), properties
[PROP_NAME
]);
405 purple_conversation_autoset_title(conv
);
406 purple_conversation_update(conv
, PURPLE_CONVERSATION_UPDATE_NAME
);
410 purple_conversation_get_name(PurpleConversation
*conv
)
412 PurpleConversationPrivate
*priv
= NULL
;
414 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
416 priv
= purple_conversation_get_instance_private(conv
);
421 purple_conversation_set_e2ee_state(PurpleConversation
*conv
,
422 PurpleE2eeState
*state
)
424 PurpleConversationPrivate
*priv
= NULL
;
426 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
427 priv
= purple_conversation_get_instance_private(conv
);
429 if (state
!= NULL
&& purple_e2ee_state_get_provider(state
) !=
430 purple_e2ee_provider_get_main())
432 purple_debug_error("conversation",
433 "This is not the main e2ee provider");
438 if (state
== priv
->e2ee_state
)
442 purple_e2ee_state_ref(state
);
443 purple_e2ee_state_unref(priv
->e2ee_state
);
444 priv
->e2ee_state
= state
;
446 purple_conversation_update(conv
, PURPLE_CONVERSATION_UPDATE_E2EE
);
450 purple_conversation_get_e2ee_state(PurpleConversation
*conv
)
452 PurpleConversationPrivate
*priv
= NULL
;
453 PurpleE2eeProvider
*provider
;
455 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
456 priv
= purple_conversation_get_instance_private(conv
);
458 if (priv
->e2ee_state
== NULL
)
461 provider
= purple_e2ee_provider_get_main();
462 if (provider
== NULL
)
465 if (purple_e2ee_state_get_provider(priv
->e2ee_state
) != provider
) {
466 purple_debug_warning("conversation",
467 "e2ee state has invalid provider set");
471 return priv
->e2ee_state
;
475 purple_conversation_set_logging(PurpleConversation
*conv
, gboolean log
)
477 PurpleConversationPrivate
*priv
= NULL
;
479 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
480 priv
= purple_conversation_get_instance_private(conv
);
482 if (priv
->logging
!= log
)
485 if (log
&& priv
->logs
== NULL
) {
489 dt
= g_date_time_new_now_local();
490 log
= purple_log_new(PURPLE_IS_CHAT_CONVERSATION(conv
)
493 priv
->name
, priv
->account
, conv
,
495 g_date_time_unref(dt
);
497 priv
->logs
= g_list_append(NULL
, log
);
500 g_object_notify_by_pspec(G_OBJECT(conv
), properties
[PROP_LOGGING
]);
502 purple_conversation_update(conv
, PURPLE_CONVERSATION_UPDATE_LOGGING
);
507 purple_conversation_is_logging(PurpleConversation
*conv
)
509 PurpleConversationPrivate
*priv
= NULL
;
511 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), FALSE
);
513 priv
= purple_conversation_get_instance_private(conv
);
514 return priv
->logging
;
518 purple_conversation_close_logs(PurpleConversation
*conv
)
520 PurpleConversationPrivate
*priv
= NULL
;
522 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
524 priv
= purple_conversation_get_instance_private(conv
);
525 g_list_free_full(priv
->logs
, (GDestroyNotify
)purple_log_free
);
530 _purple_conversation_write_common(PurpleConversation
*conv
, PurpleMessage
*pmsg
)
532 PurpleConversationPrivate
*priv
= NULL
;
533 PurpleProtocol
*protocol
= NULL
;
534 PurpleConnection
*gc
= NULL
;
535 PurpleAccount
*account
;
536 PurpleConversationUiOps
*ops
;
539 /* int logging_font_options = 0; */
541 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
542 g_return_if_fail(pmsg
!= NULL
);
544 priv
= purple_conversation_get_instance_private(conv
);
545 ops
= purple_conversation_get_ui_ops(conv
);
547 account
= purple_conversation_get_account(conv
);
550 gc
= purple_account_get_connection(account
);
552 if (PURPLE_IS_CHAT_CONVERSATION(conv
) &&
553 (gc
!= NULL
&& !g_slist_find(purple_connection_get_active_chats(gc
), conv
)))
556 if (PURPLE_IS_IM_CONVERSATION(conv
) &&
557 !g_list_find(purple_conversations_get_all(), conv
))
560 plugin_return
= GPOINTER_TO_INT(purple_signal_emit_return_1(
561 purple_conversations_get_handle(),
562 (PURPLE_IS_IM_CONVERSATION(conv
) ? "writing-im-msg" : "writing-chat-msg"),
565 if (purple_message_is_empty(pmsg
))
571 if (account
!= NULL
) {
572 protocol
= purple_protocols_find(purple_account_get_protocol_id(account
));
574 if (PURPLE_IS_IM_CONVERSATION(conv
) ||
575 !(purple_protocol_get_options(protocol
) & OPT_PROTO_UNIQUE_CHATNAME
)) {
577 if (purple_message_get_flags(pmsg
) & PURPLE_MESSAGE_SEND
) {
580 b
= purple_blist_find_buddy(account
,
581 purple_account_get_username(account
));
583 if (purple_account_get_private_alias(account
) != NULL
)
584 alias
= purple_account_get_private_alias(account
);
585 else if (b
!= NULL
&& !purple_strequal(purple_buddy_get_name(b
),
586 purple_buddy_get_contact_alias(b
)))
588 alias
= purple_buddy_get_contact_alias(b
);
589 } else if (purple_connection_get_display_name(gc
) != NULL
)
590 alias
= purple_connection_get_display_name(gc
);
592 alias
= purple_account_get_username(account
);
594 purple_message_set_author_alias(pmsg
, alias
);
596 else if (purple_message_get_flags(pmsg
) & PURPLE_MESSAGE_RECV
)
598 /* TODO: PurpleDude - folks not on the buddy list */
599 b
= purple_blist_find_buddy(account
,
600 purple_message_get_author(pmsg
));
603 purple_message_set_author_alias(pmsg
,
604 purple_buddy_get_contact_alias(b
));
610 if (!(purple_message_get_flags(pmsg
) & PURPLE_MESSAGE_NO_LOG
) && purple_conversation_is_logging(conv
)) {
614 dt
= g_date_time_new_from_unix_local(purple_message_get_time(pmsg
));
616 while (log
!= NULL
) {
617 purple_log_write((PurpleLog
*)log
->data
,
618 purple_message_get_flags(pmsg
),
619 purple_message_get_author_alias(pmsg
),
621 purple_message_get_contents(pmsg
));
624 g_date_time_unref(dt
);
628 if (PURPLE_IS_CHAT_CONVERSATION(conv
) && ops
->write_chat
)
629 ops
->write_chat(PURPLE_CHAT_CONVERSATION(conv
), pmsg
);
630 else if (PURPLE_IS_IM_CONVERSATION(conv
) && ops
->write_im
)
631 ops
->write_im(PURPLE_IM_CONVERSATION(conv
), pmsg
);
632 else if (ops
->write_conv
)
633 ops
->write_conv(conv
, pmsg
);
637 priv
->message_history
= g_list_prepend(priv
->message_history
, pmsg
);
639 purple_signal_emit(purple_conversations_get_handle(),
640 (PURPLE_IS_IM_CONVERSATION(conv
) ? "wrote-im-msg" : "wrote-chat-msg"),
645 purple_conversation_write_message(PurpleConversation
*conv
, PurpleMessage
*msg
)
647 PurpleConversationClass
*klass
= NULL
;
649 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
651 klass
= PURPLE_CONVERSATION_GET_CLASS(conv
);
653 if (klass
&& klass
->write_message
)
654 klass
->write_message(conv
, msg
);
657 void purple_conversation_write_system_message(PurpleConversation
*conv
,
658 const gchar
*message
, PurpleMessageFlags flags
)
660 _purple_conversation_write_common(conv
,
661 purple_message_new_system(message
, flags
));
665 purple_conversation_send(PurpleConversation
*conv
, const char *message
)
667 purple_conversation_send_with_flags(conv
, message
, 0);
671 purple_conversation_send_with_flags(PurpleConversation
*conv
, const char *message
,
672 PurpleMessageFlags flags
)
674 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
675 g_return_if_fail(message
!= NULL
);
677 common_send(conv
, message
, flags
);
681 purple_conversation_has_focus(PurpleConversation
*conv
)
683 gboolean ret
= FALSE
;
684 PurpleConversationUiOps
*ops
;
686 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), FALSE
);
688 ops
= purple_conversation_get_ui_ops(conv
);
690 if (ops
!= NULL
&& ops
->has_focus
!= NULL
)
691 ret
= ops
->has_focus(conv
);
697 * TODO: Need to make sure calls to this function happen in the core
698 * instead of the UI. That way UIs have less work to do, and the
699 * core/UI split is cleaner. Also need to make sure this is called
700 * when chats are added/removed from the blist.
703 purple_conversation_update(PurpleConversation
*conv
, PurpleConversationUpdateType type
)
705 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
707 purple_signal_emit(purple_conversations_get_handle(),
708 "conversation-updated", conv
, type
);
711 gboolean
purple_conversation_present_error(const char *who
, PurpleAccount
*account
, const char *what
)
713 PurpleConversation
*conv
;
715 g_return_val_if_fail(who
!= NULL
, FALSE
);
716 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
717 g_return_val_if_fail(what
!= NULL
, FALSE
);
719 conv
= purple_conversations_find_with_account(who
, account
);
721 purple_conversation_write_system_message(conv
, what
, PURPLE_MESSAGE_ERROR
);
729 purple_conversation_send_confirm_cb(gpointer
*data
)
731 PurpleConversation
*conv
= data
[0];
732 char *message
= data
[1];
736 if (!PURPLE_IS_CONVERSATION(conv
)) {
737 /* Maybe it was closed before this callback was called. */
741 common_send(conv
, message
, 0);
745 purple_conversation_send_confirm(PurpleConversation
*conv
, const char *message
)
747 PurpleConversationPrivate
*priv
= NULL
;
751 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
752 g_return_if_fail(message
!= NULL
);
754 priv
= purple_conversation_get_instance_private(conv
);
755 if (priv
->ui_ops
!= NULL
&& priv
->ui_ops
->send_confirm
!= NULL
)
757 priv
->ui_ops
->send_confirm(conv
, message
);
761 text
= g_strdup_printf("You are about to send the following message:\n%s", message
);
762 data
= g_new0(gpointer
, 2);
764 data
[1] = (gpointer
)message
;
766 purple_request_action(conv
, NULL
, _("Send Message"), text
, 0,
767 purple_request_cpar_from_account(
768 purple_conversation_get_account(conv
)),
769 data
, 2, _("_Send Message"),
770 G_CALLBACK(purple_conversation_send_confirm_cb
), _("Cancel"), NULL
);
774 purple_conversation_get_extended_menu(PurpleConversation
*conv
)
778 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
780 purple_signal_emit(purple_conversations_get_handle(),
781 "conversation-extended-menu", conv
, &menu
);
785 void purple_conversation_clear_message_history(PurpleConversation
*conv
)
787 PurpleConversationPrivate
*priv
= NULL
;
790 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
792 priv
= purple_conversation_get_instance_private(conv
);
793 list
= priv
->message_history
;
794 g_list_free_full(list
, g_object_unref
);
795 priv
->message_history
= NULL
;
797 purple_signal_emit(purple_conversations_get_handle(),
798 "cleared-message-history", conv
);
801 GList
*purple_conversation_get_message_history(PurpleConversation
*conv
)
803 PurpleConversationPrivate
*priv
= NULL
;
805 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
807 priv
= purple_conversation_get_instance_private(conv
);
808 return priv
->message_history
;
811 void purple_conversation_set_ui_data(PurpleConversation
*conv
, gpointer ui_data
)
813 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
815 conv
->ui_data
= ui_data
;
818 gpointer
purple_conversation_get_ui_data(const PurpleConversation
*conv
)
820 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
822 return conv
->ui_data
;
826 purple_conversation_do_command(PurpleConversation
*conv
, const gchar
*cmdline
,
827 const gchar
*markup
, gchar
**error
)
829 char *mark
= (markup
&& *markup
) ? NULL
: g_markup_escape_text(cmdline
, -1), *err
= NULL
;
830 PurpleCmdStatus status
= purple_cmd_do_command(conv
, cmdline
, mark
? mark
: markup
, error
? error
: &err
);
833 return (status
== PURPLE_CMD_STATUS_OK
);
837 purple_conversation_get_max_message_size(PurpleConversation
*conv
)
839 PurpleProtocol
*protocol
;
841 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), 0);
843 protocol
= purple_connection_get_protocol(
844 purple_conversation_get_connection(conv
));
846 g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol
), 0);
848 return purple_protocol_client_iface_get_max_message_size(protocol
, conv
);
852 purple_conversation_add_smiley(PurpleConversation
*conv
, PurpleSmiley
*smiley
) {
853 PurpleConversationPrivate
*priv
= NULL
;
855 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
856 g_return_if_fail(smiley
);
858 priv
= purple_conversation_get_instance_private(conv
);
860 if (priv
->remote_smileys
== NULL
) {
861 priv
->remote_smileys
= purple_smiley_list_new();
862 g_object_set(priv
->remote_smileys
,
863 "drop-failed-remotes", TRUE
, NULL
);
866 if(purple_smiley_list_get_by_shortcut(
867 priv
->remote_smileys
,
868 purple_smiley_get_shortcut(smiley
)))
870 /* smiley was already added */
874 if (!purple_smiley_list_add(priv
->remote_smileys
, smiley
)) {
875 purple_debug_error("conversation", "failed adding remote "
876 "smiley to the list");
881 purple_conversation_get_smiley(PurpleConversation
*conv
, const gchar
*shortcut
) {
882 PurpleConversationPrivate
*priv
= NULL
;
884 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
885 g_return_val_if_fail(shortcut
, NULL
);
887 priv
= purple_conversation_get_instance_private(conv
);
889 if (priv
->remote_smileys
== NULL
)
892 return purple_smiley_list_get_by_shortcut(priv
->remote_smileys
, shortcut
);
896 purple_conversation_get_remote_smileys(PurpleConversation
*conv
)
898 PurpleConversationPrivate
*priv
= NULL
;
900 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
902 priv
= purple_conversation_get_instance_private(conv
);
903 return priv
->remote_smileys
;
907 /**************************************************************************
909 **************************************************************************/
911 /* Set method for GObject properties */
913 purple_conversation_set_property(GObject
*obj
, guint param_id
, const GValue
*value
,
916 PurpleConversation
*conv
= PURPLE_CONVERSATION(obj
);
917 PurpleConversationPrivate
*priv
=
918 purple_conversation_get_instance_private(conv
);
922 priv
->account
= g_value_get_object(value
);
926 priv
->name
= g_value_dup_string(value
);
930 priv
->title
= g_value_dup_string(value
);
933 purple_conversation_set_logging(conv
, g_value_get_boolean(value
));
936 purple_conversation_set_features(conv
, g_value_get_flags(value
));
939 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
944 /* Get method for GObject properties */
946 purple_conversation_get_property(GObject
*obj
, guint param_id
, GValue
*value
,
949 PurpleConversation
*conv
= PURPLE_CONVERSATION(obj
);
953 g_value_set_object(value
, purple_conversation_get_account(conv
));
956 g_value_set_string(value
, purple_conversation_get_name(conv
));
959 g_value_set_string(value
, purple_conversation_get_title(conv
));
962 g_value_set_boolean(value
, purple_conversation_is_logging(conv
));
965 g_value_set_flags(value
, purple_conversation_get_features(conv
));
968 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
974 purple_conversation_init(PurpleConversation
*conv
)
978 /* Called when done constructing */
980 purple_conversation_constructed(GObject
*object
)
982 PurpleConversation
*conv
= PURPLE_CONVERSATION(object
);
983 PurpleAccount
*account
;
984 PurpleConnection
*gc
;
985 PurpleConversationUiOps
*ops
;
987 G_OBJECT_CLASS(purple_conversation_parent_class
)->constructed(object
);
989 g_object_get(object
, "account", &account
, NULL
);
990 gc
= purple_account_get_connection(account
);
992 /* copy features from the connection. */
993 purple_conversation_set_features(conv
, purple_connection_get_flags(gc
));
995 /* add the conversation to the appropriate lists */
996 purple_conversations_add(conv
);
998 /* Auto-set the title. */
999 purple_conversation_autoset_title(conv
);
1001 /* Don't move this.. it needs to be one of the last things done otherwise
1002 * it causes mysterious crashes on my system.
1005 ops
= purple_conversations_get_ui_ops();
1006 purple_conversation_set_ui_ops(conv
, ops
);
1007 if (ops
!= NULL
&& ops
->create_conversation
!= NULL
)
1008 ops
->create_conversation(conv
);
1010 purple_signal_emit(purple_conversations_get_handle(),
1011 "conversation-created", conv
);
1013 g_object_unref(account
);
1017 purple_conversation_dispose(GObject
*object
)
1019 g_object_set_data(object
, "is-finalizing", GINT_TO_POINTER(TRUE
));
1022 /* GObject finalize function */
1024 purple_conversation_finalize(GObject
*object
)
1026 PurpleConversation
*conv
= PURPLE_CONVERSATION(object
);
1027 PurpleConversationPrivate
*priv
=
1028 purple_conversation_get_instance_private(conv
);
1029 PurpleConversationUiOps
*ops
= purple_conversation_get_ui_ops(conv
);
1031 purple_request_close_with_handle(conv
);
1033 purple_e2ee_state_unref(priv
->e2ee_state
);
1034 priv
->e2ee_state
= NULL
;
1036 /* remove from conversations and im/chats lists prior to emit */
1037 purple_conversations_remove(conv
);
1039 purple_signal_emit(purple_conversations_get_handle(),
1040 "deleting-conversation", conv
);
1042 purple_conversation_close_logs(conv
);
1043 purple_conversation_clear_message_history(conv
);
1045 if (ops
!= NULL
&& ops
->destroy_conversation
!= NULL
)
1046 ops
->destroy_conversation(conv
);
1049 g_free(priv
->title
);
1054 G_OBJECT_CLASS(purple_conversation_parent_class
)->finalize(object
);
1057 /* Class initializer function */
1059 purple_conversation_class_init(PurpleConversationClass
*klass
)
1061 GObjectClass
*obj_class
= G_OBJECT_CLASS(klass
);
1063 obj_class
->dispose
= purple_conversation_dispose
;
1064 obj_class
->finalize
= purple_conversation_finalize
;
1065 obj_class
->constructed
= purple_conversation_constructed
;
1067 /* Setup properties */
1068 obj_class
->get_property
= purple_conversation_get_property
;
1069 obj_class
->set_property
= purple_conversation_set_property
;
1071 properties
[PROP_ACCOUNT
] = g_param_spec_object("account", "Account",
1072 "The account for the conversation.", PURPLE_TYPE_ACCOUNT
,
1073 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
| G_PARAM_STATIC_STRINGS
);
1075 properties
[PROP_NAME
] = g_param_spec_string("name", "Name",
1076 "The name of the conversation.", NULL
,
1077 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
| G_PARAM_STATIC_STRINGS
);
1079 properties
[PROP_TITLE
] = g_param_spec_string("title", "Title",
1080 "The title of the conversation.", NULL
,
1081 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
| G_PARAM_STATIC_STRINGS
);
1083 properties
[PROP_LOGGING
] = g_param_spec_boolean("logging", "Logging status",
1084 "Whether logging is enabled or not.", FALSE
,
1085 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1087 properties
[PROP_FEATURES
] = g_param_spec_flags("features",
1088 "Connection features",
1089 "The connection features of the conversation.",
1090 PURPLE_TYPE_CONNECTION_FLAGS
, 0,
1091 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1093 g_object_class_install_properties(obj_class
, PROP_LAST
, properties
);