changeset 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 4d2ecbb139a0
children 655c48791b3c
files src/blist.h src/gtkconv.c src/gtkstatus.c src/gtkutils.c src/log.h src/status.c src/status.h
diffstat 7 files changed, 246 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/src/blist.h	Sun Dec 12 18:20:17 2004 +0000
+++ b/src/blist.h	Sun Dec 12 23:57:52 2004 +0000
@@ -718,12 +718,6 @@
 
 /*@{*/
 /**
- * Force an immediate write of the buddy list.  Normally the buddy list is
- * saved automatically a few seconds after a change is made.
- */
-void gaim_blist_sync();
-
-/**
  * Parses the toc-style buddy list used in older versions of Gaim and for SSI in toc.c
  *
  * @param account  This is the account that the buddies and groups from config will get added to
@@ -738,6 +732,12 @@
 void gaim_blist_load();
 
 /**
+ * Force an immediate write of the buddy list.  Normally the buddy list is
+ * saved automatically a few seconds after a change is made.
+ */
+void gaim_blist_sync();
+
+/**
  * Requests from the user information needed to add a buddy to the
  * buddy list.
  *
--- a/src/gtkconv.c	Sun Dec 12 18:20:17 2004 +0000
+++ b/src/gtkconv.c	Sun Dec 12 23:57:52 2004 +0000
@@ -5029,9 +5029,7 @@
 
 		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf, 0);
 	} else if (flags & GAIM_MESSAGE_RAW) {
-		g_snprintf(buf, BUF_LONG, "%s", message);
-
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf, 0);
+		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, 0);
 	} else {
 		char *new_message = g_memdup(message, length);
 		char *who_escaped = (who ? g_markup_escape_text(who, strlen(who)) : g_strdup(""));
--- a/src/gtkstatus.c	Sun Dec 12 18:20:17 2004 +0000
+++ b/src/gtkstatus.c	Sun Dec 12 23:57:52 2004 +0000
@@ -432,7 +432,7 @@
 		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);
+						   gaim_statuses_saved_get_title(saved_status), -1);
 	}
 }
 
--- a/src/gtkutils.c	Sun Dec 12 18:20:17 2004 +0000
+++ b/src/gtkutils.c	Sun Dec 12 23:57:52 2004 +0000
@@ -1507,10 +1507,11 @@
 
 			if (gc)
 				prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
+
 			if (prpl_info && prpl_info->options & OPT_PROTO_IM_IMAGE)
 				im = TRUE;
 
-			if (prpl_info && prpl_info->send_file)
+			if (prpl_info && prpl_info->can_receive_file)
 				ft = prpl_info->can_receive_file(gc, who);
 
 			if (im && ft)
--- a/src/log.h	Sun Dec 12 18:20:17 2004 +0000
+++ b/src/log.h	Sun Dec 12 23:57:52 2004 +0000
@@ -38,11 +38,11 @@
 typedef enum {
 	GAIM_LOG_IM,
 	GAIM_LOG_CHAT,
-	GAIM_LOG_SYSTEM,
+	GAIM_LOG_SYSTEM
 } GaimLogType;
 
 typedef enum {
-	GAIM_LOG_READ_NO_NEWLINE = 1,
+	GAIM_LOG_READ_NO_NEWLINE = 1
 } GaimLogReadFlags;
 
 #include "account.h"
--- a/src/status.c	Sun Dec 12 18:20:17 2004 +0000
+++ b/src/status.c	Sun Dec 12 23:57:52 2004 +0000
@@ -135,17 +135,17 @@
  */
 struct _GaimStatusSaved
 {
-	char *name;
-	GaimStatusType *type;
+	char *title;
+	GaimStatusPrimitive type;
 	char *message;
 
-	GList *individual;      /**< A list of GaimStatusSavedSub's. */
+	GList *substatuses;      /**< A list of GaimStatusSavedSub's. */
 };
 
 struct _GaimStatusSavedSub
 {
 	GaimAccount *account;
-	GaimStatusType *type;
+	const GaimStatusType *type;
 	char *message;
 };
 
@@ -169,6 +169,37 @@
 #define SCORE_IDLE      5
 #define SCORE_IDLE_TIME 6
 
+/**
+ * Elements of this array correspond to the GaimStatusPrimitive
+ * enumeration.
+ */
+static const char *primitive_names[] =
+{
+	"unset",
+	"offline",
+	"available",
+	"unavailable",
+	"hidden",
+	"away",
+	"extended_away"
+};
+
+static GaimStatusPrimitive
+gaim_primitive_get_type(const char *name)
+{
+	int i;
+
+	g_return_val_if_fail(name != NULL, GAIM_STATUS_UNSET);
+
+	for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++)
+	{
+		if (!strcmp(name, primitive_names[i]))
+			return i;
+	}
+
+	return GAIM_STATUS_UNSET;
+}
+
 /**************************************************************************
  * GaimStatusType API
  **************************************************************************/
