Mercurial > pidgin
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 } |