comparison libpurple/status.c @ 32819:2c6510167895 default tip

propagate from branch 'im.pidgin.pidgin.2.x.y' (head 3315c5dfbd0ad16511bdcf865e5b07c02d07df24) to branch 'im.pidgin.pidgin' (head cbd1eda6bcbf0565ae7766396bb8f6f419cb6a9a)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sat, 02 Jun 2012 02:30:49 +0000
parents 78fae2fc38d5
children
comparison
equal deleted inserted replaced
32818:01ff09d4a463 32819:2c6510167895
42 { 42 {
43 PurpleStatusPrimitive primitive; 43 PurpleStatusPrimitive primitive;
44 44
45 char *id; 45 char *id;
46 char *name; 46 char *name;
47 char *primary_attr_id;
48 47
49 gboolean saveable; 48 gboolean saveable;
50 gboolean user_settable; 49 gboolean user_settable;
51 gboolean independent; 50 gboolean independent;
52 51
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
431 g_return_val_if_fail(status_type != NULL, FALSE); 401 g_return_val_if_fail(status_type != NULL, FALSE);
432 402
433 primitive = purple_status_type_get_primitive(status_type); 403 primitive = purple_status_type_get_primitive(status_type);
434 404
435 return (primitive == PURPLE_STATUS_AVAILABLE); 405 return (primitive == PURPLE_STATUS_AVAILABLE);
436 }
437
438 const char *
439 purple_status_type_get_primary_attr(const PurpleStatusType *status_type)
440 {
441 g_return_val_if_fail(status_type != NULL, NULL);
442
443 return status_type->primary_attr_id;
444 } 406 }
445 407
446 PurpleStatusAttr * 408 PurpleStatusAttr *
447 purple_status_type_get_attr(const PurpleStatusType *status_type, const char *id) 409 purple_status_type_get_attr(const PurpleStatusType *status_type, const char *id)
448 { 410 {
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);
878 g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_BOOLEAN); 683 g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_BOOLEAN);
879 684
880 purple_value_set_boolean(attr_value, value); 685 purple_value_set_boolean(attr_value, value);
881 } 686 }
882 687
883 void 688 static void
884 purple_status_set_attr_int(PurpleStatus *status, const char *id, int value) 689 status_set_attr_int(PurpleStatus *status, const char *id, int value)
885 { 690 {
886 PurpleValue *attr_value; 691 PurpleValue *attr_value;
887 692
888 g_return_if_fail(status != NULL); 693 g_return_if_fail(status != NULL);
889 g_return_if_fail(id != NULL); 694 g_return_if_fail(id != NULL);
894 g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_INT); 699 g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_INT);
895 700
896 purple_value_set_int(attr_value, value); 701 purple_value_set_int(attr_value, value);
897 } 702 }
898 703
899 void 704 static void
900 purple_status_set_attr_string(PurpleStatus *status, const char *id, 705 status_set_attr_string(PurpleStatus *status, const char *id,
901 const char *value) 706 const char *value)
902 { 707 {
903 PurpleValue *attr_value; 708 PurpleValue *attr_value;
904 709
905 g_return_if_fail(status != NULL); 710 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
1135 1097
1136 g_return_val_if_fail(conv != NULL, NULL); 1098 g_return_val_if_fail(conv != NULL, NULL);
1137 1099
1138 presence = purple_presence_new(PURPLE_PRESENCE_CONTEXT_CONV); 1100 presence = purple_presence_new(PURPLE_PRESENCE_CONTEXT_CONV);
1139 presence->u.chat.conv = conv; 1101 presence->u.chat.conv = conv;
1140 /* presence->statuses = purple_prpl_get_statuses(conv->account, presence); ? */ 1102 /* presence->statuses = purple_prpl_get_statuses(purple_conversation_get_account(conv), presence); ? */
1141 1103
1142 return presence; 1104 return presence;
1143 } 1105 }
1144 1106
1145 PurplePresence * 1107 PurplePresence *
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)