@@ -432,6 +463,24 @@
 	return status_type->attrs;
 }
 
+const GaimStatusType *
+gaim_status_type_find_with_id(GList *status_types, const char *id)
+{
+	GaimStatusType *status_type;
+
+	g_return_val_if_fail(id != NULL, NULL);
+
+	while (status_types != NULL)
+	{
+		status_type = status_types->data;
+
+		if (!strcmp(id, status_type->id))
+			return status_type;
+	}
+
+	return NULL;
+}
+
 
 /**************************************************************************
 * GaimStatusAttr API
@@ -613,12 +662,31 @@
 	}
 	else if (context == GAIM_PRESENCE_CONTEXT_CONV)
 	{
-/* TODO */
 #if 0
 		GaimConversationUiOps *ops;
 		GaimConversation *conv;
 
 		conv = gaim_status_get_conversation(new_status);
+/*
+ * TODO: Probably need to do some of the following here?  This is copied
+ *       from some old status code that was removed.
+ *
+ *           char *tmp = g_strdup_printf(_("%s logged in."), alias);
+ *           gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL));
+ *           g_free(tmp);
+ *
+ *           char *tmp = g_strdup_printf(_("%s logged out."), alias);
+ *           gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL));
+ *           g_free(tmp); 
+ *
+ *           char *tmp = g_strdup_printf(_("%s signed off"), alias);
+ *           gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp);
+ *           g_free(tmp);
+ *
+ *           serv_got_typing_stopped(gc, name);
+ *
+ *           gaim_conversation_update(c, GAIM_CONV_UPDATE_AWAY);
+ */
 #endif
 	}
 	else if (context == GAIM_PRESENCE_CONTEXT_BUDDY)
@@ -630,6 +698,14 @@
 			notify_buddy_status_update((GaimBuddy *)l->data, presence,
 					old_status, new_status);
 		}
+
+/*
+ * TODO: Maybe we should do this here?
+ *           GaimLog *log = gaim_account_get_log(account);
+ *           char *tmp = g_strdup_printf(_("%s signed on"), alias);
+ *           gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp);
+ *           g_free(tmp);
+ */
 	}
 }
 
@@ -1168,35 +1244,6 @@
 		gaim_presence_add_status(presence, (GaimStatus *)l->data);
 }
 
-/*
- * TODO: Should we g_return_if_fail(active == status_id->active); ?
- *
- * TODO: If a buddy signed on or off, should we do any of the following?
- *       (Note: We definitely need to do some of this somewhere, I'm just 
- *        not sure if here is the correct place.)
- *
- *           char *tmp = g_strdup_printf(_("%s logged in."), alias);
- *           gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL));
- *           g_free(tmp);
- *
- *           GaimLog *log = gaim_account_get_log(account);
- *           char *tmp = g_strdup_printf(_("%s signed on"), alias);
- *           gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp);
- *           g_free(tmp);
- *
- *           char *tmp = g_strdup_printf(_("%s logged out."), alias);
- *           gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL));
- *           g_free(tmp); 
- *
- *           char *tmp = g_strdup_printf(_("%s signed off"), alias);
- *           gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp);
- *           g_free(tmp);
- *
- *           serv_got_typing_stopped(gc, name);
- *
- *           gaim_conversation_update(c, GAIM_CONV_UPDATE_AWAY);
- *
- */
 void
 gaim_presence_set_status_active(GaimPresence *presence, const char *status_id,
 		gboolean active)
@@ -1209,6 +1256,8 @@
 	status = gaim_presence_get_status(presence, status_id);
 
 	g_return_if_fail(status != NULL);
+	/* TODO: Should we do the following? */
+	/* g_return_if_fail(active == status->active); */
 
 	if (gaim_status_is_exclusive(status))
 	{
@@ -1656,7 +1705,7 @@
 }
 
 GaimStatusSaved *
-gaim_statuses_find_saved(const char *name)
+gaim_statuses_find_saved(const char *title)
 {
 	GList *l;
 	GaimStatusSaved *status;
@@ -1664,7 +1713,7 @@
 	for (l = saved_statuses; l != NULL; l = g_list_next(l))
 	{
 		status = (GaimStatusSaved *)l->data;
-		if (!strcmp(status->name, name))
+		if (!strcmp(status->title, title))
 			return status;
 	}
 
@@ -1672,12 +1721,12 @@
 }
 
 const char *
-gaim_statuses_saved_get_name(const GaimStatusSaved *saved_status)
+gaim_statuses_saved_get_title(const GaimStatusSaved *saved_status)
 {
-	return saved_status->name;
+	return saved_status->title;
 }
 
