Merge heads.
[pidgin-git.git] / libpurple / request.c
blob13e24e5d17079c96b4b3bd62158dcd9c4a5416d8
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_free_full(fields->groups,
496 (GDestroyNotify)purple_request_field_group_destroy);
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_free_full(group->fields,
846 (GDestroyNotify)purple_request_field_destroy);
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 g_list_free_full(field->u.list.items, g_free);
970 g_list_free_full(field->u.list.selected, g_free);
971 g_hash_table_destroy(field->u.list.item_data);
972 g_hash_table_destroy(field->u.list.selected_table);
974 else if (field->type == PURPLE_REQUEST_FIELD_DATASHEET)
976 purple_request_datasheet_free(field->u.datasheet.sheet);
979 g_free(field);
982 void
983 purple_request_field_set_label(PurpleRequestField *field, const char *label)
985 g_return_if_fail(field != NULL);
987 g_free(field->label);
988 field->label = g_strdup(label);
991 void
992 purple_request_field_set_visible(PurpleRequestField *field, gboolean visible)
994 g_return_if_fail(field != NULL);
996 field->visible = visible;
999 void
1000 purple_request_field_set_type_hint(PurpleRequestField *field,
1001 const char *type_hint)
1003 g_return_if_fail(field != NULL);
1005 g_free(field->type_hint);
1006 field->type_hint = g_strdup(type_hint);
1009 void
1010 purple_request_field_set_tooltip(PurpleRequestField *field, const char *tooltip)
1012 g_return_if_fail(field != NULL);
1014 g_free(field->tooltip);
1015 field->tooltip = g_strdup(tooltip);
1018 void
1019 purple_request_field_set_required(PurpleRequestField *field, gboolean required)
1021 g_return_if_fail(field != NULL);
1023 if (field->required == required)
1024 return;
1026 field->required = required;
1028 if (field->group != NULL)
1030 if (required)
1032 field->group->fields_list->required_fields =
1033 g_list_append(field->group->fields_list->required_fields,
1034 field);
1036 else
1038 field->group->fields_list->required_fields =
1039 g_list_remove(field->group->fields_list->required_fields,
1040 field);
1045 PurpleRequestFieldType
1046 purple_request_field_get_field_type(const PurpleRequestField *field)
1048 g_return_val_if_fail(field != NULL, PURPLE_REQUEST_FIELD_NONE);
1050 return field->type;
1053 PurpleRequestFieldGroup *
1054 purple_request_field_get_group(const PurpleRequestField *field)
1056 g_return_val_if_fail(field != NULL, NULL);
1058 return field->group;
1061 const char *
1062 purple_request_field_get_id(const PurpleRequestField *field)
1064 g_return_val_if_fail(field != NULL, NULL);
1066 return field->id;
1069 const char *
1070 purple_request_field_get_label(const PurpleRequestField *field)
1072 g_return_val_if_fail(field != NULL, NULL);
1074 return field->label;
1077 gboolean
1078 purple_request_field_is_visible(const PurpleRequestField *field)
1080 g_return_val_if_fail(field != NULL, FALSE);
1082 return field->visible;
1085 const char *
1086 purple_request_field_get_field_type_hint(const PurpleRequestField *field)
1088 g_return_val_if_fail(field != NULL, NULL);
1090 return field->type_hint;
1093 const char *
1094 purple_request_field_get_tooltip(const PurpleRequestField *field)
1096 g_return_val_if_fail(field != NULL, NULL);
1098 return field->tooltip;
1101 gboolean
1102 purple_request_field_is_required(const PurpleRequestField *field)
1104 g_return_val_if_fail(field != NULL, FALSE);
1106 return field->required;
1109 gboolean
1110 purple_request_field_is_filled(const PurpleRequestField *field)
1112 g_return_val_if_fail(field != NULL, FALSE);
1114 switch (purple_request_field_get_field_type(field))
1116 case PURPLE_REQUEST_FIELD_STRING:
1117 return (purple_request_field_string_get_value(field) != NULL &&
1118 *(purple_request_field_string_get_value(field)) != '\0');
1119 default:
1120 return TRUE;
1124 void
1125 purple_request_field_set_validator(PurpleRequestField *field,
1126 PurpleRequestFieldValidator validator, void *user_data)
1128 g_return_if_fail(field != NULL);
1130 field->validator = validator;
1131 field->validator_data = validator ? user_data : NULL;
1133 if (field->group != NULL)
1135 PurpleRequestFields *flist = field->group->fields_list;
1136 flist->validated_fields = g_list_remove(flist->validated_fields,
1137 field);
1138 if (validator)
1140 flist->validated_fields = g_list_append(
1141 flist->validated_fields, field);
1146 gboolean
1147 purple_request_field_is_validatable(PurpleRequestField *field)
1149 g_return_val_if_fail(field != NULL, FALSE);
1151 return field->validator != NULL;
1154 gboolean
1155 purple_request_field_is_valid(PurpleRequestField *field, gchar **errmsg)
1157 gboolean valid;
1159 g_return_val_if_fail(field != NULL, FALSE);
1161 if (!field->validator)
1162 return TRUE;
1164 if (!purple_request_field_is_required(field) &&
1165 !purple_request_field_is_filled(field))
1166 return TRUE;
1168 valid = field->validator(field, errmsg, field->validator_data);
1170 if (valid && errmsg)
1171 *errmsg = NULL;
1173 return valid;
1176 void
1177 purple_request_field_set_sensitive(PurpleRequestField *field,
1178 gboolean sensitive)
1180 g_return_if_fail(field != NULL);
1182 field->sensitive = sensitive;
1185 gboolean
1186 purple_request_field_is_sensitive(PurpleRequestField *field)
1188 g_return_val_if_fail(field != NULL, FALSE);
1190 return field->sensitive;
1193 void
1194 purple_request_field_set_sensitivity_cb(PurpleRequestField *field,
1195 PurpleRequestFieldSensitivityCb cb)
1197 PurpleRequestFields *flist;
1199 g_return_if_fail(field != NULL);
1201 field->sensitivity_cb = cb;
1203 if (!field->group || !field->group->fields_list)
1204 return;
1205 flist = field->group->fields_list;
1206 flist->autosensitive_fields = g_list_remove(flist->autosensitive_fields,
1207 field);
1208 if (cb != NULL)
1210 flist->autosensitive_fields = g_list_append(
1211 flist->autosensitive_fields, field);
1215 PurpleRequestField *
1216 purple_request_field_string_new(const char *id, const char *text,
1217 const char *default_value, gboolean multiline)
1219 PurpleRequestField *field;
1221 g_return_val_if_fail(id != NULL, NULL);
1222 g_return_val_if_fail(text != NULL, NULL);
1224 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_STRING);
1226 field->u.string.multiline = multiline;
1228 purple_request_field_string_set_default_value(field, default_value);
1229 purple_request_field_string_set_value(field, default_value);
1231 return field;
1234 void
1235 purple_request_field_string_set_default_value(PurpleRequestField *field,
1236 const char *default_value)
1238 g_return_if_fail(field != NULL);
1239 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
1241 g_free(field->u.string.default_value);
1242 field->u.string.default_value = g_strdup(default_value);
1245 void
1246 purple_request_field_string_set_value(PurpleRequestField *field, const char *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.value);
1252 field->u.string.value = g_strdup(value);
1254 purple_request_fields_check_others_sensitivity(field);
1257 void
1258 purple_request_field_string_set_masked(PurpleRequestField *field, gboolean masked)
1260 g_return_if_fail(field != NULL);
1261 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
1263 field->u.string.masked = masked;
1266 const char *
1267 purple_request_field_string_get_default_value(const PurpleRequestField *field)
1269 g_return_val_if_fail(field != NULL, NULL);
1270 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, NULL);
1272 return field->u.string.default_value;
1275 const char *
1276 purple_request_field_string_get_value(const PurpleRequestField *field)
1278 g_return_val_if_fail(field != NULL, NULL);
1279 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, NULL);
1281 return field->u.string.value;
1284 gboolean
1285 purple_request_field_string_is_multiline(const PurpleRequestField *field)
1287 g_return_val_if_fail(field != NULL, FALSE);
1288 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
1290 return field->u.string.multiline;
1293 gboolean
1294 purple_request_field_string_is_masked(const PurpleRequestField *field)
1296 g_return_val_if_fail(field != NULL, FALSE);
1297 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
1299 return field->u.string.masked;
1302 PurpleRequestField *
1303 purple_request_field_int_new(const char *id, const char *text,
1304 int default_value, int lower_bound, int upper_bound)
1306 PurpleRequestField *field;
1308 g_return_val_if_fail(id != NULL, NULL);
1309 g_return_val_if_fail(text != NULL, NULL);
1311 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_INTEGER);
1313 purple_request_field_int_set_lower_bound(field, lower_bound);
1314 purple_request_field_int_set_upper_bound(field, upper_bound);
1315 purple_request_field_int_set_default_value(field, default_value);
1316 purple_request_field_int_set_value(field, default_value);
1318 return field;
1321 void
1322 purple_request_field_int_set_default_value(PurpleRequestField *field,
1323 int default_value)
1325 g_return_if_fail(field != NULL);
1326 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1328 field->u.integer.default_value = default_value;
1331 void
1332 purple_request_field_int_set_lower_bound(PurpleRequestField *field,
1333 int lower_bound)
1335 g_return_if_fail(field != NULL);
1336 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1338 field->u.integer.lower_bound = lower_bound;
1341 void
1342 purple_request_field_int_set_upper_bound(PurpleRequestField *field,
1343 int upper_bound)
1345 g_return_if_fail(field != NULL);
1346 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1348 field->u.integer.upper_bound = upper_bound;
1351 void
1352 purple_request_field_int_set_value(PurpleRequestField *field, int value)
1354 g_return_if_fail(field != NULL);
1355 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1357 if (value < field->u.integer.lower_bound ||
1358 value > field->u.integer.upper_bound) {
1359 purple_debug_error("request", "Int value out of bounds\n");
1360 return;
1363 field->u.integer.value = value;
1365 purple_request_fields_check_others_sensitivity(field);
1369 purple_request_field_int_get_default_value(const PurpleRequestField *field)
1371 g_return_val_if_fail(field != NULL, 0);
1372 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1374 return field->u.integer.default_value;
1378 purple_request_field_int_get_lower_bound(const PurpleRequestField *field)
1380 g_return_val_if_fail(field != NULL, 0);
1381 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1383 return field->u.integer.lower_bound;
1387 purple_request_field_int_get_upper_bound(const PurpleRequestField *field)
1389 g_return_val_if_fail(field != NULL, 0);
1390 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1392 return field->u.integer.upper_bound;
1396 purple_request_field_int_get_value(const PurpleRequestField *field)
1398 g_return_val_if_fail(field != NULL, 0);
1399 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1401 return field->u.integer.value;
1404 PurpleRequestField *
1405 purple_request_field_bool_new(const char *id, const char *text,
1406 gboolean default_value)
1408 PurpleRequestField *field;
1410 g_return_val_if_fail(id != NULL, NULL);
1411 g_return_val_if_fail(text != NULL, NULL);
1413 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_BOOLEAN);
1415 purple_request_field_bool_set_default_value(field, default_value);
1416 purple_request_field_bool_set_value(field, default_value);
1418 return field;
1421 void
1422 purple_request_field_bool_set_default_value(PurpleRequestField *field,
1423 gboolean default_value)
1425 g_return_if_fail(field != NULL);
1426 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN);
1428 field->u.boolean.default_value = default_value;
1431 void
1432 purple_request_field_bool_set_value(PurpleRequestField *field, gboolean value)
1434 g_return_if_fail(field != NULL);
1435 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN);
1437 field->u.boolean.value = value;
1439 purple_request_fields_check_others_sensitivity(field);
1442 gboolean
1443 purple_request_field_bool_get_default_value(const PurpleRequestField *field)
1445 g_return_val_if_fail(field != NULL, FALSE);
1446 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN, FALSE);
1448 return field->u.boolean.default_value;
1451 gboolean
1452 purple_request_field_bool_get_value(const PurpleRequestField *field)
1454 g_return_val_if_fail(field != NULL, FALSE);
1455 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN, FALSE);
1457 return field->u.boolean.value;
1460 PurpleRequestField *
1461 purple_request_field_choice_new(const char *id, const char *text,
1462 gpointer default_value)
1464 PurpleRequestField *field;
1466 g_return_val_if_fail(id != NULL, NULL);
1467 g_return_val_if_fail(text != NULL, NULL);
1469 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_CHOICE);
1471 purple_request_field_choice_set_default_value(field, default_value);
1472 purple_request_field_choice_set_value(field, default_value);
1474 return field;
1477 void
1478 purple_request_field_choice_add(PurpleRequestField *field, const char *label,
1479 gpointer value)
1481 g_return_if_fail(field != NULL);
1482 g_return_if_fail(label != NULL);
1483 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1485 field->u.choice.elements = g_list_append(field->u.choice.elements,
1486 g_strdup(label));
1487 field->u.choice.elements = g_list_append(field->u.choice.elements,
1488 value);
1491 void
1492 purple_request_field_choice_set_default_value(PurpleRequestField *field,
1493 gpointer default_value)
1495 g_return_if_fail(field != NULL);
1496 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1498 field->u.choice.default_value = default_value;
1501 void
1502 purple_request_field_choice_set_value(PurpleRequestField *field, gpointer value)
1504 g_return_if_fail(field != NULL);
1505 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1507 field->u.choice.value = value;
1509 purple_request_fields_check_others_sensitivity(field);
1512 gpointer
1513 purple_request_field_choice_get_default_value(const PurpleRequestField *field)
1515 g_return_val_if_fail(field != NULL, NULL);
1516 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, NULL);
1518 return field->u.choice.default_value;
1521 gpointer
1522 purple_request_field_choice_get_value(const PurpleRequestField *field)
1524 g_return_val_if_fail(field != NULL, NULL);
1525 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, NULL);
1527 return field->u.choice.value;
1530 GList *
1531 purple_request_field_choice_get_elements(const PurpleRequestField *field)
1533 g_return_val_if_fail(field != NULL, NULL);
1534 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, NULL);
1536 return field->u.choice.elements;
1539 void
1540 purple_request_field_choice_set_data_destructor(PurpleRequestField *field,
1541 GDestroyNotify destroy)
1543 g_return_if_fail(field != NULL);
1544 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1546 field->u.choice.data_destroy = destroy;
1549 PurpleRequestField *
1550 purple_request_field_list_new(const char *id, const char *text)
1552 PurpleRequestField *field;
1554 g_return_val_if_fail(id != NULL, NULL);
1556 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_LIST);
1558 field->u.list.item_data = g_hash_table_new_full(g_str_hash, g_str_equal,
1559 g_free, NULL);
1561 field->u.list.selected_table =
1562 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1564 return field;
1567 void
1568 purple_request_field_list_set_multi_select(PurpleRequestField *field,
1569 gboolean multi_select)
1571 g_return_if_fail(field != NULL);
1572 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1574 field->u.list.multiple_selection = multi_select;
1577 gboolean
1578 purple_request_field_list_get_multi_select(const PurpleRequestField *field)
1580 g_return_val_if_fail(field != NULL, FALSE);
1581 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, FALSE);
1583 return field->u.list.multiple_selection;
1586 void *
1587 purple_request_field_list_get_data(const PurpleRequestField *field,
1588 const char *text)
1590 g_return_val_if_fail(field != NULL, NULL);
1591 g_return_val_if_fail(text != NULL, NULL);
1592 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1594 return g_hash_table_lookup(field->u.list.item_data, text);
1597 void
1598 purple_request_field_list_add_icon(PurpleRequestField *field, const char *item, const char* icon_path,
1599 void *data)
1601 g_return_if_fail(field != NULL);
1602 g_return_if_fail(item != NULL);
1603 g_return_if_fail(data != NULL);
1604 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1606 if (icon_path)
1608 if (field->u.list.icons == NULL)
1610 GList *l;
1611 for (l = field->u.list.items ; l != NULL ; l = l->next)
1613 /* Order doesn't matter, because we're just
1614 * filing in blank items. So, we use
1615 * g_list_prepend() because it's faster. */
1616 field->u.list.icons = g_list_prepend(field->u.list.icons, NULL);
1619 field->u.list.icons = g_list_append(field->u.list.icons, g_strdup(icon_path));
1621 else if (field->u.list.icons)
1623 /* Keep this even with the items list. */
1624 field->u.list.icons = g_list_append(field->u.list.icons, NULL);
1627 field->u.list.items = g_list_append(field->u.list.items, g_strdup(item));
1628 g_hash_table_insert(field->u.list.item_data, g_strdup(item), data);
1631 void
1632 purple_request_field_list_add_selected(PurpleRequestField *field, const char *item)
1634 g_return_if_fail(field != NULL);
1635 g_return_if_fail(item != NULL);
1636 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1638 if (!purple_request_field_list_get_multi_select(field) &&
1639 field->u.list.selected != NULL)
1641 purple_debug_warning("request",
1642 "More than one item added to non-multi-select "
1643 "field %s\n",
1644 purple_request_field_get_id(field));
1645 return;
1648 field->u.list.selected = g_list_append(field->u.list.selected,
1649 g_strdup(item));
1651 g_hash_table_insert(field->u.list.selected_table, g_strdup(item), NULL);
1654 void
1655 purple_request_field_list_clear_selected(PurpleRequestField *field)
1657 g_return_if_fail(field != NULL);
1658 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1660 if (field->u.list.selected != NULL)
1662 g_list_free_full(field->u.list.selected, g_free);
1663 field->u.list.selected = NULL;
1666 g_hash_table_destroy(field->u.list.selected_table);
1668 field->u.list.selected_table =
1669 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1672 void
1673 purple_request_field_list_set_selected(PurpleRequestField *field, GList *items)
1675 GList *l;
1677 g_return_if_fail(field != NULL);
1678 g_return_if_fail(items != NULL);
1679 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1681 purple_request_field_list_clear_selected(field);
1683 if (!purple_request_field_list_get_multi_select(field) && items->next) {
1684 purple_debug_warning("request",
1685 "More than one item added to non-multi-select "
1686 "field %s\n",
1687 purple_request_field_get_id(field));
1688 return;
1691 for (l = items; l != NULL; l = l->next)
1693 field->u.list.selected = g_list_append(field->u.list.selected,
1694 g_strdup(l->data));
1695 g_hash_table_insert(field->u.list.selected_table,
1696 g_strdup((char *)l->data), NULL);
1700 gboolean
1701 purple_request_field_list_is_selected(const PurpleRequestField *field,
1702 const char *item)
1704 g_return_val_if_fail(field != NULL, FALSE);
1705 g_return_val_if_fail(item != NULL, FALSE);
1706 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, FALSE);
1708 return g_hash_table_lookup_extended(field->u.list.selected_table,
1709 item, NULL, NULL);
1712 GList *
1713 purple_request_field_list_get_selected(const PurpleRequestField *field)
1715 g_return_val_if_fail(field != NULL, NULL);
1716 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1718 return field->u.list.selected;
1721 GList *
1722 purple_request_field_list_get_items(const PurpleRequestField *field)
1724 g_return_val_if_fail(field != NULL, NULL);
1725 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1727 return field->u.list.items;
1730 GList *
1731 purple_request_field_list_get_icons(const PurpleRequestField *field)
1733 g_return_val_if_fail(field != NULL, NULL);
1734 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1736 return field->u.list.icons;
1739 PurpleRequestField *
1740 purple_request_field_label_new(const char *id, const char *text)
1742 PurpleRequestField *field;
1744 g_return_val_if_fail(id != NULL, NULL);
1745 g_return_val_if_fail(text != NULL, NULL);
1747 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_LABEL);
1749 return field;
1752 PurpleRequestField *
1753 purple_request_field_image_new(const char *id, const char *text, const char *buf, gsize size)
1755 PurpleRequestField *field;
1757 g_return_val_if_fail(id != NULL, NULL);
1758 g_return_val_if_fail(text != NULL, NULL);
1759 g_return_val_if_fail(buf != NULL, NULL);
1760 g_return_val_if_fail(size > 0, NULL);
1762 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_IMAGE);
1764 field->u.image.buffer = g_memdup(buf, size);
1765 field->u.image.size = size;
1766 field->u.image.scale_x = 1;
1767 field->u.image.scale_y = 1;
1769 return field;
1772 void
1773 purple_request_field_image_set_scale(PurpleRequestField *field, unsigned int x, unsigned int y)
1775 g_return_if_fail(field != NULL);
1776 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE);
1778 field->u.image.scale_x = x;
1779 field->u.image.scale_y = y;
1782 const char *
1783 purple_request_field_image_get_buffer(PurpleRequestField *field)
1785 g_return_val_if_fail(field != NULL, NULL);
1786 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, NULL);
1788 return field->u.image.buffer;
1791 gsize
1792 purple_request_field_image_get_size(PurpleRequestField *field)
1794 g_return_val_if_fail(field != NULL, 0);
1795 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1797 return field->u.image.size;
1800 unsigned int
1801 purple_request_field_image_get_scale_x(PurpleRequestField *field)
1803 g_return_val_if_fail(field != NULL, 0);
1804 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1806 return field->u.image.scale_x;
1809 unsigned int
1810 purple_request_field_image_get_scale_y(PurpleRequestField *field)
1812 g_return_val_if_fail(field != NULL, 0);
1813 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1815 return field->u.image.scale_y;
1818 PurpleRequestField *
1819 purple_request_field_account_new(const char *id, const char *text,
1820 PurpleAccount *account)
1822 PurpleRequestField *field;
1824 g_return_val_if_fail(id != NULL, NULL);
1825 g_return_val_if_fail(text != NULL, NULL);
1827 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_ACCOUNT);
1829 if (account == NULL && purple_connections_get_all() != NULL)
1831 account = purple_connection_get_account(
1832 (PurpleConnection *)purple_connections_get_all()->data);
1835 purple_request_field_account_set_default_value(field, account);
1836 purple_request_field_account_set_value(field, account);
1838 return field;
1841 void
1842 purple_request_field_account_set_default_value(PurpleRequestField *field,
1843 PurpleAccount *default_value)
1845 g_return_if_fail(field != NULL);
1846 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1848 field->u.account.default_account = default_value;
1851 void
1852 purple_request_field_account_set_value(PurpleRequestField *field,
1853 PurpleAccount *value)
1855 g_return_if_fail(field != NULL);
1856 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1858 field->u.account.account = value;
1860 purple_request_fields_check_others_sensitivity(field);
1863 void
1864 purple_request_field_account_set_show_all(PurpleRequestField *field,
1865 gboolean show_all)
1867 g_return_if_fail(field != NULL);
1868 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1870 if (field->u.account.show_all == show_all)
1871 return;
1873 field->u.account.show_all = show_all;
1875 if (!show_all)
1877 if (purple_account_is_connected(field->u.account.default_account))
1879 purple_request_field_account_set_default_value(field,
1880 (PurpleAccount *)purple_connections_get_all()->data);
1883 if (purple_account_is_connected(field->u.account.account))
1885 purple_request_field_account_set_value(field,
1886 (PurpleAccount *)purple_connections_get_all()->data);
1891 void
1892 purple_request_field_account_set_filter(PurpleRequestField *field,
1893 PurpleFilterAccountFunc filter_func)
1895 g_return_if_fail(field != NULL);
1896 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1898 field->u.account.filter_func = filter_func;
1901 PurpleAccount *
1902 purple_request_field_account_get_default_value(const PurpleRequestField *field)
1904 g_return_val_if_fail(field != NULL, NULL);
1905 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, NULL);
1907 return field->u.account.default_account;
1910 PurpleAccount *
1911 purple_request_field_account_get_value(const PurpleRequestField *field)
1913 g_return_val_if_fail(field != NULL, NULL);
1914 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, NULL);
1916 return field->u.account.account;
1919 gboolean
1920 purple_request_field_account_get_show_all(const PurpleRequestField *field)
1922 g_return_val_if_fail(field != NULL, FALSE);
1923 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, FALSE);
1925 return field->u.account.show_all;
1928 PurpleFilterAccountFunc
1929 purple_request_field_account_get_filter(const PurpleRequestField *field)
1931 g_return_val_if_fail(field != NULL, FALSE);
1932 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, FALSE);
1934 return field->u.account.filter_func;
1937 PurpleRequestField *
1938 purple_request_field_datasheet_new(const char *id,
1939 const gchar *text, PurpleRequestDatasheet *sheet)
1941 PurpleRequestField *field;
1943 g_return_val_if_fail(id != NULL, NULL);
1944 g_return_val_if_fail(sheet != NULL, NULL);
1946 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_DATASHEET);
1948 field->u.datasheet.sheet = sheet;
1950 return field;
1953 PurpleRequestDatasheet *
1954 purple_request_field_datasheet_get_sheet(PurpleRequestField *field)
1956 g_return_val_if_fail(field != NULL, NULL);
1957 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_DATASHEET, NULL);
1959 return field->u.datasheet.sheet;
1962 /* -- */
1964 gboolean
1965 purple_request_field_email_validator(PurpleRequestField *field, gchar **errmsg,
1966 void *user_data)
1968 const char *value;
1970 g_return_val_if_fail(field != NULL, FALSE);
1971 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
1973 value = purple_request_field_string_get_value(field);
1975 if (value != NULL && purple_email_is_valid(value))
1976 return TRUE;
1978 if (errmsg)
1979 *errmsg = g_strdup(_("Invalid email address"));
1980 return FALSE;
1983 gboolean
1984 purple_request_field_alphanumeric_validator(PurpleRequestField *field,
1985 gchar **errmsg, void *allowed_characters)
1987 const char *value;
1988 gchar invalid_char = '\0';
1990 g_return_val_if_fail(field != NULL, FALSE);
1991 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
1993 value = purple_request_field_string_get_value(field);
1995 g_return_val_if_fail(value != NULL, FALSE);
1997 if (allowed_characters)
1999 gchar *value_r = g_strdup(value);
2000 g_strcanon(value_r, allowed_characters, '\0');
2001 invalid_char = value[strlen(value_r)];
2002 g_free(value_r);
2004 else
2006 while (value)
2008 if (!g_ascii_isalnum(*value))
2010 invalid_char = *value;
2011 break;
2013 value++;
2016 if (!invalid_char)
2017 return TRUE;
2019 if (errmsg)
2020 *errmsg = g_strdup_printf(_("Invalid character '%c'"),
2021 invalid_char);
2022 return FALSE;
2025 /* -- */
2027 static gchar *
2028 purple_request_strip_html_custom(const gchar *html)
2030 gchar *tmp, *ret;
2032 tmp = purple_strreplace(html, "\n", "<br>");
2033 ret = purple_markup_strip_html(tmp);
2034 g_free(tmp);
2036 return ret;
2039 static gchar **
2040 purple_request_strip_html(PurpleRequestCommonParameters *cpar,
2041 const char **primary, const char **secondary)
2043 PurpleRequestUiOps *ops = purple_request_get_ui_ops();
2044 gchar **ret;
2046 if (!purple_request_cpar_is_html(cpar))
2047 return NULL;
2048 if (ops->features & PURPLE_REQUEST_FEATURE_HTML)
2049 return NULL;
2051 ret = g_new0(gchar*, 3);
2052 *primary = ret[0] = purple_request_strip_html_custom(*primary);
2053 *secondary = ret[1] = purple_request_strip_html_custom(*secondary);
2055 return ret;
2058 void *
2059 purple_request_input(void *handle, const char *title, const char *primary,
2060 const char *secondary, const char *default_value,
2061 gboolean multiline, gboolean masked, gchar *hint,
2062 const char *ok_text, GCallback ok_cb,
2063 const char *cancel_text, GCallback cancel_cb,
2064 PurpleRequestCommonParameters *cpar,
2065 void *user_data)
2067 PurpleRequestUiOps *ops;
2069 if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL)) {
2070 purple_request_cpar_unref(cpar);
2071 g_warn_if_fail(ok_text != NULL);
2072 g_warn_if_fail(ok_cb != NULL);
2073 g_return_val_if_reached(NULL);
2076 ops = purple_request_get_ui_ops();
2078 if (ops != NULL && ops->request_input != NULL) {
2079 PurpleRequestInfo *info;
2080 gchar **tmp;
2082 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2084 info = g_new0(PurpleRequestInfo, 1);
2085 info->type = PURPLE_REQUEST_INPUT;
2086 info->handle = handle;
2087 info->ui_handle = ops->request_input(title, primary, secondary,
2088 default_value, multiline, masked, hint, ok_text, ok_cb,
2089 cancel_text, cancel_cb, cpar, user_data);
2091 handles = g_list_append(handles, info);
2093 g_strfreev(tmp);
2094 purple_request_cpar_unref(cpar);
2095 return info->ui_handle;
2098 purple_request_cpar_unref(cpar);
2099 return NULL;
2102 void *
2103 purple_request_choice(void *handle, const char *title, const char *primary,
2104 const char *secondary, gpointer default_value, const char *ok_text,
2105 GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
2106 PurpleRequestCommonParameters *cpar, void *user_data, ...)
2108 void *ui_handle;
2109 va_list args;
2111 if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL)) {
2112 purple_request_cpar_unref(cpar);
2113 g_warn_if_fail(ok_text != NULL);
2114 g_warn_if_fail(ok_cb != NULL);
2115 g_return_val_if_reached(NULL);
2118 va_start(args, user_data);
2119 ui_handle = purple_request_choice_varg(handle, title, primary, secondary,
2120 default_value, ok_text, ok_cb,
2121 cancel_text, cancel_cb,
2122 cpar, user_data, args);
2123 va_end(args);
2125 return ui_handle;
2128 void *
2129 purple_request_choice_varg(void *handle, const char *title, const char *primary,
2130 const char *secondary, gpointer default_value, const char *ok_text,
2131 GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
2132 PurpleRequestCommonParameters *cpar, void *user_data, va_list choices)
2134 PurpleRequestUiOps *ops;
2136 if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL ||
2137 cancel_text == NULL))
2139 purple_request_cpar_unref(cpar);
2140 g_warn_if_fail(ok_text != NULL);
2141 g_warn_if_fail(ok_cb != NULL);
2142 g_warn_if_fail(cancel_text != NULL);
2143 g_return_val_if_reached(NULL);
2146 ops = purple_request_get_ui_ops();
2148 if (ops != NULL && ops->request_choice != NULL) {
2149 PurpleRequestInfo *info;
2150 gchar **tmp;
2152 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2154 info = g_new0(PurpleRequestInfo, 1);
2155 info->type = PURPLE_REQUEST_CHOICE;
2156 info->handle = handle;
2157 info->ui_handle = ops->request_choice(title, primary, secondary,
2158 default_value, ok_text, ok_cb, cancel_text, cancel_cb,
2159 cpar, user_data, choices);
2161 handles = g_list_append(handles, info);
2163 g_strfreev(tmp);
2164 purple_request_cpar_unref(cpar);
2165 return info->ui_handle;
2168 purple_request_cpar_unref(cpar);
2169 return NULL;
2172 void *
2173 purple_request_action(void *handle, const char *title, const char *primary,
2174 const char *secondary, int default_action,
2175 PurpleRequestCommonParameters *cpar, void *user_data,
2176 size_t action_count, ...)
2178 void *ui_handle;
2179 va_list args;
2181 va_start(args, action_count);
2182 ui_handle = purple_request_action_varg(handle, title, primary,
2183 secondary, default_action, cpar, user_data, action_count, args);
2184 va_end(args);
2186 return ui_handle;
2189 void *
2190 purple_request_action_varg(void *handle, const char *title, const char *primary,
2191 const char *secondary, int default_action,
2192 PurpleRequestCommonParameters *cpar, void *user_data,
2193 size_t action_count, va_list actions)
2195 PurpleRequestUiOps *ops;
2197 ops = purple_request_get_ui_ops();
2199 if (ops != NULL && ops->request_action != NULL) {
2200 PurpleRequestInfo *info;
2201 gchar **tmp;
2203 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2205 info = g_new0(PurpleRequestInfo, 1);
2206 info->type = PURPLE_REQUEST_ACTION;
2207 info->handle = handle;
2208 info->ui_handle = ops->request_action(title, primary, secondary,
2209 default_action, cpar, user_data, action_count, actions);
2211 handles = g_list_append(handles, info);
2213 g_strfreev(tmp);
2214 purple_request_cpar_unref(cpar);
2215 return info->ui_handle;
2218 purple_request_cpar_unref(cpar);
2219 return NULL;
2222 void *
2223 purple_request_wait(void *handle, const char *title, const char *primary,
2224 const char *secondary, gboolean with_progress,
2225 PurpleRequestCancelCb cancel_cb, PurpleRequestCommonParameters *cpar,
2226 void *user_data)
2228 PurpleRequestUiOps *ops;
2230 if (primary == NULL)
2231 primary = _("Please wait...");
2233 ops = purple_request_get_ui_ops();
2235 if (ops != NULL && ops->request_wait != NULL) {
2236 PurpleRequestInfo *info;
2237 gchar **tmp;
2239 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2241 info = g_new0(PurpleRequestInfo, 1);
2242 info->type = PURPLE_REQUEST_WAIT;
2243 info->handle = handle;
2244 info->ui_handle = ops->request_wait(title, primary, secondary,
2245 with_progress, cancel_cb, cpar, user_data);
2247 handles = g_list_append(handles, info);
2249 g_strfreev(tmp);
2250 purple_request_cpar_unref(cpar);
2251 return info->ui_handle;
2254 if (cpar == NULL)
2255 cpar = purple_request_cpar_new();
2256 if (purple_request_cpar_get_icon(cpar) == PURPLE_REQUEST_ICON_DEFAULT)
2257 purple_request_cpar_set_icon(cpar, PURPLE_REQUEST_ICON_WAIT);
2259 return purple_request_action(handle, title, primary, secondary,
2260 PURPLE_DEFAULT_ACTION_NONE, cpar, user_data,
2261 cancel_cb ? 1 : 0, _("Cancel"), cancel_cb);
2264 void
2265 purple_request_wait_pulse(void *ui_handle)
2267 PurpleRequestUiOps *ops;
2269 ops = purple_request_get_ui_ops();
2271 if (ops == NULL || ops->request_wait_update == NULL)
2272 return;
2274 ops->request_wait_update(ui_handle, TRUE, 0.0);
2277 void
2278 purple_request_wait_progress(void *ui_handle, gfloat fraction)
2280 PurpleRequestUiOps *ops;
2282 ops = purple_request_get_ui_ops();
2284 if (ops == NULL || ops->request_wait_update == NULL)
2285 return;
2287 if (fraction < 0.0 || fraction > 1.0) {
2288 purple_debug_warning("request", "Fraction parameter out of "
2289 "range: %f", fraction);
2290 if (fraction < 0.0)
2291 fraction = 0.0;
2292 else /* if (fraction > 1.0) */
2293 fraction = 1.0;
2296 ops->request_wait_update(ui_handle, FALSE, fraction);
2299 static void
2300 purple_request_fields_strip_html(PurpleRequestFields *fields)
2302 GList *itg;
2304 for (itg = fields->groups; itg != NULL; itg = g_list_next(itg)) {
2305 PurpleRequestFieldGroup *group = itg->data;
2306 GList *itf;
2308 for (itf = group->fields; itf != NULL; itf = g_list_next(itf)) {
2309 PurpleRequestField *field = itf->data;
2310 gchar *new_label;
2312 new_label = purple_request_strip_html_custom(
2313 field->label);
2314 if (g_strcmp0(new_label, field->label) == 0) {
2315 g_free(new_label);
2316 continue;
2318 g_free(field->label);
2319 field->label = new_label;
2324 void *
2325 purple_request_fields(void *handle, const char *title, const char *primary,
2326 const char *secondary, PurpleRequestFields *fields, const char *ok_text,
2327 GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
2328 PurpleRequestCommonParameters *cpar, void *user_data)
2330 PurpleRequestUiOps *ops;
2332 if (G_UNLIKELY(fields == NULL ||
2333 ((ok_text == NULL) != (ok_cb == NULL)) ||
2334 cancel_text == NULL))
2336 purple_request_cpar_unref(cpar);
2337 g_warn_if_fail(fields != NULL);
2338 g_warn_if_fail((ok_text == NULL) != (ok_cb == NULL));
2339 g_warn_if_fail(cancel_text != NULL);
2340 g_return_val_if_reached(NULL);
2343 ops = purple_request_get_ui_ops();
2345 if (purple_request_cpar_is_html(cpar) &&
2346 !((ops->features & PURPLE_REQUEST_FEATURE_HTML)))
2348 purple_request_fields_strip_html(fields);
2351 purple_request_fields_check_sensitivity(fields);
2353 if (ops != NULL && ops->request_fields != NULL) {
2354 PurpleRequestInfo *info;
2355 gchar **tmp;
2357 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2359 info = g_new0(PurpleRequestInfo, 1);
2360 info->type = PURPLE_REQUEST_FIELDS;
2361 info->handle = handle;
2362 info->ui_handle = ops->request_fields(title, primary, secondary,
2363 fields, ok_text, ok_cb, cancel_text, cancel_cb,
2364 cpar, user_data);
2366 handles = g_list_append(handles, info);
2368 g_strfreev(tmp);
2369 purple_request_cpar_unref(cpar);
2370 return info->ui_handle;
2373 purple_request_cpar_unref(cpar);
2374 return NULL;
2377 void *
2378 purple_request_file(void *handle, const char *title, const char *filename,
2379 gboolean savedialog, GCallback ok_cb, GCallback cancel_cb,
2380 PurpleRequestCommonParameters *cpar, void *user_data)
2382 PurpleRequestUiOps *ops;
2384 ops = purple_request_get_ui_ops();
2386 if (ops != NULL && ops->request_file != NULL) {
2387 PurpleRequestInfo *info;
2389 info = g_new0(PurpleRequestInfo, 1);
2390 info->type = PURPLE_REQUEST_FILE;
2391 info->handle = handle;
2392 info->ui_handle = ops->request_file(title, filename, savedialog,
2393 ok_cb, cancel_cb, cpar, user_data);
2394 handles = g_list_append(handles, info);
2396 purple_request_cpar_unref(cpar);
2397 return info->ui_handle;
2400 purple_request_cpar_unref(cpar);
2401 return NULL;
2404 void *
2405 purple_request_folder(void *handle, const char *title, const char *dirname,
2406 GCallback ok_cb, GCallback cancel_cb,
2407 PurpleRequestCommonParameters *cpar, void *user_data)
2409 PurpleRequestUiOps *ops;
2411 ops = purple_request_get_ui_ops();
2413 if (ops != NULL && ops->request_file != NULL) {
2414 PurpleRequestInfo *info;
2416 info = g_new0(PurpleRequestInfo, 1);
2417 info->type = PURPLE_REQUEST_FOLDER;
2418 info->handle = handle;
2419 info->ui_handle = ops->request_folder(title, dirname, ok_cb,
2420 cancel_cb, cpar, user_data);
2421 handles = g_list_append(handles, info);
2423 purple_request_cpar_unref(cpar);
2424 return info->ui_handle;
2427 purple_request_cpar_unref(cpar);
2428 return NULL;
2431 gboolean
2432 purple_request_is_valid_ui_handle(void *ui_handle, PurpleRequestType *type)
2434 PurpleRequestInfo *info;
2436 if (ui_handle == NULL)
2437 return FALSE;
2439 info = purple_request_info_from_ui_handle(ui_handle);
2441 if (info == NULL)
2442 return FALSE;
2444 if (type != NULL)
2445 *type = info->type;
2447 return TRUE;
2450 void
2451 purple_request_add_close_notify(void *ui_handle, GDestroyNotify notify,
2452 gpointer notify_data)
2454 PurpleRequestInfo *info;
2455 PurpleRequestCloseNotified *notified;
2457 g_return_if_fail(ui_handle != NULL);
2458 g_return_if_fail(notify != NULL);
2460 info = purple_request_info_from_ui_handle(ui_handle);
2461 g_return_if_fail(info != NULL);
2463 notified = g_new0(PurpleRequestCloseNotified, 1);
2464 notified->cb = notify;
2465 notified->data = notify_data;
2467 info->notify_on_close = g_slist_append(info->notify_on_close, notified);
2470 static void
2471 purple_request_close_info(PurpleRequestInfo *info)
2473 PurpleRequestUiOps *ops;
2474 GSList *it;
2476 ops = purple_request_get_ui_ops();
2478 purple_notify_close_with_handle(info->ui_handle);
2479 purple_request_close_with_handle(info->ui_handle);
2481 if (ops != NULL && ops->close_request != NULL)
2482 ops->close_request(info->type, info->ui_handle);
2484 for (it = info->notify_on_close; it; it = g_slist_next(it)) {
2485 PurpleRequestCloseNotified *notify = it->data;
2487 notify->cb(notify->data);
2490 g_slist_free_full(info->notify_on_close, g_free);
2491 g_free(info);
2494 void
2495 purple_request_close(PurpleRequestType type, void *ui_handle)
2497 GList *l;
2499 g_return_if_fail(ui_handle != NULL);
2501 for (l = handles; l != NULL; l = l->next) {
2502 PurpleRequestInfo *info = l->data;
2504 if (info->ui_handle == ui_handle) {
2505 handles = g_list_remove(handles, info);
2506 purple_request_close_info(info);
2507 break;
2512 void
2513 purple_request_close_with_handle(void *handle)
2515 GList *l, *l_next;
2517 g_return_if_fail(handle != NULL);
2519 for (l = handles; l != NULL; l = l_next) {
2520 PurpleRequestInfo *info = l->data;
2522 l_next = l->next;
2524 if (info->handle == handle) {
2525 handles = g_list_remove(handles, info);
2526 purple_request_close_info(info);
2531 void
2532 purple_request_set_ui_ops(PurpleRequestUiOps *ops)
2534 request_ui_ops = ops;
2537 PurpleRequestUiOps *
2538 purple_request_get_ui_ops(void)
2540 return request_ui_ops;
2543 /**************************************************************************
2544 * GBoxed code
2545 **************************************************************************/
2546 static PurpleRequestUiOps *
2547 purple_request_ui_ops_copy(PurpleRequestUiOps *ops)
2549 PurpleRequestUiOps *ops_new;
2551 g_return_val_if_fail(ops != NULL, NULL);
2553 ops_new = g_new(PurpleRequestUiOps, 1);
2554 *ops_new = *ops;
2556 return ops_new;
2559 GType
2560 purple_request_ui_ops_get_type(void)
2562 static GType type = 0;
2564 if (type == 0) {
2565 type = g_boxed_type_register_static("PurpleRequestUiOps",
2566 (GBoxedCopyFunc)purple_request_ui_ops_copy,
2567 (GBoxedFreeFunc)g_free);
2570 return type;