# HG changeset patch
# Node ID 91204fad1b54
# Parent  ffc82edcdbfe
diff --git a/ChangeLog.API b/ChangeLog.API
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -248,6 +248,7 @@
 		  instead.
 		* account-setting-info, account-set-info signals
 		* account-status-changing signal.
+		* buddy-status-changed signal.
 		* chat-topic-changed signal.
 		* file-recv-accept, file-recv-cancel, file-recv-complete,
 		  file-recv-start, file-send-accept, file-send-cancel,
@@ -273,6 +274,7 @@
 		* purple_account_add_buddies_with_invite
 		* purple_account_add_buddy_with_invite
 		* purple_account_destroy_log
+		* purple_account_get_active_status
 		* purple_account_get_check_mail
 		* purple_account_get_log
 		* purple_account_get_name_for_display. Use
@@ -284,11 +286,16 @@
 		* purple_account_get_private_alias. Use purple_contact_get_alias
 		  instead.
 		* purple_account_get_silence_suppression
+		* purple_account_get_status
+		* purple_account_get_status_type
+		* purple_account_get_status_type_with_primitive
+		* purple_account_get_status_types
 		* purple_account_get_ui_int
 		* purple_account_get_ui_string
 		* purple_account_get_ui_bool
 		* purple_account_get_username. Use purple_contact_info_get_username
 		  instead.
+		* purple_account_is_status_active
 		* purple_account_notify_added
 		* purple_account_privacy_allow
 		* purple_account_privacy_check
@@ -313,11 +320,15 @@
 		  instead.
 		* purple_account_set_public_alias
 		* purple_account_set_silence_suppression
+		* purple_account_set_status
+		* purple_account_set_status_attrs
+		* purple_account_set_status_types
 		* purple_account_set_ui_int
 		* purple_account_set_ui_string
 		* purple_account_set_ui_bool
 		* purple_account_set_username. Use purple_contact_info_set_username
 		  instead.
+		* account-status-changed signal
 		* purple_accounts_add
 		* purple_accounts_find
 		* purple_accounts_get_all
@@ -605,6 +616,12 @@
 		* PurplePounceEvent
 		* PurplePounceOption
 		* PurplePrefsUiOps
+		* purple_presence_get_status
+		* purple_presence_get_statuses
+		* purple_presence_is_status_active
+		* purple_presence_is_status_primitive_active
+		* purple_presence_set_status_active
+		* purple_presence_switch_status
 		* purple_protocol_got_account_actions
 		* purple_protocol_got_account_idle
 		* purple_protocol_got_account_status
diff --git a/doc/reference/libpurple/libpurple.toml.in b/doc/reference/libpurple/libpurple.toml.in
--- a/doc/reference/libpurple/libpurple.toml.in
+++ b/doc/reference/libpurple/libpurple.toml.in
@@ -47,7 +47,6 @@
 	"signals_conversation.md",
 	"signals_core.md",
 	"signals_jabber.md",
-	"signals_savedstatus.md",
 	"tut_c_plugins.md",
 ]
 content_images = [
diff --git a/doc/reference/libpurple/meson.build b/doc/reference/libpurple/meson.build
--- a/doc/reference/libpurple/meson.build
+++ b/doc/reference/libpurple/meson.build
@@ -8,8 +8,6 @@
 	'signals_connection.md',
 	'signals_conversation.md',
 	'signals_core.md',
-	'signals_jabber.md',
-	'signals_savedstatus.md',
 	'tut_c_plugins.md',
 ]
 
diff --git a/doc/reference/libpurple/signals_account.md b/doc/reference/libpurple/signals_account.md
--- a/doc/reference/libpurple/signals_account.md
+++ b/doc/reference/libpurple/signals_account.md
@@ -5,7 +5,6 @@
 
 ### Signal List
 
-* [account-status-changed](#account-status-changed)
 * [account-signed-on](#account-signed-on)
 * [account-signed-off](#account-signed-off)
 
@@ -47,33 +46,6 @@
 
 ----
 
-#### account-status-changed
-
-```c
-void user_function(PurpleAccount *account,
-                   PurpleStatus *old,
-                   PurpleStatus *new,
-                   gpointer user_data);
-```
-
-Emitted when the status of an account changes (after the change).
-
-**Parameters:**
-
-**account**
-: The account that changed status.
-
-**old**
-: The status before change.
-
-**new**
-: The status after change.
-
-**user_data**
-: User data set when the signal handler was connected.
-
-----
-
 #### account-signed-on
 
 ```c
diff --git a/doc/reference/libpurple/signals_blist.md b/doc/reference/libpurple/signals_blist.md
--- a/doc/reference/libpurple/signals_blist.md
+++ b/doc/reference/libpurple/signals_blist.md
@@ -5,7 +5,6 @@
 
 ### Signal List
 
-* [buddy-status-changed](#buddy-status-changed)
 * [buddy-idle-changed](#buddy-idle-changed)
 * [buddy-signed-on](#buddy-signed-on)
 * [buddy-signed-off](#buddy-signed-off)
@@ -18,33 +17,6 @@
 
 ### Signal Details
 
-#### buddy-status-changed
-
-```c
-void user_function(PurpleBuddy *buddy,
-                   PurpleStatus *old_status,
-                   PurpleStatus *status,
-                   gpointer user_data);
-```
-
-Emitted when a buddy on your buddy list goes away.
-
-**Parameters:**
-
-**buddy**
-: The buddy whose status changed.
-
-**old_status**
-: The status that the buddy just changed from.
-
-**status**
-: The status that the buddy just changed to.
-
-**user_data**
-: user data set when the signal handler was connected.
-
-----
-
 #### buddy-idle-changed
 
 ```c
diff --git a/doc/reference/libpurple/signals_savedstatus.md b/doc/reference/libpurple/signals_savedstatus.md
deleted file mode 100644
--- a/doc/reference/libpurple/signals_savedstatus.md
+++ /dev/null
@@ -1,20 +0,0 @@
-Title: Saved Status Signals
-Slug: saved-status-signals
-
-## Saved Status Signals
-
-### Signal List
-
-* [savedstatus-changed](#savedstatus-changed)
-
-### Signal Details
-
-#### savedstatus-changed
-
-```c
-void user_function(PurpleSavedStatus *new,
-                   PurpleSavedStatus *old,
-                   gpointer user_data);
-```
-
-Emitted when a new saved status is activated.
diff --git a/libpurple/accounts.c b/libpurple/accounts.c
--- a/libpurple/accounts.c
+++ b/libpurple/accounts.c
@@ -625,11 +625,6 @@
 	void *handle = purple_accounts_get_handle();
 	void *conn_handle = purple_connections_get_handle();
 
-	purple_signal_register(handle, "account-status-changed",
-						 purple_marshal_VOID__POINTER_POINTER_POINTER,
-						 G_TYPE_NONE, 3, PURPLE_TYPE_ACCOUNT,
-						 PURPLE_TYPE_STATUS, PURPLE_TYPE_STATUS);
-
 	purple_signal_register(handle, "account-signed-on",
 	                       purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
 	                       PURPLE_TYPE_ACCOUNT);
diff --git a/libpurple/buddy.h b/libpurple/buddy.h
--- a/libpurple/buddy.h
+++ b/libpurple/buddy.h
@@ -46,7 +46,6 @@
 #include "purpleaccount.h"
 #include "purplepresence.h"
 #include "purpleversion.h"
-#include "status.h"
 
 /**
  * PURPLE_BUDDY_IS_ONLINE:
@@ -271,20 +270,6 @@
 PurplePresence *purple_buddy_get_presence(PurpleBuddy *buddy);
 
 /**
- * purple_buddy_update_status:
- * @buddy:      The buddy whose status has changed.
- * @old_status: The status from which we are changing.
- *
- * Updates a buddy's status.
- *
- * This should only be called from within Purple.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_buddy_update_status(PurpleBuddy *buddy, PurpleStatus *old_status);
-
-/**
  * purple_buddy_get_media_caps:
  * @buddy: The buddy.
  *
diff --git a/libpurple/buddy.c b/libpurple/buddy.c
--- a/libpurple/buddy.c
+++ b/libpurple/buddy.c
@@ -191,7 +191,8 @@
 	}
 
 	priv->presence = purple_presence_new();
-	purple_presence_set_status_active(priv->presence, "offline", TRUE);
+	purple_presence_set_primitive(priv->presence,
+	                              PURPLE_PRESENCE_PRIMITIVE_OFFLINE);
 
 	purple_blist_new_node(purple_blist_get_default(),
 	                      PURPLE_BLIST_NODE(buddy));
@@ -704,78 +705,6 @@
 	return priv->presence;
 }
 
-void
-purple_buddy_update_status(PurpleBuddy *buddy, PurpleStatus *old_status) {
-	PurpleBuddyList *blist = NULL;
-	PurpleBuddyPrivate *priv = NULL;
-	PurpleStatus *status = NULL;
-	gpointer handle = NULL;
-
-	gboolean old_online = FALSE, new_online = FALSE;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(buddy));
-
-	priv = purple_buddy_get_instance_private(buddy);
-	status = purple_presence_get_active_status(priv->presence);
-	blist = purple_blist_get_default();
-	handle = purple_blist_get_handle();
-
-	purple_debug_info("blistnodetypes", "Updating buddy status for %s (%s)\n",
-	                  priv->name,
-	                  purple_account_get_protocol_name(priv->account));
-
-	old_online = purple_status_is_online(old_status);
-	new_online = purple_status_is_online(status);
-
-	if(old_online != new_online) {
-		PurpleBlistNode *cnode = NULL, *gnode = NULL;
-		PurpleMetaContact *contact = NULL;
-		PurpleCountingNode *contact_counter = NULL, *group_counter = NULL;
-		gint delta = 0, limit = 0;
-
-		if(new_online) {
-			purple_signal_emit(handle, "buddy-signed-on", buddy);
-			delta = 1;
-			limit = 1;
-		} else {
-			purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), "last_seen",
-			                          time(NULL));
-
-			purple_signal_emit(handle, "buddy-signed-off", buddy);
-			delta = -1;
-			limit = 0;
-		}
-
-		cnode = purple_blist_node_get_parent(PURPLE_BLIST_NODE(buddy));
-		contact = PURPLE_META_CONTACT(cnode);
-		contact_counter = PURPLE_COUNTING_NODE(contact);
-		gnode = purple_blist_node_get_parent(cnode);
-		group_counter = PURPLE_COUNTING_NODE(gnode);
-
-		purple_counting_node_change_online_count(contact_counter, delta);
-		if(purple_counting_node_get_online_count(contact_counter) == limit) {
-			purple_counting_node_change_online_count(group_counter, delta);
-		}
-	} else {
-		purple_signal_emit(handle, "buddy-status-changed", buddy, old_status,
-		                   status);
-	}
-
-	/*
-	 * This function used to only call the following two functions if one of
-	 * the above signals had been triggered, but that's not good, because
-	 * if someone's away message changes and they don't go from away to back
-	 * to away then no signal is triggered.
-	 *
-	 * It's a safe assumption that SOMETHING called this function.  PROBABLY
-	 * because something, somewhere changed.  Calling the stuff below
-	 * certainly won't hurt anything.  Unless you're on a K6-2 300.
-	 */
-	purple_meta_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy));
-
-	purple_blist_update_node(blist, PURPLE_BLIST_NODE(buddy));
-}
-
 PurpleMediaCaps
 purple_buddy_get_media_caps(PurpleBuddy *buddy) {
 	PurpleBuddyPrivate *priv = NULL;
diff --git a/libpurple/buddylist.c b/libpurple/buddylist.c
--- a/libpurple/buddylist.c
+++ b/libpurple/buddylist.c
@@ -1912,7 +1912,8 @@
 
 	for (iter = list; iter; iter = iter->next)
 	{
-		purple_presence_set_status_active(iter->data, "offline", TRUE);
+		purple_presence_set_primitive(iter->data,
+		                              PURPLE_PRESENCE_PRIMITIVE_OFFLINE);
 	}
 	g_list_free(list);
 }
@@ -2084,10 +2085,6 @@
 	/* Set a default, which can't be done as a static initializer. */
 	buddy_list_type = PURPLE_TYPE_BUDDY_LIST;
 
-	purple_signal_register(handle, "buddy-status-changed",
-	                     purple_marshal_VOID__POINTER_POINTER_POINTER,
-	                     G_TYPE_NONE, 3, PURPLE_TYPE_BUDDY, PURPLE_TYPE_STATUS, 
-	                     PURPLE_TYPE_STATUS);
 	purple_signal_register(handle, "buddy-privacy-changed",
 	                     purple_marshal_VOID__POINTER, G_TYPE_NONE,
 	                     1, PURPLE_TYPE_BUDDY);
diff --git a/libpurple/connection.h b/libpurple/connection.h
--- a/libpurple/connection.h
+++ b/libpurple/connection.h
@@ -112,7 +112,6 @@
 #include "purpleaccount.h"
 #include "purpleconnectionerrorinfo.h"
 #include "purpleprotocol.h"
-#include "status.h"
 
 struct _PurpleConnectionClass {
 	/*< private >*/
diff --git a/libpurple/core.c b/libpurple/core.c
--- a/libpurple/core.c
+++ b/libpurple/core.c
@@ -44,9 +44,7 @@
 #include "purplepath.h"
 #include "purplepresencemanagerprivate.h"
 #include "purpleprivate.h"
-#include "savedstatuses.h"
 #include "signals.h"
-#include "status.h"
 #include "util.h"
 #ifdef _WIN32
 #include "win32/win32dep.h"
@@ -149,17 +147,15 @@
 	 */
 	purple_plugins_init();
 
-	/* Accounts use status, buddy icons and connection signals, so
-	 * initialize these before accounts
+	/* Accounts buddy icons and connection signals, so initialize these before
+	 * accounts.
 	 */
-	purple_statuses_init();
 	purple_buddy_icons_init();
 	purple_connections_init();
 
 	purple_account_manager_startup();
 	purple_accounts_init();
 	purple_contact_manager_startup();
-	purple_savedstatuses_init();
 	purple_presence_manager_startup();
 	purple_notify_init();
 	purple_conversations_init();
@@ -241,8 +237,6 @@
 	purple_connections_uninit();
 	purple_buddy_icons_uninit();
 	purple_presence_manager_shutdown();
-	purple_savedstatuses_uninit();
-	purple_statuses_uninit();
 	purple_accounts_uninit();
 	purple_proxy_uninit();
 	purple_network_uninit();
diff --git a/libpurple/meson.build b/libpurple/meson.build
--- a/libpurple/meson.build
+++ b/libpurple/meson.build
@@ -112,10 +112,8 @@
 	'request/purplerequestpage.c',
 	'request-datasheet.c',
 	'roomlist.c',
-	'savedstatuses.c',
 	'server.c',
 	'signals.c',
-	'status.c',
 	'util.c',
 	'xmlnode.c'
 ]
@@ -221,10 +219,8 @@
 	'request.h',
 	'request-datasheet.h',
 	'roomlist.h',
-	'savedstatuses.h',
 	'server.h',
 	'signals.h',
-	'status.h',
 	'util.h',
 	'xmlnode.h',
 ]
@@ -312,7 +308,6 @@
 	'purpleproxyinfo.h',
 	'purpletyping.h',
 	'roomlist.h',
-	'status.h',
 	'xmlnode.h'
 ]
 
diff --git a/libpurple/purpleaccount.h b/libpurple/purpleaccount.h
--- a/libpurple/purpleaccount.h
+++ b/libpurple/purpleaccount.h
@@ -41,7 +41,6 @@
 #include "purpleprotocol.h"
 #include "purpleproxyinfo.h"
 #include "purpleversion.h"
-#include "status.h"
 
 G_BEGIN_DECLS
 
