Index: protocols/jabber/iq.c
===================================================================
--- protocols/jabber/iq.c	(revision d8e04849607d4a5ca590752dce37954f12179580)
+++ protocols/jabber/iq.c	(revision 5e202b09f2cd9faff5f316ae6804facb5342eace)
@@ -107,5 +107,5 @@
 		}
 		
-		presence_announce( gc );
+		account_online( gc );
 	}
 	else if( strcmp( type, "result" ) == 0 && orig )
Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision d8e04849607d4a5ca590752dce37954f12179580)
+++ protocols/jabber/jabber.c	(revision 5e202b09f2cd9faff5f316ae6804facb5342eace)
@@ -111,4 +111,5 @@
 	xt_free( jd->xt );
 	
+	g_free( jd->away_message );
 	g_free( jd->username );
 	g_free( jd );
@@ -128,21 +129,28 @@
 }
 
-/* TODO: For away state handling, implement some list like the one for MSN. */
 static GList *jabber_away_states( struct gaim_connection *gc )
 {
-	GList *l = NULL;
+	static GList *l = NULL;
+	int i;
 	
-	l = g_list_append( l, (void*) "Online" );
-	l = g_list_append( l, (void*) "Away" );
-	l = g_list_append( l, (void*) "Extended Away" );
-	l = g_list_append( l, (void*) "Do Not Disturb" );
+	if( l == NULL )
+		for( i = 0; jabber_away_state_list[i].full_name; i ++ )
+			l = g_list_append( l, (void*) jabber_away_state_list[i].full_name );
 	
-	return( l );
+	return l;
 }
 
-static void jabber_set_away( struct gaim_connection *gc, char *state, char *message )
+static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char *message )
 {
-	/* For now let's just always set state to "away" and send the message, if available. */
-	presence_send( gc, NULL, g_strcasecmp( state, "Online" ) == 0 ? NULL : "away", message );
+	struct jabber_data *jd = gc->proto_data;
+	struct jabber_away_state *state;
+	
+	/* Save all this info. We need it, for example, when changing the priority setting. */
+	state = (void *) jabber_away_state_by_name( state_txt );
+	jd->away_state = state ? state : (void *) jabber_away_state_list; /* Fall back to "Away" if necessary. */
+	g_free( jd->away_message );
+	jd->away_message = ( message && *message ) ? g_strdup( message ) : NULL;
+	
+	presence_send( gc, NULL, jd->away_state->code, jd->away_message );
 }
 
Index: protocols/jabber/jabber.h
===================================================================
--- protocols/jabber/jabber.h	(revision d8e04849607d4a5ca590752dce37954f12179580)
+++ protocols/jabber/jabber.h	(revision 5e202b09f2cd9faff5f316ae6804facb5342eace)
@@ -39,36 +39,4 @@
 } jabber_flags_t;
 
-/* iq.c */
-xt_status jabber_pkt_iq( struct xt_node *node, gpointer data );
-int jabber_start_iq_auth( struct gaim_connection *gc );
-int jabber_get_roster( struct gaim_connection *gc );
-
-xt_status jabber_pkt_message( struct xt_node *node, gpointer data );
-
-/* presence.c */
-xt_status jabber_pkt_presence( struct xt_node *node, gpointer data );
-int presence_announce( struct gaim_connection *gc );
-int presence_send( struct gaim_connection *gc, char *to, char *show, char *status );
-
-/* jabber_util.c */
-char *set_eval_resprio( set_t *set, char *value );
-char *set_eval_tls( set_t *set, char *value );
-struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
-void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node );
-struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id );
-
-/* io.c */
-int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node );
-int jabber_write( struct gaim_connection *gc, char *buf, int len );
-gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond );
-gboolean jabber_start_stream( struct gaim_connection *gc );
-void jabber_end_stream( struct gaim_connection *gc );
-
-/* sasl.c */
-xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data );
-xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data );
-xt_status sasl_pkt_result( struct xt_node *node, gpointer data );
-gboolean sasl_supported( struct gaim_connection *gc );
-
 struct jabber_data
 {
@@ -86,7 +54,50 @@
 	char *username;		/* USERNAME@server */
 	char *server;		/* username@SERVER -=> server/domain, not hostname */
+	struct jabber_away_state *away_state;
+	char *away_message;
 	
 	struct xt_node *node_cache;
 };
 
