comparison libpurple/notify.c @ 15374:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children 32c366eeeb99
comparison
equal deleted inserted replaced
15373:f79e0f4df793 15374:5fe8042783c1
1 /**
2 * @file notify.c Notification API
3 * @ingroup core
4 *
5 * gaim
6 *
7 * Gaim is the legal property of its developers, whose names are too numerous
8 * to list here. Please refer to the COPYRIGHT file distributed with this
9 * source distribution.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25 #include "notify.h"
26
27 static GaimNotifyUiOps *notify_ui_ops = NULL;
28 static GList *handles = NULL;
29
30 typedef struct
31 {
32 GaimNotifyType type;
33 void *handle;
34 void *ui_handle;
35 GaimNotifyCloseCallback cb;
36 gpointer cb_user_data;
37 } GaimNotifyInfo;
38
39 /**
40 * Definition of a user info entry
41 */
42 struct _GaimNotifyUserInfoEntry
43 {
44 char *label;
45 char *value;
46 GaimNotifyUserInfoEntryType type;
47 };
48
49 struct _GaimNotifyUserInfo
50 {
51 GList *user_info_entries;
52 };
53
54 void *
55 gaim_notify_message(void *handle, GaimNotifyMsgType type,
56 const char *title, const char *primary,
57 const char *secondary, GaimNotifyCloseCallback cb, gpointer user_data)
58 {
59 GaimNotifyUiOps *ops;
60
61 g_return_val_if_fail(primary != NULL, NULL);
62
63 ops = gaim_notify_get_ui_ops();
64
65 if (ops != NULL && ops->notify_message != NULL) {
66 GaimNotifyInfo *info;
67
68 info = g_new0(GaimNotifyInfo, 1);
69 info->type = GAIM_NOTIFY_MESSAGE;
70 info->handle = handle;
71 info->ui_handle = ops->notify_message(type, title, primary,
72 secondary);
73 info->cb = cb;
74 info->cb_user_data = user_data;
75
76 if (info->ui_handle != NULL) {
77 handles = g_list_append(handles, info);
78
79 return info->ui_handle;
80
81 } else {
82 if (info->cb != NULL)
83 info->cb(info->cb_user_data);
84
85 g_free(info);
86
87 return NULL;
88 }
89
90 } else {
91 if (cb != NULL)
92 cb(user_data);
93 }
94
95 return NULL;
96 }
97
98 void *
99 gaim_notify_email(void *handle, const char *subject, const char *from,
100 const char *to, const char *url, GaimNotifyCloseCallback cb,
101 gpointer user_data)
102 {
103 GaimNotifyUiOps *ops;
104
105 ops = gaim_notify_get_ui_ops();
106
107 if (ops != NULL && ops->notify_email != NULL) {
108 GaimNotifyInfo *info;
109
110 info = g_new0(GaimNotifyInfo, 1);
111 info->type = GAIM_NOTIFY_EMAIL;
112 info->handle = handle;
113 info->ui_handle = ops->notify_email(handle, subject, from, to, url);
114 info->cb = cb;
115 info->cb_user_data = user_data;
116
117 if (info->ui_handle != NULL) {
118 handles = g_list_append(handles, info);
119
120 return info->ui_handle;
121
122 } else {
123 if (info->cb != NULL)
124 info->cb(info->cb_user_data);
125
126 g_free(info);
127
128 return NULL;
129 }
130 } else {
131 if (cb != NULL)
132 cb(user_data);
133 }
134
135 return NULL;
136 }
137
138 void *
139 gaim_notify_emails(void *handle, size_t count, gboolean detailed,
140 const char **subjects, const char **froms,
141 const char **tos, const char **urls,
142 GaimNotifyCloseCallback cb, gpointer user_data)
143 {
144 GaimNotifyUiOps *ops;
145
146 g_return_val_if_fail(count != 0, NULL);
147
148 if (count == 1) {
149 return gaim_notify_email(handle,
150 (subjects == NULL ? NULL : *subjects),
151 (froms == NULL ? NULL : *froms),
152 (tos == NULL ? NULL : *tos),
153 (urls == NULL ? NULL : *urls),
154 cb, user_data);
155 }
156
157 ops = gaim_notify_get_ui_ops();
158
159 if (ops != NULL && ops->notify_emails != NULL) {
160 GaimNotifyInfo *info;
161
162 info = g_new0(GaimNotifyInfo, 1);
163 info->type = GAIM_NOTIFY_EMAILS;
164 info->handle = handle;
165 info->ui_handle = ops->notify_emails(handle, count, detailed, subjects,
166 froms, tos, urls);
167 info->cb = cb;
168 info->cb_user_data = user_data;
169
170 if (info->ui_handle != NULL) {
171 handles = g_list_append(handles, info);
172
173 return info->ui_handle;
174
175 } else {
176 if (info->cb != NULL)
177 info->cb(info->cb_user_data);
178
179 g_free(info);
180
181 return NULL;
182 }
183
184 } else {
185 if (cb != NULL)
186 cb(user_data);
187 }
188
189 return NULL;
190 }
191
192 void *
193 gaim_notify_formatted(void *handle, const char *title, const char *primary,
194 const char *secondary, const char *text,
195 GaimNotifyCloseCallback cb, gpointer user_data)
196 {
197 GaimNotifyUiOps *ops;
198
199 g_return_val_if_fail(primary != NULL, NULL);
200
201 ops = gaim_notify_get_ui_ops();
202
203 if (ops != NULL && ops->notify_formatted != NULL) {
204 GaimNotifyInfo *info;
205
206 info = g_new0(GaimNotifyInfo, 1);
207 info->type = GAIM_NOTIFY_FORMATTED;
208 info->handle = handle;
209 info->ui_handle = ops->notify_formatted(title, primary, secondary, text);
210 info->cb = cb;
211 info->cb_user_data = user_data;
212
213 if (info->ui_handle != NULL) {
214 handles = g_list_append(handles, info);
215
216 return info->ui_handle;
217
218 } else {
219 if (info->cb != NULL)
220 info->cb(info->cb_user_data);
221
222 g_free(info);
223
224 return NULL;
225 }
226
227 } else {
228 if (cb != NULL)
229 cb(user_data);
230 }
231
232 return NULL;
233 }
234
235 void *
236 gaim_notify_searchresults(GaimConnection *gc, const char *title,
237 const char *primary, const char *secondary,
238 GaimNotifySearchResults *results, GaimNotifyCloseCallback cb,
239 gpointer user_data)
240 {
241 GaimNotifyUiOps *ops;
242
243 ops = gaim_notify_get_ui_ops();
244
245 if (ops != NULL && ops->notify_searchresults != NULL) {
246 GaimNotifyInfo *info;
247
248 info = g_new0(GaimNotifyInfo, 1);
249 info->type = GAIM_NOTIFY_SEARCHRESULTS;
250 info->handle = gc;
251 info->ui_handle = ops->notify_searchresults(gc, title, primary,
252 secondary, results, user_data);
253 info->cb = cb;
254 info->cb_user_data = user_data;
255
256 if (info->ui_handle != NULL) {
257 handles = g_list_append(handles, info);
258
259 return info->ui_handle;
260
261 } else {
262 if (info->cb != NULL)
263 info->cb(info->cb_user_data);
264
265 g_free(info);
266
267 return NULL;
268 }
269
270 } else {
271 if (cb != NULL)
272 cb(user_data);
273 }
274
275 return NULL;
276 }
277
278 void
279 gaim_notify_searchresults_free(GaimNotifySearchResults *results)
280 {
281 GList *l;
282
283 g_return_if_fail(results != NULL);
284
285 for (l = results->buttons; l; l = g_list_delete_link(l, l)) {
286 GaimNotifySearchButton *button = l->data;
287 g_free(button->label);
288 g_free(button);
289 }
290
291 for (l = results->rows; l; l = g_list_delete_link(l, l)) {
292 GList *row = l->data;
293 g_list_foreach(row, (GFunc)g_free, NULL);
294 g_list_free(row);
295 }
296
297 for (l = results->columns; l; l = g_list_delete_link(l, l)) {
298 GaimNotifySearchColumn *column = l->data;
299 g_free(column->title);
300 g_free(column);
301 }
302
303 g_free(results);
304 }
305
306 void
307 gaim_notify_searchresults_new_rows(GaimConnection *gc,
308 GaimNotifySearchResults *results,
309 void *data)
310 {
311 GaimNotifyUiOps *ops;
312
313 ops = gaim_notify_get_ui_ops();
314
315 if (ops != NULL && ops->notify_searchresults != NULL) {
316 ops->notify_searchresults_new_rows(gc, results, data);
317 }
318 }
319
320 void
321 gaim_notify_searchresults_button_add(GaimNotifySearchResults *results,
322 GaimNotifySearchButtonType type,
323 GaimNotifySearchResultsCallback cb)
324 {
325 GaimNotifySearchButton *button;
326
327 g_return_if_fail(results != NULL);
328 g_return_if_fail(cb != NULL);
329
330 button = g_new0(GaimNotifySearchButton, 1);
331 button->callback = cb;
332 button->type = type;
333
334 results->buttons = g_list_append(results->buttons, button);
335 }
336
337
338 void
339 gaim_notify_searchresults_button_add_labeled(GaimNotifySearchResults *results,
340 const char *label,
341 GaimNotifySearchResultsCallback cb) {
342 GaimNotifySearchButton *button;
343
344 g_return_if_fail(results != NULL);
345 g_return_if_fail(cb != NULL);
346 g_return_if_fail(label != NULL);
347 g_return_if_fail(*label != '\0');
348
349 button = g_new0(GaimNotifySearchButton, 1);
350 button->callback = cb;
351 button->type = GAIM_NOTIFY_BUTTON_LABELED;
352 button->label = g_strdup(label);
353
354 results->buttons = g_list_append(results->buttons, button);
355 }
356
357
358 GaimNotifySearchResults *
359 gaim_notify_searchresults_new()
360 {
361 GaimNotifySearchResults *rs = g_new0(GaimNotifySearchResults, 1);
362
363 return rs;
364 }
365
366 void
367 gaim_notify_searchresults_column_add(GaimNotifySearchResults *results,
368 GaimNotifySearchColumn *column)
369 {
370 g_return_if_fail(results != NULL);
371 g_return_if_fail(column != NULL);
372
373 results->columns = g_list_append(results->columns, column);
374 }
375
376 void gaim_notify_searchresults_row_add(GaimNotifySearchResults *results,
377 GList *row)
378 {
379 g_return_if_fail(results != NULL);
380 g_return_if_fail(row != NULL);
381
382 results->rows = g_list_append(results->rows, row);
383 }
384
385 GaimNotifySearchColumn *
386 gaim_notify_searchresults_column_new(const char *title)
387 {
388 GaimNotifySearchColumn *sc;
389
390 g_return_val_if_fail(title != NULL, NULL);
391
392 sc = g_new0(GaimNotifySearchColumn, 1);
393 sc->title = g_strdup(title);
394
395 return sc;
396 }
397
398 guint
399 gaim_notify_searchresults_get_columns_count(GaimNotifySearchResults *results)
400 {
401 g_return_val_if_fail(results != NULL, 0);
402
403 return g_list_length(results->columns);
404 }
405
406 guint
407 gaim_notify_searchresults_get_rows_count(GaimNotifySearchResults *results)
408 {
409 g_return_val_if_fail(results != NULL, 0);
410
411 return g_list_length(results->rows);
412 }
413
414 char *
415 gaim_notify_searchresults_column_get_title(GaimNotifySearchResults *results,
416 unsigned int column_id)
417 {
418 g_return_val_if_fail(results != NULL, NULL);
419
420 return ((GaimNotifySearchColumn *)g_list_nth_data(results->columns, column_id))->title;
421 }
422
423 GList *
424 gaim_notify_searchresults_row_get(GaimNotifySearchResults *results,
425 unsigned int row_id)
426 {
427 g_return_val_if_fail(results != NULL, NULL);
428
429 return g_list_nth_data(results->rows, row_id);
430 }
431
432 void *
433 gaim_notify_userinfo(GaimConnection *gc, const char *who,
434 GaimNotifyUserInfo *user_info, GaimNotifyCloseCallback cb, gpointer user_data)
435 {
436 GaimNotifyUiOps *ops;
437
438 g_return_val_if_fail(who != NULL, NULL);
439
440 ops = gaim_notify_get_ui_ops();
441
442 if (ops != NULL && ops->notify_userinfo != NULL) {
443 GaimNotifyInfo *info;
444
445 info = g_new0(GaimNotifyInfo, 1);
446 info->type = GAIM_NOTIFY_USERINFO;
447 info->handle = gc;
448
449 gaim_signal_emit(gaim_notify_get_handle(), "displaying-userinfo",
450 gaim_connection_get_account(gc), who, user_info);
451
452 info->ui_handle = ops->notify_userinfo(gc, who, user_info);
453 info->cb = cb;
454 info->cb_user_data = user_data;
455
456 if (info->ui_handle != NULL) {
457 handles = g_list_append(handles, info);
458
459 return info->ui_handle;
460
461 } else {
462 if (info->cb != NULL)
463 info->cb(info->cb_user_data);
464
465 g_free(info);
466
467 return NULL;
468 }
469
470 } else {
471 if (cb != NULL)
472 cb(user_data);
473 }
474
475 return NULL;
476 }
477
478 GaimNotifyUserInfoEntry *
479 gaim_notify_user_info_entry_new(const char *label, const char *value)
480 {
481 GaimNotifyUserInfoEntry *user_info_entry;
482
483 user_info_entry = g_new0(GaimNotifyUserInfoEntry, 1);
484 user_info_entry->label = g_strdup(label);
485 user_info_entry->value = g_strdup(value);
486 user_info_entry->type = GAIM_NOTIFY_USER_INFO_ENTRY_PAIR;
487
488 return user_info_entry;
489 }
490
491 static void
492 gaim_notify_user_info_entry_destroy(GaimNotifyUserInfoEntry *user_info_entry)
493 {
494 g_return_if_fail(user_info_entry != NULL);
495
496 g_free(user_info_entry->label);
497 g_free(user_info_entry->value);
498 g_free(user_info_entry);
499 }
500
501 GaimNotifyUserInfo *
502 gaim_notify_user_info_new()
503 {
504 GaimNotifyUserInfo *user_info;
505
506 user_info = g_new0(GaimNotifyUserInfo, 1);
507 user_info->user_info_entries = NULL;
508
509 return user_info;
510 }
511
512 void
513 gaim_notify_user_info_destroy(GaimNotifyUserInfo *user_info)
514 {
515 GList *l;
516
517 for (l = user_info->user_info_entries; l != NULL; l = l->next) {
518 GaimNotifyUserInfoEntry *user_info_entry = l->data;
519
520 gaim_notify_user_info_entry_destroy(user_info_entry);
521 }
522
523 g_list_free(user_info->user_info_entries);
524 }
525
526 GList *
527 gaim_notify_user_info_get_entries(GaimNotifyUserInfo *user_info)
528 {
529 g_return_val_if_fail(user_info != NULL, NULL);
530
531 return user_info->user_info_entries;
532 }
533
534 char *
535 gaim_notify_user_info_get_text_with_newline(GaimNotifyUserInfo *user_info, const char *newline)
536 {
537 GList *l;
538 GString *text;
539
540 text = g_string_new("");
541
542 for (l = user_info->user_info_entries; l != NULL; l = l->next) {
543 GaimNotifyUserInfoEntry *user_info_entry = l->data;
544 /* Add a newline before a section header */
545 if (user_info_entry->type == GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER)
546 g_string_append(text, newline);
547
548 /* Handle the label/value pair itself */
549 /* XXX Todo: Use a larger size for a section header? */
550 if (user_info_entry->label)
551 g_string_append_printf(text, "<b>%s</b>", user_info_entry->label);
552 if (user_info_entry->label && user_info_entry->value)
553 g_string_append(text, ": ");
554 if (user_info_entry->value)
555 g_string_append(text, user_info_entry->value);
556
557 /* Display a section break as a horizontal line */
558 if (user_info_entry->type == GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK)
559 g_string_append(text, "<HR>");
560
561 /* Don't insert a new line before or after a section break; <HR> does that for us */
562 if ((user_info_entry->type != GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK) &&
563 (l->next && ((((GaimNotifyUserInfoEntry *)(l->next->data))->type != GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK))))
564 g_string_append(text, newline);
565
566 /* Add an extra newline after a section header */
567 if (user_info_entry->type == GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER)
568 g_string_append(text, newline);
569 }
570
571 return g_string_free(text, FALSE);
572 }
573
574
575 gchar *
576 gaim_notify_user_info_entry_get_label(GaimNotifyUserInfoEntry *user_info_entry)
577 {
578 g_return_val_if_fail(user_info_entry != NULL, NULL);
579
580 return user_info_entry->label;
581 }
582
583 void
584 gaim_notify_user_info_entry_set_label(GaimNotifyUserInfoEntry *user_info_entry, const char *label)
585 {
586 g_return_if_fail(user_info_entry != NULL);
587
588 g_free(user_info_entry->label);
589 user_info_entry->label = g_strdup(label);
590 }
591
592 gchar *
593 gaim_notify_user_info_entry_get_value(GaimNotifyUserInfoEntry *user_info_entry)
594 {
595 g_return_val_if_fail(user_info_entry != NULL, NULL);
596
597 return user_info_entry->value;
598 }
599
600 void
601 gaim_notify_user_info_entry_set_value(GaimNotifyUserInfoEntry *user_info_entry, const char *value)
602 {
603 g_return_if_fail(user_info_entry != NULL);
604
605 g_free(user_info_entry->value);
606 user_info_entry->value = g_strdup(value);
607 }
608
609 GaimNotifyUserInfoEntryType
610 gaim_notify_user_info_entry_get_type(GaimNotifyUserInfoEntry *user_info_entry)
611 {
612 g_return_val_if_fail(user_info_entry != NULL, GAIM_NOTIFY_USER_INFO_ENTRY_PAIR);
613
614 return user_info_entry->type;
615 }
616
617 void
618 gaim_notify_user_info_entry_set_type(GaimNotifyUserInfoEntry *user_info_entry, GaimNotifyUserInfoEntryType type)
619 {
620 g_return_if_fail(user_info_entry != NULL);
621
622 user_info_entry->type = type;
623 }
624
625 void
626 gaim_notify_user_info_add_pair(GaimNotifyUserInfo *user_info, const char *label, const char *value)
627 {
628 GaimNotifyUserInfoEntry *entry;
629
630 entry = gaim_notify_user_info_entry_new(label, value);
631 user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry);
632 }
633
634 void
635 gaim_notify_user_info_prepend_pair(GaimNotifyUserInfo *user_info, const char *label, const char *value)
636 {
637 GaimNotifyUserInfoEntry *entry;
638
639 entry = gaim_notify_user_info_entry_new(label, value);
640 user_info->user_info_entries = g_list_prepend(user_info->user_info_entries, entry);
641 }
642
643 void
644 gaim_notify_user_info_remove_entry(GaimNotifyUserInfo *user_info, GaimNotifyUserInfoEntry *entry)
645 {
646 g_return_if_fail(user_info != NULL);
647 g_return_if_fail(entry != NULL);
648
649 user_info->user_info_entries = g_list_remove(user_info->user_info_entries, entry);
650 }
651
652 void
653 gaim_notify_user_info_add_section_header(GaimNotifyUserInfo *user_info, const char *label)
654 {
655 GaimNotifyUserInfoEntry *entry;
656
657 entry = gaim_notify_user_info_entry_new(label, NULL);
658 entry->type = GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER;
659
660 user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry);
661 }
662
663 void
664 gaim_notify_user_info_add_section_break(GaimNotifyUserInfo *user_info)
665 {
666 GaimNotifyUserInfoEntry *entry;
667
668 entry = gaim_notify_user_info_entry_new(NULL, NULL);
669 entry->type = GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK;
670
671 user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry);
672 }
673
674 void
675 gaim_notify_user_info_remove_last_item(GaimNotifyUserInfo *user_info)
676 {
677 user_info->user_info_entries = g_list_remove(user_info->user_info_entries,
678 g_list_last(user_info->user_info_entries)->data);
679 }
680
681 void *
682 gaim_notify_uri(void *handle, const char *uri)
683 {
684 GaimNotifyUiOps *ops;
685
686 g_return_val_if_fail(uri != NULL, NULL);
687
688 ops = gaim_notify_get_ui_ops();
689
690 if (ops != NULL && ops->notify_uri != NULL) {
691 GaimNotifyInfo *info;
692
693 info = g_new0(GaimNotifyInfo, 1);
694 info->type = GAIM_NOTIFY_URI;
695 info->handle = handle;
696 info->ui_handle = ops->notify_uri(uri);
697
698 if (info->ui_handle != NULL) {
699 handles = g_list_append(handles, info);
700
701 return info->ui_handle;
702
703 } else {
704 g_free(info);
705
706 return NULL;
707 }
708 }
709
710 return NULL;
711 }
712
713 void
714 gaim_notify_close(GaimNotifyType type, void *ui_handle)
715 {
716 GList *l;
717 GaimNotifyUiOps *ops;
718
719 g_return_if_fail(ui_handle != NULL);
720
721 ops = gaim_notify_get_ui_ops();
722
723 for (l = handles; l != NULL; l = l->next) {
724 GaimNotifyInfo *info = l->data;
725
726 if (info->ui_handle == ui_handle) {
727 handles = g_list_remove(handles, info);
728
729 if (ops != NULL && ops->close_notify != NULL)
730 ops->close_notify(info->type, ui_handle);
731
732 if (info->cb != NULL)
733 info->cb(info->cb_user_data);
734
735 g_free(info);
736
737 break;
738 }
739 }
740 }
741
742 void
743 gaim_notify_close_with_handle(void *handle)
744 {
745 GList *l, *l_next;
746 GaimNotifyUiOps *ops;
747
748 g_return_if_fail(handle != NULL);
749
750 ops = gaim_notify_get_ui_ops();
751
752 for (l = handles; l != NULL; l = l_next) {
753 GaimNotifyInfo *info = l->data;
754
755 l_next = l->next;
756
757 if (info->handle == handle) {
758 handles = g_list_remove(handles, info);
759
760 if (ops != NULL && ops->close_notify != NULL)
761 ops->close_notify(info->type, info->ui_handle);
762
763 if (info->cb != NULL)
764 info->cb(info->cb_user_data);
765
766 g_free(info);
767 }
768 }
769 }
770
771 void
772 gaim_notify_set_ui_ops(GaimNotifyUiOps *ops)
773 {
774 notify_ui_ops = ops;
775 }
776
777 GaimNotifyUiOps *
778 gaim_notify_get_ui_ops(void)
779 {
780 return notify_ui_ops;
781 }
782
783 void *
784 gaim_notify_get_handle(void)
785 {
786 static int handle;
787
788 return &handle;
789 }
790
791 void
792 gaim_notify_init(void)
793 {
794 gpointer handle = gaim_notify_get_handle();
795
796 gaim_signal_register(handle, "displaying-userinfo",
797 gaim_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3,
798 gaim_value_new(GAIM_TYPE_SUBTYPE,
799 GAIM_SUBTYPE_ACCOUNT),
800 gaim_value_new(GAIM_TYPE_STRING),
801 gaim_value_new(GAIM_TYPE_SUBTYPE,
802 GAIM_SUBTYPE_USERINFO));
803 }
804
805 void
806 gaim_notify_uninit(void)
807 {
808 gaim_signals_unregister_by_instance(gaim_notify_get_handle());
809 }