Mercurial > pidgin.yaz
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 } |