1 /**
2 * @file request.c Request API
3 * @ingroup core
4 */
5
6 /* purple
7 *
8 * Purple is the legal property of its developers, whose names are too numerous
9 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * source distribution.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
25 */
26 #define _PURPLE_REQUEST_C_
27
28 #include "internal.h"
29
30 #include "glibcompat.h"
31 #include "notify.h"
32 #include "request.h"
33 #include "debug.h"
34
35 static PurpleRequestUiOps *request_ui_ops = NULL;
36 static GList *handles = NULL;
37
38 typedef struct
39 {
40 PurpleRequestType type;
41 void *handle;
42 void *ui_handle;
43
44 } PurpleRequestInfo;
45
46
47 PurpleRequestFields *
purple_request_fields_new(void)48 purple_request_fields_new(void)
49 {
50 PurpleRequestFields *fields;
51
52 fields = g_new0(PurpleRequestFields, 1);
53
54 fields->fields = g_hash_table_new_full(g_str_hash, g_str_equal,
55 g_free, NULL);
56
57 return fields;
58 }
59
60 void
purple_request_fields_destroy(PurpleRequestFields * fields)61 purple_request_fields_destroy(PurpleRequestFields *fields)
62 {
63 g_return_if_fail(fields != NULL);
64
65 g_list_free_full(fields->groups,
66 (GDestroyNotify)purple_request_field_group_destroy);
67 g_list_free(fields->required_fields);
68 g_hash_table_destroy(fields->fields);
69 g_free(fields);
70 }
71
72 void
purple_request_fields_add_group(PurpleRequestFields * fields,PurpleRequestFieldGroup * group)73 purple_request_fields_add_group(PurpleRequestFields *fields,
74 PurpleRequestFieldGroup *group)
75 {
76 GList *l;
77 PurpleRequestField *field;
78
79 g_return_if_fail(fields != NULL);
80 g_return_if_fail(group != NULL);
81
82 fields->groups = g_list_append(fields->groups, group);
83
84 group->fields_list = fields;
85
86 for (l = purple_request_field_group_get_fields(group);
87 l != NULL;
88 l = l->next) {
89
90 field = l->data;
91
92 g_hash_table_insert(fields->fields,
93 g_strdup(purple_request_field_get_id(field)), field);
94
95 if (purple_request_field_is_required(field)) {
96 fields->required_fields =
97 g_list_append(fields->required_fields, field);
98 }
99
100 }
101 }
102
103 GList *
purple_request_fields_get_groups(const PurpleRequestFields * fields)104 purple_request_fields_get_groups(const PurpleRequestFields *fields)
105 {
106 g_return_val_if_fail(fields != NULL, NULL);
107
108 return fields->groups;
109 }
110
111 gboolean
purple_request_fields_exists(const PurpleRequestFields * fields,const char * id)112 purple_request_fields_exists(const PurpleRequestFields *fields, const char *id)
113 {
114 g_return_val_if_fail(fields != NULL, FALSE);
115 g_return_val_if_fail(id != NULL, FALSE);
116
117 return (g_hash_table_lookup(fields->fields, id) != NULL);
118 }
119
120 GList *
purple_request_fields_get_required(const PurpleRequestFields * fields)121 purple_request_fields_get_required(const PurpleRequestFields *fields)
122 {
123 g_return_val_if_fail(fields != NULL, NULL);
124
125 return fields->required_fields;
126 }
127
128 gboolean
purple_request_fields_is_field_required(const PurpleRequestFields * fields,const char * id)129 purple_request_fields_is_field_required(const PurpleRequestFields *fields,
130 const char *id)
131 {
132 PurpleRequestField *field;
133
134 g_return_val_if_fail(fields != NULL, FALSE);
135 g_return_val_if_fail(id != NULL, FALSE);
136
137 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
138 return FALSE;
139
140 return purple_request_field_is_required(field);
141 }
142
143 gpointer
purple_request_field_get_ui_data(const PurpleRequestField * field)144 purple_request_field_get_ui_data(const PurpleRequestField *field)
145 {
146 g_return_val_if_fail(field != NULL, NULL);
147
148 return field->ui_data;
149 }
150
151 void
purple_request_field_set_ui_data(PurpleRequestField * field,gpointer ui_data)152 purple_request_field_set_ui_data(PurpleRequestField *field,
153 gpointer ui_data)
154 {
155 g_return_if_fail(field != NULL);
156
157 field->ui_data = ui_data;
158 }
159
160 gboolean
purple_request_fields_all_required_filled(const PurpleRequestFields * fields)161 purple_request_fields_all_required_filled(const PurpleRequestFields *fields)
162 {
163 GList *l;
164
165 g_return_val_if_fail(fields != NULL, FALSE);
166
167 for (l = fields->required_fields; l != NULL; l = l->next)
168 {
169 PurpleRequestField *field = (PurpleRequestField *)l->data;
170
171 switch (purple_request_field_get_type(field))
172 {
173 case PURPLE_REQUEST_FIELD_STRING:
174 if (purple_request_field_string_get_value(field) == NULL ||
175 *(purple_request_field_string_get_value(field)) == '\0')
176 return FALSE;
177
178 break;
179
180 default:
181 break;
182 }
183 }
184
185 return TRUE;
186 }
187
188 PurpleRequestField *
purple_request_fields_get_field(const PurpleRequestFields * fields,const char * id)189 purple_request_fields_get_field(const PurpleRequestFields *fields, const char *id)
190 {
191 PurpleRequestField *field;
192
193 g_return_val_if_fail(fields != NULL, NULL);
194 g_return_val_if_fail(id != NULL, NULL);
195
196 field = g_hash_table_lookup(fields->fields, id);
197
198 g_return_val_if_fail(field != NULL, NULL);
199
200 return field;
201 }
202
203 const char *
purple_request_fields_get_string(const PurpleRequestFields * fields,const char * id)204 purple_request_fields_get_string(const PurpleRequestFields *fields, const char *id)
205 {
206 PurpleRequestField *field;
207
208 g_return_val_if_fail(fields != NULL, NULL);
209 g_return_val_if_fail(id != NULL, NULL);
210
211 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
212 return NULL;
213
214 return purple_request_field_string_get_value(field);
215 }
216
217 int
purple_request_fields_get_integer(const PurpleRequestFields * fields,const char * id)218 purple_request_fields_get_integer(const PurpleRequestFields *fields,
219 const char *id)
220 {
221 PurpleRequestField *field;
222
223 g_return_val_if_fail(fields != NULL, 0);
224 g_return_val_if_fail(id != NULL, 0);
225
226 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
227 return 0;
228
229 return purple_request_field_int_get_value(field);
230 }
231
232 gboolean
purple_request_fields_get_bool(const PurpleRequestFields * fields,const char * id)233 purple_request_fields_get_bool(const PurpleRequestFields *fields, const char *id)
234 {
235 PurpleRequestField *field;
236
237 g_return_val_if_fail(fields != NULL, FALSE);
238 g_return_val_if_fail(id != NULL, FALSE);
239
240 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
241 return FALSE;
242
243 return purple_request_field_bool_get_value(field);
244 }
245
246 int
purple_request_fields_get_choice(const PurpleRequestFields * fields,const char * id)247 purple_request_fields_get_choice(const PurpleRequestFields *fields, const char *id)
248 {
249 PurpleRequestField *field;
250
251 g_return_val_if_fail(fields != NULL, -1);
252 g_return_val_if_fail(id != NULL, -1);
253
254 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
255 return -1;
256
257 return purple_request_field_choice_get_value(field);
258 }
259
260 PurpleAccount *
purple_request_fields_get_account(const PurpleRequestFields * fields,const char * id)261 purple_request_fields_get_account(const PurpleRequestFields *fields,
262 const char *id)
263 {
264 PurpleRequestField *field;
265
266 g_return_val_if_fail(fields != NULL, NULL);
267 g_return_val_if_fail(id != NULL, NULL);
268
269 if ((field = purple_request_fields_get_field(fields, id)) == NULL)
270 return NULL;
271
272 return purple_request_field_account_get_value(field);
273 }
274
275 PurpleRequestFieldGroup *
purple_request_field_group_new(const char * title)276 purple_request_field_group_new(const char *title)
277 {
278 PurpleRequestFieldGroup *group;
279
280 group = g_new0(PurpleRequestFieldGroup, 1);
281
282 group->title = g_strdup(title);
283
284 return group;
285 }
286
287 void
purple_request_field_group_destroy(PurpleRequestFieldGroup * group)288 purple_request_field_group_destroy(PurpleRequestFieldGroup *group)
289 {
290 g_return_if_fail(group != NULL);
291
292 g_free(group->title);
293
294 g_list_free_full(group->fields,
295 (GDestroyNotify)purple_request_field_destroy);
296
297 g_free(group);
298 }
299
300 void
purple_request_field_group_add_field(PurpleRequestFieldGroup * group,PurpleRequestField * field)301 purple_request_field_group_add_field(PurpleRequestFieldGroup *group,
302 PurpleRequestField *field)
303 {
304 g_return_if_fail(group != NULL);
305 g_return_if_fail(field != NULL);
306
307 group->fields = g_list_append(group->fields, field);
308
309 if (group->fields_list != NULL)
310 {
311 g_hash_table_insert(group->fields_list->fields,
312 g_strdup(purple_request_field_get_id(field)), field);
313
314 if (purple_request_field_is_required(field))
315 {
316 group->fields_list->required_fields =
317 g_list_append(group->fields_list->required_fields, field);
318 }
319 }
320
321 field->group = group;
322
323 }
324
325 const char *
purple_request_field_group_get_title(const PurpleRequestFieldGroup * group)326 purple_request_field_group_get_title(const PurpleRequestFieldGroup *group)
327 {
328 g_return_val_if_fail(group != NULL, NULL);
329
330 return group->title;
331 }
332
333 GList *
purple_request_field_group_get_fields(const PurpleRequestFieldGroup * group)334 purple_request_field_group_get_fields(const PurpleRequestFieldGroup *group)
335 {
336 g_return_val_if_fail(group != NULL, NULL);
337
338 return group->fields;
339 }
340
341 PurpleRequestField *
purple_request_field_new(const char * id,const char * text,PurpleRequestFieldType type)342 purple_request_field_new(const char *id, const char *text,
343 PurpleRequestFieldType type)
344 {
345 PurpleRequestField *field;
346
347 g_return_val_if_fail(id != NULL, NULL);
348 g_return_val_if_fail(type != PURPLE_REQUEST_FIELD_NONE, NULL);
349
350 field = g_new0(PurpleRequestField, 1);
351
352 field->id = g_strdup(id);
353 field->type = type;
354
355 purple_request_field_set_label(field, text);
356 purple_request_field_set_visible(field, TRUE);
357
358 return field;
359 }
360
361 void
purple_request_field_destroy(PurpleRequestField * field)362 purple_request_field_destroy(PurpleRequestField *field)
363 {
364 g_return_if_fail(field != NULL);
365
366 g_free(field->id);
367 g_free(field->label);
368 g_free(field->type_hint);
369
370 if (field->type == PURPLE_REQUEST_FIELD_STRING)
371 {
372 g_free(field->u.string.default_value);
373 g_free(field->u.string.value);
374 }
375 else if (field->type == PURPLE_REQUEST_FIELD_CHOICE)
376 {
377 if (field->u.choice.labels != NULL)
378 {
379 g_list_free_full(field->u.choice.labels, (GDestroyNotify)g_free);
380 }
381 }
382 else if (field->type == PURPLE_REQUEST_FIELD_LIST)
383 {
384 if (field->u.list.items != NULL)
385 {
386 g_list_free_full(field->u.list.items, (GDestroyNotify)g_free);
387 }
388
389 if (field->u.list.selected != NULL)
390 {
391 g_list_free_full(field->u.list.selected, (GDestroyNotify)g_free);
392 }
393
394 g_hash_table_destroy(field->u.list.item_data);
395 g_hash_table_destroy(field->u.list.selected_table);
396 }
397
398 g_free(field);
399 }
400
401 void
purple_request_field_set_label(PurpleRequestField * field,const char * label)402 purple_request_field_set_label(PurpleRequestField *field, const char *label)
403 {
404 g_return_if_fail(field != NULL);
405
406 g_free(field->label);
407 field->label = g_strdup(label);
408 }
409
410 void
purple_request_field_set_visible(PurpleRequestField * field,gboolean visible)411 purple_request_field_set_visible(PurpleRequestField *field, gboolean visible)
412 {
413 g_return_if_fail(field != NULL);
414
415 field->visible = visible;
416 }
417
418 void
purple_request_field_set_type_hint(PurpleRequestField * field,const char * type_hint)419 purple_request_field_set_type_hint(PurpleRequestField *field,
420 const char *type_hint)
421 {
422 g_return_if_fail(field != NULL);
423
424 g_free(field->type_hint);
425 field->type_hint = g_strdup(type_hint);
426 }
427
428 void
purple_request_field_set_required(PurpleRequestField * field,gboolean required)429 purple_request_field_set_required(PurpleRequestField *field, gboolean required)
430 {
431 g_return_if_fail(field != NULL);
432
433 if (field->required == required)
434 return;
435
436 field->required = required;
437
438 if (field->group != NULL)
439 {
440 if (required)
441 {
442 field->group->fields_list->required_fields =
443 g_list_append(field->group->fields_list->required_fields,
444 field);
445 }
446 else
447 {
448 field->group->fields_list->required_fields =
449 g_list_remove(field->group->fields_list->required_fields,
450 field);
451 }
452 }
453 }
454
455 PurpleRequestFieldType
purple_request_field_get_type(const PurpleRequestField * field)456 purple_request_field_get_type(const PurpleRequestField *field)
457 {
458 g_return_val_if_fail(field != NULL, PURPLE_REQUEST_FIELD_NONE);
459
460 return field->type;
461 }
462
463 PurpleRequestFieldGroup *
purple_request_field_get_group(const PurpleRequestField * field)464 purple_request_field_get_group(const PurpleRequestField *field)
465 {
466 g_return_val_if_fail(field != NULL, NULL);
467
468 return field->group;
469 }
470
471 const char *
purple_request_field_get_id(const PurpleRequestField * field)472 purple_request_field_get_id(const PurpleRequestField *field)
473 {
474 g_return_val_if_fail(field != NULL, NULL);
475
476 return field->id;
477 }
478
479 const char *
purple_request_field_get_label(const PurpleRequestField * field)480 purple_request_field_get_label(const PurpleRequestField *field)
481 {
482 g_return_val_if_fail(field != NULL, NULL);
483
484 return field->label;
485 }
486
487 gboolean
purple_request_field_is_visible(const PurpleRequestField * field)488 purple_request_field_is_visible(const PurpleRequestField *field)
489 {
490 g_return_val_if_fail(field != NULL, FALSE);
491
492 return field->visible;
493 }
494
495 const char *
purple_request_field_get_type_hint(const PurpleRequestField * field)496 purple_request_field_get_type_hint(const PurpleRequestField *field)
497 {
498 g_return_val_if_fail(field != NULL, NULL);
499
500 return field->type_hint;
501 }
502
503 gboolean
purple_request_field_is_required(const PurpleRequestField * field)504 purple_request_field_is_required(const PurpleRequestField *field)
505 {
506 g_return_val_if_fail(field != NULL, FALSE);
507
508 return field->required;
509 }
510
511 PurpleRequestField *
purple_request_field_string_new(const char * id,const char * text,const char * default_value,gboolean multiline)512 purple_request_field_string_new(const char *id, const char *text,
513 const char *default_value, gboolean multiline)
514 {
515 PurpleRequestField *field;
516
517 g_return_val_if_fail(id != NULL, NULL);
518 g_return_val_if_fail(text != NULL, NULL);
519
520 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_STRING);
521
522 field->u.string.multiline = multiline;
523 field->u.string.editable = TRUE;
524
525 purple_request_field_string_set_default_value(field, default_value);
526 purple_request_field_string_set_value(field, default_value);
527
528 return field;
529 }
530
531 void
purple_request_field_string_set_default_value(PurpleRequestField * field,const char * default_value)532 purple_request_field_string_set_default_value(PurpleRequestField *field,
533 const char *default_value)
534 {
535 g_return_if_fail(field != NULL);
536 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
537
538 g_free(field->u.string.default_value);
539 field->u.string.default_value = g_strdup(default_value);
540 }
541
542 void
purple_request_field_string_set_value(PurpleRequestField * field,const char * value)543 purple_request_field_string_set_value(PurpleRequestField *field, const char *value)
544 {
545 g_return_if_fail(field != NULL);
546 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
547
548 g_free(field->u.string.value);
549 field->u.string.value = g_strdup(value);
550 }
551
552 void
purple_request_field_string_set_masked(PurpleRequestField * field,gboolean masked)553 purple_request_field_string_set_masked(PurpleRequestField *field, gboolean masked)
554 {
555 g_return_if_fail(field != NULL);
556 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
557
558 field->u.string.masked = masked;
559 }
560
561 void
purple_request_field_string_set_editable(PurpleRequestField * field,gboolean editable)562 purple_request_field_string_set_editable(PurpleRequestField *field,
563 gboolean editable)
564 {
565 g_return_if_fail(field != NULL);
566 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING);
567
568 field->u.string.editable = editable;
569 }
570
571 const char *
purple_request_field_string_get_default_value(const PurpleRequestField * field)572 purple_request_field_string_get_default_value(const PurpleRequestField *field)
573 {
574 g_return_val_if_fail(field != NULL, NULL);
575 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, NULL);
576
577 return field->u.string.default_value;
578 }
579
580 const char *
purple_request_field_string_get_value(const PurpleRequestField * field)581 purple_request_field_string_get_value(const PurpleRequestField *field)
582 {
583 g_return_val_if_fail(field != NULL, NULL);
584 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, NULL);
585
586 return field->u.string.value;
587 }
588
589 gboolean
purple_request_field_string_is_multiline(const PurpleRequestField * field)590 purple_request_field_string_is_multiline(const PurpleRequestField *field)
591 {
592 g_return_val_if_fail(field != NULL, FALSE);
593 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
594
595 return field->u.string.multiline;
596 }
597
598 gboolean
purple_request_field_string_is_masked(const PurpleRequestField * field)599 purple_request_field_string_is_masked(const PurpleRequestField *field)
600 {
601 g_return_val_if_fail(field != NULL, FALSE);
602 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
603
604 return field->u.string.masked;
605 }
606
607 gboolean
purple_request_field_string_is_editable(const PurpleRequestField * field)608 purple_request_field_string_is_editable(const PurpleRequestField *field)
609 {
610 g_return_val_if_fail(field != NULL, FALSE);
611 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE);
612
613 return field->u.string.editable;
614 }
615
616 PurpleRequestField *
purple_request_field_int_new(const char * id,const char * text,int default_value)617 purple_request_field_int_new(const char *id, const char *text,
618 int default_value)
619 {
620 PurpleRequestField *field;
621
622 g_return_val_if_fail(id != NULL, NULL);
623 g_return_val_if_fail(text != NULL, NULL);
624
625 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_INTEGER);
626
627 purple_request_field_int_set_default_value(field, default_value);
628 purple_request_field_int_set_value(field, default_value);
629
630 return field;
631 }
632
633 void
purple_request_field_int_set_default_value(PurpleRequestField * field,int default_value)634 purple_request_field_int_set_default_value(PurpleRequestField *field,
635 int default_value)
636 {
637 g_return_if_fail(field != NULL);
638 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
639
640 field->u.integer.default_value = default_value;
641 }
642
643 void
purple_request_field_int_set_value(PurpleRequestField * field,int value)644 purple_request_field_int_set_value(PurpleRequestField *field, int value)
645 {
646 g_return_if_fail(field != NULL);
647 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER);
648
649 field->u.integer.value = value;
650 }
651
652 int
purple_request_field_int_get_default_value(const PurpleRequestField * field)653 purple_request_field_int_get_default_value(const PurpleRequestField *field)
654 {
655 g_return_val_if_fail(field != NULL, 0);
656 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
657
658 return field->u.integer.default_value;
659 }
660
661 int
purple_request_field_int_get_value(const PurpleRequestField * field)662 purple_request_field_int_get_value(const PurpleRequestField *field)
663 {
664 g_return_val_if_fail(field != NULL, 0);
665 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_INTEGER, 0);
666
667 return field->u.integer.value;
668 }
669
670 PurpleRequestField *
purple_request_field_bool_new(const char * id,const char * text,gboolean default_value)671 purple_request_field_bool_new(const char *id, const char *text,
672 gboolean default_value)
673 {
674 PurpleRequestField *field;
675
676 g_return_val_if_fail(id != NULL, NULL);
677 g_return_val_if_fail(text != NULL, NULL);
678
679 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_BOOLEAN);
680
681 purple_request_field_bool_set_default_value(field, default_value);
682 purple_request_field_bool_set_value(field, default_value);
683
684 return field;
685 }
686
687 void
purple_request_field_bool_set_default_value(PurpleRequestField * field,gboolean default_value)688 purple_request_field_bool_set_default_value(PurpleRequestField *field,
689 gboolean default_value)
690 {
691 g_return_if_fail(field != NULL);
692 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN);
693
694 field->u.boolean.default_value = default_value;
695 }
696
697 void
purple_request_field_bool_set_value(PurpleRequestField * field,gboolean value)698 purple_request_field_bool_set_value(PurpleRequestField *field, gboolean value)
699 {
700 g_return_if_fail(field != NULL);
701 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN);
702
703 field->u.boolean.value = value;
704 }
705
706 gboolean
purple_request_field_bool_get_default_value(const PurpleRequestField * field)707 purple_request_field_bool_get_default_value(const PurpleRequestField *field)
708 {
709 g_return_val_if_fail(field != NULL, FALSE);
710 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN, FALSE);
711
712 return field->u.boolean.default_value;
713 }
714
715 gboolean
purple_request_field_bool_get_value(const PurpleRequestField * field)716 purple_request_field_bool_get_value(const PurpleRequestField *field)
717 {
718 g_return_val_if_fail(field != NULL, FALSE);
719 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BOOLEAN, FALSE);
720
721 return field->u.boolean.value;
722 }
723
724 PurpleRequestField *
purple_request_field_choice_new(const char * id,const char * text,int default_value)725 purple_request_field_choice_new(const char *id, const char *text,
726 int default_value)
727 {
728 PurpleRequestField *field;
729
730 g_return_val_if_fail(id != NULL, NULL);
731 g_return_val_if_fail(text != NULL, NULL);
732
733 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_CHOICE);
734
735 purple_request_field_choice_set_default_value(field, default_value);
736 purple_request_field_choice_set_value(field, default_value);
737
738 return field;
739 }
740
741 void
purple_request_field_choice_add(PurpleRequestField * field,const char * label)742 purple_request_field_choice_add(PurpleRequestField *field, const char *label)
743 {
744 g_return_if_fail(field != NULL);
745 g_return_if_fail(label != NULL);
746 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
747
748 field->u.choice.labels = g_list_append(field->u.choice.labels,
749 g_strdup(label));
750 }
751
752 void
purple_request_field_choice_set_default_value(PurpleRequestField * field,int default_value)753 purple_request_field_choice_set_default_value(PurpleRequestField *field,
754 int default_value)
755 {
756 g_return_if_fail(field != NULL);
757 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
758
759 field->u.choice.default_value = default_value;
760 }
761
762 void
purple_request_field_choice_set_value(PurpleRequestField * field,int value)763 purple_request_field_choice_set_value(PurpleRequestField *field,
764 int value)
765 {
766 g_return_if_fail(field != NULL);
767 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
768
769 field->u.choice.value = value;
770 }
771
772 int
purple_request_field_choice_get_default_value(const PurpleRequestField * field)773 purple_request_field_choice_get_default_value(const PurpleRequestField *field)
774 {
775 g_return_val_if_fail(field != NULL, -1);
776 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, -1);
777
778 return field->u.choice.default_value;
779 }
780
781 int
purple_request_field_choice_get_value(const PurpleRequestField * field)782 purple_request_field_choice_get_value(const PurpleRequestField *field)
783 {
784 g_return_val_if_fail(field != NULL, -1);
785 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, -1);
786
787 return field->u.choice.value;
788 }
789
790 GList *
purple_request_field_choice_get_labels(const PurpleRequestField * field)791 purple_request_field_choice_get_labels(const PurpleRequestField *field)
792 {
793 g_return_val_if_fail(field != NULL, NULL);
794 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE, NULL);
795
796 return field->u.choice.labels;
797 }
798
799 PurpleRequestField *
purple_request_field_list_new(const char * id,const char * text)800 purple_request_field_list_new(const char *id, const char *text)
801 {
802 PurpleRequestField *field;
803
804 g_return_val_if_fail(id != NULL, NULL);
805
806 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_LIST);
807
808 field->u.list.item_data = g_hash_table_new_full(g_str_hash, g_str_equal,
809 g_free, NULL);
810
811 field->u.list.selected_table =
812 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
813
814 return field;
815 }
816
817 void
purple_request_field_list_set_multi_select(PurpleRequestField * field,gboolean multi_select)818 purple_request_field_list_set_multi_select(PurpleRequestField *field,
819 gboolean multi_select)
820 {
821 g_return_if_fail(field != NULL);
822 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
823
824 field->u.list.multiple_selection = multi_select;
825 }
826
827 gboolean
purple_request_field_list_get_multi_select(const PurpleRequestField * field)828 purple_request_field_list_get_multi_select(const PurpleRequestField *field)
829 {
830 g_return_val_if_fail(field != NULL, FALSE);
831 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, FALSE);
832
833 return field->u.list.multiple_selection;
834 }
835
836 void *
purple_request_field_list_get_data(const PurpleRequestField * field,const char * text)837 purple_request_field_list_get_data(const PurpleRequestField *field,
838 const char *text)
839 {
840 g_return_val_if_fail(field != NULL, NULL);
841 g_return_val_if_fail(text != NULL, NULL);
842 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
843
844 return g_hash_table_lookup(field->u.list.item_data, text);
845 }
846
847 void
purple_request_field_list_add(PurpleRequestField * field,const char * item,void * data)848 purple_request_field_list_add(PurpleRequestField *field, const char *item,
849 void *data)
850 {
851 purple_request_field_list_add_icon(field, item, NULL, data);
852 }
853
854 void
purple_request_field_list_add_icon(PurpleRequestField * field,const char * item,const char * icon_path,void * data)855 purple_request_field_list_add_icon(PurpleRequestField *field, const char *item, const char* icon_path,
856 void *data)
857 {
858 g_return_if_fail(field != NULL);
859 g_return_if_fail(item != NULL);
860 g_return_if_fail(data != NULL);
861 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
862
863 if (icon_path)
864 {
865 if (field->u.list.icons == NULL)
866 {
867 GList *l;
868 for (l = field->u.list.items ; l != NULL ; l = l->next)
869 {
870 /* Order doesn't matter, because we're just
871 * filing in blank items. So, we use
872 * g_list_prepend() because it's faster. */
873 field->u.list.icons = g_list_prepend(field->u.list.icons, NULL);
874 }
875 }
876 field->u.list.icons = g_list_append(field->u.list.icons, g_strdup(icon_path));
877 }
878 else if (field->u.list.icons)
879 {
880 /* Keep this even with the items list. */
881 field->u.list.icons = g_list_append(field->u.list.icons, NULL);
882 }
883
884 field->u.list.items = g_list_append(field->u.list.items, g_strdup(item));
885 g_hash_table_insert(field->u.list.item_data, g_strdup(item), data);
886 }
887
888 void
purple_request_field_list_add_selected(PurpleRequestField * field,const char * item)889 purple_request_field_list_add_selected(PurpleRequestField *field, const char *item)
890 {
891 g_return_if_fail(field != NULL);
892 g_return_if_fail(item != NULL);
893 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
894
895 if (!purple_request_field_list_get_multi_select(field) &&
896 field->u.list.selected != NULL)
897 {
898 purple_debug_warning("request",
899 "More than one item added to non-multi-select "
900 "field %s\n",
901 purple_request_field_get_id(field));
902 return;
903 }
904
905 field->u.list.selected = g_list_append(field->u.list.selected,
906 g_strdup(item));
907
908 g_hash_table_insert(field->u.list.selected_table, g_strdup(item), NULL);
909 }
910
911 void
purple_request_field_list_clear_selected(PurpleRequestField * field)912 purple_request_field_list_clear_selected(PurpleRequestField *field)
913 {
914 g_return_if_fail(field != NULL);
915 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
916
917 if (field->u.list.selected != NULL)
918 {
919 g_list_free_full(field->u.list.selected, (GDestroyNotify)g_free);
920 field->u.list.selected = NULL;
921 }
922
923 g_hash_table_destroy(field->u.list.selected_table);
924
925 field->u.list.selected_table =
926 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
927 }
928
929 void
purple_request_field_list_set_selected(PurpleRequestField * field,GList * items)930 purple_request_field_list_set_selected(PurpleRequestField *field, GList *items)
931 {
932 GList *l;
933
934 g_return_if_fail(field != NULL);
935 g_return_if_fail(items != NULL);
936 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
937
938 purple_request_field_list_clear_selected(field);
939
940 if (!purple_request_field_list_get_multi_select(field) &&
941 items && items->next)
942 {
943 purple_debug_warning("request",
944 "More than one item added to non-multi-select "
945 "field %s\n",
946 purple_request_field_get_id(field));
947 return;
948 }
949
950 for (l = items; l != NULL; l = l->next)
951 {
952 field->u.list.selected = g_list_append(field->u.list.selected,
953 g_strdup(l->data));
954 g_hash_table_insert(field->u.list.selected_table,
955 g_strdup((char *)l->data), NULL);
956 }
957 }
958
959 gboolean
purple_request_field_list_is_selected(const PurpleRequestField * field,const char * item)960 purple_request_field_list_is_selected(const PurpleRequestField *field,
961 const char *item)
962 {
963 g_return_val_if_fail(field != NULL, FALSE);
964 g_return_val_if_fail(item != NULL, FALSE);
965 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, FALSE);
966
967 return g_hash_table_lookup_extended(field->u.list.selected_table,
968 item, NULL, NULL);
969 }
970
971 GList *
purple_request_field_list_get_selected(const PurpleRequestField * field)972 purple_request_field_list_get_selected(const PurpleRequestField *field)
973 {
974 g_return_val_if_fail(field != NULL, NULL);
975 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
976
977 return field->u.list.selected;
978 }
979
980 GList *
purple_request_field_list_get_items(const PurpleRequestField * field)981 purple_request_field_list_get_items(const PurpleRequestField *field)
982 {
983 g_return_val_if_fail(field != NULL, NULL);
984 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
985
986 return field->u.list.items;
987 }
988
989 GList *
purple_request_field_list_get_icons(const PurpleRequestField * field)990 purple_request_field_list_get_icons(const PurpleRequestField *field)
991 {
992 g_return_val_if_fail(field != NULL, NULL);
993 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
994
995 return field->u.list.icons;
996 }
997
998 PurpleRequestField *
purple_request_field_label_new(const char * id,const char * text)999 purple_request_field_label_new(const char *id, const char *text)
1000 {
1001 PurpleRequestField *field;
1002
1003 g_return_val_if_fail(id != NULL, NULL);
1004 g_return_val_if_fail(text != NULL, NULL);
1005
1006 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_LABEL);
1007
1008 return field;
1009 }
1010
1011 PurpleRequestField *
purple_request_field_image_new(const char * id,const char * text,const char * buf,gsize size)1012 purple_request_field_image_new(const char *id, const char *text, const char *buf, gsize size)
1013 {
1014 PurpleRequestField *field;
1015
1016 g_return_val_if_fail(id != NULL, NULL);
1017 g_return_val_if_fail(text != NULL, NULL);
1018 g_return_val_if_fail(buf != NULL, NULL);
1019 g_return_val_if_fail(size > 0, NULL);
1020
1021 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_IMAGE);
1022
1023 field->u.image.buffer = g_memdup2(buf, size);
1024 field->u.image.size = size;
1025 field->u.image.scale_x = 1;
1026 field->u.image.scale_y = 1;
1027
1028 return field;
1029 }
1030
1031 void
purple_request_field_image_set_scale(PurpleRequestField * field,unsigned int x,unsigned int y)1032 purple_request_field_image_set_scale(PurpleRequestField *field, unsigned int x, unsigned int y)
1033 {
1034 g_return_if_fail(field != NULL);
1035 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE);
1036
1037 field->u.image.scale_x = x;
1038 field->u.image.scale_y = y;
1039 }
1040
1041 const char *
purple_request_field_image_get_buffer(PurpleRequestField * field)1042 purple_request_field_image_get_buffer(PurpleRequestField *field)
1043 {
1044 g_return_val_if_fail(field != NULL, NULL);
1045 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, NULL);
1046
1047 return field->u.image.buffer;
1048 }
1049
1050 gsize
purple_request_field_image_get_size(PurpleRequestField * field)1051 purple_request_field_image_get_size(PurpleRequestField *field)
1052 {
1053 g_return_val_if_fail(field != NULL, 0);
1054 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1055
1056 return field->u.image.size;
1057 }
1058
1059 unsigned int
purple_request_field_image_get_scale_x(PurpleRequestField * field)1060 purple_request_field_image_get_scale_x(PurpleRequestField *field)
1061 {
1062 g_return_val_if_fail(field != NULL, 0);
1063 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1064
1065 return field->u.image.scale_x;
1066 }
1067
1068 unsigned int
purple_request_field_image_get_scale_y(PurpleRequestField * field)1069 purple_request_field_image_get_scale_y(PurpleRequestField *field)
1070 {
1071 g_return_val_if_fail(field != NULL, 0);
1072 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
1073
1074 return field->u.image.scale_y;
1075 }
1076
1077 PurpleRequestField *
purple_request_field_account_new(const char * id,const char * text,PurpleAccount * account)1078 purple_request_field_account_new(const char *id, const char *text,
1079 PurpleAccount *account)
1080 {
1081 PurpleRequestField *field;
1082
1083 g_return_val_if_fail(id != NULL, NULL);
1084 g_return_val_if_fail(text != NULL, NULL);
1085
1086 field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_ACCOUNT);
1087
1088 if (account == NULL && purple_connections_get_all() != NULL)
1089 {
1090 account = purple_connection_get_account(
1091 (PurpleConnection *)purple_connections_get_all()->data);
1092 }
1093
1094 purple_request_field_account_set_default_value(field, account);
1095 purple_request_field_account_set_value(field, account);
1096
1097 return field;
1098 }
1099
1100 void
purple_request_field_account_set_default_value(PurpleRequestField * field,PurpleAccount * default_value)1101 purple_request_field_account_set_default_value(PurpleRequestField *field,
1102 PurpleAccount *default_value)
1103 {
1104 g_return_if_fail(field != NULL);
1105 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1106
1107 field->u.account.default_account = default_value;
1108 }
1109
1110 void
purple_request_field_account_set_value(PurpleRequestField * field,PurpleAccount * value)1111 purple_request_field_account_set_value(PurpleRequestField *field,
1112 PurpleAccount *value)
1113 {
1114 g_return_if_fail(field != NULL);
1115 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1116
1117 field->u.account.account = value;
1118 }
1119
1120 void
purple_request_field_account_set_show_all(PurpleRequestField * field,gboolean show_all)1121 purple_request_field_account_set_show_all(PurpleRequestField *field,
1122 gboolean show_all)
1123 {
1124 g_return_if_fail(field != NULL);
1125 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1126
1127 if (field->u.account.show_all == show_all)
1128 return;
1129
1130 field->u.account.show_all = show_all;
1131
1132 if (!show_all)
1133 {
1134 if (purple_account_is_connected(field->u.account.default_account))
1135 {
1136 purple_request_field_account_set_default_value(field,
1137 (PurpleAccount *)purple_connections_get_all()->data);
1138 }
1139
1140 if (purple_account_is_connected(field->u.account.account))
1141 {
1142 purple_request_field_account_set_value(field,
1143 (PurpleAccount *)purple_connections_get_all()->data);
1144 }
1145 }
1146 }
1147
1148 void
purple_request_field_account_set_filter(PurpleRequestField * field,PurpleFilterAccountFunc filter_func)1149 purple_request_field_account_set_filter(PurpleRequestField *field,
1150 PurpleFilterAccountFunc filter_func)
1151 {
1152 g_return_if_fail(field != NULL);
1153 g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT);
1154
1155 field->u.account.filter_func = filter_func;
1156 }
1157
1158 PurpleAccount *
purple_request_field_account_get_default_value(const PurpleRequestField * field)1159 purple_request_field_account_get_default_value(const PurpleRequestField *field)
1160 {
1161 g_return_val_if_fail(field != NULL, NULL);
1162 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, NULL);
1163
1164 return field->u.account.default_account;
1165 }
1166
1167 PurpleAccount *
purple_request_field_account_get_value(const PurpleRequestField * field)1168 purple_request_field_account_get_value(const PurpleRequestField *field)
1169 {
1170 g_return_val_if_fail(field != NULL, NULL);
1171 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, NULL);
1172
1173 return field->u.account.account;
1174 }
1175
1176 gboolean
purple_request_field_account_get_show_all(const PurpleRequestField * field)1177 purple_request_field_account_get_show_all(const PurpleRequestField *field)
1178 {
1179 g_return_val_if_fail(field != NULL, FALSE);
1180 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, FALSE);
1181
1182 return field->u.account.show_all;
1183 }
1184
1185 PurpleFilterAccountFunc
purple_request_field_account_get_filter(const PurpleRequestField * field)1186 purple_request_field_account_get_filter(const PurpleRequestField *field)
1187 {
1188 g_return_val_if_fail(field != NULL, FALSE);
1189 g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_ACCOUNT, FALSE);
1190
1191 return field->u.account.filter_func;
1192 }
1193
1194 /* -- */
1195
1196 void *
purple_request_input(void * handle,const char * title,const char * primary,const char * secondary,const char * default_value,gboolean multiline,gboolean masked,gchar * hint,const char * ok_text,GCallback ok_cb,const char * cancel_text,GCallback cancel_cb,PurpleAccount * account,const char * who,PurpleConversation * conv,void * user_data)1197 purple_request_input(void *handle, const char *title, const char *primary,
1198 const char *secondary, const char *default_value,
1199 gboolean multiline, gboolean masked, gchar *hint,
1200 const char *ok_text, GCallback ok_cb,
1201 const char *cancel_text, GCallback cancel_cb,
1202 PurpleAccount *account, const char *who, PurpleConversation *conv,
1203 void *user_data)
1204 {
1205 PurpleRequestUiOps *ops;
1206
1207 g_return_val_if_fail(ok_text != NULL, NULL);
1208 g_return_val_if_fail(ok_cb != NULL, NULL);
1209
1210 ops = purple_request_get_ui_ops();
1211
1212 if (ops != NULL && ops->request_input != NULL) {
1213 PurpleRequestInfo *info;
1214
1215 info = g_new0(PurpleRequestInfo, 1);
1216 info->type = PURPLE_REQUEST_INPUT;
1217 info->handle = handle;
1218 info->ui_handle = ops->request_input(title, primary, secondary,
1219 default_value,
1220 multiline, masked, hint,
1221 ok_text, ok_cb,
1222 cancel_text, cancel_cb,
1223 account, who, conv,
1224 user_data);
1225
1226 handles = g_list_append(handles, info);
1227
1228 return info->ui_handle;
1229 }
1230
1231 return NULL;
1232 }
1233
1234 void *
purple_request_choice(void * handle,const char * title,const char * primary,const char * secondary,int default_value,const char * ok_text,GCallback ok_cb,const char * cancel_text,GCallback cancel_cb,PurpleAccount * account,const char * who,PurpleConversation * conv,void * user_data,...)1235 purple_request_choice(void *handle, const char *title, const char *primary,
1236 const char *secondary, int default_value,
1237 const char *ok_text, GCallback ok_cb,
1238 const char *cancel_text, GCallback cancel_cb,
1239 PurpleAccount *account, const char *who, PurpleConversation *conv,
1240 void *user_data, ...)
1241 {
1242 void *ui_handle;
1243 va_list args;
1244
1245 g_return_val_if_fail(ok_text != NULL, NULL);
1246 g_return_val_if_fail(ok_cb != NULL, NULL);
1247
1248 va_start(args, user_data);
1249 ui_handle = purple_request_choice_varg(handle, title, primary, secondary,
1250 default_value, ok_text, ok_cb,
1251 cancel_text, cancel_cb,
1252 account, who, conv, user_data, args);
1253 va_end(args);
1254
1255 return ui_handle;
1256 }
1257
1258 void *
purple_request_choice_varg(void * handle,const char * title,const char * primary,const char * secondary,int default_value,const char * ok_text,GCallback ok_cb,const char * cancel_text,GCallback cancel_cb,PurpleAccount * account,const char * who,PurpleConversation * conv,void * user_data,va_list choices)1259 purple_request_choice_varg(void *handle, const char *title,
1260 const char *primary, const char *secondary,
1261 int default_value,
1262 const char *ok_text, GCallback ok_cb,
1263 const char *cancel_text, GCallback cancel_cb,
1264 PurpleAccount *account, const char *who, PurpleConversation *conv,
1265 void *user_data, va_list choices)
1266 {
1267 PurpleRequestUiOps *ops;
1268
1269 g_return_val_if_fail(ok_text != NULL, NULL);
1270 g_return_val_if_fail(ok_cb != NULL, NULL);
1271 g_return_val_if_fail(cancel_text != NULL, NULL);
1272
1273 ops = purple_request_get_ui_ops();
1274
1275 if (ops != NULL && ops->request_choice != NULL) {
1276 PurpleRequestInfo *info;
1277
1278 info = g_new0(PurpleRequestInfo, 1);
1279 info->type = PURPLE_REQUEST_CHOICE;
1280 info->handle = handle;
1281 info->ui_handle = ops->request_choice(title, primary, secondary,
1282 default_value,
1283 ok_text, ok_cb,
1284 cancel_text, cancel_cb,
1285 account, who, conv,
1286 user_data, choices);
1287
1288 handles = g_list_append(handles, info);
1289
1290 return info->ui_handle;
1291 }
1292
1293 return NULL;
1294 }
1295
1296 void *
purple_request_action(void * handle,const char * title,const char * primary,const char * secondary,int default_action,PurpleAccount * account,const char * who,PurpleConversation * conv,void * user_data,size_t action_count,...)1297 purple_request_action(void *handle, const char *title, const char *primary,
1298 const char *secondary, int default_action,
1299 PurpleAccount *account, const char *who, PurpleConversation *conv,
1300 void *user_data, size_t action_count, ...)
1301 {
1302 void *ui_handle;
1303 va_list args;
1304
1305 g_return_val_if_fail(action_count > 0, NULL);
1306
1307 va_start(args, action_count);
1308 ui_handle = purple_request_action_varg(handle, title, primary, secondary,
1309 default_action, account, who, conv,
1310 user_data, action_count, args);
1311 va_end(args);
1312
1313 return ui_handle;
1314 }
1315
1316 void *
purple_request_action_with_icon(void * handle,const char * title,const char * primary,const char * secondary,int default_action,PurpleAccount * account,const char * who,PurpleConversation * conv,gconstpointer icon_data,gsize icon_size,void * user_data,size_t action_count,...)1317 purple_request_action_with_icon(void *handle, const char *title,
1318 const char *primary,
1319 const char *secondary, int default_action,
1320 PurpleAccount *account, const char *who,
1321 PurpleConversation *conv, gconstpointer icon_data,
1322 gsize icon_size, void *user_data, size_t action_count, ...)
1323 {
1324 void *ui_handle;
1325 va_list args;
1326
1327 g_return_val_if_fail(action_count > 0, NULL);
1328
1329 va_start(args, action_count);
1330 ui_handle = purple_request_action_with_icon_varg(handle, title, primary,
1331 secondary, default_action, account, who, conv, icon_data, icon_size,
1332 user_data, action_count, args);
1333 va_end(args);
1334
1335 return ui_handle;
1336 }
1337
1338
1339 void *
purple_request_action_varg(void * handle,const char * title,const char * primary,const char * secondary,int default_action,PurpleAccount * account,const char * who,PurpleConversation * conv,void * user_data,size_t action_count,va_list actions)1340 purple_request_action_varg(void *handle, const char *title,
1341 const char *primary, const char *secondary,
1342 int default_action,
1343 PurpleAccount *account, const char *who, PurpleConversation *conv,
1344 void *user_data, size_t action_count, va_list actions)
1345 {
1346 PurpleRequestUiOps *ops;
1347
1348 g_return_val_if_fail(action_count > 0, NULL);
1349
1350 ops = purple_request_get_ui_ops();
1351
1352 if (ops != NULL && ops->request_action != NULL) {
1353 PurpleRequestInfo *info;
1354
1355 info = g_new0(PurpleRequestInfo, 1);
1356 info->type = PURPLE_REQUEST_ACTION;
1357 info->handle = handle;
1358 info->ui_handle = ops->request_action(title, primary, secondary,
1359 default_action, account, who, conv,
1360 user_data, action_count, actions);
1361
1362 handles = g_list_append(handles, info);
1363
1364 return info->ui_handle;
1365 }
1366
1367 return NULL;
1368 }
1369
1370 void *
purple_request_action_with_icon_varg(void * handle,const char * title,const char * primary,const char * secondary,int default_action,PurpleAccount * account,const char * who,PurpleConversation * conv,gconstpointer icon_data,gsize icon_size,void * user_data,size_t action_count,va_list actions)1371 purple_request_action_with_icon_varg(void *handle, const char *title,
1372 const char *primary, const char *secondary,
1373 int default_action,
1374 PurpleAccount *account, const char *who,
1375 PurpleConversation *conv, gconstpointer icon_data,
1376 gsize icon_size,
1377 void *user_data, size_t action_count, va_list actions)
1378 {
1379 PurpleRequestUiOps *ops;
1380
1381 g_return_val_if_fail(action_count > 0, NULL);
1382
1383 ops = purple_request_get_ui_ops();
1384
1385 if (ops != NULL && ops->request_action_with_icon != NULL) {
1386 PurpleRequestInfo *info;
1387
1388 info = g_new0(PurpleRequestInfo, 1);
1389 info->type = PURPLE_REQUEST_ACTION;
1390 info->handle = handle;
1391 info->ui_handle = ops->request_action_with_icon(title, primary, secondary,
1392 default_action, account, who, conv,
1393 icon_data, icon_size,
1394 user_data, action_count, actions);
1395
1396 handles = g_list_append(handles, info);
1397
1398 return info->ui_handle;
1399 } else {
1400 /* Fall back on the non-icon request if the UI doesn't support icon
1401 requests */
1402 return purple_request_action_varg(handle, title, primary, secondary,
1403 default_action, account, who, conv, user_data, action_count, actions);
1404 }
1405
1406 return NULL;
1407 }
1408
1409
1410 void *
purple_request_fields(void * handle,const char * title,const char * primary,const char * secondary,PurpleRequestFields * fields,const char * ok_text,GCallback ok_cb,const char * cancel_text,GCallback cancel_cb,PurpleAccount * account,const char * who,PurpleConversation * conv,void * user_data)1411 purple_request_fields(void *handle, const char *title, const char *primary,
1412 const char *secondary, PurpleRequestFields *fields,
1413 const char *ok_text, GCallback ok_cb,
1414 const char *cancel_text, GCallback cancel_cb,
1415 PurpleAccount *account, const char *who, PurpleConversation *conv,
1416 void *user_data)
1417 {
1418 PurpleRequestUiOps *ops;
1419
1420 g_return_val_if_fail(fields != NULL, NULL);
1421 g_return_val_if_fail(ok_text != NULL, NULL);
1422 g_return_val_if_fail(ok_cb != NULL, NULL);
1423 g_return_val_if_fail(cancel_text != NULL, NULL);
1424
1425 ops = purple_request_get_ui_ops();
1426
1427 if (ops != NULL && ops->request_fields != NULL) {
1428 PurpleRequestInfo *info;
1429
1430 info = g_new0(PurpleRequestInfo, 1);
1431 info->type = PURPLE_REQUEST_FIELDS;
1432 info->handle = handle;
1433 info->ui_handle = ops->request_fields(title, primary, secondary,
1434 fields, ok_text, ok_cb,
1435 cancel_text, cancel_cb,
1436 account, who, conv,
1437 user_data);
1438
1439 handles = g_list_append(handles, info);
1440
1441 return info->ui_handle;
1442 }
1443
1444 return NULL;
1445 }
1446
1447 void *
purple_request_file(void * handle,const char * title,const char * filename,gboolean savedialog,GCallback ok_cb,GCallback cancel_cb,PurpleAccount * account,const char * who,PurpleConversation * conv,void * user_data)1448 purple_request_file(void *handle, const char *title, const char *filename,
1449 gboolean savedialog,
1450 GCallback ok_cb, GCallback cancel_cb,
1451 PurpleAccount *account, const char *who, PurpleConversation *conv,
1452 void *user_data)
1453 {
1454 PurpleRequestUiOps *ops;
1455
1456 ops = purple_request_get_ui_ops();
1457
1458 if (ops != NULL && ops->request_file != NULL) {
1459 PurpleRequestInfo *info;
1460
1461 info = g_new0(PurpleRequestInfo, 1);
1462 info->type = PURPLE_REQUEST_FILE;
1463 info->handle = handle;
1464 info->ui_handle = ops->request_file(title, filename, savedialog,
1465 ok_cb, cancel_cb,
1466 account, who, conv, user_data);
1467 handles = g_list_append(handles, info);
1468 return info->ui_handle;
1469 }
1470
1471 return NULL;
1472 }
1473
1474 void *
purple_request_folder(void * handle,const char * title,const char * dirname,GCallback ok_cb,GCallback cancel_cb,PurpleAccount * account,const char * who,PurpleConversation * conv,void * user_data)1475 purple_request_folder(void *handle, const char *title, const char *dirname,
1476 GCallback ok_cb, GCallback cancel_cb,
1477 PurpleAccount *account, const char *who, PurpleConversation *conv,
1478 void *user_data)
1479 {
1480 PurpleRequestUiOps *ops;
1481
1482 ops = purple_request_get_ui_ops();
1483
1484 if (ops != NULL && ops->request_file != NULL) {
1485 PurpleRequestInfo *info;
1486
1487 info = g_new0(PurpleRequestInfo, 1);
1488 info->type = PURPLE_REQUEST_FOLDER;
1489 info->handle = handle;
1490 info->ui_handle = ops->request_folder(title, dirname,
1491 ok_cb, cancel_cb,
1492 account, who, conv,
1493 user_data);
1494 handles = g_list_append(handles, info);
1495 return info->ui_handle;
1496 }
1497
1498 return NULL;
1499 }
1500
1501 void *
purple_request_screenshare_media(void * handle,const char * title,const char * primary,const char * secondary,PurpleAccount * account,GCallback cb,void * user_data)1502 purple_request_screenshare_media(void *handle, const char *title,
1503 const char *primary, const char *secondary,
1504 PurpleAccount *account, GCallback cb,
1505 void *user_data)
1506 {
1507 PurpleRequestUiOps *ops;
1508
1509 ops = purple_request_get_ui_ops();
1510
1511 if (ops != NULL && ops->request_screenshare_media != NULL) {
1512 PurpleRequestInfo *info;
1513
1514 info = g_new0(PurpleRequestInfo, 1);
1515 info->type = PURPLE_REQUEST_SCREENSHARE;
1516 info->handle = handle;
1517 info->ui_handle = ops->request_screenshare_media(title, primary, secondary,
1518 account, cb, user_data);
1519 handles = g_list_append(handles, info);
1520 return info->ui_handle;
1521 }
1522
1523 return NULL;
1524 }
1525
1526 static void
purple_request_close_info(PurpleRequestInfo * info)1527 purple_request_close_info(PurpleRequestInfo *info)
1528 {
1529 PurpleRequestUiOps *ops;
1530
1531 ops = purple_request_get_ui_ops();
1532
1533 purple_notify_close_with_handle(info->ui_handle);
1534 purple_request_close_with_handle(info->ui_handle);
1535
1536 if (ops != NULL && ops->close_request != NULL)
1537 ops->close_request(info->type, info->ui_handle);
1538
1539 g_free(info);
1540 }
1541
1542 void
purple_request_close(PurpleRequestType type,void * ui_handle)1543 purple_request_close(PurpleRequestType type, void *ui_handle)
1544 {
1545 GList *l;
1546
1547 g_return_if_fail(ui_handle != NULL);
1548
1549 for (l = handles; l != NULL; l = l->next) {
1550 PurpleRequestInfo *info = l->data;
1551
1552 if (info->ui_handle == ui_handle) {
1553 handles = g_list_remove(handles, info);
1554 purple_request_close_info(info);
1555 break;
1556 }
1557 }
1558 }
1559
1560 void
purple_request_close_with_handle(void * handle)1561 purple_request_close_with_handle(void *handle)
1562 {
1563 GList *l, *l_next;
1564
1565 g_return_if_fail(handle != NULL);
1566
1567 for (l = handles; l != NULL; l = l_next) {
1568 PurpleRequestInfo *info = l->data;
1569
1570 l_next = l->next;
1571
1572 if (info->handle == handle) {
1573 handles = g_list_remove(handles, info);
1574 purple_request_close_info(info);
1575 }
1576 }
1577 }
1578
1579 void
purple_request_set_ui_ops(PurpleRequestUiOps * ops)1580 purple_request_set_ui_ops(PurpleRequestUiOps *ops)
1581 {
1582 request_ui_ops = ops;
1583 }
1584
1585 PurpleRequestUiOps *
purple_request_get_ui_ops(void)1586 purple_request_get_ui_ops(void)
1587 {
1588 return request_ui_ops;
1589 }
1590