@@ -253,71 +252,6 @@
 void purple_account_set_proxy_info(PurpleAccount *account, PurpleProxyInfo *info);
 
 /**
- * purple_account_set_status_types:
- * @account: The account.
- * @status_types: (element-type PurpleStatusType): The list of status types.
- *
- * Sets the account's status types.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_account_set_status_types(PurpleAccount *account, GList *status_types);
-
-/**
- * purple_account_set_status:
- * @account: The account.
- * @status_id: The ID of the status.
- * @active: Whether @status_id is to be activated (%TRUE) or deactivated
- *          (%FALSE).
- * @...: A %NULL-terminated list of pairs of `const char *` attribute name
- *       followed by `const char *` attribute value for the status. (For
- *       example, one pair might be `"message"` followed by `"hello, talk to
- *       me!"`.)
- *
- * Activates or deactivates a status.
- *
- * All changes to the statuses of an account go through this function or
- * [method@Purple.Account.set_status_attrs].
- *
- * You can only deactivate an exclusive status by activating another exclusive
- * status. So, if @status_id is an exclusive status and @active is %FALSE, this
- * function does nothing.
- *
- * Variadic version of [method@Purple.Account.set_status_attrs].
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_account_set_status(PurpleAccount *account, const char *status_id, gboolean active, ...) G_GNUC_NULL_TERMINATED;
-
-
-/**
- * purple_account_set_status_attrs: (rename-to purple_account_set_status):
- * @account: The account.
- * @status_id: The ID of the status.
- * @active: Whether @status_id is to be activated (%TRUE) or deactivated
- *          (%FALSE).
- * @attrs: (element-type utf8 utf8): A hash table with keys of attribute
- *         names and values of attributes for the status. (For example, one
- *         pair might be a key of `"message"` with a value of `"hello, talk to
- *         me!"`.)
- *
- * Activates or deactivates a status.
- *
- * All changes to the statuses of an account go through this function or
- * [method@Purple.Account.set_status].
- *
- * You can only deactivate an exclusive status by activating another exclusive
- * status. So, if @status_id is an exclusive status and @active is %FALSE, this
- * function does nothing.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_account_set_status_attrs(PurpleAccount *account, const char *status_id, gboolean active, GHashTable *attrs);
-
-/**
  * purple_account_set_int:
  * @account: The account.
  * @name: The name of the setting.
@@ -514,67 +448,6 @@
 PurpleProxyInfo *purple_account_get_proxy_info(PurpleAccount *account);
 
 /**
- * purple_account_get_active_status:
- * @account: The account.
- *
- * Returns the active status for this account.  This looks through
- * the PurplePresence associated with this account and returns the
- * PurpleStatus that has its active flag set to "TRUE."  There can be
- * only one active PurpleStatus in a PurplePresence.
- *
- * Returns: (transfer none): The active status.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatus *purple_account_get_active_status(PurpleAccount *account);
-
-/**
- * purple_account_get_status:
- * @account: The account.
- * @status_id: The status ID.
- *
- * Returns the account status with the specified ID.
- *
- * Returns: (transfer none): The status, or %NULL if it was never registered.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatus *purple_account_get_status(PurpleAccount *account, const char *status_id);
-
-/**
- * purple_account_get_status_type:
- * @account: The account.
- * @id: The ID of the status type to find.
- *
- * Returns the account status type with the specified ID.
- *
- * Returns: The status type if found, or %NULL.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatusType *purple_account_get_status_type(PurpleAccount *account, const char *id);
-
-/**
- * purple_account_get_status_type_with_primitive:
- * @account: The account.
- * @primitive: The type of the status type to find.
- *
- * Returns the account status type with the specified primitive.
- * Note: It is possible for an account to have more than one
- * PurpleStatusType with the same primitive.  In this case, the
- * first PurpleStatusType is returned.
- *
- * Returns: The status if found, or %NULL.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatusType *purple_account_get_status_type_with_primitive(PurpleAccount *account, PurpleStatusPrimitive primitive);
-
-/**
  * purple_account_get_presence:
  * @account: The account.
  *
@@ -588,33 +461,6 @@
 PurplePresence *purple_account_get_presence(PurpleAccount *account);
 
 /**
- * purple_account_is_status_active:
- * @account: The account.
- * @status_id: The status ID.
- *
- * Returns whether or not an account status is active.
- *
- * Returns: TRUE if active, or FALSE if not.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_account_is_status_active(PurpleAccount *account, const char *status_id);
-
-/**
- * purple_account_get_status_types:
- * @account: The account.
- *
- * Returns the account's status types.
- *
- * Returns: (transfer none) (element-type PurpleStatusType): The account's status types.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-GList *purple_account_get_status_types(PurpleAccount *account);
-
-/**
  * purple_account_get_int:
  * @account: The account.
  * @name: The name of the setting.
diff --git a/libpurple/purpleaccount.c b/libpurple/purpleaccount.c
--- a/libpurple/purpleaccount.c
+++ b/libpurple/purpleaccount.c
@@ -74,8 +74,6 @@
 
 	PurpleProxyInfo *proxy_info;
 
-	GList *status_types;
-
 	PurplePresence *presence;
 
 	PurpleConnectionErrorInfo *error;
@@ -807,8 +805,6 @@
 
 	purple_account_free_notify_settings(account);
 
-	purple_account_set_status_types(account, NULL);
-
 	g_clear_object(&account->proxy_info);
 
 	g_clear_pointer(&account->error, purple_connection_error_info_free);
@@ -1419,65 +1415,6 @@
 }
 
 void
-purple_account_set_status_types(PurpleAccount *account, GList *status_types) {
-	g_return_if_fail(PURPLE_IS_ACCOUNT(account));
-
-	/* Out with the old... */
-	g_list_free_full(account->status_types,
-	                 (GDestroyNotify)purple_status_type_destroy);
-
-	/* In with the new... */
-	account->status_types = status_types;
-}
-
-void
-purple_account_set_status(PurpleAccount *account, const char *status_id,
-                          gboolean active, ...)
-{
-	GHashTable *attrs;
-	va_list args;
-
-	va_start(args, active);
-	attrs = purple_attrs_from_vargs(args);
-	purple_account_set_status_attrs(account, status_id, active, attrs);
-	g_hash_table_destroy(attrs);
-	va_end(args);
-}
-
-void
-purple_account_set_status_attrs(PurpleAccount *account, const char *status_id,
-                                gboolean active, GHashTable *attrs)
-{
-	PurpleStatus *status;
-
-	g_return_if_fail(PURPLE_IS_ACCOUNT(account));
-	g_return_if_fail(status_id != NULL);
-
-	status = purple_account_get_status(account, status_id);
-	if(status == NULL) {
-		PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
-
-		purple_debug_error("account",
-		                   "Invalid status ID '%s' for account %s (%s)\n",
-		                   status_id,
-		                   purple_contact_info_get_username(info),
-		                   purple_account_get_protocol_id(account));
-
-		return;
-	}
-
-	if(active || purple_status_is_independent(status)) {
-		purple_status_set_active_with_attributes(status, active, attrs);
-	}
-
-	/*
-	 * Our current statuses are saved to accounts.xml (so that when we
-	 * reconnect, we go back to the previous status).
-	 */
-	purple_accounts_schedule_save();
-}
-
-void
 purple_account_set_int(PurpleAccount *account, const char *name, int value) {
 	PurpleAccountSetting *setting;
 
@@ -1631,59 +1568,6 @@
 	return account->proxy_info;
 }
 
-PurpleStatus *
-purple_account_get_active_status(PurpleAccount *account) {
-	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
-
-	return purple_presence_get_active_status(account->presence);
-}
-
-PurpleStatus *
-purple_account_get_status(PurpleAccount *account, const char *status_id) {
-	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
-	g_return_val_if_fail(status_id != NULL, NULL);
-
-	return purple_presence_get_status(account->presence, status_id);
-}
-
-PurpleStatusType *
-purple_account_get_status_type(PurpleAccount *account, const char *id) {
-	GList *l;
-
-	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
-	g_return_val_if_fail(id != NULL, NULL);
-
-	for (l = purple_account_get_status_types(account); l != NULL; l = l->next)
-	{
-		PurpleStatusType *status_type = (PurpleStatusType *)l->data;
-
-		if(purple_strequal(purple_status_type_get_id(status_type), id)) {
-			return status_type;
-		}
-	}
-
-	return NULL;
-}
-
-PurpleStatusType *
-purple_account_get_status_type_with_primitive(PurpleAccount *account,
-                                              PurpleStatusPrimitive primitive)
-{
-	GList *l;
-
-	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
-
-	for(l = purple_account_get_status_types(account); l != NULL; l = l->next) {
-		PurpleStatusType *status_type = (PurpleStatusType *)l->data;
-
-		if(purple_status_type_get_primitive(status_type) == primitive) {
-			return status_type;
-		}
-	}
-
-	return NULL;
-}
-
 PurplePresence *
 purple_account_get_presence(PurpleAccount *account) {
 	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
@@ -1691,23 +1575,6 @@
 	return account->presence;
 }
 
-gboolean
-purple_account_is_status_active(PurpleAccount *account,
-                                const char *status_id)
-{
-	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
-	g_return_val_if_fail(status_id != NULL, FALSE);
-
-	return purple_presence_is_status_active(account->presence, status_id);
-}
-
-GList *
-purple_account_get_status_types(PurpleAccount *account) {
-	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
-
-	return account->status_types;
-}
-
 int
 purple_account_get_int(PurpleAccount *account, const char *name,
                        int default_value)
diff --git a/libpurple/purplepresence.h b/libpurple/purplepresence.h
--- a/libpurple/purplepresence.h
+++ b/libpurple/purplepresence.h
@@ -52,8 +52,6 @@
 
 typedef struct _PurplePresence PurplePresence;
 
-#include "status.h"
-
 /**
  * PurplePresencePrimitive:
  * @PURPLE_PRESENCE_PRIMITIVE_OFFLINE: The presence is offline or otherwise
@@ -131,38 +129,6 @@
 PurplePresence *purple_presence_new(void);
 
 /**
- * purple_presence_set_status_active:
- * @presence: The #PurplePresence instance.
- * @status_id: The ID of the status.
- * @active: The active state.
- *
- * Sets the active state of a status in a presence.
- *
- * Only independent statuses can be set inactive. Normal statuses can only
- * be set active, so if you wish to disable a status, set another
- * non-independent status to active, or use purple_presence_switch_status().
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_presence_set_status_active(PurplePresence *presence, const gchar *status_id, gboolean active);
-
-/**
- * purple_presence_switch_status:
- * @presence: The #PurplePresence instance.
- * @status_id: The status ID to switch to.
- *
- * Switches the active status in a presence.
- *
- * This is similar to purple_presence_set_status_active(), except it won't
- * activate independent statuses.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_presence_switch_status(PurplePresence *presence, const gchar *status_id);
-
-/**
  * purple_presence_set_idle:
  * @presence: The #PurplePresence instance.
  * @idle: The idle state.
@@ -190,46 +156,6 @@
 void purple_presence_set_login_time(PurplePresence *presence, GDateTime *login_time);
 
 /**
- * purple_presence_get_statuses:
- * @presence: The #PurplePresence instance.
- *
- * Gets a list of all the statuses in @presence.
- *
- * Returns: (element-type PurpleStatus) (transfer none): The statuses.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-GList *purple_presence_get_statuses(PurplePresence *presence);
-
-/**
- * purple_presence_get_status:
- * @presence: The #PurplePresence instance.
- * @status_id: The ID of the status.
- *
- * Gets the status with the specified ID from @presence.
- *
- * Returns: (transfer none): The #PurpleStatus if found, or %NULL.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatus *purple_presence_get_status(PurplePresence *presence, const gchar *status_id);
-
-/**
- * purple_presence_get_active_status:
- * @presence: The #PurplePresence instance.
- *
- * Gets the active exclusive status from @presence.
- *
- * Returns: (transfer none): The active exclusive status.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatus *purple_presence_get_active_status(PurplePresence *presence);
-
-/**
  * purple_presence_is_available:
  * @presence: The #PurplePresence instance.
  *
@@ -258,39 +184,6 @@
 gboolean purple_presence_is_online(PurplePresence *presence);
 
 /**
- * purple_presence_is_status_active:
- * @presence: The #PurplePresence instance.
- * @status_id: The ID of the status.
- *
- * Gets whether or not a status in @presence is active.
- *
- * A status is active if itself or any of its sub-statuses are active.
- *
- * Returns: %TRUE if the status is active, or %FALSE.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_presence_is_status_active(PurplePresence *presence, const gchar *status_id);
-
-/**
- * purple_presence_is_status_primitive_active:
- * @presence: The #PurplePresence instance.
- * @primitive: The status primitive.
- *
- * Gets whether or not a status with the specified primitive type in @presence
- * is active.
- *
- * A status is active if itself or any of its sub-statuses are active.
- *
- * Returns: %TRUE if the status is active, or %FALSE.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_presence_is_status_primitive_active(PurplePresence *presence, PurpleStatusPrimitive primitive);
-
-/**
  * purple_presence_is_idle:
  * @presence: The #PurplePresence instance.
  *
@@ -366,7 +259,7 @@
  * @presence: The instance.
  * @primitive: The new primitive.
  *
- * Sets the [enum@Purple.StatusPrimitive] for @presence to @primitive.
+ * Sets the [enum@Purple.PresencePrimitive] for @presence to @primitive.
  *
  * Since: 3.0
  */
diff --git a/libpurple/purplepresence.c b/libpurple/purplepresence.c
--- a/libpurple/purplepresence.c
+++ b/libpurple/purplepresence.c
@@ -33,10 +33,6 @@
 	GDateTime *idle_time;
 	GDateTime *login_time;
 
-	GHashTable *status_table;
-
-	PurpleStatus *active_status;
-
 	PurplePresencePrimitive primitive;
 	char *message;
 	char *emoji;
@@ -49,7 +45,6 @@
 	PROP_IDLE,
 	PROP_IDLE_TIME,
 	PROP_LOGIN_TIME,
-	PROP_ACTIVE_STATUS,
 	PROP_PRIMITIVE,
 	PROP_MESSAGE,
 	PROP_EMOJI,
@@ -62,28 +57,6 @@
 G_DEFINE_TYPE_WITH_PRIVATE(PurplePresence, purple_presence, G_TYPE_OBJECT)
 
 /******************************************************************************
- * Helpers
- *****************************************************************************/
-static void
-purple_presence_set_active_status(PurplePresence *presence,
-                                  PurpleStatus *status)
-{
-	PurplePresencePrivate *priv = NULL;
-
-	priv = purple_presence_get_instance_private(presence);
-
-	if(g_set_object(&priv->active_status, status)) {
-		GObject *obj = G_OBJECT(presence);
-
-		g_object_freeze_notify(obj);
-		g_object_notify_by_pspec(obj, properties[PROP_ACTIVE_STATUS]);
-		g_object_notify_by_pspec(obj, properties[PROP_PRIMITIVE]);
-		g_object_notify_by_pspec(obj, properties[PROP_MESSAGE]);
-		g_object_thaw_notify(obj);
-	}
-}
-
-/******************************************************************************
  * GObject Implementation
  *****************************************************************************/
 static void
@@ -103,10 +76,6 @@
 		case PROP_LOGIN_TIME:
 			purple_presence_set_login_time(presence, g_value_get_boxed(value));
 			break;
-		case PROP_ACTIVE_STATUS:
-			purple_presence_set_active_status(presence,
-			                                  g_value_get_object(value));
-			break;
 		case PROP_PRIMITIVE:
 			purple_presence_set_primitive(presence, g_value_get_enum(value));
 			break;
@@ -145,9 +114,6 @@
 		case PROP_LOGIN_TIME:
 			g_value_set_boxed(value, purple_presence_get_login_time(presence));
 			break;
-		case PROP_ACTIVE_STATUS:
-			g_value_set_object(value, purple_presence_get_active_status(presence));
-			break;
 		case PROP_PRIMITIVE:
 			g_value_set_enum(value, purple_presence_get_primitive(presence));
 			break;
@@ -171,13 +137,7 @@
 }
 
 static void
-purple_presence_init(PurplePresence *presence) {
-	PurplePresencePrivate *priv = NULL;
-
-	priv = purple_presence_get_instance_private(presence);
-
-	priv->status_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-	                                           NULL);
+purple_presence_init(G_GNUC_UNUSED PurplePresence *presence) {
 }
 
 static void
@@ -186,9 +146,6 @@
 
 	priv = purple_presence_get_instance_private(PURPLE_PRESENCE(obj));
 
-	g_hash_table_destroy(priv->status_table);
-	g_clear_object(&priv->active_status);
-
 	g_clear_pointer(&priv->idle_time, g_date_time_unref);
 	g_clear_pointer(&priv->login_time, g_date_time_unref);
 
@@ -244,21 +201,9 @@
 		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
 	/**
-	 * PurplePresence:active-status:
-	 *
-	 * The currently active status of the presence.
-	 *
-	 * Since: 3.0
-	 */
-	properties[PROP_ACTIVE_STATUS] = g_param_spec_object("active-status",
-				"Active status",
-				"The active status for the presence.", PURPLE_TYPE_STATUS,
-				G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	/**
 	 * PurplePresence:primitive:
 	 *
-	 * The [enum@Purple.StatusPrimitive] for this presence.
+	 * The [enum@Purple.PresencePrimitive] for this presence.
 	 *
 	 * Since: 3.0
 	 */
@@ -337,41 +282,6 @@
 }
 
 void
-purple_presence_set_status_active(PurplePresence *presence,
-                                  const gchar *status_id, gboolean active)
-{
-	PurpleStatus *status = NULL;
-
-	g_return_if_fail(PURPLE_IS_PRESENCE(presence));
-	g_return_if_fail(status_id != NULL);
-
-	status = purple_presence_get_status(presence, status_id);
-
-	g_return_if_fail(PURPLE_IS_STATUS(status));
-	/* TODO: Should we do the following? */
-	/* g_return_if_fail(active == status->active); */
-
-	if(purple_status_is_exclusive(status)) {
-		if(!active) {
-			purple_debug_warning("presence",
-					"Attempted to set a non-independent status "
-					"(%s) inactive. Only independent statuses "
-					"can be specifically marked inactive.",
-					status_id);
-			return;
-		}
-	}
-
-	purple_status_set_active(status, active);
-}
-
-void
-purple_presence_switch_status(PurplePresence *presence, const gchar *status_id)
-{
-	purple_presence_set_status_active(presence, status_id, TRUE);
-}
-
-void
 purple_presence_set_idle(PurplePresence *presence, gboolean idle,
                          GDateTime *idle_time)
 {
@@ -436,126 +346,37 @@
 	g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_LOGIN_TIME]);
 }
 
-GList *
-purple_presence_get_statuses(PurplePresence *presence) {
-	PurplePresenceClass *klass = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL);
-
-	klass = PURPLE_PRESENCE_GET_CLASS(presence);
-	if(klass && klass->get_statuses) {
-		return klass->get_statuses(presence);
-	}
+gboolean
+purple_presence_is_available(PurplePresence *presence) {
+	PurplePresencePrivate *priv = NULL;
 
-	return NULL;
-}
-
-PurpleStatus *
-purple_presence_get_status(PurplePresence *presence, const gchar *status_id) {
-	PurplePresencePrivate *priv = NULL;
-	PurpleStatus *status = NULL;
-	GList *l = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL);
-	g_return_val_if_fail(status_id != NULL, NULL);
+	g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
 
 	priv = purple_presence_get_instance_private(presence);
 
-	/* What's the purpose of this hash table? */
-	status = (PurpleStatus *)g_hash_table_lookup(priv->status_table,
-	                                             status_id);
-
-	if(status == NULL) {
-		for(l = purple_presence_get_statuses(presence);
-			l != NULL && status == NULL; l = l->next)
-		{
-			PurpleStatus *temp_status = l->data;
-
-			if (purple_strequal(status_id, purple_status_get_id(temp_status))) {
-				status = temp_status;
-			}
-		}
-
-		if(status != NULL) {
-			g_hash_table_insert(priv->status_table,
-								g_strdup(purple_status_get_id(status)), status);
-		}
-	}
-
-	return status;
-}
-
-PurpleStatus *
-purple_presence_get_active_status(PurplePresence *presence) {
-	PurplePresencePrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL);
-
-	priv = purple_presence_get_instance_private(presence);
-
-	return priv->active_status;
-}
-
-gboolean
-purple_presence_is_available(PurplePresence *presence) {
-	PurpleStatus *status = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
-
-	status = purple_presence_get_active_status(presence);
-
-	return ((status != NULL && purple_status_is_available(status)) &&
-			!purple_presence_is_idle(presence));
+	return priv->primitive == PURPLE_PRESENCE_PRIMITIVE_AVAILABLE;
 }
 
 gboolean
 purple_presence_is_online(PurplePresence *presence) {
-	PurpleStatus *status = NULL;
+	PurplePresencePrivate *priv = NULL;
 
 	g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
 
-	if((status = purple_presence_get_active_status(presence)) == NULL) {
+	priv = purple_presence_get_instance_private(presence);
+
+	switch(priv->primitive) {
+	case PURPLE_PRESENCE_PRIMITIVE_AVAILABLE:
+	case PURPLE_PRESENCE_PRIMITIVE_IDLE:
+	case PURPLE_PRESENCE_PRIMITIVE_INVISIBLE:
+	case PURPLE_PRESENCE_PRIMITIVE_AWAY:
+	case PURPLE_PRESENCE_PRIMITIVE_DO_NOT_DISTURB:
+	case PURPLE_PRESENCE_PRIMITIVE_STREAMING:
+		return TRUE;
+	case PURPLE_PRESENCE_PRIMITIVE_OFFLINE:
+	default:
 		return FALSE;
 	}
-
-	return purple_status_is_online(status);
-}
-
-gboolean
-purple_presence_is_status_active(PurplePresence *presence,
-                                 const gchar *status_id)
-{
-	PurpleStatus *status = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
-	g_return_val_if_fail(status_id != NULL, FALSE);
-
-	status = purple_presence_get_status(presence, status_id);
-
-	return (status != NULL && purple_status_is_active(status));
-}
-
-gboolean
-purple_presence_is_status_primitive_active(PurplePresence *presence,
-                                           PurpleStatusPrimitive primitive)
-{
-	GList *l = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
-	g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, FALSE);
-
-	for(l = purple_presence_get_statuses(presence); l != NULL; l = l->next) {
-		PurpleStatus *temp_status = l->data;
-		PurpleStatusType *type = purple_status_get_status_type(temp_status);
-
-		if(purple_status_type_get_primitive(type) == primitive &&
-		    purple_status_is_active(temp_status))
-		{
-			return TRUE;
-		}
-	}
-
-	return FALSE;
 }
 
 gboolean
