# HG changeset patch
# Node ID 03fa8295353f
# Parent  e78a46048ae7
diff --git a/ChangeLog.API b/ChangeLog.API
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -415,23 +415,20 @@
 		* purple_conversation_get_message_history
 		* purple_conversation_get_remote_smileys
 		* purple_conversation_get_smiley
+		* purple_conversation_get_ui_ops
 		* purple_conversation_is_logging
 		* purple_conversation_set_account
-		* purple_conversations_add. Use purple_conversation_manager_register
-		  instead.
-		* purple_conversations_remove. Use
-		  purple_conversation_manager_unregister instead.
-		* purple_conversations_get_all. Use purple_conversation_manager_get_all
-		  instead.
-		* purple_conversations_find_with_account. Use
-		  purple_conversation_manager_find instead.
-		* purple_conversations_find_im_with_account. Use
-		  purple_conversation_manager_find_im instead.
-		* purple_conversations_find_chat_with_account. Use
-		  purple_conversation_manager_find_chat instead.
-		* purple_conversations_find_chat. Use
-		  purple_conversation_manager_find_chat_by_id instead.
 		* purple_conversation_set_logging
+		* purple_conversation_set_ui_ops
+		* purple_conversations_add.
+		* purple_conversations_get_all.
+		* purple_conversations_find_with_account.
+		* purple_conversations_find_im_with_account.
+		* purple_conversations_find_chat_with_account.
+		* purple_conversations_find_chat.
+		* purple_conversations_get_ui_ops.
+		* purple_conversations_remove.
+		* purple_conversations_set_ui_ops.
 		* purple_core_get_ui, use purple_core_get_ui_info instead.
 		* purple_core_ensure_single_instance. Check via GApplication
 		  or whatever is appropriate for your UI.
diff --git a/libpurple/buddy.c b/libpurple/buddy.c
--- a/libpurple/buddy.c
+++ b/libpurple/buddy.c
@@ -25,6 +25,7 @@
 #include "debug.h"
 #include "purplecontactmanager.h"
 #include "purpleconversationmanager.h"
+#include "purpleimconversation.h"
 #include "purpleprotocolclient.h"
 #include "util.h"
 
diff --git a/libpurple/buddyicon.c b/libpurple/buddyicon.c
--- a/libpurple/buddyicon.c
+++ b/libpurple/buddyicon.c
@@ -24,6 +24,7 @@
 #include "debug.h"
 #include "image.h"
 #include "purpleaccountmanager.h"
+#include "purplechatconversation.h"
 #include "purpleconversation.h"
 #include "purpleconversationmanager.h"
 #include "purplepath.h"
diff --git a/libpurple/cmds.c b/libpurple/cmds.c
--- a/libpurple/cmds.c
+++ b/libpurple/cmds.c
@@ -22,6 +22,8 @@
 
 #include "cmds.h"
 #include "purpleaccount.h"
+#include "purplechatconversation.h"
+#include "purpleimconversation.h"
 #include "purplemarkup.h"
 
 static GList *cmds = NULL;
diff --git a/libpurple/connection.h b/libpurple/connection.h
--- a/libpurple/connection.h
+++ b/libpurple/connection.h
@@ -328,20 +328,6 @@
 GCancellable *purple_connection_get_cancellable(PurpleConnection *connection);
 
 /**
- * purple_connection_get_active_chats:
- * @gc: The connection.
- *
- * Returns a list of active chat conversations on a connection.
- *
- * Returns: (element-type PurpleChatConversation) (transfer none): The active
- *          chats on the connection.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-GSList *purple_connection_get_active_chats(PurpleConnection *gc);
-
-/**
  * purple_connection_get_display_name:
  * @gc: The connection.
  *
diff --git a/libpurple/connection.c b/libpurple/connection.c
--- a/libpurple/connection.c
+++ b/libpurple/connection.c
@@ -57,9 +57,6 @@
 	PurpleAccount *account;       /* The account being connected to.   */
 	char *password;               /* The password used.                */
 
