Mercurial > pidgin
comparison libpurple/protocols/gg/gg.c @ 24483:4d50b5d09d4a
Support displaying buddy icons from Gadu-Gadu buddies. Fixes #220.
committer: John Bailey <rekkanoryo@rekkanoryo.org>
author | Adam Strzelecki <ono@java.pl> |
---|---|
date | Sun, 23 Nov 2008 04:11:36 +0000 |
parents | 0320b4a33432 |
children | 0d3af2ecf4ad |
comparison
equal
deleted
inserted
replaced
24482:39841a84c944 | 24483:4d50b5d09d4a |
---|---|
1239 break; | 1239 break; |
1240 } | 1240 } |
1241 } | 1241 } |
1242 /* }}} */ | 1242 /* }}} */ |
1243 | 1243 |
1244 | |
1245 /* static void ggp_recv_image_handler(PurpleConnection *gc, const struct gg_event *ev) {{{ */ | |
1246 static void ggp_recv_image_handler(PurpleConnection *gc, const struct gg_event *ev) | |
1247 { | |
1248 gint imgid = 0; | |
1249 GGPInfo *info = gc->proto_data; | |
1250 GList *entry = g_list_first(info->pending_richtext_messages); | |
1251 gchar *handlerid = g_strdup_printf("IMGID_HANDLER-%i", ev->event.image_reply.crc32); | |
1252 | |
1253 imgid = purple_imgstore_add_with_id( | |
1254 g_memdup(ev->event.image_reply.image, ev->event.image_reply.size), | |
1255 ev->event.image_reply.size, | |
1256 ev->event.image_reply.filename); | |
1257 | |
1258 purple_debug_info("gg", "ggp_recv_image_handler: got image with crc32: %u\n", ev->event.image_reply.crc32); | |
1259 | |
1260 while(entry) { | |
1261 if (strstr((gchar *)entry->data, handlerid) != NULL) { | |
1262 gchar **split = g_strsplit((gchar *)entry->data, handlerid, 3); | |
1263 gchar *text = g_strdup_printf("%s%i%s", split[0], imgid, split[1]); | |
1264 purple_debug_info("gg", "ggp_recv_image_handler: found message matching crc32: %s\n", (gchar *)entry->data); | |
1265 g_strfreev(split); | |
1266 info->pending_richtext_messages = g_list_remove(info->pending_richtext_messages, entry->data); | |
1267 /* We don't have any more images to download */ | |
1268 if (strstr(text, "<IMG ID=\"IMGID_HANDLER") == NULL) { | |
1269 gchar *buf = g_strdup_printf("%lu", (unsigned long int)ev->event.msg.sender); | |
1270 serv_got_im(gc, buf, text, PURPLE_MESSAGE_IMAGES, ev->event.msg.time); | |
1271 g_free(buf); | |
1272 purple_debug_info("gg", "ggp_recv_image_handler: richtext message: %s\n", text); | |
1273 g_free(text); | |
1274 break; | |
1275 } | |
1276 info->pending_richtext_messages = g_list_append(info->pending_richtext_messages, text); | |
1277 break; | |
1278 } | |
1279 entry = g_list_next(entry); | |
1280 } | |
1281 g_free(handlerid); | |
1282 | |
1283 return; | |
1284 } | |
1285 /* }}} */ | |
1286 | |
1287 | |
1244 /** | 1288 /** |
1245 * Dispatch a message received from a buddy. | 1289 * Dispatch a message received from a buddy. |
1246 * | 1290 * |
1247 * @param gc PurpleConnection. | 1291 * @param gc PurpleConnection. |
1248 * @param ev Gadu-Gadu event structure. | 1292 * @param ev Gadu-Gadu event structure. |
1293 * | |
1294 * Image receiving, some code borrowed from Kadu http://www.kadu.net | |
1249 */ | 1295 */ |
1250 /* static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event *ev) {{{ */ | 1296 /* static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event *ev) {{{ */ |
1251 static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event *ev) | 1297 static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event *ev) |
1252 { | 1298 { |
1253 GGPInfo *info = gc->proto_data; | 1299 GGPInfo *info = gc->proto_data; |
1262 "CP1250", "UTF-8"); | 1308 "CP1250", "UTF-8"); |
1263 purple_str_strip_char(tmp, '\r'); | 1309 purple_str_strip_char(tmp, '\r'); |
1264 msg = g_markup_escape_text(tmp, -1); | 1310 msg = g_markup_escape_text(tmp, -1); |
1265 g_free(tmp); | 1311 g_free(tmp); |
1266 | 1312 |
1267 purple_debug_info("gg", "msg form (%s): %s (class = %d; rcpt_count = %d)\n", | 1313 /* We got richtext message */ |
1314 if (ev->event.msg.formats_length) | |
1315 { | |
1316 gboolean got_image = FALSE, bold = FALSE, italic = FALSE, under= FALSE; | |
1317 char *cformats = (char *)ev->event.msg.formats; | |
1318 char *cformats_end = cformats + ev->event.msg.formats_length; | |
1319 gint increased_len = 0; | |
1320 struct gg_msg_richtext_format *actformat; | |
1321 struct gg_msg_richtext_image *actimage; | |
1322 GString *message = g_string_new(msg); | |
1323 gchar *handlerid; | |
1324 | |
1325 purple_debug_info("gg", "ggp_recv_message_handler: richtext msg from (%s): %s %i formats\n", from, msg, ev->event.msg.formats_length); | |
1326 | |
1327 while (cformats < cformats_end) | |
1328 { | |
1329 gint byteoffset; | |
1330 actformat = (struct gg_msg_richtext_format *)cformats; | |
1331 cformats += sizeof(struct gg_msg_richtext_format); | |
1332 byteoffset = g_utf8_offset_to_pointer(message->str, actformat->position + increased_len) - message->str; | |
1333 | |
1334 if(actformat->position == 0 && actformat->font == 0) { | |
1335 purple_debug_warning("gg", "ggp_recv_message_handler: bogus formatting (inc: %i)\n", increased_len); | |
1336 continue; | |
1337 } | |
1338 purple_debug_info("gg", "ggp_recv_message_handler: format at pos: %i, image:%i, bold:%i, italic: %i, under:%i (inc: %i)\n", | |
1339 actformat->position, | |
1340 (actformat->font & GG_FONT_IMAGE) != 0, | |
1341 (actformat->font & GG_FONT_BOLD) != 0, | |
1342 (actformat->font & GG_FONT_ITALIC) != 0, | |
1343 (actformat->font & GG_FONT_UNDERLINE) != 0, | |
1344 increased_len); | |
1345 | |
1346 if (actformat->font & GG_FONT_IMAGE) { | |
1347 got_image = TRUE; | |
1348 actimage = (struct gg_msg_richtext_image*)(cformats); | |
1349 cformats += sizeof(struct gg_msg_richtext_image); | |
1350 purple_debug_info("gg", "ggp_recv_message_handler: image received, size: %d, crc32: %i\n", actimage->size, actimage->crc32); | |
1351 | |
1352 /* Checking for errors, image size shouldn't be | |
1353 * larger than 255.000 bytes */ | |
1354 if (actimage->size > 255000) { | |
1355 purple_debug_warning("gg", "ggp_recv_message_handler: received image large than 255 kb\n"); | |
1356 continue; | |
1357 } | |
1358 | |
1359 gg_image_request(info->session, ev->event.msg.sender, | |
1360 actimage->size, actimage->crc32); | |
1361 | |
1362 handlerid = g_strdup_printf("<IMG ID=\"IMGID_HANDLER-%i\">", actimage->crc32); | |
1363 g_string_insert(message, byteoffset, handlerid); | |
1364 increased_len += strlen(handlerid); | |
1365 g_free(handlerid); | |
1366 continue; | |
1367 } | |
1368 | |
1369 if (actformat->font & GG_FONT_BOLD) { | |
1370 if (bold == FALSE) { | |
1371 g_string_insert(message, byteoffset, "<b>"); | |
1372 increased_len += 3; | |
1373 bold = TRUE; | |
1374 } | |
1375 } else if (bold) { | |
1376 g_string_insert(message, byteoffset, "</b>"); | |
1377 increased_len += 4; | |
1378 bold = FALSE; | |
1379 } | |
1380 | |
1381 if (actformat->font & GG_FONT_ITALIC) { | |
1382 if (italic == FALSE) { | |
1383 g_string_insert(message, byteoffset, "<i>"); | |
1384 increased_len += 3; | |
1385 italic = TRUE; | |
1386 } | |
1387 } else if (italic) { | |
1388 g_string_insert(message, byteoffset, "</i>"); | |
1389 increased_len += 4; | |
1390 italic = FALSE; | |
1391 } | |
1392 | |
1393 if (actformat->font & GG_FONT_UNDERLINE) { | |
1394 if (under == FALSE) { | |
1395 g_string_insert(message, byteoffset, "<u>"); | |
1396 increased_len += 3; | |
1397 under = TRUE; | |
1398 } | |
1399 } else if (under) { | |
1400 g_string_insert(message, byteoffset, "</u>"); | |
1401 increased_len += 4; | |
1402 under = FALSE; | |
1403 } | |
1404 } | |
1405 | |
1406 msg = message->str; | |
1407 g_string_free(message, FALSE); | |
1408 | |
1409 if (got_image) { | |
1410 info->pending_richtext_messages = g_list_append(info->pending_richtext_messages, msg); | |
1411 return; | |
1412 } | |
1413 } | |
1414 | |
1415 purple_debug_info("gg", "ggp_recv_message_handler: msg from (%s): %s (class = %d; rcpt_count = %d)\n", | |
1268 from, msg, ev->event.msg.msgclass, | 1416 from, msg, ev->event.msg.msgclass, |
1269 ev->event.msg.recipients_count); | 1417 ev->event.msg.recipients_count); |
1270 | 1418 |
1271 if (ev->event.msg.recipients_count == 0) { | 1419 if (ev->event.msg.recipients_count == 0) { |
1272 serv_got_im(gc, from, msg, 0, ev->event.msg.time); | 1420 serv_got_im(gc, from, msg, 0, ev->event.msg.time); |
1298 PURPLE_MESSAGE_RECV, msg, ev->event.msg.time); | 1446 PURPLE_MESSAGE_RECV, msg, ev->event.msg.time); |
1299 g_free(buddy_name); | 1447 g_free(buddy_name); |
1300 } | 1448 } |
1301 g_free(msg); | 1449 g_free(msg); |
1302 g_free(from); | 1450 g_free(from); |
1451 } | |
1452 /* }}} */ | |
1453 | |
1454 /* | |
1455 */ | |
1456 /* static void ggp_send_image_handler(PurpleConnection *gc, const struct gg_event *ev) {{{ */ | |
1457 static void ggp_send_image_handler(PurpleConnection *gc, const struct gg_event *ev) | |
1458 { | |
1459 GGPInfo *info = gc->proto_data; | |
1460 PurpleStoredImage *image; | |
1461 gint imgid = (gint) g_hash_table_lookup(info->pending_images, &ev->event.image_request.crc32); | |
1462 | |
1463 purple_debug_info("gg", "ggp_send_image_handler: image request received, crc32: %u\n", ev->event.image_request.crc32); | |
1464 | |
1465 if(imgid) | |
1466 { | |
1467 if((image = purple_imgstore_find_by_id(imgid))) { | |
1468 gint image_size = purple_imgstore_get_size(image); | |
1469 gconstpointer image_bin = purple_imgstore_get_data(image); | |
1470 const char *image_filename = purple_imgstore_get_filename(image); | |
1471 | |
1472 purple_debug_info("gg", "ggp_send_image_handler: sending image imgid: %i, crc: %u\n", imgid, ev->event.image_request.crc32); | |
1473 gg_image_reply(info->session, (unsigned long int)ev->event.image_request.sender, image_filename, image_bin, image_size); | |
1474 purple_imgstore_unref(image); | |
1475 } else { | |
1476 purple_debug_error("gg", "ggp_send_image_handler: image imgid: %i, crc: %u in hash but not found in imgstore!\n", imgid, ev->event.image_request.crc32); | |
1477 } | |
1478 g_hash_table_remove(info->pending_images, &ev->event.image_request.crc32); | |
1479 } | |
1303 } | 1480 } |
1304 /* }}} */ | 1481 /* }}} */ |
1305 | 1482 |
1306 /* | 1483 /* |
1307 */ | 1484 */ |
1328 break; | 1505 break; |
1329 case GG_EVENT_MSG: | 1506 case GG_EVENT_MSG: |
1330 ggp_recv_message_handler(gc, ev); | 1507 ggp_recv_message_handler(gc, ev); |
1331 break; | 1508 break; |
1332 case GG_EVENT_ACK: | 1509 case GG_EVENT_ACK: |
1510 /* Changing %u to %i fixes compiler warning */ | |
1333 purple_debug_info("gg", | 1511 purple_debug_info("gg", |
1334 "message sent to: %u, delivery status=%d, seq=%d\n", | 1512 "ggp_callback_recv: message sent to: %i, delivery status=%d, seq=%d\n", |
1335 ev->event.ack.recipient, ev->event.ack.status, | 1513 ev->event.ack.recipient, ev->event.ack.status, |
1336 ev->event.ack.seq); | 1514 ev->event.ack.seq); |
1515 break; | |
1516 case GG_EVENT_IMAGE_REPLY: | |
1517 ggp_recv_image_handler(gc, ev); | |
1518 break; | |
1519 case GG_EVENT_IMAGE_REQUEST: | |
1520 ggp_send_image_handler(gc, ev); | |
1337 break; | 1521 break; |
1338 case GG_EVENT_NOTIFY: | 1522 case GG_EVENT_NOTIFY: |
1339 case GG_EVENT_NOTIFY_DESCR: | 1523 case GG_EVENT_NOTIFY_DESCR: |
1340 { | 1524 { |
1341 struct gg_notify_reply *n; | 1525 struct gg_notify_reply *n; |
1563 /* static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) {{{ */ | 1747 /* static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) {{{ */ |
1564 static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) | 1748 static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) |
1565 { | 1749 { |
1566 PurpleStatus *status; | 1750 PurpleStatus *status; |
1567 char *text, *tmp; | 1751 char *text, *tmp; |
1568 const char *msg, *name; | 1752 const char *msg, *name, *alias; |
1569 | 1753 |
1570 g_return_if_fail(b != NULL); | 1754 g_return_if_fail(b != NULL); |
1571 | 1755 |
1572 status = purple_presence_get_active_status(purple_buddy_get_presence(b)); | 1756 status = purple_presence_get_active_status(purple_buddy_get_presence(b)); |
1573 msg = purple_status_get_attr_string(status, "message"); | 1757 msg = purple_status_get_attr_string(status, "message"); |
1574 name = purple_status_get_name(status); | 1758 name = purple_status_get_name(status); |
1759 alias = purple_buddy_get_alias(b); | |
1760 | |
1761 purple_notify_user_info_add_pair (user_info, _("Alias"), alias); | |
1575 | 1762 |
1576 if (msg != NULL) { | 1763 if (msg != NULL) { |
1577 text = g_markup_escape_text(msg, -1); | 1764 text = g_markup_escape_text(msg, -1); |
1578 if (PURPLE_BUDDY_IS_ONLINE(b)) { | 1765 if (PURPLE_BUDDY_IS_ONLINE(b)) { |
1579 tmp = g_strdup_printf("%s: %s", name, text); | 1766 tmp = g_strdup_printf("%s: %s", name, text); |
1704 info->session = NULL; | 1891 info->session = NULL; |
1705 info->chats = NULL; | 1892 info->chats = NULL; |
1706 info->chats_count = 0; | 1893 info->chats_count = 0; |
1707 info->token = NULL; | 1894 info->token = NULL; |
1708 info->searches = ggp_search_new(); | 1895 info->searches = ggp_search_new(); |
1896 info->pending_richtext_messages = NULL; | |
1897 info->pending_images = g_hash_table_new(g_int_hash, g_int_equal); | |
1709 | 1898 |
1710 gc->proto_data = info; | 1899 gc->proto_data = info; |
1711 | 1900 |
1712 glp->uin = ggp_get_uin(account); | 1901 glp->uin = ggp_get_uin(account); |
1713 glp->password = (char *)purple_account_get_password(account); | 1902 glp->password = (char *)purple_account_get_password(account); |
1903 glp->image_size = 255; | |
1714 | 1904 |
1715 presence = purple_account_get_presence(account); | 1905 presence = purple_account_get_presence(account); |
1716 status = purple_presence_get_active_status(presence); | 1906 status = purple_presence_get_active_status(presence); |
1717 | 1907 |
1718 glp->async = 1; | 1908 glp->async = 1; |
1758 * upon the contents of info->searches, which we are about to destroy. | 1948 * upon the contents of info->searches, which we are about to destroy. |
1759 */ | 1949 */ |
1760 purple_notify_close_with_handle(gc); | 1950 purple_notify_close_with_handle(gc); |
1761 | 1951 |
1762 ggp_search_destroy(info->searches); | 1952 ggp_search_destroy(info->searches); |
1953 g_list_free(info->pending_richtext_messages); | |
1954 g_hash_table_destroy(info->pending_images); | |
1763 g_free(info); | 1955 g_free(info); |
1764 gc->proto_data = NULL; | 1956 gc->proto_data = NULL; |
1765 } | 1957 } |
1766 | 1958 |
1767 if (gc->inpa > 0) | 1959 if (gc->inpa > 0) |
1777 static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg, | 1969 static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg, |
1778 PurpleMessageFlags flags) | 1970 PurpleMessageFlags flags) |
1779 { | 1971 { |
1780 GGPInfo *info = gc->proto_data; | 1972 GGPInfo *info = gc->proto_data; |
1781 char *tmp, *plain; | 1973 char *tmp, *plain; |
1782 int ret = 0; | 1974 int ret = 1; |
1783 | 1975 unsigned char format[1024]; |
1784 if (strlen(msg) == 0) { | 1976 unsigned int format_length = sizeof(struct gg_msg_richtext); |
1977 gint pos = 0; | |
1978 GData *attribs; | |
1979 const char *start, *end = NULL, *last; | |
1980 | |
1981 if (msg == NULL || *msg == 0) { | |
1785 return 0; | 1982 return 0; |
1786 } | 1983 } |
1787 | 1984 |
1788 purple_debug_info("gg", "ggp_send_im: msg = %s\n", msg); | 1985 last = msg; |
1789 plain = purple_unescape_html(msg); | 1986 |
1987 /* Check if the message is richtext */ | |
1988 /* TODO: Check formatting, too */ | |
1989 if(purple_markup_find_tag("img", last, &start, &end, &attribs)) { | |
1990 | |
1991 GString *string_buffer = g_string_new(NULL); | |
1992 struct gg_msg_richtext fmt; | |
1993 | |
1994 do { | |
1995 PurpleStoredImage *image; | |
1996 const char *id; | |
1997 | |
1998 /* Add text before the image */ | |
1999 if(start - last) { | |
2000 pos = pos + g_utf8_strlen(last, start - last); | |
2001 g_string_append_len(string_buffer, last, start - last); | |
2002 } | |
2003 | |
2004 if((id = g_datalist_get_data(&attribs, "id")) && (image = purple_imgstore_find_by_id(atoi(id)))) { | |
2005 struct gg_msg_richtext_format actformat; | |
2006 struct gg_msg_richtext_image actimage; | |
2007 gint image_size = purple_imgstore_get_size(image); | |
2008 gconstpointer image_bin = purple_imgstore_get_data(image); | |
2009 const char *image_filename = purple_imgstore_get_filename(image); | |
2010 uint32_t crc32 = gg_crc32(0, image_bin, image_size); | |
2011 | |
2012 g_hash_table_insert(info->pending_images, &crc32, (gpointer)atoi(id)); | |
2013 purple_imgstore_ref(image); | |
2014 purple_debug_info("gg", "ggp_send_im_richtext: got crc: %i for imgid: %i\n", crc32, atoi(id)); | |
2015 | |
2016 actformat.font = GG_FONT_IMAGE; | |
2017 actformat.position = pos; | |
2018 | |
2019 actimage.unknown1 = 0x0109; | |
2020 actimage.size = gg_fix32(image_size); | |
2021 actimage.crc32 = gg_fix32(crc32); | |
2022 | |
2023 if (actimage.size > 255000) { | |
2024 purple_debug_warning("gg", "ggp_send_im_richtext: image over 255kb!\n"); | |
2025 continue; | |
2026 } | |
2027 | |
2028 purple_debug_info("gg", "ggp_send_im_richtext: adding images to richtext, size: %i, crc32: %u, name: %s\n", actimage.size, actimage.crc32, image_filename); | |
2029 | |
2030 memcpy(format + format_length, &actformat, sizeof(actformat)); | |
2031 format_length += sizeof(actformat); | |
2032 memcpy(format + format_length, &actimage, sizeof(actimage)); | |
2033 format_length += sizeof(actimage); | |
2034 } else { | |
2035 purple_debug_error("gg", "ggp_send_im_richtext: image not found in the image store!"); | |
2036 } | |
2037 | |
2038 last = end + 1; | |
2039 g_datalist_clear(&attribs); | |
2040 | |
2041 } while(purple_markup_find_tag("img", last, &start, &end, &attribs)); | |
2042 | |
2043 /* Add text after the images */ | |
2044 if(last && *last) { | |
2045 pos = pos + g_utf8_strlen(last, -1); | |
2046 g_string_append(string_buffer, last); | |
2047 } | |
2048 | |
2049 fmt.flag = 2; | |
2050 fmt.length = format_length - sizeof(fmt); | |
2051 memcpy(format, &fmt, sizeof(fmt)); | |
2052 | |
2053 purple_debug_info("gg", "ggp_send_im: richtext msg = %s\n", string_buffer->str); | |
2054 plain = purple_unescape_html(string_buffer->str); | |
2055 g_string_free(string_buffer, TRUE); | |
2056 } else { | |
2057 purple_debug_info("gg", "ggp_send_im: msg = %s\n", msg); | |
2058 plain = purple_unescape_html(msg); | |
2059 } | |
2060 | |
1790 tmp = charset_convert(plain, "UTF-8", "CP1250"); | 2061 tmp = charset_convert(plain, "UTF-8", "CP1250"); |
1791 | 2062 |
1792 if (NULL == tmp || strlen(tmp) == 0) { | 2063 if (tmp && (format_length - sizeof(struct gg_msg_richtext))) { |
2064 if(gg_send_message_richtext(info->session, GG_CLASS_CHAT, ggp_str_to_uin(who), (unsigned char *)tmp, format, format_length) < 0) { | |
2065 ret = -1; | |
2066 } else { | |
2067 ret = 1; | |
2068 } | |
2069 } else if (NULL == tmp || *tmp == 0) { | |
1793 ret = 0; | 2070 ret = 0; |
1794 } else if (strlen(tmp) > GG_MSG_MAXSIZE) { | 2071 } else if (strlen(tmp) > GG_MSG_MAXSIZE) { |
1795 ret = -E2BIG; | 2072 ret = -E2BIG; |
1796 } else if (gg_send_message(info->session, GG_CLASS_CHAT, | 2073 } else if (gg_send_message(info->session, GG_CLASS_CHAT, |
1797 ggp_str_to_uin(who), (unsigned char *)tmp) < 0) { | 2074 ggp_str_to_uin(who), (unsigned char *)tmp) < 0) { |
2101 /* }}} */ | 2378 /* }}} */ |
2102 | 2379 |
2103 /* prpl_info setup {{{ */ | 2380 /* prpl_info setup {{{ */ |
2104 static PurplePluginProtocolInfo prpl_info = | 2381 static PurplePluginProtocolInfo prpl_info = |
2105 { | 2382 { |
2106 OPT_PROTO_REGISTER_NOSCREENNAME, | 2383 OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_IM_IMAGE, |
2107 NULL, /* user_splits */ | 2384 NULL, /* user_splits */ |
2108 NULL, /* protocol_options */ | 2385 NULL, /* protocol_options */ |
2109 {"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ | 2386 {"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ |
2110 ggp_list_icon, /* list_icon */ | 2387 ggp_list_icon, /* list_icon */ |
2111 NULL, /* list_emblem */ | 2388 NULL, /* list_emblem */ |