comparison src/pounce.c @ 10432:dc4475bf718f

[gaim-migrate @ 11684] Shuffle some things around in pounce.c to match savedstatuses.c, blist.c and accounts.c Write the pounces using the util function and xmlnodes (so pounces.xml is out-of-disk-space safe, now) committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Mon, 27 Dec 2004 08:56:04 +0000
parents 3232e1a33899
children 50224ac8184d
comparison
equal deleted inserted replaced
10431:843ed1f2bf3f 10432:dc4475bf718f
68 } GaimPounceHandler; 68 } GaimPounceHandler;
69 69
70 70
71 static GHashTable *pounce_handlers = NULL; 71 static GHashTable *pounce_handlers = NULL;
72 static GList *pounces = NULL; 72 static GList *pounces = NULL;
73 static guint pounces_save_timer = 0; 73 static guint save_timer = 0;
74 static gboolean pounces_loaded = FALSE; 74 static gboolean pounces_loaded = FALSE;
75 75
76
77 /*********************************************************************
78 * Private utility functions *
79 *********************************************************************/
76 80
77 static GaimPounceActionData * 81 static GaimPounceActionData *
78 find_action_data(const GaimPounce *pounce, const char *name) 82 find_action_data(const GaimPounce *pounce, const char *name)
79 { 83 {
80 GaimPounceActionData *action; 84 GaimPounceActionData *action;
97 g_hash_table_destroy(action_data->atts); 101 g_hash_table_destroy(action_data->atts);
98 102
99 g_free(action_data); 103 g_free(action_data);
100 } 104 }
101 105
106
107 /*********************************************************************
108 * Writing to disk *
109 *********************************************************************/
110
111 static void
112 action_parameter_to_xmlnode(gpointer key, gpointer value, gpointer user_data)
113 {
114 const char *name, *param_value;
115 xmlnode *node, *child;
116
117 name = (const char *)key;
118 param_value = (const char *)value;
119 node = (xmlnode *)user_data;
120
121 child = xmlnode_new_child(node, "param");
122 xmlnode_set_attrib(child, "name", name);
123 xmlnode_insert_data(child, param_value, -1);
124 }
125
126 static void
127 action_parameter_list_to_xmlnode(gpointer key, gpointer value, gpointer user_data)
128 {
129 const char *action;
130 GaimPounceActionData *action_data;
131 xmlnode *node, *child;
132
133 action = (const char *)key;
134 action_data = (GaimPounceActionData *)value;
135 node = (xmlnode *)user_data;
136
137 if (!action_data->enabled)
138 return;
139
140 child = xmlnode_new_child(node, "action");
141 xmlnode_set_attrib(child, "type", action);
142
143 g_hash_table_foreach(action_data->atts, action_parameter_to_xmlnode, child);
144 }
145
146 static void
147 add_event_to_xmlnode(xmlnode *node, const char *type)
148 {
149 xmlnode *child;
150
151 child = xmlnode_new_child(node, "event");
152 xmlnode_set_attrib(child, "type", type);
153 }
154
155 static xmlnode *
156 pounce_to_xmlnode(GaimPounce *pounce)
157 {
158 xmlnode *node, *child;
159 GaimAccount *pouncer;
160 GaimPounceEvent events;
161
162 pouncer = gaim_pounce_get_pouncer(pounce);
163 events = gaim_pounce_get_events(pounce);
164
165 node = xmlnode_new("pounce");
166 xmlnode_set_attrib(node, "ui", pounce->ui_type);
167
168 child = xmlnode_new_child(node, "account");
169 xmlnode_set_attrib(child, "protocol", pouncer->protocol_id);
170 xmlnode_insert_data(child, gaim_account_get_username(pouncer), -1);
171
172 child = xmlnode_new_child(node, "pouncee");
173 xmlnode_insert_data(child, gaim_pounce_get_pouncee(pounce), -1);
174
175 /* Write pounce events */
176 child = xmlnode_new_child(node, "events");
177 if (events & GAIM_POUNCE_SIGNON)
178 add_event_to_xmlnode(child, "sign-on");
179 if (events & GAIM_POUNCE_SIGNOFF)
180 add_event_to_xmlnode(child, "sign-off");
181 if (events & GAIM_POUNCE_AWAY)
182 add_event_to_xmlnode(child, "away");
183 if (events & GAIM_POUNCE_AWAY_RETURN)
184 add_event_to_xmlnode(child, "return-from-away");
185 if (events & GAIM_POUNCE_IDLE)
186 add_event_to_xmlnode(child, "idle");
187 if (events & GAIM_POUNCE_IDLE_RETURN)
188 add_event_to_xmlnode(child, "return-from-idle");
189 if (events & GAIM_POUNCE_TYPING)
190 add_event_to_xmlnode(child, "start-typing");
191 if (events & GAIM_POUNCE_TYPING_STOPPED)
192 add_event_to_xmlnode(child, "stop-typing");
193
194 /* Write pounce actions */
195 child = xmlnode_new_child(node, "actions");
196 g_hash_table_foreach(pounce->actions, action_parameter_list_to_xmlnode, child);
197
198 if (gaim_pounce_get_save(pounce))
199 child = xmlnode_new_child(node, "save");
200
201 return node;
202 }
203
204 static xmlnode *
205 pounces_to_xmlnode(void)
206 {
207 xmlnode *node, *child;
208 GList *cur;
209
210 node = xmlnode_new("pounces");
211 xmlnode_set_attrib(node, "version", "1.0");
212
213 for (cur = gaim_pounces_get_all(); cur != NULL; cur = cur->next)
214 {
215 child = pounce_to_xmlnode(cur->data);
216 xmlnode_insert_child(node, child);
217 }
218
219 return node;
220 }
221
222 static void
223 sync_pounces(void)
224 {
225 xmlnode *node;
226 char *data;
227
228 if (!pounces_loaded)
229 {
230 gaim_debug_error("pounce", "Attempted to save buddy pounces before "
231 "they were read!\n");
232 return;
233 }
234
235 node = pounces_to_xmlnode();
236 data = xmlnode_to_formatted_str(node, NULL);
237 gaim_util_write_data_to_file("pounces.xml", data, -1);
238 g_free(data);
239 xmlnode_free(node);
240 }
241
102 static gboolean 242 static gboolean
103 pounces_save_cb(gpointer unused) 243 save_cb(gpointer data)
104 { 244 {
105 gaim_pounces_sync(); 245 sync_pounces();
106 pounces_save_timer = 0; 246 save_timer = 0;
107
108 return FALSE; 247 return FALSE;
109 } 248 }
110 249
111 static void 250 static void
112 schedule_pounces_save(void) 251 schedule_pounces_save(void)
113 { 252 {
114 if (!pounces_save_timer) 253 if (save_timer == 0)
115 pounces_save_timer = gaim_timeout_add(5000, pounces_save_cb, NULL); 254 save_timer = gaim_timeout_add(5000, save_cb, NULL);
116 } 255 }
117 256
118 GaimPounce * 257
119 gaim_pounce_new(const char *ui_type, GaimAccount *pouncer, 258 /*********************************************************************
120 const char *pouncee, GaimPounceEvent event) 259 * Reading from disk *
121 { 260 *********************************************************************/
122 GaimPounce *pounce; 261
123 GaimPounceHandler *handler;
124
125 g_return_val_if_fail(ui_type != NULL, NULL);
126 g_return_val_if_fail(pouncer != NULL, NULL);
127 g_return_val_if_fail(pouncee != NULL, NULL);
128 g_return_val_if_fail(event != 0, NULL);
129
130 pounce = g_new0(GaimPounce, 1);
131
132 pounce->ui_type = g_strdup(ui_type);
133 pounce->pouncer = pouncer;
134 pounce->pouncee = g_strdup(pouncee);
135 pounce->events = event;
136
137 pounce->actions = g_hash_table_new_full(g_str_hash, g_str_equal,
138 g_free, free_action_data);
139
140 handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
141
142 if (handler != NULL && handler->new_pounce != NULL)
143 handler->new_pounce(pounce);
144
145 pounces = g_list_append(pounces, pounce);
146
147 return pounce;
148 }
149
150 void
151 gaim_pounce_destroy(GaimPounce *pounce)
152 {
153 GaimPounceHandler *handler;
154
155 g_return_if_fail(pounce != NULL);
156
157 handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
158
159 pounces = g_list_remove(pounces, pounce);
160
161 if (pounce->ui_type != NULL) g_free(pounce->ui_type);
162 if (pounce->pouncee != NULL) g_free(pounce->pouncee);
163
164 g_hash_table_destroy(pounce->actions);
165
166 if (handler != NULL && handler->free_pounce != NULL)
167 handler->free_pounce(pounce);
168
169 g_free(pounce);
170
171 schedule_pounces_save();
172 }
173
174 void
175 gaim_pounce_destroy_all_by_account(GaimAccount *account)
176 {
177 GaimAccount *pouncer;
178 GaimPounce *pounce;
179 GList *l, *l_next;
180
181 g_return_if_fail(account != NULL);
182
183 for (l = gaim_pounces_get_all(); l != NULL; l = l_next) {
184 pounce = (GaimPounce *)l->data;
185 l_next = l->next;
186
187 pouncer = gaim_pounce_get_pouncer(pounce);
188 if (pouncer == account)
189 gaim_pounce_destroy(pounce);
190 }
191 }
192
193 void
194 gaim_pounce_set_events(GaimPounce *pounce, GaimPounceEvent events)
195 {
196 g_return_if_fail(pounce != NULL);
197 g_return_if_fail(pounce != GAIM_POUNCE_NONE);
198
199 pounce->events = events;
200
201 schedule_pounces_save();
202 }
203
204 void
205 gaim_pounce_set_pouncer(GaimPounce *pounce, GaimAccount *pouncer)
206 {
207 g_return_if_fail(pounce != NULL);
208 g_return_if_fail(pouncer != NULL);
209
210 pounce->pouncer = pouncer;
211
212 schedule_pounces_save();
213 }
214
215 void
216 gaim_pounce_set_pouncee(GaimPounce *pounce, const char *pouncee)
217 {
218 g_return_if_fail(pounce != NULL);
219 g_return_if_fail(pouncee != NULL);
220
221 if (pounce->pouncee != NULL)
222 g_free(pounce->pouncee);
223
224 pounce->pouncee = (pouncee == NULL ? NULL : g_strdup(pouncee));
225
226 schedule_pounces_save();
227 }
228
229 void
230 gaim_pounce_set_save(GaimPounce *pounce, gboolean save)
231 {
232 g_return_if_fail(pounce != NULL);
233
234 pounce->save = save;
235
236 schedule_pounces_save();
237 }
238
239 void
240 gaim_pounce_action_register(GaimPounce *pounce, const char *name)
241 {
242 GaimPounceActionData *action_data;
243
244 g_return_if_fail(pounce != NULL);
245 g_return_if_fail(name != NULL);
246
247 if (g_hash_table_lookup(pounce->actions, name) != NULL)
248 return;
249
250 action_data = g_new0(GaimPounceActionData, 1);
251
252 action_data->name = g_strdup(name);
253 action_data->enabled = FALSE;
254 action_data->atts = g_hash_table_new_full(g_str_hash, g_str_equal,
255 g_free, g_free);
256
257 g_hash_table_insert(pounce->actions, g_strdup(name), action_data);
258
259 schedule_pounces_save();
260 }
261
262 void
263 gaim_pounce_action_set_enabled(GaimPounce *pounce, const char *action,
264 gboolean enabled)
265 {
266 GaimPounceActionData *action_data;
267
268 g_return_if_fail(pounce != NULL);
269 g_return_if_fail(action != NULL);
270
271 action_data = find_action_data(pounce, action);
272
273 g_return_if_fail(action_data != NULL);
274
275 action_data->enabled = enabled;
276
277 schedule_pounces_save();
278 }
279
280 void
281 gaim_pounce_action_set_attribute(GaimPounce *pounce, const char *action,
282 const char *attr, const char *value)
283 {
284 GaimPounceActionData *action_data;
285
286 g_return_if_fail(pounce != NULL);
287 g_return_if_fail(action != NULL);
288 g_return_if_fail(attr != NULL);
289
290 action_data = find_action_data(pounce, action);
291
292 g_return_if_fail(action_data != NULL);
293
294 if (value == NULL)
295 g_hash_table_remove(action_data->atts, attr);
296 else
297 g_hash_table_insert(action_data->atts, g_strdup(attr),
298 g_strdup(value));
299
300 schedule_pounces_save();
301 }
302
303 void
304 gaim_pounce_set_data(GaimPounce *pounce, void *data)
305 {
306 g_return_if_fail(pounce != NULL);
307
308 pounce->data = data;
309 }
310
311 GaimPounceEvent
312 gaim_pounce_get_events(const GaimPounce *pounce)
313 {
314 g_return_val_if_fail(pounce != NULL, GAIM_POUNCE_NONE);
315
316 return pounce->events;
317 }
318
319 GaimAccount *
320 gaim_pounce_get_pouncer(const GaimPounce *pounce)
321 {
322 g_return_val_if_fail(pounce != NULL, NULL);
323
324 return pounce->pouncer;
325 }
326
327 const char *
328 gaim_pounce_get_pouncee(const GaimPounce *pounce)
329 {
330 g_return_val_if_fail(pounce != NULL, NULL);
331
332 return pounce->pouncee;
333 }
334
335 gboolean
336 gaim_pounce_get_save(const GaimPounce *pounce)
337 {
338 g_return_val_if_fail(pounce != NULL, FALSE);
339
340 return pounce->save;
341 }
342
343 gboolean
344 gaim_pounce_action_is_enabled(const GaimPounce *pounce, const char *action)
345 {
346 GaimPounceActionData *action_data;
347
348 g_return_val_if_fail(pounce != NULL, FALSE);
349 g_return_val_if_fail(action != NULL, FALSE);
350
351 action_data = find_action_data(pounce, action);
352
353 g_return_val_if_fail(action_data != NULL, FALSE);
354
355 return action_data->enabled;
356 }
357
358 const char *
359 gaim_pounce_action_get_attribute(const GaimPounce *pounce,
360 const char *action, const char *attr)
361 {
362 GaimPounceActionData *action_data;
363
364 g_return_val_if_fail(pounce != NULL, NULL);
365 g_return_val_if_fail(action != NULL, NULL);
366 g_return_val_if_fail(attr != NULL, NULL);
367
368 action_data = find_action_data(pounce, action);
369
370 g_return_val_if_fail(action_data != NULL, NULL);
371
372 return g_hash_table_lookup(action_data->atts, attr);
373 }
374
375 void *
376 gaim_pounce_get_data(const GaimPounce *pounce)
377 {
378 g_return_val_if_fail(pounce != NULL, NULL);
379
380 return pounce->data;
381 }
382
383 void
384 gaim_pounce_execute(const GaimAccount *pouncer, const char *pouncee,
385 GaimPounceEvent events)
386 {
387 GaimPounce *pounce;
388 GaimPounceHandler *handler;
389 GList *l, *l_next;
390 char *norm_pouncee;
391
392 g_return_if_fail(pouncer != NULL);
393 g_return_if_fail(pouncee != NULL);
394 g_return_if_fail(events != GAIM_POUNCE_NONE);
395
396 norm_pouncee = g_strdup(gaim_normalize(pouncer, pouncee));
397
398 for (l = gaim_pounces_get_all(); l != NULL; l = l_next)
399 {
400 pounce = (GaimPounce *)l->data;
401 l_next = l->next;
402
403 if ((gaim_pounce_get_events(pounce) & events) &&
404 (gaim_pounce_get_pouncer(pounce) == pouncer) &&
405 !gaim_utf8_strcasecmp(gaim_normalize(pouncer, gaim_pounce_get_pouncee(pounce)),
406 norm_pouncee))
407 {
408 handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
409
410 if (handler != NULL && handler->cb != NULL)
411 {
412 handler->cb(pounce, events, gaim_pounce_get_data(pounce));
413
414 if (!gaim_pounce_get_save(pounce))
415 gaim_pounce_destroy(pounce);
416 }
417 }
418 }
419
420 g_free(norm_pouncee);
421 }
422
423 GaimPounce *
424 gaim_find_pounce(const GaimAccount *pouncer, const char *pouncee,
425 GaimPounceEvent events)
426 {
427 GaimPounce *pounce = NULL;
428 GList *l;
429 char *norm_pouncee;
430
431 g_return_val_if_fail(pouncer != NULL, NULL);
432 g_return_val_if_fail(pouncee != NULL, NULL);
433 g_return_val_if_fail(events != GAIM_POUNCE_NONE, NULL);
434
435 norm_pouncee = g_strdup(gaim_normalize(pouncer, pouncee));
436
437 for (l = gaim_pounces_get_all(); l != NULL; l = l->next)
438 {
439 pounce = (GaimPounce *)l->data;
440
441 if ((gaim_pounce_get_events(pounce) & events) &&
442 (gaim_pounce_get_pouncer(pounce) == pouncer) &&
443 !gaim_utf8_strcasecmp(gaim_normalize(pouncer, gaim_pounce_get_pouncee(pounce)),
444 norm_pouncee))
445 {
446 break;
447 }
448
449 pounce = NULL;
450 }
451
452 g_free(norm_pouncee);
453
454 return pounce;
455 }
456
457 /* XML Stuff */
458 static void 262 static void
459 free_parser_data(gpointer user_data) 263 free_parser_data(gpointer user_data)
460 { 264 {
461 PounceParserData *data = user_data; 265 PounceParserData *data = user_data;
462 266
748 pounces_loaded = TRUE; 552 pounces_loaded = TRUE;
749 553
750 return TRUE; 554 return TRUE;
751 } 555 }
752 556
753 static void 557
754 write_action_parameter(gpointer key, gpointer value, gpointer user_data) 558 GaimPounce *
755 { 559 gaim_pounce_new(const char *ui_type, GaimAccount *pouncer,
756 const char *name, *param_value; 560 const char *pouncee, GaimPounceEvent event)
757 FILE *fp; 561 {
758 562 GaimPounce *pounce;
759 param_value = (const char *)value; 563 GaimPounceHandler *handler;
760 name = (const char *)key; 564
761 fp = (FILE *)user_data; 565 g_return_val_if_fail(ui_type != NULL, NULL);
762 566 g_return_val_if_fail(pouncer != NULL, NULL);
763 fprintf(fp, " <param name='%s'>%s</param>\n", name, param_value); 567 g_return_val_if_fail(pouncee != NULL, NULL);
764 } 568 g_return_val_if_fail(event != 0, NULL);
765 569
766 static void 570 pounce = g_new0(GaimPounce, 1);
767 write_action_parameter_list(gpointer key, gpointer value, gpointer user_data) 571
572 pounce->ui_type = g_strdup(ui_type);
573 pounce->pouncer = pouncer;
574 pounce->pouncee = g_strdup(pouncee);
575 pounce->events = event;
576
577 pounce->actions = g_hash_table_new_full(g_str_hash, g_str_equal,
578 g_free, free_action_data);
579
580 handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
581
582 if (handler != NULL && handler->new_pounce != NULL)
583 handler->new_pounce(pounce);
584
585 pounces = g_list_append(pounces, pounce);
586
587 schedule_pounces_save();
588
589 return pounce;
590 }
591
592 void
593 gaim_pounce_destroy(GaimPounce *pounce)
594 {
595 GaimPounceHandler *handler;
596
597 g_return_if_fail(pounce != NULL);
598
599 handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
600
601 pounces = g_list_remove(pounces, pounce);
602
603 if (pounce->ui_type != NULL) g_free(pounce->ui_type);
604 if (pounce->pouncee != NULL) g_free(pounce->pouncee);
605
606 g_hash_table_destroy(pounce->actions);
607
608 if (handler != NULL && handler->free_pounce != NULL)
609 handler->free_pounce(pounce);
610
611 g_free(pounce);
612
613 schedule_pounces_save();
614 }
615
616 void
617 gaim_pounce_destroy_all_by_account(GaimAccount *account)
618 {
619 GaimAccount *pouncer;
620 GaimPounce *pounce;
621 GList *l, *l_next;
622
623 g_return_if_fail(account != NULL);
624
625 for (l = gaim_pounces_get_all(); l != NULL; l = l_next)
626 {
627 pounce = (GaimPounce *)l->data;
628 l_next = l->next;
629
630 pouncer = gaim_pounce_get_pouncer(pounce);
631 if (pouncer == account)
632 gaim_pounce_destroy(pounce);
633 }
634 }
635
636 void
637 gaim_pounce_set_events(GaimPounce *pounce, GaimPounceEvent events)
638 {
639 g_return_if_fail(pounce != NULL);
640 g_return_if_fail(pounce != GAIM_POUNCE_NONE);
641
642 pounce->events = events;
643
644 schedule_pounces_save();
645 }
646
647 void
648 gaim_pounce_set_pouncer(GaimPounce *pounce, GaimAccount *pouncer)
649 {
650 g_return_if_fail(pounce != NULL);
651 g_return_if_fail(pouncer != NULL);
652
653 pounce->pouncer = pouncer;
654
655 schedule_pounces_save();
656 }
657
658 void
659 gaim_pounce_set_pouncee(GaimPounce *pounce, const char *pouncee)
660 {
661 g_return_if_fail(pounce != NULL);
662 g_return_if_fail(pouncee != NULL);
663
664 if (pounce->pouncee != NULL)
665 g_free(pounce->pouncee);
666
667 pounce->pouncee = (pouncee == NULL ? NULL : g_strdup(pouncee));
668
669 schedule_pounces_save();
670 }
671
672 void
673 gaim_pounce_set_save(GaimPounce *pounce, gboolean save)
674 {
675 g_return_if_fail(pounce != NULL);
676
677 pounce->save = save;
678
679 schedule_pounces_save();
680 }
681
682 void
683 gaim_pounce_action_register(GaimPounce *pounce, const char *name)
768 { 684 {
769 GaimPounceActionData *action_data; 685 GaimPounceActionData *action_data;
770 const char *action; 686
771 FILE *fp; 687 g_return_if_fail(pounce != NULL);
772 688 g_return_if_fail(name != NULL);
773 action_data = (GaimPounceActionData *)value; 689
774 action = (const char *)key; 690 if (g_hash_table_lookup(pounce->actions, name) != NULL)
775 fp = (FILE *)user_data;
776
777 if (!action_data->enabled)
778 return; 691 return;
779 692
780 fprintf(fp, " <action type='%s'", action); 693 action_data = g_new0(GaimPounceActionData, 1);
781 694
782 if (g_hash_table_size(action_data->atts) == 0) { 695 action_data->name = g_strdup(name);
783 fprintf(fp, "/>\n"); 696 action_data->enabled = FALSE;
784 } 697 action_data->atts = g_hash_table_new_full(g_str_hash, g_str_equal,
785 else { 698 g_free, g_free);
786 fprintf(fp, ">\n"); 699
787 700 g_hash_table_insert(pounce->actions, g_strdup(name), action_data);
788 g_hash_table_foreach(action_data->atts, write_action_parameter, fp); 701
789 702 schedule_pounces_save();
790 fprintf(fp, " </action>\n"); 703 }
791 } 704
792 } 705 void
793 706 gaim_pounce_action_set_enabled(GaimPounce *pounce, const char *action,
794 static void 707 gboolean enabled)
795 gaim_pounces_write(FILE *fp, GaimPounce *pounce) 708 {
796 { 709 GaimPounceActionData *action_data;
797 GaimAccount *pouncer; 710
798 GaimPounceEvent events; 711 g_return_if_fail(pounce != NULL);
799 char *pouncer_name; 712 g_return_if_fail(action != NULL);
800 713
801 pouncer = gaim_pounce_get_pouncer(pounce); 714 action_data = find_action_data(pounce, action);
802 events = gaim_pounce_get_events(pounce); 715
803 716 g_return_if_fail(action_data != NULL);
804 pouncer_name = g_markup_escape_text(gaim_account_get_username(pouncer), -1); 717
805 718 action_data->enabled = enabled;
806 fprintf(fp, " <pounce ui='%s'>\n", pounce->ui_type); 719
807 fprintf(fp, " <account protocol='%s'>%s</account>\n", 720 schedule_pounces_save();
808 pouncer->protocol_id, pouncer_name); 721 }
809 fprintf(fp, " <pouncee>%s</pouncee>\n", gaim_pounce_get_pouncee(pounce)); 722
810 fprintf(fp, " <events>\n"); 723 void
811 724 gaim_pounce_action_set_attribute(GaimPounce *pounce, const char *action,
812 if (events & GAIM_POUNCE_SIGNON) 725 const char *attr, const char *value)
813 fprintf(fp, " <event type='sign-on'/>\n"); 726 {
814 if (events & GAIM_POUNCE_SIGNOFF) 727 GaimPounceActionData *action_data;
815 fprintf(fp, " <event type='sign-off'/>\n"); 728
816 if (events & GAIM_POUNCE_AWAY) 729 g_return_if_fail(pounce != NULL);
817 fprintf(fp, " <event type='away'/>\n"); 730 g_return_if_fail(action != NULL);
818 if (events & GAIM_POUNCE_AWAY_RETURN) 731 g_return_if_fail(attr != NULL);
819 fprintf(fp, " <event type='return-from-away'/>\n"); 732
820 if (events & GAIM_POUNCE_IDLE) 733 action_data = find_action_data(pounce, action);
821 fprintf(fp, " <event type='idle'/>\n"); 734
822 if (events & GAIM_POUNCE_IDLE_RETURN) 735 g_return_if_fail(action_data != NULL);
823 fprintf(fp, " <event type='return-from-idle'/>\n"); 736
824 if (events & GAIM_POUNCE_TYPING) 737 if (value == NULL)
825 fprintf(fp, " <event type='start-typing'/>\n"); 738 g_hash_table_remove(action_data->atts, attr);
826 if (events & GAIM_POUNCE_TYPING_STOPPED)
827 fprintf(fp, " <event type='stop-typing'/>\n");
828
829 fprintf(fp, " </events>\n");
830 fprintf(fp, " <actions>\n");
831
832 g_hash_table_foreach(pounce->actions, write_action_parameter_list, fp);
833
834 fprintf(fp, " </actions>\n");
835
836 if (gaim_pounce_get_save(pounce))
837 fprintf(fp, " <save/>\n");
838
839 fprintf(fp, " </pounce>\n");
840
841 g_free(pouncer_name);
842 }
843
844 void
845 gaim_pounces_sync(void)
846 {
847 FILE *fp;
848 struct stat st;
849 const char *user_dir = gaim_user_dir();
850 char *filename;
851 char *filename_real;
852
853 if (!pounces_loaded) {
854 gaim_debug(GAIM_DEBUG_WARNING, "pounces",
855 "Writing pounces to disk.\n");
856 schedule_pounces_save();
857 return;
858 }
859
860 if (user_dir == NULL)
861 return;
862
863 gaim_debug(GAIM_DEBUG_INFO, "pounces", "Writing pounces to disk.\n");
864
865 fp = fopen(user_dir, "r");
866
867 if (fp == NULL)
868 mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
869 else 739 else
870 fclose(fp); 740 g_hash_table_insert(action_data->atts, g_strdup(attr),
871 741 g_strdup(value));
872 filename = g_build_filename(user_dir, "pounces.xml.save", NULL); 742
873 743 schedule_pounces_save();
874 if ((fp = fopen(filename, "w")) != NULL) { 744 }
875 GList *l; 745
876 746 void
877 fprintf(fp, "<?xml version='1.0' encoding='UTF-8' ?>\n\n"); 747 gaim_pounce_set_data(GaimPounce *pounce, void *data)
878 fprintf(fp, "<pounces version='1.0'>\n"); 748 {
879 749 g_return_if_fail(pounce != NULL);
880 for (l = gaim_pounces_get_all(); l != NULL; l = l->next) 750
881 gaim_pounces_write(fp, l->data); 751 pounce->data = data;
882 752
883 fprintf(fp, "</pounces>\n"); 753 schedule_pounces_save();
884 754 }
885 fclose(fp); 755
886 chmod(filename, S_IRUSR | S_IWUSR); 756 GaimPounceEvent
887 } 757 gaim_pounce_get_events(const GaimPounce *pounce)
888 else { 758 {
889 gaim_debug(GAIM_DEBUG_ERROR, "pounces", "Unable to write %s\n", 759 g_return_val_if_fail(pounce != NULL, GAIM_POUNCE_NONE);
890 filename); 760
891 g_free(filename); 761 return pounce->events;
892 return; 762 }
893 } 763
894 764 GaimAccount *
895 if (stat(filename, &st) || (st.st_size == 0)) { 765 gaim_pounce_get_pouncer(const GaimPounce *pounce)
896 gaim_debug_error("pounces", "Failed to save pounces\n"); 766 {
897 unlink(filename); 767 g_return_val_if_fail(pounce != NULL, NULL);
898 g_free(filename); 768
899 return; 769 return pounce->pouncer;
900 } 770 }
901 771
902 filename_real = g_build_filename(user_dir, "pounces.xml", NULL); 772 const char *
903 773 gaim_pounce_get_pouncee(const GaimPounce *pounce)
904 if (rename(filename, filename_real) < 0) { 774 {
905 gaim_debug(GAIM_DEBUG_ERROR, "pounces", "Error renaming %s to %s\n", 775 g_return_val_if_fail(pounce != NULL, NULL);
906 filename, filename_real); 776
907 } 777 return pounce->pouncee;
908 778 }
909 g_free(filename); 779
910 g_free(filename_real); 780 gboolean
781 gaim_pounce_get_save(const GaimPounce *pounce)
782 {
783 g_return_val_if_fail(pounce != NULL, FALSE);
784
785 return pounce->save;
786 }
787
788 gboolean
789 gaim_pounce_action_is_enabled(const GaimPounce *pounce, const char *action)
790 {
791 GaimPounceActionData *action_data;
792
793 g_return_val_if_fail(pounce != NULL, FALSE);
794 g_return_val_if_fail(action != NULL, FALSE);
795
796 action_data = find_action_data(pounce, action);
797
798 g_return_val_if_fail(action_data != NULL, FALSE);
799
800 return action_data->enabled;
801 }
802
803 const char *
804 gaim_pounce_action_get_attribute(const GaimPounce *pounce,
805 const char *action, const char *attr)
806 {
807 GaimPounceActionData *action_data;
808
809 g_return_val_if_fail(pounce != NULL, NULL);
810 g_return_val_if_fail(action != NULL, NULL);
811 g_return_val_if_fail(attr != NULL, NULL);
812
813 action_data = find_action_data(pounce, action);
814
815 g_return_val_if_fail(action_data != NULL, NULL);
816
817 return g_hash_table_lookup(action_data->atts, attr);
818 }
819
820 void *
821 gaim_pounce_get_data(const GaimPounce *pounce)
822 {
823 g_return_val_if_fail(pounce != NULL, NULL);
824
825 return pounce->data;
826 }
827
828 void
829 gaim_pounce_execute(const GaimAccount *pouncer, const char *pouncee,
830 GaimPounceEvent events)
831 {
832 GaimPounce *pounce;
833 GaimPounceHandler *handler;
834 GList *l, *l_next;
835 char *norm_pouncee;
836
837 g_return_if_fail(pouncer != NULL);
838 g_return_if_fail(pouncee != NULL);
839 g_return_if_fail(events != GAIM_POUNCE_NONE);
840
841 norm_pouncee = g_strdup(gaim_normalize(pouncer, pouncee));
842
843 for (l = gaim_pounces_get_all(); l != NULL; l = l_next)
844 {
845 pounce = (GaimPounce *)l->data;
846 l_next = l->next;
847
848 if ((gaim_pounce_get_events(pounce) & events) &&
849 (gaim_pounce_get_pouncer(pounce) == pouncer) &&
850 !gaim_utf8_strcasecmp(gaim_normalize(pouncer, gaim_pounce_get_pouncee(pounce)),
851 norm_pouncee))
852 {
853 handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
854
855 if (handler != NULL && handler->cb != NULL)
856 {
857 handler->cb(pounce, events, gaim_pounce_get_data(pounce));
858
859 if (!gaim_pounce_get_save(pounce))
860 gaim_pounce_destroy(pounce);
861 }
862 }
863 }
864
865 g_free(norm_pouncee);
866 }
867
868 GaimPounce *
869 gaim_find_pounce(const GaimAccount *pouncer, const char *pouncee,
870 GaimPounceEvent events)
871 {
872 GaimPounce *pounce = NULL;
873 GList *l;
874 char *norm_pouncee;
875
876 g_return_val_if_fail(pouncer != NULL, NULL);
877 g_return_val_if_fail(pouncee != NULL, NULL);
878 g_return_val_if_fail(events != GAIM_POUNCE_NONE, NULL);
879
880 norm_pouncee = g_strdup(gaim_normalize(pouncer, pouncee));
881
882 for (l = gaim_pounces_get_all(); l != NULL; l = l->next)
883 {
884 pounce = (GaimPounce *)l->data;
885
886 if ((gaim_pounce_get_events(pounce) & events) &&
887 (gaim_pounce_get_pouncer(pounce) == pouncer) &&
888 !gaim_utf8_strcasecmp(gaim_normalize(pouncer, gaim_pounce_get_pouncee(pounce)),
889 norm_pouncee))
890 {
891 break;
892 }
893
894 pounce = NULL;
895 }
896
897 g_free(norm_pouncee);
898
899 return pounce;
911 } 900 }
912 901
913 void 902 void
914 gaim_pounces_register_handler(const char *ui, GaimPounceCb cb, 903 gaim_pounces_register_handler(const char *ui, GaimPounceCb cb,
915 void (*new_pounce)(GaimPounce *pounce), 904 void (*new_pounce)(GaimPounce *pounce),
985 } 974 }
986 975
987 void 976 void
988 gaim_pounces_init(void) 977 gaim_pounces_init(void)
989 { 978 {
979 void *handle = gaim_pounces_get_handle();
990 void *blist_handle = gaim_blist_get_handle(); 980 void *blist_handle = gaim_blist_get_handle();
991 void *conv_handle = gaim_conversations_get_handle(); 981 void *conv_handle = gaim_conversations_get_handle();
992 void *handle = gaim_pounces_get_handle();
993 982
994 pounce_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, 983 pounce_handlers = g_hash_table_new_full(g_str_hash, g_str_equal,
995 g_free, free_pounce_handler); 984 g_free, free_pounce_handler);
996 985
997 gaim_signal_connect(blist_handle, "buddy-idle", 986 gaim_signal_connect(blist_handle, "buddy-idle",
1020 } 1009 }
1021 1010
1022 void 1011 void
1023 gaim_pounces_uninit() 1012 gaim_pounces_uninit()
1024 { 1013 {
1025 if (pounces_save_timer != 0) { 1014 if (save_timer != 0)
1026 gaim_timeout_remove(pounces_save_timer); 1015 {
1027 pounces_save_timer = 0; 1016 gaim_timeout_remove(save_timer);
1028 gaim_pounces_sync(); 1017 save_timer = 0;
1018 sync_pounces();
1029 } 1019 }
1030 1020
1031 gaim_signals_disconnect_by_handle(gaim_pounces_get_handle()); 1021 gaim_signals_disconnect_by_handle(gaim_pounces_get_handle());
1032 } 1022 }