pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Remove the Gtk Ticker plugin as it doesn't scale to today's IM networks
2020-08-22, Gary Kramlich
fefaa6596e74
Remove the Gtk Ticker plugin as it doesn't scale to today's IM networks
Remove the ticker plugin as it doesn't scale to todays typical IM usage.
Testing Done:
Compile and install.
Reviewed at https://reviews.imfreedom.org/r/81/
/*
* purple
*
* Purple is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include
<glib/gi18n-lib.h>
#include
"internal.h"
#include
"conversationtypes.h"
#include
"debug.h"
#include
"enums.h"
#include
"purpleprivate.h"
/**************************************************************************/
/* PurpleChatConversation */
/**************************************************************************/
/*
* Data specific to Chats.
*/
typedef
struct
{
GList
*
ignored
;
/* Ignored users. */
char
*
who
;
/* The person who set the topic. */
char
*
topic
;
/* The topic. */
int
id
;
/* The chat ID. */
char
*
nick
;
/* Your nick in this chat. */
gboolean
left
;
/* We left the chat and kept the window open */
GHashTable
*
users
;
/* Hash table of the users in the room. */
}
PurpleChatConversationPrivate
;
/* Chat Property enums */
enum
{
CHAT_PROP_0
,
CHAT_PROP_TOPIC_WHO
,
CHAT_PROP_TOPIC
,
CHAT_PROP_ID
,
CHAT_PROP_NICK
,
CHAT_PROP_LEFT
,
CHAT_PROP_LAST
};
static
GParamSpec
*
chat_properties
[
CHAT_PROP_LAST
];
G_DEFINE_TYPE_WITH_PRIVATE
(
PurpleChatConversation
,
purple_chat_conversation
,
PURPLE_TYPE_CONVERSATION
);
/**************************************************************************/
/* PurpleChatUser */
/**************************************************************************/
/**
* PurpleChatUser:
*
* Structure representing a chat user instance.
*/
struct
_PurpleChatUser
{
GObject
gparent
;
gpointer
ui_data
;
};
/*
* Data for "Chat Buddies"
*/
typedef
struct
{
PurpleChatConversation
*
chat
;
/* The chat */
char
*
name
;
/* The chat participant's name in the
chat. */
char
*
alias
;
/* The chat participant's alias, if known;
NULL otherwise. */
char
*
alias_key
;
/* A string by which this user will be
sorted, or @c NULL if the user should be
sorted by its @name.
(This is currently always NULL. */
gboolean
buddy
;
/* TRUE if this chat participant is on
the buddy list; FALSE otherwise. */
PurpleChatUserFlags
flags
;
/* A bitwise OR of flags for this
participant, such as whether they
are a channel operator. */
}
PurpleChatUserPrivate
;
/* Chat User Property enums */
enum
{
CU_PROP_0
,
CU_PROP_CHAT
,
CU_PROP_NAME
,
CU_PROP_ALIAS
,
CU_PROP_FLAGS
,
CU_PROP_LAST
};
static
GParamSpec
*
cu_properties
[
CU_PROP_LAST
];
G_DEFINE_TYPE_WITH_PRIVATE
(
PurpleChatUser
,
purple_chat_user
,
G_TYPE_OBJECT
);
static
int
purple_chat_user_compare
(
PurpleChatUser
*
a
,
PurpleChatUser
*
b
);
/**************************************************************************
* Chat Conversation API
**************************************************************************/
static
guint
_purple_conversation_user_hash
(
gconstpointer
data
)
{
const
gchar
*
name
=
data
;
gchar
*
collated
;
guint
hash
;
collated
=
g_utf8_collate_key
(
name
,
-1
);
hash
=
g_str_hash
(
collated
);
g_free
(
collated
);
return
hash
;
}
static
gboolean
_purple_conversation_user_equal
(
gconstpointer
a
,
gconstpointer
b
)
{
return
!
g_utf8_collate
(
a
,
b
);
}
GList
*
purple_chat_conversation_get_users
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
return
g_hash_table_get_values
(
priv
->
users
);
}
guint
purple_chat_conversation_get_users_count
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
0
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
return
g_hash_table_size
(
priv
->
users
);
}
void
purple_chat_conversation_ignore
(
PurpleChatConversation
*
chat
,
const
char
*
name
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
g_return_if_fail
(
name
!=
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
/* Make sure the user isn't already ignored. */
if
(
purple_chat_conversation_is_ignored_user
(
chat
,
name
))
return
;
purple_chat_conversation_set_ignored
(
chat
,
g_list_append
(
priv
->
ignored
,
g_strdup
(
name
)));
}
void
purple_chat_conversation_unignore
(
PurpleChatConversation
*
chat
,
const
char
*
name
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
GList
*
item
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
g_return_if_fail
(
name
!=
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
/* Make sure the user is actually ignored. */
if
(
!
purple_chat_conversation_is_ignored_user
(
chat
,
name
))
return
;
item
=
g_list_find
(
purple_chat_conversation_get_ignored
(
chat
),
purple_chat_conversation_get_ignored_user
(
chat
,
name
));
g_free
(
item
->
data
);
purple_chat_conversation_set_ignored
(
chat
,
g_list_delete_link
(
priv
->
ignored
,
item
));
}
GList
*
purple_chat_conversation_set_ignored
(
PurpleChatConversation
*
chat
,
GList
*
ignored
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
priv
->
ignored
=
ignored
;
return
ignored
;
}
GList
*
purple_chat_conversation_get_ignored
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
return
priv
->
ignored
;
}
const
char
*
purple_chat_conversation_get_ignored_user
(
PurpleChatConversation
*
chat
,
const
char
*
user
)
{
GList
*
ignored
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
NULL
);
g_return_val_if_fail
(
user
!=
NULL
,
NULL
);
for
(
ignored
=
purple_chat_conversation_get_ignored
(
chat
);
ignored
!=
NULL
;
ignored
=
ignored
->
next
)
{
const
char
*
ign
=
(
const
char
*
)
ignored
->
data
;
if
(
!
purple_utf8_strcasecmp
(
user
,
ign
)
||
((
*
ign
==
'+'
||
*
ign
==
'%'
)
&&
!
purple_utf8_strcasecmp
(
user
,
ign
+
1
)))
return
ign
;
if
(
*
ign
==
'@'
)
{
ign
++
;
if
((
*
ign
==
'+'
&&
!
purple_utf8_strcasecmp
(
user
,
ign
+
1
))
||
(
*
ign
!=
'+'
&&
!
purple_utf8_strcasecmp
(
user
,
ign
)))
return
ign
;
}
}
return
NULL
;
}
gboolean
purple_chat_conversation_is_ignored_user
(
PurpleChatConversation
*
chat
,
const
char
*
user
)
{
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
FALSE
);
g_return_val_if_fail
(
user
!=
NULL
,
FALSE
);
return
(
purple_chat_conversation_get_ignored_user
(
chat
,
user
)
!=
NULL
);
}
void
purple_chat_conversation_set_topic
(
PurpleChatConversation
*
chat
,
const
char
*
who
,
const
char
*
topic
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
GObject
*
obj
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
g_free
(
priv
->
who
);
g_free
(
priv
->
topic
);
priv
->
who
=
g_strdup
(
who
);
priv
->
topic
=
g_strdup
(
topic
);
obj
=
G_OBJECT
(
chat
);
g_object_freeze_notify
(
obj
);
g_object_notify_by_pspec
(
obj
,
chat_properties
[
CHAT_PROP_TOPIC_WHO
]);
g_object_notify_by_pspec
(
obj
,
chat_properties
[
CHAT_PROP_TOPIC
]);
g_object_thaw_notify
(
obj
);
purple_conversation_update
(
PURPLE_CONVERSATION
(
chat
),
PURPLE_CONVERSATION_UPDATE_TOPIC
);
purple_signal_emit
(
purple_conversations_get_handle
(),
"chat-topic-changed"
,
chat
,
priv
->
who
,
priv
->
topic
);
}
const
char
*
purple_chat_conversation_get_topic
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
return
priv
->
topic
;
}
const
char
*
purple_chat_conversation_get_topic_who
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
return
priv
->
who
;
}
void
purple_chat_conversation_set_id
(
PurpleChatConversation
*
chat
,
int
id
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
priv
->
id
=
id
;
g_object_notify_by_pspec
(
G_OBJECT
(
chat
),
chat_properties
[
CHAT_PROP_ID
]);
}
int
purple_chat_conversation_get_id
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
-1
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
return
priv
->
id
;
}
static
void
chat_conversation_write_message
(
PurpleConversation
*
conv
,
PurpleMessage
*
msg
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
PurpleMessageFlags
flags
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
conv
));
g_return_if_fail
(
msg
!=
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
PURPLE_CHAT_CONVERSATION
(
conv
));
/* Don't display this if the person who wrote it is ignored. */
if
(
purple_message_get_author
(
msg
)
&&
purple_chat_conversation_is_ignored_user
(
PURPLE_CHAT_CONVERSATION
(
conv
),
purple_message_get_author
(
msg
)))
{
return
;
}
flags
=
purple_message_get_flags
(
msg
);
if
(
flags
&
PURPLE_MESSAGE_RECV
)
{
if
(
purple_utf8_has_word
(
purple_message_get_contents
(
msg
),
priv
->
nick
))
{
flags
|=
PURPLE_MESSAGE_NICK
;
purple_message_set_flags
(
msg
,
flags
);
}
}
_purple_conversation_write_common
(
conv
,
msg
);
}
void
purple_chat_conversation_add_user
(
PurpleChatConversation
*
chat
,
const
char
*
user
,
const
char
*
extra_msg
,
PurpleChatUserFlags
flags
,
gboolean
new_arrival
)
{
GList
*
users
=
g_list_append
(
NULL
,
(
char
*
)
user
);
GList
*
extra_msgs
=
g_list_append
(
NULL
,
(
char
*
)
extra_msg
);
GList
*
flags2
=
g_list_append
(
NULL
,
GINT_TO_POINTER
(
flags
));
purple_chat_conversation_add_users
(
chat
,
users
,
extra_msgs
,
flags2
,
new_arrival
);
g_list_free
(
users
);
g_list_free
(
extra_msgs
);
g_list_free
(
flags2
);
}
void
purple_chat_conversation_add_users
(
PurpleChatConversation
*
chat
,
GList
*
users
,
GList
*
extra_msgs
,
GList
*
flags
,
gboolean
new_arrivals
)
{
PurpleConversation
*
conv
;
PurpleConversationUiOps
*
ops
;
PurpleChatUser
*
chatuser
;
PurpleChatConversationPrivate
*
priv
;
PurpleAccount
*
account
;
PurpleConnection
*
gc
;
PurpleProtocol
*
protocol
;
GList
*
ul
,
*
fl
;
GList
*
cbuddies
=
NULL
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
g_return_if_fail
(
users
!=
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
conv
=
PURPLE_CONVERSATION
(
chat
);
ops
=
purple_conversation_get_ui_ops
(
conv
);
account
=
purple_conversation_get_account
(
conv
);
gc
=
purple_conversation_get_connection
(
conv
);
g_return_if_fail
(
PURPLE_IS_CONNECTION
(
gc
));
protocol
=
purple_connection_get_protocol
(
gc
);
g_return_if_fail
(
PURPLE_IS_PROTOCOL
(
protocol
));
ul
=
users
;
fl
=
flags
;
while
((
ul
!=
NULL
)
&&
(
fl
!=
NULL
))
{
const
char
*
user
=
(
const
char
*
)
ul
->
data
;
const
char
*
alias
=
user
;
gboolean
quiet
;
PurpleChatUserFlags
flag
=
GPOINTER_TO_INT
(
fl
->
data
);
const
char
*
extra_msg
=
(
extra_msgs
?
extra_msgs
->
data
:
NULL
);
if
(
!
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_UNIQUE_CHATNAME
))
{
if
(
purple_strequal
(
priv
->
nick
,
purple_normalize
(
account
,
user
)))
{
const
char
*
alias2
=
purple_account_get_private_alias
(
account
);
if
(
alias2
!=
NULL
)
alias
=
alias2
;
else
{
const
char
*
display_name
=
purple_connection_get_display_name
(
gc
);
if
(
display_name
!=
NULL
)
alias
=
display_name
;
}
}
else
{
PurpleBuddy
*
buddy
;
if
((
buddy
=
purple_blist_find_buddy
(
purple_connection_get_account
(
gc
),
user
))
!=
NULL
)
alias
=
purple_buddy_get_contact_alias
(
buddy
);
}
}
quiet
=
GPOINTER_TO_INT
(
purple_signal_emit_return_1
(
purple_conversations_get_handle
(),
"chat-user-joining"
,
chat
,
user
,
flag
))
||
purple_chat_conversation_is_ignored_user
(
chat
,
user
);
chatuser
=
purple_chat_user_new
(
chat
,
user
,
alias
,
flag
);
g_hash_table_replace
(
priv
->
users
,
g_strdup
(
purple_chat_user_get_name
(
chatuser
)),
chatuser
);
cbuddies
=
g_list_prepend
(
cbuddies
,
chatuser
);
if
(
!
quiet
&&
new_arrivals
)
{
char
*
alias_esc
=
g_markup_escape_text
(
alias
,
-1
);
char
*
tmp
;
if
(
extra_msg
==
NULL
)
tmp
=
g_strdup_printf
(
_
(
"%s entered the room."
),
alias_esc
);
else
{
char
*
extra_msg_esc
=
g_markup_escape_text
(
extra_msg
,
-1
);
tmp
=
g_strdup_printf
(
_
(
"%s [<I>%s</I>] entered the room."
),
alias_esc
,
extra_msg_esc
);
g_free
(
extra_msg_esc
);
}
g_free
(
alias_esc
);
purple_conversation_write_system_message
(
conv
,
tmp
,
PURPLE_MESSAGE_NO_LINKIFY
);
g_free
(
tmp
);
}
purple_signal_emit
(
purple_conversations_get_handle
(),
"chat-user-joined"
,
chat
,
user
,
flag
,
new_arrivals
);
ul
=
ul
->
next
;
fl
=
fl
->
next
;
if
(
extra_msgs
!=
NULL
)
extra_msgs
=
extra_msgs
->
next
;
}
cbuddies
=
g_list_sort
(
cbuddies
,
(
GCompareFunc
)
purple_chat_user_compare
);
if
(
ops
!=
NULL
&&
ops
->
chat_add_users
!=
NULL
)
ops
->
chat_add_users
(
chat
,
cbuddies
,
new_arrivals
);
g_list_free
(
cbuddies
);
}
void
purple_chat_conversation_rename_user
(
PurpleChatConversation
*
chat
,
const
char
*
old_user
,
const
char
*
new_user
)
{
PurpleConversation
*
conv
;
PurpleConversationUiOps
*
ops
;
PurpleAccount
*
account
;
PurpleConnection
*
gc
;
PurpleProtocol
*
protocol
;
PurpleChatUser
*
cb
;
PurpleChatUserFlags
flags
;
PurpleChatConversationPrivate
*
priv
;
const
char
*
new_alias
=
new_user
;
char
tmp
[
BUF_LONG
];
gboolean
is_me
=
FALSE
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
g_return_if_fail
(
old_user
!=
NULL
);
g_return_if_fail
(
new_user
!=
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
conv
=
PURPLE_CONVERSATION
(
chat
);
ops
=
purple_conversation_get_ui_ops
(
conv
);
account
=
purple_conversation_get_account
(
conv
);
gc
=
purple_conversation_get_connection
(
conv
);
g_return_if_fail
(
PURPLE_IS_CONNECTION
(
gc
));
protocol
=
purple_connection_get_protocol
(
gc
);
g_return_if_fail
(
PURPLE_IS_PROTOCOL
(
protocol
));
if
(
purple_strequal
(
priv
->
nick
,
purple_normalize
(
account
,
old_user
)))
{
const
char
*
alias
;
/* Note this for later. */
is_me
=
TRUE
;
if
(
!
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_UNIQUE_CHATNAME
))
{
alias
=
purple_account_get_private_alias
(
account
);
if
(
alias
!=
NULL
)
new_alias
=
alias
;
else
{
const
char
*
display_name
=
purple_connection_get_display_name
(
gc
);
if
(
display_name
!=
NULL
)
new_alias
=
display_name
;
}
}
}
else
if
(
!
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_UNIQUE_CHATNAME
))
{
PurpleBuddy
*
buddy
;
if
((
buddy
=
purple_blist_find_buddy
(
purple_connection_get_account
(
gc
),
new_user
))
!=
NULL
)
new_alias
=
purple_buddy_get_contact_alias
(
buddy
);
}
flags
=
purple_chat_user_get_flags
(
purple_chat_conversation_find_user
(
chat
,
old_user
));
cb
=
purple_chat_user_new
(
chat
,
new_user
,
new_alias
,
flags
);
g_hash_table_replace
(
priv
->
users
,
g_strdup
(
purple_chat_user_get_name
(
cb
)),
cb
);
if
(
ops
!=
NULL
&&
ops
->
chat_rename_user
!=
NULL
)
ops
->
chat_rename_user
(
chat
,
old_user
,
new_user
,
new_alias
);
cb
=
purple_chat_conversation_find_user
(
chat
,
old_user
);
if
(
cb
)
g_hash_table_remove
(
priv
->
users
,
purple_chat_user_get_name
(
cb
));
if
(
purple_chat_conversation_is_ignored_user
(
chat
,
old_user
))
{
purple_chat_conversation_unignore
(
chat
,
old_user
);
purple_chat_conversation_ignore
(
chat
,
new_user
);
}
else
if
(
purple_chat_conversation_is_ignored_user
(
chat
,
new_user
))
purple_chat_conversation_unignore
(
chat
,
new_user
);
if
(
is_me
)
purple_chat_conversation_set_nick
(
chat
,
new_user
);
if
(
purple_prefs_get_bool
(
"/purple/conversations/chat/show_nick_change"
)
&&
!
purple_chat_conversation_is_ignored_user
(
chat
,
new_user
))
{
if
(
is_me
)
{
char
*
escaped
=
g_markup_escape_text
(
new_user
,
-1
);
g_snprintf
(
tmp
,
sizeof
(
tmp
),
_
(
"You are now known as %s"
),
escaped
);
g_free
(
escaped
);
}
else
{
const
char
*
old_alias
=
old_user
;
const
char
*
new_alias
=
new_user
;
char
*
escaped
;
char
*
escaped2
;
if
(
!
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_UNIQUE_CHATNAME
))
{
PurpleBuddy
*
buddy
;
if
((
buddy
=
purple_blist_find_buddy
(
purple_connection_get_account
(
gc
),
old_user
))
!=
NULL
)
old_alias
=
purple_buddy_get_contact_alias
(
buddy
);
if
((
buddy
=
purple_blist_find_buddy
(
purple_connection_get_account
(
gc
),
new_user
))
!=
NULL
)
new_alias
=
purple_buddy_get_contact_alias
(
buddy
);
}
escaped
=
g_markup_escape_text
(
old_alias
,
-1
);
escaped2
=
g_markup_escape_text
(
new_alias
,
-1
);
g_snprintf
(
tmp
,
sizeof
(
tmp
),
_
(
"%s is now known as %s"
),
escaped
,
escaped2
);
g_free
(
escaped
);
g_free
(
escaped2
);
}
purple_conversation_write_system_message
(
conv
,
tmp
,
PURPLE_MESSAGE_NO_LINKIFY
);
}
}
void
purple_chat_conversation_remove_user
(
PurpleChatConversation
*
chat
,
const
char
*
user
,
const
char
*
reason
)
{
GList
*
users
=
g_list_append
(
NULL
,
(
char
*
)
user
);
purple_chat_conversation_remove_users
(
chat
,
users
,
reason
);
g_list_free
(
users
);
}
void
purple_chat_conversation_remove_users
(
PurpleChatConversation
*
chat
,
GList
*
users
,
const
char
*
reason
)
{
PurpleConversation
*
conv
;
PurpleConnection
*
gc
;
PurpleProtocol
*
protocol
;
PurpleConversationUiOps
*
ops
;
PurpleChatUser
*
cb
;
PurpleChatConversationPrivate
*
priv
;
GList
*
l
;
gboolean
quiet
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
g_return_if_fail
(
users
!=
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
conv
=
PURPLE_CONVERSATION
(
chat
);
gc
=
purple_conversation_get_connection
(
conv
);
g_return_if_fail
(
PURPLE_IS_CONNECTION
(
gc
));
protocol
=
purple_connection_get_protocol
(
gc
);
g_return_if_fail
(
PURPLE_IS_PROTOCOL
(
protocol
));
ops
=
purple_conversation_get_ui_ops
(
conv
);
for
(
l
=
users
;
l
!=
NULL
;
l
=
l
->
next
)
{
const
char
*
user
=
(
const
char
*
)
l
->
data
;
quiet
=
GPOINTER_TO_INT
(
purple_signal_emit_return_1
(
purple_conversations_get_handle
(),
"chat-user-leaving"
,
chat
,
user
,
reason
))
|
purple_chat_conversation_is_ignored_user
(
chat
,
user
);
cb
=
purple_chat_conversation_find_user
(
chat
,
user
);
if
(
cb
)
{
g_hash_table_remove
(
priv
->
users
,
purple_chat_user_get_name
(
cb
));
}
/* NOTE: Don't remove them from ignored in case they re-enter. */
if
(
!
quiet
)
{
const
char
*
alias
=
user
;
char
*
alias_esc
;
char
*
tmp
;
if
(
!
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_UNIQUE_CHATNAME
))
{
PurpleBuddy
*
buddy
;
if
((
buddy
=
purple_blist_find_buddy
(
purple_connection_get_account
(
gc
),
user
))
!=
NULL
)
alias
=
purple_buddy_get_contact_alias
(
buddy
);
}
alias_esc
=
g_markup_escape_text
(
alias
,
-1
);
if
(
reason
==
NULL
||
!*
reason
)
tmp
=
g_strdup_printf
(
_
(
"%s left the room."
),
alias_esc
);
else
{
char
*
reason_esc
=
g_markup_escape_text
(
reason
,
-1
);
tmp
=
g_strdup_printf
(
_
(
"%s left the room (%s)."
),
alias_esc
,
reason_esc
);
g_free
(
reason_esc
);
}
g_free
(
alias_esc
);
purple_conversation_write_system_message
(
conv
,
tmp
,
PURPLE_MESSAGE_NO_LINKIFY
);
g_free
(
tmp
);
}
purple_signal_emit
(
purple_conversations_get_handle
(),
"chat-user-left"
,
conv
,
user
,
reason
);
}
if
(
ops
!=
NULL
&&
ops
->
chat_remove_users
!=
NULL
)
ops
->
chat_remove_users
(
chat
,
users
);
}
void
purple_chat_conversation_clear_users
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
PurpleConversationUiOps
*
ops
;
GHashTableIter
it
;
gchar
*
name
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
ops
=
purple_conversation_get_ui_ops
(
PURPLE_CONVERSATION
(
chat
));
if
(
ops
!=
NULL
&&
ops
->
chat_remove_users
!=
NULL
)
{
GList
*
names
=
NULL
;
g_hash_table_iter_init
(
&
it
,
priv
->
users
);
while
(
g_hash_table_iter_next
(
&
it
,
(
gpointer
*
)
&
name
,
NULL
))
names
=
g_list_prepend
(
names
,
name
);
ops
->
chat_remove_users
(
chat
,
names
);
g_list_free
(
names
);
}
g_hash_table_iter_init
(
&
it
,
priv
->
users
);
while
(
g_hash_table_iter_next
(
&
it
,
(
gpointer
*
)
&
name
,
NULL
))
{
purple_signal_emit
(
purple_conversations_get_handle
(),
"chat-user-leaving"
,
chat
,
name
,
NULL
);
purple_signal_emit
(
purple_conversations_get_handle
(),
"chat-user-left"
,
chat
,
name
,
NULL
);
}
g_hash_table_remove_all
(
priv
->
users
);
}
void
purple_chat_conversation_set_nick
(
PurpleChatConversation
*
chat
,
const
char
*
nick
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
g_free
(
priv
->
nick
);
priv
->
nick
=
g_strdup
(
purple_normalize
(
purple_conversation_get_account
(
PURPLE_CONVERSATION
(
chat
)),
nick
));
g_object_notify_by_pspec
(
G_OBJECT
(
chat
),
chat_properties
[
CHAT_PROP_NICK
]);
}
const
char
*
purple_chat_conversation_get_nick
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
return
priv
->
nick
;
}
static
void
invite_user_to_chat
(
gpointer
data
,
PurpleRequestFields
*
fields
)
{
PurpleConversation
*
conv
;
PurpleChatConversationPrivate
*
priv
;
const
char
*
user
,
*
message
;
conv
=
data
;
priv
=
purple_chat_conversation_get_instance_private
(
PURPLE_CHAT_CONVERSATION
(
conv
));
user
=
purple_request_fields_get_string
(
fields
,
"screenname"
);
message
=
purple_request_fields_get_string
(
fields
,
"message"
);
purple_serv_chat_invite
(
purple_conversation_get_connection
(
conv
),
priv
->
id
,
message
,
user
);
}
void
purple_chat_conversation_invite_user
(
PurpleChatConversation
*
chat
,
const
char
*
user
,
const
char
*
message
,
gboolean
confirm
)
{
PurpleAccount
*
account
;
PurpleRequestFields
*
fields
;
PurpleRequestFieldGroup
*
group
;
PurpleRequestField
*
field
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
if
(
!
user
||
!*
user
||
!
message
||
!*
message
)
confirm
=
TRUE
;
account
=
purple_conversation_get_account
(
PURPLE_CONVERSATION
(
chat
));
if
(
!
confirm
)
{
purple_serv_chat_invite
(
purple_account_get_connection
(
account
),
purple_chat_conversation_get_id
(
chat
),
message
,
user
);
return
;
}
fields
=
purple_request_fields_new
();
group
=
purple_request_field_group_new
(
_
(
"Invite to chat"
));
purple_request_fields_add_group
(
fields
,
group
);
field
=
purple_request_field_string_new
(
"screenname"
,
_
(
"Buddy"
),
user
,
FALSE
);
purple_request_field_group_add_field
(
group
,
field
);
purple_request_field_set_required
(
field
,
TRUE
);
purple_request_field_set_type_hint
(
field
,
"screenname"
);
field
=
purple_request_field_string_new
(
"message"
,
_
(
"Message"
),
message
,
FALSE
);
purple_request_field_group_add_field
(
group
,
field
);
purple_request_fields
(
chat
,
_
(
"Invite to chat"
),
NULL
,
_
(
"Please enter the name of the user you wish to invite, "
"along with an optional invite message."
),
fields
,
_
(
"Invite"
),
G_CALLBACK
(
invite_user_to_chat
),
_
(
"Cancel"
),
NULL
,
purple_request_cpar_from_conversation
(
PURPLE_CONVERSATION
(
chat
)),
chat
);
}
gboolean
purple_chat_conversation_has_user
(
PurpleChatConversation
*
chat
,
const
char
*
user
)
{
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
FALSE
);
g_return_val_if_fail
(
user
!=
NULL
,
FALSE
);
return
(
purple_chat_conversation_find_user
(
chat
,
user
)
!=
NULL
);
}
void
purple_chat_conversation_leave
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
));
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
priv
->
left
=
TRUE
;
if
(
!
g_object_get_data
(
G_OBJECT
(
chat
),
"is-finalizing"
))
g_object_notify_by_pspec
(
G_OBJECT
(
chat
),
chat_properties
[
CHAT_PROP_LEFT
]);
purple_conversation_update
(
PURPLE_CONVERSATION
(
chat
),
PURPLE_CONVERSATION_UPDATE_CHATLEFT
);
}
gboolean
purple_chat_conversation_has_left
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
TRUE
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
return
priv
->
left
;
}
static
void
chat_conversation_cleanup_for_rejoin
(
PurpleChatConversation
*
chat
)
{
const
char
*
disp
;
PurpleAccount
*
account
;
PurpleConnection
*
gc
;
PurpleConversation
*
conv
=
PURPLE_CONVERSATION
(
chat
);
PurpleChatConversationPrivate
*
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
account
=
purple_conversation_get_account
(
conv
);
purple_conversation_close_logs
(
conv
);
purple_conversation_set_logging
(
conv
,
TRUE
);
gc
=
purple_account_get_connection
(
account
);
if
((
disp
=
purple_connection_get_display_name
(
gc
))
!=
NULL
)
purple_chat_conversation_set_nick
(
chat
,
disp
);
else
{
purple_chat_conversation_set_nick
(
chat
,
purple_account_get_username
(
account
));
}
purple_chat_conversation_clear_users
(
chat
);
purple_chat_conversation_set_topic
(
chat
,
NULL
,
NULL
);
priv
->
left
=
FALSE
;
g_object_notify_by_pspec
(
G_OBJECT
(
chat
),
chat_properties
[
CHAT_PROP_LEFT
]);
purple_conversation_update
(
conv
,
PURPLE_CONVERSATION_UPDATE_CHATLEFT
);
}
PurpleChatUser
*
purple_chat_conversation_find_user
(
PurpleChatConversation
*
chat
,
const
char
*
name
)
{
PurpleChatConversationPrivate
*
priv
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
NULL
);
g_return_val_if_fail
(
name
!=
NULL
,
NULL
);
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
return
g_hash_table_lookup
(
priv
->
users
,
name
);
}
/**************************************************************************
* GObject code for chats
**************************************************************************/
/* Set method for GObject properties */
static
void
purple_chat_conversation_set_property
(
GObject
*
obj
,
guint
param_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
PurpleChatConversation
*
chat
=
PURPLE_CHAT_CONVERSATION
(
obj
);
switch
(
param_id
)
{
case
CHAT_PROP_ID
:
purple_chat_conversation_set_id
(
chat
,
g_value_get_int
(
value
));
break
;
case
CHAT_PROP_NICK
:
purple_chat_conversation_set_nick
(
chat
,
g_value_get_string
(
value
));
break
;
case
CHAT_PROP_LEFT
:
{
gboolean
left
=
g_value_get_boolean
(
value
);
if
(
left
)
purple_chat_conversation_leave
(
chat
);
}
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
pspec
);
break
;
}
}
/* Get method for GObject properties */
static
void
purple_chat_conversation_get_property
(
GObject
*
obj
,
guint
param_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
PurpleChatConversation
*
chat
=
PURPLE_CHAT_CONVERSATION
(
obj
);
switch
(
param_id
)
{
case
CHAT_PROP_TOPIC_WHO
:
g_value_set_string
(
value
,
purple_chat_conversation_get_topic_who
(
chat
));
break
;
case
CHAT_PROP_TOPIC
:
g_value_set_string
(
value
,
purple_chat_conversation_get_topic
(
chat
));
break
;
case
CHAT_PROP_ID
:
g_value_set_int
(
value
,
purple_chat_conversation_get_id
(
chat
));
break
;
case
CHAT_PROP_NICK
:
g_value_set_string
(
value
,
purple_chat_conversation_get_nick
(
chat
));
break
;
case
CHAT_PROP_LEFT
:
g_value_set_boolean
(
value
,
purple_chat_conversation_has_left
(
chat
));
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
pspec
);
break
;
}
}
/* GObject initialization function */
static
void
purple_chat_conversation_init
(
PurpleChatConversation
*
chat
)
{
PurpleChatConversationPrivate
*
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
priv
->
users
=
g_hash_table_new_full
(
_purple_conversation_user_hash
,
_purple_conversation_user_equal
,
g_free
,
g_object_unref
);
}
/* Called when done constructing */
static
void
purple_chat_conversation_constructed
(
GObject
*
object
)
{
PurpleChatConversation
*
chat
=
PURPLE_CHAT_CONVERSATION
(
object
);
PurpleAccount
*
account
;
const
char
*
disp
;
G_OBJECT_CLASS
(
purple_chat_conversation_parent_class
)
->
constructed
(
object
);
g_object_get
(
object
,
"account"
,
&
account
,
NULL
);
if
((
disp
=
purple_connection_get_display_name
(
purple_account_get_connection
(
account
))))
purple_chat_conversation_set_nick
(
chat
,
disp
);
else
purple_chat_conversation_set_nick
(
chat
,
purple_account_get_username
(
account
));
if
(
purple_prefs_get_bool
(
"/purple/logging/log_chats"
))
purple_conversation_set_logging
(
PURPLE_CONVERSATION
(
chat
),
TRUE
);
g_object_unref
(
account
);
}
/* GObject dispose function */
static
void
purple_chat_conversation_dispose
(
GObject
*
object
)
{
PurpleChatConversationPrivate
*
priv
=
purple_chat_conversation_get_instance_private
(
PURPLE_CHAT_CONVERSATION
(
object
));
g_hash_table_remove_all
(
priv
->
users
);
G_OBJECT_CLASS
(
purple_chat_conversation_parent_class
)
->
dispose
(
object
);
}
/* GObject finalize function */
static
void
purple_chat_conversation_finalize
(
GObject
*
object
)
{
PurpleChatConversation
*
chat
=
PURPLE_CHAT_CONVERSATION
(
object
);
PurpleConnection
*
gc
=
purple_conversation_get_connection
(
PURPLE_CONVERSATION
(
chat
));
PurpleChatConversationPrivate
*
priv
=
purple_chat_conversation_get_instance_private
(
chat
);
if
(
gc
!=
NULL
)
{
/* Still connected */
int
chat_id
=
purple_chat_conversation_get_id
(
chat
);
/*
* Close the window when the user tells us to, and let the protocol
* deal with the internals on it's own time. Don't do this if the
* protocol already knows it left the chat.
*/
if
(
!
purple_chat_conversation_has_left
(
chat
))
purple_serv_chat_leave
(
gc
,
chat_id
);
/*
* If they didn't call purple_serv_got_chat_left by now, it's too late.
* So we better do it for them before we destroy the thing.
*/
if
(
!
purple_chat_conversation_has_left
(
chat
))
purple_serv_got_chat_left
(
gc
,
chat_id
);
}
g_hash_table_destroy
(
priv
->
users
);
priv
->
users
=
NULL
;
g_list_free_full
(
priv
->
ignored
,
g_free
);
priv
->
ignored
=
NULL
;
g_free
(
priv
->
who
);
g_free
(
priv
->
topic
);
g_free
(
priv
->
nick
);
priv
->
who
=
NULL
;
priv
->
topic
=
NULL
;
priv
->
nick
=
NULL
;
G_OBJECT_CLASS
(
purple_chat_conversation_parent_class
)
->
finalize
(
object
);
}
/* Class initializer function */
static
void
purple_chat_conversation_class_init
(
PurpleChatConversationClass
*
klass
)
{
GObjectClass
*
obj_class
=
G_OBJECT_CLASS
(
klass
);
PurpleConversationClass
*
conv_class
=
PURPLE_CONVERSATION_CLASS
(
klass
);
obj_class
->
dispose
=
purple_chat_conversation_dispose
;
obj_class
->
finalize
=
purple_chat_conversation_finalize
;
obj_class
->
constructed
=
purple_chat_conversation_constructed
;
/* Setup properties */
obj_class
->
get_property
=
purple_chat_conversation_get_property
;
obj_class
->
set_property
=
purple_chat_conversation_set_property
;
conv_class
->
write_message
=
chat_conversation_write_message
;
chat_properties
[
CHAT_PROP_TOPIC_WHO
]
=
g_param_spec_string
(
"topic-who"
,
"Who set topic"
,
"Who set the chat topic."
,
NULL
,
G_PARAM_READABLE
|
G_PARAM_STATIC_STRINGS
);
chat_properties
[
CHAT_PROP_TOPIC
]
=
g_param_spec_string
(
"topic"
,
"Topic"
,
"Topic of the chat."
,
NULL
,
G_PARAM_READABLE
|
G_PARAM_STATIC_STRINGS
);
chat_properties
[
CHAT_PROP_ID
]
=
g_param_spec_int
(
"chat-id"
,
"Chat ID"
,
"The ID of the chat."
,
G_MININT
,
G_MAXINT
,
0
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
chat_properties
[
CHAT_PROP_NICK
]
=
g_param_spec_string
(
"nick"
,
"Nickname"
,
"The nickname of the user in a chat."
,
NULL
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
chat_properties
[
CHAT_PROP_LEFT
]
=
g_param_spec_boolean
(
"left"
,
"Left the chat"
,
"Whether the user has left the chat."
,
FALSE
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
g_object_class_install_properties
(
obj_class
,
CHAT_PROP_LAST
,
chat_properties
);
}
PurpleChatConversation
*
purple_chat_conversation_new
(
PurpleAccount
*
account
,
const
char
*
name
)
{
PurpleChatConversation
*
chat
;
PurpleConnection
*
gc
;
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
g_return_val_if_fail
(
name
!=
NULL
,
NULL
);
/* Check if this conversation already exists. */
if
((
chat
=
purple_conversations_find_chat_with_account
(
name
,
account
))
!=
NULL
)
{
if
(
!
purple_chat_conversation_has_left
(
chat
))
{
purple_debug_warning
(
"conversationtypes"
,
"Trying to create "
"multiple chats (%s) with the same name is deprecated and "
"will be removed in libpurple 3.0.0"
,
name
);
}
else
{
/*
* This hack is necessary because some protocols (MSN) have unnamed chats
* that all use the same name. A PurpleConversation for one of those
* is only ever re-used if the user has left, so calls to
* purple_conversation_new need to fall-through to creating a new
* chat.
* TODO 3.0.0: Remove this workaround and mandate unique names.
*/
chat_conversation_cleanup_for_rejoin
(
chat
);
return
chat
;
}
}
gc
=
purple_account_get_connection
(
account
);
g_return_val_if_fail
(
PURPLE_IS_CONNECTION
(
gc
),
NULL
);
chat
=
g_object_new
(
PURPLE_TYPE_CHAT_CONVERSATION
,
"account"
,
account
,
"name"
,
name
,
"title"
,
name
,
NULL
);
return
chat
;
}
/**************************************************************************
* Chat Conversation User API
**************************************************************************/
static
int
purple_chat_user_compare
(
PurpleChatUser
*
a
,
PurpleChatUser
*
b
)
{
PurpleChatUserFlags
f1
=
0
,
f2
=
0
;
PurpleChatUserPrivate
*
priva
,
*
privb
;
char
*
user1
=
NULL
,
*
user2
=
NULL
;
gint
ret
=
0
;
priva
=
purple_chat_user_get_instance_private
(
a
);
privb
=
purple_chat_user_get_instance_private
(
b
);
if
(
priva
)
{
f1
=
priva
->
flags
;
if
(
priva
->
alias_key
)
user1
=
priva
->
alias_key
;
else
if
(
priva
->
name
)
user1
=
priva
->
name
;
}
if
(
privb
)
{
f2
=
privb
->
flags
;
if
(
privb
->
alias_key
)
user2
=
privb
->
alias_key
;
else
if
(
privb
->
name
)
user2
=
privb
->
name
;
}
if
(
user1
==
NULL
||
user2
==
NULL
)
{
if
(
!
(
user1
==
NULL
&&
user2
==
NULL
))
ret
=
(
user1
==
NULL
)
?
-1
:
1
;
}
else
if
(
f1
!=
f2
)
{
/* sort more important users first */
ret
=
(
f1
>
f2
)
?
-1
:
1
;
}
else
if
(
priva
->
buddy
!=
privb
->
buddy
)
{
ret
=
priva
->
buddy
?
-1
:
1
;
}
else
{
ret
=
purple_utf8_strcasecmp
(
user1
,
user2
);
}
return
ret
;
}
const
char
*
purple_chat_user_get_alias
(
PurpleChatUser
*
cb
)
{
PurpleChatUserPrivate
*
priv
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_USER
(
cb
),
NULL
);
priv
=
purple_chat_user_get_instance_private
(
cb
);
return
priv
->
alias
;
}
const
char
*
purple_chat_user_get_name
(
PurpleChatUser
*
cb
)
{
PurpleChatUserPrivate
*
priv
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_USER
(
cb
),
NULL
);
priv
=
purple_chat_user_get_instance_private
(
cb
);
return
priv
->
name
;
}
void
purple_chat_user_set_flags
(
PurpleChatUser
*
cb
,
PurpleChatUserFlags
flags
)
{
PurpleConversationUiOps
*
ops
;
PurpleChatUserFlags
oldflags
;
PurpleChatUserPrivate
*
priv
;
g_return_if_fail
(
PURPLE_IS_CHAT_USER
(
cb
));
priv
=
purple_chat_user_get_instance_private
(
cb
);
if
(
flags
==
priv
->
flags
)
return
;
oldflags
=
priv
->
flags
;
priv
->
flags
=
flags
;
g_object_notify_by_pspec
(
G_OBJECT
(
cb
),
cu_properties
[
CU_PROP_FLAGS
]);
ops
=
purple_conversation_get_ui_ops
(
PURPLE_CONVERSATION
(
priv
->
chat
));
if
(
ops
!=
NULL
&&
ops
->
chat_update_user
!=
NULL
)
ops
->
chat_update_user
(
cb
);
purple_signal_emit
(
purple_conversations_get_handle
(),
"chat-user-flags"
,
cb
,
oldflags
,
flags
);
}
PurpleChatUserFlags
purple_chat_user_get_flags
(
PurpleChatUser
*
cb
)
{
PurpleChatUserPrivate
*
priv
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_USER
(
cb
),
PURPLE_CHAT_USER_NONE
);
priv
=
purple_chat_user_get_instance_private
(
cb
);
return
priv
->
flags
;
}
void
purple_chat_user_set_ui_data
(
PurpleChatUser
*
cb
,
gpointer
ui_data
)
{
g_return_if_fail
(
PURPLE_IS_CHAT_USER
(
cb
));
cb
->
ui_data
=
ui_data
;
}
gpointer
purple_chat_user_get_ui_data
(
PurpleChatUser
*
cb
)
{
g_return_val_if_fail
(
PURPLE_IS_CHAT_USER
(
cb
),
NULL
);
return
cb
->
ui_data
;
}
void
purple_chat_user_set_chat
(
PurpleChatUser
*
cb
,
PurpleChatConversation
*
chat
)
{
PurpleChatUserPrivate
*
priv
;
g_return_if_fail
(
PURPLE_IS_CHAT_USER
(
cb
));
priv
=
purple_chat_user_get_instance_private
(
cb
);
priv
->
chat
=
chat
;
g_object_notify_by_pspec
(
G_OBJECT
(
cb
),
cu_properties
[
CU_PROP_CHAT
]);
}
PurpleChatConversation
*
purple_chat_user_get_chat
(
PurpleChatUser
*
cb
)
{
PurpleChatUserPrivate
*
priv
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_USER
(
cb
),
NULL
);
priv
=
purple_chat_user_get_instance_private
(
cb
);
return
priv
->
chat
;
}
gboolean
purple_chat_user_is_buddy
(
PurpleChatUser
*
cb
)
{
PurpleChatUserPrivate
*
priv
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_USER
(
cb
),
FALSE
);
priv
=
purple_chat_user_get_instance_private
(
cb
);
return
priv
->
buddy
;
}
/**************************************************************************
* GObject code for chat user
**************************************************************************/
/* Set method for GObject properties */
static
void
purple_chat_user_set_property
(
GObject
*
obj
,
guint
param_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
PurpleChatUser
*
cb
=
PURPLE_CHAT_USER
(
obj
);
PurpleChatUserPrivate
*
priv
=
purple_chat_user_get_instance_private
(
cb
);
switch
(
param_id
)
{
case
CU_PROP_CHAT
:
priv
->
chat
=
g_value_get_object
(
value
);
break
;
case
CU_PROP_NAME
:
g_free
(
priv
->
name
);
priv
->
name
=
g_value_dup_string
(
value
);
break
;
case
CU_PROP_ALIAS
:
g_free
(
priv
->
alias
);
priv
->
alias
=
g_value_dup_string
(
value
);
break
;
case
CU_PROP_FLAGS
:
priv
->
flags
=
g_value_get_flags
(
value
);
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
pspec
);
break
;
}
}
/* Get method for GObject properties */
static
void
purple_chat_user_get_property
(
GObject
*
obj
,
guint
param_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
PurpleChatUser
*
cb
=
PURPLE_CHAT_USER
(
obj
);
switch
(
param_id
)
{
case
CU_PROP_CHAT
:
g_value_set_object
(
value
,
purple_chat_user_get_chat
(
cb
));
break
;
case
CU_PROP_NAME
:
g_value_set_string
(
value
,
purple_chat_user_get_name
(
cb
));
break
;
case
CU_PROP_ALIAS
:
g_value_set_string
(
value
,
purple_chat_user_get_alias
(
cb
));
break
;
case
CU_PROP_FLAGS
:
g_value_set_flags
(
value
,
purple_chat_user_get_flags
(
cb
));
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
pspec
);
break
;
}
}
/* GObject initialization function */
static
void
purple_chat_user_init
(
PurpleChatUser
*
user
)
{
}
/* Called when done constructing */
static
void
purple_chat_user_constructed
(
GObject
*
object
)
{
PurpleChatUserPrivate
*
priv
=
purple_chat_user_get_instance_private
(
PURPLE_CHAT_USER
(
object
));
PurpleAccount
*
account
;
G_OBJECT_CLASS
(
purple_chat_user_parent_class
)
->
constructed
(
object
);
account
=
purple_conversation_get_account
(
PURPLE_CONVERSATION
(
priv
->
chat
));
if
(
purple_blist_find_buddy
(
account
,
priv
->
name
)
!=
NULL
)
priv
->
buddy
=
TRUE
;
}
/* GObject finalize function */
static
void
purple_chat_user_finalize
(
GObject
*
object
)
{
PurpleChatUser
*
cb
=
PURPLE_CHAT_USER
(
object
);
PurpleChatUserPrivate
*
priv
=
purple_chat_user_get_instance_private
(
cb
);
purple_signal_emit
(
purple_conversations_get_handle
(),
"deleting-chat-user"
,
cb
);
g_free
(
priv
->
alias
);
g_free
(
priv
->
alias_key
);
g_free
(
priv
->
name
);
G_OBJECT_CLASS
(
purple_chat_user_parent_class
)
->
finalize
(
object
);
}
/* Class initializer function */
static
void
purple_chat_user_class_init
(
PurpleChatUserClass
*
klass
)
{
GObjectClass
*
obj_class
=
G_OBJECT_CLASS
(
klass
);
obj_class
->
constructed
=
purple_chat_user_constructed
;
obj_class
->
finalize
=
purple_chat_user_finalize
;
/* Setup properties */
obj_class
->
get_property
=
purple_chat_user_get_property
;
obj_class
->
set_property
=
purple_chat_user_set_property
;
cu_properties
[
CU_PROP_CHAT
]
=
g_param_spec_object
(
"chat"
,
"Chat"
,
"The chat the buddy belongs to."
,
PURPLE_TYPE_CHAT_CONVERSATION
,
G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT_ONLY
|
G_PARAM_STATIC_STRINGS
);
cu_properties
[
CU_PROP_NAME
]
=
g_param_spec_string
(
"name"
,
"Name"
,
"Name of the chat user."
,
NULL
,
G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT
|
G_PARAM_STATIC_STRINGS
);
cu_properties
[
CU_PROP_ALIAS
]
=
g_param_spec_string
(
"alias"
,
"Alias"
,
"Alias of the chat user."
,
NULL
,
G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT
|
G_PARAM_STATIC_STRINGS
);
cu_properties
[
CU_PROP_FLAGS
]
=
g_param_spec_flags
(
"flags"
,
"Buddy flags"
,
"The flags for the chat user."
,
PURPLE_TYPE_CHAT_USER_FLAGS
,
PURPLE_CHAT_USER_NONE
,
G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT
|
G_PARAM_STATIC_STRINGS
);
g_object_class_install_properties
(
obj_class
,
CU_PROP_LAST
,
cu_properties
);
}
PurpleChatUser
*
purple_chat_user_new
(
PurpleChatConversation
*
chat
,
const
char
*
name
,
const
char
*
alias
,
PurpleChatUserFlags
flags
)
{
PurpleChatUser
*
cb
;
g_return_val_if_fail
(
PURPLE_IS_CHAT_CONVERSATION
(
chat
),
NULL
);
g_return_val_if_fail
(
name
!=
NULL
,
NULL
);
cb
=
g_object_new
(
PURPLE_TYPE_CHAT_USER
,
"chat"
,
chat
,
"name"
,
name
,
"alias"
,
alias
,
"flags"
,
flags
,
NULL
);
return
cb
;
}