@@ -689,15 +510,7 @@
 
 	priv = purple_presence_get_instance_private(presence);
 
-	if(priv->message != NULL) {
-		return priv->message;
-	}
-
-	if(priv->active_status == NULL) {
-		return NULL;
-	}
-
-	return purple_status_get_attr_string(priv->active_status, "message");
+	return priv->message;
 }
 
 void
diff --git a/libpurple/purpleprotocolserver.h b/libpurple/purpleprotocolserver.h
--- a/libpurple/purpleprotocolserver.h
+++ b/libpurple/purpleprotocolserver.h
@@ -63,7 +63,6 @@
 	void (*set_info)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *info);
 	void (*get_info)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *who);
 
-	void (*set_status)(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status);
 	void (*set_idle)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, gint idletime);
 
 	void (*change_passwd)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *old_pass, const gchar *new_pass);
@@ -116,19 +115,6 @@
 void purple_protocol_server_get_info(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *who);
 
 /**
- * purple_protocol_server_set_status:
- * @protocol_server: The #PurpleProtocolServer instance.
- * @account: The #PurpleAccount instance.
- * @status: The #PurpleStatus instance.
- *
- * Sets the status for account @account to @status.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_protocol_server_set_status(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status);
-
-/**
  * purple_protocol_server_set_idle:
  * @protocol_server: The #PurpleProtocolServer instance.
  * @connection: The #PurpleConnection instance.
diff --git a/libpurple/purpleprotocolserver.c b/libpurple/purpleprotocolserver.c
--- a/libpurple/purpleprotocolserver.c
+++ b/libpurple/purpleprotocolserver.c
@@ -69,22 +69,6 @@
 }
 
 void
-purple_protocol_server_set_status(PurpleProtocolServer *protocol_server,
-                                  PurpleAccount *account, PurpleStatus *status)
-{
-	PurpleProtocolServerInterface *iface = NULL;
-
-	g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
-	g_return_if_fail(PURPLE_IS_ACCOUNT(account));
-	g_return_if_fail(PURPLE_IS_STATUS(status));
-
-	iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
-	if(iface != NULL && iface->set_status != NULL) {
-		iface->set_status(protocol_server, account, status);
-	}
-}
-
-void
 purple_protocol_server_set_idle(PurpleProtocolServer *protocol_server,
                                 PurpleConnection *connection, gint idletime)
 {
diff --git a/libpurple/purplesavedpresence.c b/libpurple/purplesavedpresence.c
--- a/libpurple/purplesavedpresence.c
+++ b/libpurple/purplesavedpresence.c
@@ -395,7 +395,7 @@
 	/**
 	 * PurpleSavedPresence:primitive:
 	 *
-	 * The [enum@Purple.StatusPrimitive] for this saved presence.
+	 * The [enum@Purple.PresencePrimitive] for this saved presence.
 	 *
 	 * Since: 3.0
 	 */
