comparison src/status.c @ 10348:64bc206c7473

[gaim-migrate @ 11562] Ability to read sub-statuses from ~/.gaim/status.xml. We don't actually WRITE these to the file yet, so this doesn't do anything. Also a few other minor changes elsewhere. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sun, 12 Dec 2004 23:57:52 +0000
parents ee4f477fc8cf
children 242b5482910e
comparison
equal deleted inserted replaced
10347:4d2ecbb139a0 10348:64bc206c7473
133 * are fully backward compatible. The new status API just 133 * are fully backward compatible. The new status API just
134 * adds the optional sub-statuses to the XML file. 134 * adds the optional sub-statuses to the XML file.
135 */ 135 */
136 struct _GaimStatusSaved 136 struct _GaimStatusSaved
137 { 137 {
138 char *name; 138 char *title;
139 GaimStatusType *type; 139 GaimStatusPrimitive type;
140 char *message; 140 char *message;
141 141
142 GList *individual; /**< A list of GaimStatusSavedSub's. */ 142 GList *substatuses; /**< A list of GaimStatusSavedSub's. */
143 }; 143 };
144 144
145 struct _GaimStatusSavedSub 145 struct _GaimStatusSavedSub
146 { 146 {
147 GaimAccount *account; 147 GaimAccount *account;
148 GaimStatusType *type; 148 const GaimStatusType *type;
149 char *message; 149 char *message;
150 }; 150 };
151 151
152 static int primitive_scores[] = 152 static int primitive_scores[] =
153 { 153 {
167 static GList *saved_statuses = NULL; 167 static GList *saved_statuses = NULL;
168 168
169 #define SCORE_IDLE 5 169 #define SCORE_IDLE 5
170 #define SCORE_IDLE_TIME 6 170 #define SCORE_IDLE_TIME 6
171 171
172 /**
173 * Elements of this array correspond to the GaimStatusPrimitive
174 * enumeration.
175 */
176 static const char *primitive_names[] =
177 {
178 "unset",
179 "offline",
180 "available",
181 "unavailable",
182 "hidden",
183 "away",
184 "extended_away"
185 };
186
187 static GaimStatusPrimitive
188 gaim_primitive_get_type(const char *name)
189 {
190 int i;
191
192 g_return_val_if_fail(name != NULL, GAIM_STATUS_UNSET);
193
194 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++)
195 {
196 if (!strcmp(name, primitive_names[i]))
197 return i;
198 }
199
200 return GAIM_STATUS_UNSET;
201 }
202
172 /************************************************************************** 203 /**************************************************************************
173 * GaimStatusType API 204 * GaimStatusType API
174 **************************************************************************/ 205 **************************************************************************/
175 GaimStatusType * 206 GaimStatusType *
176 gaim_status_type_new_full(GaimStatusPrimitive primitive, const char *id, 207 gaim_status_type_new_full(GaimStatusPrimitive primitive, const char *id,
430 g_return_val_if_fail(status_type != NULL, NULL); 461 g_return_val_if_fail(status_type != NULL, NULL);
431 462
432 return status_type->attrs; 463 return status_type->attrs;
433 } 464 }
434 465
466 const GaimStatusType *
467 gaim_status_type_find_with_id(GList *status_types, const char *id)
468 {
469 GaimStatusType *status_type;
470
471 g_return_val_if_fail(id != NULL, NULL);
472
473 while (status_types != NULL)
474 {
475 status_type = status_types->data;
476
477 if (!strcmp(id, status_type->id))
478 return status_type;
479 }
480
481 return NULL;
482 }
483
435 484
436 /************************************************************************** 485 /**************************************************************************
437 * GaimStatusAttr API 486 * GaimStatusAttr API
438 **************************************************************************/ 487 **************************************************************************/
439 GaimStatusAttr * 488 GaimStatusAttr *
611 ops->status_changed(account, new_status); 660 ops->status_changed(account, new_status);
612 } 661 }
613 } 662 }
614 else if (context == GAIM_PRESENCE_CONTEXT_CONV) 663 else if (context == GAIM_PRESENCE_CONTEXT_CONV)
615 { 664 {
616 /* TODO */
617 #if 0 665 #if 0
618 GaimConversationUiOps *ops; 666 GaimConversationUiOps *ops;
619 GaimConversation *conv; 667 GaimConversation *conv;
620 668
621 conv = gaim_status_get_conversation(new_status); 669 conv = gaim_status_get_conversation(new_status);
622 #endif
623 }
624 else if (context == GAIM_PRESENCE_CONTEXT_BUDDY)
625 {
626 const GList *l;
627
628 for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next)
629 {
630 notify_buddy_status_update((GaimBuddy *)l->data, presence,
631 old_status, new_status);
632 }
633 }
634 }
635
636 static void
637 status_has_changed(GaimStatus *status)
638 {
639 GaimPresence *presence;
640 GaimStatus *old_status;
641
642 presence = gaim_status_get_presence(status);
643 old_status = gaim_presence_get_active_status(presence);
644
645 /*
646 * If this status is exclusive, then we must be setting it to "active."
647 * Since we are setting it to active, we want to set the currently
648 * active status to "inactive."
649 */
650 if (gaim_status_is_exclusive(status))
651 {
652 const GList *l;
653
654 for (l = gaim_presence_get_statuses(presence); l != NULL; l = l->next)
655 {
656 GaimStatus *temp_status = l->data;
657
658 if (temp_status == status)
659 continue;
660
661 if (gaim_status_is_independent(temp_status))
662 continue;
663
664 if (gaim_status_is_active(temp_status))
665 {
666 /*
667 * Since we don't want infinite recursion, we have to set
668 * the active variable ourself instead of calling
669 * gaim_status_set_active().
670 */
671 temp_status->active = FALSE;
672
673 notify_status_update(presence, old_status, temp_status);
674
675 break;
676 }
677 }
678 }
679
680 notify_status_update(presence, old_status, status);
681 }
682
683 void
684 gaim_status_set_active(GaimStatus *status, gboolean active)
685 {
686 if (!active && gaim_status_is_exclusive(status))
687 {
688 gaim_debug_error("status",
689 "Cannot deactivate an exclusive status (%s).\n",
690 gaim_status_get_id(status));
691 return;
692 }
693
694 g_return_if_fail(status != NULL);
695
696 if (status->active == active)
697 return;
698
699 status->active = active;
700
701 status_has_changed(status);
702 }
703
704 void
705 gaim_status_set_active_with_attrs(GaimStatus *status, gboolean active, va_list args)
706 {
707 gboolean changed = FALSE;
708 const gchar *id;
709
710 if (!active && gaim_status_is_exclusive(status))
711 {
712 gaim_debug_error("status",
713 "Cannot deactivate an exclusive status (%s).\n",
714 gaim_status_get_id(status));
715 return;
716 }
717
718 g_return_if_fail(status != NULL);
719
720 if (status->active != active)
721 changed = TRUE;
722
723 status->active = active;
724
725 /* Set any attributes */
726 while ((id = va_arg(args, const char *)) != NULL)
727 {
728 GaimValue *value;
729 value = gaim_status_get_attr_value(status, id);
730 if (value->type == GAIM_TYPE_STRING)
731 {
732 const gchar *string_data = va_arg(args, const char *);
733 if (((string_data == NULL) && (value->data.string_data == NULL)) ||
734 ((string_data != NULL) && (value->data.string_data != NULL) &&
735 !strcmp(string_data, value->data.string_data)))
736 {
737 continue;
738 }
739 gaim_status_set_attr_string(status, id, string_data);
740 changed = TRUE;
741 }
742 else if (value->type == GAIM_TYPE_INT)
743 {
744 int int_data = va_arg(args, int);
745 if (int_data == value->data.int_data)
746 continue;
747 gaim_status_set_attr_int(status, id, int_data);
748 changed = TRUE;
749 }
750 else if (value->type == GAIM_TYPE_BOOLEAN)
751 {
752 gboolean boolean_data = va_arg(args, gboolean);
753 if (boolean_data == value->data.boolean_data)
754 continue;
755 gaim_status_set_attr_int(status, id, boolean_data);
756 changed = TRUE;
757 }
758 else
759 {
760 /* We don't know what the data is--skip over it */
761 va_arg(args, void *);
762 }
763 }
764
765 if (!changed)
766 return;
767
768 status_has_changed(status);
769 }
770
771 void
772 gaim_status_set_attr_boolean(GaimStatus *status, const char *id,
773 gboolean value)
774 {
775 GaimStatusType *status_type;
776 GaimValue *attr_value;
777
778 g_return_if_fail(status != NULL);
779 g_return_if_fail(id != NULL);
780
781 status_type = gaim_status_get_type(status);
782
783 /* Make sure this attribute exists and is the correct type. */
784 attr_value = gaim_status_get_attr_value(status, id);
785 g_return_if_fail(attr_value != NULL);
786 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_BOOLEAN);
787
788 gaim_value_set_boolean(attr_value, value);
789 }
790
791 void
792 gaim_status_set_attr_int(GaimStatus *status, const char *id, int value)
793 {
794 GaimStatusType *status_type;
795 GaimValue *attr_value;
796
797 g_return_if_fail(status != NULL);
798 g_return_if_fail(id != NULL);
799
800 status_type = gaim_status_get_type(status);
801
802 /* Make sure this attribute exists and is the correct type. */
803 attr_value = gaim_status_get_attr_value(status, id);
804 g_return_if_fail(attr_value != NULL);
805 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_INT);
806
807 gaim_value_set_int(attr_value, value);
808 }
809
810 void
811 gaim_status_set_attr_string(GaimStatus *status, const char *id,
812 const char *value)
813 {
814 GaimStatusType *status_type;
815 GaimValue *attr_value;
816
817 g_return_if_fail(status != NULL);
818 g_return_if_fail(id != NULL);
819
820 status_type = gaim_status_get_type(status);
821
822 /* Make sure this attribute exists and is the correct type. */
823 attr_value = gaim_status_get_attr_value(status, id);
824 g_return_if_fail(attr_value != NULL);
825 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_STRING);
826
827 gaim_value_set_string(attr_value, value);
828 }
829
830 GaimStatusType *
831 gaim_status_get_type(const GaimStatus *status)
832 {
833 g_return_val_if_fail(status != NULL, NULL);
834
835 return status->type;
836 }
837
838 GaimPresence *
839 gaim_status_get_presence(const GaimStatus *status)
840 {
841 g_return_val_if_fail(status != NULL, NULL);
842
843 return status->presence;
844 }
845
846 const char *
847 gaim_status_get_id(const GaimStatus *status)
848 {
849 g_return_val_if_fail(status != NULL, NULL);
850
851 return gaim_status_type_get_id(gaim_status_get_type(status));
852 }
853
854 const char *
855 gaim_status_get_name(const GaimStatus *status)
856 {
857 g_return_val_if_fail(status != NULL, NULL);
858
859 return gaim_status_type_get_name(gaim_status_get_type(status));
860 }
861
862 gboolean
863 gaim_status_is_independent(const GaimStatus *status)
864 {
865 g_return_val_if_fail(status != NULL, FALSE);
866
867 return gaim_status_type_is_independent(gaim_status_get_type(status));
868 }
869
870 gboolean
871 gaim_status_is_exclusive(const GaimStatus *status)
872 {
873 g_return_val_if_fail(status != NULL, FALSE);
874
875 return gaim_status_type_is_exclusive(gaim_status_get_type(status));
876 }
877
878 gboolean
879 gaim_status_is_available(const GaimStatus *status)
880 {
881 g_return_val_if_fail(status != NULL, FALSE);
882
883 return gaim_status_type_is_available(gaim_status_get_type(status));
884 }
885
886 gboolean
887 gaim_status_is_active(const GaimStatus *status)
888 {
889 g_return_val_if_fail(status != NULL, FALSE);
890
891 return status->active;
892 }
893
894 gboolean
895 gaim_status_is_online(const GaimStatus *status)
896 {
897 GaimStatusPrimitive primitive;
898
899 g_return_val_if_fail( status != NULL, FALSE);
900
901 primitive = gaim_status_type_get_primitive(gaim_status_get_type(status));
902
903 return (primitive != GAIM_STATUS_UNSET &&
904 primitive != GAIM_STATUS_OFFLINE);
905 }
906
907 GaimValue *
908 gaim_status_get_attr_value(const GaimStatus *status, const char *id)
909 {
910 GaimStatusType *status_type;
911 GaimStatusAttr *attr;
912
913 g_return_val_if_fail(status != NULL, NULL);
914 g_return_val_if_fail(id != NULL, NULL);
915
916 status_type = gaim_status_get_type(status);
917
918 /* Make sure this attribute exists. */
919 attr = gaim_status_type_get_attr(status_type, id);
920 g_return_val_if_fail(attr != NULL, NULL);
921
922 return (GaimValue *)g_hash_table_lookup(status->attr_values, id);
923 }
924
925 gboolean
926 gaim_status_get_attr_boolean(const GaimStatus *status, const char *id)
927 {
928 const GaimValue *value;
929
930 g_return_val_if_fail(status != NULL, FALSE);
931 g_return_val_if_fail(id != NULL, FALSE);
932
933 if ((value = gaim_status_get_attr_value(status, id)) == NULL)
934 return FALSE;
935
936 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_BOOLEAN, FALSE);
937
938 return gaim_value_get_boolean(value);
939 }
940
941 int
942 gaim_status_get_attr_int(const GaimStatus *status, const char *id)
943 {
944 const GaimValue *value;
945
946 g_return_val_if_fail(status != NULL, FALSE);
947 g_return_val_if_fail(id != NULL, FALSE);
948
949 if ((value = gaim_status_get_attr_value(status, id)) == NULL)
950 return FALSE;
951
952 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_INT, 0);
953
954 return gaim_value_get_int(value);
955 }
956
957 const char *
958 gaim_status_get_attr_string(const GaimStatus *status, const char *id)
959 {
960 const GaimValue *value;
961
962 g_return_val_if_fail(status != NULL, FALSE);
963 g_return_val_if_fail(id != NULL, FALSE);
964
965 if ((value = gaim_status_get_attr_value(status, id)) == NULL)
966 return FALSE;
967
968 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_STRING, NULL);
969
970 return gaim_value_get_string(value);
971 }
972
973 gint
974 gaim_status_compare(const GaimStatus *status1, const GaimStatus *status2)
975 {
976 GaimStatusType *type1, *type2;
977 int score1 = 0, score2 = 0;
978
979 if ((status1 == NULL && status2 == NULL) ||
980 (status1 == status2))
981 {
982 return 0;
983 }
984 else if (status1 == NULL)
985 return 1;
986 else if (status2 == NULL)
987 return -1;
988
989 type1 = gaim_status_get_type(status1);
990 type2 = gaim_status_get_type(status2);
991
992 if (gaim_status_is_active(status1))
993 score1 = primitive_scores[gaim_status_type_get_primitive(type1)];
994
995 if (gaim_status_is_active(status2))
996 score2 = primitive_scores[gaim_status_type_get_primitive(type2)];
997
998 if (score1 > score2)
999 return -1;
1000 else if (score1 < score2)
1001 return 1;
1002
1003 return 0;
1004 }
1005
1006
1007 /**************************************************************************
1008 * GaimPresence API
1009 **************************************************************************/
1010 GaimPresence *
1011 gaim_presence_new(GaimPresenceContext context)
1012 {
1013 GaimPresence *presence;
1014
1015 g_return_val_if_fail(context != GAIM_PRESENCE_CONTEXT_UNSET, NULL);
1016
1017 presence = g_new0(GaimPresence, 1);
1018
1019 presence->context = context;
1020
1021 presence->status_table =
1022 g_hash_table_new_full(g_str_hash, g_str_equal,
1023 g_free, (GFreeFunc)gaim_status_destroy);
1024
1025 return presence;
1026 }
1027
1028 GaimPresence *
1029 gaim_presence_new_for_account(GaimAccount *account)
1030 {
1031 GaimPresence *presence = NULL;
1032 g_return_val_if_fail(account != NULL, NULL);
1033
1034 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_ACCOUNT);
1035 presence->u.account = account;
1036 presence->statuses = gaim_prpl_get_statuses(account, presence);
1037
1038 return presence;
1039 }
1040
1041 GaimPresence *
1042 gaim_presence_new_for_conv(GaimConversation *conv)
1043 {
1044 GaimPresence *presence;
1045
1046 g_return_val_if_fail(conv != NULL, NULL);
1047
1048 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_CONV);
1049 presence->u.chat.conv = conv;
1050 /* presence->statuses = gaim_prpl_get_statuses(conv->account, presence); ? */
1051
1052 return presence;
1053 }
1054
1055 GaimPresence *
1056 gaim_presence_new_for_buddy(GaimBuddy *buddy)
1057 {
1058 GaimPresence *presence;
1059 GaimStatusBuddyKey *key;
1060 GaimAccount *account;
1061
1062 g_return_val_if_fail(buddy != NULL, NULL);
1063 account = buddy->account;
1064
1065 account = buddy->account;
1066
1067 key = g_new0(GaimStatusBuddyKey, 1);
1068 key->account = buddy->account;
1069 key->name = g_strdup(buddy->name);
1070
1071 presence = g_hash_table_lookup(buddy_presences, key);
1072 if (presence == NULL)
1073 {
1074 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_BUDDY);
1075
1076 presence->u.buddy.name = g_strdup(buddy->name);
1077 presence->u.buddy.account = buddy->account;
1078 presence->statuses = gaim_prpl_get_statuses(buddy->account, presence);
1079
1080 g_hash_table_insert(buddy_presences, key, presence);
1081 }
1082 else
1083 {
1084 g_free(key->name);
1085 g_free(key);
1086 }
1087
1088 presence->u.buddy.ref_count++;
1089 presence->u.buddy.buddies = g_list_append(presence->u.buddy.buddies,
1090 buddy);
1091
1092 return presence;
1093 }
1094
1095 void
1096 gaim_presence_destroy(GaimPresence *presence)
1097 {
1098 g_return_if_fail(presence != NULL);
1099
1100 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY)
1101 {
1102 GaimStatusBuddyKey key;
1103
1104 presence->u.buddy.ref_count--;
1105
1106 if(presence->u.buddy.ref_count != 0)
1107 return;
1108
1109 key.account = presence->u.buddy.account;
1110 key.name = presence->u.buddy.name;
1111
1112 g_hash_table_remove(buddy_presences, &key);
1113
1114 if (presence->u.buddy.name != NULL)
1115 g_free(presence->u.buddy.name);
1116 }
1117 else if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_CONV)
1118 {
1119 if (presence->u.chat.user != NULL)
1120 g_free(presence->u.chat.user);
1121 }
1122
1123 if (presence->statuses != NULL)
1124 g_list_free(presence->statuses);
1125
1126 g_hash_table_destroy(presence->status_table);
1127
1128 g_free(presence);
1129 }
1130
1131 void
1132 gaim_presence_remove_buddy(GaimPresence *presence, GaimBuddy *buddy)
1133 {
1134 g_return_if_fail(presence != NULL);
1135 g_return_if_fail(buddy != NULL);
1136 g_return_if_fail(gaim_presence_get_context(presence) ==
1137 GAIM_PRESENCE_CONTEXT_BUDDY);
1138
1139 if (g_list_find(presence->u.buddy.buddies, buddy) != NULL)
1140 {
1141 presence->u.buddy.buddies = g_list_remove(presence->u.buddy.buddies,
1142 buddy);
1143 presence->u.buddy.ref_count--;
1144 }
1145 }
1146
1147 void
1148 gaim_presence_add_status(GaimPresence *presence, GaimStatus *status)
1149 {
1150 g_return_if_fail(presence != NULL);
1151 g_return_if_fail(status != NULL);
1152
1153 presence->statuses = g_list_append(presence->statuses, status);
1154
1155 g_hash_table_insert(presence->status_table,
1156 g_strdup(gaim_status_get_id(status)), status);
1157 }
1158
1159 void
1160 gaim_presence_add_presence(GaimPresence *presence, const GList *source_list)
1161 {
1162 const GList *l;
1163
1164 g_return_if_fail(presence != NULL);
1165 g_return_if_fail(source_list != NULL);
1166
1167 for (l = source_list; l != NULL; l = l->next)
1168 gaim_presence_add_status(presence, (GaimStatus *)l->data);
1169 }
1170
1171 /* 670 /*
1172 * TODO: Should we g_return_if_fail(active == status_id->active); ? 671 * TODO: Probably need to do some of the following here? This is copied
1173 * 672 * from some old status code that was removed.
1174 * TODO: If a buddy signed on or off, should we do any of the following?
1175 * (Note: We definitely need to do some of this somewhere, I'm just
1176 * not sure if here is the correct place.)
1177 * 673 *
1178 * char *tmp = g_strdup_printf(_("%s logged in."), alias); 674 * char *tmp = g_strdup_printf(_("%s logged in."), alias);
1179 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); 675 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL));
1180 * g_free(tmp);
1181 *
1182 * GaimLog *log = gaim_account_get_log(account);
1183 * char *tmp = g_strdup_printf(_("%s signed on"), alias);
1184 * gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp);
1185 * g_free(tmp); 676 * g_free(tmp);
1186 * 677 *
1187 * char *tmp = g_strdup_printf(_("%s logged out."), alias); 678 * char *tmp = g_strdup_printf(_("%s logged out."), alias);
1188 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); 679 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL));
1189 * g_free(tmp); 680 * g_free(tmp);
1193 * g_free(tmp); 684 * g_free(tmp);
1194 * 685 *
1195 * serv_got_typing_stopped(gc, name); 686 * serv_got_typing_stopped(gc, name);
1196 * 687 *
1197 * gaim_conversation_update(c, GAIM_CONV_UPDATE_AWAY); 688 * gaim_conversation_update(c, GAIM_CONV_UPDATE_AWAY);
1198 *
1199 */ 689 */
690 #endif
691 }
692 else if (context == GAIM_PRESENCE_CONTEXT_BUDDY)
693 {
694 const GList *l;
695
696 for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next)
697 {
698 notify_buddy_status_update((GaimBuddy *)l->data, presence,
699 old_status, new_status);
700 }
701
702 /*
703 * TODO: Maybe we should do this here?
704 * GaimLog *log = gaim_account_get_log(account);
705 * char *tmp = g_strdup_printf(_("%s signed on"), alias);
706 * gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp);
707 * g_free(tmp);
708 */
709 }
710 }
711
712 static void
713 status_has_changed(GaimStatus *status)
714 {
715 GaimPresence *presence;
716 GaimStatus *old_status;
717
718 presence = gaim_status_get_presence(status);
719 old_status = gaim_presence_get_active_status(presence);
720
721 /*
722 * If this status is exclusive, then we must be setting it to "active."
723 * Since we are setting it to active, we want to set the currently
724 * active status to "inactive."
725 */
726 if (gaim_status_is_exclusive(status))
727 {
728 const GList *l;
729
730 for (l = gaim_presence_get_statuses(presence); l != NULL; l = l->next)
731 {
732 GaimStatus *temp_status = l->data;
733
734 if (temp_status == status)
735 continue;
736
737 if (gaim_status_is_independent(temp_status))
738 continue;
739
740 if (gaim_status_is_active(temp_status))
741 {
742 /*
743 * Since we don't want infinite recursion, we have to set
744 * the active variable ourself instead of calling
745 * gaim_status_set_active().
746 */
747 temp_status->active = FALSE;
748
749 notify_status_update(presence, old_status, temp_status);
750
751 break;
752 }
753 }
754 }
755
756 notify_status_update(presence, old_status, status);
757 }
758
759 void
760 gaim_status_set_active(GaimStatus *status, gboolean active)
761 {
762 if (!active && gaim_status_is_exclusive(status))
763 {
764 gaim_debug_error("status",
765 "Cannot deactivate an exclusive status (%s).\n",
766 gaim_status_get_id(status));
767 return;
768 }
769
770 g_return_if_fail(status != NULL);
771
772 if (status->active == active)
773 return;
774
775 status->active = active;
776
777 status_has_changed(status);
778 }
779
780 void
781 gaim_status_set_active_with_attrs(GaimStatus *status, gboolean active, va_list args)
782 {
783 gboolean changed = FALSE;
784 const gchar *id;
785
786 if (!active && gaim_status_is_exclusive(status))
787 {
788 gaim_debug_error("status",
789 "Cannot deactivate an exclusive status (%s).\n",
790 gaim_status_get_id(status));
791 return;
792 }
793
794 g_return_if_fail(status != NULL);
795
796 if (status->active != active)
797 changed = TRUE;
798
799 status->active = active;
800
801 /* Set any attributes */
802 while ((id = va_arg(args, const char *)) != NULL)
803 {
804 GaimValue *value;
805 value = gaim_status_get_attr_value(status, id);
806 if (value->type == GAIM_TYPE_STRING)
807 {
808 const gchar *string_data = va_arg(args, const char *);
809 if (((string_data == NULL) && (value->data.string_data == NULL)) ||
810 ((string_data != NULL) && (value->data.string_data != NULL) &&
811 !strcmp(string_data, value->data.string_data)))
812 {
813 continue;
814 }
815 gaim_status_set_attr_string(status, id, string_data);
816 changed = TRUE;
817 }
818 else if (value->type == GAIM_TYPE_INT)
819 {
820 int int_data = va_arg(args, int);
821 if (int_data == value->data.int_data)
822 continue;
823 gaim_status_set_attr_int(status, id, int_data);
824 changed = TRUE;
825 }
826 else if (value->type == GAIM_TYPE_BOOLEAN)
827 {
828 gboolean boolean_data = va_arg(args, gboolean);
829 if (boolean_data == value->data.boolean_data)
830 continue;
831 gaim_status_set_attr_int(status, id, boolean_data);
832 changed = TRUE;
833 }
834 else
835 {
836 /* We don't know what the data is--skip over it */
837 va_arg(args, void *);
838 }
839 }
840
841 if (!changed)
842 return;
843
844 status_has_changed(status);
845 }
846
847 void
848 gaim_status_set_attr_boolean(GaimStatus *status, const char *id,
849 gboolean value)
850 {
851 GaimStatusType *status_type;
852 GaimValue *attr_value;
853
854 g_return_if_fail(status != NULL);
855 g_return_if_fail(id != NULL);
856
857 status_type = gaim_status_get_type(status);
858
859 /* Make sure this attribute exists and is the correct type. */
860 attr_value = gaim_status_get_attr_value(status, id);
861 g_return_if_fail(attr_value != NULL);
862 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_BOOLEAN);
863
864 gaim_value_set_boolean(attr_value, value);
865 }
866
867 void
868 gaim_status_set_attr_int(GaimStatus *status, const char *id, int value)
869 {
870 GaimStatusType *status_type;
871 GaimValue *attr_value;
872
873 g_return_if_fail(status != NULL);
874 g_return_if_fail(id != NULL);
875
876 status_type = gaim_status_get_type(status);
877
878 /* Make sure this attribute exists and is the correct type. */
879 attr_value = gaim_status_get_attr_value(status, id);
880 g_return_if_fail(attr_value != NULL);
881 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_INT);
882
883 gaim_value_set_int(attr_value, value);
884 }
885
886 void
887 gaim_status_set_attr_string(GaimStatus *status, const char *id,
888 const char *value)
889 {
890 GaimStatusType *status_type;
891 GaimValue *attr_value;
892
893 g_return_if_fail(status != NULL);
894 g_return_if_fail(id != NULL);
895
896 status_type = gaim_status_get_type(status);
897
898 /* Make sure this attribute exists and is the correct type. */
899 attr_value = gaim_status_get_attr_value(status, id);
900 g_return_if_fail(attr_value != NULL);
901 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_STRING);
902
903 gaim_value_set_string(attr_value, value);
904 }
905
906 GaimStatusType *
907 gaim_status_get_type(const GaimStatus *status)
908 {
909 g_return_val_if_fail(status != NULL, NULL);
910
911 return status->type;
912 }
913
914 GaimPresence *
915 gaim_status_get_presence(const GaimStatus *status)
916 {
917 g_return_val_if_fail(status != NULL, NULL);
918
919 return status->presence;
920 }
921
922 const char *
923 gaim_status_get_id(const GaimStatus *status)
924 {
925 g_return_val_if_fail(status != NULL, NULL);
926
927 return gaim_status_type_get_id(gaim_status_get_type(status));
928 }
929
930 const char *
931 gaim_status_get_name(const GaimStatus *status)
932 {
933 g_return_val_if_fail(status != NULL, NULL);
934
935 return gaim_status_type_get_name(gaim_status_get_type(status));
936 }
937
938 gboolean
939 gaim_status_is_independent(const GaimStatus *status)
940 {
941 g_return_val_if_fail(status != NULL, FALSE);
942
943 return gaim_status_type_is_independent(gaim_status_get_type(status));
944 }
945
946 gboolean
947 gaim_status_is_exclusive(const GaimStatus *status)
948 {
949 g_return_val_if_fail(status != NULL, FALSE);
950
951 return gaim_status_type_is_exclusive(gaim_status_get_type(status));
952 }
953
954 gboolean
955 gaim_status_is_available(const GaimStatus *status)
956 {
957 g_return_val_if_fail(status != NULL, FALSE);
958
959 return gaim_status_type_is_available(gaim_status_get_type(status));
960 }
961
962 gboolean
963 gaim_status_is_active(const GaimStatus *status)
964 {
965 g_return_val_if_fail(status != NULL, FALSE);
966
967 return status->active;
968 }
969
970 gboolean
971 gaim_status_is_online(const GaimStatus *status)
972 {
973 GaimStatusPrimitive primitive;
974
975 g_return_val_if_fail( status != NULL, FALSE);
976
977 primitive = gaim_status_type_get_primitive(gaim_status_get_type(status));
978
979 return (primitive != GAIM_STATUS_UNSET &&
980 primitive != GAIM_STATUS_OFFLINE);
981 }
982
983 GaimValue *
984 gaim_status_get_attr_value(const GaimStatus *status, const char *id)
985 {
986 GaimStatusType *status_type;
987 GaimStatusAttr *attr;
988
989 g_return_val_if_fail(status != NULL, NULL);
990 g_return_val_if_fail(id != NULL, NULL);
991
992 status_type = gaim_status_get_type(status);
993
994 /* Make sure this attribute exists. */
995 attr = gaim_status_type_get_attr(status_type, id);
996 g_return_val_if_fail(attr != NULL, NULL);
997
998 return (GaimValue *)g_hash_table_lookup(status->attr_values, id);
999 }
1000
1001 gboolean
1002 gaim_status_get_attr_boolean(const GaimStatus *status, const char *id)
1003 {
1004 const GaimValue *value;
1005
1006 g_return_val_if_fail(status != NULL, FALSE);
1007 g_return_val_if_fail(id != NULL, FALSE);
1008
1009 if ((value = gaim_status_get_attr_value(status, id)) == NULL)
1010 return FALSE;
1011
1012 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_BOOLEAN, FALSE);
1013
1014 return gaim_value_get_boolean(value);
1015 }
1016
1017 int
1018 gaim_status_get_attr_int(const GaimStatus *status, const char *id)
1019 {
1020 const GaimValue *value;
1021
1022 g_return_val_if_fail(status != NULL, FALSE);
1023 g_return_val_if_fail(id != NULL, FALSE);
1024
1025 if ((value = gaim_status_get_attr_value(status, id)) == NULL)
1026 return FALSE;
1027
1028 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_INT, 0);
1029
1030 return gaim_value_get_int(value);
1031 }
1032
1033 const char *
1034 gaim_status_get_attr_string(const GaimStatus *status, const char *id)
1035 {
1036 const GaimValue *value;
1037
1038 g_return_val_if_fail(status != NULL, FALSE);
1039 g_return_val_if_fail(id != NULL, FALSE);
1040
1041 if ((value = gaim_status_get_attr_value(status, id)) == NULL)
1042 return FALSE;
1043
1044 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_STRING, NULL);
1045
1046 return gaim_value_get_string(value);
1047 }
1048
1049 gint
1050 gaim_status_compare(const GaimStatus *status1, const GaimStatus *status2)
1051 {
1052 GaimStatusType *type1, *type2;
1053 int score1 = 0, score2 = 0;
1054
1055 if ((status1 == NULL && status2 == NULL) ||
1056 (status1 == status2))
1057 {
1058 return 0;
1059 }
1060 else if (status1 == NULL)
1061 return 1;
1062 else if (status2 == NULL)
1063 return -1;
1064
1065 type1 = gaim_status_get_type(status1);
1066 type2 = gaim_status_get_type(status2);
1067
1068 if (gaim_status_is_active(status1))
1069 score1 = primitive_scores[gaim_status_type_get_primitive(type1)];
1070
1071 if (gaim_status_is_active(status2))
1072 score2 = primitive_scores[gaim_status_type_get_primitive(type2)];
1073
1074 if (score1 > score2)
1075 return -1;
1076 else if (score1 < score2)
1077 return 1;
1078
1079 return 0;
1080 }
1081
1082
1083 /**************************************************************************
1084 * GaimPresence API
1085 **************************************************************************/
1086 GaimPresence *
1087 gaim_presence_new(GaimPresenceContext context)
1088 {
1089 GaimPresence *presence;
1090
1091 g_return_val_if_fail(context != GAIM_PRESENCE_CONTEXT_UNSET, NULL);
1092
1093 presence = g_new0(GaimPresence, 1);
1094
1095 presence->context = context;
1096
1097 presence->status_table =
1098 g_hash_table_new_full(g_str_hash, g_str_equal,
1099 g_free, (GFreeFunc)gaim_status_destroy);
1100
1101 return presence;
1102 }
1103
1104 GaimPresence *
1105 gaim_presence_new_for_account(GaimAccount *account)
1106 {
1107 GaimPresence *presence = NULL;
1108 g_return_val_if_fail(account != NULL, NULL);
1109
1110 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_ACCOUNT);
1111 presence->u.account = account;
1112 presence->statuses = gaim_prpl_get_statuses(account, presence);
1113
1114 return presence;
1115 }
1116
1117 GaimPresence *
1118 gaim_presence_new_for_conv(GaimConversation *conv)
1119 {
1120 GaimPresence *presence;
1121
1122 g_return_val_if_fail(conv != NULL, NULL);
1123
1124 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_CONV);
1125 presence->u.chat.conv = conv;
1126 /* presence->statuses = gaim_prpl_get_statuses(conv->account, presence); ? */
1127
1128 return presence;
1129 }
1130
1131 GaimPresence *
1132 gaim_presence_new_for_buddy(GaimBuddy *buddy)
1133 {
1134 GaimPresence *presence;
1135 GaimStatusBuddyKey *key;
1136 GaimAccount *account;
1137
1138 g_return_val_if_fail(buddy != NULL, NULL);
1139 account = buddy->account;
1140
1141 account = buddy->account;
1142
1143 key = g_new0(GaimStatusBuddyKey, 1);
1144 key->account = buddy->account;
1145 key->name = g_strdup(buddy->name);
1146
1147 presence = g_hash_table_lookup(buddy_presences, key);
1148 if (presence == NULL)
1149 {
1150 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_BUDDY);
1151
1152 presence->u.buddy.name = g_strdup(buddy->name);
1153 presence->u.buddy.account = buddy->account;
1154 presence->statuses = gaim_prpl_get_statuses(buddy->account, presence);
1155
1156 g_hash_table_insert(buddy_presences, key, presence);
1157 }
1158 else
1159 {
1160 g_free(key->name);
1161 g_free(key);
1162 }
1163
1164 presence->u.buddy.ref_count++;
1165 presence->u.buddy.buddies = g_list_append(presence->u.buddy.buddies,
1166 buddy);
1167
1168 return presence;
1169 }
1170
1171 void
1172 gaim_presence_destroy(GaimPresence *presence)
1173 {
1174 g_return_if_fail(presence != NULL);
1175
1176 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY)
1177 {
1178 GaimStatusBuddyKey key;
1179
1180 presence->u.buddy.ref_count--;
1181
1182 if(presence->u.buddy.ref_count != 0)
1183 return;
1184
1185 key.account = presence->u.buddy.account;
1186 key.name = presence->u.buddy.name;
1187
1188 g_hash_table_remove(buddy_presences, &key);
1189
1190 if (presence->u.buddy.name != NULL)
1191 g_free(presence->u.buddy.name);
1192 }
1193 else if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_CONV)
1194 {
1195 if (presence->u.chat.user != NULL)
1196 g_free(presence->u.chat.user);
1197 }
1198
1199 if (presence->statuses != NULL)
1200 g_list_free(presence->statuses);
1201
1202 g_hash_table_destroy(presence->status_table);
1203
1204 g_free(presence);
1205 }
1206
1207 void
1208 gaim_presence_remove_buddy(GaimPresence *presence, GaimBuddy *buddy)
1209 {
1210 g_return_if_fail(presence != NULL);
1211 g_return_if_fail(buddy != NULL);
1212 g_return_if_fail(gaim_presence_get_context(presence) ==
1213 GAIM_PRESENCE_CONTEXT_BUDDY);
1214
1215 if (g_list_find(presence->u.buddy.buddies, buddy) != NULL)
1216 {
1217 presence->u.buddy.buddies = g_list_remove(presence->u.buddy.buddies,
1218 buddy);
1219 presence->u.buddy.ref_count--;
1220 }
1221 }
1222
1223 void
1224 gaim_presence_add_status(GaimPresence *presence, GaimStatus *status)
1225 {
1226 g_return_if_fail(presence != NULL);
1227 g_return_if_fail(status != NULL);
1228
1229 presence->statuses = g_list_append(presence->statuses, status);
1230
1231 g_hash_table_insert(presence->status_table,
1232 g_strdup(gaim_status_get_id(status)), status);
1233 }
1234
1235 void
1236 gaim_presence_add_presence(GaimPresence *presence, const GList *source_list)
1237 {
1238 const GList *l;
1239
1240 g_return_if_fail(presence != NULL);
1241 g_return_if_fail(source_list != NULL);
1242
1243 for (l = source_list; l != NULL; l = l->next)
1244 gaim_presence_add_status(presence, (GaimStatus *)l->data);
1245 }
1246
1200 void 1247 void
1201 gaim_presence_set_status_active(GaimPresence *presence, const char *status_id, 1248 gaim_presence_set_status_active(GaimPresence *presence, const char *status_id,
1202 gboolean active) 1249 gboolean active)
1203 { 1250 {
1204 GaimStatus *status; 1251 GaimStatus *status;
1207 g_return_if_fail(status_id != NULL); 1254 g_return_if_fail(status_id != NULL);
1208 1255
1209 status = gaim_presence_get_status(presence, status_id); 1256 status = gaim_presence_get_status(presence, status_id);
1210 1257
1211 g_return_if_fail(status != NULL); 1258 g_return_if_fail(status != NULL);
1259 /* TODO: Should we do the following? */
1260 /* g_return_if_fail(active == status->active); */
1212 1261
1213 if (gaim_status_is_exclusive(status)) 1262 if (gaim_status_is_exclusive(status))
1214 { 1263 {
1215 if (!active) 1264 if (!active)
1216 { 1265 {
1654 { 1703 {
1655 return saved_statuses; 1704 return saved_statuses;
1656 } 1705 }
1657 1706
1658 GaimStatusSaved * 1707 GaimStatusSaved *
1659 gaim_statuses_find_saved(const char *name) 1708 gaim_statuses_find_saved(const char *title)
1660 { 1709 {
1661 GList *l; 1710 GList *l;
1662 GaimStatusSaved *status; 1711 GaimStatusSaved *status;
1663 1712
1664 for (l = saved_statuses; l != NULL; l = g_list_next(l)) 1713 for (l = saved_statuses; l != NULL; l = g_list_next(l))
1665 { 1714 {
1666 status = (GaimStatusSaved *)l->data; 1715 status = (GaimStatusSaved *)l->data;
1667 if (!strcmp(status->name, name)) 1716 if (!strcmp(status->title, title))
1668 return status; 1717 return status;
1669 } 1718 }
1670 1719
1671 return NULL; 1720 return NULL;
1672 } 1721 }
1673 1722
1674 const char * 1723 const char *
1675 gaim_statuses_saved_get_name(const GaimStatusSaved *saved_status) 1724 gaim_statuses_saved_get_title(const GaimStatusSaved *saved_status)
1676 { 1725 {
1677 return saved_status->name; 1726 return saved_status->title;
1678 } 1727 }
1679 1728
1680 const GaimStatusType * 1729 GaimStatusPrimitive
1681 gaim_statuses_saved_get_type(const GaimStatusSaved *saved_status) 1730 gaim_statuses_saved_get_type(const GaimStatusSaved *saved_status)
1682 { 1731 {
1683 return saved_status->type; 1732 return saved_status->type;
1684 } 1733 }
1685 1734
1749 1798
1750 buddy_presences = NULL; 1799 buddy_presences = NULL;
1751 } 1800 }
1752 } 1801 }
1753 1802
1754 void 1803 static GaimStatusSavedSub *
1755 gaim_statuses_sync(void) 1804 gaim_statuses_read_parse_substatus(xmlnode *substatus)
1756 { 1805 {
1757 /* TODO: Write me, baby. */ 1806 GaimStatusSavedSub *ret;
1807 xmlnode *node;
1808 const char *tmp;
1809
1810 ret = g_new0(GaimStatusSavedSub, 1);
1811
1812 /* Read the account */
1813 node = xmlnode_get_child(substatus, "account");
1814 if (node != NULL)
1815 {
1816 const char *acct_name;
1817 const char *protocol;
1818 acct_name = xmlnode_get_data(node);
1819 protocol = xmlnode_get_attrib(node, "protocol");
1820 if ((acct_name != NULL) && (protocol != NULL))
1821 ret->account = gaim_accounts_find(acct_name, protocol);
1822 }
1823
1824 if (ret->account == NULL)
1825 {
1826 g_free(ret);
1827 return NULL;
1828 }
1829
1830 /* Read the state */
1831 node = xmlnode_get_child(substatus, "state");
1832 if (node != NULL)
1833 tmp = xmlnode_get_data(node);
1834 if (tmp != NULL)
1835 ret->type = gaim_status_type_find_with_id(ret->account->status_types,
1836 tmp);
1837
1838 /* Read the message */
1839 node = xmlnode_get_child(substatus, "message");
1840 if (node != NULL)
1841 tmp = xmlnode_get_data(node);
1842 if (tmp != NULL)
1843 ret->message = g_strdup(tmp);
1844
1845 return ret;
1758 } 1846 }
1759 1847
1760 /** 1848 /**
1761 * Parse a saved status and add it to the saved_statuses linked list. 1849 * Parse a saved status and add it to the saved_statuses linked list.
1762 * 1850 *
1765 * <state>away</state> 1853 * <state>away</state>
1766 * <message>I like the way that they walk 1854 * <message>I like the way that they walk
1767 * And it's chill to hear them talk 1855 * And it's chill to hear them talk
1768 * And I can always make them smile 1856 * And I can always make them smile
1769 * From White Castle to the Nile</message> 1857 * From White Castle to the Nile</message>
1858 * <substatus>
1859 * <account protocol='prpl-oscar'>markdoliner</account>
1860 * <state>available</state>
1861 * <message>The ladies man is here to answer your queries.</message>
1862 * </substatus>
1863 * <substatus>
1864 * <account protocol='prpl-oscar'>giantgraypanda</account>
1865 * <state>away</state>
1866 * <message>A.C. ain't in charge no more.</message>
1867 * </substatus>
1770 * </status> 1868 * </status>
1771 * 1869 *
1772 * I know. Moving, huh? 1870 * I know. Moving, huh?
1773 */ 1871 */
1774 static void 1872 static GaimStatusSaved *
1775 gaim_statuses_read_parse_status(xmlnode *status) 1873 gaim_statuses_read_parse_status(xmlnode *status)
1776 { 1874 {
1875 GaimStatusSaved *ret;
1777 xmlnode *node; 1876 xmlnode *node;
1778 const char *name, *state, *message; 1877 const char *tmp;
1779 GaimStatusSaved *new;
1780 int i; 1878 int i;
1781 1879
1782 name = xmlnode_get_attrib(status, "name"); 1880 ret = g_new0(GaimStatusSaved, 1);
1783 if (name == NULL) 1881
1784 name = "No Title"; 1882 /* Read the title */
1785 1883 tmp = xmlnode_get_attrib(status, "name");
1884 if (tmp == NULL)
1885 tmp = "No Title";
1886 /* Ensure the title is unique */
1887 ret->title = g_strdup(tmp);
1888 i = 2;
1889 while (gaim_statuses_find_saved(ret->title) != NULL)
1890 {
1891 g_free(ret->title);
1892 ret->title = g_strdup_printf("%s %d", tmp, i);
1893 i++;
1894 }
1895
1896 /* Read the primitive status type */
1786 node = xmlnode_get_child(status, "state"); 1897 node = xmlnode_get_child(status, "state");
1787 if (node != NULL) { 1898 if (node != NULL)
1788 state = xmlnode_get_data(node); 1899 tmp = xmlnode_get_data(node);
1789 } 1900 if (tmp != NULL)
1790 1901 ret->type = gaim_primitive_get_type(tmp);
1902
1903 /* Read the message */
1791 node = xmlnode_get_child(status, "message"); 1904 node = xmlnode_get_child(status, "message");
1792 if (node != NULL) { 1905 if (node != NULL)
1793 message = xmlnode_get_data(node); 1906 tmp = xmlnode_get_data(node);
1794 } 1907 if (tmp != NULL)
1795 1908 ret->message = g_strdup(tmp);
1796 /* TODO: Need to read in substatuses here */ 1909
1797 1910 /* Read substatuses */
1798 new = g_new0(GaimStatusSaved, 1); 1911 for (node = xmlnode_get_child(status, "status"); node != NULL;
1799 1912 node = xmlnode_get_next_twin(node))
1800 new->name = g_strdup(name); 1913 {
1801 /* TODO: Need to set type based on "state" */ 1914 GaimStatusSavedSub *new;
1802 new->type = NULL; 1915 new = gaim_statuses_read_parse_substatus(node);
1803 if (message != NULL) 1916 if (new != NULL)
1804 new->message = g_strdup(message); 1917 ret->substatuses = g_list_append(ret->substatuses, new);
1805 1918 }
1806 /* Ensure the title is unique */ 1919
1807 i = 2; 1920 return ret;
1808 while (gaim_statuses_find_saved(new->name) != NULL) {
1809 g_free(new->name);
1810 new->name = g_strdup_printf("%s %d", name, i);
1811 i++;
1812 }
1813
1814 saved_statuses = g_list_append(saved_statuses, new);
1815 } 1921 }
1816 1922
1817 /** 1923 /**
1818 * @return TRUE on success, FALSE on failure (if the file can not 1924 * @return TRUE on success, FALSE on failure (if the file can not
1819 * be opened, or if it contains invalid XML). 1925 * be opened, or if it contains invalid XML).
1820 */ 1926 */
1821 gboolean 1927 static gboolean
1822 gaim_statuses_read(const char *filename) 1928 gaim_statuses_read(const char *filename)
1823 { 1929 {
1824 GError *error; 1930 GError *error;
1825 gchar *contents = NULL; 1931 gchar *contents = NULL;
1826 gsize length; 1932 gsize length;
1827 xmlnode *statuses, *status; 1933 xmlnode *statuses, *status;
1828 1934
1829 gaim_debug_info("status", "Reading %s\n", filename); 1935 gaim_debug_info("status", "Reading %s\n", filename);
1830 1936
1831 if (!g_file_get_contents(filename, &contents, &length, &error)) { 1937 if (!g_file_get_contents(filename, &contents, &length, &error))
1938 {
1832 gaim_debug_error("status", "Error reading statuses: %s\n", 1939 gaim_debug_error("status", "Error reading statuses: %s\n",
1833 error->message); 1940 error->message);
1834 g_error_free(error); 1941 g_error_free(error);
1835 return FALSE; 1942 return FALSE;
1836 } 1943 }
1837 1944
1838 statuses = xmlnode_from_str(contents, length); 1945 statuses = xmlnode_from_str(contents, length);
1839 1946
1840 if (statuses == NULL) { 1947 if (statuses == NULL)
1948 {
1841 FILE *backup; 1949 FILE *backup;
1842 gchar *name; 1950 gchar *name;
1843 gaim_debug_error("status", "Error parsing statuses\n"); 1951 gaim_debug_error("status", "Error parsing statuses\n");
1844 name = g_strdup_printf("%s~", filename); 1952 name = g_strdup_printf("%s~", filename);
1845 if ((backup = fopen(name, "w"))) { 1953 if ((backup = fopen(name, "w")))
1954 {
1846 fwrite(contents, length, 1, backup); 1955 fwrite(contents, length, 1, backup);
1847 fclose(backup); 1956 fclose(backup);
1848 chmod(name, S_IRUSR | S_IWUSR); 1957 chmod(name, S_IRUSR | S_IWUSR);
1849 } else { 1958 }
1959 else
1960 {
1850 gaim_debug_error("status", "Unable to write backup %s\n", name); 1961 gaim_debug_error("status", "Unable to write backup %s\n", name);
1851 } 1962 }
1852 g_free(name); 1963 g_free(name);
1853 g_free(contents); 1964 g_free(contents);
1854 return FALSE; 1965 return FALSE;
1855 } 1966 }
1856 1967
1857 g_free(contents); 1968 g_free(contents);
1858 1969
1859 for (status = xmlnode_get_child(statuses, "status"); status != NULL; 1970 for (status = xmlnode_get_child(statuses, "status"); status != NULL;
1860 status = xmlnode_get_next_twin(status)) { 1971 status = xmlnode_get_next_twin(status))
1861 gaim_statuses_read_parse_status(status); 1972 {
1973 GaimStatusSaved *new;
1974 new = gaim_statuses_read_parse_status(status);
1975 saved_statuses = g_list_append(saved_statuses, new);
1862 } 1976 }
1863 1977
1864 gaim_debug_info("status", "Finished reading statuses\n"); 1978 gaim_debug_info("status", "Finished reading statuses\n");
1865 1979
1866 xmlnode_free(statuses); 1980 xmlnode_free(statuses);
1878 if (user_dir == NULL) 1992 if (user_dir == NULL)
1879 return; 1993 return;
1880 1994
1881 filename = g_build_filename(user_dir, "status.xml", NULL); 1995 filename = g_build_filename(user_dir, "status.xml", NULL);
1882 1996
1883 if (g_file_test(filename, G_FILE_TEST_EXISTS)) { 1997 if (g_file_test(filename, G_FILE_TEST_EXISTS))
1884 if (!gaim_statuses_read(filename)) { 1998 {
1999 if (!gaim_statuses_read(filename))
2000 {
1885 msg = g_strdup_printf(_("An error was encountered parsing the " 2001 msg = g_strdup_printf(_("An error was encountered parsing the "
1886 "file containing your saved statuses (%s). They " 2002 "file containing your saved statuses (%s). They "
1887 "have not been loaded, and the old file has been " 2003 "have not been loaded, and the old file has been "
1888 "renamed to status.xml~."), filename); 2004 "renamed to status.xml~."), filename);
1889 gaim_notify_error(NULL, NULL, _("Saved Statuses Error"), msg); 2005 gaim_notify_error(NULL, NULL, _("Saved Statuses Error"), msg);
1891 } 2007 }
1892 } 2008 }
1893 2009
1894 g_free(filename); 2010 g_free(filename);
1895 } 2011 }
2012
2013 void
2014 gaim_statuses_sync(void)
2015 {
2016 /* TODO: Write me, baby. */
2017 }