-	GSList *active_chats;         /* A list of active chats
-	                                  (#PurpleChatConversation structs). */
-
 	char *display_name;           /* How you appear to other people.   */
 
 	/* Wants to Die state.  This is set when the user chooses to log out, or
@@ -281,17 +278,6 @@
 	g_object_notify_by_pspec(G_OBJECT(connection), properties[PROP_PASSWORD]);
 }
 
-GSList *
-purple_connection_get_active_chats(PurpleConnection *connection) {
-	PurpleConnectionPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), NULL);
-
-	priv = purple_connection_get_instance_private(connection);
-
-	return priv->active_chats;
-}
-
 const char *
 purple_connection_get_display_name(PurpleConnection *connection) {
 	PurpleConnectionPrivate *priv = NULL;
@@ -303,19 +289,6 @@
 	return priv->display_name;
 }
 
-void
-_purple_connection_remove_active_chat(PurpleConnection *connection,
-                                      PurpleChatConversation *chat)
-{
-	PurpleConnectionPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_CONNECTION(connection));
-
-	priv = purple_connection_get_instance_private(connection);
-
-	priv->active_chats = g_slist_remove(priv->active_chats, chat);
-}
-
 gboolean
 _purple_connection_wants_to_die(PurpleConnection *connection) {
 	PurpleConnectionPrivate *priv = NULL;
@@ -879,9 +852,6 @@
 	                            PURPLE_CONNECTION_STATE_DISCONNECTING);
 	purple_signal_emit(handle, "signing-off", connection);
 
-	g_slist_free_full(priv->active_chats,
-	                  (GDestroyNotify)purple_chat_conversation_leave);
-
 	/* Dispatch to the connection's disconnect method. */
 	klass = PURPLE_CONNECTION_GET_CLASS(connection);
 	if(klass != NULL && klass->disconnect != NULL) {
diff --git a/libpurple/contact.c b/libpurple/contact.c
--- a/libpurple/contact.c
+++ b/libpurple/contact.c
@@ -23,6 +23,7 @@
 #include "contact.h"
 #include "prefs.h"
 #include "purpleconversationmanager.h"
+#include "purpleimconversation.h"
 #include "purpleprivate.h"
 #include "util.h"
 
diff --git a/libpurple/conversations.h b/libpurple/conversations.h
--- a/libpurple/conversations.h
+++ b/libpurple/conversations.h
@@ -37,29 +37,6 @@
 /**************************************************************************/
 
 /**
- * purple_conversations_set_ui_ops:
- * @ops:  The UI conversation operations structure.
- *
- * Sets the default conversation UI operations structure.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_conversations_set_ui_ops(PurpleConversationUiOps *ops);
-
-/**
- * purple_conversations_get_ui_ops:
- *
- * Gets the default conversation UI operations structure.
- *
- * Returns:  The UI conversation operations structure.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-PurpleConversationUiOps *purple_conversations_get_ui_ops(void);
-
-/**
  * purple_conversations_get_handle:
  *
  * Returns the conversation subsystem handle.
diff --git a/libpurple/conversations.c b/libpurple/conversations.c
--- a/libpurple/conversations.c
+++ b/libpurple/conversations.c
@@ -24,22 +24,10 @@
 
 #include "prefs.h"
 #include "purpleprivate.h"
+#include "purplechatconversation.h"
+#include "purpleimconversation.h"
 #include "purpleconversationmanager.h"
 
-static PurpleConversationUiOps *default_ops = NULL;
-
-void
-purple_conversations_set_ui_ops(PurpleConversationUiOps *ops)
-{
-	default_ops = ops;
-}
-
-PurpleConversationUiOps *
-purple_conversations_get_ui_ops(void)
-{
-	return default_ops;
-}
-
 void *
 purple_conversations_get_handle(void)
 {
diff --git a/libpurple/meson.build b/libpurple/meson.build
--- a/libpurple/meson.build
+++ b/libpurple/meson.build
@@ -46,7 +46,6 @@
 	'purpleconversation.c',
 	'purpleconversationmanager.c',
 	'purpleconversationmember.c',
-	'purpleconversationuiops.c',
 	'purplecreateconversationdetails.c',
 	'purplecredentialmanager.c',
 	'purplecredentialprovider.c',
@@ -162,7 +161,6 @@
 	'purpleconversation.h',
 	'purpleconversationmanager.h',
 	'purpleconversationmember.h',
-	'purpleconversationuiops.h',
 	'purplecreateconversationdetails.h',
 	'purplecredentialmanager.h',
 	'purplecredentialprovider.h',
diff --git a/libpurple/purplechatconversation.h b/libpurple/purplechatconversation.h
--- a/libpurple/purplechatconversation.h
+++ b/libpurple/purplechatconversation.h
@@ -319,7 +319,6 @@
  * @chat: The chat.
  *
  * Lets the core know we left a chat, without destroying it.
- * Called from purple_serv_got_chat_left().
  *
  * Since: 3.0
  */
diff --git a/libpurple/purplechatconversation.c b/libpurple/purplechatconversation.c
--- a/libpurple/purplechatconversation.c
+++ b/libpurple/purplechatconversation.c
@@ -226,14 +226,6 @@
 		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_clear_pointer(&priv->users, g_hash_table_destroy);
@@ -478,7 +470,6 @@
                                    gboolean new_arrivals)
 {
 	PurpleConversation *conv;
-	PurpleConversationUiOps *ops;
 	PurpleChatUser *chatuser;
 	PurpleChatConversationPrivate *priv;
 	PurpleAccount *account;
@@ -492,7 +483,6 @@
 
 	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);
