* 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 * 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 static GObjectClass *parent_class; /************************************************************************** **************************************************************************/ purple_protocol_get_id(const PurpleProtocol *protocol) g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL); purple_protocol_get_name(const PurpleProtocol *protocol) g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL); purple_protocol_get_options(const PurpleProtocol *protocol) g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), 0); return protocol->options; purple_protocol_get_user_splits(const PurpleProtocol *protocol) g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL); return protocol->user_splits; purple_protocol_get_account_options(const PurpleProtocol *protocol) g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL); return protocol->account_options; purple_protocol_get_icon_spec(const PurpleProtocol *protocol) g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL); return protocol->icon_spec; purple_protocol_get_whiteboard_ops(const PurpleProtocol *protocol) g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL); return protocol->whiteboard_ops; icon_spec_free(PurpleProtocol *protocol) g_return_if_fail(PURPLE_IS_PROTOCOL(protocol)); g_free(protocol->icon_spec); protocol->icon_spec = NULL; /************************************************************************** **************************************************************************/ purple_protocol_init(GTypeInstance *instance, gpointer klass) purple_protocol_finalize(GObject *object) PurpleProtocol *protocol = PURPLE_PROTOCOL(object); accounts = purple_accounts_get_all_active(); for (l = accounts; l != NULL; l = l->next) { PurpleAccount *account = PURPLE_ACCOUNT(l->data); if (purple_account_is_disconnected(account)) if (purple_strequal(protocol->id, purple_account_get_protocol_id(account))) purple_account_disconnect(account); purple_request_close_with_handle(protocol); purple_notify_close_with_handle(protocol); purple_signals_disconnect_by_handle(protocol); purple_signals_unregister_by_instance(protocol); purple_prefs_disconnect_by_handle(protocol); g_list_free_full(protocol->user_splits, (GDestroyNotify)purple_account_user_split_destroy); g_list_free_full(protocol->account_options, (GDestroyNotify)purple_account_option_destroy); icon_spec_free(protocol); parent_class->finalize(object); purple_protocol_class_init(PurpleProtocolClass *klass) GObjectClass *obj_class = G_OBJECT_CLASS(klass); parent_class = g_type_class_peek_parent(klass); obj_class->finalize = purple_protocol_finalize; purple_protocol_get_type(void) if (G_UNLIKELY(type == 0)) { static const GTypeInfo info = { .class_size = sizeof(PurpleProtocolClass), .class_init = (GClassInitFunc)purple_protocol_class_init, .instance_size = sizeof(PurpleProtocol), .instance_init = (GInstanceInitFunc)purple_protocol_init, type = g_type_register_static(G_TYPE_OBJECT, "PurpleProtocol", &info, G_TYPE_FLAG_ABSTRACT); /************************************************************************** **************************************************************************/ #define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \ PurpleProtocolClass *klass = PURPLE_PROTOCOL_GET_CLASS(protocol); \ g_return_if_fail(klass != NULL); \ klass->funcname(__VA_ARGS__); #define DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol,defaultreturn,funcname,...) \ PurpleProtocolClass *klass = PURPLE_PROTOCOL_GET_CLASS(protocol); \ g_return_val_if_fail(klass != NULL, defaultreturn); \ return klass->funcname(__VA_ARGS__); \ purple_protocol_class_login(PurpleProtocol *protocol, PurpleAccount *account) DEFINE_PROTOCOL_FUNC(protocol, login, account); purple_protocol_class_close(PurpleProtocol *protocol, PurpleConnection *gc) DEFINE_PROTOCOL_FUNC(protocol, close, gc); purple_protocol_class_status_types(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, status_types, account); purple_protocol_class_list_icon(PurpleProtocol *protocol, PurpleAccount *account, PurpleBuddy *buddy) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, list_icon, account, buddy); #undef DEFINE_PROTOCOL_FUNC_WITH_RETURN #undef DEFINE_PROTOCOL_FUNC /************************************************************************** * Protocol Client Interface API **************************************************************************/ #define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \ PurpleProtocolClientInterface *client_iface = \ PURPLE_PROTOCOL_CLIENT_GET_IFACE(protocol); \ if (client_iface && client_iface->funcname) \ client_iface->funcname(__VA_ARGS__); #define DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol,defaultreturn,funcname,...) \ PurpleProtocolClientInterface *client_iface = \ PURPLE_PROTOCOL_CLIENT_GET_IFACE(protocol); \ if (client_iface && client_iface->funcname) \ return client_iface->funcname(__VA_ARGS__); \ purple_protocol_client_iface_get_type(void) if (G_UNLIKELY(type == 0)) { static const GTypeInfo info = { .class_size = sizeof(PurpleProtocolClientInterface), type = g_type_register_static(G_TYPE_INTERFACE, "PurpleProtocolClientInterface", &info, 0); purple_protocol_client_iface_get_actions(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, get_actions, gc); purple_protocol_client_iface_list_emblem(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, list_emblem, buddy); purple_protocol_client_iface_status_text(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, status_text, buddy); purple_protocol_client_iface_tooltip_text(PurpleProtocol *protocol, PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full) DEFINE_PROTOCOL_FUNC(protocol, tooltip_text, buddy, user_info, full); purple_protocol_client_iface_blist_node_menu(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, blist_node_menu, node); purple_protocol_client_iface_buddy_free(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC(protocol, buddy_free, buddy); purple_protocol_client_iface_convo_closed(PurpleProtocol *protocol, PurpleConnection *gc, const char *who) DEFINE_PROTOCOL_FUNC(protocol, convo_closed, gc, who); purple_protocol_client_iface_normalize(PurpleProtocol *protocol, const PurpleAccount *account, const char *who) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, normalize, account, who); purple_protocol_client_iface_find_blist_chat(PurpleProtocol *protocol, PurpleAccount *account, const char *name) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, find_blist_chat, account, purple_protocol_client_iface_offline_message(PurpleProtocol *protocol, const PurpleBuddy *buddy) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, FALSE, offline_message, buddy); purple_protocol_client_iface_get_account_text_table(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, get_account_text_table, purple_protocol_client_iface_get_moods(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, get_moods, account); purple_protocol_client_iface_get_max_message_size(PurpleProtocol *protocol, PurpleConversation *conv) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, 0, get_max_message_size, conv); #undef DEFINE_PROTOCOL_FUNC_WITH_RETURN #undef DEFINE_PROTOCOL_FUNC /************************************************************************** * Protocol Server Interface API **************************************************************************/ #define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \ PurpleProtocolServerInterface *server_iface = \ PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol); \ if (server_iface && server_iface->funcname) \ server_iface->funcname(__VA_ARGS__); #define DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol,defaultreturn,funcname,...) \ PurpleProtocolServerInterface *server_iface = \ PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol); \ if (server_iface && server_iface->funcname) \ return server_iface->funcname(__VA_ARGS__); \ purple_protocol_server_iface_get_type(void) if (G_UNLIKELY(type == 0)) { static const GTypeInfo info = { .class_size = sizeof(PurpleProtocolServerInterface), type = g_type_register_static(G_TYPE_INTERFACE, "PurpleProtocolServerInterface", &info, 0); purple_protocol_server_iface_register_user(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC(protocol, register_user, account); purple_protocol_server_iface_unregister_user(PurpleProtocol *protocol, PurpleAccount *account, PurpleAccountUnregistrationCb cb, DEFINE_PROTOCOL_FUNC(protocol, unregister_user, account, cb, user_data); purple_protocol_server_iface_set_info(PurpleProtocol *protocol, PurpleConnection *gc, const char *info) DEFINE_PROTOCOL_FUNC(protocol, set_info, gc, info); purple_protocol_server_iface_get_info(PurpleProtocol *protocol, PurpleConnection *gc, const char *who) DEFINE_PROTOCOL_FUNC(protocol, get_info, gc, who); purple_protocol_server_iface_set_status(PurpleProtocol *protocol, PurpleAccount *account, PurpleStatus *status) DEFINE_PROTOCOL_FUNC(protocol, set_status, account, status); purple_protocol_server_iface_set_idle(PurpleProtocol *protocol, PurpleConnection *gc, int idletime) DEFINE_PROTOCOL_FUNC(protocol, set_idle, gc, idletime); purple_protocol_server_iface_change_passwd(PurpleProtocol *protocol, PurpleConnection *gc, const char *old_pass, const char *new_pass) DEFINE_PROTOCOL_FUNC(protocol, change_passwd, gc, old_pass, new_pass); purple_protocol_server_iface_add_buddy(PurpleProtocol *protocol, PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, DEFINE_PROTOCOL_FUNC(protocol, add_buddy, gc, buddy, group, message); purple_protocol_server_iface_add_buddies(PurpleProtocol *protocol, PurpleConnection *gc, GList *buddies, GList *groups, DEFINE_PROTOCOL_FUNC(protocol, add_buddies, gc, buddies, groups, message); purple_protocol_server_iface_remove_buddy(PurpleProtocol *protocol, PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) DEFINE_PROTOCOL_FUNC(protocol, remove_buddy, gc, buddy, group); purple_protocol_server_iface_remove_buddies(PurpleProtocol *protocol, PurpleConnection *gc, GList *buddies, GList *groups) DEFINE_PROTOCOL_FUNC(protocol, remove_buddies, gc, buddies, groups); purple_protocol_server_iface_keepalive(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC(protocol, keepalive, gc); purple_protocol_server_iface_get_keepalive_interval(PurpleProtocol *protocol) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, 30, get_keepalive_interval); purple_protocol_server_iface_alias_buddy(PurpleProtocol *protocol, PurpleConnection *gc, const char *who, const char *alias) DEFINE_PROTOCOL_FUNC(protocol, alias_buddy, gc, who, alias); purple_protocol_server_iface_group_buddy(PurpleProtocol *protocol, PurpleConnection *gc, const char *who, const char *old_group, DEFINE_PROTOCOL_FUNC(protocol, group_buddy, gc, who, old_group, new_group); purple_protocol_server_iface_rename_group(PurpleProtocol *protocol, PurpleConnection *gc, const char *old_name, PurpleGroup *group, DEFINE_PROTOCOL_FUNC(protocol, rename_group, gc, old_name, group, purple_protocol_server_iface_set_buddy_icon(PurpleProtocol *protocol, PurpleConnection *gc, PurpleImage *img) DEFINE_PROTOCOL_FUNC(protocol, set_buddy_icon, gc, img); purple_protocol_server_iface_remove_group(PurpleProtocol *protocol, PurpleConnection *gc, PurpleGroup *group) DEFINE_PROTOCOL_FUNC(protocol, remove_group, gc, group); purple_protocol_server_iface_send_raw(PurpleProtocol *protocol, PurpleConnection *gc, const char *buf, int len) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, 0, send_raw, gc, buf, len); purple_protocol_server_iface_set_public_alias(PurpleProtocol *protocol, PurpleConnection *gc, const char *alias, PurpleSetPublicAliasSuccessCallback success_cb, PurpleSetPublicAliasFailureCallback failure_cb) DEFINE_PROTOCOL_FUNC(protocol, set_public_alias, gc, alias, success_cb, purple_protocol_server_iface_get_public_alias(PurpleProtocol *protocol, PurpleConnection *gc, PurpleGetPublicAliasSuccessCallback success_cb, PurpleGetPublicAliasFailureCallback failure_cb) DEFINE_PROTOCOL_FUNC(protocol, get_public_alias, gc, success_cb, #undef DEFINE_PROTOCOL_FUNC_WITH_RETURN #undef DEFINE_PROTOCOL_FUNC /************************************************************************** * Protocol IM Interface API **************************************************************************/ #define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \ PurpleProtocolIMInterface *im_iface = \ PURPLE_PROTOCOL_IM_GET_IFACE(protocol); \ if (im_iface && im_iface->funcname) \ im_iface->funcname(__VA_ARGS__); #define DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol,defaultreturn,funcname,...) \ PurpleProtocolIMInterface *im_iface = \ PURPLE_PROTOCOL_IM_GET_IFACE(protocol); \ if (im_iface && im_iface->funcname) \ return im_iface->funcname(__VA_ARGS__); \ purple_protocol_im_iface_get_type(void) if (G_UNLIKELY(type == 0)) { static const GTypeInfo info = { .class_size = sizeof(PurpleProtocolIMInterface), type = g_type_register_static(G_TYPE_INTERFACE, "PurpleProtocolIMInterface", &info, 0); purple_protocol_im_iface_send(PurpleProtocol *protocol, PurpleConnection *gc, DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, 0, send, gc, msg); purple_protocol_im_iface_send_typing(PurpleProtocol *protocol, PurpleConnection *gc, const char *name, PurpleIMTypingState state) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, 0, send_typing, gc, name, state); #undef DEFINE_PROTOCOL_FUNC_WITH_RETURN #undef DEFINE_PROTOCOL_FUNC /************************************************************************** * Protocol Chat Interface API **************************************************************************/ #define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \ PurpleProtocolChatInterface *chat_iface = \ PURPLE_PROTOCOL_CHAT_GET_IFACE(protocol); \ if (chat_iface && chat_iface->funcname) \ chat_iface->funcname(__VA_ARGS__); #define DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol,defaultreturn,funcname,...) \ PurpleProtocolChatInterface *chat_iface = \ PURPLE_PROTOCOL_CHAT_GET_IFACE(protocol); \ if (chat_iface && chat_iface->funcname) \ return chat_iface->funcname(__VA_ARGS__); \ purple_protocol_chat_iface_get_type(void) if (G_UNLIKELY(type == 0)) { static const GTypeInfo info = { .class_size = sizeof(PurpleProtocolChatInterface), type = g_type_register_static(G_TYPE_INTERFACE, "PurpleProtocolChatInterface", &info, 0); purple_protocol_chat_iface_info(PurpleProtocol *protocol, PurpleConnection *gc) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, info, gc); purple_protocol_chat_iface_info_defaults(PurpleProtocol *protocol, PurpleConnection *gc, const char *chat_name) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, info_defaults, gc, purple_protocol_chat_iface_join(PurpleProtocol *protocol, PurpleConnection *gc, DEFINE_PROTOCOL_FUNC(protocol, join, gc, components); purple_protocol_chat_iface_reject(PurpleProtocol *protocol, PurpleConnection *gc, GHashTable *components) DEFINE_PROTOCOL_FUNC(protocol, reject, gc, components); purple_protocol_chat_iface_get_name(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, get_name, components); purple_protocol_chat_iface_invite(PurpleProtocol *protocol, PurpleConnection *gc, int id, const char *message, const char *who) DEFINE_PROTOCOL_FUNC(protocol, invite, gc, id, message, who); purple_protocol_chat_iface_leave(PurpleProtocol *protocol, PurpleConnection *gc, DEFINE_PROTOCOL_FUNC(protocol, leave, gc, id); purple_protocol_chat_iface_send(PurpleProtocol *protocol, PurpleConnection *gc, int id, PurpleMessage *msg) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, 0, send, gc, id, msg); purple_protocol_chat_iface_get_user_real_name(PurpleProtocol *protocol, PurpleConnection *gc, int id, const char *who) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, get_user_real_name, gc, id, purple_protocol_chat_iface_set_topic(PurpleProtocol *protocol, PurpleConnection *gc, int id, const char *topic) DEFINE_PROTOCOL_FUNC(protocol, set_topic, gc, id, topic); #undef DEFINE_PROTOCOL_FUNC_WITH_RETURN #undef DEFINE_PROTOCOL_FUNC /************************************************************************** * Protocol Privacy Interface API **************************************************************************/ #define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \ PurpleProtocolPrivacyInterface *privacy_iface = \ PURPLE_PROTOCOL_PRIVACY_GET_IFACE(protocol); \ if (privacy_iface && privacy_iface->funcname) \ privacy_iface->funcname(__VA_ARGS__); #define DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol,defaultreturn,funcname,...) \ PurpleProtocolPrivacyInterface *privacy_iface = \ PURPLE_PROTOCOL_PRIVACY_GET_IFACE(protocol); \ if (privacy_iface && privacy_iface->funcname) \ return privacy_iface->funcname(__VA_ARGS__); \ purple_protocol_privacy_iface_get_type(void) if (G_UNLIKELY(type == 0)) { static const GTypeInfo info = { .class_size = sizeof(PurpleProtocolPrivacyInterface), type = g_type_register_static(G_TYPE_INTERFACE, "PurpleProtocolPrivacyInterface", &info, 0); purple_protocol_privacy_iface_add_permit(PurpleProtocol *protocol, PurpleConnection *gc, const char *name) DEFINE_PROTOCOL_FUNC(protocol, add_permit, gc, name); purple_protocol_privacy_iface_add_deny(PurpleProtocol *protocol, PurpleConnection *gc, const char *name) DEFINE_PROTOCOL_FUNC(protocol, add_deny, gc, name); purple_protocol_privacy_iface_rem_permit(PurpleProtocol *protocol, PurpleConnection *gc, const char *name) DEFINE_PROTOCOL_FUNC(protocol, rem_permit, gc, name); purple_protocol_privacy_iface_rem_deny(PurpleProtocol *protocol, PurpleConnection *gc, const char *name) DEFINE_PROTOCOL_FUNC(protocol, rem_deny, gc, name); purple_protocol_privacy_iface_set_permit_deny(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC(protocol, set_permit_deny, gc); #undef DEFINE_PROTOCOL_FUNC_WITH_RETURN #undef DEFINE_PROTOCOL_FUNC /************************************************************************** * Protocol Media Interface API **************************************************************************/ #define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \ PurpleProtocolMediaInterface *media_iface = \ PURPLE_PROTOCOL_MEDIA_GET_IFACE(protocol); \ if (media_iface && media_iface->funcname) \ media_iface->funcname(__VA_ARGS__); #define DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol,defaultreturn,funcname,...) \ PurpleProtocolMediaInterface *media_iface = \ PURPLE_PROTOCOL_MEDIA_GET_IFACE(protocol); \ if (media_iface && media_iface->funcname) \ return media_iface->funcname(__VA_ARGS__); \ purple_protocol_media_iface_get_type(void) if (G_UNLIKELY(type == 0)) { static const GTypeInfo info = { .class_size = sizeof(PurpleProtocolMediaInterface), type = g_type_register_static(G_TYPE_INTERFACE, "PurpleProtocolMediaInterface", &info, 0); purple_protocol_media_iface_initiate_session(PurpleProtocol *protocol, PurpleAccount *account, const char *who, PurpleMediaSessionType type) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, FALSE, initiate_session, account, purple_protocol_media_iface_get_caps(PurpleProtocol *protocol, PurpleAccount *account, const char *who) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, 0, get_caps, account, who); gboolean purple_protocol_media_iface_send_dtmf(PurpleProtocol *protocol, PurpleMedia *media, gchar dtmf, guint8 volume, guint8 duration) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, FALSE, send_dtmf, media, #undef DEFINE_PROTOCOL_FUNC_WITH_RETURN #undef DEFINE_PROTOCOL_FUNC /************************************************************************** * Protocol Factory Interface API **************************************************************************/ #define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \ PurpleProtocolFactoryInterface *factory_iface = \ PURPLE_PROTOCOL_FACTORY_GET_IFACE(protocol); \ if (factory_iface && factory_iface->funcname) \ factory_iface->funcname(__VA_ARGS__); #define DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol,defaultreturn,funcname,...) \ PurpleProtocolFactoryInterface *factory_iface = \ PURPLE_PROTOCOL_FACTORY_GET_IFACE(protocol); \ if (factory_iface && factory_iface->funcname) \ return factory_iface->funcname(__VA_ARGS__); \ purple_protocol_factory_iface_get_type(void) if (G_UNLIKELY(type == 0)) { static const GTypeInfo info = { .class_size = sizeof(PurpleProtocolFactoryInterface), type = g_type_register_static(G_TYPE_INTERFACE, "PurpleProtocolFactoryInterface", &info, 0); purple_protocol_factory_iface_connection_new(PurpleProtocol *protocol, PurpleAccount *account, const char *password) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, connection_new, protocol, purple_protocol_factory_iface_roomlist_new(PurpleProtocol *protocol, DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, roomlist_new, account); purple_protocol_factory_iface_whiteboard_new(PurpleProtocol *protocol, PurpleAccount *account, const char *who, int state) DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, whiteboard_new, account, #undef DEFINE_PROTOCOL_FUNC_WITH_RETURN #undef DEFINE_PROTOCOL_FUNC