# HG changeset patch
# Node ID 6dc644a67476
# Parent  0fd8d38cabf7
diff --git a/libpurple/meson.build b/libpurple/meson.build
--- a/libpurple/meson.build
+++ b/libpurple/meson.build
@@ -85,6 +85,7 @@ purple_coresources = [
 	'purpleprotocolwhiteboard.c',
 	'purpleproxyinfo.c',
 	'purplerequestfield.c',
+	'purplerequestgroup.c',
 	'purpleroomlistroom.c',
 	'purplesqlite3.c',
 	'purplesqlitehistoryadapter.c',
@@ -192,6 +193,7 @@ purple_coreheaders = [
 	'purpleprotocolwhiteboard.h',
 	'purpleproxyinfo.h',
 	'purplerequestfield.h',
+	'purplerequestgroup.h',
 	'purpleroomlistroom.h',
 	'purplesqlite3.h',
 	'purplesqlitehistoryadapter.h',
diff --git a/libpurple/purpleprivate.h b/libpurple/purpleprivate.h
--- a/libpurple/purpleprivate.h
+++ b/libpurple/purpleprivate.h
@@ -338,6 +338,10 @@ void purple_whiteboard_manager_shutdown(
  */
 G_GNUC_INTERNAL void purple_account_set_enabled_plain(PurpleAccount *account, gboolean enabled);
 
+G_GNUC_INTERNAL void _purple_request_field_list_add_field(PurpleRequestFields *fields, PurpleRequestField *field);
+G_GNUC_INTERNAL void _purple_request_field_list_set_field_required(PurpleRequestFields *fields, PurpleRequestField *field, gboolean required);
+G_GNUC_INTERNAL void _purple_request_field_list_set_field_validator(PurpleRequestFields *fields, PurpleRequestField *field, gboolean validator);
+G_GNUC_INTERNAL void _purple_request_field_group_set_field_list(PurpleRequestFieldGroup *group, PurpleRequestFields *fields);
 G_GNUC_INTERNAL void _purple_request_field_set_group(PurpleRequestField *field, PurpleRequestFieldGroup *group);
 G_GNUC_INTERNAL void _purple_request_field_group_set_field_required(PurpleRequestFieldGroup *group, PurpleRequestField *field, gboolean required);
 G_GNUC_INTERNAL void _purple_request_field_group_set_field_validator(PurpleRequestFieldGroup *group, PurpleRequestField *field, gboolean validator);
diff --git a/libpurple/request.h b/libpurple/purplerequestgroup.h
copy from libpurple/request.h
copy to libpurple/purplerequestgroup.h
--- a/libpurple/request.h
+++ b/libpurple/purplerequestgroup.h
@@ -24,23 +24,14 @@
 # error "only <purple.h> may be included directly"
 #endif
 
-#ifndef PURPLE_REQUEST_H
-#define PURPLE_REQUEST_H
+#ifndef PURPLE_REQUEST_GROUP_H
+#define PURPLE_REQUEST_GROUP_H
 
 #include <stdlib.h>
 
 #include <glib.h>
 #include <glib-object.h>
 
-#define PURPLE_TYPE_REQUEST_UI_OPS (purple_request_ui_ops_get_type())
-
-/**
- * PurpleRequestFields:
- *
- * Multiple fields request data.
- */
-typedef struct _PurpleRequestFields PurpleRequestFields;
-
 /**
  * PurpleRequestFieldGroup:
  *
@@ -48,677 +39,10 @@ typedef struct _PurpleRequestFields Purp
  */
 typedef struct _PurpleRequestFieldGroup PurpleRequestFieldGroup;
 
-/**
- * PurpleRequestCommonParameters:
- *
- * Common parameters for UI operations.
- */
-typedef struct _PurpleRequestCommonParameters PurpleRequestCommonParameters;
-
-typedef struct _PurpleRequestUiOps PurpleRequestUiOps;
-
-#include "account.h"
-#include "purpleconversation.h"
 #include "purplerequestfield.h"
-#include "request-datasheet.h"
-
-#define PURPLE_DEFAULT_ACTION_NONE	-1
-
-/**
- * PurpleRequestType:
- * @PURPLE_REQUEST_INPUT:  Text input request.
- * @PURPLE_REQUEST_CHOICE: Multiple-choice request.
- * @PURPLE_REQUEST_ACTION: Action request.
- * @PURPLE_REQUEST_WAIT:   Please wait dialog.
- * @PURPLE_REQUEST_FIELDS: Multiple fields request.
- * @PURPLE_REQUEST_FILE:   File open or save request.
- * @PURPLE_REQUEST_FOLDER: Folder selection request.
- *
- * Request types.
- */
-typedef enum
-{
-	PURPLE_REQUEST_INPUT = 0,
-	PURPLE_REQUEST_CHOICE,
-	PURPLE_REQUEST_ACTION,
-	PURPLE_REQUEST_WAIT,
-	PURPLE_REQUEST_FIELDS,
-	PURPLE_REQUEST_FILE,
-	PURPLE_REQUEST_FOLDER
-
-} PurpleRequestType;
-
-/**
- * PurpleRequestFeature:
- * @PURPLE_REQUEST_FEATURE_HTML: Specifies that HTML should be supported.
- *
- * Feature flags for the request api.
- */
-typedef enum
-{
-	PURPLE_REQUEST_FEATURE_HTML = 0x00000001
-} PurpleRequestFeature;
-
-/**
- * PurpleRequestIconType:
- * @PURPLE_REQUEST_ICON_DEFAULT: The default icon.
- * @PURPLE_REQUEST_ICON_REQUEST: Use a question icon.
- * @PURPLE_REQUEST_ICON_DIALOG: Use a dialog icon.
- * @PURPLE_REQUEST_ICON_WAIT: Use a wait icon.
- * @PURPLE_REQUEST_ICON_INFO: Use an info icon.
- * @PURPLE_REQUEST_ICON_WARNING: Use a warning icon.
- * @PURPLE_REQUEST_ICON_ERROR: Use an error icon.
- *
- * Constants to define which kind of icon should be displayed.
- */
-typedef enum
-{
-	PURPLE_REQUEST_ICON_DEFAULT = 0,
-	PURPLE_REQUEST_ICON_REQUEST,
-	PURPLE_REQUEST_ICON_DIALOG,
-	PURPLE_REQUEST_ICON_WAIT,
-	PURPLE_REQUEST_ICON_INFO,
-	PURPLE_REQUEST_ICON_WARNING,
-	PURPLE_REQUEST_ICON_ERROR
-} PurpleRequestIconType;
-
-/**
- * PurpleRequestCancelCb:
- * @data: user-data.
- *
- * A callback that's used to handle cancel actions.
- */
-typedef void (*PurpleRequestCancelCb)(gpointer data);
-
-/**
- * PurpleRequestUiOps:
- * @features:            A bitwise or of #PurpleRequestFeature's.
- * @request_input:       See purple_request_input().
- * @request_choice:      See purple_request_choice_varg().
- * @request_action:      See purple_request_action_varg().
- * @request_wait:        See purple_request_wait().
- * @request_wait_update: See purple_request_wait_pulse(),
- *                       purple_request_wait_progress().
- * @request_fields:      See purple_request_fields().
- * @request_file:        See purple_request_file().
- * @request_folder:      See purple_request_folder().
- * @close_request:       See purple_request_close().
- *
- * Request UI operations.
- */
-struct _PurpleRequestUiOps
-{
-	PurpleRequestFeature features;
-
-	void *(*request_input)(const char *title, const char *primary,
-		const char *secondary, const char *default_value,
-		gboolean multiline, gboolean masked, gchar *hint,
-		const char *ok_text, GCallback ok_cb,
-		const char *cancel_text, GCallback cancel_cb,
-		PurpleRequestCommonParameters *cpar, void *user_data);
-
-	void *(*request_choice)(const char *title, const char *primary,
-		const char *secondary, gpointer default_value,
-		const char *ok_text, GCallback ok_cb, const char *cancel_text,
-		GCallback cancel_cb, PurpleRequestCommonParameters *cpar,
-		void *user_data, va_list choices);
-
-	void *(*request_action)(const char *title, const char *primary,
-		const char *secondary, int default_action,
-		PurpleRequestCommonParameters *cpar, void *user_data,
-		size_t action_count, va_list actions);
-
-	void *(*request_wait)(const char *title, const char *primary,
-		const char *secondary, gboolean with_progress,
-		PurpleRequestCancelCb cancel_cb,
-		PurpleRequestCommonParameters *cpar, void *user_data);
-
-	void (*request_wait_update)(void *ui_handle, gboolean animate,
-		gfloat fraction);
-
-	void *(*request_fields)(const char *title, const char *primary,
-		const char *secondary, PurpleRequestFields *fields,
-		const char *ok_text, GCallback ok_cb,
-		const char *cancel_text, GCallback cancel_cb,
-		PurpleRequestCommonParameters *cpar, void *user_data);
-
-	void *(*request_file)(const char *title, const char *filename,
-		gboolean savedialog, GCallback ok_cb, GCallback cancel_cb,
-		PurpleRequestCommonParameters *cpar, void *user_data);
-
-	void *(*request_folder)(const char *title, const char *dirname,
-		GCallback ok_cb, GCallback cancel_cb,
-		PurpleRequestCommonParameters *cpar, void *user_data);
-
-	void (*close_request)(PurpleRequestType type, void *ui_handle);
-
-	/*< private >*/
-	void (*_purple_reserved1)(void);
-	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
-};
-
-typedef void (*PurpleRequestInputCb)(void *data, const char *value);
-
-/**
- * PurpleRequestActionCb:
- * @data:   user-data
- * @action: The action that was chosen.
- *
- * The type of callbacks passed to purple_request_action().  The first
- * argument is the <literal>user_data</literal> parameter; the second is the
- * index in the list of actions of the one chosen.
- */
-typedef void (*PurpleRequestActionCb)(void *data, int action);
-
-/**
- * PurpleRequestChoiceCb:
- * @data:  user-data
- * @value: The choice that was made.
- *
- * The type of callbacks passed to purple_request_choice().  The first
- * argument is the <literal>user_data</literal> parameter; the second is the
- * values of those choice.
- */
-typedef void (*PurpleRequestChoiceCb)(void *data, gpointer value);
-typedef void (*PurpleRequestFieldsCb)(void *data, PurpleRequestFields *fields);
-typedef void (*PurpleRequestFileCb)(void *data, const char *filename);
-typedef void (*PurpleRequestHelpCb)(gpointer data);
 
 G_BEGIN_DECLS
 
-/**************************************************************************/
-/* Common parameters API                                                  */
-/**************************************************************************/
-
-/**
- * purple_request_cpar_new:
- *
- * Creates new parameters set for the request, which may or may not be used by
- * the UI to display the request.
- *
- * Returns: (transfer full): The new parameters set.
- */
-PurpleRequestCommonParameters *
-purple_request_cpar_new(void);
-
-/**
- * purple_request_cpar_from_connection:
- * @gc: The #PurpleConnection.
- *
- * Creates new parameters set initially bound with the #PurpleConnection.
- *
- * Returns: (transfer full): The new parameters set.
- */
-PurpleRequestCommonParameters *
-purple_request_cpar_from_connection(PurpleConnection *gc);
-
-/**
- * purple_request_cpar_from_account:
- * @account: The #PurpleAccount.
- *
- * Creates new parameters set initially bound with the #PurpleAccount.
- *
- * Returns: (transfer full): The new parameters set.
- */
-PurpleRequestCommonParameters *
-purple_request_cpar_from_account(PurpleAccount *account);
-
-/**
- * purple_request_cpar_from_conversation:
- * @conv: The #PurpleConversation.
- *
- * Creates new parameters set initially bound with the #PurpleConversation.
- *
- * Returns: (transfer full): The new parameters set.
- */
-PurpleRequestCommonParameters *
-purple_request_cpar_from_conversation(PurpleConversation *conv);
-
-/**
- * purple_request_cpar_ref:
- * @cpar: The object to ref.
- *
- * Increases the reference count on the parameters set.
- */
-void
-purple_request_cpar_ref(PurpleRequestCommonParameters *cpar);
-
-/**
- * purple_request_cpar_unref:
- * @cpar: The parameters set object to unref and possibly destroy.
- *
- * Decreases the reference count on the parameters set.
- *
- * The object will be destroyed when this reaches 0.
- */
-void
-purple_request_cpar_unref(PurpleRequestCommonParameters *cpar);
-
-/**
- * purple_request_cpar_set_account:
- * @cpar:    The parameters set.
- * @account: The #PurpleAccount to associate.
- *
- * Sets the #PurpleAccount associated with the request, or %NULL, if none is.
- */
-void
-purple_request_cpar_set_account(PurpleRequestCommonParameters *cpar,
-	PurpleAccount *account);
-
-/**
- * purple_request_cpar_get_account:
- * @cpar: The parameters set (may be %NULL).
- *
- * Gets the #PurpleAccount associated with the request.
- *
- * Returns: (transfer none): The associated #PurpleAccount, or %NULL if none is
- *          set.
- */
-PurpleAccount *
-purple_request_cpar_get_account(PurpleRequestCommonParameters *cpar);
-
-/**
- * purple_request_cpar_set_conversation:
- * @cpar: The parameters set.
- * @conv: The #PurpleConversation to associate.
- *
- * Sets the #PurpleConversation associated with the request, or %NULL, if
- * none is.
- */
-void
-purple_request_cpar_set_conversation(PurpleRequestCommonParameters *cpar,
-	PurpleConversation *conv);
-
-/**
- * purple_request_cpar_get_conversation:
- * @cpar: The parameters set (may be %NULL).
- *
- * Gets the #PurpleConversation associated with the request.
- *
- * Returns: (transfer none): The associated #PurpleConversation, or %NULL if
- *          none is set.
- */
-PurpleConversation *
-purple_request_cpar_get_conversation(PurpleRequestCommonParameters *cpar);
-
-/**
- * purple_request_cpar_set_icon:
- * @cpar:      The parameters set.
- * @icon_type: The icon type.
- *
- * Sets the icon associated with the request.
- */
-void
-purple_request_cpar_set_icon(PurpleRequestCommonParameters *cpar,
-	PurpleRequestIconType icon_type);
-
-/**
- * purple_request_cpar_get_icon:
- * @cpar: The parameters set.
- *
- * Gets the icon associated with the request.
- *
- * Returns: icon_type The icon type.
- */
-PurpleRequestIconType
-purple_request_cpar_get_icon(PurpleRequestCommonParameters *cpar);
-
-/**
- * purple_request_cpar_set_custom_icon:
- * @cpar:      The parameters set.
- * @icon_data: The icon image contents (%NULL to reset).
- * @icon_size: The icon image size.
- *
- * Sets the custom icon associated with the request.
- */
-void
-purple_request_cpar_set_custom_icon(PurpleRequestCommonParameters *cpar,
-	gconstpointer icon_data, gsize icon_size);
-
-/**
- * purple_request_cpar_get_custom_icon:
- * @cpar:      The parameters set (may be %NULL).
- * @icon_size: The pointer to variable, where icon size should be stored
- *                  (may be %NULL).
- *
- * Gets the custom icon associated with the request.
- *
- * Returns: The icon image contents.
- */
-gconstpointer
-purple_request_cpar_get_custom_icon(PurpleRequestCommonParameters *cpar,
-	gsize *icon_size);
-
-/**
- * purple_request_cpar_set_html:
- * @cpar:    The parameters set.
- * @enabled: 1, if the text passed with the request contains HTML,
- *                0 otherwise. Don't use any other values, as they may be
- *                redefined in the future.
- *
- * Switches the request text to be HTML or not.
- */
-void
-purple_request_cpar_set_html(PurpleRequestCommonParameters *cpar,
-	gboolean enabled);
-
-/**
- * purple_request_cpar_is_html:
- * @cpar: The parameters set (may be %NULL).
- *
- * Checks, if the text passed to the request is HTML.
- *
- * Returns: %TRUE, if the text is HTML, %FALSE otherwise.
- */
-gboolean
-purple_request_cpar_is_html(PurpleRequestCommonParameters *cpar);
-
-/**
- * purple_request_cpar_set_compact:
- * @cpar:    The parameters set.
- * @compact: TRUE for compact, FALSE otherwise.
- *
- * Sets dialog display mode to compact or default.
- */
-void
-purple_request_cpar_set_compact(PurpleRequestCommonParameters *cpar,
-	gboolean compact);
-
-/**
- * purple_request_cpar_is_compact:
- * @cpar: The parameters set (may be %NULL).
- *
- * Gets dialog display mode.
- *
- * Returns: TRUE for compact, FALSE for default.
- */
-gboolean
-purple_request_cpar_is_compact(PurpleRequestCommonParameters *cpar);
-
-/**
- * purple_request_cpar_set_help_cb:
- * @cpar:      The parameters set.
- * @cb: (scope notified):       The callback.
- * @user_data: The data to be passed to the callback.
- *
- * Sets the callback for the Help button.
- */
-void
-purple_request_cpar_set_help_cb(PurpleRequestCommonParameters *cpar,
-	PurpleRequestHelpCb cb, gpointer user_data);
-
-/**
- * purple_request_cpar_get_help_cb:
- * @cpar:      The parameters set (may be %NULL).
- * @user_data: The pointer to the variable, where user data (to be passed to
- *             callback function) should be stored.
- *
- * Gets the callback for the Help button.
- *
- * Returns: (transfer none): The callback.
- */
-PurpleRequestHelpCb
-purple_request_cpar_get_help_cb(PurpleRequestCommonParameters *cpar,
-	gpointer *user_data);
-
-/**
- * purple_request_cpar_set_extra_actions:
- * @cpar: The parameters set.
- * @...:  A list of actions. These are pairs of arguments. The first of each
- *        pair is the <type>char *</type> label that appears on the button.  It
- *        should have an underscore before the letter you want to use as the
- *        accelerator key for the button. The second of each pair is the
- *        #PurpleRequestFieldsCb function to use when the button is clicked.
- *        Should be terminated with the NULL label.
- *
- * Sets extra actions for the PurpleRequestFields dialog.
- */
-void
-purple_request_cpar_set_extra_actions(PurpleRequestCommonParameters *cpar, ...);
-
-/**
- * purple_request_cpar_get_extra_actions:
- * @cpar: The parameters set (may be %NULL).
- *
- * Gets extra actions for the PurpleRequestFields dialog.
- *
- * Returns: (element-type PurpleKeyValuePair) (transfer none): A list of actions (pairs of arguments, as in
- *          setter).
- */
-GSList *
-purple_request_cpar_get_extra_actions(PurpleRequestCommonParameters *cpar);
-
-/**
- * purple_request_cpar_set_parent_from:
- * @cpar:      The parameters set.
- * @ui_handle: The UI handle.
- *
- * Sets the same parent window for this dialog, as the parent of specified
- * Notify API or Request API dialog UI handle.
- */
-void
-purple_request_cpar_set_parent_from(PurpleRequestCommonParameters *cpar,
-	gpointer ui_handle);
-
-/**
- * purple_request_cpar_get_parent_from:
- * @cpar: The parameters set (may be %NULL).
- *
- * Gets the parent "donor" for this dialog.
- *
- * Returns: The donors UI handle.
- */
-gpointer
-purple_request_cpar_get_parent_from(PurpleRequestCommonParameters *cpar);
-
-/**************************************************************************/
-/* Field List API                                                         */
-/**************************************************************************/
-
-/**
- * purple_request_fields_new:
- *
- * Creates a list of fields to pass to purple_request_fields().
- *
- * Returns: (transfer full): A PurpleRequestFields structure.
- */
-PurpleRequestFields *purple_request_fields_new(void);
-
-/**
- * purple_request_fields_destroy:
- * @fields: The list of fields to destroy.
- *
- * Destroys a list of fields.
- */
-void purple_request_fields_destroy(PurpleRequestFields *fields);
-
-/**
- * purple_request_fields_add_group:
- * @fields: The fields list.
- * @group:  The group to add.
- *
- * Adds a group of fields to the list.
- */
-void purple_request_fields_add_group(PurpleRequestFields *fields,
-								   PurpleRequestFieldGroup *group);
-
-/**
- * purple_request_fields_get_groups:
- * @fields: The fields list.
- *
- * Returns a list of all groups in a field list.
- *
- * Returns: (element-type PurpleRequestFieldGroup) (transfer none): A list of groups.
- */
-GList *purple_request_fields_get_groups(const PurpleRequestFields *fields);
-
-/**
- * purple_request_fields_exists:
- * @fields: The fields list.
- * @id:     The ID of the field.
- *
- * Returns whether or not the field with the specified ID exists.
- *
- * Returns: TRUE if the field exists, or FALSE.
- */
-gboolean purple_request_fields_exists(const PurpleRequestFields *fields,
-									const char *id);
-
-/**
- * purple_request_fields_get_required:
- * @fields: The fields list.
- *
- * Returns a list of all required fields.
- *
- * Returns: (element-type PurpleRequestField) (transfer none): The list of required fields.
- */
-const GList *purple_request_fields_get_required(
-	const PurpleRequestFields *fields);
-
-/**
- * purple_request_fields_get_validatable:
- * @fields: The fields list.
- *
- * Returns a list of all validated fields.
- *
- * Returns: (element-type PurpleRequestField) (transfer none): The list of validated fields.
- */
-const GList *purple_request_fields_get_validatable(
-	const PurpleRequestFields *fields);
-
-/**
- * purple_request_fields_is_field_required:
- * @fields: The fields list.
- * @id:     The field ID.
- *
- * Returns whether or not a field with the specified ID is required.
- *
- * Returns: TRUE if the specified field is required, or FALSE.
- */
-gboolean purple_request_fields_is_field_required(const PurpleRequestFields *fields,
-											   const char *id);
-
-/**
- * purple_request_fields_all_required_filled:
- * @fields: The fields list.
- *
- * Returns whether or not all required fields have values.
- *
- * Returns: TRUE if all required fields have values, or FALSE.
- */
-gboolean purple_request_fields_all_required_filled(
-	const PurpleRequestFields *fields);
-
-/**
- * purple_request_fields_all_valid:
- * @fields: The fields list.
- *
- * Returns whether or not all fields are valid.
- *
- * Returns: TRUE if all fields are valid, or FALSE.
- */
-gboolean purple_request_fields_all_valid(const PurpleRequestFields *fields);
-
-/**
- * purple_request_fields_get_field:
- * @fields: The fields list.
- * @id:     The ID of the field.
- *
- * Return the field with the specified ID.
- *
- * Returns: (transfer none): The field, if found.
- */
-PurpleRequestField *purple_request_fields_get_field(
-		const PurpleRequestFields *fields, const char *id);
-
-/**
- * purple_request_fields_get_string:
- * @fields: The fields list.
- * @id:     The ID of the field.
- *
- * Returns the string value of a field with the specified ID.
- *
- * Returns: The string value, if found, or %NULL otherwise.
- */
-const char *purple_request_fields_get_string(const PurpleRequestFields *fields,
-										   const char *id);
-
-/**
- * purple_request_fields_get_integer:
- * @fields: The fields list.
- * @id:     The ID of the field.
- *
- * Returns the integer value of a field with the specified ID.
- *
- * Returns: The integer value, if found, or 0 otherwise.
- */
-int purple_request_fields_get_integer(const PurpleRequestFields *fields,
-									const char *id);
-
-/**
- * purple_request_fields_get_bool:
- * @fields: The fields list.
- * @id:     The ID of the field.
- *
- * Returns the boolean value of a field with the specified ID.
- *
- * Returns: The boolean value, if found, or %FALSE otherwise.
- */
-gboolean purple_request_fields_get_bool(const PurpleRequestFields *fields,
-									  const char *id);
-
-/**
- * purple_request_fields_get_choice:
- * @fields: The fields list.
- * @id:     The ID of the field.
- *
- * Returns the choice index of a field with the specified ID.
- *
- * Returns: The choice value, if found, or NULL otherwise.
- */
-gpointer
-purple_request_fields_get_choice(const PurpleRequestFields *fields,
-	const char *id);
-
-/**
- * purple_request_fields_get_account:
- * @fields: The fields list.
- * @id:     The ID of the field.
- *
- * Returns the account of a field with the specified ID.
- *
- * Returns: (transfer none): The account value, if found, or %NULL otherwise.
- */
-PurpleAccount *purple_request_fields_get_account(const PurpleRequestFields *fields,
-											 const char *id);
-
-/**
- * purple_request_fields_get_ui_data:
- * @fields: The fields list.
- *
- * Returns the UI data associated with this object.
- *
- * Returns: The UI data associated with this object.  This is a
- *         convenience field provided to the UIs--it is not
- *         used by the libpurple core.
- */
-gpointer purple_request_fields_get_ui_data(const PurpleRequestFields *fields);
-
-/**
- * purple_request_fields_set_ui_data:
- * @fields: The fields list.
- * @ui_data: A pointer to associate with this object.
- *
- * Set the UI data associated with this object.
- */
-void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data);
-
-/**************************************************************************/
-/* Fields Group API                                                       */
-/**************************************************************************/
-
 /**
  * purple_request_field_group_new:
  * @title: The optional title to give the group.
@@ -780,501 +104,6 @@ GList *purple_request_field_group_get_fi
 PurpleRequestFields *purple_request_field_group_get_fields_list(
 		const PurpleRequestFieldGroup *group);
 
-/**************************************************************************/
-/* Request API                                                            */
-/**************************************************************************/
-
-/**
- * purple_request_input:
- * @handle:        The plugin or connection handle.  For some
- *                 things this is <emphasis>extremely</emphasis> important.  The
- *                 handle is used to programmatically close the request
- *                 dialog when it is no longer needed.  For protocols this
- *                 is often a pointer to the #PurpleConnection
- *                 instance.  For plugins this should be a similar,
- *                 unique memory location.  This value is important
- *                 because it allows a request to be closed with
- *                 purple_request_close_with_handle() when, for
- *                 example, you sign offline.  If the request is
- *                 <emphasis>not</emphasis> closed it is
- *                 <emphasis>very</emphasis> likely to cause a crash whenever
- *                 the callback handler functions are triggered.
- * @title:         The title of the message, or %NULL if it should have
- *                 no title.
- * @primary:       The main point of the message, or %NULL if you're
- *                 feeling enigmatic.
- * @secondary:     Secondary information, or %NULL if there is none.
- * @default_value: The default value.
- * @multiline:     %TRUE if the inputted text can span multiple lines.
- * @masked:        %TRUE if the inputted text should be masked in some
- *                 way (such as by displaying characters as stars).  This
- *                 might be because the input is some kind of password.
- * @hint:          Optionally suggest how the input box should appear.
- *                 Use "html", for example, to allow the user to enter HTML.
- * @ok_text:       The text for the <literal>OK</literal> button, which may not
- *                 be %NULL.
- * @ok_cb: (scope notified):         The callback for the <literal>OK</literal> button, which may
- *                 not be %NULL.
- * @cancel_text:   The text for the <literal>Cancel</literal> button, which may
- *                 not be %NULL.
- * @cancel_cb: (scope notified):     The callback for the <literal>Cancel</literal> button, which
- *                 may be %NULL.
- * @cpar:          The #PurpleRequestCommonParameters object, which gets
- *                 unref'ed after this call.
- * @user_data:     The data to pass to the callback.
- *
- * Prompts the user for text input.
- *
- * Returns: A UI-specific handle.
- */
-void *purple_request_input(void *handle, const char *title, const char *primary,
-	const char *secondary, const char *default_value, gboolean multiline,
-	gboolean masked, gchar *hint,
-	const char *ok_text, GCallback ok_cb,
-	const char *cancel_text, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar,
-	void *user_data);
-
-/**
- * purple_request_choice:
- * @handle:        The plugin or connection handle.  For some things this
- *                 is <emphasis>extremely</emphasis> important.  See the comments on
- *                 purple_request_input().
- * @title:         The title of the message, or %NULL if it should have
- *                 no title.
- * @primary:       The main point of the message, or %NULL if you're
- *                 feeling enigmatic.
- * @secondary:     Secondary information, or %NULL if there is none.
- * @default_value: The default choice; this should be one of the values
- *                 listed in the varargs.
- * @ok_text:       The text for the <literal>OK</literal> button, which may not
- *                 be %NULL.
- * @ok_cb: (scope notified):         The callback for the <literal>OK</literal> button, which may
- *                 not be %NULL.
- * @cancel_text:   The text for the <literal>Cancel</literal> button, which may
- *                 not be %NULL.
- * @cancel_cb: (scope notified):     The callback for the <literal>Cancel</literal> button, or
- *                 %NULL to do nothing.
- * @cpar:          The #PurpleRequestCommonParameters object, which gets
- *                 unref'ed after this call.
- * @user_data:     The data to pass to the callback.
- * @...:           The choices, which should be pairs of <type>char *</type>
- *                 descriptions and <type>int</type> values, terminated with a
- *                 %NULL parameter.
- *
- * Prompts the user for multiple-choice input.
- *
- * Returns: A UI-specific handle.
- */
-void *purple_request_choice(void *handle, const char *title, const char *primary,
-	const char *secondary, gpointer default_value,
-	const char *ok_text, GCallback ok_cb,
-	const char *cancel_text, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar,
-	void *user_data, ...) G_GNUC_NULL_TERMINATED;
-
-/**
- * purple_request_choice_varg:
- * @handle:        The plugin or connection handle.  For some things this
- *                 is <emphasis>extremely</emphasis> important.  See the comments on
- *                 purple_request_input().
- * @title:         The title of the message, or %NULL if it should have
- *                 no title.
- * @primary:       The main point of the message, or %NULL if you're
- *                 feeling enigmatic.
- * @secondary:     Secondary information, or %NULL if there is none.
- * @default_value: The default choice; this should be one of the values
- *                 listed in the varargs.
- * @ok_text:       The text for the <literal>OK</literal> button, which may not
- *                 be %NULL.
- * @ok_cb: (scope notified):         The callback for the <literal>OK</literal> button, which may
- *                 not be %NULL.
- * @cancel_text:   The text for the <literal>Cancel</literal> button, which may
- *                 not be %NULL.
- * @cancel_cb: (scope notified):     The callback for the <literal>Cancel</literal> button, or
- *                 %NULL to do nothing.
- * @cpar:          The #PurpleRequestCommonParameters object, which gets
- *                 unref'ed after this call.
- * @user_data:     The data to pass to the callback.
- * @choices:       The choices, which should be pairs of <type>char *</type>
- *                 descriptions and <type>int</type> values, terminated with a
- *                 %NULL parameter.
- *
- * <literal>va_list</literal> version of purple_request_choice(); see its
- * documentation.
- */
-void *purple_request_choice_varg(void *handle, const char *title,
-	const char *primary, const char *secondary, gpointer default_value,
-	const char *ok_text, GCallback ok_cb,
-	const char *cancel_text, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar,
-	void *user_data, va_list choices);
-
-/**
- * purple_request_action:
- * @handle:         The plugin or connection handle.  For some things this
- *                  is <emphasis>extremely</emphasis> important.  See the comments on
- *                  purple_request_input().
- * @title:          The title of the message, or %NULL if it should have
- *                  no title.
- * @primary:        The main point of the message, or %NULL if you're
- *                  feeling enigmatic.
- * @secondary:      Secondary information, or %NULL if there is none.
- * @default_action: The default action, zero-indexed; if the third action
- *                  supplied should be the default, supply
- *                  <literal>2</literal>.  This should be the action that
- *                  users are most likely to select.
- * @cpar:           The #PurpleRequestCommonParameters object, which gets
- *                  unref'ed after this call.
- * @user_data:      The data to pass to the callback.
- * @action_count:   The number of actions.
- * @...:            A list of actions.  These are pairs of
- *                  arguments.  The first of each pair is the
- *                  <type>char *</type> label that appears on the button.
- *                  It should have an underscore before the letter you want
- *                  to use as the accelerator key for the button.  The
- *                  second of each pair is the #PurpleRequestActionCb
- *                  function to use when the button is clicked.
- *
- * Prompts the user for an action.
- *
- * This is often represented as a dialog with a button for each action.
- *
- * Returns: A UI-specific handle.
- */
-void *
-purple_request_action(void *handle, const char *title, const char *primary,
-	const char *secondary, int default_action,
-	PurpleRequestCommonParameters *cpar, void *user_data,
-	size_t action_count, ...);
-
-/**
- * purple_request_action_varg:
- * @handle:         The plugin or connection handle.  For some things this
- *                  is <emphasis>extremely</emphasis> important.  See the comments on
- *                  purple_request_input().
- * @title:          The title of the message, or %NULL if it should have
- *                  no title.
- * @primary:        The main point of the message, or %NULL if you're
- *                  feeling enigmatic.
- * @secondary:      Secondary information, or %NULL if there is none.
- * @default_action: The default action, zero-indexed; if the third action
- *                  supplied should be the default, supply
- *                  <literal>2</literal>.  This should be the action that
- *                  users are most likely to select.
- * @cpar:           The #PurpleRequestCommonParameters object, which gets
- *                  unref'ed after this call.
- * @user_data:      The data to pass to the callback.
- * @action_count:   The number of actions.
- * @actions:        A list of actions.  These are pairs of
- *                  arguments.  The first of each pair is the
- *                  <type>char *</type> label that appears on the button.
- *                  It should have an underscore before the letter you want
- *                  to use as the accelerator key for the button.  The
- *                  second of each pair is the #PurpleRequestActionCb
- *                  function to use when the button is clicked.
- *
- * <literal>va_list</literal> version of purple_request_action(); see its
- * documentation.
- */
-void *
-purple_request_action_varg(void *handle, const char *title, const char *primary,
-	const char *secondary, int default_action,
-	PurpleRequestCommonParameters *cpar, void *user_data,
-	size_t action_count, va_list actions);
-
-/**
- * purple_request_wait:
- * @handle:        The plugin or connection handle.  For some things this
- *                 is <emphasis>extremely</emphasis> important.  See the comments on
- *                 purple_request_input().
- * @title:         The title of the message, or %NULL if it should have
- *                 default title.
- * @primary:       The main point of the message, or %NULL if you're
- *                 feeling enigmatic.
- * @secondary:     Secondary information, or %NULL if there is none.
- * @with_progress: %TRUE, if we want to display progress bar, %FALSE
- *                 otherwise
- * @cancel_cb: (scope notified): The callback for the <literal>Cancel</literal> button, which
- *                 may be %NULL.
- * @cpar:          The #PurpleRequestCommonParameters object, which gets
- *                 unref'ed after this call.
- * @user_data:     The data to pass to the callback.
- *
- * Displays a "please wait" dialog.
- *
- * Returns: A UI-specific handle.
- */
-void *
-purple_request_wait(void *handle, const char *title, const char *primary,
-	const char *secondary, gboolean with_progress,
-	PurpleRequestCancelCb cancel_cb, PurpleRequestCommonParameters *cpar,
-	void *user_data);
-
-/**
- * purple_request_wait_pulse:
- * @ui_handle: The request UI handle.
- *
- * Notifies the "please wait" dialog that some progress has been made, but you
- * don't know how much.
- */
-void
-purple_request_wait_pulse(void *ui_handle);
-
-/**
- * purple_request_wait_progress:
- * @ui_handle: The request UI handle.
- * @fraction:  The part of task that is done (between 0.0 and 1.0,
- *                  inclusive).
- *
- * Notifies the "please wait" dialog about progress has been made.
- */
-void
-purple_request_wait_progress(void *ui_handle, gfloat fraction);
-
-/**
- * purple_request_fields:
- * @handle:      The plugin or connection handle.  For some things this
- *               is <emphasis>extremely</emphasis> important.  See the comments on
- *               purple_request_input().
- * @title:       The title of the message, or %NULL if it should have
- *               no title.
- * @primary:     The main point of the message, or %NULL if you're
- *               feeling enigmatic.
- * @secondary:   Secondary information, or %NULL if there is none.
- * @fields:      The list of fields.
- * @ok_text:     The text for the <literal>OK</literal> button, which may not be
- *               %NULL.
- * @ok_cb: (scope notified):       The callback for the <literal>OK</literal> button, which may
- *               not be
- *               %NULL.
- * @cancel_text: The text for the <literal>Cancel</literal> button, which may
- *               not be %NULL.
- * @cancel_cb: (scope notified):   The callback for the <literal>Cancel</literal> button, which
- *               may be %NULL.
- * @cpar:        The #PurpleRequestCommonParameters object, which gets
- *               unref'ed after this call.
- * @user_data:   The data to pass to the callback.
- *
- * Displays groups of fields for the user to fill in.
- *
- * Returns: A UI-specific handle.
- */
-void *
-purple_request_fields(void *handle, const char *title, const char *primary,
-	const char *secondary, PurpleRequestFields *fields,
-	const char *ok_text, GCallback ok_cb,
-	const char *cancel_text, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar,
-	void *user_data);
-
-/**
- * purple_request_is_valid_ui_handle:
- * @ui_handle: The UI handle.
- * @type:      The pointer to variable, where request type may be stored
- *             (may be %NULL).
- *
- * Checks, if passed UI handle is valid.
- *
- * Returns: TRUE, if handle is valid, FALSE otherwise.
- */
-gboolean
-purple_request_is_valid_ui_handle(void *ui_handle, PurpleRequestType *type);
-
-/**
- * purple_request_add_close_notify:
- * @ui_handle:   The UI handle.
- * @notify:      The function to be called.
- * @notify_data: The data to be passed to the callback function.
- *
- * Adds a function called when notification dialog is closed.
- */
-void
-purple_request_add_close_notify(void *ui_handle, GDestroyNotify notify,
-	gpointer notify_data);
-
-/**
- * purple_request_close:
- * @type:     The request type.
- * @uihandle: The request UI handle.
- *
- * Closes a request.
- */
-void purple_request_close(PurpleRequestType type, void *uihandle);
-
-/**
- * purple_request_close_with_handle:
- * @handle: The handle, as supplied as the @handle parameter to one of the
- *          <literal>purple_request_*</literal> functions.
- *
- * Closes all requests registered with the specified handle.
- *
- * See purple_request_input().
- */
-void purple_request_close_with_handle(void *handle);
-
-/**
- * purple_request_yes_no:
- * @handle:         The handle, as supplied as the @handle parameter to one of the
- *                  <literal>purple_request_*</literal> functions.
- * @title:          The title of the message, or %NULL if it should have
- *                  no title.
- * @primary:        The main point of the message, or %NULL if you're
- *                  feeling enigmatic.
- * @secondary:      Secondary information, or %NULL if there is none.
- * @default_action: The default action, zero-indexed; if the third action
- *                  supplied should be the default, supply
- *                  <literal>2</literal>.  This should be the action that
- *                  users are most likely to select.
- * @cpar:           The #PurpleRequestCommonParameters object, which gets
- *                  unref'ed after this call.
- * @user_data:      The data to pass to the callback.
- * @yes_cb:         A #PurpleRequestActionCb to call when yes is selected.
- * @no_cb:          A #PurpleRequestActionCb to call when no is selected.
- *
- * A wrapper for purple_request_action() that uses <literal>Yes</literal> and
- * <literal>No</literal> buttons.
- */
-#define purple_request_yes_no(handle, title, primary, secondary, default_action, cpar, user_data, yes_cb, no_cb) \
-	purple_request_action((handle), (title), (primary), (secondary), \
-		(default_action), (cpar), (user_data), 2, _("_Yes"), (yes_cb), \
-		_("_No"), (no_cb))
-
-/**
- * purple_request_ok_cancel:
- * @handle:         The handle, as supplied as the @handle parameter to one of
- *                  the <literal>purple_request_*</literal> functions.
- * @title:          The title of the message, or %NULL if it should have
- *                  no title.
- * @primary:        The main point of the message, or %NULL if you're
- *                  feeling enigmatic.
- * @secondary:      Secondary information, or %NULL if there is none.
- * @default_action: The default action, zero-indexed; if the third action
- *                  supplied should be the default, supply
- *                  <literal>2</literal>.  This should be the action that
- *                  users are most likely to select.
- * @cpar:           The #PurpleRequestCommonParameters object, which gets
- *                  unref'ed after this call.
- * @user_data:      The data to pass to the callback.
- * @ok_cb:          A #PurpleRequestActionCb to call when ok is selected.
- * @cancel_cb:      A #PurpleRequestActionCb to call when cancel is selected.
- *
- * A wrapper for purple_request_action() that uses <literal>OK</literal> and
- * <literal>Cancel</literal> buttons.
- */
-#define purple_request_ok_cancel(handle, title, primary, secondary, default_action, cpar, user_data, ok_cb, cancel_cb) \
-	purple_request_action((handle), (title), (primary), (secondary), \
-		(default_action), (cpar), (user_data), 2, _("_OK"), (ok_cb), \
-		_("_Cancel"), (cancel_cb))
-
-/**
- * purple_request_accept_cancel:
- * @handle:         The handle, as supplied as the @handle parameter to one of
- *                  the <literal>purple_request_*</literal> functions.
- * @title:          The title of the message, or %NULL if it should have
- *                  no title.
- * @primary:        The main point of the message, or %NULL if you're
- *                  feeling enigmatic.
- * @secondary:      Secondary information, or %NULL if there is none.
- * @default_action: The default action, zero-indexed; if the third action
- *                  supplied should be the default, supply
- *                  <literal>2</literal>.  This should be the action that
- *                  users are most likely to select.
- * @cpar:           The #PurpleRequestCommonParameters object, which gets
- *                  unref'ed after this call.
- * @user_data:      The data to pass to the callback.
- * @accept_cb:      A #PurpleRequestActionCb to call when accepted is selected.
- * @cancel_cb:      A #PurpleRequestActionCb to call when cancel is selected.
- *
- * A wrapper for purple_request_action() that uses Accept and Cancel buttons.
- */
-#define purple_request_accept_cancel(handle, title, primary, secondary, default_action, cpar, user_data, accept_cb, cancel_cb) \
-	purple_request_action((handle), (title), (primary), (secondary), \
-		(default_action), (cpar), (user_data), 2, _("_Accept"), \
-		(accept_cb), _("_Cancel"), (cancel_cb))
-
-/**
- * purple_request_file:
- * @handle:     The plugin or connection handle.  For some things this
- *              is <emphasis>extremely</emphasis> important.  See the comments
- *              on purple_request_input().
- * @title:      The title of the message, or %NULL if it should have no title.
- * @filename:   The default filename (may be %NULL)
- * @savedialog: True if this dialog is being used to save a file.  False if
- *              it is being used to open a file.
- * @ok_cb: (scope notified):      The callback for the <literal>OK</literal> button.
- * @cancel_cb: (scope notified):  The callback for the <literal>Cancel</literal> button, which
- *              may be %NULL.
- * @cpar:       The #PurpleRequestCommonParameters object, which gets unref'ed
- *              after this call.
- * @user_data:  The data to pass to the callback.
- *
- * Displays a file selector request dialog.  Returns the selected filename to
- * the callback.  Can be used for either opening a file or saving a file.
- *
- * Returns: A UI-specific handle.
- */
-void *
-purple_request_file(void *handle, const char *title, const char *filename,
-	gboolean savedialog, GCallback ok_cb, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar, void *user_data);
-
-/**
- * purple_request_folder:
- * @handle:    The plugin or connection handle.  For some things this is
- *             <emphasis>extremely</emphasis> important.  See the comments on
- *             purple_request_input().
- * @title:     The title of the message, or %NULL if it should have no title.
- * @dirname:   The default directory name (may be %NULL)
- * @ok_cb: (scope notified):     The callback for the <literal>OK</literal> button.
- * @cancel_cb: (scope notified): The callback for the <literal>Cancel</literal> button, which
- *             may be %NULL.
- * @cpar:      The #PurpleRequestCommonParameters object, which gets unref'ed
- *             after this call.
- * @user_data: The data to pass to the callback.
- *
- * Displays a folder select dialog. Returns the selected filename to
- * the callback.
- *
- * Returns: A UI-specific handle.
- */
-void *
-purple_request_folder(void *handle, const char *title, const char *dirname,
-	GCallback ok_cb, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar, void *user_data);
-
-/**************************************************************************/
-/* UI Registration Functions                                              */
-/**************************************************************************/
-
-/**
- * purple_request_ui_ops_get_type:
- *
- * The standard _get_type function for #PurpleRequestUiOps.
- *
- * Returns: The #GType for the #PurpleRequestUiOps boxed structure.
- */
-GType purple_request_ui_ops_get_type(void);
-
-/**
- * purple_request_set_ui_ops:
- * @ops: The UI operations structure.
- *
- * Sets the UI operations structure to be used when displaying a
- * request.
- */
-void purple_request_set_ui_ops(PurpleRequestUiOps *ops);
-
-/**
- * purple_request_get_ui_ops:
- *
- * Returns the UI operations structure to be used when displaying a
- * request.
- *
- * Returns: The UI operations structure.
- */
-PurpleRequestUiOps *purple_request_get_ui_ops(void);
-
 G_END_DECLS
 
-#endif /* PURPLE_REQUEST_H */
+#endif /* PURPLE_REQUEST_GROUP_H */
diff --git a/libpurple/request.h b/libpurple/request.h
--- a/libpurple/request.h
+++ b/libpurple/request.h
@@ -42,13 +42,6 @@
 typedef struct _PurpleRequestFields PurpleRequestFields;
 
 /**
- * PurpleRequestFieldGroup:
- *
- * A group of fields with a title.
- */
-typedef struct _PurpleRequestFieldGroup PurpleRequestFieldGroup;
-
-/**
  * PurpleRequestCommonParameters:
  *
  * Common parameters for UI operations.
@@ -59,6 +52,7 @@ typedef struct _PurpleRequestUiOps Purpl
 
 #include "account.h"
 #include "purpleconversation.h"
+#include "purplerequestgroup.h"
 #include "purplerequestfield.h"
 #include "request-datasheet.h"
 
@@ -716,71 +710,6 @@ gpointer purple_request_fields_get_ui_da
 void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data);
 
 /**************************************************************************/
-/* Fields Group API                                                       */
-/**************************************************************************/
-
-/**
- * purple_request_field_group_new:
- * @title: The optional title to give the group.
- *
- * Creates a fields group with an optional title.
- *
- * Returns: (transfer full): A new fields group
- */
-PurpleRequestFieldGroup *purple_request_field_group_new(const char *title);
-
-/**
- * purple_request_field_group_destroy:
- * @group: The group to destroy.
- *
- * Destroys a fields group.
- */
-void purple_request_field_group_destroy(PurpleRequestFieldGroup *group);
-
-/**
- * purple_request_field_group_add_field:
- * @group: The group to add the field to.
- * @field: The field to add to the group.
- *
- * Adds a field to the group.
- */
-void purple_request_field_group_add_field(PurpleRequestFieldGroup *group,
-										PurpleRequestField *field);
-
-/**
- * purple_request_field_group_get_title:
- * @group: The group.
- *
- * Returns the title of a fields group.
- *
- * Returns: The title, if set.
- */
-const char *purple_request_field_group_get_title(
-		const PurpleRequestFieldGroup *group);
-
-/**
- * purple_request_field_group_get_fields:
- * @group: The group.
- *
- * Returns a list of all fields in a group.
- *
- * Returns: (element-type PurpleRequestField) (transfer none): The list of fields in the group.
- */
-GList *purple_request_field_group_get_fields(
-		const PurpleRequestFieldGroup *group);
-
-/**
- * purple_request_field_group_get_fields_list:
- * @group: The group.
- *
- * Returns a list of all fields in a group.
- *
- * Returns: (transfer none): The list of fields in the group.
- */
-PurpleRequestFields *purple_request_field_group_get_fields_list(
-		const PurpleRequestFieldGroup *group);
-
-/**************************************************************************/
 /* Request API                                                            */
 /**************************************************************************/
 
diff --git a/libpurple/request.c b/libpurple/purplerequestgroup.c
copy from libpurple/request.c
copy to libpurple/purplerequestgroup.c
--- a/libpurple/request.c
+++ b/libpurple/purplerequestgroup.c
@@ -22,43 +22,9 @@
 #include <glib/gi18n-lib.h>
 
 #include "glibcompat.h"
-#include "notify.h"
-#include "purplemarkup.h"
-#include "request.h"
-#include "debug.h"
-#include "purplekeyvaluepair.h"
+#include "purplerequestgroup.h"
 #include "purpleprivate.h"
 
-static PurpleRequestUiOps *request_ui_ops = NULL;
-static GList *handles = NULL;
-
-typedef struct
-{
-	GDestroyNotify cb;
-	gpointer data;
-} PurpleRequestCloseNotified;
-
-typedef struct
-{
-	PurpleRequestType type;
-	void *handle;
-	void *ui_handle;
-	GSList *notify_on_close;
-} PurpleRequestInfo;
-
-struct _PurpleRequestFields
-{
-	GList *groups;
-
-	GHashTable *fields;
-
-	GList *required_fields;
-
-	GList *validated_fields;
-
-	void *ui_data;
-};
-
 struct _PurpleRequestFieldGroup
 {
 	PurpleRequestFields *fields_list;
@@ -68,553 +34,6 @@ struct _PurpleRequestFieldGroup
 	GList *fields;
 };
 
-struct _PurpleRequestCommonParameters {
-	PurpleAccount *account;
-	PurpleConversation *conv;
-
-	PurpleRequestIconType icon_type;
-	gconstpointer icon_data;
-	gsize icon_size;
-
-	gboolean html;
-
-	gboolean compact;
-
-	PurpleRequestHelpCb help_cb;
-	gpointer help_data;
-
-	GSList *extra_actions;
-
-	gpointer parent_from;
-};
-
-PurpleRequestCommonParameters *
-purple_request_cpar_new(void)
-{
-	return g_rc_box_new0(PurpleRequestCommonParameters);
-}
-
-PurpleRequestCommonParameters *
-purple_request_cpar_from_connection(PurpleConnection *gc)
-{
-	if (gc == NULL)
-		return purple_request_cpar_new();
-	return purple_request_cpar_from_account(
-		purple_connection_get_account(gc));
-}
-
-PurpleRequestCommonParameters *
-purple_request_cpar_from_account(PurpleAccount *account)
-{
-	PurpleRequestCommonParameters *cpar;
-
-	cpar = purple_request_cpar_new();
-	purple_request_cpar_set_account(cpar, account);
-
-	return cpar;
-}
-
-PurpleRequestCommonParameters *
-purple_request_cpar_from_conversation(PurpleConversation *conv)
-{
-	PurpleRequestCommonParameters *cpar;
-	PurpleAccount *account = NULL;
-
-	if (conv != NULL) {
-		account = purple_connection_get_account(
-			purple_conversation_get_connection(conv));
-	}
-
-	cpar = purple_request_cpar_new();
-	purple_request_cpar_set_account(cpar, account);
-	purple_request_cpar_set_conversation(cpar, conv);
-
-	return cpar;
-}
-
-void
-purple_request_cpar_ref(PurpleRequestCommonParameters *cpar)
-{
-	g_return_if_fail(cpar != NULL);
-
-	g_rc_box_acquire(cpar);
-}
-
-static void
-purple_request_cpar_destroy(PurpleRequestCommonParameters *cpar) {
-	g_slist_free_full(cpar->extra_actions,
-	                  (GDestroyNotify)purple_key_value_pair_free);
-}
-
-void
-purple_request_cpar_unref(PurpleRequestCommonParameters *cpar)
-{
-	if(cpar == NULL) {
-		return;
-	}
-
-	g_rc_box_release_full(cpar, (GDestroyNotify)purple_request_cpar_destroy);
-}
-
-void
-purple_request_cpar_set_account(PurpleRequestCommonParameters *cpar,
-	PurpleAccount *account)
-{
-	g_return_if_fail(cpar != NULL);
-
-	cpar->account = account;
-}
-
-PurpleAccount *
-purple_request_cpar_get_account(PurpleRequestCommonParameters *cpar)
-{
-	if (cpar == NULL)
-		return NULL;
-
-	return cpar->account;
-}
-
-void
-purple_request_cpar_set_conversation(PurpleRequestCommonParameters *cpar,
-	PurpleConversation *conv)
-{
-	g_return_if_fail(cpar != NULL);
-
-	cpar->conv = conv;
-}
-
-PurpleConversation *
-purple_request_cpar_get_conversation(PurpleRequestCommonParameters *cpar)
-{
-	if (cpar == NULL)
-		return NULL;
-
-	return cpar->conv;
-}
-
-void
-purple_request_cpar_set_icon(PurpleRequestCommonParameters *cpar,
-	PurpleRequestIconType icon_type)
-{
-	g_return_if_fail(cpar != NULL);
-
-	cpar->icon_type = icon_type;
-}
-
-PurpleRequestIconType
-purple_request_cpar_get_icon(PurpleRequestCommonParameters *cpar)
-{
-	if (cpar == NULL)
-		return PURPLE_REQUEST_ICON_DEFAULT;
-
-	return cpar->icon_type;
-}
-
-void
-purple_request_cpar_set_custom_icon(PurpleRequestCommonParameters *cpar,
-	gconstpointer icon_data, gsize icon_size)
-{
-	g_return_if_fail(cpar != NULL);
-	g_return_if_fail((icon_data == NULL) == (icon_size == 0));
-
-	cpar->icon_data = icon_data;
-	cpar->icon_size = icon_size;
-}
-
-gconstpointer
-purple_request_cpar_get_custom_icon(PurpleRequestCommonParameters *cpar,
-	gsize *icon_size)
-{
-	if (cpar == NULL) {
-		if (icon_size != NULL)
-			*icon_size = 0;
-		return NULL;
-	}
-
-	if (icon_size != NULL)
-		*icon_size = cpar->icon_size;
-	return cpar->icon_data;
-}
-
-void
-purple_request_cpar_set_html(PurpleRequestCommonParameters *cpar,
-	gboolean enabled)
-{
-	g_return_if_fail(cpar != NULL);
-
-	cpar->html = enabled;
-}
-
-gboolean
-purple_request_cpar_is_html(PurpleRequestCommonParameters *cpar)
-{
-	if (cpar == NULL)
-		return FALSE;
-
-	return cpar->html;
-}
-
-void
-purple_request_cpar_set_compact(PurpleRequestCommonParameters *cpar,
-	gboolean compact)
-{
-	g_return_if_fail(cpar != NULL);
-
-	cpar->compact = compact;
-}
-
-gboolean
-purple_request_cpar_is_compact(PurpleRequestCommonParameters *cpar)
-{
-	if (cpar == NULL)
-		return FALSE;
-
-	return cpar->compact;
-}
-
-void
-purple_request_cpar_set_help_cb(PurpleRequestCommonParameters *cpar,
-	PurpleRequestHelpCb cb, gpointer user_data)
-{
-	g_return_if_fail(cpar != NULL);
-
-	cpar->help_cb = cb;
-	cpar->help_data = cb ? user_data : NULL;
-}
-
-PurpleRequestHelpCb
-purple_request_cpar_get_help_cb(PurpleRequestCommonParameters *cpar,
-	gpointer *user_data)
-{
-	if (cpar == NULL)
-		return NULL;
-
-	if (user_data != NULL)
-		*user_data = cpar->help_data;
-	return cpar->help_cb;
-}
-
-void
-purple_request_cpar_set_extra_actions(PurpleRequestCommonParameters *cpar, ...)
-{
-	va_list args;
-	GSList *extra = NULL;
-
-	g_slist_free_full(cpar->extra_actions, (GDestroyNotify)purple_key_value_pair_free);
-
-	va_start(args, cpar);
-
-	while (TRUE) {
-		const gchar *label;
-		PurpleRequestFieldsCb cb;
-		PurpleKeyValuePair *extra_action;
-
-		label = va_arg(args, const gchar*);
-		if (label == NULL)
-			break;
-		cb = va_arg(args, PurpleRequestFieldsCb);
-
-		extra_action = purple_key_value_pair_new(label, cb);
-
-		extra = g_slist_append(extra, extra_action);
-	}
-
-	va_end(args);
-
-	cpar->extra_actions = extra;
-}
-
-GSList *
-purple_request_cpar_get_extra_actions(PurpleRequestCommonParameters *cpar)
-{
-	if (cpar == NULL)
-		return NULL;
-
-	return cpar->extra_actions;
-}
-
-void
-purple_request_cpar_set_parent_from(PurpleRequestCommonParameters *cpar,
-	gpointer ui_handle)
-{
-	g_return_if_fail(cpar != NULL);
-
-	cpar->parent_from = ui_handle;
-}
-
-gpointer
-purple_request_cpar_get_parent_from(PurpleRequestCommonParameters *cpar)
-{
-	if (cpar == NULL)
-		return NULL;
-
-	return cpar->parent_from;
-}
-
-static PurpleRequestInfo *
-purple_request_info_from_ui_handle(void *ui_handle)
-{
-	GList *it;
-
-	g_return_val_if_fail(ui_handle != NULL, NULL);
-
-	for (it = handles; it != NULL; it = g_list_next(it)) {
-		PurpleRequestInfo *info = it->data;
-
-		if (info->ui_handle == ui_handle)
-			return info;
-	}
-
-	return NULL;
-}
-
-PurpleRequestFields *
-purple_request_fields_new(void)
-{
-	PurpleRequestFields *fields;
-
-	fields = g_new0(PurpleRequestFields, 1);
-
-	fields->fields = g_hash_table_new_full(g_str_hash, g_str_equal,
-										   g_free, NULL);
-
-	return fields;
-}
-
-void
-purple_request_fields_destroy(PurpleRequestFields *fields)
-{
-	g_return_if_fail(fields != NULL);
-
-	g_list_free_full(fields->groups,
-	                 (GDestroyNotify)purple_request_field_group_destroy);
-	g_list_free(fields->required_fields);
-	g_list_free(fields->validated_fields);
-	g_hash_table_destroy(fields->fields);
-	g_free(fields);
-}
-
-void
-purple_request_fields_add_group(PurpleRequestFields *fields,
-							  PurpleRequestFieldGroup *group)
-{
-	GList *l;
-	PurpleRequestField *field;
-
-	g_return_if_fail(fields != NULL);
-	g_return_if_fail(group  != NULL);
-
-	fields->groups = g_list_append(fields->groups, group);
-
-	group->fields_list = fields;
-
-	for (l = purple_request_field_group_get_fields(group);
-		 l != NULL;
-		 l = l->next) {
-
-		field = l->data;
-
-		g_hash_table_insert(fields->fields,
-			g_strdup(purple_request_field_get_id(field)), field);
-
-		if (purple_request_field_is_required(field)) {
-			fields->required_fields =
-				g_list_append(fields->required_fields, field);
-		}
-
-		if (purple_request_field_is_validatable(field)) {
-			fields->validated_fields =
-				g_list_append(fields->validated_fields, field);
-		}
-	}
-}
-
-GList *
-purple_request_fields_get_groups(const PurpleRequestFields *fields)
-{
-	g_return_val_if_fail(fields != NULL, NULL);
-
-	return fields->groups;
-}
-
-gboolean
-purple_request_fields_exists(const PurpleRequestFields *fields, const char *id)
-{
-	g_return_val_if_fail(fields != NULL, FALSE);
-	g_return_val_if_fail(id     != NULL, FALSE);
-
-	return (g_hash_table_lookup(fields->fields, id) != NULL);
-}
-
-const GList *
-purple_request_fields_get_required(const PurpleRequestFields *fields)
-{
-	g_return_val_if_fail(fields != NULL, NULL);
-
-	return fields->required_fields;
-}
-
-const GList *
-purple_request_fields_get_validatable(const PurpleRequestFields *fields)
-{
-	g_return_val_if_fail(fields != NULL, NULL);
-
-	return fields->validated_fields;
-}
-
-gboolean
-purple_request_fields_is_field_required(const PurpleRequestFields *fields,
-									  const char *id)
-{
-	PurpleRequestField *field;
-
-	g_return_val_if_fail(fields != NULL, FALSE);
-	g_return_val_if_fail(id     != NULL, FALSE);
-
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
-		return FALSE;
-
-	return purple_request_field_is_required(field);
-}
-
-gboolean
-purple_request_fields_all_required_filled(const PurpleRequestFields *fields)
-{
-	GList *l;
-
-	g_return_val_if_fail(fields != NULL, FALSE);
-
-	for (l = fields->required_fields; l != NULL; l = l->next)
-	{
-		PurpleRequestField *field = (PurpleRequestField *)l->data;
-
-		if (!purple_request_field_is_filled(field))
-			return FALSE;
-	}
-
-	return TRUE;
-}
-
-gboolean
-purple_request_fields_all_valid(const PurpleRequestFields *fields)
-{
-	GList *l;
-
-	g_return_val_if_fail(fields != NULL, FALSE);
-
-	for (l = fields->validated_fields; l != NULL; l = l->next)
-	{
-		PurpleRequestField *field = (PurpleRequestField *)l->data;
-
-		if (!purple_request_field_is_valid(field, NULL))
-			return FALSE;
-	}
-
-	return TRUE;
-}
-
-PurpleRequestField *
-purple_request_fields_get_field(const PurpleRequestFields *fields, const char *id)
-{
-	PurpleRequestField *field;
-
-	g_return_val_if_fail(fields != NULL, NULL);
-	g_return_val_if_fail(id     != NULL, NULL);
-
-	field = g_hash_table_lookup(fields->fields, id);
-
-	g_return_val_if_fail(field != NULL, NULL);
-
-	return field;
-}
-
-const char *
-purple_request_fields_get_string(const PurpleRequestFields *fields, const char *id)
-{
-	PurpleRequestField *field;
-
-	g_return_val_if_fail(fields != NULL, NULL);
-	g_return_val_if_fail(id     != NULL, NULL);
-
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
-		return NULL;
-
-	return purple_request_field_string_get_value(field);
-}
-
-int
-purple_request_fields_get_integer(const PurpleRequestFields *fields,
-								const char *id)
-{
-	PurpleRequestField *field;
-
-	g_return_val_if_fail(fields != NULL, 0);
-	g_return_val_if_fail(id     != NULL, 0);
-
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
-		return 0;
-
-	return purple_request_field_int_get_value(field);
-}
-
-gboolean
-purple_request_fields_get_bool(const PurpleRequestFields *fields, const char *id)
-{
-	PurpleRequestField *field;
-
-	g_return_val_if_fail(fields != NULL, FALSE);
-	g_return_val_if_fail(id     != NULL, FALSE);
-
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
-		return FALSE;
-
-	return purple_request_field_bool_get_value(field);
-}
-
-gpointer
-purple_request_fields_get_choice(const PurpleRequestFields *fields,
-	const char *id)
-{
-	PurpleRequestField *field;
-
-	g_return_val_if_fail(fields != NULL, NULL);
-	g_return_val_if_fail(id != NULL, NULL);
-
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
-		return NULL;
-
-	return purple_request_field_choice_get_value(field);
-}
-
-PurpleAccount *
-purple_request_fields_get_account(const PurpleRequestFields *fields,
-								const char *id)
-{
-	PurpleRequestField *field;
-
-	g_return_val_if_fail(fields != NULL, NULL);
-	g_return_val_if_fail(id     != NULL, NULL);
-
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
-		return NULL;
-
-	return purple_request_field_account_get_value(field);
-}
-
-gpointer purple_request_fields_get_ui_data(const PurpleRequestFields *fields)
-{
-	g_return_val_if_fail(fields != NULL, NULL);
-
-	return fields->ui_data;
-}
-
-void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data)
-{
-	g_return_if_fail(fields != NULL);
-
-	fields->ui_data = ui_data;
-}
-
 PurpleRequestFieldGroup *
 purple_request_field_group_new(const char *title)
 {
@@ -641,19 +60,23 @@ purple_request_field_group_destroy(Purpl
 }
 
 void
+_purple_request_field_group_set_field_list(PurpleRequestFieldGroup *group,
+                                           PurpleRequestFields *fields)
+{
+	g_return_if_fail(group != NULL);
+
+	group->fields_list = fields;
+}
+
+void
 _purple_request_field_group_set_field_required(PurpleRequestFieldGroup *group,
                                                PurpleRequestField *field,
                                                gboolean required)
 {
-		if(required) {
-			group->fields_list->required_fields =
-				g_list_append(group->fields_list->required_fields,
-							  field);
-		} else {
-			group->fields_list->required_fields =
-				g_list_remove(group->fields_list->required_fields,
-							  field);
-		}
+	g_return_if_fail(group != NULL);
+
+	_purple_request_field_list_set_field_required(group->fields_list, field,
+	                                              required);
 }
 
 void
@@ -661,12 +84,10 @@ void
                                                 PurpleRequestField *field,
                                                 gboolean validator)
 {
-		PurpleRequestFields *flist = group->fields_list;
-		flist->validated_fields = g_list_remove(flist->validated_fields, field);
-		if(validator) {
-			flist->validated_fields = g_list_append(flist->validated_fields,
-			                                        field);
-		}
+	g_return_if_fail(group != NULL);
+
+	_purple_request_field_list_set_field_validator(group->fields_list, field,
+	                                               validator);
 }
 
 void
@@ -678,22 +99,8 @@ purple_request_field_group_add_field(Pur
 
 	group->fields = g_list_append(group->fields, field);
 
-	if (group->fields_list != NULL)
-	{
-		g_hash_table_insert(group->fields_list->fields,
-							g_strdup(purple_request_field_get_id(field)), field);
-
-		if (purple_request_field_is_required(field))
-		{
-			group->fields_list->required_fields =
-				g_list_append(group->fields_list->required_fields, field);
-		}
-
-		if (purple_request_field_is_validatable(field))
-		{
-			group->fields_list->validated_fields =
-				g_list_append(group->fields_list->validated_fields, field);
-		}
+	if(group->fields_list != NULL) {
+		_purple_request_field_list_add_field(group->fields_list, field);
 	}
 
 	_purple_request_field_set_group(field, group);
@@ -722,548 +129,3 @@ purple_request_field_group_get_fields_li
 
 	return group->fields_list;
 }
-
-/* -- */
-
-static gchar *
-purple_request_strip_html_custom(const gchar *html)
-{
-	gchar *tmp, *ret;
-
-	tmp = purple_strreplace(html, "\n", "<br>");
-	ret = purple_markup_strip_html(tmp);
-	g_free(tmp);
-
-	return ret;
-}
-
-static gchar **
-purple_request_strip_html(PurpleRequestCommonParameters *cpar,
-	const char **primary, const char **secondary)
-{
-	PurpleRequestUiOps *ops = purple_request_get_ui_ops();
-	gchar **ret;
-
-	if (!purple_request_cpar_is_html(cpar))
-		return NULL;
-	if (ops->features & PURPLE_REQUEST_FEATURE_HTML)
-		return NULL;
-
-	ret = g_new0(gchar*, 3);
-	*primary = ret[0] = purple_request_strip_html_custom(*primary);
-	*secondary = ret[1] = purple_request_strip_html_custom(*secondary);
-
-	return ret;
-}
-
-void *
-purple_request_input(void *handle, const char *title, const char *primary,
-				   const char *secondary, const char *default_value,
-				   gboolean multiline, gboolean masked, gchar *hint,
-				   const char *ok_text, GCallback ok_cb,
-				   const char *cancel_text, GCallback cancel_cb,
-				   PurpleRequestCommonParameters *cpar,
-				   void *user_data)
-{
-	PurpleRequestUiOps *ops;
-
-	if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL)) {
-		purple_request_cpar_unref(cpar);
-		g_warn_if_fail(ok_text != NULL);
-		g_warn_if_fail(ok_cb != NULL);
-		g_return_val_if_reached(NULL);
-	}
-
-	ops = purple_request_get_ui_ops();
-
-	if (ops != NULL && ops->request_input != NULL) {
-		PurpleRequestInfo *info;
-		gchar **tmp;
-
-		tmp = purple_request_strip_html(cpar, &primary, &secondary);
-
-		info            = g_new0(PurpleRequestInfo, 1);
-		info->type      = PURPLE_REQUEST_INPUT;
-		info->handle    = handle;
-		info->ui_handle = ops->request_input(title, primary, secondary,
-			default_value, multiline, masked, hint, ok_text, ok_cb,
-			cancel_text, cancel_cb, cpar, user_data);
-
-		handles = g_list_append(handles, info);
-
-		g_strfreev(tmp);
-		purple_request_cpar_unref(cpar);
-		return info->ui_handle;
-	}
-
-	purple_request_cpar_unref(cpar);
-	return NULL;
-}
-
-void *
-purple_request_choice(void *handle, const char *title, const char *primary,
-	const char *secondary, gpointer default_value, const char *ok_text,
-	GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar, void *user_data, ...)
-{
-	void *ui_handle;
-	va_list args;
-
-	if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL)) {
-		purple_request_cpar_unref(cpar);
-		g_warn_if_fail(ok_text != NULL);
-		g_warn_if_fail(ok_cb != NULL);
-		g_return_val_if_reached(NULL);
-	}
-
-	va_start(args, user_data);
-	ui_handle = purple_request_choice_varg(handle, title, primary, secondary,
-					     default_value, ok_text, ok_cb,
-					     cancel_text, cancel_cb,
-					     cpar, user_data, args);
-	va_end(args);
-
-	return ui_handle;
-}
-
-void *
-purple_request_choice_varg(void *handle, const char *title, const char *primary,
-	const char *secondary, gpointer default_value, const char *ok_text,
-	GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar, void *user_data, va_list choices)
-{
-	PurpleRequestUiOps *ops;
-
-	if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL ||
-		cancel_text == NULL))
-	{
-		purple_request_cpar_unref(cpar);
-		g_warn_if_fail(ok_text != NULL);
-		g_warn_if_fail(ok_cb != NULL);
-		g_warn_if_fail(cancel_text != NULL);
-		g_return_val_if_reached(NULL);
-	}
-
-	ops = purple_request_get_ui_ops();
-
-	if (ops != NULL && ops->request_choice != NULL) {
-		PurpleRequestInfo *info;
-		gchar **tmp;
-
-		tmp = purple_request_strip_html(cpar, &primary, &secondary);
-
-		info            = g_new0(PurpleRequestInfo, 1);
-		info->type      = PURPLE_REQUEST_CHOICE;
-		info->handle    = handle;
-		info->ui_handle = ops->request_choice(title, primary, secondary,
-			default_value, ok_text, ok_cb, cancel_text, cancel_cb,
-			cpar, user_data, choices);
-
-		handles = g_list_append(handles, info);
-
-		g_strfreev(tmp);
-		purple_request_cpar_unref(cpar);
-		return info->ui_handle;
-	}
-
-	purple_request_cpar_unref(cpar);
-	return NULL;
-}
-
-void *
-purple_request_action(void *handle, const char *title, const char *primary,
-	const char *secondary, int default_action,
-	PurpleRequestCommonParameters *cpar, void *user_data,
-	size_t action_count, ...)
-{
-	void *ui_handle;
-	va_list args;
-
-	va_start(args, action_count);
-	ui_handle = purple_request_action_varg(handle, title, primary,
-		secondary, default_action, cpar, user_data, action_count, args);
-	va_end(args);
-
-	return ui_handle;
-}
-
-void *
-purple_request_action_varg(void *handle, const char *title, const char *primary,
-	const char *secondary, int default_action,
-	PurpleRequestCommonParameters *cpar, void *user_data,
-	size_t action_count, va_list actions)
-{
-	PurpleRequestUiOps *ops;
-
-	ops = purple_request_get_ui_ops();
-
-	if (ops != NULL && ops->request_action != NULL) {
-		PurpleRequestInfo *info;
-		gchar **tmp;
-
-		tmp = purple_request_strip_html(cpar, &primary, &secondary);
-
-		info            = g_new0(PurpleRequestInfo, 1);
-		info->type      = PURPLE_REQUEST_ACTION;
-		info->handle    = handle;
-		info->ui_handle = ops->request_action(title, primary, secondary,
-			default_action, cpar, user_data, action_count, actions);
-
-		handles = g_list_append(handles, info);
-
-		g_strfreev(tmp);
-		purple_request_cpar_unref(cpar);
-		return info->ui_handle;
-	}
-
-	purple_request_cpar_unref(cpar);
-	return NULL;
-}
-
-void *
-purple_request_wait(void *handle, const char *title, const char *primary,
-	const char *secondary, gboolean with_progress,
-	PurpleRequestCancelCb cancel_cb, PurpleRequestCommonParameters *cpar,
-	void *user_data)
-{
-	PurpleRequestUiOps *ops;
-
-	if (primary == NULL)
-		primary = _("Please wait...");
-
-	ops = purple_request_get_ui_ops();
-
-	if (ops != NULL && ops->request_wait != NULL) {
-		PurpleRequestInfo *info;
-		gchar **tmp;
-
-		tmp = purple_request_strip_html(cpar, &primary, &secondary);
-
-		info            = g_new0(PurpleRequestInfo, 1);
-		info->type      = PURPLE_REQUEST_WAIT;
-		info->handle    = handle;
-		info->ui_handle = ops->request_wait(title, primary, secondary,
-			with_progress, cancel_cb, cpar, user_data);
-
-		handles = g_list_append(handles, info);
-
-		g_strfreev(tmp);
-		purple_request_cpar_unref(cpar);
-		return info->ui_handle;
-	}
-
-	if (cpar == NULL)
-		cpar = purple_request_cpar_new();
-	if (purple_request_cpar_get_icon(cpar) == PURPLE_REQUEST_ICON_DEFAULT)
-		purple_request_cpar_set_icon(cpar, PURPLE_REQUEST_ICON_WAIT);
-
-	return purple_request_action(handle, title, primary, secondary,
-		PURPLE_DEFAULT_ACTION_NONE, cpar, user_data,
-		cancel_cb ? 1 : 0, _("Cancel"), cancel_cb);
-}
-
-void
-purple_request_wait_pulse(void *ui_handle)
-{
-	PurpleRequestUiOps *ops;
-
-	ops = purple_request_get_ui_ops();
-
-	if (ops == NULL || ops->request_wait_update == NULL)
-		return;
-
-	ops->request_wait_update(ui_handle, TRUE, 0.0);
-}
-
-void
-purple_request_wait_progress(void *ui_handle, gfloat fraction)
-{
-	PurpleRequestUiOps *ops;
-
-	ops = purple_request_get_ui_ops();
-
-	if (ops == NULL || ops->request_wait_update == NULL)
-		return;
-
-	if (fraction < 0.0 || fraction > 1.0) {
-		purple_debug_warning("request", "Fraction parameter out of "
-			"range: %f", fraction);
-		if (fraction < 0.0)
-			fraction = 0.0;
-		else /* if (fraction > 1.0) */
-			fraction = 1.0;
-	}
-
-	ops->request_wait_update(ui_handle, FALSE, fraction);
-}
-
-static void
-purple_request_fields_strip_html(PurpleRequestFields *fields)
-{
-	GList *itg;
-
-	for (itg = fields->groups; itg != NULL; itg = g_list_next(itg)) {
-		PurpleRequestFieldGroup *group = itg->data;
-		GList *itf;
-
-		for (itf = group->fields; itf != NULL; itf = g_list_next(itf)) {
-			PurpleRequestField *field = itf->data;
-			const char *old_label;
-			gchar *new_label;
-
-			old_label = purple_request_field_get_label(field);
-			new_label = purple_request_strip_html_custom(old_label);
-			if(g_strcmp0(new_label, old_label) != 0) {
-				purple_request_field_set_label(field, new_label);
-			}
-			g_free(new_label);
-		}
-	}
-}
-
-void *
-purple_request_fields(void *handle, const char *title, const char *primary,
-	const char *secondary, PurpleRequestFields *fields, const char *ok_text,
-	GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar, void *user_data)
-{
-	PurpleRequestUiOps *ops;
-
-	if (G_UNLIKELY(fields == NULL ||
-		((ok_text == NULL) != (ok_cb == NULL)) ||
-		cancel_text == NULL))
-	{
-		purple_request_cpar_unref(cpar);
-		g_warn_if_fail(fields != NULL);
-		g_warn_if_fail((ok_text == NULL) != (ok_cb == NULL));
-		g_warn_if_fail(cancel_text != NULL);
-		g_return_val_if_reached(NULL);
-	}
-
-	ops = purple_request_get_ui_ops();
-
-	if (purple_request_cpar_is_html(cpar) &&
-		!((ops->features & PURPLE_REQUEST_FEATURE_HTML)))
-	{
-		purple_request_fields_strip_html(fields);
-	}
-
-	if (ops != NULL && ops->request_fields != NULL) {
-		PurpleRequestInfo *info;
-		gchar **tmp;
-
-		tmp = purple_request_strip_html(cpar, &primary, &secondary);
-
-		info            = g_new0(PurpleRequestInfo, 1);
-		info->type      = PURPLE_REQUEST_FIELDS;
-		info->handle    = handle;
-		info->ui_handle = ops->request_fields(title, primary, secondary,
-			fields, ok_text, ok_cb, cancel_text, cancel_cb,
-			cpar, user_data);
-
-		handles = g_list_append(handles, info);
-
-		g_strfreev(tmp);
-		purple_request_cpar_unref(cpar);
-		return info->ui_handle;
-	}
-
-	purple_request_cpar_unref(cpar);
-	return NULL;
-}
-
-void *
-purple_request_file(void *handle, const char *title, const char *filename,
-	gboolean savedialog, GCallback ok_cb, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar, void *user_data)
-{
-	PurpleRequestUiOps *ops;
-
-	ops = purple_request_get_ui_ops();
-
-	if (ops != NULL && ops->request_file != NULL) {
-		PurpleRequestInfo *info;
-
-		info            = g_new0(PurpleRequestInfo, 1);
-		info->type      = PURPLE_REQUEST_FILE;
-		info->handle    = handle;
-		info->ui_handle = ops->request_file(title, filename, savedialog,
-			ok_cb, cancel_cb, cpar, user_data);
-		handles = g_list_append(handles, info);
-
-		purple_request_cpar_unref(cpar);
-		return info->ui_handle;
-	}
-
-	purple_request_cpar_unref(cpar);
-	return NULL;
-}
-
-void *
-purple_request_folder(void *handle, const char *title, const char *dirname,
-	GCallback ok_cb, GCallback cancel_cb,
-	PurpleRequestCommonParameters *cpar, void *user_data)
-{
-	PurpleRequestUiOps *ops;
-
-	ops = purple_request_get_ui_ops();
-
-	if (ops != NULL && ops->request_file != NULL) {
-		PurpleRequestInfo *info;
-
-		info            = g_new0(PurpleRequestInfo, 1);
-		info->type      = PURPLE_REQUEST_FOLDER;
-		info->handle    = handle;
-		info->ui_handle = ops->request_folder(title, dirname, ok_cb,
-			cancel_cb, cpar, user_data);
-		handles = g_list_append(handles, info);
-
-		purple_request_cpar_unref(cpar);
-		return info->ui_handle;
-	}
-
-	purple_request_cpar_unref(cpar);
-	return NULL;
-}
-
-gboolean
-purple_request_is_valid_ui_handle(void *ui_handle, PurpleRequestType *type)
-{
-	PurpleRequestInfo *info;
-
-	if (ui_handle == NULL)
-		return FALSE;
-
-	info = purple_request_info_from_ui_handle(ui_handle);
-
-	if (info == NULL)
-		return FALSE;
-
-	if (type != NULL)
-		*type = info->type;
-
-	return TRUE;
-}
-
-void
-purple_request_add_close_notify(void *ui_handle, GDestroyNotify notify,
-	gpointer notify_data)
-{
-	PurpleRequestInfo *info;
-	PurpleRequestCloseNotified *notified;
-
-	g_return_if_fail(ui_handle != NULL);
-	g_return_if_fail(notify != NULL);
-
-	info = purple_request_info_from_ui_handle(ui_handle);
-	g_return_if_fail(info != NULL);
-
-	notified = g_new0(PurpleRequestCloseNotified, 1);
-	notified->cb = notify;
-	notified->data = notify_data;
-
-	info->notify_on_close = g_slist_append(info->notify_on_close, notified);
-}
-
-static void
-purple_request_close_info(PurpleRequestInfo *info)
-{
-	PurpleRequestUiOps *ops;
-	GSList *it;
-
-	ops = purple_request_get_ui_ops();
-
-	purple_notify_close_with_handle(info->ui_handle);
-	purple_request_close_with_handle(info->ui_handle);
-
-	if (ops != NULL && ops->close_request != NULL)
-		ops->close_request(info->type, info->ui_handle);
-
-	for (it = info->notify_on_close; it; it = g_slist_next(it)) {
-		PurpleRequestCloseNotified *notify = it->data;
-
-		notify->cb(notify->data);
-	}
-
-	g_slist_free_full(info->notify_on_close, g_free);
-	g_free(info);
-}
-
-void
-purple_request_close(G_GNUC_UNUSED PurpleRequestType type, void *ui_handle)
-{
-	GList *l;
-
-	g_return_if_fail(ui_handle != NULL);
-
-	for (l = handles; l != NULL; l = l->next) {
-		PurpleRequestInfo *info = l->data;
-
-		if (info->ui_handle == ui_handle) {
-			handles = g_list_delete_link(handles, l);
-			purple_request_close_info(info);
-			break;
-		}
-	}
-}
-
-void
-purple_request_close_with_handle(void *handle)
-{
-	GList *l, *l_next;
-
-	g_return_if_fail(handle != NULL);
-
-	for (l = handles; l != NULL; l = l_next) {
-		PurpleRequestInfo *info = l->data;
-
-		l_next = l->next;
-
-		if (info->handle == handle) {
-			handles = g_list_delete_link(handles, l);
-			purple_request_close_info(info);
-		}
-	}
-}
-
-void
-purple_request_set_ui_ops(PurpleRequestUiOps *ops)
-{
-	request_ui_ops = ops;
-}
-
-PurpleRequestUiOps *
-purple_request_get_ui_ops(void)
-{
-	return request_ui_ops;
-}
-
-/**************************************************************************
- * GBoxed code
- **************************************************************************/
-static PurpleRequestUiOps *
-purple_request_ui_ops_copy(PurpleRequestUiOps *ops)
-{
-	PurpleRequestUiOps *ops_new;
-
-	g_return_val_if_fail(ops != NULL, NULL);
-
-	ops_new = g_new(PurpleRequestUiOps, 1);
-	*ops_new = *ops;
-
-	return ops_new;
-}
-
-GType
-purple_request_ui_ops_get_type(void)
-{
-	static GType type = 0;
-
-	if (type == 0) {
-		type = g_boxed_type_register_static("PurpleRequestUiOps",
-				(GBoxedCopyFunc)purple_request_ui_ops_copy,
-				(GBoxedFreeFunc)g_free);
-	}
-
-	return type;
-}
diff --git a/libpurple/request.c b/libpurple/request.c
--- a/libpurple/request.c
+++ b/libpurple/request.c
@@ -59,15 +59,6 @@ struct _PurpleRequestFields
 	void *ui_data;
 };
 
