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