+struct jabber_away_state
+{
+	char code[5];
+	char *full_name;
+};
+
+/* iq.c */
+xt_status jabber_pkt_iq( struct xt_node *node, gpointer data );
+int jabber_start_iq_auth( struct gaim_connection *gc );
+int jabber_get_roster( struct gaim_connection *gc );
+
+xt_status jabber_pkt_message( struct xt_node *node, gpointer data );
+
+/* presence.c */
+xt_status jabber_pkt_presence( struct xt_node *node, gpointer data );
+int presence_send( struct gaim_connection *gc, char *to, char *show, char *status );
+
+/* jabber_util.c */
+char *set_eval_resprio( set_t *set, char *value );
+char *set_eval_tls( set_t *set, char *value );
+struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
+void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node );
+struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id );
+const struct jabber_away_state *jabber_away_state_by_code( char *code );
+const struct jabber_away_state *jabber_away_state_by_name( char *name );
+
+extern const struct jabber_away_state jabber_away_state_list[];
+
+/* io.c */
+int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node );
+int jabber_write( struct gaim_connection *gc, char *buf, int len );
+gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond );
+gboolean jabber_start_stream( struct gaim_connection *gc );
+void jabber_end_stream( struct gaim_connection *gc );
+
+/* sasl.c */
+xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data );
+xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data );
+xt_status sasl_pkt_result( struct xt_node *node, gpointer data );
+gboolean sasl_supported( struct gaim_connection *gc );
+
 #endif
Index: protocols/jabber/jabber_util.c
===================================================================
--- protocols/jabber/jabber_util.c	(revision d8e04849607d4a5ca590752dce37954f12179580)
+++ protocols/jabber/jabber_util.c	(revision 5e202b09f2cd9faff5f316ae6804facb5342eace)
@@ -92,2 +92,34 @@
 	return node;
 }
+
+const struct jabber_away_state jabber_away_state_list[] =
+{
+	{ "away",  "Away" },
+	{ "chat",  "Free for Chat" },
+	{ "dnd",   "Do not Disturb" },
+	{ "xa",    "Extended Away" },
+	{ "",      "Online" },
+	{ "",      NULL }
+};
+
+const struct jabber_away_state *jabber_away_state_by_code( char *code )
+{
+	int i;
+	
+	for( i = 0; jabber_away_state_list[i].full_name; i ++ )
+		if( g_strcasecmp( jabber_away_state_list[i].code, code ) == 0 )
+			return jabber_away_state_list + i;
+	
+	return NULL;
+}
+
+const struct jabber_away_state *jabber_away_state_by_name( char *name )
+{
+	int i;
+	
+	for( i = 0; jabber_away_state_list[i].full_name; i ++ )
+		if( g_strcasecmp( jabber_away_state_list[i].full_name, name ) == 0 )
+			return jabber_away_state_list + i;
+	
+	return NULL;
+}
Index: protocols/jabber/presence.c
===================================================================
--- protocols/jabber/presence.c	(revision d8e04849607d4a5ca590752dce37954f12179580)
+++ protocols/jabber/presence.c	(revision 5e202b09f2cd9faff5f316ae6804facb5342eace)
@@ -54,22 +54,4 @@
 }
 
-/* Send the <presence/> tag that finalizes the whole login process, from here
-   we'll actually show up as online to our buddies. */
-int presence_announce( struct gaim_connection *gc )
-{
-	struct xt_node *node;
-	int st;
-	
-	node = jabber_make_packet( "presence", NULL, NULL, NULL );
-	
-	st = jabber_write_packet( gc, node );
-	
-	if( st )
-		account_online( gc );
-	
-	xt_free_node( node );
-	return st;
-}
-
 int presence_send( struct gaim_connection *gc, char *to, char *show, char *status )
 {
@@ -78,5 +60,5 @@
 	
 	node = jabber_make_packet( "presence", NULL, to, NULL );
-	if( show )
+	if( show && *show )
 		xt_add_child( node, xt_new_node( "show", show, NULL ) );
 	if( status )
Index: protocols/msn/msn.c
===================================================================
--- protocols/msn/msn.c	(revision d8e04849607d4a5ca590752dce37954f12179580)
+++ protocols/msn/msn.c	(revision 5e202b09f2cd9faff5f316ae6804facb5342eace)
@@ -183,11 +183,12 @@
 static GList *msn_away_states( struct gaim_connection *gc )
 {
-	GList *l = NULL;
+	static GList *l = NULL;
 	int i;
 	
-	for( i = 0; msn_away_state_list[i].number > -1; i ++ )
-		l = g_list_append( l, (void*) msn_away_state_list[i].name );
-	
-	return( l );
+	if( l == NULL )
+		for( i = 0; msn_away_state_list[i].number > -1; i ++ )
+			l = g_list_append( l, (void*) msn_away_state_list[i].name );
+	
+	return l;
 }
 
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision d8e04849607d4a5ca590752dce37954f12179580)
+++ protocols/nogaim.c	(revision 5e202b09f2cd9faff5f316ae6804facb5342eace)
@@ -1019,6 +1019,4 @@
 	}
 	
-	g_list_free( ms );
-	
 	return( 1 );
 }
