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_foreach(priv
->logs
, (GFunc
)purple_log_free
, NULL
);
526 g_list_free(priv
->logs
);
531 _purple_conversation_write_common(PurpleConversation
*conv
, PurpleMessage
*pmsg
)
533 PurpleConversationPrivate
*priv
= NULL
;
534 PurpleProtocol
*protocol
= NULL
;
535 PurpleConnection
*gc
= NULL
;
536 PurpleAccount
*account
;
537 PurpleConversationUiOps
*ops
;
540 /* int logging_font_options = 0; */
542 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
543 g_return_if_fail(pmsg
!= NULL
);
545 priv
= purple_conversation_get_instance_private(conv
);
546 ops
= purple_conversation_get_ui_ops(conv
);
548 account
= purple_conversation_get_account(conv
);
551 gc
= purple_account_get_connection(account
);
553 if (PURPLE_IS_CHAT_CONVERSATION(conv
) &&
554 (gc
!= NULL
&& !g_slist_find(purple_connection_get_active_chats(gc
), conv
)))
557 if (PURPLE_IS_IM_CONVERSATION(conv
) &&
558 !g_list_find(purple_conversations_get_all(), conv
))
561 plugin_return
= GPOINTER_TO_INT(purple_signal_emit_return_1(
562 purple_conversations_get_handle(),
563 (PURPLE_IS_IM_CONVERSATION(conv
) ? "writing-im-msg" : "writing-chat-msg"),
566 if (purple_message_is_empty(pmsg
))
572 if (account
!= NULL
) {
573 protocol
= purple_protocols_find(purple_account_get_protocol_id(account
));
575 if (PURPLE_IS_IM_CONVERSATION(conv
) ||
576 !(purple_protocol_get_options(protocol
) & OPT_PROTO_UNIQUE_CHATNAME
)) {
578 if (purple_message_get_flags(pmsg
) & PURPLE_MESSAGE_SEND
) {
581 b
= purple_blist_find_buddy(account
,
582 purple_account_get_username(account
));
584 if (purple_account_get_private_alias(account
) != NULL
)
585 alias
= purple_account_get_private_alias(account
);
586 else if (b
!= NULL
&& !purple_strequal(purple_buddy_get_name(b
),
587 purple_buddy_get_contact_alias(b
)))
589 alias
= purple_buddy_get_contact_alias(b
);
590 } else if (purple_connection_get_display_name(gc
) != NULL
)
591 alias
= purple_connection_get_display_name(gc
);
593 alias
= purple_account_get_username(account
);
595 purple_message_set_author_alias(pmsg
, alias
);
597 else if (purple_message_get_flags(pmsg
) & PURPLE_MESSAGE_RECV
)
599 /* TODO: PurpleDude - folks not on the buddy list */
600 b
= purple_blist_find_buddy(account
,
601 purple_message_get_author(pmsg
));
604 purple_message_set_author_alias(pmsg
,
605 purple_buddy_get_contact_alias(b
));
611 if (!(purple_message_get_flags(pmsg
) & PURPLE_MESSAGE_NO_LOG
) && purple_conversation_is_logging(conv
)) {
615 dt
= g_date_time_new_from_unix_local(purple_message_get_time(pmsg
));
617 while (log
!= NULL
) {
618 purple_log_write((PurpleLog
*)log
->data
,
619 purple_message_get_flags(pmsg
),
620 purple_message_get_author_alias(pmsg
),
622 purple_message_get_contents(pmsg
));
625 g_date_time_unref(dt
);
629 if (PURPLE_IS_CHAT_CONVERSATION(conv
) && ops
->write_chat
)
630 ops
->write_chat(PURPLE_CHAT_CONVERSATION(conv
), pmsg
);
631 else if (PURPLE_IS_IM_CONVERSATION(conv
) && ops
->write_im
)
632 ops
->write_im(PURPLE_IM_CONVERSATION(conv
), pmsg
);
633 else if (ops
->write_conv
)
634 ops
->write_conv(conv
, pmsg
);
638 priv
->message_history
= g_list_prepend(priv
->message_history
, pmsg
);
640 purple_signal_emit(purple_conversations_get_handle(),
641 (PURPLE_IS_IM_CONVERSATION(conv
) ? "wrote-im-msg" : "wrote-chat-msg"),
646 purple_conversation_write_message(PurpleConversation
*conv
, PurpleMessage
*msg
)
648 PurpleConversationClass
*klass
= NULL
;
650 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
652 klass
= PURPLE_CONVERSATION_GET_CLASS(conv
);
654 if (klass
&& klass
->write_message
)
655 klass
->write_message(conv
, msg
);
658 void purple_conversation_write_system_message(PurpleConversation
*conv
,
659 const gchar
*message
, PurpleMessageFlags flags
)
661 _purple_conversation_write_common(conv
,
662 purple_message_new_system(message
, flags
));
666 purple_conversation_send(PurpleConversation
*conv
, const char *message
)
668 purple_conversation_send_with_flags(conv
, message
, 0);
672 purple_conversation_send_with_flags(PurpleConversation
*conv
, const char *message
,
673 PurpleMessageFlags flags
)
675 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
676 g_return_if_fail(message
!= NULL
);
678 common_send(conv
, message
, flags
);
682 purple_conversation_has_focus(PurpleConversation
*conv
)
684 gboolean ret
= FALSE
;
685 PurpleConversationUiOps
*ops
;
687 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), FALSE
);
689 ops
= purple_conversation_get_ui_ops(conv
);
691 if (ops
!= NULL
&& ops
->has_focus
!= NULL
)
692 ret
= ops
->has_focus(conv
);
698 * TODO: Need to make sure calls to this function happen in the core
699 * instead of the UI. That way UIs have less work to do, and the
700 * core/UI split is cleaner. Also need to make sure this is called
701 * when chats are added/removed from the blist.
704 purple_conversation_update(PurpleConversation
*conv
, PurpleConversationUpdateType type
)
706 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
708 purple_signal_emit(purple_conversations_get_handle(),
709 "conversation-updated", conv
, type
);
712 gboolean
purple_conversation_present_error(const char *who
, PurpleAccount
*account
, const char *what
)
714 PurpleConversation
*conv
;
716 g_return_val_if_fail(who
!= NULL
, FALSE
);
717 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
718 g_return_val_if_fail(what
!= NULL
, FALSE
);
720 conv
= purple_conversations_find_with_account(who
, account
);
722 purple_conversation_write_system_message(conv
, what
, PURPLE_MESSAGE_ERROR
);
730 purple_conversation_send_confirm_cb(gpointer
*data
)
732 PurpleConversation
*conv
= data
[0];
733 char *message
= data
[1];
737 if (!PURPLE_IS_CONVERSATION(conv
)) {
738 /* Maybe it was closed before this callback was called. */
742 common_send(conv
, message
, 0);
746 purple_conversation_send_confirm(PurpleConversation
*conv
, const char *message
)
748 PurpleConversationPrivate
*priv
= NULL
;
752 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
753 g_return_if_fail(message
!= NULL
);
755 priv
= purple_conversation_get_instance_private(conv
);
756 if (priv
->ui_ops
!= NULL
&& priv
->ui_ops
->send_confirm
!= NULL
)
758 priv
->ui_ops
->send_confirm(conv
, message
);
762 text
= g_strdup_printf("You are about to send the following message:\n%s", message
);
763 data
= g_new0(gpointer
, 2);
765 data
[1] = (gpointer
)message
;
767 purple_request_action(conv
, NULL
, _("Send Message"), text
, 0,
768 purple_request_cpar_from_account(
769 purple_conversation_get_account(conv
)),
770 data
, 2, _("_Send Message"),
771 G_CALLBACK(purple_conversation_send_confirm_cb
), _("Cancel"), NULL
);
775 purple_conversation_get_extended_menu(PurpleConversation
*conv
)
779 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
781 purple_signal_emit(purple_conversations_get_handle(),
782 "conversation-extended-menu", conv
, &menu
);
786 void purple_conversation_clear_message_history(PurpleConversation
*conv
)
788 PurpleConversationPrivate
*priv
= NULL
;
791 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
793 priv
= purple_conversation_get_instance_private(conv
);
794 list
= priv
->message_history
;
795 g_list_free_full(list
, g_object_unref
);
796 priv
->message_history
= NULL
;
798 purple_signal_emit(purple_conversations_get_handle(),
799 "cleared-message-history", conv
);
802 GList
*purple_conversation_get_message_history(PurpleConversation
*conv
)
804 PurpleConversationPrivate
*priv
= NULL
;
806 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
808 priv
= purple_conversation_get_instance_private(conv
);
809 return priv
->message_history
;
812 void purple_conversation_set_ui_data(PurpleConversation
*conv
, gpointer ui_data
)
814 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
816 conv
->ui_data
= ui_data
;
819 gpointer
purple_conversation_get_ui_data(const PurpleConversation
*conv
)
821 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
823 return conv
->ui_data
;
827 purple_conversation_do_command(PurpleConversation
*conv
, const gchar
*cmdline
,
828 const gchar
*markup
, gchar
**error
)
830 char *mark
= (markup
&& *markup
) ? NULL
: g_markup_escape_text(cmdline
, -1), *err
= NULL
;
831 PurpleCmdStatus status
= purple_cmd_do_command(conv
, cmdline
, mark
? mark
: markup
, error
? error
: &err
);
834 return (status
== PURPLE_CMD_STATUS_OK
);
838 purple_conversation_get_max_message_size(PurpleConversation
*conv
)
840 PurpleProtocol
*protocol
;
842 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), 0);
844 protocol
= purple_connection_get_protocol(
845 purple_conversation_get_connection(conv
));
847 g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol
), 0);
849 return purple_protocol_client_iface_get_max_message_size(protocol
, conv
);
853 purple_conversation_add_smiley(PurpleConversation
*conv
, PurpleSmiley
*smiley
) {
854 PurpleConversationPrivate
*priv
= NULL
;
856 g_return_if_fail(PURPLE_IS_CONVERSATION(conv
));
857 g_return_if_fail(smiley
);
859 priv
= purple_conversation_get_instance_private(conv
);
861 if (priv
->remote_smileys
== NULL
) {
862 priv
->remote_smileys
= purple_smiley_list_new();
863 g_object_set(priv
->remote_smileys
,
864 "drop-failed-remotes", TRUE
, NULL
);
867 if(purple_smiley_list_get_by_shortcut(
868 priv
->remote_smileys
,
869 purple_smiley_get_shortcut(smiley
)))
871 /* smiley was already added */
875 if (!purple_smiley_list_add(priv
->remote_smileys
, smiley
)) {
876 purple_debug_error("conversation", "failed adding remote "
877 "smiley to the list");
882 purple_conversation_get_smiley(PurpleConversation
*conv
, const gchar
*shortcut
) {
883 PurpleConversationPrivate
*priv
= NULL
;
885 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
886 g_return_val_if_fail(shortcut
, NULL
);
888 priv
= purple_conversation_get_instance_private(conv
);
890 if (priv
->remote_smileys
== NULL
)
893 return purple_smiley_list_get_by_shortcut(priv
->remote_smileys
, shortcut
);
897 purple_conversation_get_remote_smileys(PurpleConversation
*conv
)
899 PurpleConversationPrivate
*priv
= NULL
;
901 g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv
), NULL
);
903 priv
= purple_conversation_get_instance_private(conv
);
904 return priv
->remote_smileys
;
908 /**************************************************************************
910 **************************************************************************/
912 /* Set method for GObject properties */
914 purple_conversation_set_property(GObject
*obj
, guint param_id
, const GValue
*value
,
917 PurpleConversation
*conv
= PURPLE_CONVERSATION(obj
);
918 PurpleConversationPrivate
*priv
=
919 purple_conversation_get_instance_private(conv
);
923 priv
->account
= g_value_get_object(value
);
927 priv
->name
= g_value_dup_string(value
);
931 priv
->title
= g_value_dup_string(value
);
934 purple_conversation_set_logging(conv
, g_value_get_boolean(value
));
937 purple_conversation_set_features(conv
, g_value_get_flags(value
));
940 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
945 /* Get method for GObject properties */
947 purple_conversation_get_property(GObject
*obj
, guint param_id
, GValue
*value
,
950 PurpleConversation
*conv
= PURPLE_CONVERSATION(obj
);
954 g_value_set_object(value
, purple_conversation_get_account(conv
));
957 g_value_set_string(value
, purple_conversation_get_name(conv
));
960 g_value_set_string(value
, purple_conversation_get_title(conv
));
963 g_value_set_boolean(value
, purple_conversation_is_logging(conv
));
966 g_value_set_flags(value
, purple_conversation_get_features(conv
));
969 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
975 purple_conversation_init(PurpleConversation
*conv
)
979 /* Called when done constructing */
981 purple_conversation_constructed(GObject
*object
)
983 PurpleConversation
*conv
= PURPLE_CONVERSATION(object
);
984 PurpleAccount
*account
;
985 PurpleConnection
*gc
;
986 PurpleConversationUiOps
*ops
;
988 G_OBJECT_CLASS(purple_conversation_parent_class
)->constructed(object
);
990 g_object_get(object
, "account", &account
, NULL
);
991 gc
= purple_account_get_connection(account
);
993 /* copy features from the connection. */
994 purple_conversation_set_features(conv
, purple_connection_get_flags(gc
));
996 /* add the conversation to the appropriate lists */
997 purple_conversations_add(conv
);
999 /* Auto-set the title. */
1000 purple_conversation_autoset_title(conv
);
1002 /* Don't move this.. it needs to be one of the last things done otherwise
1003 * it causes mysterious crashes on my system.
1006 ops
= purple_conversations_get_ui_ops();
1007 purple_conversation_set_ui_ops(conv
, ops
);
1008 if (ops
!= NULL
&& ops
->create_conversation
!= NULL
)
1009 ops
->create_conversation(conv
);
1011 purple_signal_emit(purple_conversations_get_handle(),
1012 "conversation-created", conv
);
1014 g_object_unref(account
);
1018 purple_conversation_dispose(GObject
*object
)
1020 g_object_set_data(object
, "is-finalizing", GINT_TO_POINTER(TRUE
));
1023 /* GObject finalize function */
1025 purple_conversation_finalize(GObject
*object
)
1027 PurpleConversation
*conv
= PURPLE_CONVERSATION(object
);
1028 PurpleConversationPrivate
*priv
=
1029 purple_conversation_get_instance_private(conv
);
1030 PurpleConversationUiOps
*ops
= purple_conversation_get_ui_ops(conv
);
1032 purple_request_close_with_handle(conv
);
1034 purple_e2ee_state_unref(priv
->e2ee_state
);
1035 priv
->e2ee_state
= NULL
;
1037 /* remove from conversations and im/chats lists prior to emit */
1038 purple_conversations_remove(conv
);
1040 purple_signal_emit(purple_conversations_get_handle(),
1041 "deleting-conversation", conv
);
1043 purple_conversation_close_logs(conv
);
1044 purple_conversation_clear_message_history(conv
);
1046 if (ops
!= NULL
&& ops
->destroy_conversation
!= NULL
)
1047 ops
->destroy_conversation(conv
);
1050 g_free(priv
->title
);
1055 G_OBJECT_CLASS(purple_conversation_parent_class
)->finalize(object
);
1058 /* Class initializer function */
1060 purple_conversation_class_init(PurpleConversationClass
*klass
)
1062 GObjectClass
*obj_class
= G_OBJECT_CLASS(klass
);
1064 obj_class
->dispose
= purple_conversation_dispose
;
1065 obj_class
->finalize
= purple_conversation_finalize
;
1066 obj_class
->constructed
= purple_conversation_constructed
;
1068 /* Setup properties */
1069 obj_class
->get_property
= purple_conversation_get_property
;
1070 obj_class
->set_property
= purple_conversation_set_property
;
1072 properties
[PROP_ACCOUNT
] = g_param_spec_object("account", "Account",
1073 "The account for the conversation.", PURPLE_TYPE_ACCOUNT
,
1074 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
| G_PARAM_STATIC_STRINGS
);
1076 properties
[PROP_NAME
] = g_param_spec_string("name", "Name",
1077 "The name of the conversation.", NULL
,
1078 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
| G_PARAM_STATIC_STRINGS
);
1080 properties
[PROP_TITLE
] = g_param_spec_string("title", "Title",
1081 "The title of the conversation.", NULL
,
1082 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
| G_PARAM_STATIC_STRINGS
);
1084 properties
[PROP_LOGGING
] = g_param_spec_boolean("logging", "Logging status",
1085 "Whether logging is enabled or not.", FALSE
,
1086 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1088 properties
[PROP_FEATURES
] = g_param_spec_flags("features",
1089 "Connection features",
1090 "The connection features of the conversation.",
1091 PURPLE_TYPE_CONNECTION_FLAGS
, 0,
1092 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1094 g_object_class_install_properties(obj_class
, PROP_LAST
, properties
);