mark PurpleImageClass as private
[pidgin-git.git] / libpurple / request.c
blobd62170ff0abce683824f58ad33b710a63ddd8224
1 /* purple
3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
22 #include "internal.h"
24 #include "glibcompat.h"
25 #include "notify.h"
26 #include "request.h"
27 #include "debug.h"
29 static PurpleRequestUiOps *request_ui_ops = NULL;
30 static GList *handles = NULL;
32 typedef struct
34 GDestroyNotify cb;
35 gpointer data;
36 } PurpleRequestCloseNotified;
38 typedef struct
40 PurpleRequestType type;
41 void *handle;
42 void *ui_handle;
43 GSList *notify_on_close;
44 } PurpleRequestInfo;
46 struct _PurpleRequestField
48 PurpleRequestFieldType type;
49 PurpleRequestFieldGroup *group;
51 char *id;
52 char *label;
53 char *type_hint;
55 gboolean visible;
56 gboolean required;
57 gboolean sensitive;
58 PurpleRequestFieldSensitivityCb sensitivity_cb;
60 union
62 struct
64 gboolean multiline;
65 gboolean masked;
66 char *default_value;
67 char *value;
69 } string;
71 struct
73 int default_value;
74 int value;
75 int lower_bound;
76 int upper_bound;
77 } integer;
79 struct
81 gboolean default_value;
82 gboolean value;
84 } boolean;
86 struct
88 gpointer default_value;
89 gpointer value;
91 GList *elements;
92 GDestroyNotify data_destroy;
93 } choice;
95 struct
97 GList *items;
98 GList *icons;
99 GHashTable *item_data;
100 GList *selected;
101 GHashTable *selected_table;
103 gboolean multiple_selection;
105 } list;
107 struct
109 PurpleAccount *default_account;
110 PurpleAccount *account;
111 gboolean show_all;
113 PurpleFilterAccountFunc filter_func;
115 } account;
117 struct
119 unsigned int scale_x;
120 unsigned int scale_y;
121 const char *buffer;
122 gsize size;
123 } image;
125 struct
127 PurpleRequestDatasheet *sheet;
128 } datasheet;
129 } u;
131 void *ui_data;
132 char *tooltip;
134 PurpleRequestFieldValidator validator;
135 void *validator_data;
138 struct _PurpleRequestFields
140 GList *groups;
142 GHashTable *fields;
144 gchar **tab_names;
146 GList *required_fields;
148 GList *validated_fields;
150 GList *autosensitive_fields;
152 void *ui_data;
155 struct _PurpleRequestFieldGroup
157 PurpleRequestFields *fields_list;
159 char *title;
160 gint tab_no;
162 GList *fields;
165 struct _PurpleRequestCommonParameters
167 int ref_count;
169 PurpleAccount *account;
170 PurpleConversation *conv;
172 PurpleRequestIconType icon_type;
173 gconstpointer icon_data;
174 gsize icon_size;
176 gboolean html;
178 gboolean compact;
180 PurpleRequestHelpCb help_cb;
181 gpointer help_data;
183 GSList *extra_actions;
185 gpointer parent_from;
188 static void
189 purple_request_fields_check_others_sensitivity(PurpleRequestField *field);
191 PurpleRequestCommonParameters *
192 purple_request_cpar_new(void)
194 return g_new0(PurpleRequestCommonParameters, 1);
197 PurpleRequestCommonParameters *
198 purple_request_cpar_from_connection(PurpleConnection *gc)
200 if (gc == NULL)
201 return purple_request_cpar_new();
202 return purple_request_cpar_from_account(
203 purple_connection_get_account(gc));
206 PurpleRequestCommonParameters *
207 purple_request_cpar_from_account(PurpleAccount *account)
209 PurpleRequestCommonParameters *cpar;
211 cpar = purple_request_cpar_new();
212 purple_request_cpar_set_account(cpar, account);
214 return cpar;
217 PurpleRequestCommonParameters *
218 purple_request_cpar_from_conversation(PurpleConversation *conv)
220 PurpleRequestCommonParameters *cpar;
221 PurpleAccount *account = NULL;
223 if (conv != NULL) {
224 account = purple_connection_get_account(
225 purple_conversation_get_connection(conv));
228 cpar = purple_request_cpar_new();
229 purple_request_cpar_set_account(cpar, account);
230 purple_request_cpar_set_conversation(cpar, conv);
232 return cpar;
235 void
236 purple_request_cpar_ref(PurpleRequestCommonParameters *cpar)
238 g_return_if_fail(cpar != NULL);
240 cpar->ref_count++;
243 PurpleRequestCommonParameters *
244 purple_request_cpar_unref(PurpleRequestCommonParameters *cpar)
246 if (cpar == NULL)
247 return NULL;
249 if (--cpar->ref_count > 0)
250 return cpar;
252 purple_request_cpar_set_extra_actions(cpar, NULL);
253 g_free(cpar);
254 return NULL;
257 void
258 purple_request_cpar_set_account(PurpleRequestCommonParameters *cpar,
259 PurpleAccount *account)
261 g_return_if_fail(cpar != NULL);
263 cpar->account = account;
266 PurpleAccount *
267 purple_request_cpar_get_account(PurpleRequestCommonParameters *cpar)
269 if (cpar == NULL)
270 return NULL;
272 return cpar->account;
275 void
276 purple_request_cpar_set_conversation(PurpleRequestCommonParameters *cpar,
277 PurpleConversation *conv)
279 g_return_if_fail(cpar != NULL);
281 cpar->conv = conv;
284 PurpleConversation *
285 purple_request_cpar_get_conversation(PurpleRequestCommonParameters *cpar)
287 if (cpar == NULL)
288 return NULL;
290 return cpar->conv;
293 void
294 purple_request_cpar_set_icon(PurpleRequestCommonParameters *cpar,
295 PurpleRequestIconType icon_type)
297 g_return_if_fail(cpar != NULL);
299 cpar->icon_type = icon_type;
302 PurpleRequestIconType
303 purple_request_cpar_get_icon(PurpleRequestCommonParameters *cpar)
305 if (cpar == NULL)
306 return PURPLE_REQUEST_ICON_DEFAULT;
308 return cpar->icon_type;
311 void
312 purple_request_cpar_set_custom_icon(PurpleRequestCommonParameters *cpar,
313 gconstpointer icon_data, gsize icon_size)
315 g_return_if_fail(cpar != NULL);
316 g_return_if_fail((icon_data == NULL) == (icon_size == 0));
318 cpar->icon_data = icon_data;
319 cpar->icon_size = icon_size;
322 gconstpointer
323 purple_request_cpar_get_custom_icon(PurpleRequestCommonParameters *cpar,
324 gsize *icon_size)
326 if (cpar == NULL) {
327 if (icon_size != NULL)
328 *icon_size = 0;
329 return NULL;
332 if (icon_size != NULL)
333 *icon_size = cpar->icon_size;
334 return cpar->icon_data;
337 void
338 purple_request_cpar_set_html(PurpleRequestCommonParameters *cpar,
339 gboolean enabled)
341 g_return_if_fail(cpar != NULL);
343 cpar->html = enabled;
346 gboolean
347 purple_request_cpar_is_html(PurpleRequestCommonParameters *cpar)
349 if (cpar == NULL)
350 return FALSE;
352 return cpar->html;
355 void
356 purple_request_cpar_set_compact(PurpleRequestCommonParameters *cpar,
357 gboolean compact)
359 g_return_if_fail(cpar != NULL);
361 cpar->compact = compact;
364 gboolean
365 purple_request_cpar_is_compact(PurpleRequestCommonParameters *cpar)
367 if (cpar == NULL)
368 return FALSE;
370 return cpar->compact;
373 void
374 purple_request_cpar_set_help_cb(PurpleRequestCommonParameters *cpar,
375 PurpleRequestHelpCb cb, gpointer user_data)
377 g_return_if_fail(cpar != NULL);
379 cpar->help_cb = cb;
380 cpar->help_data = cb ? user_data : NULL;
383 PurpleRequestHelpCb
384 purple_request_cpar_get_help_cb(PurpleRequestCommonParameters *cpar,
385 gpointer *user_data)
387 if (cpar == NULL)
388 return NULL;
390 if (user_data != NULL)
391 *user_data = cpar->help_data;
392 return cpar->help_cb;
395 void
396 purple_request_cpar_set_extra_actions(PurpleRequestCommonParameters *cpar, ...)
398 va_list args;
399 GSList *extra = NULL, *it;
401 it = cpar->extra_actions;
402 while (it != NULL) {
403 gchar *label = it->data;
405 g_free(label);
406 it = g_slist_next(it);
407 if (it == NULL)
408 break;
409 it = g_slist_next(it);
412 va_start(args, cpar);
414 while (TRUE) {
415 const gchar *label;
416 PurpleRequestFieldsCb cb;
418 label = va_arg(args, const gchar*);
419 if (label == NULL)
420 break;
421 cb = va_arg(args, PurpleRequestFieldsCb);
423 extra = g_slist_append(extra, g_strdup(label));
424 extra = g_slist_append(extra, cb);
427 va_end(args);
429 cpar->extra_actions = extra;
432 GSList *
433 purple_request_cpar_get_extra_actions(PurpleRequestCommonParameters *cpar)
435 if (cpar == NULL)
436 return NULL;
438 return cpar->extra_actions;
441 void
442 purple_request_cpar_set_parent_from(PurpleRequestCommonParameters *cpar,
443 gpointer ui_handle)
445 g_return_if_fail(cpar != NULL);
447 cpar->parent_from = ui_handle;
450 gpointer
451 purple_request_cpar_get_parent_from(PurpleRequestCommonParameters *cpar)
453 if (cpar == NULL)
454 return NULL;
456 return cpar->parent_from;
459 static PurpleRequestInfo *
460 purple_request_info_from_ui_handle(void *ui_handle)
462 GList *it;
464 g_return_val_if_fail(ui_handle != NULL, NULL);
466 for (it = handles; it != NULL; it = g_list_next(it)) {
467 PurpleRequestInfo *info = it->data;
469 if (info->ui_handle == ui_handle)
470 return info;
473 return NULL;
476 PurpleRequestFields *
477 purple_request_fields_new(void)
479 PurpleRequestFields *fields;
481 fields = g_new0(PurpleRequestFields, 1);
483 fields->fields = g_hash_table_new_full(g_str_hash, g_str_equal,
484 g_free, NULL);
486 return fields;
489 void
490 purple_request_fields_destroy(PurpleRequestFields *fields)
492 g_return_if_fail(fields != NULL);
494 g_strfreev(fields->tab_names);
495 g_list_foreach(fields->groups, (GFunc)purple_request_field_group_destroy, NULL);
496 g_list_free(fields->groups);
497 g_list_free(fields->required_fields);
498 g_list_free(fields->validated_fields);
499 g_list_free(fields->autosensitive_fields);
500 g_hash_table_destroy(fields->fields);
501 g_free(fields);
504 void
505 purple_request_fields_add_group(PurpleRequestFields *fields,
506 PurpleRequestFieldGroup *group)
508 GList *l;
509 PurpleRequestField *field;
511 g_return_if_fail(fields != NULL);
512 g_return_if_fail(group != NULL);
514 fields->groups = g_list_append(fields->groups, group);
516 group->fields_list = fields;
518 for (l = purple_request_field_group_get_fields(group);
519 l != NULL;
520 l = l->next) {
522 field = l->data;
524 g_hash_table_insert(fields->fields,
525 g_strdup(purple_request_field_get_id(field)), field);
527 if (purple_request_field_is_required(field)) {
528 fields->required_fields =
529 g_list_append(fields->required_fields, field);
532 if (purple_request_field_is_validatable(field)) {
533 fields->validated_fields =
534 g_list_append(fields->validated_fields, field);
537 if (field->sensitivity_cb != NULL) {
538 fields->autosensitive_fields =
539 g_list_append(fields->autosensitive_fields, field);
544 GList *
545 purple_request_fields_get_groups(const PurpleRequestFields *fields)
547 g_return_val_if_fail(fields != NULL, NULL);
549 return fields->groups;
552 void
553 purple_request_fields_set_tab_names(PurpleRequestFields *fields,
554 const gchar **tab_names)
556 guint i, tab_count;
557 gchar **new_names;
559 g_return_if_fail(fields != NULL);
561 tab_count = (tab_names != NULL) ? g_strv_length((gchar **)tab_names) : 0;
562 new_names = (tab_count > 0) ? g_new0(gchar*, tab_count + 1) : NULL;
563 for (i = 0; i < tab_count; i++)
564 new_names[i] = g_strdup(tab_names[i]);
566 g_strfreev(fields->tab_names);
567 fields->tab_names = new_names;
570 const gchar **
571 purple_request_fields_get_tab_names(const PurpleRequestFields *fields)
573 g_return_val_if_fail(fields != NULL, NULL);
575 return (const gchar **)fields->tab_names;
578 gboolean
579 purple_request_fields_exists(const PurpleRequestFields *fields, const char *id)
581 g_return_val_if_fail(fields != NULL, FALSE);
582 g_return_val_if_fail(id != NULL, FALSE);
584 return (g_hash_table_lookup(fields->fields, id) != NULL);
587 const GList *
588 purple_request_fields_get_required(const PurpleRequestFields *fields)
590 g_return_val_if_fail(fields != NULL, NULL);
592 return fields->required_fields;
595 const GList *
596 purple_request_fields_get_validatable(const PurpleRequestFields *fields)
598 g_return_val_if_fail(fields != NULL, NULL);
600 return fields->validated_fields;
603 const GList *
604 purple_request_fields_get_autosensitive(const PurpleRequestFields *fields)
606 g_return_val_if_fail(fields != NULL, NULL);
608 return fields->autosensitive_fields;
611 gboolean
612 purple_request_fields_is_field_required(const PurpleRequestFields *fields,
613 const char *id)
615 PurpleRequestField *field;
617 g_return_val_if_fail(fields != NULL, FALSE);
618 g_return_val_if_fail(id != NULL, FALSE);
620 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
621 return FALSE;
623 return purple_request_field_is_required(field);
626 gpointer
627 purple_request_field_get_ui_data(const PurpleRequestField *field)
629 g_return_val_if_fail(field != NULL, NULL);
631 return field->ui_data;
634 void
635 purple_request_field_set_ui_data(PurpleRequestField *field,
636 gpointer ui_data)
638 g_return_if_fail(field != NULL);
640 field->ui_data = ui_data;
643 gboolean
644 purple_request_fields_all_required_filled(const PurpleRequestFields *fields)
646 GList *l;
648 g_return_val_if_fail(fields != NULL, FALSE);
650 for (l = fields->required_fields; l != NULL; l = l->next)
652 PurpleRequestField *field = (PurpleRequestField *)l->data;
654 if (!purple_request_field_is_filled(field))
655 return FALSE;
658 return TRUE;
661 gboolean
662 purple_request_fields_all_valid(const PurpleRequestFields *fields)
664 GList *l;
666 g_return_val_if_fail(fields != NULL, FALSE);
668 for (l = fields->validated_fields; l != NULL; l = l->next)
670 PurpleRequestField *field = (PurpleRequestField *)l->data;
672 if (!purple_request_field_is_valid(field, NULL))
673 return FALSE;
676 return TRUE;
679 static void
680 purple_request_fields_check_sensitivity(PurpleRequestFields *fields)
682 GList *it;
684 g_return_if_fail(fields != NULL);
686 for (it = fields->autosensitive_fields; it; it = g_list_next(it)) {
687 PurpleRequestField *field = it->data;
689 if (field->sensitivity_cb == NULL) {
690 g_warn_if_reached();
691 continue;
694 purple_request_field_set_sensitive(field,
695 field->sensitivity_cb(field));
699 static void
700 purple_request_fields_check_others_sensitivity(PurpleRequestField *field)
702 g_return_if_fail(field != NULL);
704 if (field->group == NULL || field->group->fields_list == NULL)
705 return;
707 purple_request_fields_check_sensitivity(field->group->fields_list);
710 PurpleRequestField *
711 purple_request_fields_get_field(const PurpleRequestFields *fields, const char *id)
713 PurpleRequestField *field;
715 g_return_val_if_fail(fields != NULL, NULL);
716 g_return_val_if_fail(id != NULL, NULL);
718 field = g_hash_table_lookup(fields->fields, id);
720 g_return_val_if_fail(field != NULL, NULL);
722 return field;
725 const char *
726 purple_request_fields_get_string(const PurpleRequestFields *fields, const char *id)
728 PurpleRequestField *field;
730 g_return_val_if_fail(fields != NULL, NULL);
731 g_return_val_if_fail(id != NULL, NULL);
733 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
734 return NULL;
736 return purple_request_field_string_get_value(field);
740 purple_request_fields_get_integer(const PurpleRequestFields *fields,
741 const char *id)
743 PurpleRequestField *field;
745 g_return_val_if_fail(fields != NULL, 0);
746 g_return_val_if_fail(id != NULL, 0);
748 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
749 return 0;
751 return purple_request_field_int_get_value(field);
754 gboolean
755 purple_request_fields_get_bool(const PurpleRequestFields *fields, const char *id)
757 PurpleRequestField *field;
759 g_return_val_if_fail(fields != NULL, FALSE);
760 g_return_val_if_fail(id != NULL, FALSE);
762 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
763 return FALSE;
765 return purple_request_field_bool_get_value(field);
768 gpointer
769 purple_request_fields_get_choice(const PurpleRequestFields *fields,
770 const char *id)
772 PurpleRequestField *field;
774 g_return_val_if_fail(fields != NULL, NULL);
775 g_return_val_if_fail(id != NULL, NULL);
777 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
778 return NULL;
780 return purple_request_field_choice_get_value(field);
783 PurpleAccount *
784 purple_request_fields_get_account(const PurpleRequestFields *fields,
785 const char *id)
787 PurpleRequestField *field;
789 g_return_val_if_fail(fields != NULL, NULL);
790 g_return_val_if_fail(id != NULL, NULL);
792 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
793 return NULL;
795 return purple_request_field_account_get_value(field);
798 gpointer purple_request_fields_get_ui_data(const PurpleRequestFields *fields)
800 g_return_val_if_fail(fields != NULL, NULL);
802 return fields->ui_data;
805 void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data)
807 g_return_if_fail(fields != NULL);
809 fields->ui_data = ui_data;
812 PurpleRequestFieldGroup *
813 purple_request_field_group_new(const char *title)
815 PurpleRequestFieldGroup *group;
817 group = g_new0(PurpleRequestFieldGroup, 1);
819 group->title = g_strdup(title);
821 return group;
824 void
825 purple_request_field_group_set_tab(PurpleRequestFieldGroup *group, guint tab_no)
827 g_return_if_fail(group != NULL);
829 group->tab_no = tab_no;
832 guint
833 purple_request_field_group_get_tab(const PurpleRequestFieldGroup *group)
835 return group->tab_no;
838 void
839 purple_request_field_group_destroy(PurpleRequestFieldGroup *group)
841 g_return_if_fail(group != NULL);
843 g_free(group->title);
845 g_list_foreach(group->fields, (GFunc)purple_request_field_destroy, NULL);
846 g_list_free(group->fields);
848 g_free(group);
851 void
852 purple_request_field_group_add_field(PurpleRequestFieldGroup *group,
853 PurpleRequestField *field)
855 g_return_if_fail(group != NULL);
856 g_return_if_fail(field != NULL);
858 group->fields = g_list_append(group->fields, field);
860 if (group->fields_list != NULL)
862 g_hash_table_insert(group->fields_list->fields,
863 g_strdup(purple_request_field_get_id(field)), field);
865 if (purple_request_field_is_required(field))
867 group->fields_list->required_fields =
868 g_list_append(group->fields_list->required_fields, field);
871 if (purple_request_field_is_validatable(field))
873 group->fields_list->validated_fields =
874 g_list_append(group->fields_list->validated_fields, field);
877 if (field->sensitivity_cb != NULL)
879 group->fields_list->autosensitive_fields =
880 g_list_append(group->fields_list->autosensitive_fields, field);
884 field->group = group;
888 const char *
889 purple_request_field_group_get_title(const PurpleRequestFieldGroup *group)
891 g_return_val_if_fail(group != NULL, NULL);
893 return group->title;
896 GList *
897 purple_request_field_group_get_fields(const PurpleRequestFieldGroup *group)
899 g_return_val_if_fail(group != NULL, NULL);
901 return group->fields;
904 PurpleRequestFields *
905 purple_request_field_group_get_fields_list(const PurpleRequestFieldGroup *group)
907 g_return_val_if_fail(group != NULL, NULL);
909 return group->fields_list;
912 PurpleRequestField *
913 purple_request_field_new(const char *id, const char *text,
914 PurpleRequestFieldType type)
916 PurpleRequestField *field;
918 g_return_val_if_fail(id != NULL, NULL);
919 g_return_val_if_fail(type != PURPLE_REQUEST_FIELD_NONE, NULL);
921 field = g_new0(PurpleRequestField, 1);
923 field->id = g_strdup(id);
924 field->type = type;
926 purple_request_field_set_label(field, text);
927 purple_request_field_set_visible(field, TRUE);
928 purple_request_field_set_sensitive(field, TRUE);
930 return field;
933 void
934 purple_request_field_destroy(PurpleRequestField *field)
936 g_return_if_fail(field != NULL);
938 g_free(field->id);
939 g_free(field->label);
940 g_free(field->type_hint);
941 g_free(field->tooltip);
943 if (field->type == PURPLE_REQUEST_FIELD_STRING)
945 g_free(field->u.string.default_value);
946 g_free(field->u.string.value);
948 else if (field->type == PURPLE_REQUEST_FIELD_CHOICE)
950 if (field->u.choice.elements != NULL)
952 GList *it = field->u.choice.elements;
953 while (it != NULL) {
954 g_free(it->data);
955 it = g_list_next(it); /* value */
956 if (it == NULL) {
957 g_warn_if_reached();
958 break;
960 if (it->data && field->u.choice.data_destroy)
961 field->u.choice.data_destroy(it->data);
962 it = g_list_next(it); /* next label */
964 g_list_free(field->u.choice.elements);
967 else if (field->type == PURPLE_REQUEST_FIELD_LIST)
969 if (field->u.list.items != NULL)
971 g_list_foreach(field->u.list.items, (GFunc)g_free, NULL);
972 g_list_free(field->u.list.items);
975 if (field->u.list.selected != NULL)
977 g_list_foreach(field->u.list.selected, (GFunc)g_free, NULL);
978 g_list_free(field->u.list.selected);
981 g_hash_table_destroy(field->u.list.item_data);
982 g_hash_table_destroy(field->u.list.selected_table);
984 else if (field->type == PURPLE_REQUEST_FIELD_DATASHEET)
986 purple_request_datasheet_free(field->u.datasheet.sheet);
989 g_free(field);
992 void
993 purple_request_field_set_label(PurpleRequestField *field, const char *label)
995 g_return_if_fail(field != NULL);
997 g_free(field->label);
998 field->label = g_strdup(label);
1001 void
1002 purple_request_field_set_visible(PurpleRequestField *field, gboolean visible)
1004 g_return_if_fail(field != NULL);
1006 field->visible = visible;
1009 void
1010 purple_request_field_set_type_hint(PurpleRequestField *field,
1011 const char *type_hint)
1013 g_return_if_fail(field != NULL);
1015 g_free(field->type_hint);
1016 field->type_hint = g_strdup(type_hint);
1019 void
1020 purple_request_field_set_tooltip(PurpleRequestField *field, const char *tooltip)
1022 g_return_if_fail(field != NULL);
1024 g_free(field->tooltip);
1025 field->tooltip = g_strdup(tooltip);
1028 void
1029 purple_request_field_set_required(PurpleRequestField *field, gboolean required)
1031 g_return_if_fail(field != NULL);
1033 if (field->required == required)
1034 return;
1036 field->required = required;
1038 if (field->group != NULL)
1040 if (required)
1042 field->group->fields_list->required_fields =
1043 g_list_append(field->group->fields_list->required_fields,
1044 field);
1046 else
1048 field->group->fields_list->required_fields =
1049 g_list_remove(field->group->fields_list->required_fields,
1050 field);
1055 PurpleRequestFieldType
1056 purple_request_field_get_field_type(const PurpleRequestField *field)
1058 g_return_val_if_fail(field != NULL, PURPLE_REQUEST_FIELD_NONE);
1060 return field->type;
1063 PurpleRequestFieldGroup *
1064 purple_request_field_get_group(const PurpleRequestField *field)
1066 g_return_val_if_fail(field != NULL, NULL);
1068 return field->group;
1071 const char *
1072 purple_request_field_get_id(const PurpleRequestField *field)
1074 g_return_val_if_fail(field != NULL, NULL);
1076 return field->id;
1079 const char *
1080 purple_request_field_get_label(const PurpleRequestField *field)
1082 g_return_val_if_fail(field != NULL, NULL);
1084 return field->label;
1087 gboolean
1088 purple_request_field_is_visible(const PurpleRequestField *field)
1090 g_return_val_if_fail(field != NULL, FALSE);
1092 return field->visible;
1095 const char *
1096 purple_request_field_get_field_type_hint(const PurpleRequestField *field)
1098 g_return_val_if_fail(field != NULL, NULL);
1100 return field->type_hint;
1103 const char *
1104 purple_request_field_get_tooltip(const PurpleRequestField *field)
1106 g_return_val_if_fail(field != NULL, NULL);
1108 return field->tooltip;
1111 gboolean
1112 purple_request_field_is_required(const PurpleRequestField *field)
1114 g_return_val_if_fail(field != NULL, FALSE);
1116 return field->required;
1119 gboolean
1120 purple_request_field_is_filled(const PurpleRequestField *field)
1122 g_return_val_if_fail(field != NULL, FALSE);
1124 switch (purple_request_field_get_field_type(field))
1126 case PURPLE_REQUEST_FIELD_STRING:
1127 return (purple_request_field_string_get_value(field) != NULL &&
1128 *(purple_request_field_string_get_value(field)) != '\0');
1129 default:
1130 return TRUE;
1134 void
1135 purple_request_field_set_validator(PurpleRequestField *field,
1136 PurpleRequestFieldValidator validator, void *user_data)
1138 g_return_if_fail(field != NULL);
1140 field->validator = validator;
1141 field->validator_data = validator ? user_data : NULL;
1143 if (field->group != NULL)
1145 PurpleRequestFields *flist = field->group->fields_list;
1146 flist->validated_fields = g_list_remove(flist->validated_fields,
1147 field);
1148 if (validator)
1150 flist->validated_fields = g_list_append(
1151 flist->validated_fields, field);
1156 gboolean
1157 purple_request_field_is_validatable(PurpleRequestField *field)
1159 g_return_val_if_fail(field != NULL, FALSE);
1161 return field->validator != NULL;
1164 gboolean
1165 purple_request_field_is_valid(PurpleRequestField *field, gchar **errmsg)
1167 gboolean valid;
1169 g_return_val_if_fail(field != NULL, FALSE);
1171 if (!field->validator)
1172 return TRUE;
1174 if (!purple_request_field_is_required(field) &&
1175 !purple_request_field_is_filled(field))
1176 return TRUE;
1178 valid = field->validator(field, errmsg, field->validator_data);
1180 if (valid && errmsg)
1181 *errmsg = NULL;
1183 return valid;
1186 void
1187 purple_request_field_set_sensitive(PurpleRequestField *field,
1188 gboolean sensitive)
1190 g_return_if_fail(field != NULL);
1192 field->sensitive = sensitive;
1195 gboolean
1196 purple_request_field_is_sensitive(PurpleRequestField *field)
1198 g_return_val_if_fail(field != NULL, FALSE);
1200 return field->sensitive;
1203 void
1204 purple_request_field_set_sensitivity_cb(PurpleRequestField *field,
1205 PurpleRequestFieldSensitivityCb cb)
1207 PurpleRequestFields *flist;
1209 g_return_if_fail(field != NULL);
1211 field->sensitivity_cb = cb;
1213 if (!field->group || !field->group->fields_list)
1214 return;
1215 flist = field->group->fields_list;
1216 flist->autosensitive_fields = g_list_remove(flist->autosensitive_fields,
1217 field);
1218 if (cb != NULL)
1220 flist->autosensitive_fields = g_list_append(
1221 flist->autosensitive_fields, field);
1225 PurpleRequestField *
1226 purple_request_field_string_new(const char *id, const char *text,
1227 const char *default_value, gboolean multiline)
1229 PurpleRequestField *field;
1231 g_return_val_if_fail(id != NULL, NULL);
1232 g_return_val_if_fail(text != NULL, NULL);
1234 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_STRING);
1236 field->u.string.multiline = multiline;
1238 purple_request_field_string_set_default_value(field, default_value);
1239 purple_request_field_string_set_value(field, default_value);
1241 return field;
1244 void
1245 purple_request_field_string_set_default_value(PurpleRequestField *field,
1246 const char *default_value)
1248 g_return_if_fail(field != NULL);
1249 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
1251 g_free(field->u.string.default_value);
1252 field->u.string.default_value = g_strdup(default_value);
1255 void
1256 purple_request_field_string_set_value(PurpleRequestField *field, const char *value)
1258 g_return_if_fail(field != NULL);
1259 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
1261 g_free(field->u.string.value);
1262 field->u.string.value = g_strdup(value);
1264 purple_request_fields_check_others_sensitivity(field);
1267 void
1268 purple_request_field_string_set_masked(PurpleRequestField *field, gboolean masked)
1270 g_return_if_fail(field != NULL);
1271 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
1273 field->u.string.masked = masked;
1276 const char *
1277 purple_request_field_string_get_default_value(const PurpleRequestField *field)
1279 g_return_val_if_fail(field != NULL, NULL);
1280 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, NULL);
1282 return field->u.string.default_value;
1285 const char *
1286 purple_request_field_string_get_value(const PurpleRequestField *field)
1288 g_return_val_if_fail(field != NULL, NULL);
1289 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, NULL);
1291 return field->u.string.value;
1294 gboolean
1295 purple_request_field_string_is_multiline(const PurpleRequestField *field)
1297 g_return_val_if_fail(field != NULL, FALSE);
1298 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
1300 return field->u.string.multiline;
1303 gboolean
1304 purple_request_field_string_is_masked(const PurpleRequestField *field)
1306 g_return_val_if_fail(field != NULL, FALSE);
1307 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
1309 return field->u.string.masked;
1312 PurpleRequestField *
1313 purple_request_field_int_new(const char *id, const char *text,
1314 int default_value, int lower_bound, int upper_bound)
1316 PurpleRequestField *field;
1318 g_return_val_if_fail(id != NULL, NULL);
1319 g_return_val_if_fail(text != NULL, NULL);
1321 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_INTEGER);
1323 purple_request_field_int_set_lower_bound(field, lower_bound);
1324 purple_request_field_int_set_upper_bound(field, upper_bound);
1325 purple_request_field_int_set_default_value(field, default_value);
1326 purple_request_field_int_set_value(field, default_value);
1328 return field;
1331 void
1332 purple_request_field_int_set_default_value(PurpleRequestField *field,
1333 int default_value)
1335 g_return_if_fail(field != NULL);
1336 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1338 field->u.integer.default_value = default_value;
1341 void
1342 purple_request_field_int_set_lower_bound(PurpleRequestField *field,
1343 int lower_bound)
1345 g_return_if_fail(field != NULL);
1346 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1348 field->u.integer.lower_bound = lower_bound;
1351 void
1352 purple_request_field_int_set_upper_bound(PurpleRequestField *field,
1353 int upper_bound)
1355 g_return_if_fail(field != NULL);
1356 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1358 field->u.integer.upper_bound = upper_bound;
1361 void
1362 purple_request_field_int_set_value(PurpleRequestField *field, int value)
1364 g_return_if_fail(field != NULL);
1365 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1367 if (value < field->u.integer.lower_bound ||
1368 value > field->u.integer.upper_bound) {
1369 purple_debug_error("request", "Int value out of bounds\n");
1370 return;
1373 field->u.integer.value = value;
1375 purple_request_fields_check_others_sensitivity(field);
1379 purple_request_field_int_get_default_value(const PurpleRequestField *field)
1381 g_return_val_if_fail(field != NULL, 0);
1382 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1384 return field->u.integer.default_value;
1388 purple_request_field_int_get_lower_bound(const PurpleRequestField *field)
1390 g_return_val_if_fail(field != NULL, 0);
1391 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1393 return field->u.integer.lower_bound;
1397 purple_request_field_int_get_upper_bound(const PurpleRequestField *field)
1399 g_return_val_if_fail(field != NULL, 0);
1400 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1402 return field->u.integer.upper_bound;
1406 purple_request_field_int_get_value(const PurpleRequestField *field)
1408 g_return_val_if_fail(field != NULL, 0);
1409 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1411 return field->u.integer.value;
1414 PurpleRequestField *
1415 purple_request_field_bool_new(const char *id, const char *text,
1416 gboolean default_value)
1418 PurpleRequestField *field;
1420 g_return_val_if_fail(id != NULL, NULL);
1421 g_return_val_if_fail(text != NULL, NULL);
1423 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_BOOLEAN);
1425 purple_request_field_bool_set_default_value(field, default_value);
1426 purple_request_field_bool_set_value(field, default_value);
1428 return field;
1431 void
1432 purple_request_field_bool_set_default_value(PurpleRequestField *field,
1433 gboolean default_value)
1435 g_return_if_fail(field != NULL);
1436 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN);
1438 field->u.boolean.default_value = default_value;
1441 void
1442 purple_request_field_bool_set_value(PurpleRequestField *field, gboolean value)
1444 g_return_if_fail(field != NULL);
1445 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN);
1447 field->u.boolean.value = value;
1449 purple_request_fields_check_others_sensitivity(field);
1452 gboolean
1453 purple_request_field_bool_get_default_value(const PurpleRequestField *field)
1455 g_return_val_if_fail(field != NULL, FALSE);
1456 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN, FALSE);
1458 return field->u.boolean.default_value;
1461 gboolean
1462 purple_request_field_bool_get_value(const PurpleRequestField *field)
1464 g_return_val_if_fail(field != NULL, FALSE);
1465 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN, FALSE);
1467 return field->u.boolean.value;
1470 PurpleRequestField *
1471 purple_request_field_choice_new(const char *id, const char *text,
1472 gpointer default_value)
1474 PurpleRequestField *field;
1476 g_return_val_if_fail(id != NULL, NULL);
1477 g_return_val_if_fail(text != NULL, NULL);
1479 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_CHOICE);
1481 purple_request_field_choice_set_default_value(field, default_value);
1482 purple_request_field_choice_set_value(field, default_value);
1484 return field;
1487 void
1488 purple_request_field_choice_add(PurpleRequestField *field, const char *label,
1489 gpointer value)
1491 g_return_if_fail(field != NULL);
1492 g_return_if_fail(label != NULL);
1493 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1495 field->u.choice.elements = g_list_append(field->u.choice.elements,
1496 g_strdup(label));
1497 field->u.choice.elements = g_list_append(field->u.choice.elements,
1498 value);
1501 void
1502 purple_request_field_choice_set_default_value(PurpleRequestField *field,
1503 gpointer default_value)
1505 g_return_if_fail(field != NULL);
1506 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1508 field->u.choice.default_value = default_value;
1511 void
1512 purple_request_field_choice_set_value(PurpleRequestField *field, gpointer value)
1514 g_return_if_fail(field != NULL);
1515 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1517 field->u.choice.value = value;
1519 purple_request_fields_check_others_sensitivity(field);
1522 gpointer
1523 purple_request_field_choice_get_default_value(const PurpleRequestField *field)
1525 g_return_val_if_fail(field != NULL, NULL);
1526 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, NULL);
1528 return field->u.choice.default_value;
1531 gpointer
1532 purple_request_field_choice_get_value(const PurpleRequestField *field)
1534 g_return_val_if_fail(field != NULL, NULL);
1535 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, NULL);
1537 return field->u.choice.value;
1540 GList *
1541 purple_request_field_choice_get_elements(const PurpleRequestField *field)
1543 g_return_val_if_fail(field != NULL, NULL);
1544 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, NULL);
1546 return field->u.choice.elements;
1549 void
1550 purple_request_field_choice_set_data_destructor(PurpleRequestField *field,
1551 GDestroyNotify destroy)
1553 g_return_if_fail(field != NULL);
1554 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1556 field->u.choice.data_destroy = destroy;
1559 PurpleRequestField *
1560 purple_request_field_list_new(const char *id, const char *text)
1562 PurpleRequestField *field;
1564 g_return_val_if_fail(id != NULL, NULL);
1566 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_LIST);
1568 field->u.list.item_data = g_hash_table_new_full(g_str_hash, g_str_equal,
1569 g_free, NULL);
1571 field->u.list.selected_table =
1572 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1574 return field;
1577 void
1578 purple_request_field_list_set_multi_select(PurpleRequestField *field,
1579 gboolean multi_select)
1581 g_return_if_fail(field != NULL);
1582 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1584 field->u.list.multiple_selection = multi_select;
1587 gboolean
1588 purple_request_field_list_get_multi_select(const PurpleRequestField *field)
1590 g_return_val_if_fail(field != NULL, FALSE);
1591 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, FALSE);
1593 return field->u.list.multiple_selection;
1596 void *
1597 purple_request_field_list_get_data(const PurpleRequestField *field,
1598 const char *text)
1600 g_return_val_if_fail(field != NULL, NULL);
1601 g_return_val_if_fail(text != NULL, NULL);
1602 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1604 return g_hash_table_lookup(field->u.list.item_data, text);
1607 void
1608 purple_request_field_list_add_icon(PurpleRequestField *field, const char *item, const char* icon_path,
1609 void *data)
1611 g_return_if_fail(field != NULL);
1612 g_return_if_fail(item != NULL);
1613 g_return_if_fail(data != NULL);
1614 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1616 if (icon_path)
1618 if (field->u.list.icons == NULL)
1620 GList *l;
1621 for (l = field->u.list.items ; l != NULL ; l = l->next)
1623 /* Order doesn't matter, because we're just
1624 * filing in blank items. So, we use
1625 * g_list_prepend() because it's faster. */
1626 field->u.list.icons = g_list_prepend(field->u.list.icons, NULL);
1629 field->u.list.icons = g_list_append(field->u.list.icons, g_strdup(icon_path));
1631 else if (field->u.list.icons)
1633 /* Keep this even with the items list. */
1634 field->u.list.icons = g_list_append(field->u.list.icons, NULL);
1637 field->u.list.items = g_list_append(field->u.list.items, g_strdup(item));
1638 g_hash_table_insert(field->u.list.item_data, g_strdup(item), data);
1641 void
1642 purple_request_field_list_add_selected(PurpleRequestField *field, const char *item)
1644 g_return_if_fail(field != NULL);
1645 g_return_if_fail(item != NULL);
1646 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1648 if (!purple_request_field_list_get_multi_select(field) &&
1649 field->u.list.selected != NULL)
1651 purple_debug_warning("request",
1652 "More than one item added to non-multi-select "
1653 "field %s\n",
1654 purple_request_field_get_id(field));
1655 return;
1658 field->u.list.selected = g_list_append(field->u.list.selected,
1659 g_strdup(item));
1661 g_hash_table_insert(field->u.list.selected_table, g_strdup(item), NULL);
1664 void
1665 purple_request_field_list_clear_selected(PurpleRequestField *field)
1667 g_return_if_fail(field != NULL);
1668 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1670 if (field->u.list.selected != NULL)
1672 g_list_foreach(field->u.list.selected, (GFunc)g_free, NULL);
1673 g_list_free(field->u.list.selected);
1674 field->u.list.selected = NULL;
1677 g_hash_table_destroy(field->u.list.selected_table);
1679 field->u.list.selected_table =
1680 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1683 void
1684 purple_request_field_list_set_selected(PurpleRequestField *field, GList *items)
1686 GList *l;
1688 g_return_if_fail(field != NULL);
1689 g_return_if_fail(items != NULL);
1690 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1692 purple_request_field_list_clear_selected(field);
1694 if (!purple_request_field_list_get_multi_select(field) &&
1695 items && items->next)
1697 purple_debug_warning("request",
1698 "More than one item added to non-multi-select "
1699 "field %s\n",
1700 purple_request_field_get_id(field));
1701 return;
1704 for (l = items; l != NULL; l = l->next)
1706 field->u.list.selected = g_list_append(field->u.list.selected,
1707 g_strdup(l->data));
1708 g_hash_table_insert(field->u.list.selected_table,
1709 g_strdup((char *)l->data), NULL);
1713 gboolean
1714 purple_request_field_list_is_selected(const PurpleRequestField *field,
1715 const char *item)
1717 g_return_val_if_fail(field != NULL, FALSE);
1718 g_return_val_if_fail(item != NULL, FALSE);
1719 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, FALSE);
1721 return g_hash_table_lookup_extended(field->u.list.selected_table,
1722 item, NULL, NULL);
1725 GList *
1726 purple_request_field_list_get_selected(const PurpleRequestField *field)
1728 g_return_val_if_fail(field != NULL, NULL);
1729 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1731 return field->u.list.selected;
1734 GList *
1735 purple_request_field_list_get_items(const PurpleRequestField *field)
1737 g_return_val_if_fail(field != NULL, NULL);
1738 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1740 return field->u.list.items;
1743 GList *
1744 purple_request_field_list_get_icons(const PurpleRequestField *field)
1746 g_return_val_if_fail(field != NULL, NULL);
1747 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1749 return field->u.list.icons;
1752 PurpleRequestField *
1753 purple_request_field_label_new(const char *id, const char *text)
1755 PurpleRequestField *field;
1757 g_return_val_if_fail(id != NULL, NULL);
1758 g_return_val_if_fail(text != NULL, NULL);
1760 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_LABEL);
1762 return field;
1765 PurpleRequestField *
1766 purple_request_field_image_new(const char *id, const char *text, const char *buf, gsize size)
1768 PurpleRequestField *field;
1770 g_return_val_if_fail(id != NULL, NULL);
1771 g_return_val_if_fail(text != NULL, NULL);
1772 g_return_val_if_fail(buf != NULL, NULL);
1773 g_return_val_if_fail(size > 0, NULL);
1775 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_IMAGE);
1777 field->u.image.buffer = g_memdup(buf, size);
1778 field->u.image.size = size;
1779 field->u.image.scale_x = 1;
1780 field->u.image.scale_y = 1;
1782 return field;
1785 void
1786 purple_request_field_image_set_scale(PurpleRequestField *field, unsigned int x, unsigned int y)
1788 g_return_if_fail(field != NULL);
1789 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE);
1791 field->u.image.scale_x = x;
1792 field->u.image.scale_y = y;
1795 const char *
1796 purple_request_field_image_get_buffer(PurpleRequestField *field)
1798 g_return_val_if_fail(field != NULL, NULL);
1799 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, NULL);
1801 return field->u.image.buffer;
1804 gsize
1805 purple_request_field_image_get_size(PurpleRequestField *field)
1807 g_return_val_if_fail(field != NULL, 0);
1808 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1810 return field->u.image.size;
1813 unsigned int
1814 purple_request_field_image_get_scale_x(PurpleRequestField *field)
1816 g_return_val_if_fail(field != NULL, 0);
1817 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1819 return field->u.image.scale_x;
1822 unsigned int
1823 purple_request_field_image_get_scale_y(PurpleRequestField *field)
1825 g_return_val_if_fail(field != NULL, 0);
1826 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1828 return field->u.image.scale_y;
1831 PurpleRequestField *
1832 purple_request_field_account_new(const char *id, const char *text,
1833 PurpleAccount *account)
1835 PurpleRequestField *field;
1837 g_return_val_if_fail(id != NULL, NULL);
1838 g_return_val_if_fail(text != NULL, NULL);
1840 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_ACCOUNT);
1842 if (account == NULL && purple_connections_get_all() != NULL)
1844 account = purple_connection_get_account(
1845 (PurpleConnection *)purple_connections_get_all()->data);
1848 purple_request_field_account_set_default_value(field, account);
1849 purple_request_field_account_set_value(field, account);
1851 return field;
1854 void
1855 purple_request_field_account_set_default_value(PurpleRequestField *field,
1856 PurpleAccount *default_value)
1858 g_return_if_fail(field != NULL);
1859 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1861 field->u.account.default_account = default_value;
1864 void
1865 purple_request_field_account_set_value(PurpleRequestField *field,
1866 PurpleAccount *value)
1868 g_return_if_fail(field != NULL);
1869 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1871 field->u.account.account = value;
1873 purple_request_fields_check_others_sensitivity(field);
1876 void
1877 purple_request_field_account_set_show_all(PurpleRequestField *field,
1878 gboolean show_all)
1880 g_return_if_fail(field != NULL);
1881 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1883 if (field->u.account.show_all == show_all)
1884 return;
1886 field->u.account.show_all = show_all;
1888 if (!show_all)
1890 if (purple_account_is_connected(field->u.account.default_account))
1892 purple_request_field_account_set_default_value(field,
1893 (PurpleAccount *)purple_connections_get_all()->data);
1896 if (purple_account_is_connected(field->u.account.account))
1898 purple_request_field_account_set_value(field,
1899 (PurpleAccount *)purple_connections_get_all()->data);
1904 void
1905 purple_request_field_account_set_filter(PurpleRequestField *field,
1906 PurpleFilterAccountFunc filter_func)
1908 g_return_if_fail(field != NULL);
1909 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1911 field->u.account.filter_func = filter_func;
1914 PurpleAccount *
1915 purple_request_field_account_get_default_value(const PurpleRequestField *field)
1917 g_return_val_if_fail(field != NULL, NULL);
1918 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, NULL);
1920 return field->u.account.default_account;
1923 PurpleAccount *
1924 purple_request_field_account_get_value(const PurpleRequestField *field)
1926 g_return_val_if_fail(field != NULL, NULL);
1927 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, NULL);
1929 return field->u.account.account;
1932 gboolean
1933 purple_request_field_account_get_show_all(const PurpleRequestField *field)
1935 g_return_val_if_fail(field != NULL, FALSE);
1936 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, FALSE);
1938 return field->u.account.show_all;
1941 PurpleFilterAccountFunc
1942 purple_request_field_account_get_filter(const PurpleRequestField *field)
1944 g_return_val_if_fail(field != NULL, FALSE);
1945 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, FALSE);
1947 return field->u.account.filter_func;
1950 PurpleRequestField *
1951 purple_request_field_datasheet_new(const char *id,
1952 const gchar *text, PurpleRequestDatasheet *sheet)
1954 PurpleRequestField *field;
1956 g_return_val_if_fail(id != NULL, NULL);
1957 g_return_val_if_fail(sheet != NULL, NULL);
1959 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_DATASHEET);
1961 field->u.datasheet.sheet = sheet;
1963 return field;
1966 PurpleRequestDatasheet *
1967 purple_request_field_datasheet_get_sheet(PurpleRequestField *field)
1969 g_return_val_if_fail(field != NULL, NULL);
1970 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_DATASHEET, NULL);
1972 return field->u.datasheet.sheet;
1975 /* -- */
1977 gboolean
1978 purple_request_field_email_validator(PurpleRequestField *field, gchar **errmsg,
1979 void *user_data)
1981 const char *value;
1983 g_return_val_if_fail(field != NULL, FALSE);
1984 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
1986 value = purple_request_field_string_get_value(field);
1988 if (value != NULL && purple_email_is_valid(value))
1989 return TRUE;
1991 if (errmsg)
1992 *errmsg = g_strdup(_("Invalid email address"));
1993 return FALSE;
1996 gboolean
1997 purple_request_field_alphanumeric_validator(PurpleRequestField *field,
1998 gchar **errmsg, void *allowed_characters)
2000 const char *value;
2001 gchar invalid_char = '\0';
2003 g_return_val_if_fail(field != NULL, FALSE);
2004 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
2006 value = purple_request_field_string_get_value(field);
2008 g_return_val_if_fail(value != NULL, FALSE);
2010 if (allowed_characters)
2012 gchar *value_r = g_strdup(value);
2013 g_strcanon(value_r, allowed_characters, '\0');
2014 invalid_char = value[strlen(value_r)];
2015 g_free(value_r);
2017 else
2019 while (value)
2021 if (!g_ascii_isalnum(*value))
2023 invalid_char = *value;
2024 break;
2026 value++;
2029 if (!invalid_char)
2030 return TRUE;
2032 if (errmsg)
2033 *errmsg = g_strdup_printf(_("Invalid character '%c'"),
2034 invalid_char);
2035 return FALSE;
2038 /* -- */
2040 static gchar *
2041 purple_request_strip_html_custom(const gchar *html)
2043 gchar *tmp, *ret;
2045 tmp = purple_strreplace(html, "\n", "<br>");
2046 ret = purple_markup_strip_html(tmp);
2047 g_free(tmp);
2049 return ret;
2052 static gchar **
2053 purple_request_strip_html(PurpleRequestCommonParameters *cpar,
2054 const char **primary, const char **secondary)
2056 PurpleRequestUiOps *ops = purple_request_get_ui_ops();
2057 gchar **ret;
2059 if (!purple_request_cpar_is_html(cpar))
2060 return NULL;
2061 if (ops->features & PURPLE_REQUEST_FEATURE_HTML)
2062 return NULL;
2064 ret = g_new0(gchar*, 3);
2065 *primary = ret[0] = purple_request_strip_html_custom(*primary);
2066 *secondary = ret[1] = purple_request_strip_html_custom(*secondary);
2068 return ret;
2071 void *
2072 purple_request_input(void *handle, const char *title, const char *primary,
2073 const char *secondary, const char *default_value,
2074 gboolean multiline, gboolean masked, gchar *hint,
2075 const char *ok_text, GCallback ok_cb,
2076 const char *cancel_text, GCallback cancel_cb,
2077 PurpleRequestCommonParameters *cpar,
2078 void *user_data)
2080 PurpleRequestUiOps *ops;
2082 if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL)) {
2083 purple_request_cpar_unref(cpar);
2084 g_warn_if_fail(ok_text != NULL);
2085 g_warn_if_fail(ok_cb != NULL);
2086 g_return_val_if_reached(NULL);
2089 ops = purple_request_get_ui_ops();
2091 if (ops != NULL && ops->request_input != NULL) {
2092 PurpleRequestInfo *info;
2093 gchar **tmp;
2095 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2097 info = g_new0(PurpleRequestInfo, 1);
2098 info->type = PURPLE_REQUEST_INPUT;
2099 info->handle = handle;
2100 info->ui_handle = ops->request_input(title, primary, secondary,
2101 default_value, multiline, masked, hint, ok_text, ok_cb,
2102 cancel_text, cancel_cb, cpar, user_data);
2104 handles = g_list_append(handles, info);
2106 g_strfreev(tmp);
2107 purple_request_cpar_unref(cpar);
2108 return info->ui_handle;
2111 purple_request_cpar_unref(cpar);
2112 return NULL;
2115 void *
2116 purple_request_choice(void *handle, const char *title, const char *primary,
2117 const char *secondary, gpointer default_value, const char *ok_text,
2118 GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
2119 PurpleRequestCommonParameters *cpar, void *user_data, ...)
2121 void *ui_handle;
2122 va_list args;
2124 if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL)) {
2125 purple_request_cpar_unref(cpar);
2126 g_warn_if_fail(ok_text != NULL);
2127 g_warn_if_fail(ok_cb != NULL);
2128 g_return_val_if_reached(NULL);
2131 va_start(args, user_data);
2132 ui_handle = purple_request_choice_varg(handle, title, primary, secondary,
2133 default_value, ok_text, ok_cb,
2134 cancel_text, cancel_cb,
2135 cpar, user_data, args);
2136 va_end(args);
2138 return ui_handle;
2141 void *
2142 purple_request_choice_varg(void *handle, const char *title, const char *primary,
2143 const char *secondary, gpointer default_value, const char *ok_text,
2144 GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
2145 PurpleRequestCommonParameters *cpar, void *user_data, va_list choices)
2147 PurpleRequestUiOps *ops;
2149 if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL ||
2150 cancel_text == NULL))
2152 purple_request_cpar_unref(cpar);
2153 g_warn_if_fail(ok_text != NULL);
2154 g_warn_if_fail(ok_cb != NULL);
2155 g_warn_if_fail(cancel_text != NULL);
2156 g_return_val_if_reached(NULL);
2159 ops = purple_request_get_ui_ops();
2161 if (ops != NULL && ops->request_choice != NULL) {
2162 PurpleRequestInfo *info;
2163 gchar **tmp;
2165 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2167 info = g_new0(PurpleRequestInfo, 1);
2168 info->type = PURPLE_REQUEST_CHOICE;
2169 info->handle = handle;
2170 info->ui_handle = ops->request_choice(title, primary, secondary,
2171 default_value, ok_text, ok_cb, cancel_text, cancel_cb,
2172 cpar, user_data, choices);
2174 handles = g_list_append(handles, info);
2176 g_strfreev(tmp);
2177 purple_request_cpar_unref(cpar);
2178 return info->ui_handle;
2181 purple_request_cpar_unref(cpar);
2182 return NULL;
2185 void *
2186 purple_request_action(void *handle, const char *title, const char *primary,
2187 const char *secondary, int default_action,
2188 PurpleRequestCommonParameters *cpar, void *user_data,
2189 size_t action_count, ...)
2191 void *ui_handle;
2192 va_list args;
2194 va_start(args, action_count);
2195 ui_handle = purple_request_action_varg(handle, title, primary,
2196 secondary, default_action, cpar, user_data, action_count, args);
2197 va_end(args);
2199 return ui_handle;
2202 void *
2203 purple_request_action_varg(void *handle, const char *title, const char *primary,
2204 const char *secondary, int default_action,
2205 PurpleRequestCommonParameters *cpar, void *user_data,
2206 size_t action_count, va_list actions)
2208 PurpleRequestUiOps *ops;
2210 ops = purple_request_get_ui_ops();
2212 if (ops != NULL && ops->request_action != NULL) {
2213 PurpleRequestInfo *info;
2214 gchar **tmp;
2216 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2218 info = g_new0(PurpleRequestInfo, 1);
2219 info->type = PURPLE_REQUEST_ACTION;
2220 info->handle = handle;
2221 info->ui_handle = ops->request_action(title, primary, secondary,
2222 default_action, cpar, user_data, action_count, actions);
2224 handles = g_list_append(handles, info);
2226 g_strfreev(tmp);
2227 purple_request_cpar_unref(cpar);
2228 return info->ui_handle;
2231 purple_request_cpar_unref(cpar);
2232 return NULL;
2235 void *
2236 purple_request_wait(void *handle, const char *title, const char *primary,
2237 const char *secondary, gboolean with_progress,
2238 PurpleRequestCancelCb cancel_cb, PurpleRequestCommonParameters *cpar,
2239 void *user_data)
2241 PurpleRequestUiOps *ops;
2243 if (primary == NULL)
2244 primary = _("Please wait...");
2246 ops = purple_request_get_ui_ops();
2248 if (ops != NULL && ops->request_wait != NULL) {
2249 PurpleRequestInfo *info;
2250 gchar **tmp;
2252 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2254 info = g_new0(PurpleRequestInfo, 1);
2255 info->type = PURPLE_REQUEST_WAIT;
2256 info->handle = handle;
2257 info->ui_handle = ops->request_wait(title, primary, secondary,
2258 with_progress, cancel_cb, cpar, user_data);
2260 handles = g_list_append(handles, info);
2262 g_strfreev(tmp);
2263 purple_request_cpar_unref(cpar);
2264 return info->ui_handle;
2267 if (cpar == NULL)
2268 cpar = purple_request_cpar_new();
2269 if (purple_request_cpar_get_icon(cpar) == PURPLE_REQUEST_ICON_DEFAULT)
2270 purple_request_cpar_set_icon(cpar, PURPLE_REQUEST_ICON_WAIT);
2272 return purple_request_action(handle, title, primary, secondary,
2273 PURPLE_DEFAULT_ACTION_NONE, cpar, user_data,
2274 cancel_cb ? 1 : 0, _("Cancel"), cancel_cb);
2277 void
2278 purple_request_wait_pulse(void *ui_handle)
2280 PurpleRequestUiOps *ops;
2282 ops = purple_request_get_ui_ops();
2284 if (ops == NULL || ops->request_wait_update == NULL)
2285 return;
2287 ops->request_wait_update(ui_handle, TRUE, 0.0);
2290 void
2291 purple_request_wait_progress(void *ui_handle, gfloat fraction)
2293 PurpleRequestUiOps *ops;
2295 ops = purple_request_get_ui_ops();
2297 if (ops == NULL || ops->request_wait_update == NULL)
2298 return;
2300 if (fraction < 0.0 || fraction > 1.0) {
2301 purple_debug_warning("request", "Fraction parameter out of "
2302 "range: %f", fraction);
2303 if (fraction < 0.0)
2304 fraction = 0.0;
2305 else /* if (fraction > 1.0) */
2306 fraction = 1.0;
2309 ops->request_wait_update(ui_handle, FALSE, fraction);
2312 static void
2313 purple_request_fields_strip_html(PurpleRequestFields *fields)
2315 GList *itg;
2317 for (itg = fields->groups; itg != NULL; itg = g_list_next(itg)) {
2318 PurpleRequestFieldGroup *group = itg->data;
2319 GList *itf;
2321 for (itf = group->fields; itf != NULL; itf = g_list_next(itf)) {
2322 PurpleRequestField *field = itf->data;
2323 gchar *new_label;
2325 new_label = purple_request_strip_html_custom(
2326 field->label);
2327 if (g_strcmp0(new_label, field->label) == 0) {
2328 g_free(new_label);
2329 continue;
2331 g_free(field->label);
2332 field->label = new_label;
2337 void *
2338 purple_request_fields(void *handle, const char *title, const char *primary,
2339 const char *secondary, PurpleRequestFields *fields, const char *ok_text,
2340 GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
2341 PurpleRequestCommonParameters *cpar, void *user_data)
2343 PurpleRequestUiOps *ops;
2345 if (G_UNLIKELY(fields == NULL ||
2346 ((ok_text == NULL) != (ok_cb == NULL)) ||
2347 cancel_text == NULL))
2349 purple_request_cpar_unref(cpar);
2350 g_warn_if_fail(fields != NULL);
2351 g_warn_if_fail((ok_text == NULL) != (ok_cb == NULL));
2352 g_warn_if_fail(cancel_text != NULL);
2353 g_return_val_if_reached(NULL);
2356 ops = purple_request_get_ui_ops();
2358 if (purple_request_cpar_is_html(cpar) &&
2359 !((ops->features & PURPLE_REQUEST_FEATURE_HTML)))
2361 purple_request_fields_strip_html(fields);
2364 purple_request_fields_check_sensitivity(fields);
2366 if (ops != NULL && ops->request_fields != NULL) {
2367 PurpleRequestInfo *info;
2368 gchar **tmp;
2370 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2372 info = g_new0(PurpleRequestInfo, 1);
2373 info->type = PURPLE_REQUEST_FIELDS;
2374 info->handle = handle;
2375 info->ui_handle = ops->request_fields(title, primary, secondary,
2376 fields, ok_text, ok_cb, cancel_text, cancel_cb,
2377 cpar, user_data);
2379 handles = g_list_append(handles, info);
2381 g_strfreev(tmp);
2382 purple_request_cpar_unref(cpar);
2383 return info->ui_handle;
2386 purple_request_cpar_unref(cpar);
2387 return NULL;
2390 void *
2391 purple_request_file(void *handle, const char *title, const char *filename,
2392 gboolean savedialog, GCallback ok_cb, GCallback cancel_cb,
2393 PurpleRequestCommonParameters *cpar, void *user_data)
2395 PurpleRequestUiOps *ops;
2397 ops = purple_request_get_ui_ops();
2399 if (ops != NULL && ops->request_file != NULL) {
2400 PurpleRequestInfo *info;
2402 info = g_new0(PurpleRequestInfo, 1);
2403 info->type = PURPLE_REQUEST_FILE;
2404 info->handle = handle;
2405 info->ui_handle = ops->request_file(title, filename, savedialog,
2406 ok_cb, cancel_cb, cpar, user_data);
2407 handles = g_list_append(handles, info);
2409 purple_request_cpar_unref(cpar);
2410 return info->ui_handle;
2413 purple_request_cpar_unref(cpar);
2414 return NULL;
2417 void *
2418 purple_request_folder(void *handle, const char *title, const char *dirname,
2419 GCallback ok_cb, GCallback cancel_cb,
2420 PurpleRequestCommonParameters *cpar, void *user_data)
2422 PurpleRequestUiOps *ops;
2424 ops = purple_request_get_ui_ops();
2426 if (ops != NULL && ops->request_file != NULL) {
2427 PurpleRequestInfo *info;
2429 info = g_new0(PurpleRequestInfo, 1);
2430 info->type = PURPLE_REQUEST_FOLDER;
2431 info->handle = handle;
2432 info->ui_handle = ops->request_folder(title, dirname, ok_cb,
2433 cancel_cb, cpar, user_data);
2434 handles = g_list_append(handles, info);
2436 purple_request_cpar_unref(cpar);
2437 return info->ui_handle;
2440 purple_request_cpar_unref(cpar);
2441 return NULL;
2444 gboolean
2445 purple_request_is_valid_ui_handle(void *ui_handle, PurpleRequestType *type)
2447 PurpleRequestInfo *info;
2449 if (ui_handle == NULL)
2450 return FALSE;
2452 info = purple_request_info_from_ui_handle(ui_handle);
2454 if (info == NULL)
2455 return FALSE;
2457 if (type != NULL)
2458 *type = info->type;
2460 return TRUE;
2463 void
2464 purple_request_add_close_notify(void *ui_handle, GDestroyNotify notify,
2465 gpointer notify_data)
2467 PurpleRequestInfo *info;
2468 PurpleRequestCloseNotified *notified;
2470 g_return_if_fail(ui_handle != NULL);
2471 g_return_if_fail(notify != NULL);
2473 info = purple_request_info_from_ui_handle(ui_handle);
2474 g_return_if_fail(info != NULL);
2476 notified = g_new0(PurpleRequestCloseNotified, 1);
2477 notified->cb = notify;
2478 notified->data = notify_data;
2480 info->notify_on_close = g_slist_append(info->notify_on_close, notified);
2483 static void
2484 purple_request_close_info(PurpleRequestInfo *info)
2486 PurpleRequestUiOps *ops;
2487 GSList *it;
2489 ops = purple_request_get_ui_ops();
2491 purple_notify_close_with_handle(info->ui_handle);
2492 purple_request_close_with_handle(info->ui_handle);
2494 if (ops != NULL && ops->close_request != NULL)
2495 ops->close_request(info->type, info->ui_handle);
2497 for (it = info->notify_on_close; it; it = g_slist_next(it)) {
2498 PurpleRequestCloseNotified *notify = it->data;
2500 notify->cb(notify->data);
2503 g_slist_free_full(info->notify_on_close, g_free);
2504 g_free(info);
2507 void
2508 purple_request_close(PurpleRequestType type, void *ui_handle)
2510 GList *l;
2512 g_return_if_fail(ui_handle != NULL);
2514 for (l = handles; l != NULL; l = l->next) {
2515 PurpleRequestInfo *info = l->data;
2517 if (info->ui_handle == ui_handle) {
2518 handles = g_list_remove(handles, info);
2519 purple_request_close_info(info);
2520 break;
2525 void
2526 purple_request_close_with_handle(void *handle)
2528 GList *l, *l_next;
2530 g_return_if_fail(handle != NULL);
2532 for (l = handles; l != NULL; l = l_next) {
2533 PurpleRequestInfo *info = l->data;
2535 l_next = l->next;
2537 if (info->handle == handle) {
2538 handles = g_list_remove(handles, info);
2539 purple_request_close_info(info);
2544 void
2545 purple_request_set_ui_ops(PurpleRequestUiOps *ops)
2547 request_ui_ops = ops;
2550 PurpleRequestUiOps *
2551 purple_request_get_ui_ops(void)
2553 return request_ui_ops;
2556 /**************************************************************************
2557 * GBoxed code
2558 **************************************************************************/
2559 static PurpleRequestUiOps *
2560 purple_request_ui_ops_copy(PurpleRequestUiOps *ops)
2562 PurpleRequestUiOps *ops_new;
2564 g_return_val_if_fail(ops != NULL, NULL);
2566 ops_new = g_new(PurpleRequestUiOps, 1);
2567 *ops_new = *ops;
2569 return ops_new;
2572 GType
2573 purple_request_ui_ops_get_type(void)
2575 static GType type = 0;
2577 if (type == 0) {
2578 type = g_boxed_type_register_static("PurpleRequestUiOps",
2579 (GBoxedCopyFunc)purple_request_ui_ops_copy,
2580 (GBoxedFreeFunc)g_free);
2583 return type;