Merged pidgin/main into default
[pidgin-git.git] / libpurple / request.c
blob3fb3e47775cee996ea3f0b68c6e945c78551efff
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
21 #define _PURPLE_REQUEST_C_
23 #include "internal.h"
25 #include "glibcompat.h"
26 #include "notify.h"
27 #include "request.h"
28 #include "debug.h"
30 static PurpleRequestUiOps *request_ui_ops = NULL;
31 static GList *handles = NULL;
33 typedef struct
35 GDestroyNotify cb;
36 gpointer data;
37 } PurpleRequestCloseNotified;
39 typedef struct
41 PurpleRequestType type;
42 void *handle;
43 void *ui_handle;
44 GSList *notify_on_close;
45 } PurpleRequestInfo;
47 struct _PurpleRequestField
49 PurpleRequestFieldType type;
50 PurpleRequestFieldGroup *group;
52 char *id;
53 char *label;
54 char *type_hint;
56 gboolean visible;
57 gboolean required;
58 gboolean sensitive;
59 PurpleRequestFieldSensitivityCb sensitivity_cb;
61 union
63 struct
65 gboolean multiline;
66 gboolean masked;
67 char *default_value;
68 char *value;
70 } string;
72 struct
74 int default_value;
75 int value;
76 int lower_bound;
77 int upper_bound;
78 } integer;
80 struct
82 gboolean default_value;
83 gboolean value;
85 } boolean;
87 struct
89 gpointer default_value;
90 gpointer value;
92 GList *elements;
93 GDestroyNotify data_destroy;
94 } choice;
96 struct
98 GList *items;
99 GList *icons;
100 GHashTable *item_data;
101 GList *selected;
102 GHashTable *selected_table;
104 gboolean multiple_selection;
106 } list;
108 struct
110 PurpleAccount *default_account;
111 PurpleAccount *account;
112 gboolean show_all;
114 PurpleFilterAccountFunc filter_func;
116 } account;
118 struct
120 unsigned int scale_x;
121 unsigned int scale_y;
122 const char *buffer;
123 gsize size;
124 } image;
126 struct
128 GTlsCertificate *cert;
129 } certificate;
131 struct
133 PurpleRequestDatasheet *sheet;
134 } datasheet;
135 } u;
137 void *ui_data;
138 char *tooltip;
140 PurpleRequestFieldValidator validator;
141 void *validator_data;
144 struct _PurpleRequestFields
146 GList *groups;
148 GHashTable *fields;
150 gchar **tab_names;
152 GList *required_fields;
154 GList *validated_fields;
156 GList *autosensitive_fields;
158 void *ui_data;
161 struct _PurpleRequestFieldGroup
163 PurpleRequestFields *fields_list;
165 char *title;
166 gint tab_no;
168 GList *fields;
171 struct _PurpleRequestCommonParameters
173 int ref_count;
175 PurpleAccount *account;
176 PurpleConversation *conv;
178 PurpleRequestIconType icon_type;
179 gconstpointer icon_data;
180 gsize icon_size;
182 gboolean html;
184 gboolean compact;
186 PurpleRequestHelpCb help_cb;
187 gpointer help_data;
189 GSList *extra_actions;
191 gpointer parent_from;
194 static void
195 purple_request_fields_check_others_sensitivity(PurpleRequestField *field);
197 PurpleRequestCommonParameters *
198 purple_request_cpar_new(void)
200 return g_new0(PurpleRequestCommonParameters, 1);
203 PurpleRequestCommonParameters *
204 purple_request_cpar_from_connection(PurpleConnection *gc)
206 if (gc == NULL)
207 return purple_request_cpar_new();
208 return purple_request_cpar_from_account(
209 purple_connection_get_account(gc));
212 PurpleRequestCommonParameters *
213 purple_request_cpar_from_account(PurpleAccount *account)
215 PurpleRequestCommonParameters *cpar;
217 cpar = purple_request_cpar_new();
218 purple_request_cpar_set_account(cpar, account);
220 return cpar;
223 PurpleRequestCommonParameters *
224 purple_request_cpar_from_conversation(PurpleConversation *conv)
226 PurpleRequestCommonParameters *cpar;
227 PurpleAccount *account = NULL;
229 if (conv != NULL) {
230 account = purple_connection_get_account(
231 purple_conversation_get_connection(conv));
234 cpar = purple_request_cpar_new();
235 purple_request_cpar_set_account(cpar, account);
236 purple_request_cpar_set_conversation(cpar, conv);
238 return cpar;
241 void
242 purple_request_cpar_ref(PurpleRequestCommonParameters *cpar)
244 g_return_if_fail(cpar != NULL);
246 cpar->ref_count++;
249 PurpleRequestCommonParameters *
250 purple_request_cpar_unref(PurpleRequestCommonParameters *cpar)
252 if (cpar == NULL)
253 return NULL;
255 if (--cpar->ref_count > 0)
256 return cpar;
258 purple_request_cpar_set_extra_actions(cpar, NULL);
259 g_free(cpar);
260 return NULL;
263 void
264 purple_request_cpar_set_account(PurpleRequestCommonParameters *cpar,
265 PurpleAccount *account)
267 g_return_if_fail(cpar != NULL);
269 cpar->account = account;
272 PurpleAccount *
273 purple_request_cpar_get_account(PurpleRequestCommonParameters *cpar)
275 if (cpar == NULL)
276 return NULL;
278 return cpar->account;
281 void
282 purple_request_cpar_set_conversation(PurpleRequestCommonParameters *cpar,
283 PurpleConversation *conv)
285 g_return_if_fail(cpar != NULL);
287 cpar->conv = conv;
290 PurpleConversation *
291 purple_request_cpar_get_conversation(PurpleRequestCommonParameters *cpar)
293 if (cpar == NULL)
294 return NULL;
296 return cpar->conv;
299 void
300 purple_request_cpar_set_icon(PurpleRequestCommonParameters *cpar,
301 PurpleRequestIconType icon_type)
303 g_return_if_fail(cpar != NULL);
305 cpar->icon_type = icon_type;
308 PurpleRequestIconType
309 purple_request_cpar_get_icon(PurpleRequestCommonParameters *cpar)
311 if (cpar == NULL)
312 return PURPLE_REQUEST_ICON_DEFAULT;
314 return cpar->icon_type;
317 void
318 purple_request_cpar_set_custom_icon(PurpleRequestCommonParameters *cpar,
319 gconstpointer icon_data, gsize icon_size)
321 g_return_if_fail(cpar != NULL);
322 g_return_if_fail((icon_data == NULL) == (icon_size == 0));
324 cpar->icon_data = icon_data;
325 cpar->icon_size = icon_size;
328 gconstpointer
329 purple_request_cpar_get_custom_icon(PurpleRequestCommonParameters *cpar,
330 gsize *icon_size)
332 if (cpar == NULL) {
333 if (icon_size != NULL)
334 *icon_size = 0;
335 return NULL;
338 if (icon_size != NULL)
339 *icon_size = cpar->icon_size;
340 return cpar->icon_data;
343 void
344 purple_request_cpar_set_html(PurpleRequestCommonParameters *cpar,
345 gboolean enabled)
347 g_return_if_fail(cpar != NULL);
349 cpar->html = enabled;
352 gboolean
353 purple_request_cpar_is_html(PurpleRequestCommonParameters *cpar)
355 if (cpar == NULL)
356 return FALSE;
358 return cpar->html;
361 void
362 purple_request_cpar_set_compact(PurpleRequestCommonParameters *cpar,
363 gboolean compact)
365 g_return_if_fail(cpar != NULL);
367 cpar->compact = compact;
370 gboolean
371 purple_request_cpar_is_compact(PurpleRequestCommonParameters *cpar)
373 if (cpar == NULL)
374 return FALSE;
376 return cpar->compact;
379 void
380 purple_request_cpar_set_help_cb(PurpleRequestCommonParameters *cpar,
381 PurpleRequestHelpCb cb, gpointer user_data)
383 g_return_if_fail(cpar != NULL);
385 cpar->help_cb = cb;
386 cpar->help_data = cb ? user_data : NULL;
389 PurpleRequestHelpCb
390 purple_request_cpar_get_help_cb(PurpleRequestCommonParameters *cpar,
391 gpointer *user_data)
393 if (cpar == NULL)
394 return NULL;
396 if (user_data != NULL)
397 *user_data = cpar->help_data;
398 return cpar->help_cb;
401 void
402 purple_request_cpar_set_extra_actions(PurpleRequestCommonParameters *cpar, ...)
404 va_list args;
405 GSList *extra = NULL, *it;
407 it = cpar->extra_actions;
408 while (it != NULL) {
409 gchar *label = it->data;
411 g_free(label);
412 it = g_slist_next(it);
413 if (it == NULL)
414 break;
415 it = g_slist_next(it);
418 va_start(args, cpar);
420 while (TRUE) {
421 const gchar *label;
422 PurpleRequestFieldsCb cb;
424 label = va_arg(args, const gchar*);
425 if (label == NULL)
426 break;
427 cb = va_arg(args, PurpleRequestFieldsCb);
429 extra = g_slist_append(extra, g_strdup(label));
430 extra = g_slist_append(extra, cb);
433 va_end(args);
435 cpar->extra_actions = extra;
438 GSList *
439 purple_request_cpar_get_extra_actions(PurpleRequestCommonParameters *cpar)
441 if (cpar == NULL)
442 return NULL;
444 return cpar->extra_actions;
447 void
448 purple_request_cpar_set_parent_from(PurpleRequestCommonParameters *cpar,
449 gpointer ui_handle)
451 g_return_if_fail(cpar != NULL);
453 cpar->parent_from = ui_handle;
456 gpointer
457 purple_request_cpar_get_parent_from(PurpleRequestCommonParameters *cpar)
459 if (cpar == NULL)
460 return NULL;
462 return cpar->parent_from;
465 static PurpleRequestInfo *
466 purple_request_info_from_ui_handle(void *ui_handle)
468 GList *it;
470 g_return_val_if_fail(ui_handle != NULL, NULL);
472 for (it = handles; it != NULL; it = g_list_next(it)) {
473 PurpleRequestInfo *info = it->data;
475 if (info->ui_handle == ui_handle)
476 return info;
479 return NULL;
482 PurpleRequestFields *
483 purple_request_fields_new(void)
485 PurpleRequestFields *fields;
487 fields = g_new0(PurpleRequestFields, 1);
489 fields->fields = g_hash_table_new_full(g_str_hash, g_str_equal,
490 g_free, NULL);
492 return fields;
495 void
496 purple_request_fields_destroy(PurpleRequestFields *fields)
498 g_return_if_fail(fields != NULL);
500 g_strfreev(fields->tab_names);
501 g_list_foreach(fields->groups, (GFunc)purple_request_field_group_destroy, NULL);
502 g_list_free(fields->groups);
503 g_list_free(fields->required_fields);
504 g_list_free(fields->validated_fields);
505 g_list_free(fields->autosensitive_fields);
506 g_hash_table_destroy(fields->fields);
507 g_free(fields);
510 void
511 purple_request_fields_add_group(PurpleRequestFields *fields,
512 PurpleRequestFieldGroup *group)
514 GList *l;
515 PurpleRequestField *field;
517 g_return_if_fail(fields != NULL);
518 g_return_if_fail(group != NULL);
520 fields->groups = g_list_append(fields->groups, group);
522 group->fields_list = fields;
524 for (l = purple_request_field_group_get_fields(group);
525 l != NULL;
526 l = l->next) {
528 field = l->data;
530 g_hash_table_insert(fields->fields,
531 g_strdup(purple_request_field_get_id(field)), field);
533 if (purple_request_field_is_required(field)) {
534 fields->required_fields =
535 g_list_append(fields->required_fields, field);
538 if (purple_request_field_is_validatable(field)) {
539 fields->validated_fields =
540 g_list_append(fields->validated_fields, field);
543 if (field->sensitivity_cb != NULL) {
544 fields->autosensitive_fields =
545 g_list_append(fields->autosensitive_fields, field);
550 GList *
551 purple_request_fields_get_groups(const PurpleRequestFields *fields)
553 g_return_val_if_fail(fields != NULL, NULL);
555 return fields->groups;
558 void
559 purple_request_fields_set_tab_names(PurpleRequestFields *fields,
560 const gchar **tab_names)
562 guint i, tab_count;
563 gchar **new_names;
565 g_return_if_fail(fields != NULL);
567 tab_count = (tab_names != NULL) ? g_strv_length((gchar **)tab_names) : 0;
568 new_names = (tab_count > 0) ? g_new0(gchar*, tab_count + 1) : NULL;
569 for (i = 0; i < tab_count; i++)
570 new_names[i] = g_strdup(tab_names[i]);
572 g_strfreev(fields->tab_names);
573 fields->tab_names = new_names;
576 const gchar **
577 purple_request_fields_get_tab_names(const PurpleRequestFields *fields)
579 g_return_val_if_fail(fields != NULL, NULL);
581 return (const gchar **)fields->tab_names;
584 gboolean
585 purple_request_fields_exists(const PurpleRequestFields *fields, const char *id)
587 g_return_val_if_fail(fields != NULL, FALSE);
588 g_return_val_if_fail(id != NULL, FALSE);
590 return (g_hash_table_lookup(fields->fields, id) != NULL);
593 const GList *
594 purple_request_fields_get_required(const PurpleRequestFields *fields)
596 g_return_val_if_fail(fields != NULL, NULL);
598 return fields->required_fields;
601 const GList *
602 purple_request_fields_get_validatable(const PurpleRequestFields *fields)
604 g_return_val_if_fail(fields != NULL, NULL);
606 return fields->validated_fields;
609 const GList *
610 purple_request_fields_get_autosensitive(const PurpleRequestFields *fields)
612 g_return_val_if_fail(fields != NULL, NULL);
614 return fields->autosensitive_fields;
617 gboolean
618 purple_request_fields_is_field_required(const PurpleRequestFields *fields,
619 const char *id)
621 PurpleRequestField *field;
623 g_return_val_if_fail(fields != NULL, FALSE);
624 g_return_val_if_fail(id != NULL, FALSE);
626 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
627 return FALSE;
629 return purple_request_field_is_required(field);
632 gpointer
633 purple_request_field_get_ui_data(const PurpleRequestField *field)
635 g_return_val_if_fail(field != NULL, NULL);
637 return field->ui_data;
640 void
641 purple_request_field_set_ui_data(PurpleRequestField *field,
642 gpointer ui_data)
644 g_return_if_fail(field != NULL);
646 field->ui_data = ui_data;
649 gboolean
650 purple_request_fields_all_required_filled(const PurpleRequestFields *fields)
652 GList *l;
654 g_return_val_if_fail(fields != NULL, FALSE);
656 for (l = fields->required_fields; l != NULL; l = l->next)
658 PurpleRequestField *field = (PurpleRequestField *)l->data;
660 if (!purple_request_field_is_filled(field))
661 return FALSE;
664 return TRUE;
667 gboolean
668 purple_request_fields_all_valid(const PurpleRequestFields *fields)
670 GList *l;
672 g_return_val_if_fail(fields != NULL, FALSE);
674 for (l = fields->validated_fields; l != NULL; l = l->next)
676 PurpleRequestField *field = (PurpleRequestField *)l->data;
678 if (!purple_request_field_is_valid(field, NULL))
679 return FALSE;
682 return TRUE;
685 static void
686 purple_request_fields_check_sensitivity(PurpleRequestFields *fields)
688 GList *it;
690 g_return_if_fail(fields != NULL);
692 for (it = fields->autosensitive_fields; it; it = g_list_next(it)) {
693 PurpleRequestField *field = it->data;
695 if (field->sensitivity_cb == NULL) {
696 g_warn_if_reached();
697 continue;
700 purple_request_field_set_sensitive(field,
701 field->sensitivity_cb(field));
705 static void
706 purple_request_fields_check_others_sensitivity(PurpleRequestField *field)
708 g_return_if_fail(field != NULL);
710 if (field->group == NULL || field->group->fields_list == NULL)
711 return;
713 purple_request_fields_check_sensitivity(field->group->fields_list);
716 PurpleRequestField *
717 purple_request_fields_get_field(const PurpleRequestFields *fields, const char *id)
719 PurpleRequestField *field;
721 g_return_val_if_fail(fields != NULL, NULL);
722 g_return_val_if_fail(id != NULL, NULL);
724 field = g_hash_table_lookup(fields->fields, id);
726 g_return_val_if_fail(field != NULL, NULL);
728 return field;
731 const char *
732 purple_request_fields_get_string(const PurpleRequestFields *fields, const char *id)
734 PurpleRequestField *field;
736 g_return_val_if_fail(fields != NULL, NULL);
737 g_return_val_if_fail(id != NULL, NULL);
739 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
740 return NULL;
742 return purple_request_field_string_get_value(field);
746 purple_request_fields_get_integer(const PurpleRequestFields *fields,
747 const char *id)
749 PurpleRequestField *field;
751 g_return_val_if_fail(fields != NULL, 0);
752 g_return_val_if_fail(id != NULL, 0);
754 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
755 return 0;
757 return purple_request_field_int_get_value(field);
760 gboolean
761 purple_request_fields_get_bool(const PurpleRequestFields *fields, const char *id)
763 PurpleRequestField *field;
765 g_return_val_if_fail(fields != NULL, FALSE);
766 g_return_val_if_fail(id != NULL, FALSE);
768 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
769 return FALSE;
771 return purple_request_field_bool_get_value(field);
774 gpointer
775 purple_request_fields_get_choice(const PurpleRequestFields *fields,
776 const char *id)
778 PurpleRequestField *field;
780 g_return_val_if_fail(fields != NULL, NULL);
781 g_return_val_if_fail(id != NULL, NULL);
783 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
784 return NULL;
786 return purple_request_field_choice_get_value(field);
789 PurpleAccount *
790 purple_request_fields_get_account(const PurpleRequestFields *fields,
791 const char *id)
793 PurpleRequestField *field;
795 g_return_val_if_fail(fields != NULL, NULL);
796 g_return_val_if_fail(id != NULL, NULL);
798 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
799 return NULL;
801 return purple_request_field_account_get_value(field);
804 gpointer purple_request_fields_get_ui_data(const PurpleRequestFields *fields)
806 g_return_val_if_fail(fields != NULL, NULL);
808 return fields->ui_data;
811 void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data)
813 g_return_if_fail(fields != NULL);
815 fields->ui_data = ui_data;
818 PurpleRequestFieldGroup *
819 purple_request_field_group_new(const char *title)
821 PurpleRequestFieldGroup *group;
823 group = g_new0(PurpleRequestFieldGroup, 1);
825 group->title = g_strdup(title);
827 return group;
830 void
831 purple_request_field_group_set_tab(PurpleRequestFieldGroup *group, guint tab_no)
833 g_return_if_fail(group != NULL);
835 group->tab_no = tab_no;
838 guint
839 purple_request_field_group_get_tab(const PurpleRequestFieldGroup *group)
841 return group->tab_no;
844 void
845 purple_request_field_group_destroy(PurpleRequestFieldGroup *group)
847 g_return_if_fail(group != NULL);
849 g_free(group->title);
851 g_list_foreach(group->fields, (GFunc)purple_request_field_destroy, NULL);
852 g_list_free(group->fields);
854 g_free(group);
857 void
858 purple_request_field_group_add_field(PurpleRequestFieldGroup *group,
859 PurpleRequestField *field)
861 g_return_if_fail(group != NULL);
862 g_return_if_fail(field != NULL);
864 group->fields = g_list_append(group->fields, field);
866 if (group->fields_list != NULL)
868 g_hash_table_insert(group->fields_list->fields,
869 g_strdup(purple_request_field_get_id(field)), field);
871 if (purple_request_field_is_required(field))
873 group->fields_list->required_fields =
874 g_list_append(group->fields_list->required_fields, field);
877 if (purple_request_field_is_validatable(field))
879 group->fields_list->validated_fields =
880 g_list_append(group->fields_list->validated_fields, field);
883 if (field->sensitivity_cb != NULL)
885 group->fields_list->autosensitive_fields =
886 g_list_append(group->fields_list->autosensitive_fields, field);
890 field->group = group;
894 const char *
895 purple_request_field_group_get_title(const PurpleRequestFieldGroup *group)
897 g_return_val_if_fail(group != NULL, NULL);
899 return group->title;
902 GList *
903 purple_request_field_group_get_fields(const PurpleRequestFieldGroup *group)
905 g_return_val_if_fail(group != NULL, NULL);
907 return group->fields;
910 PurpleRequestFields *
911 purple_request_field_group_get_fields_list(const PurpleRequestFieldGroup *group)
913 g_return_val_if_fail(group != NULL, NULL);
915 return group->fields_list;
918 PurpleRequestField *
919 purple_request_field_new(const char *id, const char *text,
920 PurpleRequestFieldType type)
922 PurpleRequestField *field;
924 g_return_val_if_fail(id != NULL, NULL);
925 g_return_val_if_fail(type != PURPLE_REQUEST_FIELD_NONE, NULL);
927 field = g_new0(PurpleRequestField, 1);
929 field->id = g_strdup(id);
930 field->type = type;
932 purple_request_field_set_label(field, text);
933 purple_request_field_set_visible(field, TRUE);
934 purple_request_field_set_sensitive(field, TRUE);
936 return field;
939 void
940 purple_request_field_destroy(PurpleRequestField *field)
942 g_return_if_fail(field != NULL);
944 g_free(field->id);
945 g_free(field->label);
946 g_free(field->type_hint);
947 g_free(field->tooltip);
949 if (field->type == PURPLE_REQUEST_FIELD_STRING)
951 g_free(field->u.string.default_value);
952 g_free(field->u.string.value);
954 else if (field->type == PURPLE_REQUEST_FIELD_CHOICE)
956 if (field->u.choice.elements != NULL)
958 GList *it = field->u.choice.elements;
959 while (it != NULL) {
960 g_free(it->data);
961 it = g_list_next(it); /* value */
962 if (it == NULL) {
963 g_warn_if_reached();
964 break;
966 if (it->data && field->u.choice.data_destroy)
967 field->u.choice.data_destroy(it->data);
968 it = g_list_next(it); /* next label */
970 g_list_free(field->u.choice.elements);
973 else if (field->type == PURPLE_REQUEST_FIELD_LIST)
975 if (field->u.list.items != NULL)
977 g_list_foreach(field->u.list.items, (GFunc)g_free, NULL);
978 g_list_free(field->u.list.items);
981 if (field->u.list.selected != NULL)
983 g_list_foreach(field->u.list.selected, (GFunc)g_free, NULL);
984 g_list_free(field->u.list.selected);
987 g_hash_table_destroy(field->u.list.item_data);
988 g_hash_table_destroy(field->u.list.selected_table);
990 else if (field->type == PURPLE_REQUEST_FIELD_DATASHEET)
992 purple_request_datasheet_free(field->u.datasheet.sheet);
995 g_free(field);
998 void
999 purple_request_field_set_label(PurpleRequestField *field, const char *label)
1001 g_return_if_fail(field != NULL);
1003 g_free(field->label);
1004 field->label = g_strdup(label);
1007 void
1008 purple_request_field_set_visible(PurpleRequestField *field, gboolean visible)
1010 g_return_if_fail(field != NULL);
1012 field->visible = visible;
1015 void
1016 purple_request_field_set_type_hint(PurpleRequestField *field,
1017 const char *type_hint)
1019 g_return_if_fail(field != NULL);
1021 g_free(field->type_hint);
1022 field->type_hint = g_strdup(type_hint);
1025 void
1026 purple_request_field_set_tooltip(PurpleRequestField *field, const char *tooltip)
1028 g_return_if_fail(field != NULL);
1030 g_free(field->tooltip);
1031 field->tooltip = g_strdup(tooltip);
1034 void
1035 purple_request_field_set_required(PurpleRequestField *field, gboolean required)
1037 g_return_if_fail(field != NULL);
1039 if (field->required == required)
1040 return;
1042 field->required = required;
1044 if (field->group != NULL)
1046 if (required)
1048 field->group->fields_list->required_fields =
1049 g_list_append(field->group->fields_list->required_fields,
1050 field);
1052 else
1054 field->group->fields_list->required_fields =
1055 g_list_remove(field->group->fields_list->required_fields,
1056 field);
1061 PurpleRequestFieldType
1062 purple_request_field_get_field_type(const PurpleRequestField *field)
1064 g_return_val_if_fail(field != NULL, PURPLE_REQUEST_FIELD_NONE);
1066 return field->type;
1069 PurpleRequestFieldGroup *
1070 purple_request_field_get_group(const PurpleRequestField *field)
1072 g_return_val_if_fail(field != NULL, NULL);
1074 return field->group;
1077 const char *
1078 purple_request_field_get_id(const PurpleRequestField *field)
1080 g_return_val_if_fail(field != NULL, NULL);
1082 return field->id;
1085 const char *
1086 purple_request_field_get_label(const PurpleRequestField *field)
1088 g_return_val_if_fail(field != NULL, NULL);
1090 return field->label;
1093 gboolean
1094 purple_request_field_is_visible(const PurpleRequestField *field)
1096 g_return_val_if_fail(field != NULL, FALSE);
1098 return field->visible;
1101 const char *
1102 purple_request_field_get_field_type_hint(const PurpleRequestField *field)
1104 g_return_val_if_fail(field != NULL, NULL);
1106 return field->type_hint;
1109 const char *
1110 purple_request_field_get_tooltip(const PurpleRequestField *field)
1112 g_return_val_if_fail(field != NULL, NULL);
1114 return field->tooltip;
1117 gboolean
1118 purple_request_field_is_required(const PurpleRequestField *field)
1120 g_return_val_if_fail(field != NULL, FALSE);
1122 return field->required;
1125 gboolean
1126 purple_request_field_is_filled(const PurpleRequestField *field)
1128 g_return_val_if_fail(field != NULL, FALSE);
1130 switch (purple_request_field_get_field_type(field))
1132 case PURPLE_REQUEST_FIELD_STRING:
1133 return (purple_request_field_string_get_value(field) != NULL &&
1134 *(purple_request_field_string_get_value(field)) != '\0');
1135 default:
1136 return TRUE;
1140 void
1141 purple_request_field_set_validator(PurpleRequestField *field,
1142 PurpleRequestFieldValidator validator, void *user_data)
1144 g_return_if_fail(field != NULL);
1146 field->validator = validator;
1147 field->validator_data = validator ? user_data : NULL;
1149 if (field->group != NULL)
1151 PurpleRequestFields *flist = field->group->fields_list;
1152 flist->validated_fields = g_list_remove(flist->validated_fields,
1153 field);
1154 if (validator)
1156 flist->validated_fields = g_list_append(
1157 flist->validated_fields, field);
1162 gboolean
1163 purple_request_field_is_validatable(PurpleRequestField *field)
1165 g_return_val_if_fail(field != NULL, FALSE);
1167 return field->validator != NULL;
1170 gboolean
1171 purple_request_field_is_valid(PurpleRequestField *field, gchar **errmsg)
1173 gboolean valid;
1175 g_return_val_if_fail(field != NULL, FALSE);
1177 if (!field->validator)
1178 return TRUE;
1180 if (!purple_request_field_is_required(field) &&
1181 !purple_request_field_is_filled(field))
1182 return TRUE;
1184 valid = field->validator(field, errmsg, field->validator_data);
1186 if (valid && errmsg)
1187 *errmsg = NULL;
1189 return valid;
1192 void
1193 purple_request_field_set_sensitive(PurpleRequestField *field,
1194 gboolean sensitive)
1196 g_return_if_fail(field != NULL);
1198 field->sensitive = sensitive;
1201 gboolean
1202 purple_request_field_is_sensitive(PurpleRequestField *field)
1204 g_return_val_if_fail(field != NULL, FALSE);
1206 return field->sensitive;
1209 void
1210 purple_request_field_set_sensitivity_cb(PurpleRequestField *field,
1211 PurpleRequestFieldSensitivityCb cb)
1213 PurpleRequestFields *flist;
1215 g_return_if_fail(field != NULL);
1217 field->sensitivity_cb = cb;
1219 if (!field->group || !field->group->fields_list)
1220 return;
1221 flist = field->group->fields_list;
1222 flist->autosensitive_fields = g_list_remove(flist->autosensitive_fields,
1223 field);
1224 if (cb != NULL)
1226 flist->autosensitive_fields = g_list_append(
1227 flist->autosensitive_fields, field);
1231 PurpleRequestField *
1232 purple_request_field_string_new(const char *id, const char *text,
1233 const char *default_value, gboolean multiline)
1235 PurpleRequestField *field;
1237 g_return_val_if_fail(id != NULL, NULL);
1238 g_return_val_if_fail(text != NULL, NULL);
1240 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_STRING);
1242 field->u.string.multiline = multiline;
1244 purple_request_field_string_set_default_value(field, default_value);
1245 purple_request_field_string_set_value(field, default_value);
1247 return field;
1250 void
1251 purple_request_field_string_set_default_value(PurpleRequestField *field,
1252 const char *default_value)
1254 g_return_if_fail(field != NULL);
1255 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
1257 g_free(field->u.string.default_value);
1258 field->u.string.default_value = g_strdup(default_value);
1261 void
1262 purple_request_field_string_set_value(PurpleRequestField *field, const char *value)
1264 g_return_if_fail(field != NULL);
1265 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
1267 g_free(field->u.string.value);
1268 field->u.string.value = g_strdup(value);
1270 purple_request_fields_check_others_sensitivity(field);
1273 void
1274 purple_request_field_string_set_masked(PurpleRequestField *field, gboolean masked)
1276 g_return_if_fail(field != NULL);
1277 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
1279 field->u.string.masked = masked;
1282 const char *
1283 purple_request_field_string_get_default_value(const PurpleRequestField *field)
1285 g_return_val_if_fail(field != NULL, NULL);
1286 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, NULL);
1288 return field->u.string.default_value;
1291 const char *
1292 purple_request_field_string_get_value(const PurpleRequestField *field)
1294 g_return_val_if_fail(field != NULL, NULL);
1295 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, NULL);
1297 return field->u.string.value;
1300 gboolean
1301 purple_request_field_string_is_multiline(const PurpleRequestField *field)
1303 g_return_val_if_fail(field != NULL, FALSE);
1304 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
1306 return field->u.string.multiline;
1309 gboolean
1310 purple_request_field_string_is_masked(const PurpleRequestField *field)
1312 g_return_val_if_fail(field != NULL, FALSE);
1313 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
1315 return field->u.string.masked;
1318 PurpleRequestField *
1319 purple_request_field_int_new(const char *id, const char *text,
1320 int default_value, int lower_bound, int upper_bound)
1322 PurpleRequestField *field;
1324 g_return_val_if_fail(id != NULL, NULL);
1325 g_return_val_if_fail(text != NULL, NULL);
1327 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_INTEGER);
1329 purple_request_field_int_set_lower_bound(field, lower_bound);
1330 purple_request_field_int_set_upper_bound(field, upper_bound);
1331 purple_request_field_int_set_default_value(field, default_value);
1332 purple_request_field_int_set_value(field, default_value);
1334 return field;
1337 void
1338 purple_request_field_int_set_default_value(PurpleRequestField *field,
1339 int default_value)
1341 g_return_if_fail(field != NULL);
1342 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1344 field->u.integer.default_value = default_value;
1347 void
1348 purple_request_field_int_set_lower_bound(PurpleRequestField *field,
1349 int lower_bound)
1351 g_return_if_fail(field != NULL);
1352 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1354 field->u.integer.lower_bound = lower_bound;
1357 void
1358 purple_request_field_int_set_upper_bound(PurpleRequestField *field,
1359 int upper_bound)
1361 g_return_if_fail(field != NULL);
1362 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1364 field->u.integer.upper_bound = upper_bound;
1367 void
1368 purple_request_field_int_set_value(PurpleRequestField *field, int value)
1370 g_return_if_fail(field != NULL);
1371 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
1373 if (value < field->u.integer.lower_bound ||
1374 value > field->u.integer.upper_bound) {
1375 purple_debug_error("request", "Int value out of bounds\n");
1376 return;
1379 field->u.integer.value = value;
1381 purple_request_fields_check_others_sensitivity(field);
1385 purple_request_field_int_get_default_value(const PurpleRequestField *field)
1387 g_return_val_if_fail(field != NULL, 0);
1388 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1390 return field->u.integer.default_value;
1394 purple_request_field_int_get_lower_bound(const PurpleRequestField *field)
1396 g_return_val_if_fail(field != NULL, 0);
1397 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1399 return field->u.integer.lower_bound;
1403 purple_request_field_int_get_upper_bound(const PurpleRequestField *field)
1405 g_return_val_if_fail(field != NULL, 0);
1406 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1408 return field->u.integer.upper_bound;
1412 purple_request_field_int_get_value(const PurpleRequestField *field)
1414 g_return_val_if_fail(field != NULL, 0);
1415 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
1417 return field->u.integer.value;
1420 PurpleRequestField *
1421 purple_request_field_bool_new(const char *id, const char *text,
1422 gboolean default_value)
1424 PurpleRequestField *field;
1426 g_return_val_if_fail(id != NULL, NULL);
1427 g_return_val_if_fail(text != NULL, NULL);
1429 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_BOOLEAN);
1431 purple_request_field_bool_set_default_value(field, default_value);
1432 purple_request_field_bool_set_value(field, default_value);
1434 return field;
1437 void
1438 purple_request_field_bool_set_default_value(PurpleRequestField *field,
1439 gboolean default_value)
1441 g_return_if_fail(field != NULL);
1442 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN);
1444 field->u.boolean.default_value = default_value;
1447 void
1448 purple_request_field_bool_set_value(PurpleRequestField *field, gboolean value)
1450 g_return_if_fail(field != NULL);
1451 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN);
1453 field->u.boolean.value = value;
1455 purple_request_fields_check_others_sensitivity(field);
1458 gboolean
1459 purple_request_field_bool_get_default_value(const PurpleRequestField *field)
1461 g_return_val_if_fail(field != NULL, FALSE);
1462 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN, FALSE);
1464 return field->u.boolean.default_value;
1467 gboolean
1468 purple_request_field_bool_get_value(const PurpleRequestField *field)
1470 g_return_val_if_fail(field != NULL, FALSE);
1471 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN, FALSE);
1473 return field->u.boolean.value;
1476 PurpleRequestField *
1477 purple_request_field_choice_new(const char *id, const char *text,
1478 gpointer default_value)
1480 PurpleRequestField *field;
1482 g_return_val_if_fail(id != NULL, NULL);
1483 g_return_val_if_fail(text != NULL, NULL);
1485 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_CHOICE);
1487 purple_request_field_choice_set_default_value(field, default_value);
1488 purple_request_field_choice_set_value(field, default_value);
1490 return field;
1493 void
1494 purple_request_field_choice_add(PurpleRequestField *field, const char *label,
1495 gpointer value)
1497 g_return_if_fail(field != NULL);
1498 g_return_if_fail(label != NULL);
1499 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1501 field->u.choice.elements = g_list_append(field->u.choice.elements,
1502 g_strdup(label));
1503 field->u.choice.elements = g_list_append(field->u.choice.elements,
1504 value);
1507 void
1508 purple_request_field_choice_set_default_value(PurpleRequestField *field,
1509 gpointer default_value)
1511 g_return_if_fail(field != NULL);
1512 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1514 field->u.choice.default_value = default_value;
1517 void
1518 purple_request_field_choice_set_value(PurpleRequestField *field, gpointer value)
1520 g_return_if_fail(field != NULL);
1521 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1523 field->u.choice.value = value;
1525 purple_request_fields_check_others_sensitivity(field);
1528 gpointer
1529 purple_request_field_choice_get_default_value(const PurpleRequestField *field)
1531 g_return_val_if_fail(field != NULL, NULL);
1532 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, NULL);
1534 return field->u.choice.default_value;
1537 gpointer
1538 purple_request_field_choice_get_value(const PurpleRequestField *field)
1540 g_return_val_if_fail(field != NULL, NULL);
1541 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, NULL);
1543 return field->u.choice.value;
1546 GList *
1547 purple_request_field_choice_get_elements(const PurpleRequestField *field)
1549 g_return_val_if_fail(field != NULL, NULL);
1550 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, NULL);
1552 return field->u.choice.elements;
1555 void
1556 purple_request_field_choice_set_data_destructor(PurpleRequestField *field,
1557 GDestroyNotify destroy)
1559 g_return_if_fail(field != NULL);
1560 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
1562 field->u.choice.data_destroy = destroy;
1565 PurpleRequestField *
1566 purple_request_field_list_new(const char *id, const char *text)
1568 PurpleRequestField *field;
1570 g_return_val_if_fail(id != NULL, NULL);
1572 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_LIST);
1574 field->u.list.item_data = g_hash_table_new_full(g_str_hash, g_str_equal,
1575 g_free, NULL);
1577 field->u.list.selected_table =
1578 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1580 return field;
1583 void
1584 purple_request_field_list_set_multi_select(PurpleRequestField *field,
1585 gboolean multi_select)
1587 g_return_if_fail(field != NULL);
1588 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1590 field->u.list.multiple_selection = multi_select;
1593 gboolean
1594 purple_request_field_list_get_multi_select(const PurpleRequestField *field)
1596 g_return_val_if_fail(field != NULL, FALSE);
1597 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, FALSE);
1599 return field->u.list.multiple_selection;
1602 void *
1603 purple_request_field_list_get_data(const PurpleRequestField *field,
1604 const char *text)
1606 g_return_val_if_fail(field != NULL, NULL);
1607 g_return_val_if_fail(text != NULL, NULL);
1608 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1610 return g_hash_table_lookup(field->u.list.item_data, text);
1613 void
1614 purple_request_field_list_add_icon(PurpleRequestField *field, const char *item, const char* icon_path,
1615 void *data)
1617 g_return_if_fail(field != NULL);
1618 g_return_if_fail(item != NULL);
1619 g_return_if_fail(data != NULL);
1620 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1622 if (icon_path)
1624 if (field->u.list.icons == NULL)
1626 GList *l;
1627 for (l = field->u.list.items ; l != NULL ; l = l->next)
1629 /* Order doesn't matter, because we're just
1630 * filing in blank items. So, we use
1631 * g_list_prepend() because it's faster. */
1632 field->u.list.icons = g_list_prepend(field->u.list.icons, NULL);
1635 field->u.list.icons = g_list_append(field->u.list.icons, g_strdup(icon_path));
1637 else if (field->u.list.icons)
1639 /* Keep this even with the items list. */
1640 field->u.list.icons = g_list_append(field->u.list.icons, NULL);
1643 field->u.list.items = g_list_append(field->u.list.items, g_strdup(item));
1644 g_hash_table_insert(field->u.list.item_data, g_strdup(item), data);
1647 void
1648 purple_request_field_list_add_selected(PurpleRequestField *field, const char *item)
1650 g_return_if_fail(field != NULL);
1651 g_return_if_fail(item != NULL);
1652 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1654 if (!purple_request_field_list_get_multi_select(field) &&
1655 field->u.list.selected != NULL)
1657 purple_debug_warning("request",
1658 "More than one item added to non-multi-select "
1659 "field %s\n",
1660 purple_request_field_get_id(field));
1661 return;
1664 field->u.list.selected = g_list_append(field->u.list.selected,
1665 g_strdup(item));
1667 g_hash_table_insert(field->u.list.selected_table, g_strdup(item), NULL);
1670 void
1671 purple_request_field_list_clear_selected(PurpleRequestField *field)
1673 g_return_if_fail(field != NULL);
1674 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1676 if (field->u.list.selected != NULL)
1678 g_list_foreach(field->u.list.selected, (GFunc)g_free, NULL);
1679 g_list_free(field->u.list.selected);
1680 field->u.list.selected = NULL;
1683 g_hash_table_destroy(field->u.list.selected_table);
1685 field->u.list.selected_table =
1686 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1689 void
1690 purple_request_field_list_set_selected(PurpleRequestField *field, GList *items)
1692 GList *l;
1694 g_return_if_fail(field != NULL);
1695 g_return_if_fail(items != NULL);
1696 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
1698 purple_request_field_list_clear_selected(field);
1700 if (!purple_request_field_list_get_multi_select(field) &&
1701 items && items->next)
1703 purple_debug_warning("request",
1704 "More than one item added to non-multi-select "
1705 "field %s\n",
1706 purple_request_field_get_id(field));
1707 return;
1710 for (l = items; l != NULL; l = l->next)
1712 field->u.list.selected = g_list_append(field->u.list.selected,
1713 g_strdup(l->data));
1714 g_hash_table_insert(field->u.list.selected_table,
1715 g_strdup((char *)l->data), NULL);
1719 gboolean
1720 purple_request_field_list_is_selected(const PurpleRequestField *field,
1721 const char *item)
1723 g_return_val_if_fail(field != NULL, FALSE);
1724 g_return_val_if_fail(item != NULL, FALSE);
1725 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, FALSE);
1727 return g_hash_table_lookup_extended(field->u.list.selected_table,
1728 item, NULL, NULL);
1731 GList *
1732 purple_request_field_list_get_selected(const PurpleRequestField *field)
1734 g_return_val_if_fail(field != NULL, NULL);
1735 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1737 return field->u.list.selected;
1740 GList *
1741 purple_request_field_list_get_items(const PurpleRequestField *field)
1743 g_return_val_if_fail(field != NULL, NULL);
1744 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1746 return field->u.list.items;
1749 GList *
1750 purple_request_field_list_get_icons(const PurpleRequestField *field)
1752 g_return_val_if_fail(field != NULL, NULL);
1753 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
1755 return field->u.list.icons;
1758 PurpleRequestField *
1759 purple_request_field_label_new(const char *id, const char *text)
1761 PurpleRequestField *field;
1763 g_return_val_if_fail(id != NULL, NULL);
1764 g_return_val_if_fail(text != NULL, NULL);
1766 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_LABEL);
1768 return field;
1771 PurpleRequestField *
1772 purple_request_field_image_new(const char *id, const char *text, const char *buf, gsize size)
1774 PurpleRequestField *field;
1776 g_return_val_if_fail(id != NULL, NULL);
1777 g_return_val_if_fail(text != NULL, NULL);
1778 g_return_val_if_fail(buf != NULL, NULL);
1779 g_return_val_if_fail(size > 0, NULL);
1781 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_IMAGE);
1783 field->u.image.buffer = g_memdup(buf, size);
1784 field->u.image.size = size;
1785 field->u.image.scale_x = 1;
1786 field->u.image.scale_y = 1;
1788 return field;
1791 void
1792 purple_request_field_image_set_scale(PurpleRequestField *field, unsigned int x, unsigned int y)
1794 g_return_if_fail(field != NULL);
1795 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE);
1797 field->u.image.scale_x = x;
1798 field->u.image.scale_y = y;
1801 const char *
1802 purple_request_field_image_get_buffer(PurpleRequestField *field)
1804 g_return_val_if_fail(field != NULL, NULL);
1805 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, NULL);
1807 return field->u.image.buffer;
1810 gsize
1811 purple_request_field_image_get_size(PurpleRequestField *field)
1813 g_return_val_if_fail(field != NULL, 0);
1814 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1816 return field->u.image.size;
1819 unsigned int
1820 purple_request_field_image_get_scale_x(PurpleRequestField *field)
1822 g_return_val_if_fail(field != NULL, 0);
1823 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1825 return field->u.image.scale_x;
1828 unsigned int
1829 purple_request_field_image_get_scale_y(PurpleRequestField *field)
1831 g_return_val_if_fail(field != NULL, 0);
1832 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1834 return field->u.image.scale_y;
1837 PurpleRequestField *
1838 purple_request_field_account_new(const char *id, const char *text,
1839 PurpleAccount *account)
1841 PurpleRequestField *field;
1843 g_return_val_if_fail(id != NULL, NULL);
1844 g_return_val_if_fail(text != NULL, NULL);
1846 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_ACCOUNT);
1848 if (account == NULL && purple_connections_get_all() != NULL)
1850 account = purple_connection_get_account(
1851 (PurpleConnection *)purple_connections_get_all()->data);
1854 purple_request_field_account_set_default_value(field, account);
1855 purple_request_field_account_set_value(field, account);
1857 return field;
1860 void
1861 purple_request_field_account_set_default_value(PurpleRequestField *field,
1862 PurpleAccount *default_value)
1864 g_return_if_fail(field != NULL);
1865 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1867 field->u.account.default_account = default_value;
1870 void
1871 purple_request_field_account_set_value(PurpleRequestField *field,
1872 PurpleAccount *value)
1874 g_return_if_fail(field != NULL);
1875 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1877 field->u.account.account = value;
1879 purple_request_fields_check_others_sensitivity(field);
1882 void
1883 purple_request_field_account_set_show_all(PurpleRequestField *field,
1884 gboolean show_all)
1886 g_return_if_fail(field != NULL);
1887 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1889 if (field->u.account.show_all == show_all)
1890 return;
1892 field->u.account.show_all = show_all;
1894 if (!show_all)
1896 if (purple_account_is_connected(field->u.account.default_account))
1898 purple_request_field_account_set_default_value(field,
1899 (PurpleAccount *)purple_connections_get_all()->data);
1902 if (purple_account_is_connected(field->u.account.account))
1904 purple_request_field_account_set_value(field,
1905 (PurpleAccount *)purple_connections_get_all()->data);
1910 void
1911 purple_request_field_account_set_filter(PurpleRequestField *field,
1912 PurpleFilterAccountFunc filter_func)
1914 g_return_if_fail(field != NULL);
1915 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1917 field->u.account.filter_func = filter_func;
1920 PurpleAccount *
1921 purple_request_field_account_get_default_value(const PurpleRequestField *field)
1923 g_return_val_if_fail(field != NULL, NULL);
1924 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, NULL);
1926 return field->u.account.default_account;
1929 PurpleAccount *
1930 purple_request_field_account_get_value(const PurpleRequestField *field)
1932 g_return_val_if_fail(field != NULL, NULL);
1933 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, NULL);
1935 return field->u.account.account;
1938 gboolean
1939 purple_request_field_account_get_show_all(const PurpleRequestField *field)
1941 g_return_val_if_fail(field != NULL, FALSE);
1942 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, FALSE);
1944 return field->u.account.show_all;
1947 PurpleFilterAccountFunc
1948 purple_request_field_account_get_filter(const PurpleRequestField *field)
1950 g_return_val_if_fail(field != NULL, FALSE);
1951 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, FALSE);
1953 return field->u.account.filter_func;
1956 PurpleRequestField *
1957 purple_request_field_certificate_new(const char *id, const char *text, GTlsCertificate *cert)
1959 PurpleRequestField *field;
1961 g_return_val_if_fail(id != NULL, NULL);
1962 g_return_val_if_fail(text != NULL, NULL);
1963 g_return_val_if_fail(cert != NULL, NULL);
1965 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_CERTIFICATE);
1967 field->u.certificate.cert = cert;
1969 return field;
1972 GTlsCertificate *
1973 purple_request_field_certificate_get_value(const PurpleRequestField *field)
1975 g_return_val_if_fail(field != NULL, NULL);
1976 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CERTIFICATE, NULL);
1978 return field->u.certificate.cert;
1981 PurpleRequestField *
1982 purple_request_field_datasheet_new(const char *id,
1983 const gchar *text, PurpleRequestDatasheet *sheet)
1985 PurpleRequestField *field;
1987 g_return_val_if_fail(id != NULL, NULL);
1988 g_return_val_if_fail(sheet != NULL, NULL);
1990 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_DATASHEET);
1992 field->u.datasheet.sheet = sheet;
1994 return field;
1997 PurpleRequestDatasheet *
1998 purple_request_field_datasheet_get_sheet(PurpleRequestField *field)
2000 g_return_val_if_fail(field != NULL, NULL);
2001 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_DATASHEET, NULL);
2003 return field->u.datasheet.sheet;
2006 /* -- */
2008 gboolean
2009 purple_request_field_email_validator(PurpleRequestField *field, gchar **errmsg,
2010 void *user_data)
2012 const char *value;
2014 g_return_val_if_fail(field != NULL, FALSE);
2015 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
2017 value = purple_request_field_string_get_value(field);
2019 if (value != NULL && purple_email_is_valid(value))
2020 return TRUE;
2022 if (errmsg)
2023 *errmsg = g_strdup(_("Invalid email address"));
2024 return FALSE;
2027 gboolean
2028 purple_request_field_alphanumeric_validator(PurpleRequestField *field,
2029 gchar **errmsg, void *allowed_characters)
2031 const char *value;
2032 gchar invalid_char = '\0';
2034 g_return_val_if_fail(field != NULL, FALSE);
2035 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
2037 value = purple_request_field_string_get_value(field);
2039 g_return_val_if_fail(value != NULL, FALSE);
2041 if (allowed_characters)
2043 gchar *value_r = g_strdup(value);
2044 g_strcanon(value_r, allowed_characters, '\0');
2045 invalid_char = value[strlen(value_r)];
2046 g_free(value_r);
2048 else
2050 while (value)
2052 if (!g_ascii_isalnum(*value))
2054 invalid_char = *value;
2055 break;
2057 value++;
2060 if (!invalid_char)
2061 return TRUE;
2063 if (errmsg)
2064 *errmsg = g_strdup_printf(_("Invalid character '%c'"),
2065 invalid_char);
2066 return FALSE;
2069 /* -- */
2071 static gchar *
2072 purple_request_strip_html_custom(const gchar *html)
2074 gchar *tmp, *ret;
2076 tmp = purple_strreplace(html, "\n", "<br>");
2077 ret = purple_markup_strip_html(tmp);
2078 g_free(tmp);
2080 return ret;
2083 static gchar **
2084 purple_request_strip_html(PurpleRequestCommonParameters *cpar,
2085 const char **primary, const char **secondary)
2087 PurpleRequestUiOps *ops = purple_request_get_ui_ops();
2088 gchar **ret;
2090 if (!purple_request_cpar_is_html(cpar))
2091 return NULL;
2092 if (ops->features & PURPLE_REQUEST_FEATURE_HTML)
2093 return NULL;
2095 ret = g_new0(gchar*, 3);
2096 *primary = ret[0] = purple_request_strip_html_custom(*primary);
2097 *secondary = ret[1] = purple_request_strip_html_custom(*secondary);
2099 return ret;
2102 void *
2103 purple_request_input(void *handle, const char *title, const char *primary,
2104 const char *secondary, const char *default_value,
2105 gboolean multiline, gboolean masked, gchar *hint,
2106 const char *ok_text, GCallback ok_cb,
2107 const char *cancel_text, GCallback cancel_cb,
2108 PurpleRequestCommonParameters *cpar,
2109 void *user_data)
2111 PurpleRequestUiOps *ops;
2113 if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL)) {
2114 purple_request_cpar_unref(cpar);
2115 g_warn_if_fail(ok_text != NULL);
2116 g_warn_if_fail(ok_cb != NULL);
2117 g_return_val_if_reached(NULL);
2120 ops = purple_request_get_ui_ops();
2122 if (ops != NULL && ops->request_input != NULL) {
2123 PurpleRequestInfo *info;
2124 gchar **tmp;
2126 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2128 info = g_new0(PurpleRequestInfo, 1);
2129 info->type = PURPLE_REQUEST_INPUT;
2130 info->handle = handle;
2131 info->ui_handle = ops->request_input(title, primary, secondary,
2132 default_value, multiline, masked, hint, ok_text, ok_cb,
2133 cancel_text, cancel_cb, cpar, user_data);
2135 handles = g_list_append(handles, info);
2137 g_strfreev(tmp);
2138 purple_request_cpar_unref(cpar);
2139 return info->ui_handle;
2142 purple_request_cpar_unref(cpar);
2143 return NULL;
2146 void *
2147 purple_request_choice(void *handle, const char *title, const char *primary,
2148 const char *secondary, gpointer default_value, const char *ok_text,
2149 GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
2150 PurpleRequestCommonParameters *cpar, void *user_data, ...)
2152 void *ui_handle;
2153 va_list args;
2155 if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL)) {
2156 purple_request_cpar_unref(cpar);
2157 g_warn_if_fail(ok_text != NULL);
2158 g_warn_if_fail(ok_cb != NULL);
2159 g_return_val_if_reached(NULL);
2162 va_start(args, user_data);
2163 ui_handle = purple_request_choice_varg(handle, title, primary, secondary,
2164 default_value, ok_text, ok_cb,
2165 cancel_text, cancel_cb,
2166 cpar, user_data, args);
2167 va_end(args);
2169 return ui_handle;
2172 void *
2173 purple_request_choice_varg(void *handle, const char *title, const char *primary,
2174 const char *secondary, gpointer default_value, const char *ok_text,
2175 GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
2176 PurpleRequestCommonParameters *cpar, void *user_data, va_list choices)
2178 PurpleRequestUiOps *ops;
2180 if (G_UNLIKELY(ok_text == NULL || ok_cb == NULL ||
2181 cancel_text == NULL))
2183 purple_request_cpar_unref(cpar);
2184 g_warn_if_fail(ok_text != NULL);
2185 g_warn_if_fail(ok_cb != NULL);
2186 g_warn_if_fail(cancel_text != NULL);
2187 g_return_val_if_reached(NULL);
2190 ops = purple_request_get_ui_ops();
2192 if (ops != NULL && ops->request_choice != NULL) {
2193 PurpleRequestInfo *info;
2194 gchar **tmp;
2196 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2198 info = g_new0(PurpleRequestInfo, 1);
2199 info->type = PURPLE_REQUEST_CHOICE;
2200 info->handle = handle;
2201 info->ui_handle = ops->request_choice(title, primary, secondary,
2202 default_value, ok_text, ok_cb, cancel_text, cancel_cb,
2203 cpar, user_data, choices);
2205 handles = g_list_append(handles, info);
2207 g_strfreev(tmp);
2208 purple_request_cpar_unref(cpar);
2209 return info->ui_handle;
2212 purple_request_cpar_unref(cpar);
2213 return NULL;
2216 void *
2217 purple_request_action(void *handle, const char *title, const char *primary,
2218 const char *secondary, int default_action,
2219 PurpleRequestCommonParameters *cpar, void *user_data,
2220 size_t action_count, ...)
2222 void *ui_handle;
2223 va_list args;
2225 va_start(args, action_count);
2226 ui_handle = purple_request_action_varg(handle, title, primary,
2227 secondary, default_action, cpar, user_data, action_count, args);
2228 va_end(args);
2230 return ui_handle;
2233 void *
2234 purple_request_action_varg(void *handle, const char *title, const char *primary,
2235 const char *secondary, int default_action,
2236 PurpleRequestCommonParameters *cpar, void *user_data,
2237 size_t action_count, va_list actions)
2239 PurpleRequestUiOps *ops;
2241 ops = purple_request_get_ui_ops();
2243 if (ops != NULL && ops->request_action != NULL) {
2244 PurpleRequestInfo *info;
2245 gchar **tmp;
2247 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2249 info = g_new0(PurpleRequestInfo, 1);
2250 info->type = PURPLE_REQUEST_ACTION;
2251 info->handle = handle;
2252 info->ui_handle = ops->request_action(title, primary, secondary,
2253 default_action, cpar, user_data, action_count, actions);
2255 handles = g_list_append(handles, info);
2257 g_strfreev(tmp);
2258 purple_request_cpar_unref(cpar);
2259 return info->ui_handle;
2262 purple_request_cpar_unref(cpar);
2263 return NULL;
2266 void *
2267 purple_request_wait(void *handle, const char *title, const char *primary,
2268 const char *secondary, gboolean with_progress,
2269 PurpleRequestCancelCb cancel_cb, PurpleRequestCommonParameters *cpar,
2270 void *user_data)
2272 PurpleRequestUiOps *ops;
2274 if (primary == NULL)
2275 primary = _("Please wait...");
2277 ops = purple_request_get_ui_ops();
2279 if (ops != NULL && ops->request_wait != NULL) {
2280 PurpleRequestInfo *info;
2281 gchar **tmp;
2283 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2285 info = g_new0(PurpleRequestInfo, 1);
2286 info->type = PURPLE_REQUEST_WAIT;
2287 info->handle = handle;
2288 info->ui_handle = ops->request_wait(title, primary, secondary,
2289 with_progress, cancel_cb, cpar, user_data);
2291 handles = g_list_append(handles, info);
2293 g_strfreev(tmp);
2294 purple_request_cpar_unref(cpar);
2295 return info->ui_handle;
2298 if (cpar == NULL)
2299 cpar = purple_request_cpar_new();
2300 if (purple_request_cpar_get_icon(cpar) == PURPLE_REQUEST_ICON_DEFAULT)
2301 purple_request_cpar_set_icon(cpar, PURPLE_REQUEST_ICON_WAIT);
2303 return purple_request_action(handle, title, primary, secondary,
2304 PURPLE_DEFAULT_ACTION_NONE, cpar, user_data,
2305 cancel_cb ? 1 : 0, _("Cancel"), cancel_cb);
2308 void
2309 purple_request_wait_pulse(void *ui_handle)
2311 PurpleRequestUiOps *ops;
2313 ops = purple_request_get_ui_ops();
2315 if (ops == NULL || ops->request_wait_update == NULL)
2316 return;
2318 ops->request_wait_update(ui_handle, TRUE, 0.0);
2321 void
2322 purple_request_wait_progress(void *ui_handle, gfloat fraction)
2324 PurpleRequestUiOps *ops;
2326 ops = purple_request_get_ui_ops();
2328 if (ops == NULL || ops->request_wait_update == NULL)
2329 return;
2331 if (fraction < 0.0 || fraction > 1.0) {
2332 purple_debug_warning("request", "Fraction parameter out of "
2333 "range: %f", fraction);
2334 if (fraction < 0.0)
2335 fraction = 0.0;
2336 else /* if (fraction > 1.0) */
2337 fraction = 1.0;
2340 ops->request_wait_update(ui_handle, FALSE, fraction);
2343 static void
2344 purple_request_fields_strip_html(PurpleRequestFields *fields)
2346 GList *itg;
2348 for (itg = fields->groups; itg != NULL; itg = g_list_next(itg)) {
2349 PurpleRequestFieldGroup *group = itg->data;
2350 GList *itf;
2352 for (itf = group->fields; itf != NULL; itf = g_list_next(itf)) {
2353 PurpleRequestField *field = itf->data;
2354 gchar *new_label;
2356 new_label = purple_request_strip_html_custom(
2357 field->label);
2358 if (g_strcmp0(new_label, field->label) == 0) {
2359 g_free(new_label);
2360 continue;
2362 g_free(field->label);
2363 field->label = new_label;
2368 void *
2369 purple_request_fields(void *handle, const char *title, const char *primary,
2370 const char *secondary, PurpleRequestFields *fields, const char *ok_text,
2371 GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
2372 PurpleRequestCommonParameters *cpar, void *user_data)
2374 PurpleRequestUiOps *ops;
2376 if (G_UNLIKELY(fields == NULL ||
2377 ((ok_text == NULL) != (ok_cb == NULL)) ||
2378 cancel_text == NULL))
2380 purple_request_cpar_unref(cpar);
2381 g_warn_if_fail(fields != NULL);
2382 g_warn_if_fail((ok_text == NULL) != (ok_cb == NULL));
2383 g_warn_if_fail(cancel_text != NULL);
2384 g_return_val_if_reached(NULL);
2387 ops = purple_request_get_ui_ops();
2389 if (purple_request_cpar_is_html(cpar) &&
2390 !((ops->features & PURPLE_REQUEST_FEATURE_HTML)))
2392 purple_request_fields_strip_html(fields);
2395 purple_request_fields_check_sensitivity(fields);
2397 if (ops != NULL && ops->request_fields != NULL) {
2398 PurpleRequestInfo *info;
2399 gchar **tmp;
2401 tmp = purple_request_strip_html(cpar, &primary, &secondary);
2403 info = g_new0(PurpleRequestInfo, 1);
2404 info->type = PURPLE_REQUEST_FIELDS;
2405 info->handle = handle;
2406 info->ui_handle = ops->request_fields(title, primary, secondary,
2407 fields, ok_text, ok_cb, cancel_text, cancel_cb,
2408 cpar, user_data);
2410 handles = g_list_append(handles, info);
2412 g_strfreev(tmp);
2413 purple_request_cpar_unref(cpar);
2414 return info->ui_handle;
2417 purple_request_cpar_unref(cpar);
2418 return NULL;
2421 void *
2422 purple_request_file(void *handle, const char *title, const char *filename,
2423 gboolean savedialog, GCallback ok_cb, GCallback cancel_cb,
2424 PurpleRequestCommonParameters *cpar, void *user_data)
2426 PurpleRequestUiOps *ops;
2428 ops = purple_request_get_ui_ops();
2430 if (ops != NULL && ops->request_file != NULL) {
2431 PurpleRequestInfo *info;
2433 info = g_new0(PurpleRequestInfo, 1);
2434 info->type = PURPLE_REQUEST_FILE;
2435 info->handle = handle;
2436 info->ui_handle = ops->request_file(title, filename, savedialog,
2437 ok_cb, cancel_cb, cpar, user_data);
2438 handles = g_list_append(handles, info);
2440 purple_request_cpar_unref(cpar);
2441 return info->ui_handle;
2444 purple_request_cpar_unref(cpar);
2445 return NULL;
2448 void *
2449 purple_request_folder(void *handle, const char *title, const char *dirname,
2450 GCallback ok_cb, GCallback cancel_cb,
2451 PurpleRequestCommonParameters *cpar, void *user_data)
2453 PurpleRequestUiOps *ops;
2455 ops = purple_request_get_ui_ops();
2457 if (ops != NULL && ops->request_file != NULL) {
2458 PurpleRequestInfo *info;
2460 info = g_new0(PurpleRequestInfo, 1);
2461 info->type = PURPLE_REQUEST_FOLDER;
2462 info->handle = handle;
2463 info->ui_handle = ops->request_folder(title, dirname, ok_cb,
2464 cancel_cb, cpar, user_data);
2465 handles = g_list_append(handles, info);
2467 purple_request_cpar_unref(cpar);
2468 return info->ui_handle;
2471 purple_request_cpar_unref(cpar);
2472 return NULL;
2475 void *
2476 purple_request_certificate(void *handle, const char *title,
2477 const char *primary, const char *secondary,
2478 GTlsCertificate *cert,
2479 const char *ok_text, GCallback ok_cb,
2480 const char *cancel_text, GCallback cancel_cb,
2481 void *user_data)
2483 PurpleRequestFields *fields;
2484 PurpleRequestFieldGroup *group;
2485 PurpleRequestField *field;
2487 fields = purple_request_fields_new();
2488 group = purple_request_field_group_new(NULL);
2489 purple_request_fields_add_group(fields, group);
2490 field = purple_request_field_certificate_new("certificate", "Certificate", cert);
2491 purple_request_field_group_add_field(group, field);
2493 return purple_request_fields(handle, title, primary, secondary, fields,
2494 ok_text, ok_cb, cancel_text, cancel_cb,
2495 NULL, user_data);
2498 gboolean
2499 purple_request_is_valid_ui_handle(void *ui_handle, PurpleRequestType *type)
2501 PurpleRequestInfo *info;
2503 if (ui_handle == NULL)
2504 return FALSE;
2506 info = purple_request_info_from_ui_handle(ui_handle);
2508 if (info == NULL)
2509 return FALSE;
2511 if (type != NULL)
2512 *type = info->type;
2514 return TRUE;
2517 void
2518 purple_request_add_close_notify(void *ui_handle, GDestroyNotify notify,
2519 gpointer notify_data)
2521 PurpleRequestInfo *info;
2522 PurpleRequestCloseNotified *notified;
2524 g_return_if_fail(ui_handle != NULL);
2525 g_return_if_fail(notify != NULL);
2527 info = purple_request_info_from_ui_handle(ui_handle);
2528 g_return_if_fail(info != NULL);
2530 notified = g_new0(PurpleRequestCloseNotified, 1);
2531 notified->cb = notify;
2532 notified->data = notify_data;
2534 info->notify_on_close = g_slist_append(info->notify_on_close, notified);
2537 static void
2538 purple_request_close_info(PurpleRequestInfo *info)
2540 PurpleRequestUiOps *ops;
2541 GSList *it;
2543 ops = purple_request_get_ui_ops();
2545 purple_notify_close_with_handle(info->ui_handle);
2546 purple_request_close_with_handle(info->ui_handle);
2548 if (ops != NULL && ops->close_request != NULL)
2549 ops->close_request(info->type, info->ui_handle);
2551 for (it = info->notify_on_close; it; it = g_slist_next(it)) {
2552 PurpleRequestCloseNotified *notify = it->data;
2554 notify->cb(notify->data);
2557 g_slist_free_full(info->notify_on_close, g_free);
2558 g_free(info);
2561 void
2562 purple_request_close(PurpleRequestType type, void *ui_handle)
2564 GList *l;
2566 g_return_if_fail(ui_handle != NULL);
2568 for (l = handles; l != NULL; l = l->next) {
2569 PurpleRequestInfo *info = l->data;
2571 if (info->ui_handle == ui_handle) {
2572 handles = g_list_remove(handles, info);
2573 purple_request_close_info(info);
2574 break;
2579 void
2580 purple_request_close_with_handle(void *handle)
2582 GList *l, *l_next;
2584 g_return_if_fail(handle != NULL);
2586 for (l = handles; l != NULL; l = l_next) {
2587 PurpleRequestInfo *info = l->data;
2589 l_next = l->next;
2591 if (info->handle == handle) {
2592 handles = g_list_remove(handles, info);
2593 purple_request_close_info(info);
2598 void
2599 purple_request_set_ui_ops(PurpleRequestUiOps *ops)
2601 request_ui_ops = ops;
2604 PurpleRequestUiOps *
2605 purple_request_get_ui_ops(void)
2607 return request_ui_ops;
2610 /**************************************************************************
2611 * GBoxed code
2612 **************************************************************************/
2613 static PurpleRequestUiOps *
2614 purple_request_ui_ops_copy(PurpleRequestUiOps *ops)
2616 PurpleRequestUiOps *ops_new;
2618 g_return_val_if_fail(ops != NULL, NULL);
2620 ops_new = g_new(PurpleRequestUiOps, 1);
2621 *ops_new = *ops;
2623 return ops_new;
2626 GType
2627 purple_request_ui_ops_get_type(void)
2629 static GType type = 0;
2631 if (type == 0) {
2632 type = g_boxed_type_register_static("PurpleRequestUiOps",
2633 (GBoxedCopyFunc)purple_request_ui_ops_copy,
2634 (GBoxedFreeFunc)g_free);
2637 return type;