# HG changeset patch # User Mark Doliner # Date 1102564519 0 # Node ID 682201b69107eedf27e4e0eae89d35e59415539f # Parent 114d3ac8ff5a8d4da89cf377fe98543ce76d374a [gaim-migrate @ 11545] * Preliminary reading of status.xml using xmlnode.[h|c] * I made a few changes the blist.xml readering code that I think makes it cleaner * "gaim_statuses_find_saved" makes more sense to me than "gaim_statuses_find_stored" * struct GaimStatus isn't really supposed to be used for keeping the saved statuses, is it? I don't see how that would work. It seems to make more sense to have a separate data structure for it. Maybe I'm not seeing things clearly. committer: Tailor Script diff -r 114d3ac8ff5a -r 682201b69107 src/blist.c --- a/src/blist.c Thu Dec 09 03:10:30 2004 +0000 +++ b/src/blist.c Thu Dec 09 03:55:19 2004 +0000 @@ -1956,43 +1956,40 @@ gsize length; xmlnode *gaim, *blist, *privacy; - gaim_debug(GAIM_DEBUG_INFO, "blist import", - "Reading %s\n", filename); + gaim_debug_info("blist", "Reading %s\n", filename); + if (!g_file_get_contents(filename, &contents, &length, &error)) { - gaim_debug(GAIM_DEBUG_ERROR, "blist import", - "Error reading blist: %s\n", error->message); + gaim_debug_error("blist", "Error reading blist.xml: %s\n", + error->message); g_error_free(error); return FALSE; } gaim = xmlnode_from_str(contents, length); - - if (!gaim) { + + if (gaim == NULL) { FILE *backup; char *name; - gaim_debug(GAIM_DEBUG_ERROR, "blist import", "Error parsing %s\n", - filename); + gaim_debug_error("blist", "Error parsing blist.xml\n"); name = g_build_filename(gaim_user_dir(), "blist.xml~", NULL); - if ((backup = fopen(name, "w"))) { fwrite(contents, length, 1, backup); fclose(backup); chmod(name, S_IRUSR | S_IWUSR); } else { - gaim_debug(GAIM_DEBUG_ERROR, "blist load", "Unable to write backup %s\n", - name); + gaim_debug_error("blist", "Unable to write backup %s\n", name); } g_free(name); g_free(contents); return FALSE; } - + g_free(contents); - + blist = xmlnode_get_child(gaim, "blist"); if (blist) { xmlnode *groupnode; - for (groupnode = xmlnode_get_child(blist, "group"); groupnode; + for (groupnode = xmlnode_get_child(blist, "group"); groupnode != NULL; groupnode = xmlnode_get_next_twin(groupnode)) { parse_group(groupnode); } @@ -2039,31 +2036,32 @@ } } - gaim_debug(GAIM_DEBUG_INFO, "blist import", "Finished reading %s\n", - filename); + gaim_debug_info("blist", "Finished reading blist.xml\n"); xmlnode_free(gaim); + return TRUE; } void gaim_blist_load() { const char *user_dir = gaim_user_dir(); - char *filename; - char *msg; + gchar *filename; + gchar *msg; blist_safe_to_write = TRUE; - if (!user_dir) + if (user_dir == NULL) return; filename = g_build_filename(user_dir, "blist.xml", NULL); if (g_file_test(filename, G_FILE_TEST_EXISTS)) { if (!gaim_blist_read(filename)) { - msg = g_strdup_printf(_("An error was encountered parsing your " - "buddy list. It has not been loaded, " - "and the old file has moved to blist.xml~.")); + msg = g_strdup_printf(_("An error was encountered parsing the " + "file containing your buddy list (%s). It has not " + "been loaded, and the old file has been renamed " + "to blist.xml~."), filename); gaim_notify_error(NULL, NULL, _("Buddy List Error"), msg); g_free(msg); } diff -r 114d3ac8ff5a -r 682201b69107 src/gtkstatus.c --- a/src/gtkstatus.c Thu Dec 09 03:10:30 2004 +0000 +++ b/src/gtkstatus.c Thu Dec 09 03:55:19 2004 +0000 @@ -421,20 +421,19 @@ populate_saved_status_list(StatusWindow *dialog) { GtkTreeIter iter; + const GList *saved_statuses; + GaimStatusSaved *saved_status; gtk_list_store_clear(dialog->model); - gtk_list_store_append(dialog->model, &iter); - gtk_list_store_set(dialog->model, &iter, 0, "Dinner time!", -1); - - gtk_list_store_append(dialog->model, &iter); - gtk_list_store_set(dialog->model, &iter, 0, "I am not here because I am cow tipping with Jimmy.", -1); - - gtk_list_store_append(dialog->model, &iter); - gtk_list_store_set(dialog->model, &iter, 0, "Picking up the kids from the zoo.", -1); - - gtk_list_store_append(dialog->model, &iter); - gtk_list_store_set(dialog->model, &iter, 0, "In a meeting discussing what to do when King Kong gets here.", -1); + for (saved_statuses = gaim_statuses_get_saved(); saved_statuses != NULL; + saved_statuses = g_list_next(saved_statuses)) + { + saved_status = (GaimStatusSaved *)saved_statuses->data; + gtk_list_store_append(dialog->model, &iter); + gtk_list_store_set(dialog->model, &iter, 0, + gaim_statuses_saved_get_name(saved_status), -1); + } } static GtkWidget * diff -r 114d3ac8ff5a -r 682201b69107 src/status.c --- a/src/status.c Thu Dec 09 03:10:30 2004 +0000 +++ b/src/status.c Thu Dec 09 03:55:19 2004 +0000 @@ -26,9 +26,11 @@ #include "blist.h" #include "debug.h" +#include "notify.h" #include "prefs.h" #include "status.h" #include "util.h" +#include "xmlnode.h" /** * A type of status. @@ -120,30 +122,32 @@ char *name; } GaimStatusBuddyKey; - -#if 0 -static GList *stored_statuses = NULL; - -/* - * XXX This stuff should be removed in a few versions. It stores the - * old v1 status stuff so we can write it later. We don't write out - * the new status stuff, though. These should all die soon, as the - * old status.xml was created before the new status system's design - * was created. +/** + * The information of a snap-shot of the statuses of all + * your accounts. Basically these are your saved away messages. + * There is an overall status and message that applies to + * all your accounts, and then each individual account can + * optionally have a different custom status and message. * - * -- ChipX86 + * The changes to status.xml caused by the new status API + * are fully backward compatible. The new status API just + * adds the optional sub-statuses to the XML file. */ -typedef struct +struct _GaimStatusSaved { char *name; - char *state; + GaimStatusType *type; char *message; -} GaimStatusV1Info; + GList *individual; /**< A list of GaimStatusSavedSub's. */ +}; -static GList *v1_statuses = NULL; -#endif - +struct _GaimStatusSavedSub +{ + GaimAccount *account; + GaimStatusType *type; + char *message; +}; static int primitive_scores[] = { @@ -160,6 +164,7 @@ }; static GHashTable *buddy_presences = NULL; +static GList *saved_statuses = NULL; #define SCORE_IDLE 5 #define SCORE_IDLE_TIME 6 @@ -1645,15 +1650,21 @@ } const GList * -gaim_statuses_get_stored(void) +gaim_statuses_get_saved(void) +{ + return saved_statuses; +} + +GaimStatusSaved * +gaim_statuses_find_saved(const GaimStatusType *status_type, const char *id) { return NULL; } -GaimStatus * -gaim_statuses_find_stored(const GaimStatusType *status_type, const char *id) +const char * +gaim_statuses_saved_get_name(const GaimStatusSaved *saved_status) { - return NULL; + return saved_status->name; } void * @@ -1723,7 +1734,132 @@ { } +/** + * Parse a saved status and add it to the saved_statuses linked list. + * + * Here's an example of the XML for a saved status: + * + * away + * I like the way that they walk + * And it's chill to hear them talk + * And I can always make them smile + * From White Castle to the Nile + * + * + * I know. Moving, huh? + * + * TODO: Make sure the name is unique before adding it to the linked list. + */ +static void +gaim_statuses_read_parse_status(xmlnode *status) +{ + xmlnode *node; + const char *name, *state, *message; + GaimStatusSaved *new; + + name = xmlnode_get_attrib(status, "name"); + if (name == NULL) + name = "TODO: Make up something unique"; + + node = xmlnode_get_child(status, "state"); + if (node != NULL) { + state = xmlnode_get_data(node); + } + + node = xmlnode_get_child(status, "message"); + if (node != NULL) { + message = xmlnode_get_data(node); + } + + /* TODO: Need to read in substatuses here */ + + new = g_new0(GaimStatusSaved, 1); + + new->name = g_strdup(name); + /* TODO: Need to set type based on "state" */ + new->type = NULL; + if (message != NULL) + new->message = g_strdup(message); + + saved_statuses = g_list_append(saved_statuses, new); +} + +/** + * @return TRUE on success, FALSE on failure (if the file can not + * be opened, or if it contains invalid XML). + */ +gboolean +gaim_statuses_read(const char *filename) +{ + GError *error; + gchar *contents = NULL; + gsize length; + xmlnode *statuses, *status; + + gaim_debug_info("status", "Reading %s\n", filename); + + if (!g_file_get_contents(filename, &contents, &length, &error)) { + gaim_debug_error("status", "Error reading status.xml: %s\n", + error->message); + g_error_free(error); + return FALSE; + } + + statuses = xmlnode_from_str(contents, length); + + if (statuses == NULL) { + FILE *backup; + gchar *name; + gaim_debug_error("status", "Error parsing status.xml\n"); + name = g_build_filename(gaim_user_dir(), "status.xml~", NULL); + if ((backup = fopen(name, "w"))) { + fwrite(contents, length, 1, backup); + fclose(backup); + chmod(name, S_IRUSR | S_IWUSR); + } else { + gaim_debug_error("status", "Unable to write backup %s\n", name); + } + g_free(name); + g_free(contents); + return FALSE; + } + + g_free(contents); + + for (status = xmlnode_get_child(statuses, "status"); status != NULL; + status = xmlnode_get_next_twin(status)) { + gaim_statuses_read_parse_status(status); + } + + gaim_debug_info("status", "Finished reading status.xml\n"); + + xmlnode_free(statuses); + + return TRUE; +} + void gaim_statuses_load(void) { + const char *user_dir = gaim_user_dir(); + gchar *filename; + gchar *msg; + + if (user_dir == NULL) + return; + + filename = g_build_filename(user_dir, "status.xml", NULL); + + if (g_file_test(filename, G_FILE_TEST_EXISTS)) { + if (!gaim_statuses_read(filename)) { + msg = g_strdup_printf(_("An error was encountered parsing the " + "file containing your saved statuses (%s). They " + "have not been loaded, and the old file has been " + "renamed to status.xml~."), filename); + gaim_notify_error(NULL, NULL, _("Saved Statuses Error"), msg); + g_free(msg); + } + } + + g_free(filename); } diff -r 114d3ac8ff5a -r 682201b69107 src/status.h --- a/src/status.h Thu Dec 09 03:10:30 2004 +0000 +++ b/src/status.h Thu Dec 09 03:55:19 2004 +0000 @@ -25,10 +25,12 @@ #ifndef _GAIM_STATUS_H_ #define _GAIM_STATUS_H_ -typedef struct _GaimStatusType GaimStatusType; -typedef struct _GaimStatusAttr GaimStatusAttr; -typedef struct _GaimPresence GaimPresence; -typedef struct _GaimStatus GaimStatus; +typedef struct _GaimStatusType GaimStatusType; +typedef struct _GaimStatusAttr GaimStatusAttr; +typedef struct _GaimPresence GaimPresence; +typedef struct _GaimStatus GaimStatus; +typedef struct _GaimStatusSavedSub GaimStatusSavedSub; +typedef struct _GaimStatusSaved GaimStatusSaved; /** * A context for a presence. @@ -879,29 +881,37 @@ /*@}*/ - /**************************************************************************/ /** @name Status subsystem */ /**************************************************************************/ /*@{*/ /** - * Returns all stored statuses. + * Returns all saved statuses. * - * @return A list of stored statuses. + * @return A list of saved statuses. */ -const GList *gaim_statuses_get_stored(void); +const GList *gaim_statuses_get_saved(void); /** - * Finds a stored status with the specified status type and primary ID. + * Finds a saved status with the specified status type and primary ID. * * @param status_type The status type of the status. * @param id The primary attribute ID. * - * @return The stored status if found, or NULL. + * @return The saved status if found, or NULL. */ -GaimStatus *gaim_statuses_find_stored(const GaimStatusType *status_type, - const char *id); +GaimStatusSaved *gaim_statuses_find_saved(const GaimStatusType *status_type, + const char *id); + +/** + * Return the name of a given saved status. + * + * @param saved_status The saved status. + * + * @return The name. + */ +const char *gaim_statuses_saved_get_name(const GaimStatusSaved *saved_status); /** * Get the handle for the status subsystem. diff -r 114d3ac8ff5a -r 682201b69107 src/xmlnode.h --- a/src/xmlnode.h Thu Dec 09 03:10:30 2004 +0000 +++ b/src/xmlnode.h Thu Dec 09 03:55:19 2004 +0000 @@ -173,7 +173,9 @@ char *xmlnode_to_formatted_str(xmlnode *node, int *len); /** - * Creates a node from a string of xml. + * Creates a node from a string of XML. Calling this on the + * root node of an XML document will parse the entire document + * into a tree of nodes, and return the xmlnode of the root. * * @param str The string of xml. * @param size The size of the string.