-const GaimStatusType *
+GaimStatusPrimitive
 gaim_statuses_saved_get_type(const GaimStatusSaved *saved_status)
 {
 	return saved_status->type;
@@ -1751,10 +1800,49 @@
 	}
 }
 
-void
-gaim_statuses_sync(void)
+static GaimStatusSavedSub *
+gaim_statuses_read_parse_substatus(xmlnode *substatus)
 {
-	/* TODO: Write me, baby. */
+	GaimStatusSavedSub *ret;
+	xmlnode *node;
+	const char *tmp;
+
+	ret = g_new0(GaimStatusSavedSub, 1);
+
+	/* Read the account */
+	node = xmlnode_get_child(substatus, "account");
+	if (node != NULL)
+	{
+		const char *acct_name;
+		const char *protocol;
+		acct_name = xmlnode_get_data(node);
+		protocol = xmlnode_get_attrib(node, "protocol");
+		if ((acct_name != NULL) && (protocol != NULL))
+			ret->account = gaim_accounts_find(acct_name, protocol);
+	}
+
+	if (ret->account == NULL)
+	{
+		g_free(ret);
+		return NULL;
+	}
+
+	/* Read the state */
+	node = xmlnode_get_child(substatus, "state");
+	if (node != NULL)
+		tmp = xmlnode_get_data(node);
+	if (tmp != NULL)
+		ret->type = gaim_status_type_find_with_id(ret->account->status_types,
+												  tmp);
+
+	/* Read the message */
+	node = xmlnode_get_child(substatus, "message");
+	if (node != NULL)
+		tmp = xmlnode_get_data(node);
+	if (tmp != NULL)
+		ret->message = g_strdup(tmp);
+
+	return ret;
 }
 
 /**
@@ -1767,58 +1855,76 @@
  *   And it's chill to hear them talk
  *   And I can always make them smile
  *   From White Castle to the Nile</message>
+ *       <substatus>
+ *           <account protocol='prpl-oscar'>markdoliner</account>
+ *           <state>available</state>
+ *           <message>The ladies man is here to answer your queries.</message>
+ *       </substatus>
+ *       <substatus>
+ *           <account protocol='prpl-oscar'>giantgraypanda</account>
+ *           <state>away</state>
+ *           <message>A.C. ain't in charge no more.</message>
+ *       </substatus>
  *   </status>
  *
  * I know.  Moving, huh?
  */
-static void
+static GaimStatusSaved *
 gaim_statuses_read_parse_status(xmlnode *status)
 {
+	GaimStatusSaved *ret;
 	xmlnode *node;
-	const char *name, *state, *message;
-	GaimStatusSaved *new;
+	const char *tmp;
 	int i;
 
-	name = xmlnode_get_attrib(status, "name");
-	if (name == NULL)
-		name = "No Title";
-
-	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);
-	}
+	ret = g_new0(GaimStatusSaved, 1);
 
-	/* 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);
-
+	/* Read the title */
+	tmp = xmlnode_get_attrib(status, "name");
+	if (tmp == NULL)
+		tmp = "No Title";
 	/* Ensure the title is unique */
+	ret->title = g_strdup(tmp);
 	i = 2;
-	while (gaim_statuses_find_saved(new->name) != NULL) {
-		g_free(new->name);
-		new->name = g_strdup_printf("%s %d", name, i);
+	while (gaim_statuses_find_saved(ret->title) != NULL)
+	{
+		g_free(ret->title);
+		ret->title = g_strdup_printf("%s %d", tmp, i);
 		i++;
 	}
 
-	saved_statuses = g_list_append(saved_statuses, new);
+	/* Read the primitive status type */
+	node = xmlnode_get_child(status, "state");
+	if (node != NULL)
+		tmp = xmlnode_get_data(node);
+	if (tmp != NULL)
+		ret->type = gaim_primitive_get_type(tmp);
+
+	/* Read the message */
+	node = xmlnode_get_child(status, "message");
+	if (node != NULL)
+		tmp = xmlnode_get_data(node);
+	if (tmp != NULL)
+		ret->message = g_strdup(tmp);
+
+	/* Read substatuses */
+	for (node = xmlnode_get_child(status, "status"); node != NULL;
+			node = xmlnode_get_next_twin(node))
+	{
+		GaimStatusSavedSub *new;
+		new = gaim_statuses_read_parse_substatus(node);
+		if (new != NULL)
+			ret->substatuses = g_list_append(ret->substatuses, new);
+	}
+
+	return ret;
 }
 
 /**
  * @return TRUE on success, FALSE on failure (if the file can not
  *         be opened, or if it contains invalid XML).
  */