diff --git a/libpurple/savedstatuses.h b/libpurple/savedstatuses.h
deleted file mode 100644
--- a/libpurple/savedstatuses.h
+++ /dev/null
@@ -1,574 +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_SAVEDSTATUSES_H
-#define PURPLE_SAVEDSTATUSES_H
-
-#define PURPLE_TYPE_SAVEDSTATUS  (purple_savedstatus_get_type())
-
-/**
- * PurpleSavedStatus:
- *
- * Saved statuses don't really interact much with the rest of Purple.  It
- * could really be a plugin.  It's just a list of away states.  When
- * a user chooses one of the saved states, their Purple accounts are set
- * to the settings of that state.
- *
- * In the savedstatus API, there is the concept of a 'transient'
- * saved status.  A transient saved status is one that is not
- * permanent.  Purple will removed it automatically if it isn't
- * used for a period of time.  Transient saved statuses don't
- * have titles and they don't show up in the list of saved
- * statuses.  In fact, if a saved status does not have a title
- * then it is transient.  If it does have a title, then it is not
- * transient.
- *
- * What good is a transient status, you ask?  They can be used to
- * keep track of the user's 5 most recently used statuses, for
- * example.  Basically if they just set a message on the fly,
- * we'll cache it for them in case they want to use it again.  If
- * they don't use it again, we'll just delete it.
- *
- * Since: 2.0
- */
-/*
- * TODO: Hmm.  We should probably just be saving PurplePresences.  That's
- *       something we should look into once the status box gets fleshed
- *       out more.
- */
-typedef struct _PurpleSavedStatus     PurpleSavedStatus;
-
-/**
- * PurpleSavedStatusSub:
- *
- * A sub statuses of a saved status.
- *
- * Since: 2.0
- */
-typedef struct _PurpleSavedStatusSub  PurpleSavedStatusSub;
-
-#include "status.h"
-#include "purpleversion.h"
-
-G_BEGIN_DECLS
-
-/**************************************************************************/
-/* Saved status subsystem                                                 */
-/**************************************************************************/
-
-/**
- * purple_savedstatus_get_type:
- *
- * The standard _get_type function for #PurpleSavedStatus.
- *
- * Returns: The #GType for the #PurpleSavedStatus boxed structure.
- */
-/* TODO Boxing of PurpleSavedStatus is a temporary solution to having a GType
- *      for saved statuses. This should rather be a GObject instead of a GBoxed.
- */
-PURPLE_AVAILABLE_IN_3_0
-GType purple_savedstatus_get_type(void);
-
-/**
- * purple_savedstatus_new:
- * @title:     The title of the saved status.  This must be
- *                  unique.  Or, if you want to create a transient
- *                  saved status, then pass in NULL.
- * @type:      The type of saved status.
- *
- * Create a new saved status.  This will add the saved status to the
- * list of saved statuses and writes the revised list to status.xml.
- *
- * Returns: The newly created saved status, or NULL if the title you
- *         used was already taken.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleSavedStatus *purple_savedstatus_new(const char *title, PurpleStatusPrimitive type);
-
-/**
- * purple_savedstatus_set_title:
- * @status:  The saved status.
- * @title:   The title of the saved status.
- *
- * Set the title for the given saved status.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_savedstatus_set_title(PurpleSavedStatus *status, const char *title);
-
-/**
- * purple_savedstatus_set_primitive_type:
- * @status:  The saved status.
- * @type:    The type of saved status.
- *
- * Set the type for the given saved status.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_savedstatus_set_primitive_type(PurpleSavedStatus *status, PurpleStatusPrimitive type);
-
-/**
- * purple_savedstatus_set_message:
- * @status:  The saved status.
- * @message: The message, or NULL if you want to unset the
- *                message for this status.
- *
- * Set the message for the given saved status.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_savedstatus_set_message(PurpleSavedStatus *status, const char *message);
-
-/**
- * purple_savedstatus_set_substatus:
- * @status:	The saved status.
- * @account:	The account.
- * @type:		The status type for the account in the saved
- *                  status.
- * @message:	The message for the account in the substatus.
- *
- * Set a substatus for an account in a saved status.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_savedstatus_set_substatus(PurpleSavedStatus *status, const PurpleAccount *account, const PurpleStatusType *type, const char *message);
-
-/**
- * purple_savedstatus_unset_substatus:
- * @saved_status: The saved status.
- * @account: The account.
- *
- * Unset a substatus for an account in a saved status.  This clears
- * the previously set substatus for the PurpleSavedStatus.  If this
- * saved status is activated then this account will use the default
- * status type and message.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_savedstatus_unset_substatus(PurpleSavedStatus *saved_status, const PurpleAccount *account);
-
-/**
- * purple_savedstatus_delete:
- * @title: The title of the saved status.
- *
- * Delete a saved status.  This removes the saved status from the list
- * of saved statuses, and writes the revised list to status.xml.
- *
- * Returns: TRUE if the status was successfully deleted.  FALSE if the
- *          status could not be deleted because no saved status exists
- *          with the given title.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_savedstatus_delete(const char *title);
-
-/**
- * purple_savedstatus_delete_by_status:
- * @saved_status: the status to delete, the pointer is invalid after
- *        the call
- *
- * Delete a saved status.  This removes the saved status from the list
- * of saved statuses, and writes the revised list to status.xml.
- *
- * Since: 2.1
- */
-PURPLE_AVAILABLE_IN_2_1
-void purple_savedstatus_delete_by_status(PurpleSavedStatus *saved_status);
-
-/**
- * purple_savedstatuses_get_all:
- *
- * Returns all saved statuses.
- *
- * Returns: (element-type PurpleSavedStatus) (transfer none): A list of saved
- *          statuses.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-GList *purple_savedstatuses_get_all(void);
-
-/**
- * purple_savedstatuses_get_popular:
- * @how_many: The maximum number of saved statuses
- *                 to return, or '0' to get all saved
- *                 statuses sorted by popularity.
- *
- * Returns the n most popular saved statuses.  "Popularity" is
- * determined by when the last time a saved_status was used and
- * how many times it has been used. Transient statuses without
- * messages are not included in the list.
- *
- * Returns: (element-type PurpleSavedStatus) (transfer container): A list containing
- *         at most how_many saved statuses.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-GList *purple_savedstatuses_get_popular(unsigned int how_many);
-
-/**
- * purple_savedstatus_get_current:
- *
- * Returns the currently selected saved status.  If we are idle
- * then this returns purple_savedstatus_get_idleaway().  Otherwise
- * it returns purple_savedstatus_get_default().
- *
- * Returns: A pointer to the in-use PurpleSavedStatus.
- *         This function never returns NULL.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleSavedStatus *purple_savedstatus_get_current(void);
-
-/**
- * purple_savedstatus_get_default:
- *
- * Returns the default saved status that is used when our
- * accounts are not idle-away.
- *
- * Returns: A pointer to the in-use PurpleSavedStatus.
- *         This function never returns NULL.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleSavedStatus *purple_savedstatus_get_default(void);
-
-/**
- * purple_savedstatus_get_idleaway:
- *
- * Returns the saved status that is used when your
- * accounts become idle-away.
- *
- * Returns: A pointer to the idle-away PurpleSavedStatus.
- *         This function never returns NULL.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleSavedStatus *purple_savedstatus_get_idleaway(void);
-
-/**
- * purple_savedstatus_is_idleaway:
- *
- * Return TRUE if we are currently idle-away.  Otherwise
- * returns FALSE.
- *
- * Returns: TRUE if our accounts have been set to idle-away.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_savedstatus_is_idleaway(void);
-
-/**
- * purple_savedstatus_set_idleaway:
- * @idleaway: TRUE if accounts should be switched to use the
- *                 idle-away saved status.  FALSE if they should
- *                 be switched to use the default status.
- *
- * Set whether accounts in Purple are idle-away or not.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_savedstatus_set_idleaway(gboolean idleaway);
-
-/**
- * purple_savedstatus_get_startup:
- *
- * Returns the status to be used when purple is starting up
- *
- * Returns: A pointer to the startup PurpleSavedStatus.
- *         This function never returns NULL.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleSavedStatus *purple_savedstatus_get_startup(void);
-
-/**
- * purple_savedstatus_find:
- * @title: The name of the saved status.
- *
- * Finds a saved status with the specified title.
- *
- * Returns: The saved status if found, or NULL.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleSavedStatus *purple_savedstatus_find(const char *title);
-
-/**
- * purple_savedstatus_find_by_creation_time:
- * @creation_time: The timestamp when the saved
- *        status was created.
- *
- * Finds a saved status with the specified creation time.
- *
- * Returns: The saved status if found, or NULL.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleSavedStatus *purple_savedstatus_find_by_creation_time(time_t creation_time);
-
-/**
- * purple_savedstatus_find_transient_by_type_and_message:
- * @type: The PurpleStatusPrimitive for the status you're trying
- *        to find.
- * @message: The message for the status you're trying
- *        to find.
- *
- * Finds a saved status with the specified primitive and message.
- *
- * Returns: The saved status if found, or NULL.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleSavedStatus *purple_savedstatus_find_transient_by_type_and_message(PurpleStatusPrimitive type, const char *message);
-
-/**
- * purple_savedstatus_is_transient:
- * @saved_status: The saved status.
- *
- * Determines if a given saved status is "transient."
- * A transient saved status is one that was not
- * explicitly added by the user.  Transient statuses
- * are automatically removed if they are not used
- * for a period of time.
- *
- * A transient saved statuses is automatically
- * created by the status box when the user sets himself
- * to one of the generic primitive statuses.  The reason
- * we need to save this status information is so we can
- * restore it when Purple restarts.
- *
- * Returns: TRUE if the saved status is transient.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_savedstatus_is_transient(const PurpleSavedStatus *saved_status);
-
-/**
- * purple_savedstatus_get_title:
- * @saved_status: The saved status.
- *
- * Return the name of a given saved status.
- *
- * Returns: The title.  This value may be a static buffer which may
- *         be overwritten on subsequent calls to this function.  If
- *         you need a reference to the title for prolonged use then
- *         you should make a copy of it.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_savedstatus_get_title(const PurpleSavedStatus *saved_status);
-
-/**
- * purple_savedstatus_get_primitive_type:
- * @saved_status: The saved status.
- *
- * Return the type of a given saved status.
- *
- * Returns: The primitive type.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-PurpleStatusPrimitive purple_savedstatus_get_primitive_type(const PurpleSavedStatus *saved_status);
-
-/**
- * purple_savedstatus_get_message:
- * @saved_status: The saved status.
- *
- * Return the default message of a given saved status.
- *
- * Returns: The message.  This will return NULL if the saved
- *         status does not have a message.  This will
- *         contain the normal markup that is created by
- *         Purple's IMHTML (basically HTML markup).
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_savedstatus_get_message(const PurpleSavedStatus *saved_status);
-
-/**
- * purple_savedstatus_get_creation_time:
- * @saved_status: The saved status.
- *
- * Return the time in seconds-since-the-epoch when this
- * saved status was created.  Note: For any status created
- * by Purple 1.5.0 or older this value will be invalid and
- * very small (close to 0).  This is because Purple 1.5.0
- * and older did not record the timestamp when the status
- * was created.
- *
- * However, this value is guaranteed to be a unique
- * identifier for the given saved status.
- *
- * Returns: The timestamp when this saved status was created.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-time_t purple_savedstatus_get_creation_time(const PurpleSavedStatus *saved_status);
-
-/**
- * purple_savedstatus_has_substatuses:
- * @saved_status: The saved status.
- *
- * Determine if a given saved status has "substatuses,"
- * or if it is a simple status (the same for all
- * accounts).
- *
- * Returns: TRUE if the saved_status has substatuses.
- *         FALSE otherwise.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_savedstatus_has_substatuses(const PurpleSavedStatus *saved_status);
-
-/**
- * purple_savedstatus_get_substatus:
- * @saved_status: The saved status.
- * @account:      The account.
- *
- * Get the substatus for an account in a saved status.
- *
- * Returns: (transfer none): The PurpleSavedStatusSub for the account, or NULL if
- *         the given account does not have a substatus that
- *         differs from the default status of this PurpleSavedStatus.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleSavedStatusSub *purple_savedstatus_get_substatus(const PurpleSavedStatus *saved_status, const PurpleAccount *account);
-
-/**
- * purple_savedstatus_substatus_get_status_type:
- * @substatus: The substatus.
- *
- * Get the status type of a given substatus.
- *
- * Returns: The status type.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const PurpleStatusType *purple_savedstatus_substatus_get_status_type(const PurpleSavedStatusSub *substatus);
-
-/**
- * purple_savedstatus_substatus_get_message:
- * @substatus: The substatus.
- *
- * Get the message of a given substatus.
- *
- * Returns: The message of the substatus, or NULL if this substatus does
- *         not have a message.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_savedstatus_substatus_get_message(const PurpleSavedStatusSub *substatus);
-
-/**
- * purple_savedstatus_activate:
- * @saved_status: The status you want to set your accounts to.
- *
- * Sets the statuses for all your accounts to those specified
- * by the given saved_status.  This function calls
- * purple_savedstatus_activate_for_account() for all your accounts.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_savedstatus_activate(PurpleSavedStatus *saved_status);
-
-/**
- * purple_savedstatus_activate_for_account:
- * @saved_status: The status you want to set your accounts to.
- * @account:      The account whose statuses you want to change.
- *
- * Sets the statuses for a given account to those specified
- * by the given saved_status.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_savedstatus_activate_for_account(const PurpleSavedStatus *saved_status, PurpleAccount *account);
-
-/**
- * purple_savedstatuses_get_handle:
- *
- * Get the handle for the status subsystem.
- *
- * Returns: the handle to the status subsystem
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void *purple_savedstatuses_get_handle(void);
-
-/**
- * purple_savedstatuses_init:
- *
- * Initializes the status subsystem.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_savedstatuses_init(void);
-
-/**
- * purple_savedstatuses_uninit:
- *
- * Uninitializes the status subsystem.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_savedstatuses_uninit(void);
-
-G_END_DECLS
-
-#endif /* PURPLE_SAVEDSTATUSES_H */
diff --git a/libpurple/savedstatuses.c b/libpurple/savedstatuses.c
deleted file mode 100644
--- a/libpurple/savedstatuses.c
+++ /dev/null
@@ -1,1274 +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 "accounts.h"
-#include "debug.h"
-#include "notify.h"
-#include "prefs.h"
-#include "purpleaccountmanager.h"
-#include "purplemarkup.h"
-#include "savedstatuses.h"
-#include "request.h"
-#include "status.h"
-#include "xmlnode.h"
-
-/*
- * The maximum number of transient statuses to save.  This
- * is used during the shutdown process to clean out old
- * transient statuses.
- */
-#define MAX_TRANSIENTS 5
-
-/*
- * The default message to use when the user becomes auto-away.
- */
-#define DEFAULT_AUTOAWAY_MESSAGE _("I'm not here right now")
-
-/*
- * The information stores a snap-shot of the statuses of all
- * your accounts.  Basically these are your saved away messages.
- * There is an overall status and message that applies to
- * all your accounts, and then each individual account can
- * optionally have a different custom status and message.
- *
- * The changes to status.xml caused by the new status API
- * are fully backward compatible.  The new status API just
- * adds the optional sub-statuses to the XML file.
- */
-struct _PurpleSavedStatus
-{
-	char *title;
-	PurpleStatusPrimitive type;
-	char *message;
-
-	/* The timestamp when this saved status was created. This must be unique. */
-	time_t creation_time;
-
-	time_t lastused;
-
-	unsigned int usage_count;
-
-	GList *substatuses;      /* A list of PurpleSavedStatusSub's. */
-};
-
-/*
- * TODO: If a PurpleStatusType is deleted, need to also delete any
- *       associated PurpleSavedStatusSub's?
- */
-struct _PurpleSavedStatusSub
-{
-	PurpleAccount *account;
-	const PurpleStatusType *type;
-	char *message;
-};
-
-static GList      *saved_statuses = NULL;
-static guint       save_timer = 0;
-static gboolean    statuses_loaded = FALSE;
-
-/*
- * This hash table keeps track of which timestamps we've
- * used so that we don't have two saved statuses with the
- * same 'creation_time' timestamp.  The 'created' timestamp
- * is used as a unique identifier.
- *
- * So the key in this hash table is the creation_time and
- * the value is a pointer to the PurpleSavedStatus.
- */
-static GHashTable *creation_times;
-
-static void schedule_save(void);
-
-/*********************************************************************
- * Private utility functions                                         *
- *********************************************************************/
-
-static void
-free_saved_status_sub(PurpleSavedStatusSub *substatus)
-{
-	g_return_if_fail(substatus != NULL);
-
-	g_free(substatus->message);
-	purple_request_close_with_handle(substatus);
-	g_clear_object(&substatus->account);
-	g_free(substatus);
-}
-
-static void
-free_saved_status(PurpleSavedStatus *status)
-{
-	g_return_if_fail(status != NULL);
-
-	g_free(status->title);
-	g_free(status->message);
-	g_list_free_full(status->substatuses, (GDestroyNotify)free_saved_status_sub);
-	purple_request_close_with_handle(status);
-	g_free(status);
-}
-
-/*
- * Set the timestamp for when this saved status was created, and
- * make sure it is unique.
- */
-static void
-set_creation_time(PurpleSavedStatus *status, time_t creation_time)
-{
-	g_return_if_fail(status != NULL);
-
-	/* Avoid using 0 because it's an invalid hash key */
-	status->creation_time = creation_time != 0 ? creation_time : 1;
-
-	while (g_hash_table_lookup(creation_times, (gconstpointer)status->creation_time) != NULL)
-		status->creation_time++;
-
-	g_hash_table_insert(creation_times,
-						(gpointer)status->creation_time,
-						status);
-}
-
-/*
- * A magic number is calculated for each status, and then the
- * statuses are ordered by the magic number.  The magic number
- * is the date the status was last used offset by one day for
- * each time the status has been used (but only by 10 days at
- * the most).
- *
- * The goal is to have recently used statuses at the top of
- * the list, but to also keep frequently used statuses near
- * the top.
- */
-static gint
-saved_statuses_sort_func(gconstpointer a, gconstpointer b)
-{
-	const PurpleSavedStatus *saved_status_a = a;
-	const PurpleSavedStatus *saved_status_b = b;
-	time_t time_a = saved_status_a->lastused +
-						(MIN(saved_status_a->usage_count, 10) * 86400);
-	time_t time_b = saved_status_b->lastused +
-						(MIN(saved_status_b->usage_count, 10) * 86400);
-	if (time_a > time_b)
-		return -1;
-	if (time_a < time_b)
-		return 1;
-	return 0;
-}
-
-/*
- * Transient statuses are added and removed automatically by
- * Purple.  If they're not used for a certain length of time then
- * they'll expire and be automatically removed.  This function
- * does the expiration.
- */
-static void
-remove_old_transient_statuses(void)
-{
-	GList *l, *next;
-	PurpleSavedStatus *saved_status, *startup_status, *current_status;
-	int count;
-	time_t creation_time;
-
-	startup_status = purple_savedstatus_get_startup();
-	current_status = purple_savedstatus_get_current();
-
-	/*
-	 * Iterate through the list of saved statuses.  Delete all
-	 * transient statuses except for the first MAX_TRANSIENTS
-	 * (remember, the saved statuses are already sorted by popularity).
-	 * We should also keep the startup status, if any is set.
-	 */
-	count = 0;
-	for (l = saved_statuses; l != NULL; l = next)
-	{
-		next = l->next;
-		saved_status = l->data;
-		if (purple_savedstatus_is_transient(saved_status))
-		{
-			if (count == MAX_TRANSIENTS)
-			{
-				if (saved_status != current_status && saved_status != startup_status)
-				{
-					saved_statuses = g_list_delete_link(saved_statuses, l);
-					creation_time = purple_savedstatus_get_creation_time(saved_status);
-					g_hash_table_remove(creation_times, (gconstpointer)creation_time);
-					free_saved_status(saved_status);
-				}
-			}
-			else
-				count++;
-		}
-	}
-
-	if (count == MAX_TRANSIENTS)
-		schedule_save();
-}
-
-/*********************************************************************
- * Writing to disk                                                   *
- *********************************************************************/
-
-static PurpleXmlNode *
-substatus_to_xmlnode(PurpleSavedStatusSub *substatus)
-{
-	PurpleContactInfo *info = NULL;
-	PurpleXmlNode *node, *child;
-	const char *name = NULL;
-
-	info = PURPLE_CONTACT_INFO(substatus->account);
-
-	node = purple_xmlnode_new("substatus");
-
-	child = purple_xmlnode_new_child(node, "account");
-	purple_xmlnode_set_attrib(child, "protocol", purple_account_get_protocol_id(substatus->account));
-
-	name = purple_normalize(substatus->account,
-	                        purple_contact_info_get_username(info));
-
-	purple_xmlnode_insert_data(child, name, -1);
-
-	child = purple_xmlnode_new_child(node, "state");
-	purple_xmlnode_insert_data(child, purple_status_type_get_id(substatus->type), -1);
-
-	if (substatus->message != NULL)
-	{
-		child = purple_xmlnode_new_child(node, "message");
-		purple_xmlnode_insert_data(child, substatus->message, -1);
-	}
-
-	return node;
-}
-
-static PurpleXmlNode *
-status_to_xmlnode(PurpleSavedStatus *status)
-{
-	PurpleXmlNode *node, *child;
-	char buf[21];
-	GList *cur;
-
-	node = purple_xmlnode_new("status");
-	if (status->title != NULL)
-	{
-		purple_xmlnode_set_attrib(node, "name", status->title);
-	}
-	else
-	{
-		/*
-		 * Purple 1.5.0 and earlier require a name to be set, so we
-		 * do this little hack to maintain backward compatibility
-		 * in the status.xml file.  Eventually this should be removed
-		 * and we should determine if a status is transient by
-		 * whether the "name" attribute is set to something or if
-		 * it does not exist at all.
-		 */
-		purple_xmlnode_set_attrib(node, "name", "Auto-Cached");
-		purple_xmlnode_set_attrib(node, "transient", "true");
-	}
-
-	g_snprintf(buf, sizeof(buf), "%" G_GINT64_FORMAT,
-	           (gint64)status->creation_time);
-	purple_xmlnode_set_attrib(node, "created", buf);
-
-	g_snprintf(buf, sizeof(buf), "%" G_GINT64_FORMAT, (gint64)status->lastused);
-	purple_xmlnode_set_attrib(node, "lastused", buf);
-
-	g_snprintf(buf, sizeof(buf), "%u", status->usage_count);
-	purple_xmlnode_set_attrib(node, "usage_count", buf);
-
-	child = purple_xmlnode_new_child(node, "state");
-	purple_xmlnode_insert_data(child, purple_primitive_get_id_from_type(status->type), -1);
-
-	if (status->message != NULL)
-	{
-		child = purple_xmlnode_new_child(node, "message");
-		purple_xmlnode_insert_data(child, status->message, -1);
-	}
-
-	for (cur = status->substatuses; cur != NULL; cur = cur->next)
-	{
-		child = substatus_to_xmlnode(cur->data);
-		purple_xmlnode_insert_child(node, child);
-	}
-
-	return node;
-}
-
-static PurpleXmlNode *
-statuses_to_xmlnode(void)
-{
-	PurpleXmlNode *node, *child;
-	GList *cur;
-
-	node = purple_xmlnode_new("statuses");
-	purple_xmlnode_set_attrib(node, "version", "1.0");
-
-	for (cur = saved_statuses; cur != NULL; cur = cur->next)
-	{
-		child = status_to_xmlnode(cur->data);
-		purple_xmlnode_insert_child(node, child);
-	}
-
-	return node;
-}
-
-static void
-sync_statuses(void)
-{
-	PurpleXmlNode *node;
-	char *data;
-
-	if (!statuses_loaded)
-	{
-		purple_debug_error("status", "Attempted to save statuses before they "
-						 "were read!\n");
-		return;
-	}
-
-	node = statuses_to_xmlnode();
-	data = purple_xmlnode_to_formatted_str(node, NULL);
-	purple_util_write_data_to_config_file("status.xml", data, -1);
-	g_free(data);
-	purple_xmlnode_free(node);
-}
-
-static gboolean
-save_cb(G_GNUC_UNUSED gpointer data)
-{
-	sync_statuses();
-	save_timer = 0;
-	return FALSE;
-}
-
-static void
-schedule_save(void)
-{
-	if (save_timer == 0)
-		save_timer = g_timeout_add_seconds(5, save_cb, NULL);
-}
-
-
-/*********************************************************************
- * Reading from disk                                                 *
- *********************************************************************/
-
-static PurpleSavedStatusSub *
-parse_substatus(PurpleXmlNode *substatus)
-{
-	PurpleSavedStatusSub *ret;
-	PurpleXmlNode *node;
-	char *data;
-
-	ret = g_new0(PurpleSavedStatusSub, 1);
-
-	/* Read the account */
-	node = purple_xmlnode_get_child(substatus, "account");
-	if(node != NULL) {
-		gchar *acct_name;
-		const char *protocol;
-
-		acct_name = purple_xmlnode_get_data(node);
-		protocol = purple_xmlnode_get_attrib(node, "protocol");
-
-		if(acct_name != NULL && protocol != NULL) {
-			PurpleAccountManager *manager = NULL;
-
-			manager = purple_account_manager_get_default();
-
-			ret->account = purple_account_manager_find(manager, acct_name,
-			                                           protocol);
-		}
-
-		g_free(acct_name);
-	}
-
-	if(ret->account == NULL) {
-		free_saved_status_sub(ret);
-		return NULL;
-	}
-
-	/* Read the state */
-	node = purple_xmlnode_get_child(substatus, "state");
-	if((node != NULL) && ((data = purple_xmlnode_get_data(node)) != NULL)) {
-		ret->type = purple_status_type_find_with_id(
-							purple_account_get_status_types(ret->account), data);
-		g_free(data);
-	}
-
-	if(ret->type == NULL) {
-		free_saved_status_sub(ret);
-		return NULL;
-	}
-
-	/* Read the message */
-	node = purple_xmlnode_get_child(substatus, "message");
-	if((node != NULL) && ((data = purple_xmlnode_get_data(node)) != NULL)) {
-		ret->message = data;
-	}
-
-	return ret;
-}
-
-/*
- * Parse a saved status and add it to the saved_statuses linked list.
- *
- * Here's an example of the XML for a saved status:
- *   <status name="Girls">
- *       <state>away</state>
- *       <message>I like the way that they walk
- *   And it's chill to hear them talk
- *   And I can always make them smile
- *   From White Castle to the Nile</message>
- *       <substatus>
- *           <account protocol='aim'>markdoliner</account>
- *           <state>available</state>
- *           <message>The ladies man is here to answer your queries.</message>
- *       </substatus>
- *       <substatus>
- *           <account protocol='aim'>giantgraypanda</account>
- *           <state>away</state>
- *           <message>A.C. ain't in charge no more.</message>
- *       </substatus>
- *   </status>
- *
- * I know.  Moving, huh?
- */
-static PurpleSavedStatus *
-parse_status(PurpleXmlNode *status)
-{
-	PurpleSavedStatus *ret;
-	PurpleXmlNode *node;
-	const char *attrib;
-	char *data;
-	int i;
-
-	ret = g_new0(PurpleSavedStatus, 1);
-
-	attrib = purple_xmlnode_get_attrib(status, "transient");
-	if (!purple_strequal(attrib, "true"))
-	{
-		/* Read the title */
-		attrib = purple_xmlnode_get_attrib(status, "name");
-		ret->title = g_strdup(attrib);
-	}
-
-	if (ret->title != NULL)
-	{
-		/* Ensure the title is unique */
-		i = 2;
-		while (purple_savedstatus_find(ret->title) != NULL)
-		{
-			g_free(ret->title);
-			ret->title = g_strdup_printf("%s %d", attrib, i);
-			i++;
-		}
-	}
-
-	/* Read the creation time */
-	attrib = purple_xmlnode_get_attrib(status, "created");
-	set_creation_time(ret,
-	                  (attrib != NULL ? g_ascii_strtoll(attrib, NULL, 10) : 0));
-
-	/* Read the last used time */
-	attrib = purple_xmlnode_get_attrib(status, "lastused");
-	ret->lastused = (attrib != NULL ? g_ascii_strtoll(attrib, NULL, 10) : 0);
-
-	/* Read the usage count */
-	attrib = purple_xmlnode_get_attrib(status, "usage_count");
-	ret->usage_count = (attrib != NULL ? atol(attrib) : 0);
-
-	/* Read the primitive status type */
-	node = purple_xmlnode_get_child(status, "state");
-	if ((node != NULL) && ((data = purple_xmlnode_get_data(node)) != NULL))
-	{
-		ret->type = purple_primitive_get_type_from_id(data);
-		g_free(data);
-	}
-
-	/* Read the message */
-	node = purple_xmlnode_get_child(status, "message");
-	if ((node != NULL) && ((data = purple_xmlnode_get_data(node)) != NULL))
-	{
-		ret->message = data;
-	}
-
-	/* Read substatuses */
-	for (node = purple_xmlnode_get_child(status, "substatus"); node != NULL;
-			node = purple_xmlnode_get_next_twin(node))
-	{
-		PurpleSavedStatusSub *new;
-		new = parse_substatus(node);
-		if (new != NULL)
-			ret->substatuses = g_list_prepend(ret->substatuses, new);
-	}
-
-	return ret;
-}
-
-/*
- * load_statuses:
- *
- * Read the saved statuses from a file in the Purple user dir.
- *
- * Returns: TRUE on success, FALSE on failure (if the file can not
- *          be opened, or if it contains invalid XML).
- */
-static void
-load_statuses(void)
-{
-	PurpleXmlNode *statuses, *status;
-
-	statuses_loaded = TRUE;
-
-	statuses = purple_util_read_xml_from_config_file("status.xml", _("saved statuses"));
-
-	if (statuses == NULL)
-		return;
-
-	for (status = purple_xmlnode_get_child(statuses, "status"); status != NULL;
-			status = purple_xmlnode_get_next_twin(status))
-	{
-		PurpleSavedStatus *new;
-		new = parse_status(status);
-		saved_statuses = g_list_prepend(saved_statuses, new);
-	}
-	saved_statuses = g_list_sort(saved_statuses, saved_statuses_sort_func);
-
-	purple_xmlnode_free(statuses);
-}
-
-
-/**************************************************************************
-* Saved status API
-**************************************************************************/
-PurpleSavedStatus *
-purple_savedstatus_new(const char *title, PurpleStatusPrimitive type)
-{
-	PurpleSavedStatus *status;
-
-	/* Make sure we don't already have a saved status with this title. */
-	if (title != NULL)
-		g_return_val_if_fail(purple_savedstatus_find(title) == NULL, NULL);
-
-	status = g_new0(PurpleSavedStatus, 1);
-	status->title = g_strdup(title);
-	status->type = type;
-	set_creation_time(status, time(NULL));
-
-	saved_statuses = g_list_insert_sorted(saved_statuses, status, saved_statuses_sort_func);
-
-	schedule_save();
-
-	purple_signal_emit(purple_savedstatuses_get_handle(), "savedstatus-added",
-		status);
-
-	return status;
-}
-
-void
-purple_savedstatus_set_title(PurpleSavedStatus *status, const char *title)
-{
-	g_return_if_fail(status != NULL);
-
-	/* Make sure we don't already have a saved status with this title. */
-	g_return_if_fail(purple_savedstatus_find(title) == NULL);
-
-	g_free(status->title);
-	status->title = g_strdup(title);
-
-	schedule_save();
-
-	purple_signal_emit(purple_savedstatuses_get_handle(),
-			"savedstatus-modified", status);
-}
-
-void
-purple_savedstatus_set_primitive_type(PurpleSavedStatus *status, PurpleStatusPrimitive type)
-{
-	g_return_if_fail(status != NULL);
-
-	status->type = type;
-
-	schedule_save();
-	purple_signal_emit(purple_savedstatuses_get_handle(),
-			"savedstatus-modified", status);
-}
-
-void
-purple_savedstatus_set_message(PurpleSavedStatus *status, const char *message)
-{
-	g_return_if_fail(status != NULL);
-
-	g_free(status->message);
-	if ((message != NULL) && (*message == '\0'))
-		status->message = NULL;
-	else
-		status->message = g_strdup(message);
-
-	schedule_save();
-
-	purple_signal_emit(purple_savedstatuses_get_handle(),
-			"savedstatus-modified", status);
-}
-
-void
-purple_savedstatus_set_substatus(PurpleSavedStatus *saved_status,
-							   const PurpleAccount *account,
-							   const PurpleStatusType *type,
-							   const char *message)
-{
-	PurpleSavedStatusSub *substatus;
-
-	g_return_if_fail(saved_status != NULL);
-	g_return_if_fail(account      != NULL);
-	g_return_if_fail(type         != NULL);
-
-	/* Find an existing substatus or create a new one */
-	substatus = purple_savedstatus_get_substatus(saved_status, account);
-	if (substatus == NULL)
-	{
-		substatus = g_new0(PurpleSavedStatusSub, 1);
-		substatus->account = (PurpleAccount *)account;
-		saved_status->substatuses = g_list_prepend(saved_status->substatuses, substatus);
-	}
-
-	substatus->type = type;
-	g_free(substatus->message);
-	substatus->message = g_strdup(message);
-
-	schedule_save();
-	purple_signal_emit(purple_savedstatuses_get_handle(),
-			"savedstatus-modified", saved_status);
-}
-
-void
-purple_savedstatus_unset_substatus(PurpleSavedStatus *saved_status,
-								 const PurpleAccount *account)
-{
-	GList *iter;
-	PurpleSavedStatusSub *substatus;
-
-	g_return_if_fail(saved_status != NULL);
-	g_return_if_fail(account      != NULL);
-
-	for (iter = saved_status->substatuses; iter != NULL; iter = iter->next)
-	{
-		substatus = iter->data;
-		if (substatus->account == account)
-		{
-			saved_status->substatuses = g_list_delete_link(saved_status->substatuses, iter);
-			free_saved_status_sub(substatus);
-			return;
-		}
-	}
-
-	purple_signal_emit(purple_savedstatuses_get_handle(),
-			"savedstatus-modified", saved_status);
-}
-
-/*
- * This gets called when an account is deleted.  We iterate through
- * all of our saved statuses and delete any substatuses that may
- * exist for this account.
- */
-static void
-purple_savedstatus_unset_all_substatuses(G_GNUC_UNUSED PurpleAccountManager *manager,
-                                         PurpleAccount *account,
-                                         G_GNUC_UNUSED gpointer data)
-{
-	g_return_if_fail(account != NULL);
-
-	g_list_foreach(saved_statuses, (GFunc)purple_savedstatus_unset_substatus, account);
-}
-
-void
-purple_savedstatus_delete_by_status(PurpleSavedStatus *status)
-{
-	time_t creation_time, current, idleaway;
-
-	g_return_if_fail(status != NULL);
-
-	saved_statuses = g_list_remove(saved_statuses, status);
-	creation_time = purple_savedstatus_get_creation_time(status);
-	g_hash_table_remove(creation_times, (gconstpointer)creation_time);
-
-	schedule_save();
-
-	/*
-	 * If we just deleted our current status or our idleaway status,
-	 * then set the appropriate pref back to 0.
-	 */
-	current = purple_prefs_get_int("/purple/savedstatus/default");
-	if (current == creation_time)
-		purple_prefs_set_int("/purple/savedstatus/default", 0);
-
-	idleaway = purple_prefs_get_int("/purple/savedstatus/idleaway");
-	if (idleaway == creation_time)
-		purple_prefs_set_int("/purple/savedstatus/idleaway", 0);
-
-	purple_signal_emit(purple_savedstatuses_get_handle(),
-			"savedstatus-deleted", status);
-
-	free_saved_status(status);
-}
-
-gboolean
-purple_savedstatus_delete(const char *title)
-{
-	PurpleSavedStatus *status;
-
-	status = purple_savedstatus_find(title);
-
-	if (status == NULL)
-		return FALSE;
-
-	if (purple_savedstatus_get_current() == status)
-		return FALSE;
-
-	purple_savedstatus_delete_by_status(status);
-
-	return TRUE;
-}
-
-GList *
-purple_savedstatuses_get_all(void)
-{
-	return saved_statuses;
-}
-
-GList *
-purple_savedstatuses_get_popular(unsigned int how_many)
-{
-	GList *popular = NULL;
-	GList *cur;
-	unsigned int i;
-	PurpleSavedStatus *next;
-
-	/* Copy 'how_many' elements to a new list. If 'how_many' is 0, then copy all of 'em. */
-	if (how_many == 0)
-		how_many = (unsigned int) -1;
-
-	i = 0;
-	cur = saved_statuses;
-	while ((i < how_many) && (cur != NULL))
-	{
-		next = cur->data;
-		if ((!purple_savedstatus_is_transient(next)
-			|| purple_savedstatus_get_message(next) != NULL))
-		{
-			popular = g_list_prepend(popular, next);
-			i++;
-		}
-		cur = cur->next;
-	}
-
-	popular = g_list_reverse(popular);
-
-	return popular;
-}
-
-PurpleSavedStatus *
-purple_savedstatus_get_current(void)
-{
-	if (purple_savedstatus_is_idleaway())
-		return purple_savedstatus_get_idleaway();
-	else
-		return purple_savedstatus_get_default();
-}
-
-PurpleSavedStatus *
-purple_savedstatus_get_default(void)
-{
-	time_t creation_time;
-	PurpleSavedStatus *saved_status = NULL;
-
-	creation_time = purple_prefs_get_int("/purple/savedstatus/default");
-
-	if (creation_time != 0)
-		saved_status = g_hash_table_lookup(creation_times, (gconstpointer)creation_time);
-
-	if (saved_status == NULL)
-	{
-		/*
-		 * We don't have a current saved status!  This is either a new
-		 * Purple user or someone upgrading from Purple 1.5.0 or older, or
-		 * possibly someone who deleted the status they were currently
-		 * using?  In any case, add a default status.
-		 */
-		saved_status = purple_savedstatus_new(NULL, PURPLE_STATUS_AVAILABLE);
-		purple_prefs_set_int("/purple/savedstatus/default",
-						   purple_savedstatus_get_creation_time(saved_status));
-	}
-
-	return saved_status;
-}
-
-PurpleSavedStatus *
-purple_savedstatus_get_idleaway(void)
-{
-	time_t creation_time;
-	PurpleSavedStatus *saved_status = NULL;
-
-	creation_time = purple_prefs_get_int("/purple/savedstatus/idleaway");
-
-	if (creation_time != 0)
-		saved_status = g_hash_table_lookup(creation_times, (gconstpointer)creation_time);
-
-	if (saved_status == NULL)
-	{
-		/* We don't have a specified "idle" status!  Weird. */
-		saved_status = purple_savedstatus_find_transient_by_type_and_message(
-				PURPLE_STATUS_AWAY, DEFAULT_AUTOAWAY_MESSAGE);
-
-		if (saved_status == NULL)
-		{
-			saved_status = purple_savedstatus_new(NULL, PURPLE_STATUS_AWAY);
-			purple_savedstatus_set_message(saved_status, DEFAULT_AUTOAWAY_MESSAGE);
-			purple_prefs_set_int("/purple/savedstatus/idleaway",
-							   purple_savedstatus_get_creation_time(saved_status));
-		}
-	}
-
-	return saved_status;
-}
-
-gboolean
-purple_savedstatus_is_idleaway(void)
-{
-	return purple_prefs_get_bool("/purple/savedstatus/isidleaway");
-}
-
-void
-purple_savedstatus_set_idleaway(gboolean idleaway) {
-	PurpleAccountManager *manager = NULL;
-	PurpleSavedStatus *old, *saved_status;
-	GList *accounts, *node;
-
-	if(purple_savedstatus_is_idleaway() == idleaway) {
-		/* Don't need to do anything */
-		return;
-	}
-
-	old = purple_savedstatus_get_current();
-	saved_status = idleaway ? purple_savedstatus_get_idleaway()
-			: purple_savedstatus_get_default();
-	purple_prefs_set_bool("/purple/savedstatus/isidleaway", idleaway);
-
-	if(idleaway && (purple_savedstatus_get_primitive_type(old) != PURPLE_STATUS_AVAILABLE))
-	{
-		/* Our global status is already "away," so don't change anything */
-		return;
-	}
-
-	manager = purple_account_manager_get_default();
-	accounts = purple_account_manager_get_enabled(manager);
-	for (node = accounts; node != NULL; node = node->next) {
-		PurpleAccount *account;
-		PurplePresence *presence;
-		PurpleStatus *status;
-
-		account = node->data;
-		presence = purple_account_get_presence(account);
-		status = purple_presence_get_active_status(presence);
-
-		if (!idleaway || purple_status_is_available(status))
-			purple_savedstatus_activate_for_account(saved_status, account);
-	}
-
-	g_list_free(accounts);
-
-	purple_signal_emit(purple_savedstatuses_get_handle(), "savedstatus-changed",
-					 saved_status, old);
-}
-
-PurpleSavedStatus *
-purple_savedstatus_get_startup(void)
-{
-	time_t creation_time;
-	PurpleSavedStatus *saved_status = NULL;
-
-	creation_time = purple_prefs_get_int("/purple/savedstatus/startup");
-
-	if (creation_time != 0)
-		saved_status = g_hash_table_lookup(creation_times, (gconstpointer)creation_time);
-
-	if (saved_status == NULL)
-	{
-		/*
-		 * We don't have a status to apply.
-		 * This may be the first login, or the user wants to
-		 * restore the "current" status.
-		 */
-		saved_status = purple_savedstatus_get_current();
-	}
-
-	return saved_status;
-}
-
-
-PurpleSavedStatus *
-purple_savedstatus_find(const char *title)
-{
-	GList *iter;
-	PurpleSavedStatus *status;
-
-	g_return_val_if_fail(title != NULL, NULL);
-
-	for (iter = saved_statuses; iter != NULL; iter = iter->next)
-	{
-		status = (PurpleSavedStatus *)iter->data;
-		if (purple_strequal(status->title, title))
-			return status;
-	}
-
-	return NULL;
-}
-
-PurpleSavedStatus *
-purple_savedstatus_find_by_creation_time(time_t creation_time)
-{
-	GList *iter;
-	PurpleSavedStatus *status;
-
-	for (iter = saved_statuses; iter != NULL; iter = iter->next)
-	{
-		status = (PurpleSavedStatus *)iter->data;
-		if (status->creation_time == creation_time)
-			return status;
-	}
-
-	return NULL;
-}
-
-PurpleSavedStatus *
-purple_savedstatus_find_transient_by_type_and_message(PurpleStatusPrimitive type,
-													const char *message)
-{
-	GList *iter;
-	PurpleSavedStatus *status;
-
-	for (iter = saved_statuses; iter != NULL; iter = iter->next)
-	{
-		status = (PurpleSavedStatus *)iter->data;
-		if ((status->type == type) && purple_savedstatus_is_transient(status) &&
-			!purple_savedstatus_has_substatuses(status) &&
-			purple_strequal(status->message, message))
-		{
-			return status;
-		}
-	}
-
-	return NULL;
-}
-
-gboolean
-purple_savedstatus_is_transient(const PurpleSavedStatus *saved_status)
-{
-	g_return_val_if_fail(saved_status != NULL, TRUE);
-
-	return (saved_status->title == NULL);
-}
-
-const char *
-purple_savedstatus_get_title(const PurpleSavedStatus *saved_status)
-{
-	const char *message;
-
-	g_return_val_if_fail(saved_status != NULL, NULL);
-
-	/* If we have a title then return it */
-	if (saved_status->title != NULL)
-		return saved_status->title;
-
-	/* Otherwise, this is a transient status and we make up a title on the fly */
-	message = purple_savedstatus_get_message(saved_status);
-
-	if ((message == NULL) || (*message == '\0'))
-	{
-		PurpleStatusPrimitive primitive;
-		primitive = purple_savedstatus_get_primitive_type(saved_status);
-		return purple_primitive_get_name_from_type(primitive);
-	}
-	else
-	{
-		char *stripped;
-		static char buf[64];
-		stripped = purple_markup_strip_html(message);
-		purple_util_chrreplace(stripped, '\n', ' ');
-		strncpy(buf, stripped, sizeof(buf));
-		buf[sizeof(buf) - 1] = '\0';
-		if ((strlen(stripped) + 1) > sizeof(buf))
-		{
-			/* Truncate and ellipsize */
-			char *tmp = g_utf8_find_prev_char(buf, &buf[sizeof(buf) - 4]);
-			strcpy(tmp, "...");
-		}
-		g_free(stripped);
-		return buf;
-	}
-}
-
-PurpleStatusPrimitive
-purple_savedstatus_get_primitive_type(const PurpleSavedStatus *saved_status)
-{
-	g_return_val_if_fail(saved_status != NULL, PURPLE_STATUS_OFFLINE);
-
-	return saved_status->type;
-}
-
-const char *
-purple_savedstatus_get_message(const PurpleSavedStatus *saved_status)
-{
-	g_return_val_if_fail(saved_status != NULL, NULL);
-
-	return saved_status->message;
-}
-
-time_t
-purple_savedstatus_get_creation_time(const PurpleSavedStatus *saved_status)
-{
-	g_return_val_if_fail(saved_status != NULL, 0);
-
-	return saved_status->creation_time;
-}
-
-gboolean
-purple_savedstatus_has_substatuses(const PurpleSavedStatus *saved_status)
-{
-	g_return_val_if_fail(saved_status != NULL, FALSE);
-
-	return (saved_status->substatuses != NULL);
-}
-
-PurpleSavedStatusSub *
-purple_savedstatus_get_substatus(const PurpleSavedStatus *saved_status,
-							   const PurpleAccount *account)
-{
-	GList *iter;
-	PurpleSavedStatusSub *substatus;
-
-	g_return_val_if_fail(saved_status != NULL, NULL);
-	g_return_val_if_fail(account      != NULL, NULL);
-
-	for (iter = saved_status->substatuses; iter != NULL; iter = iter->next)
-	{
-		substatus = iter->data;
-		if (substatus->account == account)
-			return substatus;
-	}
-
-	return NULL;
-}
-
-const PurpleStatusType *
-purple_savedstatus_substatus_get_status_type(const PurpleSavedStatusSub *substatus)
-{
-	g_return_val_if_fail(substatus != NULL, NULL);
-
-	return substatus->type;
-}
-
-const char *
-purple_savedstatus_substatus_get_message(const PurpleSavedStatusSub *substatus)
-{
-	g_return_val_if_fail(substatus != NULL, NULL);
-
-	return substatus->message;
-}
-
-void
-purple_savedstatus_activate(PurpleSavedStatus *saved_status) {
-	PurpleAccountManager *manager = NULL;
-	PurpleSavedStatus *old = purple_savedstatus_get_current();
-	GList *accounts, *node;
-
-	g_return_if_fail(saved_status != NULL);
-
-	/* Make sure our list of saved statuses remains sorted */
-	saved_status->lastused = time(NULL);
-	saved_status->usage_count++;
-	saved_statuses = g_list_remove(saved_statuses, saved_status);
-	saved_statuses = g_list_insert_sorted(saved_statuses, saved_status,
-	                                      saved_statuses_sort_func);
-	purple_prefs_set_int("/purple/savedstatus/default",
-	                     purple_savedstatus_get_creation_time(saved_status));
-
-	manager = purple_account_manager_get_default();
-	accounts = purple_account_manager_get_enabled(manager);
-	for(node = accounts; node != NULL; node = node->next) {
-		PurpleAccount *account;
-
-		account = node->data;
-
-		purple_savedstatus_activate_for_account(saved_status, account);
-	}
-
-	g_list_free(accounts);
-
-	if(purple_savedstatus_is_idleaway()) {
-		purple_savedstatus_set_idleaway(FALSE);
-	} else {
-		purple_signal_emit(purple_savedstatuses_get_handle(),
-		                   "savedstatus-changed", saved_status, old);
-	}
-}
-
-void
-purple_savedstatus_activate_for_account(const PurpleSavedStatus *saved_status,
-									  PurpleAccount *account)
-{
-	const PurpleStatusType *status_type;
-	const PurpleSavedStatusSub *substatus;
-	const char *message = NULL;
-
-	g_return_if_fail(saved_status != NULL);
-	g_return_if_fail(account != NULL);
-
-	substatus = purple_savedstatus_get_substatus(saved_status, account);
-	if (substatus != NULL)
-	{
-		status_type = substatus->type;
-		message = substatus->message;
-	}
-	else
-	{
-		status_type = purple_account_get_status_type_with_primitive(account, saved_status->type);
-		if (status_type == NULL)
-			return;
-		message = saved_status->message;
-	}
-
-	if ((message != NULL) &&
-		(purple_status_type_get_attr(status_type, "message")))
-	{
-		purple_account_set_status(account, purple_status_type_get_id(status_type),
-								TRUE, "message", message, NULL);
-	}
-	else
-	{
-		purple_account_set_status(account, purple_status_type_get_id(status_type),
-								TRUE, NULL);
-	}
-}
-
-static PurpleSavedStatus *
-purple_savedstatus_copy(PurpleSavedStatus *savedstatus)
-{
-	PurpleSavedStatus *savedstatus_copy;
-
-	g_return_val_if_fail(savedstatus != NULL, NULL);
-
-	savedstatus_copy = g_new(PurpleSavedStatus, 1);
-	*savedstatus_copy = *savedstatus;
-
-	return savedstatus_copy;
-}
-
-GType
-purple_savedstatus_get_type(void)
-{
-	static GType type = 0;
-
-	if (type == 0) {
-		type = g_boxed_type_register_static("PurpleSavedStatus",
-				(GBoxedCopyFunc)purple_savedstatus_copy,
-				(GBoxedFreeFunc)g_free);
-	}
-
-	return type;
-}
-
-void *
-purple_savedstatuses_get_handle(void)
-{
-	static int handle;
-
-	return &handle;
-}
-
-void
-purple_savedstatuses_init(void)
-{
-	PurpleAccountManager *manager = purple_account_manager_get_default();
-	void *handle = purple_savedstatuses_get_handle();
-
-	creation_times = g_hash_table_new(g_direct_hash, g_direct_equal);
-
-	/*
-	 * Using 0 as the creation_time is a special case.
-	 * If someone calls purple_savedstatus_get_current() or
-	 * purple_savedstatus_get_idleaway() and either of those functions
-	 * sees a creation_time of 0, then it will create a default
-	 * saved status and return that to the user.
-	 */
-	purple_prefs_add_none("/purple/savedstatus");
-	purple_prefs_add_int("/purple/savedstatus/default", 0);
-	purple_prefs_add_int("/purple/savedstatus/startup", 0);
-	purple_prefs_add_bool("/purple/savedstatus/startup_current_status", TRUE);
-	purple_prefs_add_int("/purple/savedstatus/idleaway", 0);
-	purple_prefs_add_bool("/purple/savedstatus/isidleaway", FALSE);
-
-	load_statuses();
-
-	purple_signal_register(handle, "savedstatus-changed",
-					 purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
-					 PURPLE_TYPE_SAVEDSTATUS, PURPLE_TYPE_SAVEDSTATUS);
-
-	purple_signal_register(handle, "savedstatus-added",
-		purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
-		PURPLE_TYPE_SAVEDSTATUS);
-
-	purple_signal_register(handle, "savedstatus-deleted",
-		purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
-		PURPLE_TYPE_SAVEDSTATUS);
-
-	purple_signal_register(handle, "savedstatus-modified",
-		purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
-		PURPLE_TYPE_SAVEDSTATUS);
-
-	g_signal_connect(manager, "removed",
-	                 G_CALLBACK(purple_savedstatus_unset_all_substatuses),
-	                 NULL);
-}
-
-void
-purple_savedstatuses_uninit(void)
-{
-	PurpleAccountManager *manager = purple_account_manager_get_default();
-	gpointer handle = purple_savedstatuses_get_handle();
-
-	remove_old_transient_statuses();
-
-	if(save_timer != 0) {
-		g_clear_handle_id(&save_timer, g_source_remove);
-		sync_statuses();
-	}
-
-	g_clear_list(&saved_statuses, (GDestroyNotify)free_saved_status);
-
-	g_clear_pointer(&creation_times, g_hash_table_destroy);
-
-	g_signal_handlers_disconnect_by_func(manager,
-	                                     purple_savedstatus_unset_all_substatuses,
-	                                     NULL);
-	purple_signals_unregister_by_instance(handle);
-	purple_signals_disconnect_by_handle(handle);
-}
diff --git a/libpurple/server.c b/libpurple/server.c
--- a/libpurple/server.c
+++ b/libpurple/server.c
@@ -39,7 +39,6 @@
 #include "request.h"
 #include "signals.h"
 #include "server.h"
