Mercurial > pidgin
annotate src/status.c @ 10760:f93ed7f6ecc7
[gaim-migrate @ 12363]
Changing your away message by just typing new text into the GtkStatusBox
works again. I broke that earlier today when I fix a small bit of the
which-status-is-the-active-status-in-this-presence thing.
I also removed the log in or out in account.c depending on the status that
was set. This was already handled by most of the PRPLs, and I feel that's
the best way to do it.
There was some talk of removing the login and close PRPL callbacks, and
I'm not entirely against that, but things are starting to get pretty good.
I don't see a need to change that right now.
Also, I'm going to add a link to my (Mark Doliner) blog, for google,
I guess: http://www.livejournal.com/users/thekingant/
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 28 Mar 2005 04:26:33 +0000 |
parents | 8a97b59f0071 |
children | d01d81de94d8 |
rev | line source |
---|---|
9944 | 1 /** |
10067 | 2 * @file status.c Status API |
9944 | 3 * @ingroup core |
4 * | |
6065 | 5 * gaim |
6 * | |
8046 | 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. | |
9944 | 10 * |
6065 | 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 */ | |
9949 | 25 #include "internal.h" |
6065 | 26 |
9949 | 27 #include "blist.h" |
10400 | 28 #include "core.h" |
9949 | 29 #include "debug.h" |
10337 | 30 #include "notify.h" |
9949 | 31 #include "prefs.h" |
6065 | 32 #include "status.h" |
33 | |
9949 | 34 /** |
35 * A type of status. | |
36 */ | |
37 struct _GaimStatusType | |
38 { | |
39 GaimStatusPrimitive primitive; | |
6371
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
40 |
9949 | 41 char *id; |
42 char *name; | |
43 char *primary_attr_id; | |
44 | |
45 gboolean saveable; | |
46 gboolean user_settable; | |
47 gboolean independent; | |
48 | |
49 GList *attrs; | |
50 }; | |
6371
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
51 |
9949 | 52 /** |
53 * A status attribute. | |
54 */ | |
55 struct _GaimStatusAttr | |
56 { | |
57 char *id; | |
58 char *name; | |
59 GaimValue *value_type; | |
60 }; | |
6065 | 61 |
9949 | 62 /** |
63 * A list of statuses. | |
64 */ | |
65 struct _GaimPresence | |
66 { | |
67 GaimPresenceContext context; | |
68 | |
69 gboolean idle; | |
70 time_t idle_time; | |
10006 | 71 time_t login_time; |
9949 | 72 |
73 unsigned int warning_level; | |
6065 | 74 |
9949 | 75 GList *statuses; |
76 GHashTable *status_table; | |
77 | |
78 GaimStatus *active_status; | |
6065 | 79 |
9949 | 80 union |
81 { | |
82 GaimAccount *account; | |
83 | |
84 struct | |
85 { | |
86 GaimConversation *conv; | |
87 char *user; | |
88 | |
89 } chat; | |
6065 | 90 |
9949 | 91 struct |
92 { | |
93 GaimAccount *account; | |
94 char *name; | |
95 size_t ref_count; | |
96 GList *buddies; | |
97 | |
98 } buddy; | |
99 | |
100 } u; | |
101 }; | |
102 | |
103 /** | |
104 * An active status. | |
105 */ | |
106 struct _GaimStatus | |
6065 | 107 { |
9949 | 108 GaimStatusType *type; |
109 GaimPresence *presence; | |
110 | |
111 const char *title; | |
6065 | 112 |
9949 | 113 gboolean active; |
6065 | 114 |
9949 | 115 GHashTable *attr_values; |
116 }; | |
6065 | 117 |
118 typedef struct | |
119 { | |
9949 | 120 GaimAccount *account; |
121 char *name; | |
122 } GaimStatusBuddyKey; | |
123 | |
124 static int primitive_scores[] = | |
125 { | |
126 0, /* unset */ | |
127 -500, /* offline */ | |
128 0, /* online */ | |
129 100, /* available */ | |
130 -75, /* unavailable */ | |
131 -50, /* hidden */ | |
132 -100, /* away */ | |
133 -200 /* extended away */ | |
134 -10, /* idle, special case. */ | |
135 -5 /* idle time, special case. */ | |
136 }; | |
137 | |
138 static GHashTable *buddy_presences = NULL; | |
139 | |
140 #define SCORE_IDLE 5 | |
141 #define SCORE_IDLE_TIME 6 | |
142 | |
143 /************************************************************************** | |
10419 | 144 * GaimStatusPrimitive API |
145 **************************************************************************/ | |
146 static struct GaimStatusPrimitiveMap | |
147 { | |
148 GaimStatusPrimitive type; | |
149 const char *id; | |
150 const char *name; | |
151 | |
152 } const status_primitive_map[] = | |
153 { | |
154 { GAIM_STATUS_UNSET, "unset", N_("Unset") }, | |
155 { GAIM_STATUS_OFFLINE, "offline", N_("Offline") }, | |
156 { GAIM_STATUS_ONLINE, "online", N_("Online") }, | |
157 { GAIM_STATUS_AVAILABLE, "available", N_("Available") }, | |
158 { GAIM_STATUS_UNAVAILABLE, "unavailable", N_("Unavailable") }, | |
159 { GAIM_STATUS_HIDDEN, "hidden", N_("Hidden") }, | |
160 { GAIM_STATUS_AWAY, "away", N_("Away") }, | |
161 { GAIM_STATUS_EXTENDED_AWAY, "extended_away", N_("Extended Away") } | |
162 }; | |
163 | |
164 const char * | |
165 gaim_primitive_get_id_from_type(GaimStatusPrimitive type) | |
166 { | |
167 int i; | |
168 | |
169 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) | |
170 { | |
171 if (type == status_primitive_map[i].type) | |
172 return status_primitive_map[i].id; | |
173 } | |
174 | |
175 return status_primitive_map[0].id; | |
176 } | |
177 | |
178 const char * | |
179 gaim_primitive_get_name_from_type(GaimStatusPrimitive type) | |
180 { | |
181 int i; | |
182 | |
183 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) | |
184 { | |
185 if (type == status_primitive_map[i].type) | |
186 return status_primitive_map[i].name; | |
187 } | |
188 | |
189 return status_primitive_map[0].name; | |
190 } | |
191 | |
192 GaimStatusPrimitive | |
193 gaim_primitive_get_type_from_id(const char *id) | |
194 { | |
195 int i; | |
196 | |
197 g_return_val_if_fail(id != NULL, GAIM_STATUS_UNSET); | |
198 | |
199 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) | |
200 { | |
201 if (!strcmp(id, status_primitive_map[i].id)) | |
202 return status_primitive_map[i].type; | |
203 } | |
204 | |
205 return status_primitive_map[0].type; | |
206 } | |
207 | |
208 | |
209 /************************************************************************** | |
9949 | 210 * GaimStatusType API |
211 **************************************************************************/ | |
212 GaimStatusType * | |
213 gaim_status_type_new_full(GaimStatusPrimitive primitive, const char *id, | |
10009 | 214 const char *name, gboolean saveable, |
215 gboolean user_settable, gboolean independent) | |
9949 | 216 { |
217 GaimStatusType *status_type; | |
218 | |
219 g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, NULL); | |
220 g_return_val_if_fail(id != NULL, NULL); | |
221 g_return_val_if_fail(name != NULL, NULL); | |
222 | |
223 status_type = g_new0(GaimStatusType, 1); | |
224 | |
225 status_type->primitive = primitive; | |
226 status_type->id = g_strdup(id); | |
227 status_type->name = g_strdup(name); | |
228 status_type->saveable = saveable; | |
229 status_type->user_settable = user_settable; | |
230 status_type->independent = independent; | |
231 | |
232 return status_type; | |
233 } | |
234 | |
235 GaimStatusType * | |
236 gaim_status_type_new(GaimStatusPrimitive primitive, const char *id, | |
10009 | 237 const char *name, gboolean user_settable) |
9949 | 238 { |
239 g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, NULL); | |
240 g_return_val_if_fail(id != NULL, NULL); | |
241 g_return_val_if_fail(name != NULL, NULL); | |
242 | |
243 return gaim_status_type_new_full(primitive, id, name, FALSE, | |
244 user_settable, FALSE); | |
245 } | |
246 | |
247 GaimStatusType * | |
248 gaim_status_type_new_with_attrs(GaimStatusPrimitive primitive, | |
249 const char *id, const char *name, | |
250 gboolean saveable, gboolean user_settable, | |
251 gboolean independent, const char *attr_id, | |
252 const char *attr_name, GaimValue *attr_value, | |
253 ...) | |
254 { | |
255 GaimStatusType *status_type; | |
256 va_list args; | |
257 | |
258 g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, NULL); | |
259 g_return_val_if_fail(id != NULL, NULL); | |
260 g_return_val_if_fail(name != NULL, NULL); | |
10012 | 261 g_return_val_if_fail(attr_id != NULL, NULL); |
9949 | 262 g_return_val_if_fail(attr_name != NULL, NULL); |
263 g_return_val_if_fail(attr_value != NULL, NULL); | |
264 | |
265 status_type = gaim_status_type_new_full(primitive, id, name, saveable, | |
266 user_settable, independent); | |
267 | |
10010 | 268 /* Add the first attribute */ |
9949 | 269 gaim_status_type_add_attr(status_type, attr_id, attr_name, attr_value); |
270 | |
271 va_start(args, attr_value); | |
272 gaim_status_type_add_attrs_vargs(status_type, args); | |
273 va_end(args); | |
274 | |
275 return status_type; | |
276 } | |
277 | |
278 void | |
279 gaim_status_type_destroy(GaimStatusType *status_type) | |
280 { | |
281 GList *l; | |
282 | |
283 g_return_if_fail(status_type != NULL); | |
284 | |
285 g_free(status_type->id); | |
286 g_free(status_type->name); | |
287 | |
288 if (status_type->primary_attr_id != NULL) | |
289 g_free(status_type->primary_attr_id); | |
290 | |
291 if (status_type->attrs != NULL) | |
292 { | |
293 for (l = status_type->attrs; l != NULL; l = l->next) | |
294 gaim_status_attr_destroy((GaimStatusAttr *)l->data); | |
295 | |
296 g_list_free(status_type->attrs); | |
297 } | |
298 | |
299 g_free(status_type); | |
300 } | |
301 | |
302 void | |
303 gaim_status_type_set_primary_attr(GaimStatusType *status_type, const char *id) | |
304 { | |
305 g_return_if_fail(status_type != NULL); | |
306 | |
307 if (status_type->primary_attr_id != NULL) | |
308 g_free(status_type->primary_attr_id); | |
309 | |
310 status_type->primary_attr_id = (id == NULL ? NULL : g_strdup(id)); | |
311 } | |
312 | |
313 void | |
10197 | 314 gaim_status_type_add_attr(GaimStatusType *status_type, const char *id, |
9949 | 315 const char *name, GaimValue *value) |
316 { | |
317 GaimStatusAttr *attr; | |
318 | |
319 g_return_if_fail(status_type != NULL); | |
320 g_return_if_fail(id != NULL); | |
321 g_return_if_fail(name != NULL); | |
322 g_return_if_fail(value != NULL); | |
323 | |
324 attr = gaim_status_attr_new(id, name, value); | |
325 | |
326 status_type->attrs = g_list_append(status_type->attrs, attr); | |
327 } | |
328 | |
329 void | |
330 gaim_status_type_add_attrs_vargs(GaimStatusType *status_type, va_list args) | |
331 { | |
332 const char *id, *name; | |
333 GaimValue *value; | |
334 | |
335 g_return_if_fail(status_type != NULL); | |
336 | |
337 while ((id = va_arg(args, const char *)) != NULL) | |
338 { | |
339 name = va_arg(args, const char *); | |
340 g_return_if_fail(name != NULL); | |
341 | |
342 value = va_arg(args, GaimValue *); | |
343 g_return_if_fail(value != NULL); | |
6065 | 344 |
9949 | 345 gaim_status_type_add_attr(status_type, id, name, value); |
346 } | |
347 } | |
348 | |
10010 | 349 void |
350 gaim_status_type_add_attrs(GaimStatusType *status_type, const char *id, | |
351 const char *name, GaimValue *value, ...) | |
352 { | |
353 va_list args; | |
354 | |
355 g_return_if_fail(status_type != NULL); | |
356 g_return_if_fail(id != NULL); | |
357 g_return_if_fail(name != NULL); | |
358 g_return_if_fail(value != NULL); | |
359 | |
360 /* Add the first attribute */ | |
361 gaim_status_type_add_attr(status_type, id, name, value); | |
362 | |
363 va_start(args, value); | |
364 gaim_status_type_add_attrs_vargs(status_type, args); | |
365 va_end(args); | |
366 } | |
367 | |
9949 | 368 GaimStatusPrimitive |
369 gaim_status_type_get_primitive(const GaimStatusType *status_type) | |
370 { | |
371 g_return_val_if_fail(status_type != NULL, GAIM_STATUS_UNSET); | |
372 | |
373 return status_type->primitive; | |
374 } | |
375 | |
376 const char * | |
377 gaim_status_type_get_id(const GaimStatusType *status_type) | |
378 { | |
379 g_return_val_if_fail(status_type != NULL, NULL); | |
380 | |
381 return status_type->id; | |
382 } | |
383 | |
384 const char * | |
385 gaim_status_type_get_name(const GaimStatusType *status_type) | |
386 { | |
387 g_return_val_if_fail(status_type != NULL, NULL); | |
388 | |
389 return status_type->name; | |
390 } | |
391 | |
392 gboolean | |
393 gaim_status_type_is_saveable(const GaimStatusType *status_type) | |
394 { | |
395 g_return_val_if_fail(status_type != NULL, FALSE); | |
396 | |
397 return status_type->saveable; | |
398 } | |
399 | |
400 gboolean | |
401 gaim_status_type_is_user_settable(const GaimStatusType *status_type) | |
402 { | |
403 g_return_val_if_fail(status_type != NULL, FALSE); | |
404 | |
405 return status_type->user_settable; | |
406 } | |
407 | |
408 gboolean | |
409 gaim_status_type_is_independent(const GaimStatusType *status_type) | |
410 { | |
411 g_return_val_if_fail(status_type != NULL, FALSE); | |
412 | |
413 return status_type->independent; | |
414 } | |
415 | |
416 gboolean | |
10067 | 417 gaim_status_type_is_exclusive(const GaimStatusType *status_type) |
418 { | |
419 g_return_val_if_fail(status_type != NULL, FALSE); | |
420 | |
421 return !status_type->independent; | |
422 } | |
423 | |
424 gboolean | |
9949 | 425 gaim_status_type_is_available(const GaimStatusType *status_type) |
426 { | |
427 GaimStatusPrimitive primitive; | |
428 | |
429 g_return_val_if_fail(status_type != NULL, FALSE); | |
430 | |
431 primitive = gaim_status_type_get_primitive(status_type); | |
432 | |
10500 | 433 /* Why does "hidden" mean the person is available? */ |
9949 | 434 return (primitive == GAIM_STATUS_AVAILABLE || |
435 primitive == GAIM_STATUS_HIDDEN); | |
436 } | |
437 | |
438 const char * | |
439 gaim_status_type_get_primary_attr(const GaimStatusType *status_type) | |
440 { | |
441 g_return_val_if_fail(status_type != NULL, NULL); | |
442 | |
443 return status_type->primary_attr_id; | |
444 } | |
445 | |
446 GaimStatusAttr * | |
447 gaim_status_type_get_attr(const GaimStatusType *status_type, const char *id) | |
448 { | |
449 GList *l; | |
450 | |
451 g_return_val_if_fail(status_type != NULL, NULL); | |
452 g_return_val_if_fail(id != NULL, NULL); | |
453 | |
454 for (l = status_type->attrs; l != NULL; l = l->next) | |
455 { | |
456 GaimStatusAttr *attr = (GaimStatusAttr *)l->data; | |
457 | |
458 if (!strcmp(gaim_status_attr_get_id(attr), id)) | |
459 return attr; | |
460 } | |
461 | |
462 return NULL; | |
463 } | |
464 | |
465 const GList * | |
466 gaim_status_type_get_attrs(const GaimStatusType *status_type) | |
467 { | |
468 g_return_val_if_fail(status_type != NULL, NULL); | |
469 | |
470 return status_type->attrs; | |
471 } | |
472 | |
10348 | 473 const GaimStatusType * |
474 gaim_status_type_find_with_id(GList *status_types, const char *id) | |
475 { | |
476 GaimStatusType *status_type; | |
477 | |
478 g_return_val_if_fail(id != NULL, NULL); | |
479 | |
480 while (status_types != NULL) | |
481 { | |
482 status_type = status_types->data; | |
483 | |
484 if (!strcmp(id, status_type->id)) | |
485 return status_type; | |
486 } | |
487 | |
488 return NULL; | |
489 } | |
490 | |
9949 | 491 |
492 /************************************************************************** | |
493 * GaimStatusAttr API | |
494 **************************************************************************/ | |
495 GaimStatusAttr * | |
496 gaim_status_attr_new(const char *id, const char *name, GaimValue *value_type) | |
497 { | |
498 GaimStatusAttr *attr; | |
499 | |
500 g_return_val_if_fail(id != NULL, NULL); | |
501 g_return_val_if_fail(name != NULL, NULL); | |
502 g_return_val_if_fail(value_type != NULL, NULL); | |
503 | |
504 attr = g_new0(GaimStatusAttr, 1); | |
505 | |
506 attr->id = g_strdup(id); | |
507 attr->name = g_strdup(name); | |
508 attr->value_type = value_type; | |
509 | |
510 return attr; | |
511 } | |
512 | |
513 void | |
514 gaim_status_attr_destroy(GaimStatusAttr *attr) | |
515 { | |
516 g_return_if_fail(attr != NULL); | |
517 | |
518 g_free(attr->id); | |
519 g_free(attr->name); | |
520 | |
521 gaim_value_destroy(attr->value_type); | |
522 | |
523 g_free(attr); | |
524 } | |
525 | |
526 const char * | |
527 gaim_status_attr_get_id(const GaimStatusAttr *attr) | |
528 { | |
529 g_return_val_if_fail(attr != NULL, NULL); | |
530 | |
531 return attr->id; | |
532 } | |
533 | |
534 const char * | |
535 gaim_status_attr_get_name(const GaimStatusAttr *attr) | |
536 { | |
537 g_return_val_if_fail(attr != NULL, NULL); | |
538 | |
539 return attr->name; | |
540 } | |
541 | |
542 GaimValue * | |
543 gaim_status_attr_get_value_type(const GaimStatusAttr *attr) | |
544 { | |
545 g_return_val_if_fail(attr != NULL, NULL); | |
546 | |
547 return attr->value_type; | |
548 } | |
549 | |
550 | |
551 /************************************************************************** | |
552 * GaimStatus API | |
553 **************************************************************************/ | |
554 GaimStatus * | |
555 gaim_status_new(GaimStatusType *status_type, GaimPresence *presence) | |
556 { | |
557 GaimStatus *status; | |
558 const GList *l; | |
559 | |
560 g_return_val_if_fail(status_type != NULL, NULL); | |
561 g_return_val_if_fail(presence != NULL, NULL); | |
562 | |
563 status = g_new0(GaimStatus, 1); | |
564 | |
565 status->type = status_type; | |
566 status->presence = presence; | |
567 | |
568 status->attr_values = | |
569 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, | |
570 (GDestroyNotify)gaim_value_destroy); | |
571 | |
572 for (l = gaim_status_type_get_attrs(status_type); l != NULL; l = l->next) | |
573 { | |
574 GaimStatusAttr *attr = (GaimStatusAttr *)l->data; | |
575 GaimValue *value = gaim_status_attr_get_value_type(attr); | |
576 GaimValue *new_value = gaim_value_dup(value); | |
577 | |
578 g_hash_table_insert(status->attr_values, | |
10197 | 579 g_strdup(gaim_status_attr_get_id(attr)), |
580 new_value); | |
9949 | 581 } |
582 | |
583 return status; | |
584 } | |
585 | |
10754 | 586 /* |
587 * TODO: If the GaimStatus is in a GaimPresence, then | |
588 * remove it from the GaimPresence? | |
589 */ | |
9949 | 590 void |
591 gaim_status_destroy(GaimStatus *status) | |
592 { | |
593 g_return_if_fail(status != NULL); | |
594 | |
10754 | 595 /* TODO: Don't do this is if the status is exclusive */ |
9949 | 596 gaim_status_set_active(status, FALSE); |
597 | |
598 g_hash_table_destroy(status->attr_values); | |
599 | |
600 g_free(status); | |
601 } | |
6065 | 602 |
603 static void | |
9949 | 604 notify_buddy_status_update(GaimBuddy *buddy, GaimPresence *presence, |
605 GaimStatus *old_status, GaimStatus *new_status) | |
606 { | |
607 GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); | |
608 | |
609 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
610 gaim_prefs_get_bool("/core/logging/log_away_state")) | |
611 { | |
612 time_t current_time = time(NULL); | |
613 const char *buddy_alias = gaim_buddy_get_alias(buddy); | |
614 char *tmp = NULL; | |
615 | |
616 if (!gaim_status_is_available(old_status) && | |
617 gaim_status_is_available(new_status)) | |
618 { | |
619 tmp = g_strdup_printf(_("%s came back"), buddy_alias); | |
620 } | |
621 else if (gaim_status_is_available(old_status) && | |
622 !gaim_status_is_available(new_status)) | |
623 { | |
624 tmp = g_strdup_printf(_("%s went away"), buddy_alias); | |
625 } | |
626 | |
627 if (tmp != NULL) | |
628 { | |
629 GaimLog *log = gaim_account_get_log(buddy->account); | |
630 | |
631 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, buddy_alias, | |
632 current_time, tmp); | |
633 g_free(tmp); | |
634 } | |
635 } | |
636 | |
10012 | 637 if (ops != NULL && ops->update != NULL) |
638 ops->update(gaim_get_blist(), (GaimBlistNode*)buddy); | |
9949 | 639 } |
640 | |
641 static void | |
642 notify_status_update(GaimPresence *presence, GaimStatus *old_status, | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
643 GaimStatus *new_status) |
6065 | 644 { |
9949 | 645 GaimPresenceContext context = gaim_presence_get_context(presence); |
646 | |
647 if (context == GAIM_PRESENCE_CONTEXT_ACCOUNT) | |
648 { | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
649 GaimAccount *account = gaim_presence_get_account(presence); |
9949 | 650 GaimAccountUiOps *ops = gaim_accounts_get_ui_ops(); |
651 | |
10400 | 652 if (gaim_account_get_enabled(account, gaim_core_get_ui())) |
10447 | 653 gaim_prpl_change_account_status(account, old_status, new_status); |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
654 |
9949 | 655 if (ops != NULL && ops->status_changed != NULL) |
656 { | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
657 ops->status_changed(account, new_status); |
9949 | 658 } |
659 } | |
660 else if (context == GAIM_PRESENCE_CONTEXT_CONV) | |
661 { | |
662 #if 0 | |
663 GaimConversationUiOps *ops; | |
664 GaimConversation *conv; | |
665 | |
666 conv = gaim_status_get_conversation(new_status); | |
10348 | 667 /* |
668 * TODO: Probably need to do some of the following here? This is copied | |
669 * from some old status code that was removed. | |
670 * | |
671 * char *tmp = g_strdup_printf(_("%s logged in."), alias); | |
672 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
673 * g_free(tmp); | |
674 * | |
675 * char *tmp = g_strdup_printf(_("%s logged out."), alias); | |
676 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
677 * g_free(tmp); | |
678 * | |
679 * char *tmp = g_strdup_printf(_("%s signed off"), alias); | |
680 * gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp); | |
681 * g_free(tmp); | |
682 * | |
683 * serv_got_typing_stopped(gc, name); | |
684 * | |
685 * gaim_conversation_update(c, GAIM_CONV_UPDATE_AWAY); | |
686 */ | |
9949 | 687 #endif |
688 } | |
689 else if (context == GAIM_PRESENCE_CONTEXT_BUDDY) | |
690 { | |
691 const GList *l; | |
692 | |
693 for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next) | |
694 { | |
695 notify_buddy_status_update((GaimBuddy *)l->data, presence, | |
696 old_status, new_status); | |
697 } | |
10348 | 698 |
699 /* | |
700 * TODO: Maybe we should do this here? | |
701 * GaimLog *log = gaim_account_get_log(account); | |
702 * char *tmp = g_strdup_printf(_("%s signed on"), alias); | |
703 * gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp); | |
704 * g_free(tmp); | |
705 */ | |
9949 | 706 } |
707 } | |
708 | |
10204 | 709 static void |
710 status_has_changed(GaimStatus *status) | |
9949 | 711 { |
712 GaimPresence *presence; | |
713 GaimStatus *old_status; | |
714 | |
715 presence = gaim_status_get_presence(status); | |
716 | |
10204 | 717 /* |
718 * If this status is exclusive, then we must be setting it to "active." | |
719 * Since we are setting it to active, we want to set the currently | |
720 * active status to "inactive." | |
721 */ | |
722 if (gaim_status_is_exclusive(status)) | |
9949 | 723 { |
10754 | 724 old_status = gaim_presence_get_active_status(presence); |
10760 | 725 if (old_status != NULL && (old_status != status)) |
10754 | 726 old_status->active = FALSE; |
727 presence->active_status = status; | |
9949 | 728 } |
10754 | 729 else |
730 old_status = NULL; | |
9949 | 731 |
10204 | 732 notify_status_update(presence, old_status, status); |
733 } | |
734 | |
735 void | |
736 gaim_status_set_active(GaimStatus *status, gboolean active) | |
737 { | |
10754 | 738 gaim_status_set_active_with_attrs(status, active, NULL); |
10204 | 739 } |
740 | |
741 void | |
742 gaim_status_set_active_with_attrs(GaimStatus *status, gboolean active, va_list args) | |
743 { | |
744 gboolean changed = FALSE; | |
745 const gchar *id; | |
746 | |
10714 | 747 g_return_if_fail(status != NULL); |
748 | |
10204 | 749 if (!active && gaim_status_is_exclusive(status)) |
750 { | |
751 gaim_debug_error("status", | |
752 "Cannot deactivate an exclusive status (%s).\n", | |
753 gaim_status_get_id(status)); | |
754 return; | |
755 } | |
756 | |
757 if (status->active != active) | |
10738 | 758 { |
10204 | 759 changed = TRUE; |
10738 | 760 } |
10204 | 761 |
9949 | 762 status->active = active; |
6065 | 763 |
10204 | 764 /* Set any attributes */ |
10754 | 765 if (args != NULL) |
10204 | 766 while ((id = va_arg(args, const char *)) != NULL) |
767 { | |
768 GaimValue *value; | |
769 value = gaim_status_get_attr_value(status, id); | |
10713 | 770 if (value == NULL) |
771 { | |
772 gaim_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is " | |
10714 | 773 "not supported.\n", id, status->type->name); |
10713 | 774 /* Skip over the data and move on to the next attribute */ |
775 va_arg(args, void *); | |
776 continue; | |
777 } | |
778 | |
10204 | 779 if (value->type == GAIM_TYPE_STRING) |
780 { | |
781 const gchar *string_data = va_arg(args, const char *); | |
782 if (((string_data == NULL) && (value->data.string_data == NULL)) || | |
783 ((string_data != NULL) && (value->data.string_data != NULL) && | |
784 !strcmp(string_data, value->data.string_data))) | |
785 { | |
786 continue; | |
787 } | |
788 gaim_status_set_attr_string(status, id, string_data); | |
789 changed = TRUE; | |
790 } | |
791 else if (value->type == GAIM_TYPE_INT) | |
792 { | |
793 int int_data = va_arg(args, int); | |
794 if (int_data == value->data.int_data) | |
795 continue; | |
796 gaim_status_set_attr_int(status, id, int_data); | |
797 changed = TRUE; | |
798 } | |
799 else if (value->type == GAIM_TYPE_BOOLEAN) | |
800 { | |
801 gboolean boolean_data = va_arg(args, gboolean); | |
802 if (boolean_data == value->data.boolean_data) | |
803 continue; | |
804 gaim_status_set_attr_int(status, id, boolean_data); | |
805 changed = TRUE; | |
806 } | |
807 else | |
808 { | |
809 /* We don't know what the data is--skip over it */ | |
810 va_arg(args, void *); | |
811 } | |
812 } | |
813 | |
814 if (!changed) | |
815 return; | |
816 | |
817 status_has_changed(status); | |
9949 | 818 } |
819 | |
820 void | |
821 gaim_status_set_attr_boolean(GaimStatus *status, const char *id, | |
822 gboolean value) | |
823 { | |
824 GaimStatusType *status_type; | |
825 GaimValue *attr_value; | |
826 | |
827 g_return_if_fail(status != NULL); | |
828 g_return_if_fail(id != NULL); | |
829 | |
830 status_type = gaim_status_get_type(status); | |
831 | |
10197 | 832 /* Make sure this attribute exists and is the correct type. */ |
833 attr_value = gaim_status_get_attr_value(status, id); | |
834 g_return_if_fail(attr_value != NULL); | |
9949 | 835 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_BOOLEAN); |
836 | |
837 gaim_value_set_boolean(attr_value, value); | |
838 } | |
839 | |
840 void | |
841 gaim_status_set_attr_int(GaimStatus *status, const char *id, int value) | |
842 { | |
843 GaimStatusType *status_type; | |
844 GaimValue *attr_value; | |
845 | |
846 g_return_if_fail(status != NULL); | |
847 g_return_if_fail(id != NULL); | |
848 | |
849 status_type = gaim_status_get_type(status); | |
850 | |
10197 | 851 /* Make sure this attribute exists and is the correct type. */ |
852 attr_value = gaim_status_get_attr_value(status, id); | |
853 g_return_if_fail(attr_value != NULL); | |
9949 | 854 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_INT); |
855 | |
856 gaim_value_set_int(attr_value, value); | |
6065 | 857 } |
858 | |
9949 | 859 void |
860 gaim_status_set_attr_string(GaimStatus *status, const char *id, | |
861 const char *value) | |
862 { | |
863 GaimStatusType *status_type; | |
864 GaimValue *attr_value; | |
865 | |
866 g_return_if_fail(status != NULL); | |
867 g_return_if_fail(id != NULL); | |
868 | |
869 status_type = gaim_status_get_type(status); | |
870 | |
10197 | 871 /* Make sure this attribute exists and is the correct type. */ |
10196 | 872 attr_value = gaim_status_get_attr_value(status, id); |
10197 | 873 g_return_if_fail(attr_value != NULL); |
9949 | 874 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_STRING); |
875 | |
876 gaim_value_set_string(attr_value, value); | |
877 } | |
878 | |
879 GaimStatusType * | |
880 gaim_status_get_type(const GaimStatus *status) | |
881 { | |
882 g_return_val_if_fail(status != NULL, NULL); | |
883 | |
884 return status->type; | |
885 } | |
886 | |
887 GaimPresence * | |
888 gaim_status_get_presence(const GaimStatus *status) | |
6065 | 889 { |
9949 | 890 g_return_val_if_fail(status != NULL, NULL); |
891 | |
892 return status->presence; | |
893 } | |
894 | |
895 const char * | |
896 gaim_status_get_id(const GaimStatus *status) | |
897 { | |
898 g_return_val_if_fail(status != NULL, NULL); | |
899 | |
900 return gaim_status_type_get_id(gaim_status_get_type(status)); | |
901 } | |
902 | |
903 const char * | |
904 gaim_status_get_name(const GaimStatus *status) | |
905 { | |
906 g_return_val_if_fail(status != NULL, NULL); | |
907 | |
908 return gaim_status_type_get_name(gaim_status_get_type(status)); | |
909 } | |
910 | |
911 gboolean | |
912 gaim_status_is_independent(const GaimStatus *status) | |
913 { | |
914 g_return_val_if_fail(status != NULL, FALSE); | |
915 | |
916 return gaim_status_type_is_independent(gaim_status_get_type(status)); | |
917 } | |
918 | |
919 gboolean | |
10067 | 920 gaim_status_is_exclusive(const GaimStatus *status) |
921 { | |
922 g_return_val_if_fail(status != NULL, FALSE); | |
923 | |
924 return gaim_status_type_is_exclusive(gaim_status_get_type(status)); | |
925 } | |
926 | |
927 gboolean | |
9949 | 928 gaim_status_is_available(const GaimStatus *status) |
929 { | |
930 g_return_val_if_fail(status != NULL, FALSE); | |
931 | |
932 return gaim_status_type_is_available(gaim_status_get_type(status)); | |
933 } | |
6216 | 934 |
9949 | 935 gboolean |
936 gaim_status_is_active(const GaimStatus *status) | |
937 { | |
938 g_return_val_if_fail(status != NULL, FALSE); | |
939 | |
940 return status->active; | |
941 } | |
942 | |
10040
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
943 gboolean |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
944 gaim_status_is_online(const GaimStatus *status) |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
945 { |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
946 GaimStatusPrimitive primitive; |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
947 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
948 g_return_val_if_fail( status != NULL, FALSE); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
949 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
950 primitive = gaim_status_type_get_primitive(gaim_status_get_type(status)); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
951 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
952 return (primitive != GAIM_STATUS_UNSET && |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
953 primitive != GAIM_STATUS_OFFLINE); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
954 } |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
955 |
9949 | 956 GaimValue * |
957 gaim_status_get_attr_value(const GaimStatus *status, const char *id) | |
958 { | |
959 GaimStatusType *status_type; | |
960 GaimStatusAttr *attr; | |
961 | |
962 g_return_val_if_fail(status != NULL, NULL); | |
963 g_return_val_if_fail(id != NULL, NULL); | |
964 | |
965 status_type = gaim_status_get_type(status); | |
966 | |
967 /* Make sure this attribute exists. */ | |
968 attr = gaim_status_type_get_attr(status_type, id); | |
969 g_return_val_if_fail(attr != NULL, NULL); | |
970 | |
971 return (GaimValue *)g_hash_table_lookup(status->attr_values, id); | |
972 } | |
973 | |
974 gboolean | |
975 gaim_status_get_attr_boolean(const GaimStatus *status, const char *id) | |
976 { | |
977 const GaimValue *value; | |
978 | |
979 g_return_val_if_fail(status != NULL, FALSE); | |
980 g_return_val_if_fail(id != NULL, FALSE); | |
981 | |
982 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
983 return FALSE; | |
984 | |
10197 | 985 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_BOOLEAN, FALSE); |
9949 | 986 |
987 return gaim_value_get_boolean(value); | |
988 } | |
989 | |
990 int | |
991 gaim_status_get_attr_int(const GaimStatus *status, const char *id) | |
992 { | |
993 const GaimValue *value; | |
994 | |
10507 | 995 g_return_val_if_fail(status != NULL, 0); |
996 g_return_val_if_fail(id != NULL, 0); | |
9949 | 997 |
998 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
10507 | 999 return 0; |
9949 | 1000 |
1001 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_INT, 0); | |
1002 | |
1003 return gaim_value_get_int(value); | |
1004 } | |
1005 | |
1006 const char * | |
1007 gaim_status_get_attr_string(const GaimStatus *status, const char *id) | |
1008 { | |
1009 const GaimValue *value; | |
1010 | |
10507 | 1011 g_return_val_if_fail(status != NULL, NULL); |
1012 g_return_val_if_fail(id != NULL, NULL); | |
9949 | 1013 |
1014 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
10504 | 1015 return NULL; |
9949 | 1016 |
1017 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_STRING, NULL); | |
1018 | |
1019 return gaim_value_get_string(value); | |
1020 } | |
1021 | |
1022 gint | |
1023 gaim_status_compare(const GaimStatus *status1, const GaimStatus *status2) | |
1024 { | |
1025 GaimStatusType *type1, *type2; | |
1026 int score1 = 0, score2 = 0; | |
6065 | 1027 |
9949 | 1028 if ((status1 == NULL && status2 == NULL) || |
1029 (status1 == status2)) | |
1030 { | |
1031 return 0; | |
1032 } | |
1033 else if (status1 == NULL) | |
1034 return 1; | |
1035 else if (status2 == NULL) | |
1036 return -1; | |
1037 | |
1038 type1 = gaim_status_get_type(status1); | |
1039 type2 = gaim_status_get_type(status2); | |
1040 | |
1041 if (gaim_status_is_active(status1)) | |
1042 score1 = primitive_scores[gaim_status_type_get_primitive(type1)]; | |
1043 | |
1044 if (gaim_status_is_active(status2)) | |
1045 score2 = primitive_scores[gaim_status_type_get_primitive(type2)]; | |
1046 | |
1047 if (score1 > score2) | |
1048 return -1; | |
1049 else if (score1 < score2) | |
1050 return 1; | |
1051 | |
1052 return 0; | |
1053 } | |
1054 | |
1055 | |
1056 /************************************************************************** | |
1057 * GaimPresence API | |
1058 **************************************************************************/ | |
1059 GaimPresence * | |
1060 gaim_presence_new(GaimPresenceContext context) | |
1061 { | |
1062 GaimPresence *presence; | |
1063 | |
1064 g_return_val_if_fail(context != GAIM_PRESENCE_CONTEXT_UNSET, NULL); | |
1065 | |
1066 presence = g_new0(GaimPresence, 1); | |
1067 | |
1068 presence->context = context; | |
1069 | |
1070 presence->status_table = | |
10009 | 1071 g_hash_table_new_full(g_str_hash, g_str_equal, |
1072 g_free, (GFreeFunc)gaim_status_destroy); | |
9949 | 1073 |
1074 return presence; | |
1075 } | |
1076 | |
1077 GaimPresence * | |
1078 gaim_presence_new_for_account(GaimAccount *account) | |
1079 { | |
10012 | 1080 GaimPresence *presence = NULL; |
9949 | 1081 g_return_val_if_fail(account != NULL, NULL); |
1082 | |
1083 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_ACCOUNT); | |
1084 presence->u.account = account; | |
10006 | 1085 presence->statuses = gaim_prpl_get_statuses(account, presence); |
9949 | 1086 |
1087 return presence; | |
1088 } | |
1089 | |
1090 GaimPresence * | |
1091 gaim_presence_new_for_conv(GaimConversation *conv) | |
1092 { | |
1093 GaimPresence *presence; | |
1094 | |
1095 g_return_val_if_fail(conv != NULL, NULL); | |
1096 | |
1097 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_CONV); | |
1098 presence->u.chat.conv = conv; | |
10006 | 1099 /* presence->statuses = gaim_prpl_get_statuses(conv->account, presence); ? */ |
9949 | 1100 |
1101 return presence; | |
1102 } | |
6216 | 1103 |
9949 | 1104 GaimPresence * |
1105 gaim_presence_new_for_buddy(GaimBuddy *buddy) | |
1106 { | |
1107 GaimPresence *presence; | |
1108 GaimStatusBuddyKey *key; | |
10006 | 1109 GaimAccount *account; |
9949 | 1110 |
1111 g_return_val_if_fail(buddy != NULL, NULL); | |
10012 | 1112 account = buddy->account; |
9949 | 1113 |
10006 | 1114 account = buddy->account; |
1115 | |
9949 | 1116 key = g_new0(GaimStatusBuddyKey, 1); |
1117 key->account = buddy->account; | |
1118 key->name = g_strdup(buddy->name); | |
10006 | 1119 |
1120 presence = g_hash_table_lookup(buddy_presences, key); | |
1121 if (presence == NULL) | |
9949 | 1122 { |
1123 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_BUDDY); | |
1124 | |
1125 presence->u.buddy.name = g_strdup(buddy->name); | |
1126 presence->u.buddy.account = buddy->account; | |
10006 | 1127 presence->statuses = gaim_prpl_get_statuses(buddy->account, presence); |
9949 | 1128 |
1129 g_hash_table_insert(buddy_presences, key, presence); | |
1130 } | |
1131 else | |
1132 { | |
1133 g_free(key->name); | |
1134 g_free(key); | |
1135 } | |
1136 | |
1137 presence->u.buddy.ref_count++; | |
1138 presence->u.buddy.buddies = g_list_append(presence->u.buddy.buddies, | |
1139 buddy); | |
1140 | |
1141 return presence; | |
1142 } | |
1143 | |
1144 void | |
1145 gaim_presence_destroy(GaimPresence *presence) | |
1146 { | |
1147 g_return_if_fail(presence != NULL); | |
6216 | 1148 |
9949 | 1149 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) |
1150 { | |
1151 GaimStatusBuddyKey key; | |
1152 | |
10077 | 1153 if(presence->u.buddy.ref_count != 0) |
1154 return; | |
9949 | 1155 |
1156 key.account = presence->u.buddy.account; | |
1157 key.name = presence->u.buddy.name; | |
1158 | |
1159 g_hash_table_remove(buddy_presences, &key); | |
1160 | |
1161 if (presence->u.buddy.name != NULL) | |
1162 g_free(presence->u.buddy.name); | |
1163 } | |
1164 else if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_CONV) | |
1165 { | |
1166 if (presence->u.chat.user != NULL) | |
1167 g_free(presence->u.chat.user); | |
1168 } | |
1169 | |
1170 if (presence->statuses != NULL) | |
1171 g_list_free(presence->statuses); | |
1172 | |
1173 g_hash_table_destroy(presence->status_table); | |
1174 | |
1175 g_free(presence); | |
1176 } | |
1177 | |
10580 | 1178 /* |
1179 * TODO: Maybe we should cal gaim_presence_destroy() after we | |
1180 * decrement the ref count? I don't see why we should | |
1181 * make other places do it manually when we can do it here. | |
1182 */ | |
9949 | 1183 void |
1184 gaim_presence_remove_buddy(GaimPresence *presence, GaimBuddy *buddy) | |
1185 { | |
1186 g_return_if_fail(presence != NULL); | |
1187 g_return_if_fail(buddy != NULL); | |
1188 g_return_if_fail(gaim_presence_get_context(presence) == | |
1189 GAIM_PRESENCE_CONTEXT_BUDDY); | |
1190 | |
1191 if (g_list_find(presence->u.buddy.buddies, buddy) != NULL) | |
1192 { | |
1193 presence->u.buddy.buddies = g_list_remove(presence->u.buddy.buddies, | |
1194 buddy); | |
1195 presence->u.buddy.ref_count--; | |
1196 } | |
6065 | 1197 } |
1198 | |
9949 | 1199 void |
1200 gaim_presence_add_status(GaimPresence *presence, GaimStatus *status) | |
1201 { | |
1202 g_return_if_fail(presence != NULL); | |
1203 g_return_if_fail(status != NULL); | |
1204 | |
1205 presence->statuses = g_list_append(presence->statuses, status); | |
1206 | |
1207 g_hash_table_insert(presence->status_table, | |
1208 g_strdup(gaim_status_get_id(status)), status); | |
1209 } | |
1210 | |
1211 void | |
1212 gaim_presence_add_presence(GaimPresence *presence, const GList *source_list) | |
1213 { | |
1214 const GList *l; | |
1215 | |
1216 g_return_if_fail(presence != NULL); | |
1217 g_return_if_fail(source_list != NULL); | |
1218 | |
1219 for (l = source_list; l != NULL; l = l->next) | |
1220 gaim_presence_add_status(presence, (GaimStatus *)l->data); | |
1221 } | |
1222 | |
1223 void | |
1224 gaim_presence_set_status_active(GaimPresence *presence, const char *status_id, | |
1225 gboolean active) | |
1226 { | |
1227 GaimStatus *status; | |
1228 | |
1229 g_return_if_fail(presence != NULL); | |
1230 g_return_if_fail(status_id != NULL); | |
1231 | |
1232 status = gaim_presence_get_status(presence, status_id); | |
1233 | |
1234 g_return_if_fail(status != NULL); | |
10348 | 1235 /* TODO: Should we do the following? */ |
1236 /* g_return_if_fail(active == status->active); */ | |
9949 | 1237 |
10067 | 1238 if (gaim_status_is_exclusive(status)) |
9949 | 1239 { |
1240 if (!active) | |
1241 { | |
1242 gaim_debug_warning("status", | |
1243 "Attempted to set a non-independent status " | |
1244 "(%s) inactive. Only independent statuses " | |
1245 "can be specifically marked inactive.", | |
1246 status_id); | |
1247 return; | |
1248 } | |
1249 } | |
1250 | |
1251 gaim_status_set_active(status, active); | |
1252 } | |
1253 | |
1254 void | |
1255 gaim_presence_switch_status(GaimPresence *presence, const char *status_id) | |
1256 { | |
10754 | 1257 gaim_presence_set_status_active(presence, status_id, TRUE); |
9949 | 1258 } |
1259 | |
1260 static void | |
1261 update_buddy_idle(GaimBuddy *buddy, GaimPresence *presence, | |
1262 time_t current_time, gboolean old_idle, gboolean idle) | |
1263 { | |
1264 GaimBlistUiOps *ops = gaim_get_blist()->ui_ops; | |
1265 | |
1266 if (!old_idle && idle) | |
1267 { | |
1268 gaim_signal_emit(gaim_blist_get_handle(), "buddy-idle", buddy); | |
1269 | |
1270 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
1271 gaim_prefs_get_bool("/core/logging/log_idle_state")) | |
1272 { | |
1273 GaimLog *log = gaim_account_get_log(buddy->account); | |
1274 char *tmp = g_strdup_printf(_("%s became idle"), | |
1275 gaim_buddy_get_alias(buddy)); | |
1276 | |
1277 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, | |
1278 gaim_buddy_get_alias(buddy), current_time, tmp); | |
1279 g_free(tmp); | |
1280 } | |
1281 } | |
1282 else if (old_idle && !idle) | |
1283 { | |
1284 gaim_signal_emit(gaim_blist_get_handle(), "buddy-unidle", buddy); | |
1285 | |
1286 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
1287 gaim_prefs_get_bool("/core/logging/log_idle_state")) | |
1288 { | |
1289 GaimLog *log = gaim_account_get_log(buddy->account); | |
1290 char *tmp = g_strdup_printf(_("%s became unidle"), | |
1291 gaim_buddy_get_alias(buddy)); | |
1292 | |
1293 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, | |
1294 gaim_buddy_get_alias(buddy), current_time, tmp); | |
1295 g_free(tmp); | |
1296 } | |
1297 } | |
1298 | |
10378 | 1299 gaim_contact_invalidate_priority_buddy(gaim_buddy_get_contact(buddy)); |
9949 | 1300 |
1301 if (ops != NULL && ops->update != NULL) | |
1302 ops->update(gaim_get_blist(), (GaimBlistNode *)buddy); | |
1303 } | |
1304 | |
1305 void | |
1306 gaim_presence_set_idle(GaimPresence *presence, gboolean idle, time_t idle_time) | |
1307 { | |
1308 gboolean old_idle; | |
1309 | |
1310 g_return_if_fail(presence != NULL); | |
1311 | |
1312 if (presence->idle == idle && presence->idle_time == idle_time) | |
1313 return; | |
1314 | |
1315 old_idle = presence->idle; | |
1316 presence->idle = idle; | |
1317 presence->idle_time = (idle ? idle_time : 0); | |
1318 | |
1319 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) | |
1320 { | |
1321 const GList *l; | |
1322 time_t current_time = time(NULL); | |
1323 | |
1324 for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next) | |
1325 { | |
1326 update_buddy_idle((GaimBuddy *)l->data, presence, current_time, | |
1327 old_idle, idle); | |
1328 } | |
1329 } | |
1330 } | |
1331 | |
1332 void | |
10006 | 1333 gaim_presence_set_login_time(GaimPresence *presence, time_t login_time) |
1334 { | |
1335 g_return_if_fail(presence != NULL); | |
1336 | |
1337 if (presence->login_time == login_time) | |
1338 return; | |
1339 | |
1340 presence->login_time = login_time; | |
1341 } | |
1342 | |
1343 void | |
9949 | 1344 gaim_presence_set_warning_level(GaimPresence *presence, unsigned int level) |
6065 | 1345 { |
9949 | 1346 g_return_if_fail(presence != NULL); |
1347 g_return_if_fail(level <= 100); | |
1348 | |
1349 if (presence->warning_level == level) | |
1350 return; | |
1351 | |
1352 presence->warning_level = level; | |
1353 | |
1354 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) | |
1355 { | |
1356 GaimBlistUiOps *ops = gaim_get_blist()->ui_ops; | |
1357 | |
1358 if (ops != NULL && ops->update != NULL) | |
1359 { | |
1360 const GList *l; | |
1361 | |
1362 for (l = gaim_presence_get_buddies(presence); | |
1363 l != NULL; | |
1364 l = l->next) | |
1365 { | |
1366 ops->update(gaim_get_blist(), (GaimBlistNode *)l->data); | |
1367 } | |
1368 } | |
1369 } | |
1370 } | |
1371 | |
1372 GaimPresenceContext | |
1373 gaim_presence_get_context(const GaimPresence *presence) | |
1374 { | |
1375 g_return_val_if_fail(presence != NULL, GAIM_PRESENCE_CONTEXT_UNSET); | |
1376 | |
1377 return presence->context; | |
1378 } | |
1379 | |
1380 GaimAccount * | |
1381 gaim_presence_get_account(const GaimPresence *presence) | |
1382 { | |
1383 GaimPresenceContext context; | |
1384 | |
1385 g_return_val_if_fail(presence != NULL, NULL); | |
1386 | |
1387 context = gaim_presence_get_context(presence); | |
1388 | |
1389 g_return_val_if_fail(context == GAIM_PRESENCE_CONTEXT_ACCOUNT || | |
1390 context == GAIM_PRESENCE_CONTEXT_BUDDY, NULL); | |
1391 | |
1392 return presence->u.account; | |
1393 } | |
1394 | |
1395 GaimConversation * | |
1396 gaim_presence_get_conversation(const GaimPresence *presence) | |
1397 { | |
1398 g_return_val_if_fail(presence != NULL, NULL); | |
1399 g_return_val_if_fail(gaim_presence_get_context(presence) == | |
1400 GAIM_PRESENCE_CONTEXT_CONV, NULL); | |
1401 | |
1402 return presence->u.chat.conv; | |
1403 } | |
1404 | |
1405 const char * | |
1406 gaim_presence_get_chat_user(const GaimPresence *presence) | |
1407 { | |
1408 g_return_val_if_fail(presence != NULL, NULL); | |
1409 g_return_val_if_fail(gaim_presence_get_context(presence) == | |
1410 GAIM_PRESENCE_CONTEXT_CONV, NULL); | |
1411 | |
1412 return presence->u.chat.user; | |
1413 } | |
1414 | |
1415 const GList * | |
1416 gaim_presence_get_buddies(const GaimPresence *presence) | |
1417 { | |
1418 g_return_val_if_fail(presence != NULL, NULL); | |
1419 g_return_val_if_fail(gaim_presence_get_context(presence) == | |
1420 GAIM_PRESENCE_CONTEXT_BUDDY, NULL); | |
1421 | |
1422 return presence->u.buddy.buddies; | |
1423 } | |
1424 | |
1425 const GList * | |
1426 gaim_presence_get_statuses(const GaimPresence *presence) | |
1427 { | |
1428 g_return_val_if_fail(presence != NULL, NULL); | |
1429 | |
1430 return presence->statuses; | |
1431 } | |
1432 | |
1433 GaimStatus * | |
1434 gaim_presence_get_status(const GaimPresence *presence, const char *status_id) | |
1435 { | |
1436 GaimStatus *status; | |
10006 | 1437 const GList *l = NULL; |
9949 | 1438 |
1439 g_return_val_if_fail(presence != NULL, NULL); | |
1440 g_return_val_if_fail(status_id != NULL, NULL); | |
1441 | |
10006 | 1442 /* What's the purpose of this hash table? */ |
10012 | 1443 status = (GaimStatus *)g_hash_table_lookup(presence->status_table, |
10006 | 1444 status_id); |
10012 | 1445 |
10006 | 1446 if (status == NULL) { |
10012 | 1447 for (l = gaim_presence_get_statuses(presence); |
10006 | 1448 l != NULL && status == NULL; l = l->next) |
1449 { | |
1450 GaimStatus *temp_status = l->data; | |
10012 | 1451 |
10006 | 1452 if (!strcmp(status_id, gaim_status_get_id(temp_status))) |
1453 status = temp_status; | |
1454 } | |
1455 | |
1456 if (status != NULL) | |
1457 g_hash_table_insert(presence->status_table, | |
1458 g_strdup(gaim_status_get_id(status)), status); | |
10012 | 1459 } |
9949 | 1460 |
1461 return status; | |
1462 } | |
1463 | |
1464 GaimStatus * | |
1465 gaim_presence_get_active_status(const GaimPresence *presence) | |
1466 { | |
1467 g_return_val_if_fail(presence != NULL, NULL); | |
1468 | |
1469 return presence->active_status; | |
1470 } | |
1471 | |
1472 gboolean | |
1473 gaim_presence_is_available(const GaimPresence *presence) | |
1474 { | |
1475 GaimStatus *status; | |
1476 | |
1477 g_return_val_if_fail(presence != NULL, FALSE); | |
1478 | |
1479 status = gaim_presence_get_active_status(presence); | |
1480 | |
1481 return ((status != NULL && gaim_status_is_available(status)) && | |
1482 !gaim_presence_is_idle(presence)); | |
1483 } | |
1484 | |
1485 gboolean | |
1486 gaim_presence_is_online(const GaimPresence *presence) | |
1487 { | |
1488 GaimStatus *status; | |
1489 | |
1490 g_return_val_if_fail(presence != NULL, FALSE); | |
1491 | |
1492 if ((status = gaim_presence_get_active_status(presence)) == NULL) | |
1493 return FALSE; | |
1494 | |
10040
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
1495 return gaim_status_is_online(status); |
9949 | 1496 } |
1497 | |
1498 gboolean | |
1499 gaim_presence_is_status_active(const GaimPresence *presence, | |
1500 const char *status_id) | |
1501 { | |
1502 GaimStatus *status; | |
1503 | |
1504 g_return_val_if_fail(presence != NULL, FALSE); | |
1505 g_return_val_if_fail(status_id != NULL, FALSE); | |
1506 | |
1507 status = gaim_presence_get_status(presence, status_id); | |
1508 | |
1509 return (status != NULL && gaim_status_is_active(status)); | |
1510 } | |
1511 | |
1512 gboolean | |
1513 gaim_presence_is_status_primitive_active(const GaimPresence *presence, | |
1514 GaimStatusPrimitive primitive) | |
1515 { | |
1516 GaimStatus *status; | |
1517 GaimStatusType *status_type; | |
1518 | |
1519 g_return_val_if_fail(presence != NULL, FALSE); | |
1520 g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, FALSE); | |
1521 | |
1522 status = gaim_presence_get_active_status(presence); | |
1523 status_type = gaim_status_get_type(status); | |
1524 | |
1525 if (gaim_status_type_get_primitive(status_type) == primitive) | |
1526 return TRUE; | |
6065 | 1527 |
1528 return FALSE; | |
1529 } | |
1530 | |
9949 | 1531 gboolean |
1532 gaim_presence_is_idle(const GaimPresence *presence) | |
6065 | 1533 { |
9949 | 1534 g_return_val_if_fail(presence != NULL, FALSE); |
1535 | |
1536 return presence->idle; | |
6065 | 1537 } |
1538 | |
9949 | 1539 time_t |
1540 gaim_presence_get_idle_time(const GaimPresence *presence) | |
6065 | 1541 { |
9949 | 1542 g_return_val_if_fail(presence != NULL, 0); |
6065 | 1543 |
9949 | 1544 return presence->idle_time; |
1545 } | |
6065 | 1546 |
9949 | 1547 unsigned int |
1548 gaim_presence_get_warning_level(const GaimPresence *presence) | |
1549 { | |
1550 g_return_val_if_fail(presence != NULL, 0); | |
6216 | 1551 |
9949 | 1552 return presence->warning_level; |
6065 | 1553 } |
1554 | |
10567 | 1555 time_t |
1556 gaim_presence_get_login_time(const GaimPresence *presence) | |
1557 { | |
1558 g_return_val_if_fail(presence != NULL, 0); | |
1559 | |
1560 return presence->login_time; | |
1561 } | |
1562 | |
9949 | 1563 gint |
1564 gaim_presence_compare(const GaimPresence *presence1, | |
1565 const GaimPresence *presence2) | |
6065 | 1566 { |
9949 | 1567 gboolean idle1, idle2; |
1568 size_t idle_time_1, idle_time_2; | |
1569 int score1 = 0, score2 = 0; | |
1570 const GList *l; | |
6065 | 1571 |
9949 | 1572 if ((presence1 == NULL && presence2 == NULL) || (presence1 == presence2)) |
1573 return 0; | |
1574 else if (presence1 == NULL) | |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1575 return 1; |
9949 | 1576 else if (presence2 == NULL) |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1577 return -1; |
6065 | 1578 |
9949 | 1579 /* Compute the score of the first set of statuses. */ |
1580 for (l = gaim_presence_get_statuses(presence1); l != NULL; l = l->next) | |
1581 { | |
1582 GaimStatus *status = (GaimStatus *)l->data; | |
1583 GaimStatusType *type = gaim_status_get_type(status); | |
6065 | 1584 |
9949 | 1585 if (gaim_status_is_active(status)) |
1586 score1 += primitive_scores[gaim_status_type_get_primitive(type)]; | |
6065 | 1587 } |
1588 | |
9949 | 1589 /* Compute the score of the second set of statuses. */ |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1590 for (l = gaim_presence_get_statuses(presence2); l != NULL; l = l->next) |
9949 | 1591 { |
1592 GaimStatus *status = (GaimStatus *)l->data; | |
1593 GaimStatusType *type = gaim_status_get_type(status); | |
6065 | 1594 |
9949 | 1595 if (gaim_status_is_active(status)) |
1596 score2 += primitive_scores[gaim_status_type_get_primitive(type)]; | |
6065 | 1597 } |
1598 | |
9949 | 1599 idle1 = gaim_presence_is_idle(presence1); |
1600 idle2 = gaim_presence_is_idle(presence2); | |
6065 | 1601 |
9949 | 1602 if (idle1) |
1603 score1 += primitive_scores[SCORE_IDLE]; | |
6065 | 1604 |
9949 | 1605 if (idle2) |
1606 score2 += primitive_scores[SCORE_IDLE]; | |
6065 | 1607 |
9949 | 1608 idle_time_1 = gaim_presence_get_idle_time(presence1); |
1609 idle_time_2 = gaim_presence_get_idle_time(presence2); | |
6065 | 1610 |
9949 | 1611 if (idle_time_1 > idle_time_2) |
1612 score1 += primitive_scores[SCORE_IDLE_TIME]; | |
1613 else if (idle_time_1 < idle_time_2) | |
1614 score2 += primitive_scores[SCORE_IDLE_TIME]; | |
6065 | 1615 |
9949 | 1616 if (score1 < score2) |
1617 return 1; | |
1618 else if (score1 > score2) | |
1619 return -1; | |
1620 | |
1621 return 0; | |
1622 } | |
1623 | |
6065 | 1624 |
9949 | 1625 /************************************************************************** |
1626 * Status subsystem | |
1627 **************************************************************************/ | |
1628 static void | |
1629 score_pref_changed_cb(const char *name, GaimPrefType type, gpointer value, | |
1630 gpointer data) | |
1631 { | |
1632 int index = GPOINTER_TO_INT(data); | |
6065 | 1633 |
9949 | 1634 primitive_scores[index] = GPOINTER_TO_INT(value); |
6065 | 1635 } |
1636 | |
10519 | 1637 static guint |
10006 | 1638 gaim_buddy_presences_hash(gconstpointer key) |
1639 { | |
10012 | 1640 const GaimStatusBuddyKey *me = key; |
1641 guint ret; | |
1642 char *str; | |
1643 | |
1644 str = g_strdup_printf("%p%s", me->account, me->name); | |
1645 ret = g_str_hash(str); | |
1646 g_free(str); | |
1647 | |
1648 return ret; | |
10006 | 1649 } |
1650 | |
10519 | 1651 static gboolean |
10006 | 1652 gaim_buddy_presences_equal(gconstpointer a, gconstpointer b) |
1653 { | |
1654 GaimStatusBuddyKey *key_a = (GaimStatusBuddyKey *)a; | |
1655 GaimStatusBuddyKey *key_b = (GaimStatusBuddyKey *)b; | |
1656 | |
10012 | 1657 if(key_a->account == key_b->account && |
1658 !strcmp(key_a->name, key_b->name)) | |
10006 | 1659 return TRUE; |
1660 else | |
1661 return FALSE; | |
1662 } | |
1663 | |
10519 | 1664 static void |
1665 gaim_buddy_presences_key_free(gpointer a) | |
1666 { | |
1667 GaimStatusBuddyKey *key = (GaimStatusBuddyKey *)a; | |
1668 g_free(key->name); | |
1669 g_free(key); | |
1670 } | |
1671 | |
10087 | 1672 void * |
10418 | 1673 gaim_status_get_handle(void) { |
10087 | 1674 static int handle; |
1675 | |
1676 return &handle; | |
1677 } | |
1678 | |
9949 | 1679 void |
10418 | 1680 gaim_status_init(void) |
6065 | 1681 { |
10418 | 1682 void *handle = gaim_status_get_handle; |
10087 | 1683 |
9949 | 1684 gaim_prefs_add_none("/core/status"); |
1685 gaim_prefs_add_none("/core/status/scores"); | |
6065 | 1686 |
9949 | 1687 gaim_prefs_add_int("/core/status/scores/offline", |
1688 primitive_scores[GAIM_STATUS_OFFLINE]); | |
1689 gaim_prefs_add_int("/core/status/scores/available", | |
1690 primitive_scores[GAIM_STATUS_AVAILABLE]); | |
1691 gaim_prefs_add_int("/core/status/scores/hidden", | |
1692 primitive_scores[GAIM_STATUS_HIDDEN]); | |
1693 gaim_prefs_add_int("/core/status/scores/away", | |
1694 primitive_scores[GAIM_STATUS_AWAY]); | |
1695 gaim_prefs_add_int("/core/status/scores/extended_away", | |
1696 primitive_scores[GAIM_STATUS_EXTENDED_AWAY]); | |
1697 gaim_prefs_add_int("/core/status/scores/idle", | |
1698 primitive_scores[SCORE_IDLE]); | |
6065 | 1699 |
10087 | 1700 gaim_prefs_connect_callback(handle, "/core/status/scores/offline", |
9949 | 1701 score_pref_changed_cb, |
1702 GINT_TO_POINTER(GAIM_STATUS_OFFLINE)); | |
10087 | 1703 gaim_prefs_connect_callback(handle, "/core/status/scores/available", |
9949 | 1704 score_pref_changed_cb, |
1705 GINT_TO_POINTER(GAIM_STATUS_AVAILABLE)); | |
10087 | 1706 gaim_prefs_connect_callback(handle, "/core/status/scores/hidden", |
9949 | 1707 score_pref_changed_cb, |
1708 GINT_TO_POINTER(GAIM_STATUS_HIDDEN)); | |
10087 | 1709 gaim_prefs_connect_callback(handle, "/core/status/scores/away", |
9949 | 1710 score_pref_changed_cb, |
1711 GINT_TO_POINTER(GAIM_STATUS_AWAY)); | |
10087 | 1712 gaim_prefs_connect_callback(handle, "/core/status/scores/extended_away", |
9949 | 1713 score_pref_changed_cb, |
1714 GINT_TO_POINTER(GAIM_STATUS_EXTENDED_AWAY)); | |
10087 | 1715 gaim_prefs_connect_callback(handle, "/core/status/scores/idle", |
9949 | 1716 score_pref_changed_cb, |
1717 GINT_TO_POINTER(SCORE_IDLE)); | |
10006 | 1718 |
10519 | 1719 buddy_presences = g_hash_table_new_full(gaim_buddy_presences_hash, |
1720 gaim_buddy_presences_equal, | |
1721 gaim_buddy_presences_key_free, NULL); | |
9949 | 1722 } |
6065 | 1723 |
9949 | 1724 void |
10418 | 1725 gaim_status_uninit(void) |
9949 | 1726 { |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1727 if (buddy_presences != NULL) |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1728 { |
10077 | 1729 g_hash_table_destroy(buddy_presences); |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1730 |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1731 buddy_presences = NULL; |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1732 } |
9949 | 1733 } |