-gboolean
+static gboolean
 gaim_statuses_read(const char *filename)
 {
 	GError *error;
@@ -1828,7 +1934,8 @@
 
 	gaim_debug_info("status", "Reading %s\n", filename);
 
-	if (!g_file_get_contents(filename, &contents, &length, &error)) {
+	if (!g_file_get_contents(filename, &contents, &length, &error))
+	{
 		gaim_debug_error("status", "Error reading statuses: %s\n",
 						 error->message);
 		g_error_free(error);
@@ -1837,16 +1944,20 @@
 
 	statuses = xmlnode_from_str(contents, length);
 
-	if (statuses == NULL) {
+	if (statuses == NULL)
+	{
 		FILE *backup;
 		gchar *name;
 		gaim_debug_error("status", "Error parsing statuses\n");
 		name = g_strdup_printf("%s~", filename);
-		if ((backup = fopen(name, "w"))) {
+		if ((backup = fopen(name, "w")))
+		{
 			fwrite(contents, length, 1, backup);
 			fclose(backup);
 			chmod(name, S_IRUSR | S_IWUSR);
-		} else {
+		}
+		else
+		{
 			gaim_debug_error("status", "Unable to write backup %s\n", name);
 		}
 		g_free(name);
@@ -1857,8 +1968,11 @@
 	g_free(contents);
 
 	for (status = xmlnode_get_child(statuses, "status"); status != NULL;
-			status = xmlnode_get_next_twin(status)) {
-		gaim_statuses_read_parse_status(status);
+			status = xmlnode_get_next_twin(status))
+	{
+		GaimStatusSaved *new;
+		new = gaim_statuses_read_parse_status(status);
+		saved_statuses = g_list_append(saved_statuses, new);
 	}
 
 	gaim_debug_info("status", "Finished reading statuses\n");
@@ -1880,8 +1994,10 @@
 
 	filename = g_build_filename(user_dir, "status.xml", NULL);
 
-	if (g_file_test(filename, G_FILE_TEST_EXISTS)) {
-		if (!gaim_statuses_read(filename)) {
+	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 "
@@ -1893,3 +2009,9 @@
 
 	g_free(filename);
 }
+
+void
+gaim_statuses_sync(void)
+{
+	/* TODO: Write me, baby. */
+}
--- a/src/status.h	Sun Dec 12 18:20:17 2004 +0000
+++ b/src/status.h	Sun Dec 12 23:57:52 2004 +0000
@@ -58,7 +58,8 @@
 	GAIM_STATUS_UNAVAILABLE,
 	GAIM_STATUS_HIDDEN,
 	GAIM_STATUS_AWAY,
-	GAIM_STATUS_EXTENDED_AWAY
+	GAIM_STATUS_EXTENDED_AWAY,
+	GAIM_STATUS_NUM_PRIMITIVES
 
 } GaimStatusPrimitive;
 
@@ -296,6 +297,18 @@
  */
 const GList *gaim_status_type_get_attrs(const GaimStatusType *status_type);
 
+/**
+ * Find the GaimStatusType with the given id.
+ *
+ * @param status_types A list of status types.  Often account->status_types.
+ * @param id The unique ID of the status type you wish to find.
+ *
+ * @return The status type with the given ID, or NULL if one could
+ *         not be found.
+ */
+const GaimStatusType *gaim_status_type_find_with_id(GList *status_types,
+													const char *id);
+
 /*@}*/
 
 /**************************************************************************/
@@ -896,11 +909,20 @@
 /**
  * Finds a saved status with the specified title.
  *
- * @param name The name of the saved status.
+ * @param title The name of the saved status.
  *
  * @return The saved status if found, or NULL.
  */
-GaimStatusSaved *gaim_statuses_find_saved(const char *name);
+GaimStatusSaved *gaim_statuses_find_saved(const char *title);
+
+/**
+ * Return the name of a given saved status.
+ *
+ * @param saved_status The saved status.
+ *
+ * @return The title.
+ */
+const char *gaim_statuses_saved_get_title(const GaimStatusSaved *saved_status);
 
 /**
  * Return the name of a given saved status.
@@ -909,16 +931,7 @@
  *
  * @return The name.
  */
-const char *gaim_statuses_saved_get_name(const GaimStatusSaved *saved_status);
-
-/**
- * Return the name of a given saved status.
- *
- * @param saved_status The saved status.
- *
- * @return The name.
- */
-const GaimStatusType *gaim_statuses_saved_get_type(const GaimStatusSaved *saved_status);
+GaimStatusPrimitive gaim_statuses_saved_get_type(const GaimStatusSaved *saved_status);
 
 /**
  * Return the name of a given saved status.
@@ -947,15 +960,15 @@
 void gaim_statuses_uninit(void);
 
 /**
+ * Syncs status information from a file.
+ */
+void gaim_statuses_load(void);
+
+/**
  * Syncs status information to the file.
  */
 void gaim_statuses_sync(void);
 
-/**
- * Syncs status information from a file.
- */
-void gaim_statuses_load(void);
-
 /*@}*/
 
 #endif /* _GAIM_STATUS_H_ */