-#include "status.h"
 #include "util.h"
 
 unsigned int
diff --git a/libpurple/status.h b/libpurple/status.h
deleted file mode 100644
--- a/libpurple/status.h
+++ /dev/null
@@ -1,892 +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_STATUS_H
-#define PURPLE_STATUS_H
-
-#include "purpleversion.h"
-
-#define PURPLE_TYPE_STATUS (purple_status_get_type())
-typedef struct _PurpleStatus PurpleStatus;
-
-#define PURPLE_TYPE_STATUS_TYPE (purple_status_type_get_type())
-
-/**
- * PurpleStatusType:
- *
- * PurpleStatusType's are created by each protocol.  They outline the
- * available statuses of the protocol.  AIM, for example, supports
- * an available state with an optional available message, an away
- * state with a mandatory message, and an invisible state (which is
- * technically "independent" of the other two, but we'll get into
- * that later).  PurpleStatusTypes are very permanent.  They are
- * hardcoded in each protocol and will not change often.  And because
- * they are hardcoded, they do not need to be saved to any XML file.
- *
- * Since: 2.0
- */
-typedef struct _PurpleStatusType PurpleStatusType;
-
-#define PURPLE_TYPE_STATUS_ATTRIBUTE (purple_status_attribute_get_type())
-
-/**
- * PurpleStatus:
- *
- * A PurpleStatus can be thought of as an "instance" of a PurpleStatusType.
- * If you're familiar with object-oriented programming languages
- * then this should be immediately clear.  Say, for example, that
- * one of your AIM buddies has set himself as "away."  You have a
- * PurpleBuddy node for this person in your buddy list.  Purple wants
- * to mark this buddy as "away," so it creates a new PurpleStatus.
- * The PurpleStatus has its PurpleStatusType set to the "away" state
- * for the oscar protocol.  The PurpleStatus also contains the buddy's
- * away message.  PurpleStatuses are sometimes saved, depending on
- * the context.  The current PurpleStatuses associated with each of
- * your accounts are saved so that the next time you start Purple,
- * your accounts will be set to their last known statuses.  There
- * is also a list of saved statuses that are written to the
- * status.xml file.  Also, each PurpleStatus has a "saveable" boolean.
- * If "saveable" is set to FALSE then the status is NEVER saved.
- * All PurpleStatuses should be inside a PurplePresence.
- *
- * A PurpleStatus is either "independent" or "exclusive."
- * Independent statuses can be active or inactive and they don't
- * affect anything else.  However, you can only have one exclusive
- * status per PurplePresence.  If you activate one exclusive status,
- * then the previous exclusive status is automatically deactivated.
- *
- * A PurplePresence is like a collection of PurpleStatuses (plus some
- * other random info).
- *
- * See <link linkend="libpurple-purplepresence">Presence API</link>
- *
- * Since: 2.0
- */
-
-/**
- * PurpleStatusAttribute:
- *
- * An attribute that can be added to a status.
- *
- * Since: 2.0
- */
-typedef struct _PurpleStatusAttribute PurpleStatusAttribute;
-
-/**
- * PurpleStatusPrimitive:
- * @PURPLE_STATUS_UNSET: The status is not set
- * @PURPLE_STATUS_OFFLINE: The status is offline
- * @PURPLE_STATUS_AVAILABLE: The status is available
- * @PURPLE_STATUS_UNAVAILABLE: The status is unavailable
- * @PURPLE_STATUS_INVISIBLE: The stuatus is invisible
- * @PURPLE_STATUS_AWAY: The status is away
- * @PURPLE_STATUS_EXTENDED_AWAY: The status is extended away/do not disturb
- * @PURPLE_STATUS_MOBILE: The status is mobile
- * @PURPLE_STATUS_NUM_PRIMITIVES: The number of #PurpleStatusPrimitive<!-- -->s
- *
- * A primitive defining the basic structure of a status type.
- *
- * Since: 2.0
- */
-/*
- * If you add a value to this enum, make sure you update
- * the status_primitive_map and primitive_scores arrays in status.c.
- */
-typedef enum
-{
-	PURPLE_STATUS_UNSET = 0,
-	PURPLE_STATUS_OFFLINE,
-	PURPLE_STATUS_AVAILABLE,
-	PURPLE_STATUS_UNAVAILABLE,
-	PURPLE_STATUS_INVISIBLE,
-	PURPLE_STATUS_AWAY,
-	PURPLE_STATUS_EXTENDED_AWAY,
-	PURPLE_STATUS_MOBILE,
-
-	PURPLE_STATUS_NUM_PRIMITIVES, /*< skip >*/
-} PurpleStatusPrimitive;
-
-#include "purplepresence.h"
-
-G_BEGIN_DECLS
-
-/**************************************************************************/
-/* PurpleStatusPrimitive API                                              */
-/**************************************************************************/
-
-/**
- * purple_primitive_get_id_from_type:
- * @type: A primitive status type.
- *
- * Lookup the id of a primitive status type based on the type.  This
- * ID is a unique plain-text name of the status, without spaces.
- *
- * Returns: The unique ID for this type.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_primitive_get_id_from_type(PurpleStatusPrimitive type);
-
-/**
- * purple_primitive_get_name_from_type:
- * @type: A primitive status type.
- *
- * Lookup the name of a primitive status type based on the type.  This
- * name is the plain-English name of the status type.  It is usually one
- * or two words.
- *
- * Returns: The name of this type, suitable for users to see.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_primitive_get_name_from_type(PurpleStatusPrimitive type);
-
-/**
- * purple_primitive_get_type_from_id:
- * @id: The unique ID of a primitive status type.
- *
- * Lookup the value of a primitive status type based on the id.  The
- * ID is a unique plain-text name of the status, without spaces.
- *
- * Returns: The PurpleStatusPrimitive value.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatusPrimitive purple_primitive_get_type_from_id(const char *id);
-
-/**************************************************************************/
-/* PurpleStatusType API                                                   */
-/**************************************************************************/
-
-/**
- * purple_status_type_get_type:
- *
- * The standard _get_type function for #PurpleStatusType.
- *
- * Returns: The #GType for #PurpleStatusType.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-GType purple_status_type_get_type(void);
-
-/**
- * purple_status_type_new_full:
- * @primitive: The primitive status type.
- * @id: The ID of the status type, or %NULL to use the id of the primitive
- *      status type.
- * @name: The name presented to the user, or %NULL to use the name of the
- *        primitive status type.
- * @saveable: %TRUE if the information set for this status by the user can be
- *            saved for future sessions.
- * @user_settable: %TRUE if this is a status the user can manually set.
- * @independent: %TRUE if this is an independent (non-exclusive) status type.
- *
- * Creates a new status type.
- *
- * Returns: (transfer full): A new status type.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatusType *purple_status_type_new_full(PurpleStatusPrimitive primitive,
-										  const char *id, const char *name,
-										  gboolean saveable,
-										  gboolean user_settable,
-										  gboolean independent);
-
-/**
- * purple_status_type_new:
- * @primitive: The primitive status type.
- * @id: The ID of the status type, or %NULL to use the id of the primitive
- *      status type.
- * @name: The name presented to the user, or %NULL to use the name of the
- *        primitive status type.
- * @user_settable: %TRUE if this is a status the user can manually set.
- *
- * Creates a new status type with some default values (saveable and not
- * independent).
- *
- * Returns: (transfer full): A new status type.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatusType *purple_status_type_new(PurpleStatusPrimitive primitive,
-									 const char *id, const char *name,
-									 gboolean user_settable);
-
-/**
- * purple_status_type_new_with_attrs:
- * @primitive: The primitive status type.
- * @id: The ID of the status type, or %NULL to use the id of the primitive
- *      status type.
- * @name: The name presented to the user, or %NULL to use the name of the
- *        primitive status type.
- * @saveable: %TRUE if the information set for this status by the user can be
- *            saved for future sessions.
- * @user_settable: %TRUE if this is a status the user can manually set.
- * @independent: %TRUE if this is an independent (non-exclusive) status type.
- * @attr_id: The ID of the first attribute.
- * @attr_name: The name of the first attribute.
- * @attr_value: The value type of the first attribute.
- * @...: Additional attribute information.
- *
- * Creates a new status type with attributes.
- *
- * Returns: (transfer full): A new status type.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatusType *purple_status_type_new_with_attrs(PurpleStatusPrimitive primitive,
-												const char *id,
-												const char *name,
-												gboolean saveable,
-												gboolean user_settable,
-												gboolean independent,
-												const char *attr_id,
-												const char *attr_name,
-												GValue *attr_value, ...) G_GNUC_NULL_TERMINATED;
-
-/**
- * purple_status_type_new_with_attrsv: (rename-to purple_status_type_new_with_attrs):
- * @primitive: The primitive status type.
- * @id: The ID of the status type, or %NULL to use the id of the primitive
- *      status type.
- * @name: The name presented to the user, or %NULL to use the name of the
- *        primitive status type.
- * @saveable: %TRUE if the information set for this status by the user can be
- *            saved for future sessions.
- * @user_settable: %TRUE if this is a status the user can manually set.
- * @independent: %TRUE if this is an independent (non-exclusive) status type.
- * @n_attributes: The number of attributes.
- * @attr_id: (array length=n_attributes): The IDs of the attributes.
- * @attr_name: (array length=n_attributes): The names of the attributes.
- * @attr_value: (array length=n_attributes): The value types of the attributes.
- *
- * Creates a new status type with attributes.
- *
- * Returns: (transfer full): A new status type.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-PurpleStatusType *purple_status_type_new_with_attrsv(PurpleStatusPrimitive primitive,
-                                                     const gchar *id,
-                                                     const gchar *name,
-                                                     gboolean saveable,
-                                                     gboolean user_settable,
-                                                     gboolean independent,
-                                                     guint n_attributes,
-                                                     const gchar *attr_id[],
-                                                     const gchar *attr_name[],
-                                                     GValue *attr_value[]);
-
-/**
- * purple_status_type_destroy:
- * @status_type: The status type to destroy.
- *
- * Destroys a status type.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_status_type_destroy(PurpleStatusType *status_type);
-
-/**
- * purple_status_type_get_primitive:
- * @status_type: The status type.
- *
- * Returns the primitive type of a status type.
- *
- * Returns: The primitive type of the status type.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatusPrimitive purple_status_type_get_primitive(
-	const PurpleStatusType *status_type);
-
-/**
- * purple_status_type_get_id:
- * @status_type: The status type.
- *
- * Returns the ID of a status type.
- *
- * Returns: The ID of the status type.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_status_type_get_id(const PurpleStatusType *status_type);
-
-/**
- * purple_status_type_get_name:
- * @status_type: The status type.
- *
- * Returns the name of a status type.
- *
- * Returns: The name of the status type.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_status_type_get_name(const PurpleStatusType *status_type);
-
-/**
- * purple_status_type_is_saveable:
- * @status_type: The status type.
- *
- * Returns whether or not the status type is saveable.
- *
- * Returns: TRUE if user-defined statuses based off this type are saveable.
- *         FALSE otherwise.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_type_is_saveable(const PurpleStatusType *status_type);
-
-/**
- * purple_status_type_is_user_settable:
- * @status_type: The status type.
- *
- * Returns whether or not the status type can be set or modified by the
- * user.
- *
- * Returns: TRUE if the status type can be set or modified by the user.
- *         FALSE if it's a protocol-set setting.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_type_is_user_settable(const PurpleStatusType *status_type);
-
-/**
- * purple_status_type_is_independent:
- * @status_type: The status type.
- *
- * Returns whether or not the status type is independent.
- *
- * Independent status types are non-exclusive. If other status types on
- * the same hierarchy level are set, this one will not be affected.
- *
- * Returns: TRUE if the status type is independent, or FALSE otherwise.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_type_is_independent(const PurpleStatusType *status_type);
-
-/**
- * purple_status_type_is_exclusive:
- * @status_type: The status type.
- *
- * Returns whether the status type is exclusive.
- *
- * Returns: TRUE if the status type is exclusive, FALSE otherwise.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_type_is_exclusive(const PurpleStatusType *status_type);
-
-/**
- * purple_status_type_is_available:
- * @status_type: The status type.
- *
- * Returns whether or not a status type is available.
- *
- * Available status types are online and possibly invisible, but not away.
- *
- * Returns: TRUE if the status is available, or FALSE otherwise.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_type_is_available(const PurpleStatusType *status_type);
-
-/**
- * purple_status_type_get_attr:
- * @status_type: The status type containing the attribute.
- * @id:          The ID of the desired attribute.
- *
- * Returns the attribute with the specified ID.
- *
- * Returns: The attribute, if found. NULL otherwise.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatusAttribute *purple_status_type_get_attr(const PurpleStatusType *status_type,
-										  const char *id);
-
-/**
- * purple_status_type_get_attrs:
- * @status_type: The status type.
- *
- * Returns a list of all attributes in a status type.
- *
- * Returns: (element-type PurpleStatusAttribute) (transfer none): The list of attributes.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-GList *purple_status_type_get_attrs(const PurpleStatusType *status_type);
-
-/**
- * purple_status_type_find_with_id:
- * @status_types: (element-type PurpleStatus) (transfer none): A list of status
- *                types.  Often account->status_types.
- * @id: The unique ID of the status type you wish to find.
- *
- * Find the PurpleStatusType with the given id.
- *
- * Returns: The status type with the given ID, or NULL if one could
- *         not be found.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const PurpleStatusType *purple_status_type_find_with_id(GList *status_types,
-													const char *id);
-
-/**************************************************************************/
-/* PurpleStatusAttribute API                                              */
-/**************************************************************************/
-
-/**
- * purple_status_attribute_get_type:
- *
- * The standard _get_type function for #PurpleStatusAttribute.
- *
- * Returns: The #GType for the #PurpleStatusAttribute boxed structure.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-GType purple_status_attribute_get_type(void);
-
-/**
- * purple_status_attribute_new:
- * @id:         The ID of the attribute.
- * @name:       The name presented to the user.
- * @value_type: The type of data contained in the attribute.
- *
- * Creates a new status attribute.
- *
- * Returns: A new status attribute.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-PurpleStatusAttribute *purple_status_attribute_new(const char *id, const char *name,
-									 GValue *value_type);
-
-/**
- * purple_status_attribute_destroy:
- * @attr: The status attribute to destroy.
- *
- * Destroys a status attribute.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_status_attribute_destroy(PurpleStatusAttribute *attr);
-
-/**
- * purple_status_attribute_get_id:
- * @attr: The status attribute.
- *
- * Returns the ID of a status attribute.
- *
- * Returns: The status attribute's ID.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-const char *purple_status_attribute_get_id(const PurpleStatusAttribute *attr);
-
-/**
- * purple_status_attribute_get_name:
- * @attr: The status attribute.
- *
- * Returns the name of a status attribute.
- *
- * Returns: The status attribute's name.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-const char *purple_status_attribute_get_name(const PurpleStatusAttribute *attr);
-
-/**
- * purple_status_attribute_get_value:
- * @attr: The status attribute.
- *
- * Returns the value of a status attribute.
- *
- * Returns: The status attribute's value.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-GValue *purple_status_attribute_get_value(const PurpleStatusAttribute *attr);
-
-/**************************************************************************/
-/* PurpleStatus API                                                       */
-/**************************************************************************/
-
-/**
- * purple_status_get_type:
- *
- * The standard _get_type function for #PurpleStatus.
- *
- * Returns: The #GType for #PurpleStatus.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-G_DECLARE_FINAL_TYPE(PurpleStatus, purple_status, PURPLE, STATUS, GObject)
-
-/**
- * purple_status_new:
- * @status_type: The type of status.
- * @presence:    The parent presence.
- *
- * Creates a new status.
- *
- * Returns: The new status.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleStatus *purple_status_new(PurpleStatusType *status_type,
-							PurplePresence *presence);
-
-/**
- * purple_status_set_active:
- * @status: The status.
- * @active: The active state.
- *
- * Sets whether or not a status is active.
- *
- * This should only be called by the account, conversation, and buddy APIs.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_status_set_active(PurpleStatus *status, gboolean active);
-
-/**
- * purple_status_set_active_with_attributes:
- * @status: The status.
- * @active: The active state.
- * @attrs: (nullable) (element-type utf8 gpointer): A hash table of attributes
- *         to set on the status. This hash table's keys are valid attribute
- *         names for this PurpleStatusType. The hash table is not modified or
- *         freed by this function.
- *
- * Sets whether or not a status is active.
- *
- * This should only be called by the account, conversation, and buddy APIs.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_status_set_active_with_attributes(PurpleStatus *status, gboolean active, GHashTable *attrs);
-
-/**
- * purple_status_get_status_type:
- * @status: The status.
- *
- * Returns the status's type.
- *
- * Returns: The status's type.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-PurpleStatusType *purple_status_get_status_type(PurpleStatus *status);
-
-/**
- * purple_status_get_presence:
- * @status: The status.
- *
- * Returns the status's presence.
- *
- * Returns: (transfer none): The status's presence.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurplePresence *purple_status_get_presence(PurpleStatus *status);
-
-/**
- * purple_status_get_id:
- * @status: The status.
- *
- * Returns the status's type ID.
- *
- * This is a convenience method for
- * purple_status_type_get_id(purple_status_get_status_type(status)).
- *
- * Returns: The status's ID.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_status_get_id(PurpleStatus *status);
-
-/**
- * purple_status_get_name:
- * @status: The status.
- *
- * Returns the status's name.
- *
- * This is a convenience method for
- * purple_status_type_get_name(purple_status_get_status_type(status)).
- *
- * Returns: The status's name.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_status_get_name(PurpleStatus *status);
-
-/**
- * purple_status_is_independent:
- * @status: The status.
- *
- * Returns whether or not a status is independent.
- *
- * This is a convenience method for
- * purple_status_type_is_independent(purple_status_get_status_type(status)).
- *
- * Returns: TRUE if the status is independent, or FALSE otherwise.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_is_independent(PurpleStatus *status);
-
-/**
- * purple_status_is_exclusive:
- * @status: The status.
- *
- * Returns whether or not a status is exclusive.
- *
- * This is a convenience method for
- * purple_status_type_is_exclusive(purple_status_get_status_type(status)).
- *
- * Returns: TRUE if the status is exclusive, FALSE otherwise.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_is_exclusive(PurpleStatus *status);
-
-/**
- * purple_status_is_available:
- * @status: The status.
- *
- * Returns whether or not a status is available.
- *
- * Available statuses are online and possibly invisible, but not away or idle.
- *
- * This is a convenience method for
- * purple_status_type_is_available(purple_status_get_status_type(status)).
- *
- * Returns: TRUE if the status is available, or FALSE otherwise.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_is_available(PurpleStatus *status);
-
-/**
- * purple_status_is_active:
- * @status: The status.
- *
- * Returns the active state of a status.
- *
- * Returns: The active state of the status.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_is_active(PurpleStatus *status);
-
-/**
- * purple_status_is_online:
- * @status: The status.
- *
- * Returns whether or not a status is considered 'online'
- *
- * Returns: TRUE if the status is considered online, FALSE otherwise
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_is_online(PurpleStatus *status);
-
-/**
- * purple_status_get_attr_value:
- * @status: The status.
- * @id:     The attribute ID.
- *
- * Returns the value of an attribute in a status with the specified ID.
- *
- * Returns: The value of the attribute.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-GValue *purple_status_get_attr_value(PurpleStatus *status,
-									 const char *id);
-
-/**
- * purple_status_get_attr_boolean:
- * @status: The status.
- * @id:     The attribute ID.
- *
- * Returns the boolean value of an attribute in a status with the specified ID.
- *
- * Returns: The boolean value of the attribute.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_status_get_attr_boolean(PurpleStatus *status,
-									    const char *id);
-
-/**
- * purple_status_get_attr_int:
- * @status: The status.
- * @id:     The attribute ID.
- *
- * Returns the integer value of an attribute in a status with the specified ID.
- *
- * Returns: The integer value of the attribute.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-int purple_status_get_attr_int(PurpleStatus *status, const char *id);
-
-/**
- * purple_status_get_attr_string:
- * @status: The status.
- * @id:     The attribute ID.
- *
- * Returns the string value of an attribute in a status with the specified ID.
- *
- * Returns: The string value of the attribute.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_status_get_attr_string(PurpleStatus *status, const char *id);
-
-/**
- * purple_status_compare:
- * @status1: The first status.
- * @status2: The second status.
- *
- * Compares two statuses for availability.
- *
- * Returns: -1 if @status1 is more available than @status2.
- *           0 if @status1 is equal to @status2.
- *           1 if @status2 is more available than @status1.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gint purple_status_compare(PurpleStatus *status1, PurpleStatus *status2);
-
-/**************************************************************************/
-/* Statuses subsystem                                                     */
-/**************************************************************************/
-
-/**
- * purple_statuses_get_handle:
- *
- * Get the handle for the status subsystem.
- *
- * Returns: the handle to the status subsystem
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void *purple_statuses_get_handle(void);
-
-/**
- * purple_statuses_init:
- *
- * Initializes the status subsystem.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_statuses_init(void);
-
-/**
- * purple_statuses_uninit:
- *
- * Uninitializes the status subsystem.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_statuses_uninit(void);
-
-/**************************************************************************/
-/* Helpers                                                                */
-/**************************************************************************/
-
-/**
- * purple_attrs_from_vargs:
- * @args:   A list of attributes to parse.  This list is
- *               composed of key/value pairs, where each key is a valid
- *               attribute name for this PurpleStatusType.  The list should
- *               be NULL terminated.
- *
- * Returns a hash table of attributes constructed from args.
- *
- * Returns: (element-type utf8 gpointer) (transfer container): The hash table of attributes.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-GHashTable *purple_attrs_from_vargs(va_list args);
-
-G_END_DECLS
-
-#endif /* PURPLE_STATUS_H */
diff --git a/libpurple/status.c b/libpurple/status.c
deleted file mode 100644
--- a/libpurple/status.c
+++ /dev/null
@@ -1,1248 +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 "purpleprivate.h"
-
-#include "buddylist.h"
-#include "core.h"
-#include "debug.h"
-#include "notify.h"
-#include "prefs.h"
-#include "status.h"
-
-/*
- * A type of status.
- */
-struct _PurpleStatusType
-{
-	int box_count;
-
-	PurpleStatusPrimitive primitive;
-
-	char *id;
-	char *name;
-
-	gboolean saveable;
-	gboolean user_settable;
-	gboolean independent;
-
-	GList *attrs;
-};
-
-/*
- * A status attribute.
- */
-struct _PurpleStatusAttribute
-{
-	char *id;
-	char *name;
-	GValue *value_type;
-};
-
-struct _PurpleStatus
-{
-	GObject parent;
-
-	PurpleStatusType *status_type;
-	PurplePresence *presence;
-
-	gboolean active;
-
-	/*
-	 * The current values of the attributes for this status.  The
-	 * key is a string containing the name of the attribute.  It is
-	 * a borrowed reference from the list of attrs in the
-	 * PurpleStatusType.  The value is a GValue.
-	 */
-	GHashTable *attr_values;
-};
-
-/* GObject property enums */
-enum
-{
-	PROP_0,
-	PROP_STATUS_TYPE,
-	PROP_PRESENCE,
-	PROP_ACTIVE,
-	N_PROPERTIES,
-};
-
-static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-
-G_DEFINE_FINAL_TYPE(PurpleStatus, purple_status, G_TYPE_OBJECT)
-
-static int primitive_scores[] =
-{
-	0,      /* unset                    */
-	-500,   /* offline                  */
-	100,    /* available                */
-	-75,    /* unavailable              */
-	-50,    /* invisible                */
-	-100,   /* away                     */
-	-200,   /* extended away            */
-	-400,   /* mobile                   */
-	-10,    /* idle, special case.      */
-	-5,     /* idle time, special case. */
-	10      /* Offline messageable      */
-};
-
-enum {
-	SCORE_IDLE = PURPLE_STATUS_NUM_PRIMITIVES,
-	SCORE_IDLE_TIME,
-	SCORE_OFFLINE_MESSAGE,
-};
-
-/**************************************************************************
- * PurpleStatusPrimitive API
- **************************************************************************/
-static struct PurpleStatusPrimitiveMap
-{
-	PurpleStatusPrimitive type;
-	const char *id;
-	const char *name;
-
-} const status_primitive_map[] =
-{
-	{ PURPLE_STATUS_UNSET,           "unset",           N_("Unset")               },
-	{ PURPLE_STATUS_OFFLINE,         "offline",         N_("Offline")             },
-	{ PURPLE_STATUS_AVAILABLE,       "available",       N_("Available")           },
-	{ PURPLE_STATUS_UNAVAILABLE,     "unavailable",     N_("Do not disturb")      },
-	{ PURPLE_STATUS_INVISIBLE,       "invisible",       N_("Invisible")           },
-	{ PURPLE_STATUS_AWAY,            "away",            N_("Away")                },
-	{ PURPLE_STATUS_EXTENDED_AWAY,   "extended_away",   N_("Extended away")       },
-	{ PURPLE_STATUS_MOBILE,          "mobile",          N_("Mobile")              },
-};
-
-int *
-_purple_statuses_get_primitive_scores(void)
-{
-	return primitive_scores;
-}
-
-const char *
-purple_primitive_get_id_from_type(PurpleStatusPrimitive type)
-{
-    int i;
-
-    for (i = 0; i < PURPLE_STATUS_NUM_PRIMITIVES; i++)
-    {
-		if (type == status_primitive_map[i].type)
-			return status_primitive_map[i].id;
-    }
-
-    return status_primitive_map[0].id;
-}
-
-const char *
-purple_primitive_get_name_from_type(PurpleStatusPrimitive type)
-{
-    int i;
-
-    for (i = 0; i < PURPLE_STATUS_NUM_PRIMITIVES; i++)
-    {
-	if (type == status_primitive_map[i].type)
-		return _(status_primitive_map[i].name);
-    }
-
-    return _(status_primitive_map[0].name);
-}
-
-PurpleStatusPrimitive
-purple_primitive_get_type_from_id(const char *id)
-{
-    int i;
-
-    g_return_val_if_fail(id != NULL, PURPLE_STATUS_UNSET);
-
-    for (i = 0; i < PURPLE_STATUS_NUM_PRIMITIVES; i++)
-    {
-		if (purple_strequal(id, status_primitive_map[i].id))
-            return status_primitive_map[i].type;
-    }
-
-    return status_primitive_map[0].type;
-}
-
-
-/**************************************************************************
- * PurpleStatusType API
- **************************************************************************/
-PurpleStatusType *
-purple_status_type_new_full(PurpleStatusPrimitive primitive, const char *id,
-						  const char *name, gboolean saveable,
-						  gboolean user_settable, gboolean independent)
-{
-	PurpleStatusType *status_type;
-
-	g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, NULL);
-
-	status_type = g_new0(PurpleStatusType, 1);
-
-	status_type->primitive     = primitive;
-	status_type->saveable      = saveable;
-	status_type->user_settable = user_settable;
-	status_type->independent   = independent;
-
-	if (id != NULL)
-		status_type->id = g_strdup(id);
-	else
-		status_type->id = g_strdup(purple_primitive_get_id_from_type(primitive));
-
-	if (name != NULL)
-		status_type->name = g_strdup(name);
-	else
-		status_type->name = g_strdup(purple_primitive_get_name_from_type(primitive));
-
-	return status_type;
-}
-
-PurpleStatusType *
-purple_status_type_new(PurpleStatusPrimitive primitive, const char *id,
-					 const char *name, gboolean user_settable)
-{
-	g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, NULL);
-
-	return purple_status_type_new_full(primitive, id, name, TRUE,
-			user_settable, FALSE);
-}
-
-static void
-status_type_add_attr(PurpleStatusType *status_type, const char *id,
-		const char *name, GValue *value)
-{
-	PurpleStatusAttribute *attr;
-
-	g_return_if_fail(status_type != NULL);
-	g_return_if_fail(id          != NULL);
-	g_return_if_fail(name        != NULL);
-	g_return_if_fail(value       != NULL);
-
-	attr = purple_status_attribute_new(id, name, value);
-
-	status_type->attrs = g_list_append(status_type->attrs, attr);
-}
-
-static void
-status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args)
-{
-	const char *id, *name;
-	GValue *value;
-
-	g_return_if_fail(status_type != NULL);
-
-	while ((id = va_arg(args, const char *)) != NULL)
-	{
-		name = va_arg(args, const char *);
-		g_return_if_fail(name != NULL);
-
-		value = va_arg(args, GValue *);
-		g_return_if_fail(value != NULL);
-
-		status_type_add_attr(status_type, id, name, value);
-	}
-}
-
-PurpleStatusType *
-purple_status_type_new_with_attrs(PurpleStatusPrimitive primitive,
-		const char *id, const char *name,
-		gboolean saveable, gboolean user_settable,
-		gboolean independent, const char *attr_id,
-		const char *attr_name, GValue *attr_value,
-		...)
-{
-	PurpleStatusType *status_type;
-	va_list args;
-
-	g_return_val_if_fail(primitive  != PURPLE_STATUS_UNSET, NULL);
-	g_return_val_if_fail(attr_id    != NULL,              NULL);
-	g_return_val_if_fail(attr_name  != NULL,              NULL);
-	g_return_val_if_fail(attr_value != NULL,              NULL);
-
-	status_type = purple_status_type_new_full(primitive, id, name, saveable,
-			user_settable, independent);
-
-	/* Add the first attribute */
-	status_type_add_attr(status_type, attr_id, attr_name, attr_value);
-
-	va_start(args, attr_value);
-	status_type_add_attrs_vargs(status_type, args);
-	va_end(args);
-
-	return status_type;
-}
-
-PurpleStatusType *
-purple_status_type_new_with_attrsv(PurpleStatusPrimitive primitive,
-                                   const char *id, const char *name,
-                                   gboolean saveable, gboolean user_settable,
-                                   gboolean independent, guint n_attributes,
-                                   const char *attr_id[],
-                                   const char *attr_name[],
-                                   GValue *attr_value[])
-{
-	PurpleStatusType *status_type;
-
-	g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, NULL);
-	g_return_val_if_fail(attr_id != NULL, NULL);
-	g_return_val_if_fail(attr_name != NULL, NULL);
-	g_return_val_if_fail(attr_value != NULL, NULL);
-
-	status_type = purple_status_type_new_full(primitive, id, name, saveable,
-	                                          user_settable, independent);
-
-	for(guint i = 0; i < n_attributes; i++) {
-		if(attr_id[i] == NULL || attr_name[i] == NULL ||
-		   attr_value[i] == NULL)
-		{
-			purple_status_type_destroy(status_type);
-			g_return_val_if_fail(attr_id[i] != NULL, NULL);
-			g_return_val_if_fail(attr_name[i] != NULL, NULL);
-			g_return_val_if_fail(attr_value[i] != NULL, NULL);
-			return NULL;
-		}
-
-		status_type_add_attr(status_type, attr_id[i], attr_name[i],
-		                     attr_value[i]);
-	}
-
-	return status_type;
-}
-
-void
-purple_status_type_destroy(PurpleStatusType *status_type)
-{
-	g_return_if_fail(status_type != NULL);
-
-	g_free(status_type->id);
-	g_free(status_type->name);
-
-	g_list_free_full(status_type->attrs,
-	                 (GDestroyNotify)purple_status_attribute_destroy);
-
-	g_free(status_type);
-}
-
-PurpleStatusPrimitive
-purple_status_type_get_primitive(const PurpleStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, PURPLE_STATUS_UNSET);
-
-	return status_type->primitive;
-}
-
-const char *
-purple_status_type_get_id(const PurpleStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, NULL);
-
-	return status_type->id;
-}
-
-const char *
-purple_status_type_get_name(const PurpleStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, NULL);
-
-	return status_type->name;
-}
-
-gboolean
-purple_status_type_is_saveable(const PurpleStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, FALSE);
-
-	return status_type->saveable;
-}
-
-gboolean
-purple_status_type_is_user_settable(const PurpleStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, FALSE);
-
-	return status_type->user_settable;
-}
-
-gboolean
-purple_status_type_is_independent(const PurpleStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, FALSE);
-
-	return status_type->independent;
-}
-
-gboolean
-purple_status_type_is_exclusive(const PurpleStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, FALSE);
-
-	return !status_type->independent;
-}
-
-gboolean
-purple_status_type_is_available(const PurpleStatusType *status_type)
-{
-	PurpleStatusPrimitive primitive;
-
-	g_return_val_if_fail(status_type != NULL, FALSE);
-
-	primitive = purple_status_type_get_primitive(status_type);
-
-	return (primitive == PURPLE_STATUS_AVAILABLE);
-}
-
-PurpleStatusAttribute *
-purple_status_type_get_attr(const PurpleStatusType *status_type, const char *id)
-{
-	GList *l;
-
-	g_return_val_if_fail(status_type != NULL, NULL);
-	g_return_val_if_fail(id          != NULL, NULL);
-
-	for (l = status_type->attrs; l != NULL; l = l->next)
-	{
-		PurpleStatusAttribute *attr = (PurpleStatusAttribute *)l->data;
-
-		if (purple_strequal(purple_status_attribute_get_id(attr), id))
-			return attr;
-	}
-
-	return NULL;
-}
-
-GList *
-purple_status_type_get_attrs(const PurpleStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, NULL);
-
-	return status_type->attrs;
-}
-
-const PurpleStatusType *
-purple_status_type_find_with_id(GList *status_types, const char *id)
-{
-	PurpleStatusType *status_type;
-
-	g_return_val_if_fail(id != NULL, NULL);
-
-	while (status_types != NULL)
-	{
-		status_type = status_types->data;
-
-		if (purple_strequal(id, status_type->id))
-			return status_type;
-
-		status_types = status_types->next;
-	}
-
-	return NULL;
-}
-
-
-/**************************************************************************
-* PurpleStatusAttribute API
-**************************************************************************/
-PurpleStatusAttribute *
-purple_status_attribute_new(const char *id, const char *name, GValue *value_type)
-{
-	PurpleStatusAttribute *attr;
-
-	g_return_val_if_fail(id         != NULL, NULL);
-	g_return_val_if_fail(name       != NULL, NULL);
-	g_return_val_if_fail(value_type != NULL, NULL);
-
-	attr = g_new0(PurpleStatusAttribute, 1);
-
-	attr->id         = g_strdup(id);
-	attr->name       = g_strdup(name);
-	attr->value_type = value_type;
-
-	return attr;
-}
-
-void
-purple_status_attribute_destroy(PurpleStatusAttribute *attr)
-{
-	g_return_if_fail(attr != NULL);
-
-	g_free(attr->id);
-	g_free(attr->name);
-
-	purple_value_free(attr->value_type);
-
-	g_free(attr);
-}
-
-const char *
-purple_status_attribute_get_id(const PurpleStatusAttribute *attr)
-{
-	g_return_val_if_fail(attr != NULL, NULL);
-
-	return attr->id;
-}
-
-const char *
-purple_status_attribute_get_name(const PurpleStatusAttribute *attr)
-{
-	g_return_val_if_fail(attr != NULL, NULL);
-
-	return attr->name;
-}
-
-GValue *
-purple_status_attribute_get_value(const PurpleStatusAttribute *attr)
-{
-	g_return_val_if_fail(attr != NULL, NULL);
-
-	return attr->value_type;
-}
-
-
-/**************************************************************************
-* PurpleStatus API
-**************************************************************************/
-static void
-status_has_changed(PurpleStatus *status)
-{
-	PurplePresence *presence;
-	PurpleStatus *old_status;
-
-	presence   = purple_status_get_presence(status);
-
-	/*
-	 * If this status is exclusive, then we must be setting it to "active."
-	 * Since we are setting it to active, we want to set the currently
-	 * active status to "inactive."
-	 */
-	if (purple_status_is_exclusive(status))
-	{
-		old_status = purple_presence_get_active_status(presence);
-		if (old_status != NULL && (old_status != status)) {
-			old_status->active = FALSE;
-			g_object_notify_by_pspec(G_OBJECT(old_status),
-					properties[PROP_ACTIVE]);
-		}
-	}
-	else
-		old_status = NULL;
-
-	g_object_set(presence, "active-status", status, NULL);
-	g_object_notify_by_pspec(G_OBJECT(status), properties[PROP_ACTIVE]);
-}
-
-static void
-status_set_attr_boolean(PurpleStatus *status, const char *id,
-		gboolean value)
-{
-	GValue *attr_value;
-
-	g_return_if_fail(PURPLE_IS_STATUS(status));
-	g_return_if_fail(id != NULL);
-
-	/* Make sure this attribute exists and is the correct type. */
-	attr_value = purple_status_get_attr_value(status, id);
-	g_return_if_fail(attr_value != NULL);
-	g_return_if_fail(G_VALUE_TYPE(attr_value) == G_TYPE_BOOLEAN);
-
-	g_value_set_boolean(attr_value, value);
-}
-
-static void
-status_set_attr_int(PurpleStatus *status, const char *id, int value)
-{
-	GValue *attr_value;
-
-	g_return_if_fail(PURPLE_IS_STATUS(status));
-	g_return_if_fail(id != NULL);
-
-	/* Make sure this attribute exists and is the correct type. */
-	attr_value = purple_status_get_attr_value(status, id);
-	g_return_if_fail(attr_value != NULL);
-	g_return_if_fail(G_VALUE_TYPE(attr_value) == G_TYPE_INT);
-
-	g_value_set_int(attr_value, value);
-}
-
-static void
-status_set_attr_string(PurpleStatus *status, const char *id,
-		const char *value)
-{
-	GValue *attr_value;
-
-	g_return_if_fail(PURPLE_IS_STATUS(status));
-	g_return_if_fail(id != NULL);
-
-	/* Make sure this attribute exists and is the correct type. */
-	attr_value = purple_status_get_attr_value(status, id);
-	/* This used to be g_return_if_fail, but it's failing a LOT, so
-	 * let's generate a log error for now. */
-	/* g_return_if_fail(attr_value != NULL); */
-	if (attr_value == NULL) {
-		purple_debug_error("status",
-				 "Attempted to set status attribute '%s' for "
-				 "status '%s', which is not legal.  Fix "
-                                 "this!\n", id,
-				 purple_status_type_get_name(purple_status_get_status_type(status)));
-		return;
-	}
-	g_return_if_fail(G_VALUE_TYPE(attr_value) == G_TYPE_STRING);
-
-	/* XXX: Check if the value has actually changed. If it has, and the status
-	 * is active, should this trigger 'status_has_changed'? */
-	g_value_set_string(attr_value, value);
-}
-
-void
-purple_status_set_active(PurpleStatus *status, gboolean active)
-{
-	purple_status_set_active_with_attributes(status, active, NULL);
-}
-
-void
-purple_status_set_active_with_attributes(PurpleStatus *status, gboolean active,
-                                         GHashTable *attrs)
-{
-	gboolean changed = FALSE;
-	GList *l;
-	GList *specified_attr_ids = NULL;
-	PurpleStatusType *status_type;
-
-	g_return_if_fail(PURPLE_IS_STATUS(status));
-
-	if(!active && purple_status_is_exclusive(status)) {
-		purple_debug_error("status",
-		                   "Cannot deactivate an exclusive status (%s).",
-		                   purple_status_get_id(status));
-		return;
-	}
-
-	if(status->active != active) {
-		changed = TRUE;
-	}
-	status->active = active;
-
-	if(attrs != NULL) {
-		GHashTableIter iter;
-		gpointer key, data;
-
-		/* Set any attributes */
-		g_hash_table_iter_init(&iter, attrs);
-		while(g_hash_table_iter_next(&iter, &key, &data)) {
-			gchar *id = (gchar *)key;
-			GValue *value = purple_status_get_attr_value(status, id);
-			if(value == NULL) {
-				purple_debug_warning("status",
-				                     "The attribute \"%s\" on the status "
-				                     "\"%s\" is not supported.",
-				                     id, status->status_type->name);
-
-				/* Skip over the data and move on to the next attribute */
-				continue;
-			}
-
-			specified_attr_ids = g_list_prepend(specified_attr_ids, id);
-
-			if(G_VALUE_HOLDS_STRING(value)) {
-				const gchar *string_data = (const gchar *)data;
-
-				if(purple_strequal(string_data, g_value_get_string(value))) {
-					continue;
-				}
-
-				status_set_attr_string(status, id, string_data);
-				changed = TRUE;
-			} else if(G_VALUE_HOLDS_INT(value)) {
-				gint int_data = GPOINTER_TO_INT(data);
-
-				if(int_data == g_value_get_int(value)) {
-					continue;
-				}
-
-				status_set_attr_int(status, id, int_data);
-				changed = TRUE;
-			} else if(G_VALUE_HOLDS_BOOLEAN(value)) {
-				gboolean boolean_data = GPOINTER_TO_INT(data);
-
-				if(boolean_data == g_value_get_boolean(value)) {
-					continue;
-				}
-
-				status_set_attr_boolean(status, id, boolean_data);
-				changed = TRUE;
-			}
-		}
-	}
-
-	/* Reset any unspecified attributes to their default value */
-	status_type = purple_status_get_status_type(status);
-	l = purple_status_type_get_attrs(status_type);
-	while(l != NULL) {
-		PurpleStatusAttribute *attr;
-		GList *found = NULL;
-		GValue *default_value = NULL;
-		default_value = NULL;
-
-		attr = l->data;
-		l = l->next;
-
-		found = g_list_find_custom(specified_attr_ids, attr->id,
-		                           (GCompareFunc)g_strcmp0);
-		if(found != NULL) {
-			continue;
-		}
-
-		default_value = purple_status_attribute_get_value(attr);
-		if(G_VALUE_HOLDS_STRING(default_value)) {
-			const gchar *cur = purple_status_get_attr_string(status,
-			                                                 attr->id);
-			const gchar *def = g_value_get_string(default_value);
-
-			if (purple_strequal(cur, def)) {
-				continue;
-			}
-
-			status_set_attr_string(status, attr->id, def);
-		} else if(G_VALUE_HOLDS_INT(default_value)) {
-			gint cur = purple_status_get_attr_int(status, attr->id);
-			gint def = g_value_get_int(default_value);
-
-			if(cur == def) {
-				continue;
-			}
-
-			status_set_attr_int(status, attr->id, def);
-		} else if(G_VALUE_HOLDS_BOOLEAN(default_value)) {
-			gboolean cur = purple_status_get_attr_boolean(status, attr->id);
-			gboolean def = g_value_get_boolean(default_value);
-
-			if(cur == def) {
-				continue;
-			}
-
-			status_set_attr_boolean(status, attr->id, def);
-		}
-		changed = TRUE;
-	}
-	g_list_free(specified_attr_ids);
-
-	if(changed) {
-		status_has_changed(status);
-	}
-}
-
-PurpleStatusType *
-purple_status_get_status_type(PurpleStatus *status)
-{
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL);
-
-	return status->status_type;
-}
-
-PurplePresence *
-purple_status_get_presence(PurpleStatus *status)
-{
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL);
-
-	return status->presence;
-}
-
-const char *
-purple_status_get_id(PurpleStatus *status)
-{
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL);
-
-	return purple_status_type_get_id(purple_status_get_status_type(status));
-}
-
-const char *
-purple_status_get_name(PurpleStatus *status)
-{
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL);
-
-	return purple_status_type_get_name(purple_status_get_status_type(status));
-}
-
-gboolean
-purple_status_is_independent(PurpleStatus *status)
-{
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE);
-
-	return purple_status_type_is_independent(purple_status_get_status_type(status));
-}
-
-gboolean
-purple_status_is_exclusive(PurpleStatus *status)
-{
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE);
-
-	return purple_status_type_is_exclusive(purple_status_get_status_type(status));
-}
-
-gboolean
-purple_status_is_available(PurpleStatus *status)
-{
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE);
-
-	return purple_status_type_is_available(purple_status_get_status_type(status));
-}
-
-gboolean
-purple_status_is_active(PurpleStatus *status)
-{
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE);
-
-	return status->active;
-}
-
-gboolean
-purple_status_is_online(PurpleStatus *status)
-{
-	PurpleStatusPrimitive primitive;
-
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE);
-
-	primitive = purple_status_type_get_primitive(purple_status_get_status_type(status));
-
-	return (primitive != PURPLE_STATUS_UNSET &&
-			primitive != PURPLE_STATUS_OFFLINE);
-}
-
-GValue *
-purple_status_get_attr_value(PurpleStatus *status, const char *id)
-{
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL);
-	g_return_val_if_fail(id   != NULL, NULL);
-
-	return (GValue *)g_hash_table_lookup(status->attr_values, id);
-}
-
-gboolean
-purple_status_get_attr_boolean(PurpleStatus *status, const char *id)
-{
-	const GValue *value;
-
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE);
-	g_return_val_if_fail(id != NULL, FALSE);
-
-	if ((value = purple_status_get_attr_value(status, id)) == NULL)
-		return FALSE;
-
-	g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_BOOLEAN, FALSE);
-
-	return g_value_get_boolean(value);
-}
-
-int
-purple_status_get_attr_int(PurpleStatus *status, const char *id)
-{
-	const GValue *value;
-
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), 0);
-	g_return_val_if_fail(id != NULL, 0);
-
-	if ((value = purple_status_get_attr_value(status, id)) == NULL)
-		return 0;
-
-	g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_INT, 0);
-
-	return g_value_get_int(value);
-}
-
-const char *
-purple_status_get_attr_string(PurpleStatus *status, const char *id)
-{
-	const GValue *value;
-
-	g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL);
-	g_return_val_if_fail(id != NULL, NULL);
-
-	if ((value = purple_status_get_attr_value(status, id)) == NULL)
-		return NULL;
-
-	g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_STRING, NULL);
-
-	return g_value_get_string(value);
-}
-
-gint
-purple_status_compare(PurpleStatus *status1, PurpleStatus *status2)
-{
-	PurpleStatusType *type1, *type2;
-	int score1 = 0, score2 = 0;
-
-	if ((status1 == NULL && status2 == NULL) ||
-			(status1 == status2))
-	{
-		return 0;
-	}
-	else if (status1 == NULL)
-		return 1;
-	else if (status2 == NULL)
-		return -1;
-
-	type1 = purple_status_get_status_type(status1);
-	type2 = purple_status_get_status_type(status2);
-
-	if (purple_status_is_active(status1))
-		score1 = primitive_scores[purple_status_type_get_primitive(type1)];
-
-	if (purple_status_is_active(status2))
-		score2 = primitive_scores[purple_status_type_get_primitive(type2)];
-
-	if (score1 > score2)
-		return -1;
-	else if (score1 < score2)
-		return 1;
-
-	return 0;
-}
-
-
-/**************************************************************************
-* GBoxed code for PurpleStatusType
-**************************************************************************/
-static PurpleStatusType *
-purple_status_type_ref(PurpleStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, NULL);
-
-	status_type->box_count++;
-
-	return status_type;
-}
-
-static void
-purple_status_type_unref(PurpleStatusType *status_type)
-{
-	g_return_if_fail(status_type != NULL);
-	g_return_if_fail(status_type->box_count >= 0);
-
-	if (!status_type->box_count--)
-		purple_status_type_destroy(status_type);
-}
-
-GType
-purple_status_type_get_type(void)
-{
-	static GType type = 0;
-
-	if (type == 0) {
-		type = g_boxed_type_register_static("PurpleStatusType",
-				(GBoxedCopyFunc)purple_status_type_ref,
-				(GBoxedFreeFunc)purple_status_type_unref);
-	}
-
-	return type;
-}
-
-/**************************************************************************
-* GBoxed code for PurpleStatusAttribute
-**************************************************************************/
-static PurpleStatusAttribute *
-purple_status_attribute_copy(PurpleStatusAttribute *status_attr)
-{
-	g_return_val_if_fail(status_attr != NULL, NULL);
-
-	return purple_status_attribute_new(status_attr->id,
-	                              status_attr->name,
-	                              purple_value_dup(status_attr->value_type));
-}
-
-GType
-purple_status_attribute_get_type(void)
-{
-	static GType type = 0;
-
-	if (type == 0) {
-		type = g_boxed_type_register_static("PurpleStatusAttribute",
-				(GBoxedCopyFunc)purple_status_attribute_copy,
-				(GBoxedFreeFunc)purple_status_attribute_destroy);
-	}
-
-	return type;
-}
-
-/**************************************************************************
-* GObject code
-**************************************************************************/
-
-/* Set method for GObject properties */
-static void
-purple_status_set_property(GObject *obj, guint param_id, const GValue *value,
-		GParamSpec *pspec)
-{
-	PurpleStatus *status = PURPLE_STATUS(obj);
-
-	switch (param_id) {
-		case PROP_STATUS_TYPE:
-			status->status_type = g_value_get_pointer(value);
-			break;
-		case PROP_PRESENCE:
-			status->presence = g_value_get_object(value);
-			break;
-		case PROP_ACTIVE:
-			purple_status_set_active(status, g_value_get_boolean(value));
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-			break;
-	}
-}
-
-/* Get method for GObject properties */
-static void
-purple_status_get_property(GObject *obj, guint param_id, GValue *value,
-		GParamSpec *pspec)
-{
-	PurpleStatus *status = PURPLE_STATUS(obj);
-
-	switch (param_id) {
-		case PROP_STATUS_TYPE:
-			g_value_set_pointer(value, purple_status_get_status_type(status));
-			break;
-		case PROP_PRESENCE:
-			g_value_set_object(value, purple_status_get_presence(status));
-			break;
-		case PROP_ACTIVE:
-			g_value_set_boolean(value, purple_status_is_active(status));
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-			break;
-	}
-}
-
-/* GObject initialization function */
-static void
-purple_status_init(PurpleStatus *status)
-{
-	status->attr_values = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
-	                                            (GDestroyNotify)purple_value_free);
-}
-
-/* Called when done constructing */
-static void
-purple_status_constructed(GObject *object)
-{
-	PurpleStatus *status = PURPLE_STATUS(object);
-	GList *l;
-
-	G_OBJECT_CLASS(purple_status_parent_class)->constructed(object);
-
-	for (l = purple_status_type_get_attrs(status->status_type); l != NULL; l = l->next)
-	{
-		PurpleStatusAttribute *attr = (PurpleStatusAttribute *)l->data;
-		GValue *value = purple_status_attribute_get_value(attr);
-		GValue *new_value = purple_value_dup(value);
-
-		g_hash_table_insert(status->attr_values,
-							(char *)purple_status_attribute_get_id(attr),
-							new_value);
-	}
-}
-
-/*
- * GObject finalize function
- * TODO: If the PurpleStatus is in a PurplePresence, then
- *       remove it from the PurplePresence?
- */
-static void
-purple_status_finalize(GObject *obj)
-{
-	PurpleStatus *status = PURPLE_STATUS(obj);
-
-	g_hash_table_destroy(status->attr_values);
-
-	G_OBJECT_CLASS(purple_status_parent_class)->finalize(obj);
-}
-
-/* Class initializer function */
-static void
-purple_status_class_init(PurpleStatusClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-
-	obj_class->finalize = purple_status_finalize;
-	obj_class->constructed = purple_status_constructed;
-
-	/* Setup properties */
-	obj_class->get_property = purple_status_get_property;
-	obj_class->set_property = purple_status_set_property;
-
-	/**
-	 * PurpleStatus:status-type:
-	 *
-	 * The type of this status.
-	 *
-	 * Since: 3.0
-	 */
-	properties[PROP_STATUS_TYPE] = g_param_spec_pointer("status-type",
-				"Status type",
-				"The PurpleStatusType of the status.",
-				G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-				G_PARAM_STATIC_STRINGS);
-
-	/**
-	 * PurpleStatus:presence:
-	 *
-	 * The presence that the status belongs to.
-	 *
-	 * Since: 3.0
-	 */
-	properties[PROP_PRESENCE] = g_param_spec_object("presence", "Presence",
-				"The presence that the status belongs to.",
-				PURPLE_TYPE_PRESENCE,
-				G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-				G_PARAM_STATIC_STRINGS);
-
-	/**
-	 * PurpleStatus:active:
-	 *
-	 * Whether or not the status is active.
-	 *
-	 * Since: 3.0
-	 */
-	properties[PROP_ACTIVE] = g_param_spec_boolean("active", "Active",
-				"Whether the status is active or not.", FALSE,
-				G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
-}
-
-PurpleStatus *
-purple_status_new(PurpleStatusType *status_type, PurplePresence *presence)
-{
-	g_return_val_if_fail(status_type != NULL, NULL);
-	g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL);
-
-	return g_object_new(PURPLE_TYPE_STATUS,
-			"status-type",  status_type,
-			"presence",     presence,
-			NULL);
-}
-
-
-/**************************************************************************
-* Status subsystem
-**************************************************************************/
-static void
-score_pref_changed_cb(G_GNUC_UNUSED const char *name,
-                      G_GNUC_UNUSED PurplePrefType type, gconstpointer value,
-                      gpointer data)
-{
-	int index = GPOINTER_TO_INT(data);
-
-	primitive_scores[index] = GPOINTER_TO_INT(value);
-}
-
-void *
-purple_statuses_get_handle(void) {
-	static int handle;
-
-	return &handle;
-}
-
-void
-purple_statuses_init(void)
-{
-	void *handle = purple_statuses_get_handle();
-
-	purple_prefs_add_none("/purple/status");
-	purple_prefs_add_none("/purple/status/scores");
-
-	purple_prefs_add_int("/purple/status/scores/offline",
-			primitive_scores[PURPLE_STATUS_OFFLINE]);
-	purple_prefs_add_int("/purple/status/scores/available",
-			primitive_scores[PURPLE_STATUS_AVAILABLE]);
-	purple_prefs_add_int("/purple/status/scores/invisible",
-			primitive_scores[PURPLE_STATUS_INVISIBLE]);
-	purple_prefs_add_int("/purple/status/scores/away",
-			primitive_scores[PURPLE_STATUS_AWAY]);
-	purple_prefs_add_int("/purple/status/scores/extended_away",
-			primitive_scores[PURPLE_STATUS_EXTENDED_AWAY]);
-	purple_prefs_add_int("/purple/status/scores/idle",
-			primitive_scores[SCORE_IDLE]);
-	purple_prefs_add_int("/purple/status/scores/idle_time",
-			primitive_scores[SCORE_IDLE_TIME]);
-	purple_prefs_add_int("/purple/status/scores/offline_msg",
-			primitive_scores[SCORE_OFFLINE_MESSAGE]);
-
-	purple_prefs_connect_callback(handle, "/purple/status/scores/offline",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(PURPLE_STATUS_OFFLINE));
-	purple_prefs_connect_callback(handle, "/purple/status/scores/available",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(PURPLE_STATUS_AVAILABLE));
-	purple_prefs_connect_callback(handle, "/purple/status/scores/invisible",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(PURPLE_STATUS_INVISIBLE));
-	purple_prefs_connect_callback(handle, "/purple/status/scores/away",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(PURPLE_STATUS_AWAY));
-	purple_prefs_connect_callback(handle, "/purple/status/scores/extended_away",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(PURPLE_STATUS_EXTENDED_AWAY));
-	purple_prefs_connect_callback(handle, "/purple/status/scores/idle",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(SCORE_IDLE));
-	purple_prefs_connect_callback(handle, "/purple/status/scores/idle_time",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(SCORE_IDLE_TIME));
-	purple_prefs_connect_callback(handle, "/purple/status/scores/offline_msg",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(SCORE_OFFLINE_MESSAGE));
-
-	purple_prefs_trigger_callback("/purple/status/scores/offline");
-	purple_prefs_trigger_callback("/purple/status/scores/available");
-	purple_prefs_trigger_callback("/purple/status/scores/invisible");
-	purple_prefs_trigger_callback("/purple/status/scores/away");
-	purple_prefs_trigger_callback("/purple/status/scores/extended_away");
-	purple_prefs_trigger_callback("/purple/status/scores/idle");
-	purple_prefs_trigger_callback("/purple/status/scores/idle_time");
-	purple_prefs_trigger_callback("/purple/status/scores/offline_msg");
-}
-
-void
-purple_statuses_uninit(void)
-{
-	purple_prefs_disconnect_by_handle(purple_statuses_get_handle());
-}
-
-/**************************************************************************/
-/* Helpers                                                                */
-/**************************************************************************/
-GHashTable *
-purple_attrs_from_vargs(va_list args)
-{
-	GHashTable *attrs = g_hash_table_new(g_str_hash, g_str_equal);
-	gchar *id;
-
-	while ((id = va_arg(args, gchar *)) != NULL)
-	{
-		gpointer data = va_arg(args, gpointer);
-
-		g_hash_table_insert(attrs, id, data);
-	}
-
-	return attrs;
-}
diff --git a/po/POTFILES.in b/po/POTFILES.in
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -97,10 +97,8 @@
 libpurple/request/purplerequestgroup.c
 libpurple/request/purplerequestpage.c
 libpurple/roomlist.c
-libpurple/savedstatuses.c
 libpurple/server.c
 libpurple/signals.c
-libpurple/status.c
 libpurple/tests/test_account_manager.c
 libpurple/tests/test_account_option.c
 libpurple/tests/test_circular_buffer.c
