Mercurial > pidgin
annotate src/status.c @ 10734:8b2c81d9b271
[gaim-migrate @ 12336]
" Here's a simple patch that moves the focus to the Alias
textbox if a screenname has already been specified.
Basically, this covers the scenario where you've clicked
Add on someone in a chat window. I'm assuming that you
really want to add that person, so there's no need to
change the screenname. This moves the focus to the alias
box which is what I always want to type next." --rlaager
makes sense to me.
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Sat, 26 Mar 2005 03:39:00 +0000 |
parents | ad57a8b5495e |
children | 55af3fa46329 |
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 | |
586 void | |
587 gaim_status_destroy(GaimStatus *status) | |
588 { | |
589 g_return_if_fail(status != NULL); | |
590 | |
591 gaim_status_set_active(status, FALSE); | |
592 | |
593 g_hash_table_destroy(status->attr_values); | |
594 | |
595 g_free(status); | |
596 } | |
6065 | 597 |
598 static void | |
9949 | 599 notify_buddy_status_update(GaimBuddy *buddy, GaimPresence *presence, |
600 GaimStatus *old_status, GaimStatus *new_status) | |
601 { | |
602 GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); | |
603 | |
604 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
605 gaim_prefs_get_bool("/core/logging/log_away_state")) | |
606 { | |
607 time_t current_time = time(NULL); | |
608 const char *buddy_alias = gaim_buddy_get_alias(buddy); | |
609 char *tmp = NULL; | |
610 | |
611 if (!gaim_status_is_available(old_status) && | |
612 gaim_status_is_available(new_status)) | |
613 { | |
614 tmp = g_strdup_printf(_("%s came back"), buddy_alias); | |
615 } | |
616 else if (gaim_status_is_available(old_status) && | |
617 !gaim_status_is_available(new_status)) | |
618 { | |
619 tmp = g_strdup_printf(_("%s went away"), buddy_alias); | |
620 } | |
621 | |
622 if (tmp != NULL) | |
623 { | |
624 GaimLog *log = gaim_account_get_log(buddy->account); | |
625 | |
626 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, buddy_alias, | |
627 current_time, tmp); | |
628 g_free(tmp); | |
629 } | |
630 } | |
631 | |
10012 | 632 if (ops != NULL && ops->update != NULL) |
633 ops->update(gaim_get_blist(), (GaimBlistNode*)buddy); | |
9949 | 634 } |
635 | |
636 static void | |
637 notify_status_update(GaimPresence *presence, GaimStatus *old_status, | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
638 GaimStatus *new_status) |
6065 | 639 { |
9949 | 640 GaimPresenceContext context = gaim_presence_get_context(presence); |
641 | |
642 if (context == GAIM_PRESENCE_CONTEXT_ACCOUNT) | |
643 { | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
644 GaimAccount *account = gaim_presence_get_account(presence); |
9949 | 645 GaimAccountUiOps *ops = gaim_accounts_get_ui_ops(); |
646 | |
10400 | 647 if (gaim_account_get_enabled(account, gaim_core_get_ui())) |
10447 | 648 gaim_prpl_change_account_status(account, old_status, new_status); |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
649 |
9949 | 650 if (ops != NULL && ops->status_changed != NULL) |
651 { | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
652 ops->status_changed(account, new_status); |
9949 | 653 } |
654 } | |
655 else if (context == GAIM_PRESENCE_CONTEXT_CONV) | |
656 { | |
657 #if 0 | |
658 GaimConversationUiOps *ops; | |
659 GaimConversation *conv; | |
660 | |
661 conv = gaim_status_get_conversation(new_status); | |
10348 | 662 /* |
663 * TODO: Probably need to do some of the following here? This is copied | |
664 * from some old status code that was removed. | |
665 * | |
666 * char *tmp = g_strdup_printf(_("%s logged in."), alias); | |
667 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
668 * g_free(tmp); | |
669 * | |
670 * char *tmp = g_strdup_printf(_("%s logged out."), alias); | |
671 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
672 * g_free(tmp); | |
673 * | |
674 * char *tmp = g_strdup_printf(_("%s signed off"), alias); | |
675 * gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp); | |
676 * g_free(tmp); | |
677 * | |
678 * serv_got_typing_stopped(gc, name); | |
679 * | |
680 * gaim_conversation_update(c, GAIM_CONV_UPDATE_AWAY); | |
681 */ | |
9949 | 682 #endif |
683 } | |
684 else if (context == GAIM_PRESENCE_CONTEXT_BUDDY) | |
685 { | |
686 const GList *l; | |
687 | |
688 for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next) | |
689 { | |
690 notify_buddy_status_update((GaimBuddy *)l->data, presence, | |
691 old_status, new_status); | |
692 } | |
10348 | 693 |
694 /* | |
695 * TODO: Maybe we should do this here? | |
696 * GaimLog *log = gaim_account_get_log(account); | |
697 * char *tmp = g_strdup_printf(_("%s signed on"), alias); | |
698 * gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp); | |
699 * g_free(tmp); | |
700 */ | |
9949 | 701 } |
702 } | |
703 | |
10204 | 704 static void |
705 status_has_changed(GaimStatus *status) | |
9949 | 706 { |
707 GaimPresence *presence; | |
708 GaimStatus *old_status; | |
709 | |
710 presence = gaim_status_get_presence(status); | |
711 old_status = gaim_presence_get_active_status(presence); | |
712 | |
10204 | 713 /* |
714 * If this status is exclusive, then we must be setting it to "active." | |
715 * Since we are setting it to active, we want to set the currently | |
716 * active status to "inactive." | |
717 */ | |
718 if (gaim_status_is_exclusive(status)) | |
9949 | 719 { |
720 const GList *l; | |
721 | |
10006 | 722 for (l = gaim_presence_get_statuses(presence); l != NULL; l = l->next) |
9949 | 723 { |
10056
b566449d45f8
[gaim-migrate @ 11021]
Luke Schierer <lschiere@pidgin.im>
parents:
10052
diff
changeset
|
724 GaimStatus *temp_status = l->data; |
9949 | 725 |
10204 | 726 if (temp_status == status) |
727 continue; | |
9949 | 728 |
10204 | 729 if (gaim_status_is_independent(temp_status)) |
9949 | 730 continue; |
731 | |
732 if (gaim_status_is_active(temp_status)) | |
733 { | |
734 /* | |
10204 | 735 * Since we don't want infinite recursion, we have to set |
736 * the active variable ourself instead of calling | |
737 * gaim_status_set_active(). | |
9949 | 738 */ |
739 temp_status->active = FALSE; | |
740 | |
741 notify_status_update(presence, old_status, temp_status); | |
742 | |
743 break; | |
744 } | |
745 } | |
746 } | |
747 | |
10204 | 748 notify_status_update(presence, old_status, status); |
749 } | |
750 | |
751 void | |
752 gaim_status_set_active(GaimStatus *status, gboolean active) | |
753 { | |
754 if (!active && gaim_status_is_exclusive(status)) | |
755 { | |
756 gaim_debug_error("status", | |
757 "Cannot deactivate an exclusive status (%s).\n", | |
758 gaim_status_get_id(status)); | |
759 return; | |
760 } | |
761 | |
762 g_return_if_fail(status != NULL); | |
763 | |
764 if (status->active == active) | |
765 return; | |
766 | |
767 status->active = active; | |
768 | |
769 status_has_changed(status); | |
770 } | |
771 | |
772 void | |
773 gaim_status_set_active_with_attrs(GaimStatus *status, gboolean active, va_list args) | |
774 { | |
775 gboolean changed = FALSE; | |
776 const gchar *id; | |
777 | |
10714 | 778 g_return_if_fail(status != NULL); |
779 | |
10204 | 780 if (!active && gaim_status_is_exclusive(status)) |
781 { | |
782 gaim_debug_error("status", | |
783 "Cannot deactivate an exclusive status (%s).\n", | |
784 gaim_status_get_id(status)); | |
785 return; | |
786 } | |
787 | |
788 if (status->active != active) | |
789 changed = TRUE; | |
790 | |
9949 | 791 status->active = active; |
6065 | 792 |
10204 | 793 /* Set any attributes */ |
794 while ((id = va_arg(args, const char *)) != NULL) | |
795 { | |
796 GaimValue *value; | |
797 value = gaim_status_get_attr_value(status, id); | |
10713 | 798 if (value == NULL) |
799 { | |
800 gaim_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is " | |
10714 | 801 "not supported.\n", id, status->type->name); |
10713 | 802 /* Skip over the data and move on to the next attribute */ |
803 va_arg(args, void *); | |
804 continue; | |
805 } | |
806 | |
10204 | 807 if (value->type == GAIM_TYPE_STRING) |
808 { | |
809 const gchar *string_data = va_arg(args, const char *); | |
810 if (((string_data == NULL) && (value->data.string_data == NULL)) || | |
811 ((string_data != NULL) && (value->data.string_data != NULL) && | |
812 !strcmp(string_data, value->data.string_data))) | |
813 { | |
814 continue; | |
815 } | |
816 gaim_status_set_attr_string(status, id, string_data); | |
817 changed = TRUE; | |
818 } | |
819 else if (value->type == GAIM_TYPE_INT) | |
820 { | |
821 int int_data = va_arg(args, int); | |
822 if (int_data == value->data.int_data) | |
823 continue; | |
824 gaim_status_set_attr_int(status, id, int_data); | |
825 changed = TRUE; | |
826 } | |
827 else if (value->type == GAIM_TYPE_BOOLEAN) | |
828 { | |
829 gboolean boolean_data = va_arg(args, gboolean); | |
830 if (boolean_data == value->data.boolean_data) | |
831 continue; | |
832 gaim_status_set_attr_int(status, id, boolean_data); | |
833 changed = TRUE; | |
834 } | |
835 else | |
836 { | |
837 /* We don't know what the data is--skip over it */ | |
838 va_arg(args, void *); | |
839 } | |
840 } | |
841 | |
842 if (!changed) | |
843 return; | |
844 | |
845 status_has_changed(status); | |
9949 | 846 } |
847 | |
848 void | |
849 gaim_status_set_attr_boolean(GaimStatus *status, const char *id, | |
850 gboolean value) | |
851 { | |
852 GaimStatusType *status_type; | |
853 GaimValue *attr_value; | |
854 | |
855 g_return_if_fail(status != NULL); | |
856 g_return_if_fail(id != NULL); | |
857 | |
858 status_type = gaim_status_get_type(status); | |
859 | |
10197 | 860 /* Make sure this attribute exists and is the correct type. */ |
861 attr_value = gaim_status_get_attr_value(status, id); | |
862 g_return_if_fail(attr_value != NULL); | |
9949 | 863 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_BOOLEAN); |
864 | |
865 gaim_value_set_boolean(attr_value, value); | |
866 } | |
867 | |
868 void | |
869 gaim_status_set_attr_int(GaimStatus *status, const char *id, int value) | |
870 { | |
871 GaimStatusType *status_type; | |
872 GaimValue *attr_value; | |
873 | |
874 g_return_if_fail(status != NULL); | |
875 g_return_if_fail(id != NULL); | |
876 | |
877 status_type = gaim_status_get_type(status); | |
878 | |
10197 | 879 /* Make sure this attribute exists and is the correct type. */ |
880 attr_value = gaim_status_get_attr_value(status, id); | |
881 g_return_if_fail(attr_value != NULL); | |
9949 | 882 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_INT); |
883 | |
884 gaim_value_set_int(attr_value, value); | |
6065 | 885 } |
886 | |
9949 | 887 void |
888 gaim_status_set_attr_string(GaimStatus *status, const char *id, | |
889 const char *value) | |
890 { | |
891 GaimStatusType *status_type; | |
892 GaimValue *attr_value; | |
893 | |
894 g_return_if_fail(status != NULL); | |
895 g_return_if_fail(id != NULL); | |
896 | |
897 status_type = gaim_status_get_type(status); | |
898 | |
10197 | 899 /* Make sure this attribute exists and is the correct type. */ |
10196 | 900 attr_value = gaim_status_get_attr_value(status, id); |
10197 | 901 g_return_if_fail(attr_value != NULL); |
9949 | 902 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_STRING); |
903 | |
904 gaim_value_set_string(attr_value, value); | |
905 } | |
906 | |
907 GaimStatusType * | |
908 gaim_status_get_type(const GaimStatus *status) | |
909 { | |
910 g_return_val_if_fail(status != NULL, NULL); | |
911 | |
912 return status->type; | |
913 } | |
914 | |
915 GaimPresence * | |
916 gaim_status_get_presence(const GaimStatus *status) | |
6065 | 917 { |
9949 | 918 g_return_val_if_fail(status != NULL, NULL); |
919 | |
920 return status->presence; | |
921 } | |
922 | |
923 const char * | |
924 gaim_status_get_id(const GaimStatus *status) | |
925 { | |
926 g_return_val_if_fail(status != NULL, NULL); | |
927 | |
928 return gaim_status_type_get_id(gaim_status_get_type(status)); | |
929 } | |
930 | |
931 const char * | |
932 gaim_status_get_name(const GaimStatus *status) | |
933 { | |
934 g_return_val_if_fail(status != NULL, NULL); | |
935 | |
936 return gaim_status_type_get_name(gaim_status_get_type(status)); | |
937 } | |
938 | |
939 gboolean | |
940 gaim_status_is_independent(const GaimStatus *status) | |
941 { | |
942 g_return_val_if_fail(status != NULL, FALSE); | |
943 | |
944 return gaim_status_type_is_independent(gaim_status_get_type(status)); | |
945 } | |
946 | |
947 gboolean | |
10067 | 948 gaim_status_is_exclusive(const GaimStatus *status) |
949 { | |
950 g_return_val_if_fail(status != NULL, FALSE); | |
951 | |
952 return gaim_status_type_is_exclusive(gaim_status_get_type(status)); | |
953 } | |
954 | |
955 gboolean | |
9949 | 956 gaim_status_is_available(const GaimStatus *status) |
957 { | |
958 g_return_val_if_fail(status != NULL, FALSE); | |
959 | |
960 return gaim_status_type_is_available(gaim_status_get_type(status)); | |
961 } | |
6216 | 962 |
9949 | 963 gboolean |
964 gaim_status_is_active(const GaimStatus *status) | |
965 { | |
966 g_return_val_if_fail(status != NULL, FALSE); | |
967 | |
968 return status->active; | |
969 } | |
970 | |
10040
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
971 gboolean |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
972 gaim_status_is_online(const GaimStatus *status) |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
973 { |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
974 GaimStatusPrimitive primitive; |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
975 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
976 g_return_val_if_fail( status != NULL, FALSE); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
977 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
978 primitive = gaim_status_type_get_primitive(gaim_status_get_type(status)); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
979 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
980 return (primitive != GAIM_STATUS_UNSET && |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
981 primitive != GAIM_STATUS_OFFLINE); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
982 } |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
983 |
9949 | 984 GaimValue * |
985 gaim_status_get_attr_value(const GaimStatus *status, const char *id) | |
986 { | |
987 GaimStatusType *status_type; | |
988 GaimStatusAttr *attr; | |
989 | |
990 g_return_val_if_fail(status != NULL, NULL); | |
991 g_return_val_if_fail(id != NULL, NULL); | |
992 | |
993 status_type = gaim_status_get_type(status); | |
994 | |
995 /* Make sure this attribute exists. */ | |
996 attr = gaim_status_type_get_attr(status_type, id); | |
997 g_return_val_if_fail(attr != NULL, NULL); | |
998 | |
999 return (GaimValue *)g_hash_table_lookup(status->attr_values, id); | |
1000 } | |
1001 | |
1002 gboolean | |
1003 gaim_status_get_attr_boolean(const GaimStatus *status, const char *id) | |
1004 { | |
1005 const GaimValue *value; | |
1006 | |
1007 g_return_val_if_fail(status != NULL, FALSE); | |
1008 g_return_val_if_fail(id != NULL, FALSE); | |
1009 | |
1010 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
1011 return FALSE; | |
1012 | |
10197 | 1013 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_BOOLEAN, FALSE); |
9949 | 1014 |
1015 return gaim_value_get_boolean(value); | |
1016 } | |
1017 | |
1018 int | |
1019 gaim_status_get_attr_int(const GaimStatus *status, const char *id) | |
1020 { | |
1021 const GaimValue *value; | |
1022 | |
10507 | 1023 g_return_val_if_fail(status != NULL, 0); |
1024 g_return_val_if_fail(id != NULL, 0); | |
9949 | 1025 |
1026 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
10507 | 1027 return 0; |
9949 | 1028 |
1029 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_INT, 0); | |
1030 | |
1031 return gaim_value_get_int(value); | |
1032 } | |
1033 | |
1034 const char * | |
1035 gaim_status_get_attr_string(const GaimStatus *status, const char *id) | |
1036 { | |
1037 const GaimValue *value; | |
1038 | |
10507 | 1039 g_return_val_if_fail(status != NULL, NULL); |
1040 g_return_val_if_fail(id != NULL, NULL); | |
9949 | 1041 |
1042 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
10504 | 1043 return NULL; |
9949 | 1044 |
1045 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_STRING, NULL); | |
1046 | |
1047 return gaim_value_get_string(value); | |
1048 } | |
1049 | |
1050 gint | |
1051 gaim_status_compare(const GaimStatus *status1, const GaimStatus *status2) | |
1052 { | |
1053 GaimStatusType *type1, *type2; | |
1054 int score1 = 0, score2 = 0; | |
6065 | 1055 |
9949 | 1056 if ((status1 == NULL && status2 == NULL) || |
1057 (status1 == status2)) | |
1058 { | |
1059 return 0; | |
1060 } | |
1061 else if (status1 == NULL) | |
1062 return 1; | |
1063 else if (status2 == NULL) | |
1064 return -1; | |
1065 | |
1066 type1 = gaim_status_get_type(status1); | |
1067 type2 = gaim_status_get_type(status2); | |
1068 | |
1069 if (gaim_status_is_active(status1)) | |
1070 score1 = primitive_scores[gaim_status_type_get_primitive(type1)]; | |
1071 | |
1072 if (gaim_status_is_active(status2)) | |
1073 score2 = primitive_scores[gaim_status_type_get_primitive(type2)]; | |
1074 | |
1075 if (score1 > score2) | |
1076 return -1; | |
1077 else if (score1 < score2) | |
1078 return 1; | |
1079 | |
1080 return 0; | |
1081 } | |
1082 | |
1083 | |
1084 /************************************************************************** | |
1085 * GaimPresence API | |
1086 **************************************************************************/ | |
1087 GaimPresence * | |
1088 gaim_presence_new(GaimPresenceContext context) | |
1089 { | |
1090 GaimPresence *presence; | |
1091 | |
1092 g_return_val_if_fail(context != GAIM_PRESENCE_CONTEXT_UNSET, NULL); | |
1093 | |
1094 presence = g_new0(GaimPresence, 1); | |
1095 | |
1096 presence->context = context; | |
1097 | |
1098 presence->status_table = | |
10009 | 1099 g_hash_table_new_full(g_str_hash, g_str_equal, |
1100 g_free, (GFreeFunc)gaim_status_destroy); | |
9949 | 1101 |
1102 return presence; | |
1103 } | |
1104 | |
1105 GaimPresence * | |
1106 gaim_presence_new_for_account(GaimAccount *account) | |
1107 { | |
10012 | 1108 GaimPresence *presence = NULL; |
9949 | 1109 g_return_val_if_fail(account != NULL, NULL); |
1110 | |
1111 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_ACCOUNT); | |
1112 presence->u.account = account; | |
10006 | 1113 presence->statuses = gaim_prpl_get_statuses(account, presence); |
9949 | 1114 |
1115 return presence; | |
1116 } | |
1117 | |
1118 GaimPresence * | |
1119 gaim_presence_new_for_conv(GaimConversation *conv) | |
1120 { | |
1121 GaimPresence *presence; | |
1122 | |
1123 g_return_val_if_fail(conv != NULL, NULL); | |
1124 | |
1125 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_CONV); | |
1126 presence->u.chat.conv = conv; | |
10006 | 1127 /* presence->statuses = gaim_prpl_get_statuses(conv->account, presence); ? */ |
9949 | 1128 |
1129 return presence; | |
1130 } | |
6216 | 1131 |
9949 | 1132 GaimPresence * |
1133 gaim_presence_new_for_buddy(GaimBuddy *buddy) | |
1134 { | |
1135 GaimPresence *presence; | |
1136 GaimStatusBuddyKey *key; | |
10006 | 1137 GaimAccount *account; |
9949 | 1138 |
1139 g_return_val_if_fail(buddy != NULL, NULL); | |
10012 | 1140 account = buddy->account; |
9949 | 1141 |
10006 | 1142 account = buddy->account; |
1143 | |
9949 | 1144 key = g_new0(GaimStatusBuddyKey, 1); |
1145 key->account = buddy->account; | |
1146 key->name = g_strdup(buddy->name); | |
10006 | 1147 |
1148 presence = g_hash_table_lookup(buddy_presences, key); | |
1149 if (presence == NULL) | |
9949 | 1150 { |
1151 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_BUDDY); | |
1152 | |
1153 presence->u.buddy.name = g_strdup(buddy->name); | |
1154 presence->u.buddy.account = buddy->account; | |
10006 | 1155 presence->statuses = gaim_prpl_get_statuses(buddy->account, presence); |
9949 | 1156 |
1157 g_hash_table_insert(buddy_presences, key, presence); | |
1158 } | |
1159 else | |
1160 { | |
1161 g_free(key->name); | |
1162 g_free(key); | |
1163 } | |
1164 | |
1165 presence->u.buddy.ref_count++; | |
1166 presence->u.buddy.buddies = g_list_append(presence->u.buddy.buddies, | |
1167 buddy); | |
1168 | |
1169 return presence; | |
1170 } | |
1171 | |
1172 void | |
1173 gaim_presence_destroy(GaimPresence *presence) | |
1174 { | |
1175 g_return_if_fail(presence != NULL); | |
6216 | 1176 |
9949 | 1177 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) |
1178 { | |
1179 GaimStatusBuddyKey key; | |
1180 | |
10077 | 1181 if(presence->u.buddy.ref_count != 0) |
1182 return; | |
9949 | 1183 |
1184 key.account = presence->u.buddy.account; | |
1185 key.name = presence->u.buddy.name; | |
1186 | |
1187 g_hash_table_remove(buddy_presences, &key); | |
1188 | |
1189 if (presence->u.buddy.name != NULL) | |
1190 g_free(presence->u.buddy.name); | |
1191 } | |
1192 else if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_CONV) | |
1193 { | |
1194 if (presence->u.chat.user != NULL) | |
1195 g_free(presence->u.chat.user); | |
1196 } | |
1197 | |
1198 if (presence->statuses != NULL) | |
1199 g_list_free(presence->statuses); | |
1200 | |
1201 g_hash_table_destroy(presence->status_table); | |
1202 | |
1203 g_free(presence); | |
1204 } | |
1205 | |
10580 | 1206 /* |
1207 * TODO: Maybe we should cal gaim_presence_destroy() after we | |
1208 * decrement the ref count? I don't see why we should | |
1209 * make other places do it manually when we can do it here. | |
1210 */ | |
9949 | 1211 void |
1212 gaim_presence_remove_buddy(GaimPresence *presence, GaimBuddy *buddy) | |
1213 { | |
1214 g_return_if_fail(presence != NULL); | |
1215 g_return_if_fail(buddy != NULL); | |
1216 g_return_if_fail(gaim_presence_get_context(presence) == | |
1217 GAIM_PRESENCE_CONTEXT_BUDDY); | |
1218 | |
1219 if (g_list_find(presence->u.buddy.buddies, buddy) != NULL) | |
1220 { | |
1221 presence->u.buddy.buddies = g_list_remove(presence->u.buddy.buddies, | |
1222 buddy); | |
1223 presence->u.buddy.ref_count--; | |
1224 } | |
6065 | 1225 } |
1226 | |
9949 | 1227 void |
1228 gaim_presence_add_status(GaimPresence *presence, GaimStatus *status) | |
1229 { | |
1230 g_return_if_fail(presence != NULL); | |
1231 g_return_if_fail(status != NULL); | |
1232 | |
1233 presence->statuses = g_list_append(presence->statuses, status); | |
1234 | |
1235 g_hash_table_insert(presence->status_table, | |
1236 g_strdup(gaim_status_get_id(status)), status); | |
1237 } | |
1238 | |
1239 void | |
1240 gaim_presence_add_presence(GaimPresence *presence, const GList *source_list) | |
1241 { | |
1242 const GList *l; | |
1243 | |
1244 g_return_if_fail(presence != NULL); | |
1245 g_return_if_fail(source_list != NULL); | |
1246 | |
1247 for (l = source_list; l != NULL; l = l->next) | |
1248 gaim_presence_add_status(presence, (GaimStatus *)l->data); | |
1249 } | |
1250 | |
1251 void | |
1252 gaim_presence_set_status_active(GaimPresence *presence, const char *status_id, | |
1253 gboolean active) | |
1254 { | |
1255 GaimStatus *status; | |
1256 | |
1257 g_return_if_fail(presence != NULL); | |
1258 g_return_if_fail(status_id != NULL); | |
1259 | |
1260 status = gaim_presence_get_status(presence, status_id); | |
1261 | |
1262 g_return_if_fail(status != NULL); | |
10348 | 1263 /* TODO: Should we do the following? */ |
1264 /* g_return_if_fail(active == status->active); */ | |
9949 | 1265 |
10067 | 1266 if (gaim_status_is_exclusive(status)) |
9949 | 1267 { |
1268 if (!active) | |
1269 { | |
1270 gaim_debug_warning("status", | |
1271 "Attempted to set a non-independent status " | |
1272 "(%s) inactive. Only independent statuses " | |
1273 "can be specifically marked inactive.", | |
1274 status_id); | |
1275 | |
1276 return; | |
1277 } | |
1278 | |
10052 | 1279 } else if (presence->active_status != NULL) { |
1280 gaim_status_set_active(presence->active_status, FALSE); | |
9949 | 1281 |
1282 } | |
1283 | |
1284 gaim_status_set_active(status, active); | |
10052 | 1285 presence->active_status = status; |
9949 | 1286 } |
1287 | |
1288 void | |
1289 gaim_presence_switch_status(GaimPresence *presence, const char *status_id) | |
1290 { | |
1291 GaimStatus *status; | |
1292 | |
1293 g_return_if_fail(presence != NULL); | |
1294 g_return_if_fail(status_id != NULL); | |
1295 | |
1296 status = gaim_presence_get_status(presence, status_id); | |
1297 | |
1298 g_return_if_fail(status != NULL); | |
1299 | |
1300 if (gaim_status_is_independent(status)) | |
1301 return; | |
1302 | |
1303 if (presence->active_status != NULL) | |
1304 gaim_status_set_active(presence->active_status, FALSE); | |
1305 | |
1306 gaim_status_set_active(status, TRUE); | |
1307 } | |
1308 | |
1309 static void | |
1310 update_buddy_idle(GaimBuddy *buddy, GaimPresence *presence, | |
1311 time_t current_time, gboolean old_idle, gboolean idle) | |
1312 { | |
1313 GaimBlistUiOps *ops = gaim_get_blist()->ui_ops; | |
1314 | |
1315 if (!old_idle && idle) | |
1316 { | |
1317 gaim_signal_emit(gaim_blist_get_handle(), "buddy-idle", buddy); | |
1318 | |
1319 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
1320 gaim_prefs_get_bool("/core/logging/log_idle_state")) | |
1321 { | |
1322 GaimLog *log = gaim_account_get_log(buddy->account); | |
1323 char *tmp = g_strdup_printf(_("%s became idle"), | |
1324 gaim_buddy_get_alias(buddy)); | |
1325 | |
1326 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, | |
1327 gaim_buddy_get_alias(buddy), current_time, tmp); | |
1328 g_free(tmp); | |
1329 } | |
1330 } | |
1331 else if (old_idle && !idle) | |
1332 { | |
1333 gaim_signal_emit(gaim_blist_get_handle(), "buddy-unidle", buddy); | |
1334 | |
1335 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
1336 gaim_prefs_get_bool("/core/logging/log_idle_state")) | |
1337 { | |
1338 GaimLog *log = gaim_account_get_log(buddy->account); | |
1339 char *tmp = g_strdup_printf(_("%s became unidle"), | |
1340 gaim_buddy_get_alias(buddy)); | |
1341 | |
1342 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, | |
1343 gaim_buddy_get_alias(buddy), current_time, tmp); | |
1344 g_free(tmp); | |
1345 } | |
1346 } | |
1347 | |
10378 | 1348 gaim_contact_invalidate_priority_buddy(gaim_buddy_get_contact(buddy)); |
9949 | 1349 |
1350 if (ops != NULL && ops->update != NULL) | |
1351 ops->update(gaim_get_blist(), (GaimBlistNode *)buddy); | |
1352 } | |
1353 | |
1354 void | |
1355 gaim_presence_set_idle(GaimPresence *presence, gboolean idle, time_t idle_time) | |
1356 { | |
1357 gboolean old_idle; | |
1358 | |
1359 g_return_if_fail(presence != NULL); | |
1360 | |
1361 if (presence->idle == idle && presence->idle_time == idle_time) | |
1362 return; | |
1363 | |
1364 old_idle = presence->idle; | |
1365 presence->idle = idle; | |
1366 presence->idle_time = (idle ? idle_time : 0); | |
1367 | |
1368 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) | |
1369 { | |
1370 const GList *l; | |
1371 time_t current_time = time(NULL); | |
1372 | |
1373 for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next) | |
1374 { | |
1375 update_buddy_idle((GaimBuddy *)l->data, presence, current_time, | |
1376 old_idle, idle); | |
1377 } | |
1378 } | |
1379 } | |
1380 | |
1381 void | |
10006 | 1382 gaim_presence_set_login_time(GaimPresence *presence, time_t login_time) |
1383 { | |
1384 g_return_if_fail(presence != NULL); | |
1385 | |
1386 if (presence->login_time == login_time) | |
1387 return; | |
1388 | |
1389 presence->login_time = login_time; | |
1390 } | |
1391 | |
1392 void | |
9949 | 1393 gaim_presence_set_warning_level(GaimPresence *presence, unsigned int level) |
6065 | 1394 { |
9949 | 1395 g_return_if_fail(presence != NULL); |
1396 g_return_if_fail(level <= 100); | |
1397 | |
1398 if (presence->warning_level == level) | |
1399 return; | |
1400 | |
1401 presence->warning_level = level; | |
1402 | |
1403 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) | |
1404 { | |
1405 GaimBlistUiOps *ops = gaim_get_blist()->ui_ops; | |
1406 | |
1407 if (ops != NULL && ops->update != NULL) | |
1408 { | |
1409 const GList *l; | |
1410 | |
1411 for (l = gaim_presence_get_buddies(presence); | |
1412 l != NULL; | |
1413 l = l->next) | |
1414 { | |
1415 ops->update(gaim_get_blist(), (GaimBlistNode *)l->data); | |
1416 } | |
1417 } | |
1418 } | |
1419 } | |
1420 | |
1421 GaimPresenceContext | |
1422 gaim_presence_get_context(const GaimPresence *presence) | |
1423 { | |
1424 g_return_val_if_fail(presence != NULL, GAIM_PRESENCE_CONTEXT_UNSET); | |
1425 | |
1426 return presence->context; | |
1427 } | |
1428 | |
1429 GaimAccount * | |
1430 gaim_presence_get_account(const GaimPresence *presence) | |
1431 { | |
1432 GaimPresenceContext context; | |
1433 | |
1434 g_return_val_if_fail(presence != NULL, NULL); | |
1435 | |
1436 context = gaim_presence_get_context(presence); | |
1437 | |
1438 g_return_val_if_fail(context == GAIM_PRESENCE_CONTEXT_ACCOUNT || | |
1439 context == GAIM_PRESENCE_CONTEXT_BUDDY, NULL); | |
1440 | |
1441 return presence->u.account; | |
1442 } | |
1443 | |
1444 GaimConversation * | |
1445 gaim_presence_get_conversation(const GaimPresence *presence) | |
1446 { | |
1447 g_return_val_if_fail(presence != NULL, NULL); | |
1448 g_return_val_if_fail(gaim_presence_get_context(presence) == | |
1449 GAIM_PRESENCE_CONTEXT_CONV, NULL); | |
1450 | |
1451 return presence->u.chat.conv; | |
1452 } | |
1453 | |
1454 const char * | |
1455 gaim_presence_get_chat_user(const GaimPresence *presence) | |
1456 { | |
1457 g_return_val_if_fail(presence != NULL, NULL); | |
1458 g_return_val_if_fail(gaim_presence_get_context(presence) == | |
1459 GAIM_PRESENCE_CONTEXT_CONV, NULL); | |
1460 | |
1461 return presence->u.chat.user; | |
1462 } | |
1463 | |
1464 const GList * | |
1465 gaim_presence_get_buddies(const GaimPresence *presence) | |
1466 { | |
1467 g_return_val_if_fail(presence != NULL, NULL); | |
1468 g_return_val_if_fail(gaim_presence_get_context(presence) == | |
1469 GAIM_PRESENCE_CONTEXT_BUDDY, NULL); | |
1470 | |
1471 return presence->u.buddy.buddies; | |
1472 } | |
1473 | |
1474 const GList * | |
1475 gaim_presence_get_statuses(const GaimPresence *presence) | |
1476 { | |
1477 g_return_val_if_fail(presence != NULL, NULL); | |
1478 | |
1479 return presence->statuses; | |
1480 } | |
1481 | |
1482 GaimStatus * | |
1483 gaim_presence_get_status(const GaimPresence *presence, const char *status_id) | |
1484 { | |
1485 GaimStatus *status; | |
10006 | 1486 const GList *l = NULL; |
9949 | 1487 |
1488 g_return_val_if_fail(presence != NULL, NULL); | |
1489 g_return_val_if_fail(status_id != NULL, NULL); | |
1490 | |
10006 | 1491 /* What's the purpose of this hash table? */ |
10012 | 1492 status = (GaimStatus *)g_hash_table_lookup(presence->status_table, |
10006 | 1493 status_id); |
10012 | 1494 |
10006 | 1495 if (status == NULL) { |
10012 | 1496 for (l = gaim_presence_get_statuses(presence); |
10006 | 1497 l != NULL && status == NULL; l = l->next) |
1498 { | |
1499 GaimStatus *temp_status = l->data; | |
10012 | 1500 |
10006 | 1501 if (!strcmp(status_id, gaim_status_get_id(temp_status))) |
1502 status = temp_status; | |
1503 } | |
1504 | |
1505 if (status != NULL) | |
1506 g_hash_table_insert(presence->status_table, | |
1507 g_strdup(gaim_status_get_id(status)), status); | |
10012 | 1508 } |
9949 | 1509 |
1510 return status; | |
1511 } | |
1512 | |
1513 GaimStatus * | |
1514 gaim_presence_get_active_status(const GaimPresence *presence) | |
1515 { | |
1516 g_return_val_if_fail(presence != NULL, NULL); | |
1517 | |
1518 return presence->active_status; | |
1519 } | |
1520 | |
1521 gboolean | |
1522 gaim_presence_is_available(const GaimPresence *presence) | |
1523 { | |
1524 GaimStatus *status; | |
1525 | |
1526 g_return_val_if_fail(presence != NULL, FALSE); | |
1527 | |
1528 status = gaim_presence_get_active_status(presence); | |
1529 | |
1530 return ((status != NULL && gaim_status_is_available(status)) && | |
1531 !gaim_presence_is_idle(presence)); | |
1532 } | |
1533 | |
1534 gboolean | |
1535 gaim_presence_is_online(const GaimPresence *presence) | |
1536 { | |
1537 GaimStatus *status; | |
1538 | |
1539 g_return_val_if_fail(presence != NULL, FALSE); | |
1540 | |
1541 if ((status = gaim_presence_get_active_status(presence)) == NULL) | |
1542 return FALSE; | |
1543 | |
10040
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
1544 return gaim_status_is_online(status); |
9949 | 1545 } |
1546 | |
1547 gboolean | |
1548 gaim_presence_is_status_active(const GaimPresence *presence, | |
1549 const char *status_id) | |
1550 { | |
1551 GaimStatus *status; | |
1552 | |
1553 g_return_val_if_fail(presence != NULL, FALSE); | |
1554 g_return_val_if_fail(status_id != NULL, FALSE); | |
1555 | |
1556 status = gaim_presence_get_status(presence, status_id); | |
1557 | |
1558 return (status != NULL && gaim_status_is_active(status)); | |
1559 } | |
1560 | |
1561 gboolean | |
1562 gaim_presence_is_status_primitive_active(const GaimPresence *presence, | |
1563 GaimStatusPrimitive primitive) | |
1564 { | |
1565 GaimStatus *status; | |
1566 GaimStatusType *status_type; | |
1567 | |
1568 g_return_val_if_fail(presence != NULL, FALSE); | |
1569 g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, FALSE); | |
1570 | |
1571 status = gaim_presence_get_active_status(presence); | |
1572 status_type = gaim_status_get_type(status); | |
1573 | |
1574 if (gaim_status_type_get_primitive(status_type) == primitive) | |
1575 return TRUE; | |
6065 | 1576 |
1577 return FALSE; | |
1578 } | |
1579 | |
9949 | 1580 gboolean |
1581 gaim_presence_is_idle(const GaimPresence *presence) | |
6065 | 1582 { |
9949 | 1583 g_return_val_if_fail(presence != NULL, FALSE); |
1584 | |
1585 return presence->idle; | |
6065 | 1586 } |
1587 | |
9949 | 1588 time_t |
1589 gaim_presence_get_idle_time(const GaimPresence *presence) | |
6065 | 1590 { |
9949 | 1591 g_return_val_if_fail(presence != NULL, 0); |
6065 | 1592 |
9949 | 1593 return presence->idle_time; |
1594 } | |
6065 | 1595 |
9949 | 1596 unsigned int |
1597 gaim_presence_get_warning_level(const GaimPresence *presence) | |
1598 { | |
1599 g_return_val_if_fail(presence != NULL, 0); | |
6216 | 1600 |
9949 | 1601 return presence->warning_level; |
6065 | 1602 } |
1603 | |
10567 | 1604 time_t |
1605 gaim_presence_get_login_time(const GaimPresence *presence) | |
1606 { | |
1607 g_return_val_if_fail(presence != NULL, 0); | |
1608 | |
1609 return presence->login_time; | |
1610 } | |
1611 | |
9949 | 1612 gint |
1613 gaim_presence_compare(const GaimPresence *presence1, | |
1614 const GaimPresence *presence2) | |
6065 | 1615 { |
9949 | 1616 gboolean idle1, idle2; |
1617 size_t idle_time_1, idle_time_2; | |
1618 int score1 = 0, score2 = 0; | |
1619 const GList *l; | |
6065 | 1620 |
9949 | 1621 if ((presence1 == NULL && presence2 == NULL) || (presence1 == presence2)) |
1622 return 0; | |
1623 else if (presence1 == NULL) | |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1624 return 1; |
9949 | 1625 else if (presence2 == NULL) |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1626 return -1; |
6065 | 1627 |
9949 | 1628 /* Compute the score of the first set of statuses. */ |
1629 for (l = gaim_presence_get_statuses(presence1); l != NULL; l = l->next) | |
1630 { | |
1631 GaimStatus *status = (GaimStatus *)l->data; | |
1632 GaimStatusType *type = gaim_status_get_type(status); | |
6065 | 1633 |
9949 | 1634 if (gaim_status_is_active(status)) |
1635 score1 += primitive_scores[gaim_status_type_get_primitive(type)]; | |
6065 | 1636 } |
1637 | |
9949 | 1638 /* Compute the score of the second set of statuses. */ |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1639 for (l = gaim_presence_get_statuses(presence2); l != NULL; l = l->next) |
9949 | 1640 { |
1641 GaimStatus *status = (GaimStatus *)l->data; | |
1642 GaimStatusType *type = gaim_status_get_type(status); | |
6065 | 1643 |
9949 | 1644 if (gaim_status_is_active(status)) |
1645 score2 += primitive_scores[gaim_status_type_get_primitive(type)]; | |
6065 | 1646 } |
1647 | |
9949 | 1648 idle1 = gaim_presence_is_idle(presence1); |
1649 idle2 = gaim_presence_is_idle(presence2); | |
6065 | 1650 |
9949 | 1651 if (idle1) |
1652 score1 += primitive_scores[SCORE_IDLE]; | |
6065 | 1653 |
9949 | 1654 if (idle2) |
1655 score2 += primitive_scores[SCORE_IDLE]; | |
6065 | 1656 |
9949 | 1657 idle_time_1 = gaim_presence_get_idle_time(presence1); |
1658 idle_time_2 = gaim_presence_get_idle_time(presence2); | |
6065 | 1659 |
9949 | 1660 if (idle_time_1 > idle_time_2) |
1661 score1 += primitive_scores[SCORE_IDLE_TIME]; | |
1662 else if (idle_time_1 < idle_time_2) | |
1663 score2 += primitive_scores[SCORE_IDLE_TIME]; | |
6065 | 1664 |
9949 | 1665 if (score1 < score2) |
1666 return 1; | |
1667 else if (score1 > score2) | |
1668 return -1; | |
1669 | |
1670 return 0; | |
1671 } | |
1672 | |
6065 | 1673 |
9949 | 1674 /************************************************************************** |
1675 * Status subsystem | |
1676 **************************************************************************/ | |
1677 static void | |
1678 score_pref_changed_cb(const char *name, GaimPrefType type, gpointer value, | |
1679 gpointer data) | |
1680 { | |
1681 int index = GPOINTER_TO_INT(data); | |
6065 | 1682 |
9949 | 1683 primitive_scores[index] = GPOINTER_TO_INT(value); |
6065 | 1684 } |
1685 | |
10519 | 1686 static guint |
10006 | 1687 gaim_buddy_presences_hash(gconstpointer key) |
1688 { | |
10012 | 1689 const GaimStatusBuddyKey *me = key; |
1690 guint ret; | |
1691 char *str; | |
1692 | |
1693 str = g_strdup_printf("%p%s", me->account, me->name); | |
1694 ret = g_str_hash(str); | |
1695 g_free(str); | |
1696 | |
1697 return ret; | |
10006 | 1698 } |
1699 | |
10519 | 1700 static gboolean |
10006 | 1701 gaim_buddy_presences_equal(gconstpointer a, gconstpointer b) |
1702 { | |
1703 GaimStatusBuddyKey *key_a = (GaimStatusBuddyKey *)a; | |
1704 GaimStatusBuddyKey *key_b = (GaimStatusBuddyKey *)b; | |
1705 | |
10012 | 1706 if(key_a->account == key_b->account && |
1707 !strcmp(key_a->name, key_b->name)) | |
10006 | 1708 return TRUE; |
1709 else | |
1710 return FALSE; | |
1711 } | |
1712 | |
10519 | 1713 static void |
1714 gaim_buddy_presences_key_free(gpointer a) | |
1715 { | |
1716 GaimStatusBuddyKey *key = (GaimStatusBuddyKey *)a; | |
1717 g_free(key->name); | |
1718 g_free(key); | |
1719 } | |
1720 | |
10087 | 1721 void * |
10418 | 1722 gaim_status_get_handle(void) { |
10087 | 1723 static int handle; |
1724 | |
1725 return &handle; | |
1726 } | |
1727 | |
9949 | 1728 void |
10418 | 1729 gaim_status_init(void) |
6065 | 1730 { |
10418 | 1731 void *handle = gaim_status_get_handle; |
10087 | 1732 |
9949 | 1733 gaim_prefs_add_none("/core/status"); |
1734 gaim_prefs_add_none("/core/status/scores"); | |
6065 | 1735 |
9949 | 1736 gaim_prefs_add_int("/core/status/scores/offline", |
1737 primitive_scores[GAIM_STATUS_OFFLINE]); | |
1738 gaim_prefs_add_int("/core/status/scores/available", | |
1739 primitive_scores[GAIM_STATUS_AVAILABLE]); | |
1740 gaim_prefs_add_int("/core/status/scores/hidden", | |
1741 primitive_scores[GAIM_STATUS_HIDDEN]); | |
1742 gaim_prefs_add_int("/core/status/scores/away", | |
1743 primitive_scores[GAIM_STATUS_AWAY]); | |
1744 gaim_prefs_add_int("/core/status/scores/extended_away", | |
1745 primitive_scores[GAIM_STATUS_EXTENDED_AWAY]); | |
1746 gaim_prefs_add_int("/core/status/scores/idle", | |
1747 primitive_scores[SCORE_IDLE]); | |
6065 | 1748 |
10087 | 1749 gaim_prefs_connect_callback(handle, "/core/status/scores/offline", |
9949 | 1750 score_pref_changed_cb, |
1751 GINT_TO_POINTER(GAIM_STATUS_OFFLINE)); | |
10087 | 1752 gaim_prefs_connect_callback(handle, "/core/status/scores/available", |
9949 | 1753 score_pref_changed_cb, |
1754 GINT_TO_POINTER(GAIM_STATUS_AVAILABLE)); | |
10087 | 1755 gaim_prefs_connect_callback(handle, "/core/status/scores/hidden", |
9949 | 1756 score_pref_changed_cb, |
1757 GINT_TO_POINTER(GAIM_STATUS_HIDDEN)); | |
10087 | 1758 gaim_prefs_connect_callback(handle, "/core/status/scores/away", |
9949 | 1759 score_pref_changed_cb, |
1760 GINT_TO_POINTER(GAIM_STATUS_AWAY)); | |
10087 | 1761 gaim_prefs_connect_callback(handle, "/core/status/scores/extended_away", |
9949 | 1762 score_pref_changed_cb, |
1763 GINT_TO_POINTER(GAIM_STATUS_EXTENDED_AWAY)); | |
10087 | 1764 gaim_prefs_connect_callback(handle, "/core/status/scores/idle", |
9949 | 1765 score_pref_changed_cb, |
1766 GINT_TO_POINTER(SCORE_IDLE)); | |
10006 | 1767 |
10519 | 1768 buddy_presences = g_hash_table_new_full(gaim_buddy_presences_hash, |
1769 gaim_buddy_presences_equal, | |
1770 gaim_buddy_presences_key_free, NULL); | |
9949 | 1771 } |
6065 | 1772 |
9949 | 1773 void |
10418 | 1774 gaim_status_uninit(void) |
9949 | 1775 { |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1776 if (buddy_presences != NULL) |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1777 { |
10077 | 1778 g_hash_table_destroy(buddy_presences); |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1779 |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1780 buddy_presences = NULL; |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1781 } |
9949 | 1782 } |