@@ -578,10 +568,6 @@
 
 	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);
 }
 
@@ -591,7 +577,6 @@
                                      const gchar *new_user)
 {
 	PurpleConversation *conv;
-	PurpleConversationUiOps *ops;
 	PurpleAccount *account;
 	PurpleConnection *gc;
 	PurpleProtocol *protocol;
@@ -609,7 +594,6 @@
 
 	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);
@@ -648,10 +632,6 @@
 	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));
@@ -716,7 +696,6 @@
 	PurpleConversation *conv;
 	PurpleConnection *gc;
 	PurpleProtocol *protocol;
-	PurpleConversationUiOps *ops;
 	PurpleChatUser *cb;
 	PurpleChatConversationPrivate *priv;
 	GList *l;
@@ -735,7 +714,6 @@
 	protocol = purple_connection_get_protocol(gc);
 	g_return_if_fail(PURPLE_IS_PROTOCOL(protocol));
 
-	ops = purple_conversation_get_ui_ops(conv);
 	handle = purple_conversations_get_handle();
 
 	for(l = users; l != NULL; l = l->next) {
@@ -784,28 +762,18 @@
 
 		g_signal_emit(chat, signals[SIG_USER_LEFT], 0, 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 = NULL;
 	GList *names = NULL;
 
 	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));
 	names = g_hash_table_get_keys(priv->users);
 
-	if(ops != NULL && ops->chat_remove_users != NULL) {
-		ops->chat_remove_users(chat, names);
-	}
-
 	g_list_foreach(names, purple_chat_conversation_clear_users_helper, chat);
 
 	g_list_free(names);
diff --git a/libpurple/purplechatuser.c b/libpurple/purplechatuser.c
--- a/libpurple/purplechatuser.c
+++ b/libpurple/purplechatuser.c
@@ -268,7 +268,6 @@
 purple_chat_user_set_flags(PurpleChatUser *chat_user,
                            PurpleChatUserFlags flags)
 {
-	PurpleConversationUiOps *ops;
 	PurpleChatUserFlags oldflags;
 
 	g_return_if_fail(PURPLE_IS_CHAT_USER(chat_user));
@@ -282,17 +281,6 @@
 
 	g_object_notify_by_pspec(G_OBJECT(chat_user), properties[PROP_FLAGS]);
 
-	/* Only update the UI once the object is fully constructed.  This avoids an
-	 * issue where at least with XMPP, user names will be duplicated in the
-	 * chat user list.
-	 */
-	if(chat_user->constructed) {
-		ops = purple_conversation_get_ui_ops(PURPLE_CONVERSATION(chat_user->chat));
-		if(ops != NULL && ops->chat_update_user != NULL) {
-			ops->chat_update_user(chat_user);
-		}
-	}
-
 	purple_signal_emit(purple_conversations_get_handle(),
 	                   "chat-user-flags", chat_user, oldflags, flags);
 }