-struct _PurpleRequestFieldGroup
-{
-	PurpleRequestFields *fields_list;
-
-	char *title;
-
-	GList *fields;
-};
-
 struct _PurpleRequestCommonParameters {
 	PurpleAccount *account;
 	PurpleConversation *conv;
@@ -395,6 +386,54 @@ purple_request_fields_destroy(PurpleRequ
 }
 
 void
+_purple_request_field_list_set_field_required(PurpleRequestFields *fields,
+                                              PurpleRequestField *field,
+                                              gboolean required)
+{
+	g_return_if_fail(fields != NULL);
+
+	if(required) {
+		fields->required_fields = g_list_append(fields->required_fields, field);
+	} else {
+		fields->required_fields = g_list_remove(fields->required_fields, field);
+	}
+}
+
+void
+_purple_request_field_list_set_field_validator(PurpleRequestFields *fields,
+                                               PurpleRequestField *field,
+                                               gboolean validator)
+{
+	g_return_if_fail(fields != NULL);
+
+	fields->validated_fields = g_list_remove(fields->validated_fields, field);
+	if(validator) {
+		fields->validated_fields = g_list_append(fields->validated_fields,
+		                                         field);
+	}
+}
+
+void
+_purple_request_field_list_add_field(PurpleRequestFields *fields,
+                                     PurpleRequestField *field)
+{
+	g_return_if_fail(fields != NULL);
+
+	g_hash_table_insert(fields->fields,
+	                    g_strdup(purple_request_field_get_id(field)), field);
+
+	if(purple_request_field_is_required(field)) {
+		fields->required_fields = g_list_append(fields->required_fields,
+		                                        field);
+	}
+
+	if(purple_request_field_is_validatable(field)) {
+		fields->validated_fields = g_list_append(fields->validated_fields,
+		                                         field);
+	}
+}
+
+void
 purple_request_fields_add_group(PurpleRequestFields *fields,
 							  PurpleRequestFieldGroup *group)
 {
@@ -406,7 +445,7 @@ purple_request_fields_add_group(PurpleRe
 
 	fields->groups = g_list_append(fields->groups, group);
 
-	group->fields_list = fields;
+	_purple_request_field_group_set_field_list(group, fields);
 
 	for (l = purple_request_field_group_get_fields(group);
 		 l != NULL;
@@ -615,114 +654,6 @@ void purple_request_fields_set_ui_data(P
 	fields->ui_data = ui_data;
 }
 
-PurpleRequestFieldGroup *
-purple_request_field_group_new(const char *title)
-{
-	PurpleRequestFieldGroup *group;
-
-	group = g_new0(PurpleRequestFieldGroup, 1);
-
-	group->title = g_strdup(title);
-
-	return group;
-}
-
-void
-purple_request_field_group_destroy(PurpleRequestFieldGroup *group)
-{
-	g_return_if_fail(group != NULL);
-
-	g_free(group->title);
-
-	g_list_free_full(group->fields,
-	                 (GDestroyNotify)purple_request_field_destroy);
-
-	g_free(group);
-}
-
-void
-_purple_request_field_group_set_field_required(PurpleRequestFieldGroup *group,
-                                               PurpleRequestField *field,
-                                               gboolean required)
-{
-		if(required) {
-			group->fields_list->required_fields =
-				g_list_append(group->fields_list->required_fields,
-							  field);
-		} else {
-			group->fields_list->required_fields =
-				g_list_remove(group->fields_list->required_fields,
-							  field);
-		}
-}
-
-void
-_purple_request_field_group_set_field_validator(PurpleRequestFieldGroup *group,
-                                                PurpleRequestField *field,
-                                                gboolean validator)
-{
-		PurpleRequestFields *flist = group->fields_list;
-		flist->validated_fields = g_list_remove(flist->validated_fields, field);
-		if(validator) {
-			flist->validated_fields = g_list_append(flist->validated_fields,
-			                                        field);
-		}
-}
-
-void
-purple_request_field_group_add_field(PurpleRequestFieldGroup *group,
-								   PurpleRequestField *field)
-{
-	g_return_if_fail(group != NULL);
-	g_return_if_fail(field != NULL);
-
-	group->fields = g_list_append(group->fields, field);
-
-	if (group->fields_list != NULL)
-	{
-		g_hash_table_insert(group->fields_list->fields,
-							g_strdup(purple_request_field_get_id(field)), field);
-
-		if (purple_request_field_is_required(field))
-		{
-			group->fields_list->required_fields =
-				g_list_append(group->fields_list->required_fields, field);
-		}
-
-		if (purple_request_field_is_validatable(field))
-		{
-			group->fields_list->validated_fields =
-				g_list_append(group->fields_list->validated_fields, field);
-		}
-	}
-
-	_purple_request_field_set_group(field, group);
-}
-
-const char *
-purple_request_field_group_get_title(const PurpleRequestFieldGroup *group)
-{
-	g_return_val_if_fail(group != NULL, NULL);
-
-	return group->title;
-}
-
-GList *
-purple_request_field_group_get_fields(const PurpleRequestFieldGroup *group)
-{
-	g_return_val_if_fail(group != NULL, NULL);
-
-	return group->fields;
-}
-
-PurpleRequestFields *
-purple_request_field_group_get_fields_list(const PurpleRequestFieldGroup *group)
-{
-	g_return_val_if_fail(group != NULL, NULL);
-
-	return group->fields_list;
-}
-
 /* -- */
 
 static gchar *
@@ -1006,7 +937,10 @@ purple_request_fields_strip_html(PurpleR
 		PurpleRequestFieldGroup *group = itg->data;
 		GList *itf;
 
-		for (itf = group->fields; itf != NULL; itf = g_list_next(itf)) {
+		for (itf = purple_request_field_group_get_fields(group);
+		     itf != NULL;
+		     itf = g_list_next(itf))
+		{
 			PurpleRequestField *field = itf->data;
 			const char *old_label;
 			gchar *new_label;
diff --git a/po/POTFILES.in b/po/POTFILES.in
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -203,6 +203,7 @@ libpurple/purpleprotocolroomlist.c
 libpurple/purpleprotocolserver.c
 libpurple/purpleprotocolwhiteboard.c
 libpurple/purplerequestfield.c
+libpurple/purplerequestgroup.c
 libpurple/purplesqlitehistoryadapter.c
 libpurple/purpleui.c
 libpurple/purplewhiteboard.c
