comparison src/pounce.c @ 5875:448f2f4ca3ec

[gaim-migrate @ 6307] Rewrote the pounce framework.. yes, again. But now it saves! OOhh!! Neato. Things are cleaner too. AND I CHANGED THE OK BUTTON TO SAVE! committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Sun, 15 Jun 2003 02:03:23 +0000
parents 059d95c67cda
children 9e54bb2ee3b5
comparison
equal deleted inserted replaced
5874:964e4f94fc56 5875:448f2f4ca3ec
28 #include "pounce.h" 28 #include "pounce.h"
29 #include "util.h" 29 #include "util.h"
30 30
31 typedef struct 31 typedef struct
32 { 32 {
33 GString *buffer;
34
35 GaimPounce *pounce;
36 GaimPounceEvent events;
37
38 char *ui_name;
39 char *pouncee;
40 char *protocol_id;
41 char *event_type;
42 char *action_name;
43 char *param_name;
44 char *account_name;
45
46 } PounceParserData;
47
48 typedef struct
49 {
33 char *name; 50 char *name;
34 51
35 gboolean enabled; 52 gboolean enabled;
36 53
37 GHashTable *atts; 54 GHashTable *atts;
38 55
39 } GaimPounceActionData; 56 } GaimPounceActionData;
40 57
41 58 typedef struct
42 static GList *pounces = NULL; 59 {
43 static guint pounces_save_timer = 0; 60 char *ui;
44 static gboolean pounces_loaded = FALSE; 61 GaimPounceCb cb;
62 void (*new_pounce)(GaimPounce *);
63 void (*free_pounce)(GaimPounce *);
64
65 } GaimPounceHandler;
66
67
68 static GHashTable *pounce_handlers = NULL;
69 static GList *pounces = NULL;
70 static guint pounces_save_timer = 0;
71 static gboolean pounces_loaded = FALSE;
72
45 73
46 static GaimPounceActionData * 74 static GaimPounceActionData *
47 find_action_data(const GaimPounce *pounce, const char *name) 75 find_action_data(const GaimPounce *pounce, const char *name)
48 { 76 {
49 GaimPounceActionData *action; 77 GaimPounceActionData *action;
84 pounces_save_timer = g_timeout_add(5000, pounces_save_cb, NULL); 112 pounces_save_timer = g_timeout_add(5000, pounces_save_cb, NULL);
85 } 113 }
86 114
87 GaimPounce * 115 GaimPounce *
88 gaim_pounce_new(const char *ui_type, GaimAccount *pouncer, 116 gaim_pounce_new(const char *ui_type, GaimAccount *pouncer,
89 const char *pouncee, GaimPounceEvent event, 117 const char *pouncee, GaimPounceEvent event)
90 GaimPounceCb cb, void *data, void (*free)(void *))
91 { 118 {
92 GaimPounce *pounce; 119 GaimPounce *pounce;
120 GaimPounceHandler *handler;
93 121
94 g_return_val_if_fail(ui_type != NULL, NULL); 122 g_return_val_if_fail(ui_type != NULL, NULL);
95 g_return_val_if_fail(pouncer != NULL, NULL); 123 g_return_val_if_fail(pouncer != NULL, NULL);
96 g_return_val_if_fail(pouncee != NULL, NULL); 124 g_return_val_if_fail(pouncee != NULL, NULL);
97 g_return_val_if_fail(event != 0, NULL); 125 g_return_val_if_fail(event != 0, NULL);
98 g_return_val_if_fail(cb != NULL, NULL);
99 126
100 pounce = g_new0(GaimPounce, 1); 127 pounce = g_new0(GaimPounce, 1);
101 128
102 pounce->ui_type = g_strdup(ui_type); 129 pounce->ui_type = g_strdup(ui_type);
103 pounce->pouncer = pouncer; 130 pounce->pouncer = pouncer;
104 pounce->pouncee = g_strdup(pouncee); 131 pounce->pouncee = g_strdup(pouncee);
105 pounce->events = event; 132 pounce->events = event;
106 pounce->callback = cb;
107 pounce->data = data;
108 pounce->free = free;
109 133
110 pounce->actions = g_hash_table_new_full(g_str_hash, g_str_equal, 134 pounce->actions = g_hash_table_new_full(g_str_hash, g_str_equal,
111 g_free, free_action_data); 135 g_free, free_action_data);
112 136
137 handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
138
139 if (handler != NULL && handler->new_pounce != NULL)
140 handler->new_pounce(pounce);
141
113 pounces = g_list_append(pounces, pounce); 142 pounces = g_list_append(pounces, pounce);
114 143
115 return pounce; 144 return pounce;
116 } 145 }
117 146
118 void 147 void
119 gaim_pounce_destroy(GaimPounce *pounce) 148 gaim_pounce_destroy(GaimPounce *pounce)
120 { 149 {
150 GaimPounceHandler *handler;
151
121 g_return_if_fail(pounce != NULL); 152 g_return_if_fail(pounce != NULL);
153
154 handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
122 155
123 pounces = g_list_remove(pounces, pounce); 156 pounces = g_list_remove(pounces, pounce);
124 157
125 if (pounce->ui_type != NULL) g_free(pounce->ui_type); 158 if (pounce->ui_type != NULL) g_free(pounce->ui_type);
126 if (pounce->pouncee != NULL) g_free(pounce->pouncee); 159 if (pounce->pouncee != NULL) g_free(pounce->pouncee);
127 160
128 g_hash_table_destroy(pounce->actions); 161 g_hash_table_destroy(pounce->actions);
129 162
130 if (pounce->free != NULL && pounce->data != NULL) 163 if (handler != NULL && handler->free_pounce != NULL)
131 pounce->free(pounce->data); 164 handler->free_pounce(pounce);
132 165
133 g_free(pounce); 166 g_free(pounce);
134 167
135 schedule_pounces_save(); 168 schedule_pounces_save();
136 } 169 }
325 void 358 void
326 gaim_pounce_execute(const GaimAccount *pouncer, const char *pouncee, 359 gaim_pounce_execute(const GaimAccount *pouncer, const char *pouncee,
327 GaimPounceEvent events) 360 GaimPounceEvent events)
328 { 361 {
329 GaimPounce *pounce; 362 GaimPounce *pounce;
363 GaimPounceHandler *handler;
330 GList *l, *l_next; 364 GList *l, *l_next;
331 365
332 g_return_if_fail(pouncer != NULL); 366 g_return_if_fail(pouncer != NULL);
333 g_return_if_fail(pouncee != NULL); 367 g_return_if_fail(pouncee != NULL);
334 g_return_if_fail(events != GAIM_POUNCE_NONE); 368 g_return_if_fail(events != GAIM_POUNCE_NONE);
339 373
340 if ((gaim_pounce_get_events(pounce) & events) && 374 if ((gaim_pounce_get_events(pounce) & events) &&
341 (gaim_pounce_get_pouncer(pounce) == pouncer) && 375 (gaim_pounce_get_pouncer(pounce) == pouncer) &&
342 !strcmp(gaim_pounce_get_pouncee(pounce), pouncee)) { 376 !strcmp(gaim_pounce_get_pouncee(pounce), pouncee)) {
343 377
344 if (pounce->callback != NULL) { 378 handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
345 pounce->callback(pounce, events, gaim_pounce_get_data(pounce)); 379
380 if (handler != NULL && handler->cb != NULL) {
381 handler->cb(pounce, events, gaim_pounce_get_data(pounce));
346 382
347 if (!gaim_pounce_get_save(pounce)) 383 if (!gaim_pounce_get_save(pounce))
348 gaim_pounce_destroy(pounce); 384 gaim_pounce_destroy(pounce);
349 } 385 }
350 } 386 }
374 } 410 }
375 411
376 return NULL; 412 return NULL;
377 } 413 }
378 414
415 /* XML Stuff */
416 static void
417 free_parser_data(gpointer user_data)
418 {
419 PounceParserData *data = user_data;
420
421 if (data->buffer != NULL)
422 g_string_free(data->buffer, TRUE);
423
424 if (data->ui_name != NULL) g_free(data->ui_name);
425 if (data->pouncee != NULL) g_free(data->pouncee);
426 if (data->protocol_id != NULL) g_free(data->protocol_id);
427 if (data->event_type != NULL) g_free(data->event_type);
428 if (data->action_name != NULL) g_free(data->action_name);
429 if (data->param_name != NULL) g_free(data->param_name);
430 if (data->account_name != NULL) g_free(data->account_name);
431
432 g_free(data);
433 }
434
435 static void
436 start_element_handler(GMarkupParseContext *context,
437 const gchar *element_name,
438 const gchar **attribute_names,
439 const gchar **attribute_values,
440 gpointer user_data, GError **error)
441 {
442 PounceParserData *data = user_data;
443 GHashTable *atts;
444 int i;
445
446 atts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
447
448 for (i = 0; attribute_names[i] != NULL; i++) {
449 g_hash_table_insert(atts, g_strdup(attribute_names[i]),
450 g_strdup(attribute_values[i]));
451 }
452
453 if (data->buffer != NULL) {
454 g_string_free(data->buffer, TRUE);
455 data->buffer = NULL;
456 }
457
458 if (!strcmp(element_name, "pounce")) {
459 const char *ui = g_hash_table_lookup(atts, "ui");
460
461 if (ui == NULL) {
462 gaim_debug(GAIM_DEBUG_ERROR, "pounce",
463 "Unset 'ui' parameter for pounce!\n");
464 }
465 else
466 data->ui_name = g_strdup(ui);
467
468 data->events = 0;
469 }
470 else if (!strcmp(element_name, "account")) {
471 const char *protocol_id = g_hash_table_lookup(atts, "protocol");
472
473 if (protocol_id == NULL) {
474 gaim_debug(GAIM_DEBUG_ERROR, "pounce",
475 "Unset 'protocol' parameter for account!\n");
476 }
477 else
478 data->protocol_id = g_strdup(protocol_id);
479 }
480 else if (!strcmp(element_name, "event")) {
481 const char *type = g_hash_table_lookup(atts, "type");
482
483 if (type == NULL) {
484 gaim_debug(GAIM_DEBUG_ERROR, "pounce",
485 "Unset 'type' parameter for event!\n");
486 }
487 else
488 data->event_type = g_strdup(type);
489 }
490 else if (!strcmp(element_name, "action")) {
491 const char *type = g_hash_table_lookup(atts, "type");
492
493 if (type == NULL) {
494 gaim_debug(GAIM_DEBUG_ERROR, "pounce",
495 "Unset 'type' parameter for action!\n");
496 }
497 else
498 data->action_name = g_strdup(type);
499 }
500 else if (!strcmp(element_name, "param")) {
501 const char *param_name = g_hash_table_lookup(atts, "name");
502
503 if (param_name == NULL) {
504 gaim_debug(GAIM_DEBUG_ERROR, "pounce",
505 "Unset 'name' parameter for param!\n");
506 }
507 else
508 data->param_name = g_strdup(param_name);
509 }
510
511 g_hash_table_destroy(atts);
512 }
513
514 static void
515 end_element_handler(GMarkupParseContext *context, const gchar *element_name,
516 gpointer user_data, GError **error)
517 {
518 PounceParserData *data = user_data;
519 gchar *buffer = NULL;
520
521 if (data->buffer != NULL) {
522 buffer = g_string_free(data->buffer, FALSE);
523 data->buffer = NULL;
524 }
525
526 if (!strcmp(element_name, "account")) {
527 data->account_name = g_strdup(buffer);
528 }
529 else if (!strcmp(element_name, "pouncee")) {
530 data->pouncee = g_strdup(buffer);
531 }
532 else if (!strcmp(element_name, "event")) {
533 if (!strcmp(data->event_type, "sign-on"))
534 data->events |= GAIM_POUNCE_SIGNON;
535 else if (!strcmp(data->event_type, "sign-off"))
536 data->events |= GAIM_POUNCE_SIGNOFF;
537 else if (!strcmp(data->event_type, "away"))
538 data->events |= GAIM_POUNCE_AWAY;
539 else if (!strcmp(data->event_type, "return-from-away"))
540 data->events |= GAIM_POUNCE_AWAY_RETURN;
541 else if (!strcmp(data->event_type, "idle"))
542 data->events |= GAIM_POUNCE_IDLE;
543 else if (!strcmp(data->event_type, "return-from-idle"))
544 data->events |= GAIM_POUNCE_IDLE_RETURN;
545 else if (!strcmp(data->event_type, "typing"))
546 data->events |= GAIM_POUNCE_TYPING;
547 else if (!strcmp(data->event_type, "stop-typing"))
548 data->events |= GAIM_POUNCE_TYPING_STOPPED;
549
550 g_free(data->event_type);
551 data->event_type = NULL;
552 }
553 else if (!strcmp(element_name, "action")) {
554 gaim_pounce_action_set_enabled(data->pounce, data->action_name, TRUE);
555
556 g_free(data->action_name);
557 data->action_name = NULL;
558 }
559 else if (!strcmp(element_name, "param")) {
560 gaim_pounce_action_set_attribute(data->pounce, data->action_name,
561 data->param_name, buffer);
562
563 g_free(data->param_name);
564 data->param_name = NULL;
565 }
566 else if (!strcmp(element_name, "events")) {
567 GList *l;
568 GaimAccount *account;
569 GaimProtocol protocol = -1;
570
571 for (l = gaim_plugins_get_protocols(); l != NULL; l = l->next) {
572 GaimPlugin *plugin = (GaimPlugin *)l->data;
573
574 if (GAIM_IS_PROTOCOL_PLUGIN(plugin)) {
575 if (!strcmp(plugin->info->id, data->protocol_id)) {
576 protocol = GAIM_PLUGIN_PROTOCOL_INFO(plugin)->protocol;
577
578 break;
579 }
580 }
581 }
582
583 account = gaim_accounts_find(data->account_name, protocol);
584
585 g_free(data->account_name);
586 g_free(data->protocol_id);
587
588 data->account_name = NULL;
589 data->protocol_id = NULL;
590
591 if (account == NULL) {
592 gaim_debug(GAIM_DEBUG_ERROR, "pounce",
593 "Account for pounce not found!\n");
594 }
595 else {
596 gaim_debug(GAIM_DEBUG_INFO, "pounce",
597 "Creating pounce: %s, %s\n", data->ui_name,
598 data->pouncee);
599
600 data->pounce = gaim_pounce_new(data->ui_name, account,
601 data->pouncee, data->events);
602 }
603
604 g_free(data->pouncee);
605 data->pouncee = NULL;
606 }
607 else if (!strcmp(element_name, "pounce")) {
608 data->pounce = NULL;
609 data->events = 0;
610
611 if (data->ui_name != NULL) g_free(data->ui_name);
612 if (data->pouncee != NULL) g_free(data->pouncee);
613 if (data->protocol_id != NULL) g_free(data->protocol_id);
614 if (data->event_type != NULL) g_free(data->event_type);
615 if (data->action_name != NULL) g_free(data->action_name);
616 if (data->param_name != NULL) g_free(data->param_name);
617 if (data->account_name != NULL) g_free(data->account_name);
618
619 data->ui_name = NULL;
620 data->pounce = NULL;
621 data->protocol_id = NULL;
622 data->event_type = NULL;
623 data->action_name = NULL;
624 data->param_name = NULL;
625 data->account_name = NULL;
626 }
627
628 if (buffer != NULL)
629 g_free(buffer);
630 }
631
632 static void
633 text_handler(GMarkupParseContext *context, const gchar *text,
634 gsize text_len, gpointer user_data, GError **error)
635 {
636 PounceParserData *data = user_data;
637
638 if (data->buffer == NULL)
639 data->buffer = g_string_new_len(text, text_len);
640 else
641 g_string_append_len(data->buffer, text, text_len);
642 }
643
644 static GMarkupParser pounces_parser =
645 {
646 start_element_handler,
647 end_element_handler,
648 text_handler,
649 NULL,
650 NULL
651 };
652
379 gboolean 653 gboolean
380 gaim_pounces_load(void) 654 gaim_pounces_load(void)
381 { 655 {
656 gchar *filename = g_build_filename(gaim_user_dir(), "pounces.xml", NULL);
657 gchar *contents = NULL;
658 gsize length;
659 GMarkupParseContext *context;
660 GError *error = NULL;
661 PounceParserData *parser_data;
662
663 if (filename == NULL) {
664 pounces_loaded = TRUE;
665 return FALSE;
666 }
667
668 if (!g_file_get_contents(filename, &contents, &length, &error)) {
669 gaim_debug(GAIM_DEBUG_ERROR, "pounces",
670 "Error reading pounces: %s\n", error->message);
671
672 g_error_free(error);
673
674 pounces_loaded = TRUE;
675 return FALSE;
676 }
677
678 parser_data = g_new0(PounceParserData, 1);
679
680 context = g_markup_parse_context_new(&pounces_parser, 0,
681 parser_data, free_parser_data);
682
683 if (!g_markup_parse_context_parse(context, contents, length, NULL)) {
684 g_markup_parse_context_free(context);
685 g_free(contents);
686
687 pounces_loaded = TRUE;
688
689 return FALSE;
690 }
691
692 if (!g_markup_parse_context_end_parse(context, NULL)) {
693 gaim_debug(GAIM_DEBUG_ERROR, "pounces", "Error parsing %s\n",
694 filename);
695
696 g_markup_parse_context_free(context);
697 g_free(contents);
698 pounces_loaded = TRUE;
699
700 return FALSE;
701 }
702
703 g_markup_parse_context_free(context);
704 g_free(contents);
705
706 g_free(filename);
707
382 pounces_loaded = TRUE; 708 pounces_loaded = TRUE;
383 709
384 return TRUE; 710 return TRUE;
385 } 711 }
386 712
442 pouncer->protocol_id, pouncer_name); 768 pouncer->protocol_id, pouncer_name);
443 fprintf(fp, " <pouncee>%s</pouncee>\n", gaim_pounce_get_pouncee(pounce)); 769 fprintf(fp, " <pouncee>%s</pouncee>\n", gaim_pounce_get_pouncee(pounce));
444 fprintf(fp, " <events>\n"); 770 fprintf(fp, " <events>\n");
445 771
446 if (events & GAIM_POUNCE_SIGNON) 772 if (events & GAIM_POUNCE_SIGNON)
447 fprintf(fp, " <event type='sign-on'>\n"); 773 fprintf(fp, " <event type='sign-on'/>\n");
448 if (events & GAIM_POUNCE_SIGNOFF) 774 if (events & GAIM_POUNCE_SIGNOFF)
449 fprintf(fp, " <event type='sign-off'>\n"); 775 fprintf(fp, " <event type='sign-off'/>\n");
450 if (events & GAIM_POUNCE_AWAY) 776 if (events & GAIM_POUNCE_AWAY)
451 fprintf(fp, " <event type='away'>\n"); 777 fprintf(fp, " <event type='away'/>\n");
452 if (events & GAIM_POUNCE_AWAY_RETURN) 778 if (events & GAIM_POUNCE_AWAY_RETURN)
453 fprintf(fp, " <event type='return-from-away'>\n"); 779 fprintf(fp, " <event type='return-from-away'/>\n");
454 if (events & GAIM_POUNCE_IDLE) 780 if (events & GAIM_POUNCE_IDLE)
455 fprintf(fp, " <event type='idle'>\n"); 781 fprintf(fp, " <event type='idle'/>\n");
456 if (events & GAIM_POUNCE_IDLE_RETURN) 782 if (events & GAIM_POUNCE_IDLE_RETURN)
457 fprintf(fp, " <event type='return-from-idle'>\n"); 783 fprintf(fp, " <event type='return-from-idle'/>\n");
458 if (events & GAIM_POUNCE_TYPING) 784 if (events & GAIM_POUNCE_TYPING)
459 fprintf(fp, " <event type='start-typing'>\n"); 785 fprintf(fp, " <event type='start-typing'/>\n");
460 if (events & GAIM_POUNCE_TYPING_STOPPED) 786 if (events & GAIM_POUNCE_TYPING_STOPPED)
461 fprintf(fp, " <event type='stop-typing'>\n"); 787 fprintf(fp, " <event type='stop-typing'/>\n");
462 788
463 fprintf(fp, " </events>\n"); 789 fprintf(fp, " </events>\n");
464 fprintf(fp, " <actions>\n"); 790 fprintf(fp, " <actions>\n");
465 791
466 g_hash_table_foreach(pounce->actions, write_action_parameter_list, fp); 792 g_hash_table_foreach(pounce->actions, write_action_parameter_list, fp);
528 854
529 g_free(filename); 855 g_free(filename);
530 g_free(filename_real); 856 g_free(filename_real);
531 } 857 }
532 858
859 void
860 gaim_pounces_register_handler(const char *ui, GaimPounceCb cb,
861 void (*new_pounce)(GaimPounce *pounce),
862 void (*free_pounce)(GaimPounce *pounce))
863 {
864 GaimPounceHandler *handler;
865
866 g_return_if_fail(ui != NULL);
867 g_return_if_fail(cb != NULL);
868
869 handler = g_new0(GaimPounceHandler, 1);
870
871 handler->ui = g_strdup(ui);
872 handler->cb = cb;
873 handler->new_pounce = new_pounce;
874 handler->free_pounce = free_pounce;
875
876 g_hash_table_insert(pounce_handlers, g_strdup(ui), handler);
877 }
878
879 void
880 gaim_pounces_unregister_handler(const char *ui)
881 {
882 g_return_if_fail(ui != NULL);
883
884 g_hash_table_remove(pounce_handlers, ui);
885 }
886
533 GList * 887 GList *
534 gaim_pounces_get_all(void) 888 gaim_pounces_get_all(void)
535 { 889 {
536 return pounces; 890 return pounces;
537 } 891 }
892
893 static void
894 free_pounce_handler(gpointer user_data)
895 {
896 GaimPounceHandler *handler = (GaimPounceHandler *)user_data;
897
898 g_free(handler->ui);
899 g_free(handler);
900 }
901
902 void
903 gaim_pounces_init(void)
904 {
905 pounce_handlers = g_hash_table_new_full(g_str_hash, g_str_equal,
906 g_free, free_pounce_handler);
907 }