diff --git a/libpurple/purpleconversation.h b/libpurple/purpleconversation.h
--- a/libpurple/purpleconversation.h
+++ b/libpurple/purpleconversation.h
@@ -157,7 +157,6 @@
 
 #include "buddyicon.h"
 #include "purpleaccount.h"
-#include "purpleconversationuiops.h"
 
 G_BEGIN_DECLS
 
@@ -238,31 +237,6 @@
 void purple_conversation_present(PurpleConversation *conv);
 
 /**
- * purple_conversation_set_ui_ops:
- * @conv: The conversation.
- * @ops:  The UI conversation operations structure.
- *
- * Sets the specified conversation's UI operations structure.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_conversation_set_ui_ops(PurpleConversation *conv, PurpleConversationUiOps *ops);
-
-/**
- * purple_conversation_get_ui_ops:
- * @conv: The conversation.
- *
- * Returns the specified conversation's UI operations structure.
- *
- * Returns: The operations structure.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleConversationUiOps *purple_conversation_get_ui_ops(PurpleConversation *conv);
-
-/**
  * purple_conversation_get_id:
  * @conversation: The instance.
  *
diff --git a/libpurple/purpleconversation.c b/libpurple/purpleconversation.c
--- a/libpurple/purpleconversation.c
+++ b/libpurple/purpleconversation.c
@@ -27,6 +27,7 @@
 #include "conversations.h"
 #include "debug.h"
 #include "notify.h"
+#include "purplechatconversation.h"
 #include "purpleconversationmanager.h"
 #include "purpleconversationmember.h"
 #include "purpleenums.h"
@@ -46,8 +47,6 @@
 	char *name;
 	char *title;
 
-	PurpleConversationUiOps *ui_ops;
-
 	PurpleConnectionFlags features;
 
 	gboolean age_restricted;
@@ -573,7 +572,6 @@
 	PurpleConversation *conv = PURPLE_CONVERSATION(object);
 	PurpleAccount *account;
 	PurpleConnection *gc;
-	PurpleConversationUiOps *ops;
 
 	G_OBJECT_CLASS(purple_conversation_parent_class)->constructed(object);
 
@@ -591,16 +589,6 @@
 	/* Auto-set the title. */
 	purple_conversation_autoset_title(conv);
 
-	/* Don't move this.. it needs to be one of the last things done otherwise
-	 * it causes mysterious crashes on my system.
-	 *  -- Gary
-	 */
-	ops  = purple_conversations_get_ui_ops();
-	purple_conversation_set_ui_ops(conv, ops);
-	if(ops != NULL && ops->create_conversation != NULL) {
-		ops->create_conversation(conv);
-	}
-
 	purple_signal_emit(purple_conversations_get_handle(),
 	                   "conversation-created", conv);
 
@@ -617,17 +605,12 @@
 	PurpleConversation *conv = PURPLE_CONVERSATION(object);
 	PurpleConversationPrivate *priv =
 			purple_conversation_get_instance_private(conv);
-	PurpleConversationUiOps *ops  = purple_conversation_get_ui_ops(conv);
 
 	purple_request_close_with_handle(conv);
 
 	purple_signal_emit(purple_conversations_get_handle(),
 	                   "deleting-conversation", conv);
 
-	if(ops != NULL && ops->destroy_conversation != NULL) {
-		ops->destroy_conversation(conv);
-	}
-
 	g_clear_pointer(&priv->id, g_free);
 	g_clear_object(&priv->avatar);
 	g_clear_pointer(&priv->name, g_free);
@@ -1080,15 +1063,7 @@
 }
 
 void
