Gadu-Gadu: status refactoring - done soc.2012.gg
authorTomasz Wasilczyk <tomkiewicz@cpw.pidgin.im>
Fri, 17 Aug 2012 11:00:00 +0200
branchsoc.2012.gg
changeset5f00ed891179 pushlog
parent 02ee2834030c
child 481258ec30de
Gadu-Gadu: status refactoring - done
libpurple/protocols/gg/gg.c
libpurple/protocols/gg/gg.h
libpurple/protocols/gg/status.c
libpurple/protocols/gg/status.h
     1.1 --- a/libpurple/protocols/gg/gg.c
     1.2 +++ b/libpurple/protocols/gg/gg.c
     1.3 @@ -52,13 +52,29 @@
     1.4  #include "status.h"
     1.5  #include "servconn.h"
     1.6  
     1.7 -/* Prototypes */
     1.8 +/* ---------------------------------------------------------------------- */
     1.9  
    1.10 -typedef struct
    1.11 +ggp_buddy_data * ggp_buddy_get_data(PurpleBuddy *buddy)
    1.12  {
    1.13 -	gboolean blocked;
    1.14 -} ggp_buddy_data;
    1.15 +	ggp_buddy_data *buddy_data = purple_buddy_get_protocol_data(buddy);
    1.16 +	if (buddy_data)
    1.17 +		return buddy_data;
    1.18 +	
    1.19 +	buddy_data = g_new0(ggp_buddy_data, 1);
    1.20 +	purple_buddy_set_protocol_data(buddy, buddy_data);
    1.21 +	return buddy_data;
    1.22 +}
    1.23  
    1.24 +static void ggp_buddy_free(PurpleBuddy *buddy)
    1.25 +{
    1.26 +	ggp_buddy_data *buddy_data = purple_buddy_get_protocol_data(buddy);
    1.27 +
    1.28 +	if (!buddy_data)
    1.29 +		return;
    1.30 +
    1.31 +	g_free(buddy_data);
    1.32 +	purple_buddy_set_protocol_data(buddy, NULL);
    1.33 +}
    1.34  
    1.35  /* ---------------------------------------------------------------------- */
    1.36  // buddy list import/export from/to file
    1.37 @@ -383,96 +399,6 @@
    1.38  /* ---------------------------------------------------------------------- */
    1.39  
    1.40  
    1.41 -/**
    1.42 - * Handle change of the status of the buddy.
    1.43 - *
    1.44 - * @param gc     PurpleConnection
    1.45 - * @param uin    UIN of the buddy.
    1.46 - * @param status ID of the status.
    1.47 - * @param descr  Description.
    1.48 - */
    1.49 -static void ggp_generic_status_handler(PurpleConnection *gc, uin_t uin,
    1.50 -				       int status, const char *descr)
    1.51 -{
    1.52 -	gchar *from;
    1.53 -	const char *st;
    1.54 -	char *status_msg = NULL;
    1.55 -	ggp_buddy_data *buddy_data;
    1.56 -	PurpleBuddy *buddy;
    1.57 -	PurpleAccount *account = purple_connection_get_account(gc);
    1.58 -
    1.59 -	from = g_strdup_printf("%u", uin);
    1.60 -	buddy = purple_find_buddy(purple_connection_get_account(gc), from);
    1.61 -
    1.62 -	switch (status) {
    1.63 -		case GG_STATUS_NOT_AVAIL:
    1.64 -		case GG_STATUS_NOT_AVAIL_DESCR:
    1.65 -		case GG_STATUS_BLOCKED:
    1.66 -			st = purple_primitive_get_id_from_type(PURPLE_STATUS_OFFLINE);
    1.67 -			break;
    1.68 -		case GG_STATUS_FFC:
    1.69 -		case GG_STATUS_FFC_DESCR:
    1.70 -			st = "freeforchat";
    1.71 -			break;
    1.72 -		case GG_STATUS_AVAIL:
    1.73 -		case GG_STATUS_AVAIL_DESCR:
    1.74 -			st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE);
    1.75 -			break;
    1.76 -		case GG_STATUS_BUSY:
    1.77 -		case GG_STATUS_BUSY_DESCR:
    1.78 -			st = purple_primitive_get_id_from_type(PURPLE_STATUS_AWAY);
    1.79 -			break;
    1.80 -		case GG_STATUS_INVISIBLE:
    1.81 -		case GG_STATUS_INVISIBLE_DESCR:
    1.82 -			st = purple_primitive_get_id_from_type(PURPLE_STATUS_INVISIBLE);
    1.83 -			break;
    1.84 -		case GG_STATUS_DND:
    1.85 -		case GG_STATUS_DND_DESCR:
    1.86 -			st = purple_primitive_get_id_from_type(PURPLE_STATUS_UNAVAILABLE);
    1.87 -			break;
    1.88 -		default:
    1.89 -			st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE);
    1.90 -			purple_debug_info("gg",
    1.91 -				"GG_EVENT_NOTIFY: Unknown status: %d\n", status);
    1.92 -			break;
    1.93 -	}
    1.94 -
    1.95 -	if (descr != NULL) {
    1.96 -		status_msg = g_strdup(descr);
    1.97 -		g_strstrip(status_msg);
    1.98 -		if (status_msg[0] == '\0') {
    1.99 -			g_free(status_msg);
   1.100 -			status_msg = NULL;
   1.101 -		}
   1.102 -	}
   1.103 -
   1.104 -	buddy_data = purple_buddy_get_protocol_data(buddy);
   1.105 -	if (!buddy_data)
   1.106 -	{
   1.107 -		buddy_data = g_new0(ggp_buddy_data, 1);
   1.108 -		purple_buddy_set_protocol_data(buddy, buddy_data);
   1.109 -	}
   1.110 -	buddy_data->blocked = (status == GG_STATUS_BLOCKED);
   1.111 -
   1.112 -	if (uin == ggp_str_to_uin(purple_account_get_username(account)))
   1.113 -	{
   1.114 -		purple_debug_info("gg", "own status changed to %s [%s]\n", st,
   1.115 -			status_msg ? status_msg : "");
   1.116 -	}
   1.117 -
   1.118 -	purple_debug_info("gg", "status of %u is %s [%s]\n", uin, st,
   1.119 -		status_msg ? status_msg : "");
   1.120 -	if (status_msg == NULL) {
   1.121 -		purple_prpl_got_user_status(account,
   1.122 -			from, st, NULL);
   1.123 -	} else {
   1.124 -		purple_prpl_got_user_status(account,
   1.125 -			from, st, "message", status_msg, NULL);
   1.126 -		g_free(status_msg);
   1.127 -	}
   1.128 -	g_free(from);
   1.129 -}
   1.130 -
   1.131  static void ggp_sr_close_cb(gpointer user_data)
   1.132  {
   1.133  	GGPSearchForm *form = user_data;
   1.134 @@ -484,57 +410,26 @@
   1.135  	ggp_search_form_destroy(form);
   1.136  }
   1.137  
   1.138 -/**
   1.139 - * Translate a status' ID to a more user-friendly name.
   1.140 - *
   1.141 - * @param id The ID of the status.
   1.142 - *
   1.143 - * @return The user-friendly name of the status.
   1.144 - */
   1.145 -static const char *ggp_status_by_id(unsigned int id)
   1.146 -{
   1.147 -	const char *st;
   1.148 -
   1.149 -	purple_debug_info("gg", "ggp_status_by_id: %d\n", id);
   1.150 -	switch (id) {
   1.151 -		case GG_STATUS_NOT_AVAIL:
   1.152 -		case GG_STATUS_NOT_AVAIL_DESCR:
   1.153 -			st = _("Offline");
   1.154 -			break;
   1.155 -		case GG_STATUS_AVAIL:
   1.156 -		case GG_STATUS_AVAIL_DESCR:
   1.157 -			st = _("Available");
   1.158 -			break;
   1.159 -		case GG_STATUS_FFC:
   1.160 -		case GG_STATUS_FFC_DESCR:
   1.161 -			return _("Chatty");
   1.162 -		case GG_STATUS_DND:
   1.163 -		case GG_STATUS_DND_DESCR:
   1.164 -			return _("Do Not Disturb");
   1.165 -		case GG_STATUS_BUSY:
   1.166 -		case GG_STATUS_BUSY_DESCR:
   1.167 -			st = _("Away");
   1.168 -			break;
   1.169 -		default:
   1.170 -			st = _("Unknown");
   1.171 -			break;
   1.172 -	}
   1.173 -
   1.174 -	return st;
   1.175 -}
   1.176 -
   1.177  static void ggp_pubdir_handle_info(PurpleConnection *gc, gg_pubdir50_t req,
   1.178  				   GGPSearchForm *form)
   1.179  {
   1.180  	PurpleNotifyUserInfo *user_info;
   1.181  	PurpleBuddy *buddy;
   1.182  	char *val, *who;
   1.183 +	const gchar *status;
   1.184  
   1.185  	user_info = purple_notify_user_info_new();
   1.186  
   1.187 +
   1.188  	val = ggp_search_get_result(req, 0, GG_PUBDIR50_STATUS);
   1.189 -	/* XXX: Use of ggp_str_to_uin() is an ugly hack! */
   1.190 -	purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), ggp_status_by_id(ggp_str_to_uin(val)));
   1.191 +	status = ggp_status_to_purplestatus(atoi(val));
   1.192 +	if (g_strcmp0(status, "freeforchat"))
   1.193 +		//TODO: move to status.h or push to libpurple
   1.194 +		status = _("Chatty");
   1.195 +	else
   1.196 +		status = purple_primitive_get_name_from_type(
   1.197 +			purple_primitive_get_type_from_id(status));
   1.198 +	purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status);
   1.199  	g_free(val);
   1.200  
   1.201  	who = ggp_search_get_result(req, 0, GG_PUBDIR50_UIN);
   1.202 @@ -1005,7 +900,6 @@
   1.203  	PurpleConnection *gc = _gc;
   1.204  	GGPInfo *info = purple_connection_get_protocol_data(gc);
   1.205  	struct gg_event *ev;
   1.206 -	int i;
   1.207  
   1.208  	if (!(ev = gg_watch_fd(info->session))) {
   1.209  		purple_debug_error("gg",
   1.210 @@ -1036,63 +930,9 @@
   1.211  		case GG_EVENT_IMAGE_REQUEST:
   1.212  			ggp_image_send(gc, &ev->event.image_request);
   1.213  			break;
   1.214 -		case GG_EVENT_NOTIFY:
   1.215 -		case GG_EVENT_NOTIFY_DESCR:
   1.216 -			{
   1.217 -				struct gg_notify_reply *n;
   1.218 -				char *descr;
   1.219 -
   1.220 -				purple_debug_info("gg", "notify_pre: (%d) status: %d\n",
   1.221 -						ev->event.notify->uin,
   1.222 -						GG_S(ev->event.notify->status));
   1.223 -
   1.224 -				n = (ev->type == GG_EVENT_NOTIFY) ? ev->event.notify
   1.225 -								  : ev->event.notify_descr.notify;
   1.226 -
   1.227 -				for (; n->uin; n++) {
   1.228 -					descr = (ev->type == GG_EVENT_NOTIFY) ? NULL
   1.229 -							: ev->event.notify_descr.descr;
   1.230 -
   1.231 -					purple_debug_info("gg",
   1.232 -						"notify: (%d) status: %d; descr: %s\n",
   1.233 -						n->uin, GG_S(n->status), descr ? descr : "(null)");
   1.234 -
   1.235 -					ggp_generic_status_handler(gc,
   1.236 -						n->uin, GG_S(n->status), descr);
   1.237 -				}
   1.238 -			}
   1.239 -			break;
   1.240  		case GG_EVENT_NOTIFY60:
   1.241 -			for (i = 0; ev->event.notify60[i].uin; i++) {
   1.242 -				purple_debug_info("gg",
   1.243 -					"notify60: (%d) status=%d; version=%d; descr=%s\n",
   1.244 -					ev->event.notify60[i].uin,
   1.245 -					GG_S(ev->event.notify60[i].status),
   1.246 -					ev->event.notify60[i].version,
   1.247 -					ev->event.notify60[i].descr ? ev->event.notify60[i].descr : "(null)");
   1.248 -
   1.249 -				ggp_generic_status_handler(gc, ev->event.notify60[i].uin,
   1.250 -					GG_S(ev->event.notify60[i].status),
   1.251 -					ev->event.notify60[i].descr);
   1.252 -			}
   1.253 -			break;
   1.254 -		case GG_EVENT_STATUS:
   1.255 -			purple_debug_info("gg", "status: (%d) status=%d; descr=%s\n",
   1.256 -					ev->event.status.uin, GG_S(ev->event.status.status),
   1.257 -					ev->event.status.descr ? ev->event.status.descr : "(null)");
   1.258 -
   1.259 -			ggp_generic_status_handler(gc, ev->event.status.uin,
   1.260 -				GG_S(ev->event.status.status), ev->event.status.descr);
   1.261 -			break;
   1.262  		case GG_EVENT_STATUS60:
   1.263 -			purple_debug_info("gg",
   1.264 -				"status60: (%d) status=%d; version=%d; descr=%s\n",
   1.265 -				ev->event.status60.uin, GG_S(ev->event.status60.status),
   1.266 -				ev->event.status60.version,
   1.267 -				ev->event.status60.descr ? ev->event.status60.descr : "(null)");
   1.268 -
   1.269 -			ggp_generic_status_handler(gc, ev->event.status60.uin,
   1.270 -				GG_S(ev->event.status60.status), ev->event.status60.descr);
   1.271 +			ggp_status_got_others(gc, ev);
   1.272  			break;
   1.273  		case GG_EVENT_PUBDIR50_SEARCH_REPLY:
   1.274  			ggp_pubdir_reply_handler(gc, ev->event.pubdir50);
   1.275 @@ -1319,32 +1159,6 @@
   1.276  	return normalized;
   1.277  }
   1.278  
   1.279 -static char *ggp_status_text(PurpleBuddy *b)
   1.280 -{
   1.281 -	const char *msg;
   1.282 -	char *text;
   1.283 -	char *tmp;
   1.284 -	ggp_buddy_data *buddy_data = purple_buddy_get_protocol_data(b);
   1.285 -
   1.286 -	if (buddy_data && buddy_data->blocked)
   1.287 -		msg = _("Blocked");
   1.288 -	else
   1.289 -	{
   1.290 -		PurpleStatus *status = purple_presence_get_active_status(
   1.291 -			purple_buddy_get_presence(b));
   1.292 -		msg = purple_status_get_attr_string(status, "message");
   1.293 -	}
   1.294 -
   1.295 -	if (msg == NULL)
   1.296 -		return NULL;
   1.297 -
   1.298 -	tmp = purple_markup_strip_html(msg);
   1.299 -	text = g_markup_escape_text(tmp, -1);
   1.300 -	g_free(tmp);
   1.301 -
   1.302 -	return text;
   1.303 -}
   1.304 -
   1.305  static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
   1.306  {
   1.307  	PurpleStatus *status;
   1.308 @@ -1374,61 +1188,6 @@
   1.309  	}
   1.310  }
   1.311  
   1.312 -static GList *ggp_status_types(PurpleAccount *account)
   1.313 -{
   1.314 -	PurpleStatusType *type;
   1.315 -	GList *types = NULL;
   1.316 -
   1.317 -	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
   1.318 -		NULL, NULL, TRUE, TRUE, FALSE,
   1.319 -		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
   1.320 -		NULL);
   1.321 -	types = g_list_append(types, type);
   1.322 -
   1.323 -	/*
   1.324 -	 * New status for GG 8.0: PoGGadaj ze mna (chatty).
   1.325 -	 * NOTE: at this time, this is used only to set our own status.
   1.326 -	 */
   1.327 -	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
   1.328 -		"freeforchat", _("Chatty"), TRUE, TRUE, FALSE,
   1.329 -		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
   1.330 -		NULL);
   1.331 -	types = g_list_append(types, type);
   1.332 -
   1.333 -	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
   1.334 -		NULL, NULL, TRUE, TRUE, FALSE,
   1.335 -		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
   1.336 -		NULL);
   1.337 -	types = g_list_append(types, type);
   1.338 -
   1.339 -	/*
   1.340 -	 * New status for GG 8.0: Nie przeszkadzac (do not disturb).
   1.341 -	 */
   1.342 -	type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
   1.343 -		NULL, NULL, TRUE, TRUE, FALSE,
   1.344 -		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
   1.345 -		NULL);
   1.346 -	types = g_list_append(types, type);
   1.347 -
   1.348 -	/*
   1.349 -	 * It's used on buddy list if and only if it's showing our own
   1.350 -	 * (invisible) status.
   1.351 -	 */
   1.352 -	type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE,
   1.353 -		NULL, NULL, TRUE, TRUE, FALSE,
   1.354 -		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
   1.355 -		NULL);
   1.356 -	types = g_list_append(types, type);
   1.357 -
   1.358 -	type = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE,
   1.359 -		NULL, NULL, TRUE, TRUE, FALSE,
   1.360 -		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
   1.361 -		NULL);
   1.362 -	types = g_list_append(types, type);
   1.363 -
   1.364 -	return types;
   1.365 -}
   1.366 -
   1.367  static GList *ggp_blist_node_menu(PurpleBlistNode *node)
   1.368  {
   1.369  	PurpleMenuAction *act;
   1.370 @@ -1587,31 +1346,9 @@
   1.371  	info = purple_connection_get_protocol_data(gc);
   1.372  
   1.373  	if (info) {
   1.374 -		PurpleStatus *status = purple_account_get_active_status(account);
   1.375 -
   1.376  		if (info->session != NULL)
   1.377  		{
   1.378 -			const gchar *status_msg = purple_status_get_attr_string(status, "message");
   1.379 -			
   1.380 -			if (ggp_status_set(account,
   1.381 -				status_msg ? GG_STATUS_NOT_AVAIL_DESCR : GG_STATUS_NOT_AVAIL,
   1.382 -				status_msg))
   1.383 -			{
   1.384 -				/*struct gg_event *ev;
   1.385 -				guint64 wait_start = ggp_microtime(), now;
   1.386 -				int sleep_time = 5000;
   1.387 -				while ((ev = gg_watch_fd(info->session)) != NULL)
   1.388 -				{
   1.389 -					if (ev->type == GG_EVENT_DISCONNECT_ACK)
   1.390 -						break;
   1.391 -					now = ggp_microtime();
   1.392 -					if (now - wait_start + sleep_time >= 100000)
   1.393 -						break;
   1.394 -					usleep(sleep_time);
   1.395 -					sleep_time *= 2;
   1.396 -				}*/
   1.397 -				usleep(100000);
   1.398 -			}
   1.399 +			ggp_status_set_disconnected(account);
   1.400  			gg_logoff(info->session);
   1.401  			gg_free_session(info->session);
   1.402  		}
   1.403 @@ -1649,14 +1386,14 @@
   1.404  	gint pos = 0;
   1.405  	GData *attribs;
   1.406  	const char *start, *end = NULL, *last;
   1.407 -	ggp_buddy_data *buddy_data = purple_buddy_get_protocol_data(
   1.408 +	ggp_buddy_data *buddy_data = ggp_buddy_get_data(
   1.409  		purple_find_buddy(purple_connection_get_account(gc), who));
   1.410  
   1.411  	if (msg == NULL || *msg == '\0') {
   1.412  		return 0;
   1.413  	}
   1.414  
   1.415 -	if (buddy_data && buddy_data->blocked)
   1.416 +	if (buddy_data->blocked)
   1.417  		return -1;
   1.418  
   1.419  	last = msg;
   1.420 @@ -1970,10 +1707,7 @@
   1.421  
   1.422  static const char* ggp_list_emblem(PurpleBuddy *buddy)
   1.423  {
   1.424 -	ggp_buddy_data *buddy_data = purple_buddy_get_protocol_data(buddy);
   1.425 -
   1.426 -	if (!buddy_data)
   1.427 -		return NULL;
   1.428 +	ggp_buddy_data *buddy_data = ggp_buddy_get_data(buddy);
   1.429  
   1.430  	if (buddy_data->blocked)
   1.431  		return "not-authorized";
   1.432 @@ -1981,18 +1715,6 @@
   1.433  	return NULL;
   1.434  }
   1.435  
   1.436 -static void ggp_buddy_free(PurpleBuddy *buddy)
   1.437 -{
   1.438 -	ggp_buddy_data *buddy_data = purple_buddy_get_protocol_data(buddy);
   1.439 -
   1.440 -	if (!buddy_data)
   1.441 -		return;
   1.442 -
   1.443 -	g_free(buddy_data);
   1.444 -
   1.445 -	purple_buddy_set_protocol_data(buddy, NULL);
   1.446 -}
   1.447 -
   1.448  static gboolean ggp_offline_message(const PurpleBuddy *buddy)
   1.449  {
   1.450  	return TRUE;
   1.451 @@ -2015,7 +1737,7 @@
   1.452  	{"png", 1, 1, 200, 200, 0, PURPLE_ICON_SCALE_DISPLAY | PURPLE_ICON_SCALE_SEND},	/* icon_spec */
   1.453  	ggp_list_icon,			/* list_icon */
   1.454  	ggp_list_emblem,		/* list_emblem */
   1.455 -	ggp_status_text,		/* status_text */
   1.456 +	ggp_status_buddy_text,		/* status_text */
   1.457  	ggp_tooltip_text,		/* tooltip_text */
   1.458  	ggp_status_types,		/* status_types */
   1.459  	ggp_blist_node_menu,		/* blist_node_menu */
     2.1 --- a/libpurple/protocols/gg/gg.h
     2.2 +++ b/libpurple/protocols/gg/gg.h
     2.3 @@ -63,6 +63,13 @@
     2.4  	ggp_status_session_data *status_data;
     2.5  } GGPInfo;
     2.6  
     2.7 +typedef struct
     2.8 +{
     2.9 +	gboolean blocked;
    2.10 +} ggp_buddy_data;
    2.11 +
    2.12  void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event_msg *ev, gboolean multilogon);
    2.13  
    2.14 +ggp_buddy_data * ggp_buddy_get_data(PurpleBuddy *buddy);
    2.15 +
    2.16  #endif /* _PURPLE_GG_H */
     3.1 --- a/libpurple/protocols/gg/status.c
     3.2 +++ b/libpurple/protocols/gg/status.c
     3.3 @@ -16,7 +16,7 @@
     3.4  static inline ggp_status_session_data *
     3.5  ggp_status_get_ssdata(PurpleConnection *gc);
     3.6  
     3.7 -gchar * ggp_status_validate_description(const gchar* msg);
     3.8 +static gchar * ggp_status_validate_description(const gchar* msg);
     3.9  static int ggp_status_from_purplestatus(PurpleStatus *status, gchar **message);
    3.10  
    3.11  ////
    3.12 @@ -47,7 +47,7 @@
    3.13  	g_free(ssdata);
    3.14  }
    3.15  
    3.16 -gchar * ggp_status_validate_description(const gchar* msg)
    3.17 +static gchar * ggp_status_validate_description(const gchar* msg)
    3.18  {
    3.19  	if (msg == NULL || msg[0] == '\0')
    3.20  		return NULL;
    3.21 @@ -55,6 +55,43 @@
    3.22  	return ggp_utf8_strndup(msg, GG_STATUS_DESCR_MAXSIZE);
    3.23  }
    3.24  
    3.25 +GList * ggp_status_types(PurpleAccount *account)
    3.26 +{
    3.27 +	GList *types = NULL;
    3.28 +
    3.29 +	types = g_list_append(types, purple_status_type_new_with_attrs(
    3.30 +		PURPLE_STATUS_AVAILABLE, NULL, NULL,
    3.31 +		TRUE, TRUE, FALSE, "message", _("Message"),
    3.32 +		purple_value_new(PURPLE_TYPE_STRING), NULL));
    3.33 +
    3.34 +	types = g_list_append(types, purple_status_type_new_with_attrs(
    3.35 +		PURPLE_STATUS_AVAILABLE, "freeforchat", _("Chatty"),
    3.36 +		TRUE, TRUE, FALSE, "message", _("Message"),
    3.37 +		purple_value_new(PURPLE_TYPE_STRING), NULL));
    3.38 +
    3.39 +	types = g_list_append(types, purple_status_type_new_with_attrs(
    3.40 +		PURPLE_STATUS_AWAY, NULL, NULL,
    3.41 +		TRUE, TRUE, FALSE, "message", _("Message"),
    3.42 +		purple_value_new(PURPLE_TYPE_STRING), NULL));
    3.43 +
    3.44 +	types = g_list_append(types, purple_status_type_new_with_attrs(
    3.45 +		PURPLE_STATUS_UNAVAILABLE, NULL, NULL,
    3.46 +		TRUE, TRUE, FALSE, "message", _("Message"),
    3.47 +		purple_value_new(PURPLE_TYPE_STRING), NULL));
    3.48 +
    3.49 +	types = g_list_append(types, purple_status_type_new_with_attrs(
    3.50 +		PURPLE_STATUS_INVISIBLE, NULL, NULL,
    3.51 +		TRUE, TRUE, FALSE, "message", _("Message"),
    3.52 +		purple_value_new(PURPLE_TYPE_STRING), NULL));
    3.53 +
    3.54 +	types = g_list_append(types, purple_status_type_new_with_attrs(
    3.55 +		PURPLE_STATUS_OFFLINE, NULL, NULL,
    3.56 +		TRUE, TRUE, FALSE, "message", _("Message"),
    3.57 +		purple_value_new(PURPLE_TYPE_STRING), NULL));
    3.58 +
    3.59 +	return types;
    3.60 +}
    3.61 +
    3.62  static int ggp_status_from_purplestatus(PurpleStatus *status, gchar **message)
    3.63  {
    3.64  	const char *status_id = purple_status_get_id(status);
    3.65 @@ -91,6 +128,41 @@
    3.66  	return status_message ? GG_STATUS_AVAIL_DESCR : GG_STATUS_AVAIL;
    3.67  }
    3.68  
    3.69 +const gchar * ggp_status_to_purplestatus(int status)
    3.70 +{
    3.71 +	switch (status)
    3.72 +	{
    3.73 +		case GG_STATUS_NOT_AVAIL:
    3.74 +		case GG_STATUS_NOT_AVAIL_DESCR:
    3.75 +		case GG_STATUS_BLOCKED:
    3.76 +			return purple_primitive_get_id_from_type(
    3.77 +				PURPLE_STATUS_OFFLINE);
    3.78 +		case GG_STATUS_FFC:
    3.79 +		case GG_STATUS_FFC_DESCR:
    3.80 +			return "freeforchat";
    3.81 +		case GG_STATUS_AVAIL:
    3.82 +		case GG_STATUS_AVAIL_DESCR:
    3.83 +			return purple_primitive_get_id_from_type(
    3.84 +				PURPLE_STATUS_AVAILABLE);
    3.85 +		case GG_STATUS_BUSY:
    3.86 +		case GG_STATUS_BUSY_DESCR:
    3.87 +			return purple_primitive_get_id_from_type(
    3.88 +				PURPLE_STATUS_AWAY);
    3.89 +		case GG_STATUS_INVISIBLE:
    3.90 +		case GG_STATUS_INVISIBLE_DESCR:
    3.91 +			return purple_primitive_get_id_from_type(
    3.92 +				PURPLE_STATUS_INVISIBLE);
    3.93 +		case GG_STATUS_DND:
    3.94 +		case GG_STATUS_DND_DESCR:
    3.95 +			return purple_primitive_get_id_from_type(
    3.96 +				PURPLE_STATUS_UNAVAILABLE);
    3.97 +		default:
    3.98 +			purple_debug_warning("gg", "ggp_status_to_purplestatus: unknown status %d\n", status);
    3.99 +			return purple_primitive_get_id_from_type(
   3.100 +				PURPLE_STATUS_AVAILABLE);
   3.101 +	}
   3.102 +}
   3.103 +
   3.104  /*******************************************************************************
   3.105   * Own status.
   3.106   ******************************************************************************/
   3.107 @@ -155,6 +227,39 @@
   3.108  	g_free(msg);
   3.109  }
   3.110  
   3.111 +void ggp_status_set_disconnected(PurpleAccount *account)
   3.112 +{
   3.113 +	gchar *msg = NULL;
   3.114 +	
   3.115 +	ggp_status_from_purplestatus(purple_account_get_active_status(account),
   3.116 +		&msg);
   3.117 +	if (!ggp_status_set(account,
   3.118 +		msg ? GG_STATUS_NOT_AVAIL_DESCR : GG_STATUS_NOT_AVAIL, msg))
   3.119 +	{
   3.120 +		g_free(msg);
   3.121 +		return;
   3.122 +	}
   3.123 +	
   3.124 +	/*
   3.125 +	struct gg_event *ev;
   3.126 +	guint64 wait_start = ggp_microtime(), now;
   3.127 +	int sleep_time = 5000;
   3.128 +	while ((ev = gg_watch_fd(info->session)) != NULL)
   3.129 +	{
   3.130 +		if (ev->type == GG_EVENT_DISCONNECT_ACK)
   3.131 +			break;
   3.132 +		now = ggp_microtime();
   3.133 +		if (now - wait_start + sleep_time >= 100000)
   3.134 +			break;
   3.135 +		usleep(sleep_time);
   3.136 +		sleep_time *= 2;
   3.137 +	}
   3.138 +	*/
   3.139 +	usleep(100000);
   3.140 +	
   3.141 +	g_free(msg);
   3.142 +}
   3.143 +
   3.144  void ggp_status_fake_to_self(PurpleConnection *gc)
   3.145  {
   3.146  	PurpleAccount *account = purple_connection_get_account(gc);
   3.147 @@ -226,3 +331,104 @@
   3.148  	ggp_status_set_status_broadcasting(gc,
   3.149  		!purple_request_fields_get_bool(fields, "buddies_only"));
   3.150  }
   3.151 +
   3.152 +/*******************************************************************************
   3.153 + * Buddy status.
   3.154 + ******************************************************************************/
   3.155 +
   3.156 +void ggp_status_got_others_buddy(PurpleConnection *gc, uin_t uin, int status,
   3.157 +	const char *descr);
   3.158 +
   3.159 +/******************************************************************************/
   3.160 +
   3.161 +void ggp_status_got_others(PurpleConnection *gc, struct gg_event *ev)
   3.162 +{
   3.163 +	if (ev->type == GG_EVENT_NOTIFY60)
   3.164 +	{
   3.165 +		struct gg_event_notify60 *notify = ev->event.notify60;
   3.166 +		int i;
   3.167 +		for (i = 0; notify[i].uin; i++)
   3.168 +			ggp_status_got_others_buddy(gc, notify[i].uin,
   3.169 +				GG_S(notify[i].status), notify[i].descr);
   3.170 +	}
   3.171 +	else if (ev->type == GG_EVENT_STATUS60)
   3.172 +	{
   3.173 +		struct gg_event_status60 *notify = &ev->event.status60;
   3.174 +		ggp_status_got_others_buddy(gc, notify->uin,
   3.175 +			GG_S(notify->status), notify->descr);
   3.176 +	}
   3.177 +	else
   3.178 +		purple_debug_fatal("gg", "ggp_status_got_others: "
   3.179 +			"unexpected event %d\n", ev->type);
   3.180 +}
   3.181 +
   3.182 +void ggp_status_got_others_buddy(PurpleConnection *gc, uin_t uin, int status,
   3.183 +	const char *descr)
   3.184 +{
   3.185 +	PurpleAccount *account = purple_connection_get_account(gc);
   3.186 +	PurpleBuddy *buddy = purple_find_buddy(account, ggp_uin_to_str(uin));
   3.187 +	const gchar *purple_status = ggp_status_to_purplestatus(status);
   3.188 +	gchar *status_message = NULL;
   3.189 +	
   3.190 +	if (!buddy)
   3.191 +	{
   3.192 +		purple_debug_warning("gg", "ggp_status_got_others_buddy: "
   3.193 +			"buddy %u not found\n", uin);
   3.194 +		return;
   3.195 +	}
   3.196 +	ggp_buddy_get_data(buddy)->blocked = (status == GG_STATUS_BLOCKED);
   3.197 +	
   3.198 +	if (descr != NULL)
   3.199 +	{
   3.200 +		status_message = g_strdup(descr);
   3.201 +		g_strstrip(status_message);
   3.202 +		if (status_message[0] == '\0')
   3.203 +		{
   3.204 +			g_free(status_message);
   3.205 +			status_message = NULL;
   3.206 +		}
   3.207 +	}
   3.208 +	
   3.209 +	if (uin == ggp_str_to_uin(purple_account_get_username(account)))
   3.210 +	{
   3.211 +		purple_debug_info("gg", "ggp_status_got_others_buddy: "
   3.212 +			"own status changed to %s [%s]\n",
   3.213 +			purple_status, status_message ? status_message : "");
   3.214 +	}
   3.215 +	else
   3.216 +	{
   3.217 +		purple_debug_misc("gg", "ggp_status_got_others_buddy: "
   3.218 +			"status of %u changed to %s [%s]\n", uin,
   3.219 +			purple_status, status_message ? status_message : "");
   3.220 +	}
   3.221 +	
   3.222 +	if (status_message)
   3.223 +	{
   3.224 +		purple_prpl_got_user_status(account, ggp_uin_to_str(uin),
   3.225 +			purple_status, "message", status_message, NULL);
   3.226 +	}
   3.227 +	else
   3.228 +	{
   3.229 +		purple_prpl_got_user_status(account, ggp_uin_to_str(uin),
   3.230 +			purple_status, NULL);
   3.231 +	}
   3.232 +	
   3.233 +	g_free(status_message);
   3.234 +}
   3.235 +
   3.236 +char * ggp_status_buddy_text(PurpleBuddy *buddy)
   3.237 +{
   3.238 +	ggp_buddy_data *buddy_data = ggp_buddy_get_data(buddy);
   3.239 +	const gchar *purple_message;
   3.240 +	
   3.241 +	if (buddy_data->blocked)
   3.242 +		return g_strdup(_("Blocked"));
   3.243 +	
   3.244 +	purple_message = purple_status_get_attr_string(
   3.245 +		purple_presence_get_active_status(
   3.246 +			purple_buddy_get_presence(buddy)), "message");
   3.247 +	if (!purple_message)
   3.248 +		return NULL;
   3.249 +	
   3.250 +	return g_markup_escape_text(purple_message, -1);
   3.251 +}
     4.1 --- a/libpurple/protocols/gg/status.h
     4.2 +++ b/libpurple/protocols/gg/status.h
     4.3 @@ -9,12 +9,16 @@
     4.4  void ggp_status_setup(PurpleConnection *gc);
     4.5  void ggp_status_cleanup(PurpleConnection *gc);
     4.6  
     4.7 +GList * ggp_status_types(PurpleAccount *account);
     4.8 +const gchar * ggp_status_to_purplestatus(int status);
     4.9 +
    4.10  // own status
    4.11  
    4.12  void ggp_status_set_initial(PurpleConnection *gc, struct gg_login_params *glp);
    4.13  
    4.14  gboolean ggp_status_set(PurpleAccount *account, int status, const gchar* msg);
    4.15  void ggp_status_set_purplestatus(PurpleAccount *account, PurpleStatus *status);
    4.16 +void ggp_status_set_disconnected(PurpleAccount *account);
    4.17  void ggp_status_fake_to_self(PurpleConnection *gc);
    4.18  
    4.19  gboolean ggp_status_get_status_broadcasting(PurpleConnection *gc);
    4.20 @@ -22,4 +26,9 @@
    4.21  	gboolean broadcasting);
    4.22  void ggp_status_broadcasting_dialog(PurpleConnection *gc);
    4.23  
    4.24 +// buddy status
    4.25 +
    4.26 +void ggp_status_got_others(PurpleConnection *gc, struct gg_event *ev);
    4.27 +char * ggp_status_buddy_text(PurpleBuddy *buddy);
    4.28 +
    4.29  #endif /* _GGP_STATUS_H */