| 256 |
255 |
| 257 return purple_status_type_new_full(primitive, id, name, TRUE, |
256 return purple_status_type_new_full(primitive, id, name, TRUE, |
| 258 user_settable, FALSE); |
257 user_settable, FALSE); |
| 259 } |
258 } |
| 260 |
259 |
| |
260 static void |
| |
261 status_type_add_attr(PurpleStatusType *status_type, const char *id, |
| |
262 const char *name, PurpleValue *value) |
| |
263 { |
| |
264 PurpleStatusAttr *attr; |
| |
265 |
| |
266 g_return_if_fail(status_type != NULL); |
| |
267 g_return_if_fail(id != NULL); |
| |
268 g_return_if_fail(name != NULL); |
| |
269 g_return_if_fail(value != NULL); |
| |
270 |
| |
271 attr = purple_status_attr_new(id, name, value); |
| |
272 |
| |
273 status_type->attrs = g_list_append(status_type->attrs, attr); |
| |
274 } |
| |
275 |
| |
276 static void |
| |
277 status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args) |
| |
278 { |
| |
279 const char *id, *name; |
| |
280 PurpleValue *value; |
| |
281 |
| |
282 g_return_if_fail(status_type != NULL); |
| |
283 |
| |
284 while ((id = va_arg(args, const char *)) != NULL) |
| |
285 { |
| |
286 name = va_arg(args, const char *); |
| |
287 g_return_if_fail(name != NULL); |
| |
288 |
| |
289 value = va_arg(args, PurpleValue *); |
| |
290 g_return_if_fail(value != NULL); |
| |
291 |
| |
292 status_type_add_attr(status_type, id, name, value); |
| |
293 } |
| |
294 } |
| |
295 |
| 261 PurpleStatusType * |
296 PurpleStatusType * |
| 262 purple_status_type_new_with_attrs(PurpleStatusPrimitive primitive, |
297 purple_status_type_new_with_attrs(PurpleStatusPrimitive primitive, |
| 263 const char *id, const char *name, |
298 const char *id, const char *name, |
| 264 gboolean saveable, gboolean user_settable, |
299 gboolean saveable, gboolean user_settable, |
| 265 gboolean independent, const char *attr_id, |
300 gboolean independent, const char *attr_id, |
| 276 |
311 |
| 277 status_type = purple_status_type_new_full(primitive, id, name, saveable, |
312 status_type = purple_status_type_new_full(primitive, id, name, saveable, |
| 278 user_settable, independent); |
313 user_settable, independent); |
| 279 |
314 |
| 280 /* Add the first attribute */ |
315 /* Add the first attribute */ |
| 281 purple_status_type_add_attr(status_type, attr_id, attr_name, attr_value); |
316 status_type_add_attr(status_type, attr_id, attr_name, attr_value); |
| 282 |
317 |
| 283 va_start(args, attr_value); |
318 va_start(args, attr_value); |
| 284 purple_status_type_add_attrs_vargs(status_type, args); |
319 status_type_add_attrs_vargs(status_type, args); |
| 285 va_end(args); |
320 va_end(args); |
| 286 |
321 |
| 287 return status_type; |
322 return status_type; |
| 288 } |
323 } |
| 289 |
324 |
| 292 { |
327 { |
| 293 g_return_if_fail(status_type != NULL); |
328 g_return_if_fail(status_type != NULL); |
| 294 |
329 |
| 295 g_free(status_type->id); |
330 g_free(status_type->id); |
| 296 g_free(status_type->name); |
331 g_free(status_type->name); |
| 297 g_free(status_type->primary_attr_id); |
|
| 298 |
332 |
| 299 g_list_foreach(status_type->attrs, (GFunc)purple_status_attr_destroy, NULL); |
333 g_list_foreach(status_type->attrs, (GFunc)purple_status_attr_destroy, NULL); |
| 300 g_list_free(status_type->attrs); |
334 g_list_free(status_type->attrs); |
| 301 |
335 |
| 302 PURPLE_DBUS_UNREGISTER_POINTER(status_type); |
336 PURPLE_DBUS_UNREGISTER_POINTER(status_type); |
| 303 g_free(status_type); |
337 g_free(status_type); |
| 304 } |
338 } |
| 305 |
339 |
| 306 void |
|
| 307 purple_status_type_set_primary_attr(PurpleStatusType *status_type, const char *id) |
|
| 308 { |
|
| 309 g_return_if_fail(status_type != NULL); |
|
| 310 |
|
| 311 g_free(status_type->primary_attr_id); |
|
| 312 status_type->primary_attr_id = g_strdup(id); |
|
| 313 } |
|
| 314 |
|
| 315 void |
|
| 316 purple_status_type_add_attr(PurpleStatusType *status_type, const char *id, |
|
| 317 const char *name, PurpleValue *value) |
|
| 318 { |
|
| 319 PurpleStatusAttr *attr; |
|
| 320 |
|
| 321 g_return_if_fail(status_type != NULL); |
|
| 322 g_return_if_fail(id != NULL); |
|
| 323 g_return_if_fail(name != NULL); |
|
| 324 g_return_if_fail(value != NULL); |
|
| 325 |
|
| 326 attr = purple_status_attr_new(id, name, value); |
|
| 327 |
|
| 328 status_type->attrs = g_list_append(status_type->attrs, attr); |
|
| 329 } |
|
| 330 |
|
| 331 void |
|
| 332 purple_status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args) |
|
| 333 { |
|
| 334 const char *id, *name; |
|
| 335 PurpleValue *value; |
|
| 336 |
|
| 337 g_return_if_fail(status_type != NULL); |
|
| 338 |
|
| 339 while ((id = va_arg(args, const char *)) != NULL) |
|
| 340 { |
|
| 341 name = va_arg(args, const char *); |
|
| 342 g_return_if_fail(name != NULL); |
|
| 343 |
|
| 344 value = va_arg(args, PurpleValue *); |
|
| 345 g_return_if_fail(value != NULL); |
|
| 346 |
|
| 347 purple_status_type_add_attr(status_type, id, name, value); |
|
| 348 } |
|
| 349 } |
|
| 350 |
|
| 351 void |
|
| 352 purple_status_type_add_attrs(PurpleStatusType *status_type, const char *id, |
|
| 353 const char *name, PurpleValue *value, ...) |
|
| 354 { |
|
| 355 va_list args; |
|
| 356 |
|
| 357 g_return_if_fail(status_type != NULL); |
|
| 358 g_return_if_fail(id != NULL); |
|
| 359 g_return_if_fail(name != NULL); |
|
| 360 g_return_if_fail(value != NULL); |
|
| 361 |
|
| 362 /* Add the first attribute */ |
|
| 363 purple_status_type_add_attr(status_type, id, name, value); |
|
| 364 |
|
| 365 va_start(args, value); |
|
| 366 purple_status_type_add_attrs_vargs(status_type, args); |
|
| 367 va_end(args); |
|
| 368 } |
|
| 369 |
|
| 370 PurpleStatusPrimitive |
340 PurpleStatusPrimitive |
| 371 purple_status_type_get_primitive(const PurpleStatusType *status_type) |
341 purple_status_type_get_primitive(const PurpleStatusType *status_type) |
| 372 { |
342 { |
| 373 g_return_val_if_fail(status_type != NULL, PURPLE_STATUS_UNSET); |
343 g_return_val_if_fail(status_type != NULL, PURPLE_STATUS_UNSET); |
| 374 |
344 |
| 704 old_status = NULL; |
666 old_status = NULL; |
| 705 |
667 |
| 706 notify_status_update(presence, old_status, status); |
668 notify_status_update(presence, old_status, status); |
| 707 } |
669 } |
| 708 |
670 |
| 709 void |
671 static void |
| 710 purple_status_set_active(PurpleStatus *status, gboolean active) |
672 status_set_attr_boolean(PurpleStatus *status, const char *id, |
| 711 { |
|
| 712 purple_status_set_active_with_attrs_list(status, active, NULL); |
|
| 713 } |
|
| 714 |
|
| 715 /* |
|
| 716 * This used to parse the va_list directly, but now it creates a GList |
|
| 717 * and passes it to purple_status_set_active_with_attrs_list(). That |
|
| 718 * function was created because accounts.c needs to pass a GList of |
|
| 719 * attributes to the status API. |
|
| 720 */ |
|
| 721 void |
|
| 722 purple_status_set_active_with_attrs(PurpleStatus *status, gboolean active, va_list args) |
|
| 723 { |
|
| 724 GList *attrs = NULL; |
|
| 725 const gchar *id; |
|
| 726 gpointer data; |
|
| 727 |
|
| 728 while ((id = va_arg(args, const char *)) != NULL) |
|
| 729 { |
|
| 730 attrs = g_list_append(attrs, (char *)id); |
|
| 731 data = va_arg(args, void *); |
|
| 732 attrs = g_list_append(attrs, data); |
|
| 733 } |
|
| 734 purple_status_set_active_with_attrs_list(status, active, attrs); |
|
| 735 g_list_free(attrs); |
|
| 736 } |
|
| 737 |
|
| 738 void |
|
| 739 purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, |
|
| 740 GList *attrs) |
|
| 741 { |
|
| 742 gboolean changed = FALSE; |
|
| 743 GList *l; |
|
| 744 GList *specified_attr_ids = NULL; |
|
| 745 PurpleStatusType *status_type; |
|
| 746 |
|
| 747 g_return_if_fail(status != NULL); |
|
| 748 |
|
| 749 if (!active && purple_status_is_exclusive(status)) |
|
| 750 { |
|
| 751 purple_debug_error("status", |
|
| 752 "Cannot deactivate an exclusive status (%s).\n", |
|
| 753 purple_status_get_id(status)); |
|
| 754 return; |
|
| 755 } |
|
| 756 |
|
| 757 if (status->active != active) |
|
| 758 { |
|
| 759 changed = TRUE; |
|
| 760 } |
|
| 761 |
|
| 762 status->active = active; |
|
| 763 |
|
| 764 /* Set any attributes */ |
|
| 765 l = attrs; |
|
| 766 while (l != NULL) |
|
| 767 { |
|
| 768 const gchar *id; |
|
| 769 PurpleValue *value; |
|
| 770 |
|
| 771 id = l->data; |
|
| 772 l = l->next; |
|
| 773 value = purple_status_get_attr_value(status, id); |
|
| 774 if (value == NULL) |
|
| 775 { |
|
| 776 purple_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is " |
|
| 777 "not supported.\n", id, status->type->name); |
|
| 778 /* Skip over the data and move on to the next attribute */ |
|
| 779 l = l->next; |
|
| 780 continue; |
|
| 781 } |
|
| 782 |
|
| 783 specified_attr_ids = g_list_prepend(specified_attr_ids, (gpointer)id); |
|
| 784 |
|
| 785 if (value->type == PURPLE_TYPE_STRING) |
|
| 786 { |
|
| 787 const gchar *string_data = l->data; |
|
| 788 l = l->next; |
|
| 789 if (purple_strequal(string_data, value->data.string_data)) |
|
| 790 continue; |
|
| 791 purple_status_set_attr_string(status, id, string_data); |
|
| 792 changed = TRUE; |
|
| 793 } |
|
| 794 else if (value->type == PURPLE_TYPE_INT) |
|
| 795 { |
|
| 796 int int_data = GPOINTER_TO_INT(l->data); |
|
| 797 l = l->next; |
|
| 798 if (int_data == value->data.int_data) |
|
| 799 continue; |
|
| 800 purple_status_set_attr_int(status, id, int_data); |
|
| 801 changed = TRUE; |
|
| 802 } |
|
| 803 else if (value->type == PURPLE_TYPE_BOOLEAN) |
|
| 804 { |
|
| 805 gboolean boolean_data = GPOINTER_TO_INT(l->data); |
|
| 806 l = l->next; |
|
| 807 if (boolean_data == value->data.boolean_data) |
|
| 808 continue; |
|
| 809 purple_status_set_attr_boolean(status, id, boolean_data); |
|
| 810 changed = TRUE; |
|
| 811 } |
|
| 812 else |
|
| 813 { |
|
| 814 /* We don't know what the data is--skip over it */ |
|
| 815 l = l->next; |
|
| 816 } |
|
| 817 } |
|
| 818 |
|
| 819 /* Reset any unspecified attributes to their default value */ |
|
| 820 status_type = purple_status_get_type(status); |
|
| 821 l = purple_status_type_get_attrs(status_type); |
|
| 822 while (l != NULL) { |
|
| 823 PurpleStatusAttr *attr; |
|
| 824 |
|
| 825 attr = l->data; |
|
| 826 l = l->next; |
|
| 827 |
|
| 828 if (!g_list_find_custom(specified_attr_ids, attr->id, (GCompareFunc)strcmp)) { |
|
| 829 PurpleValue *default_value; |
|
| 830 default_value = purple_status_attr_get_value(attr); |
|
| 831 if (default_value->type == PURPLE_TYPE_STRING) { |
|
| 832 const char *cur = purple_status_get_attr_string(status, attr->id); |
|
| 833 const char *def = purple_value_get_string(default_value); |
|
| 834 if ((cur == NULL && def == NULL) |
|
| 835 || (cur != NULL && def != NULL |
|
| 836 && !strcmp(cur, def))) { |
|
| 837 continue; |
|
| 838 } |
|
| 839 |
|
| 840 purple_status_set_attr_string(status, attr->id, def); |
|
| 841 } else if (default_value->type == PURPLE_TYPE_INT) { |
|
| 842 int cur = purple_status_get_attr_int(status, attr->id); |
|
| 843 int def = purple_value_get_int(default_value); |
|
| 844 if (cur == def) |
|
| 845 continue; |
|
| 846 |
|
| 847 purple_status_set_attr_int(status, attr->id, def); |
|
| 848 } else if (default_value->type == PURPLE_TYPE_BOOLEAN) { |
|
| 849 gboolean cur = purple_status_get_attr_boolean(status, attr->id); |
|
| 850 gboolean def = purple_value_get_boolean(default_value); |
|
| 851 if (cur == def) |
|
| 852 continue; |
|
| 853 |
|
| 854 purple_status_set_attr_boolean(status, attr->id, def); |
|
| 855 } |
|
| 856 changed = TRUE; |
|
| 857 } |
|
| 858 } |
|
| 859 g_list_free(specified_attr_ids); |
|
| 860 |
|
| 861 if (!changed) |
|
| 862 return; |
|
| 863 status_has_changed(status); |
|
| 864 } |
|
| 865 |
|
| 866 void |
|
| 867 purple_status_set_attr_boolean(PurpleStatus *status, const char *id, |
|
| 868 gboolean value) |
673 gboolean value) |
| 869 { |
674 { |
| 870 PurpleValue *attr_value; |
675 PurpleValue *attr_value; |
| 871 |
676 |
| 872 g_return_if_fail(status != NULL); |
677 g_return_if_fail(status != NULL); |
| 923 /* XXX: Check if the value has actually changed. If it has, and the status |
728 /* XXX: Check if the value has actually changed. If it has, and the status |
| 924 * is active, should this trigger 'status_has_changed'? */ |
729 * is active, should this trigger 'status_has_changed'? */ |
| 925 purple_value_set_string(attr_value, value); |
730 purple_value_set_string(attr_value, value); |
| 926 } |
731 } |
| 927 |
732 |
| |
733 void |
| |
734 purple_status_set_active(PurpleStatus *status, gboolean active) |
| |
735 { |
| |
736 purple_status_set_active_with_attrs_list(status, active, NULL); |
| |
737 } |
| |
738 |
| |
739 /* |
| |
740 * This used to parse the va_list directly, but now it creates a GList |
| |
741 * and passes it to purple_status_set_active_with_attrs_list(). That |
| |
742 * function was created because accounts.c needs to pass a GList of |
| |
743 * attributes to the status API. |
| |
744 */ |
| |
745 void |
| |
746 purple_status_set_active_with_attrs(PurpleStatus *status, gboolean active, va_list args) |
| |
747 { |
| |
748 GList *attrs = NULL; |
| |
749 const gchar *id; |
| |
750 gpointer data; |
| |
751 |
| |
752 while ((id = va_arg(args, const char *)) != NULL) |
| |
753 { |
| |
754 attrs = g_list_append(attrs, (char *)id); |
| |
755 data = va_arg(args, void *); |
| |
756 attrs = g_list_append(attrs, data); |
| |
757 } |
| |
758 purple_status_set_active_with_attrs_list(status, active, attrs); |
| |
759 g_list_free(attrs); |
| |
760 } |
| |
761 |
| |
762 void |
| |
763 purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, |
| |
764 GList *attrs) |
| |
765 { |
| |
766 gboolean changed = FALSE; |
| |
767 GList *l; |
| |
768 GList *specified_attr_ids = NULL; |
| |
769 PurpleStatusType *status_type; |
| |
770 |
| |
771 g_return_if_fail(status != NULL); |
| |
772 |
| |
773 if (!active && purple_status_is_exclusive(status)) |
| |
774 { |
| |
775 purple_debug_error("status", |
| |
776 "Cannot deactivate an exclusive status (%s).\n", |
| |
777 purple_status_get_id(status)); |
| |
778 return; |
| |
779 } |
| |
780 |
| |
781 if (status->active != active) |
| |
782 { |
| |
783 changed = TRUE; |
| |
784 } |
| |
785 |
| |
786 status->active = active; |
| |
787 |
| |
788 /* Set any attributes */ |
| |
789 l = attrs; |
| |
790 while (l != NULL) |
| |
791 { |
| |
792 const gchar *id; |
| |
793 PurpleValue *value; |
| |
794 |
| |
795 id = l->data; |
| |
796 l = l->next; |
| |
797 value = purple_status_get_attr_value(status, id); |
| |
798 if (value == NULL) |
| |
799 { |
| |
800 purple_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is " |
| |
801 "not supported.\n", id, status->type->name); |
| |
802 /* Skip over the data and move on to the next attribute */ |
| |
803 l = l->next; |
| |
804 continue; |
| |
805 } |
| |
806 |
| |
807 specified_attr_ids = g_list_prepend(specified_attr_ids, (gpointer)id); |
| |
808 |
| |
809 if (purple_value_get_type(value) == PURPLE_TYPE_STRING) |
| |
810 { |
| |
811 const gchar *string_data = l->data; |
| |
812 l = l->next; |
| |
813 if (purple_strequal(string_data, purple_value_get_string(value))) |
| |
814 continue; |
| |
815 status_set_attr_string(status, id, string_data); |
| |
816 changed = TRUE; |
| |
817 } |
| |
818 else if (purple_value_get_type(value) == PURPLE_TYPE_INT) |
| |
819 { |
| |
820 int int_data = GPOINTER_TO_INT(l->data); |
| |
821 l = l->next; |
| |
822 if (int_data == purple_value_get_int(value)) |
| |
823 continue; |
| |
824 status_set_attr_int(status, id, int_data); |
| |
825 changed = TRUE; |
| |
826 } |
| |
827 else if (purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN) |
| |
828 { |
| |
829 gboolean boolean_data = GPOINTER_TO_INT(l->data); |
| |
830 l = l->next; |
| |
831 if (boolean_data == purple_value_get_boolean(value)) |
| |
832 continue; |
| |
833 status_set_attr_boolean(status, id, boolean_data); |
| |
834 changed = TRUE; |
| |
835 } |
| |
836 else |
| |
837 { |
| |
838 /* We don't know what the data is--skip over it */ |
| |
839 l = l->next; |
| |
840 } |
| |
841 } |
| |
842 |
| |
843 /* Reset any unspecified attributes to their default value */ |
| |
844 status_type = purple_status_get_type(status); |
| |
845 l = purple_status_type_get_attrs(status_type); |
| |
846 while (l != NULL) { |
| |
847 PurpleStatusAttr *attr; |
| |
848 |
| |
849 attr = l->data; |
| |
850 l = l->next; |
| |
851 |
| |
852 if (!g_list_find_custom(specified_attr_ids, attr->id, (GCompareFunc)strcmp)) { |
| |
853 PurpleValue *default_value; |
| |
854 default_value = purple_status_attr_get_value(attr); |
| |
855 if (purple_value_get_type(default_value) == PURPLE_TYPE_STRING) { |
| |
856 const char *cur = purple_status_get_attr_string(status, attr->id); |
| |
857 const char *def = purple_value_get_string(default_value); |
| |
858 if ((cur == NULL && def == NULL) |
| |
859 || (cur != NULL && def != NULL |
| |
860 && !strcmp(cur, def))) { |
| |
861 continue; |
| |
862 } |
| |
863 |
| |
864 status_set_attr_string(status, attr->id, def); |
| |
865 } else if (purple_value_get_type(default_value) == PURPLE_TYPE_INT) { |
| |
866 int cur = purple_status_get_attr_int(status, attr->id); |
| |
867 int def = purple_value_get_int(default_value); |
| |
868 if (cur == def) |
| |
869 continue; |
| |
870 |
| |
871 status_set_attr_int(status, attr->id, def); |
| |
872 } else if (purple_value_get_type(default_value) == PURPLE_TYPE_BOOLEAN) { |
| |
873 gboolean cur = purple_status_get_attr_boolean(status, attr->id); |
| |
874 gboolean def = purple_value_get_boolean(default_value); |
| |
875 if (cur == def) |
| |
876 continue; |
| |
877 |
| |
878 status_set_attr_boolean(status, attr->id, def); |
| |
879 } |
| |
880 changed = TRUE; |
| |
881 } |
| |
882 } |
| |
883 g_list_free(specified_attr_ids); |
| |
884 |
| |
885 if (!changed) |
| |
886 return; |
| |
887 status_has_changed(status); |
| |
888 } |
| |
889 |
| 928 PurpleStatusType * |
890 PurpleStatusType * |
| 929 purple_status_get_type(const PurpleStatus *status) |
891 purple_status_get_type(const PurpleStatus *status) |
| 930 { |
892 { |
| 931 g_return_val_if_fail(status != NULL, NULL); |
893 g_return_val_if_fail(status != NULL, NULL); |
| 932 |
894 |
| 1181 |
1143 |
| 1182 g_hash_table_destroy(presence->status_table); |
1144 g_hash_table_destroy(presence->status_table); |
| 1183 |
1145 |
| 1184 PURPLE_DBUS_UNREGISTER_POINTER(presence); |
1146 PURPLE_DBUS_UNREGISTER_POINTER(presence); |
| 1185 g_free(presence); |
1147 g_free(presence); |
| 1186 } |
|
| 1187 |
|
| 1188 void |
|
| 1189 purple_presence_add_status(PurplePresence *presence, PurpleStatus *status) |
|
| 1190 { |
|
| 1191 g_return_if_fail(presence != NULL); |
|
| 1192 g_return_if_fail(status != NULL); |
|
| 1193 |
|
| 1194 presence->statuses = g_list_append(presence->statuses, status); |
|
| 1195 |
|
| 1196 g_hash_table_insert(presence->status_table, |
|
| 1197 g_strdup(purple_status_get_id(status)), status); |
|
| 1198 } |
|
| 1199 |
|
| 1200 void |
|
| 1201 purple_presence_add_list(PurplePresence *presence, GList *source_list) |
|
| 1202 { |
|
| 1203 GList *l; |
|
| 1204 |
|
| 1205 g_return_if_fail(presence != NULL); |
|
| 1206 g_return_if_fail(source_list != NULL); |
|
| 1207 |
|
| 1208 for (l = source_list; l != NULL; l = l->next) |
|
| 1209 purple_presence_add_status(presence, (PurpleStatus *)l->data); |
|
| 1210 } |
1148 } |
| 1211 |
1149 |
| 1212 void |
1150 void |
| 1213 purple_presence_set_status_active(PurplePresence *presence, const char *status_id, |
1151 purple_presence_set_status_active(PurplePresence *presence, const char *status_id, |
| 1214 gboolean active) |
1152 gboolean active) |