-purple_conversation_present(PurpleConversation *conv) {
-	PurpleConversationUiOps *ops;
-
-	g_return_if_fail(PURPLE_IS_CONVERSATION(conv));
-
-	ops = purple_conversation_get_ui_ops(conv);
-	if(ops && ops->present) {
-		ops->present(conv);
-	}
+purple_conversation_present(G_GNUC_UNUSED PurpleConversation *conv) {
 }
 
 void
@@ -1118,38 +1093,6 @@
 	return priv->features;
 }
 
-void
-purple_conversation_set_ui_ops(PurpleConversation *conv,
-                               PurpleConversationUiOps *ops)
-{
-	PurpleConversationPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_CONVERSATION(conv));
-
-	priv = purple_conversation_get_instance_private(conv);
-
-	if(priv->ui_ops == ops) {
-		return;
-	}
-
-	if(priv->ui_ops != NULL && priv->ui_ops->destroy_conversation != NULL) {
-		priv->ui_ops->destroy_conversation(conv);
-	}
-
-	priv->ui_ops = ops;
-}
-
-PurpleConversationUiOps *
-purple_conversation_get_ui_ops(PurpleConversation *conv) {
-	PurpleConversationPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv), NULL);
-
-	priv = purple_conversation_get_instance_private(conv);
-
-	return priv->ui_ops;
-}
-
 const char *
 purple_conversation_get_id(PurpleConversation *conversation) {
 	PurpleConversationPrivate *priv = NULL;
@@ -1310,7 +1253,6 @@
 	PurpleConnection *gc = NULL;
 	PurpleConversationPrivate *priv = NULL;
 	PurpleAccount *account;
-	PurpleConversationUiOps *ops;
 	PurpleBuddy *b;
 	gint plugin_return;
 	/* int logging_font_options = 0; */
@@ -1320,19 +1262,13 @@
 
 	priv = purple_conversation_get_instance_private(conv);
 
-	ops = purple_conversation_get_ui_ops(conv);
-
 	account = purple_conversation_get_account(conv);
 
 	if(account != NULL) {
 		gc = purple_account_get_connection(account);
 	}
 
-	if(PURPLE_IS_CHAT_CONVERSATION(conv) && gc != NULL) {
-		if(!g_slist_find(purple_connection_get_active_chats(gc), conv)) {
-			return;
-		}
-	} else if(PURPLE_IS_IM_CONVERSATION(conv)) {
+	if(PURPLE_IS_IM_CONVERSATION(conv)) {
 		PurpleConversationManager *manager = NULL;
 
 		manager = purple_conversation_manager_get_default();
@@ -1398,16 +1334,6 @@
 
 	g_list_store_append(priv->messages, pmsg);
 
-	if(ops) {
-		if (PURPLE_IS_CHAT_CONVERSATION(conv) && ops->write_chat) {
-			ops->write_chat(PURPLE_CHAT_CONVERSATION(conv), pmsg);
-		} else if (PURPLE_IS_IM_CONVERSATION(conv) && ops->write_im) {
-			ops->write_im(PURPLE_IM_CONVERSATION(conv), pmsg);
-		} else if (ops->write_conv) {
-			ops->write_conv(conv, pmsg);
-		}
-	}
-
 	purple_signal_emit(purple_conversations_get_handle(),
 		(PURPLE_IS_IM_CONVERSATION(conv) ? "wrote-im-msg" : "wrote-chat-msg"),
 		conv, pmsg);
@@ -1459,16 +1385,9 @@
 gboolean
 purple_conversation_has_focus(PurpleConversation *conv) {
 	gboolean ret = FALSE;
-	PurpleConversationUiOps *ops;
 
 	g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv), FALSE);
 
-	ops = purple_conversation_get_ui_ops(conv);
-
-	if(ops != NULL && ops->has_focus != NULL) {
-		ret = ops->has_focus(conv);
-	}
-
 	return ret;
 }
 
@@ -1514,19 +1433,12 @@
 purple_conversation_send_confirm(PurpleConversation *conv,
                                  const gchar *message)
 {
-	PurpleConversationPrivate *priv = NULL;
 	gchar *text;
 	gpointer *data;
 
 	g_return_if_fail(PURPLE_IS_CONVERSATION(conv));
 	g_return_if_fail(message != NULL);
 
-	priv = purple_conversation_get_instance_private(conv);
-	if(priv->ui_ops != NULL && priv->ui_ops->send_confirm != NULL) {
-		priv->ui_ops->send_confirm(conv, message);
-		return;
-	}
-
 	text = g_strdup_printf("You are about to send the following message:\n%s",
 	                       message);
 	data = g_new0(gpointer, 2);
diff --git a/libpurple/purpleconversationuiops.h b/libpurple/purpleconversationuiops.h
deleted file mode 100644
--- a/libpurple/purpleconversationuiops.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Purple - Internet Messaging Library
- * Copyright (C) Pidgin Developers <devel@pidgin.im>
- *
- * 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 library 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 library 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 library; if not, see <https://www.gnu.org/licenses/>.
- */
-
-#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION)
-# error "only <purple.h> may be included directly"
-#endif
-
-#ifndef PURPLE_CONVERSATION_UI_OPS_H
-#define PURPLE_CONVERSATION_UI_OPS_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#define PURPLE_TYPE_CONVERSATION_UI_OPS (purple_conversation_ui_ops_get_type())
-typedef struct _PurpleConversationUiOps PurpleConversationUiOps;
-
-#include "purplechatconversation.h"
-#include "purpleconversation.h"
-#include "purpleimconversation.h"
-#include "purplemessage.h"
-
-/**
- * PurpleConversationUiOps:
- * @create_conversation: Called when @conv is created (but before the
- *   <link linkend="conversations-conversation-created"><literal>"conversation-created"</literal></link>
- *                       signal is emitted).
- * @destroy_conversation: Called just before @conv is freed.
- * @write_chat: Write a message to a chat. If this field is %NULL, libpurple
- *              will fall back to using @write_conv.
- *              See purple_conversation_write_message().
- * @write_im: Write a message to an IM conversation. If this field is %NULL,
- *            libpurple will fall back to using @write_conv.
- *            See purple_conversation_write_message().
- * @write_conv: Write a message to a conversation. This is used rather than the
- *              chat- or im-specific ops for errors, system messages (such as "x
- *              is now know as y"), and as the fallback if @write_im and
- *              @write_chat are not implemented. It should be implemented, or
- *              the UI will miss conversation error messages and your users will
- *              hate you. See purple_conversation_write_message().
- * @chat_add_users: Add @cbuddies to a chat.
- *                  <sbr/>@cbuddies:     A GList of #PurpleChatUser structs.
- *                  <sbr/>@new_arrivals: Whether join notices should be shown.
- *                                       (Join notices are actually written to
- *                                       the conversation by
- *                                       purple_chat_conversation_add_users())
- * @chat_rename_user: Rename the user in this chat named @old_name to @new_name.
- *                    (The rename message is written to the conversation by
- *                    libpurple.) See purple_chat_conversation_rename_user().
- *                    <sbr/>@new_alias: @new_name's new alias, if they have one.
- * @chat_remove_users: Remove @users from a chat @chat.
- *                     See purple_chat_conversation_remove_users().
- * @chat_update_user: Called when a user's flags are changed.
- *                    See purple_chat_user_set_flags().
- * @present: Present this conversation to the user; for example, by displaying
- *           the IM dialog.
- * @has_focus: If this UI has a concept of focus (as in a windowing system) and
- *             this conversation has the focus, return %TRUE; otherwise, return
- *             %FALSE.
- * @send_confirm: Prompt the user for confirmation to send @message. This
- *                function should arrange for the message to be sent if the user
- *                accepts. If this field is %NULL, libpurple will fall back to
- *                using purple_request_action().
- *
- * libpurple needs to tell the user interface when certain things happen in a
- * conversation and it uses this structure to do so.
- *
- * Any UI representing a conversation must assign a filled-out
- * #PurpleConversationUiOps structure to the #PurpleConversation.
- */
-struct _PurpleConversationUiOps
-{
-	void (*create_conversation)(PurpleConversation *conv);
-	void (*destroy_conversation)(PurpleConversation *conv);
-
-	void (*write_chat)(PurpleChatConversation *chat, PurpleMessage *msg);
-	void (*write_im)(PurpleIMConversation *im, PurpleMessage *msg);
-	void (*write_conv)(PurpleConversation *conv, PurpleMessage *msg);
-
-	void (*chat_add_users)(PurpleChatConversation *chat,
-	                       GList *cbuddies,
-	                       gboolean new_arrivals);
-
-	void (*chat_rename_user)(PurpleChatConversation *chat, const char *old_name,
-	                         const char *new_name, const char *new_alias);
-
-	void (*chat_remove_users)(PurpleChatConversation *chat, GList *users);
-
-	void (*chat_update_user)(PurpleChatUser *cb);
-
-	void (*present)(PurpleConversation *conv);
-	gboolean (*has_focus)(PurpleConversation *conv);
-
-	void (*send_confirm)(PurpleConversation *conv, const char *message);
-
-	/*< private >*/
-	void (*_purple_reserved1)(void);
-	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
-};
-
-G_BEGIN_DECLS
-
-/**
- * purple_conversation_ui_ops_get_type:
- *
- * Returns: The #GType for the #PurpleConversationUiOps boxed structure.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-GType purple_conversation_ui_ops_get_type(void);
-
-G_END_DECLS
-
-#endif /* PURPLE_CONVERSATION_UI_OPS_H */
diff --git a/libpurple/purpleconversationuiops.c b/libpurple/purpleconversationuiops.c
deleted file mode 100644
--- a/libpurple/purpleconversationuiops.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Purple - Internet Messaging Library
- * Copyright (C) Pidgin Developers <devel@pidgin.im>
- *
- * 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 library 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 library 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 library; if not, see <https://www.gnu.org/licenses/>.
- */
-
-#include <glib/gi18n-lib.h>
-
-#include "purpleconversationuiops.h"
-
-/******************************************************************************
- * Helpers
- *****************************************************************************/
-static PurpleConversationUiOps *
-purple_conversation_ui_ops_copy(PurpleConversationUiOps *ops)
-{
-	PurpleConversationUiOps *ops_new;
-
-	g_return_val_if_fail(ops != NULL, NULL);
-
-	ops_new = g_new(PurpleConversationUiOps, 1);
-	*ops_new = *ops;
-
-	return ops_new;
-}
-
-/******************************************************************************
- * Public API
- *****************************************************************************/
-GType
-purple_conversation_ui_ops_get_type(void)
-{
-	static GType type = 0;
-
-	if (type == 0) {
-		type = g_boxed_type_register_static("PurpleConversationUiOps",
-				(GBoxedCopyFunc)purple_conversation_ui_ops_copy,
-				(GBoxedFreeFunc)g_free);
-	}
-
-	return type;
-}
diff --git a/libpurple/purpleprivate.h b/libpurple/purpleprivate.h
--- a/libpurple/purpleprivate.h
+++ b/libpurple/purpleprivate.h
@@ -83,19 +83,6 @@
 gboolean _purple_connection_wants_to_die(PurpleConnection *gc);
 
 /**
- * _purple_connection_remove_active_chat:
- * @gc:    The connection
- * @chat:  The chat conversation to remove
- *
- * Removes a chat from the active chats list of a connection
- *
- * Note: This function should only be called by purple_serv_got_chat_left()
- *       in server.c.
- */
-G_GNUC_INTERNAL
-void _purple_connection_remove_active_chat(PurpleConnection *gc, PurpleChatConversation *chat);
-
-/**
  * _purple_statuses_get_primitive_scores:
  *
  * Note: This function should only be called by
diff --git a/libpurple/purpleprotocolim.h b/libpurple/purpleprotocolim.h
--- a/libpurple/purpleprotocolim.h
+++ b/libpurple/purpleprotocolim.h
@@ -30,8 +30,6 @@
 #include <glib.h>
 #include <glib-object.h>
 
-#include "connection.h"
-#include "purpleconversation.h"
 #include "purpleprotocol.h"
 #include "purpleversion.h"
 
@@ -49,6 +47,10 @@
 G_DECLARE_INTERFACE(PurpleProtocolIM, purple_protocol_im, PURPLE, PROTOCOL_IM,
                     PurpleProtocol)
 
+#include "connection.h"
+#include "purpleconversation.h"
+#include "purpleimconversation.h"
+
 struct _PurpleProtocolIMInterface {
 	/*< private >*/
 	GTypeInterface parent;
diff --git a/libpurple/server.h b/libpurple/server.h
--- a/libpurple/server.h
+++ b/libpurple/server.h
@@ -171,18 +171,6 @@
 PURPLE_AVAILABLE_IN_3_0
 void purple_serv_join_chat(PurpleConnection *gc, GHashTable *data);
 
-/**
- * purple_serv_got_chat_left:
- * @g:  The connection on which the chat was left.
- * @id: The id of the chat, as assigned by the protocol.
- *
- * Called by a protocol when an account has left a chat.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_serv_got_chat_left(PurpleConnection *g, int id);
-
 G_END_DECLS
 
 #endif /* PURPLE_SERVER_H */
diff --git a/libpurple/server.c b/libpurple/server.c
--- a/libpurple/server.c
+++ b/libpurple/server.c
@@ -282,29 +282,3 @@
 
 	g_free(name);
 }
-
-void purple_serv_got_chat_left(PurpleConnection *g, int id)
-{
-	GSList *bcs;
-	PurpleChatConversation *chat = NULL;
-
-	for (bcs = purple_connection_get_active_chats(g); bcs != NULL; bcs = bcs->next) {
-		if (purple_chat_conversation_get_id(
-				PURPLE_CHAT_CONVERSATION(bcs->data)) == id) {
-			chat = (PurpleChatConversation *)bcs->data;
-			break;
-		}
-	}
-
-	if (!chat)
-		return;
-
-	purple_debug_info("server", "Leaving room: %s",
-	                  purple_conversation_get_name(PURPLE_CONVERSATION(chat)));
-
-	_purple_connection_remove_active_chat(g, chat);
-
-	purple_chat_conversation_leave(chat);
-
-	purple_signal_emit(purple_conversations_get_handle(), "chat-left", chat);
-}
diff --git a/libpurple/tests/test_ui.c b/libpurple/tests/test_ui.c
--- a/libpurple/tests/test_ui.c
+++ b/libpurple/tests/test_ui.c
@@ -40,25 +40,6 @@
 
 #include "test_ui.h"
 
-/*** Conversation uiops ***/
-static void
-test_write_conv(PurpleConversation *conv, PurpleMessage *msg)
-{
-	gchar *timestamp = purple_message_format_timestamp(msg, "(%H:%M:%S)");
-
-	printf("(%s) %s %s: %s\n",
-		purple_conversation_get_name(conv),
-		timestamp,
-		purple_message_get_author_alias(msg),
-		purple_message_get_contents(msg));
-
-	g_free(timestamp);
-}
-
-static PurpleConversationUiOps test_conv_uiops = {
-	.write_conv = test_write_conv
-};
-
 /******************************************************************************
  * PurpleUi Implementation
  *****************************************************************************/
@@ -72,8 +53,6 @@
 
 static gboolean
 test_purple_ui_start(G_GNUC_UNUSED PurpleUi *ui, G_GNUC_UNUSED GError **error) {
-	purple_conversations_set_ui_ops(&test_conv_uiops);
-
 	return TRUE;
 }
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -48,7 +48,6 @@
 libpurple/purplecontact.c
 libpurple/purpleconversation.c
 libpurple/purpleconversationmanager.c
-libpurple/purpleconversationuiops.c
 libpurple/purplecredentialmanager.c
 libpurple/purplecredentialprovider.c
 libpurple/purpledebugui.c
