# HG changeset patch # User Paul Aurich # Date 1250739618 0 # Node ID df76369ffde4828044892c6676bd7420ecd19344 # Parent 9fa1de6d508a53ef47d8a8abc4849e4099a38339# Parent 5ff49aa0543965a0eb952c8b10df7dd01543c00a merge of 'a34b37757cd241377842a2da55e7c7ece45d69dd' and 'e4c44c708110388bc6b4646a63b5749285e0e820' diff -r 9fa1de6d508a -r df76369ffde4 libpurple/protocols/yahoo/util.c --- a/libpurple/protocols/yahoo/util.c Thu Aug 20 03:40:09 2009 +0000 +++ b/libpurple/protocols/yahoo/util.c Thu Aug 20 03:40:18 2009 +0000 @@ -660,7 +660,7 @@ xmlstr2 = g_strndup(xmlstr1 + 6, strlen(xmlstr1) - 13); g_free(xmlstr1); - purple_debug_misc("yahoo", "yahoo_codes_to_html: Returning string: '%s'.\n", xmlstr2); + purple_debug_misc("yahoo", "yahoo_codes_to_html(%s)=%s\n", x, xmlstr2); return xmlstr2; } @@ -669,25 +669,6 @@ #define POINT_SIZE(x) (_point_sizes [MIN ((x > 0 ? x : 1), MAX_FONT_SIZE) - 1]) static const gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 }; -enum fontattr_type -{ - FATYPE_SIZE, - FATYPE_COLOR, - FATYPE_FACE, - FATYPE_JUNK -}; - -typedef struct -{ - enum fontattr_type type; - union { - int size; - char *color; - char *face; - char *junk; - } u; -} fontattr; - typedef struct { gboolean bold; @@ -699,15 +680,6 @@ char *font_color; } CurrentMsgState; -static void fontattr_free(fontattr *f) -{ - if (f->type == FATYPE_COLOR) - g_free(f->u.color); - else if (f->type == FATYPE_FACE) - g_free(f->u.face); - g_free(f); -} - static void yahoo_htc_list_cleanup(GSList *l) { while (l != NULL) { @@ -716,177 +688,74 @@ } } -static void _parse_font_tag(const char *src, GString *dest, int *i, int *j, - int len, GSList **colors, GSList **tags, GQueue *ftattr) +static void parse_font_tag(const char *src, GString *dest, const char *tag_name, const char *tag, + int src_len, GSList **colors, GSList **tags) { - int m, n, vstart; - gboolean quote = FALSE, done = FALSE; + const char *start; + const char *end; + GData *attributes; + const char *attribute; + gboolean needendtag; + GString *tmp; - m = *j; + purple_markup_find_tag(tag_name, tag, &start, &end, &attributes); + + needendtag = FALSE; + tmp = g_string_new(NULL); - while (1) { - m++; + attribute = g_datalist_get_data(&attributes, "color"); + if (attribute != NULL) { + g_string_append(tmp, *colors ? (*colors)->data : "\033[#000000m"); + g_string_append_printf(dest, "\033[%sm", attribute); + *colors = g_slist_prepend(*colors, + g_strdup_printf("\033[%sm", attribute)); + } - if (m >= len) { - g_string_append(dest, &src[*i]); - *i = len; - break; + attribute = g_datalist_get_data(&attributes, "face"); + if (attribute != NULL) { + needendtag = TRUE; + g_string_append(dest, "'))) - done = TRUE; - - if (done) { - if (!g_ascii_strncasecmp(&src[*j+1], "FACE", m - *j - 1)) { - fontattr *f; - - f = g_new(fontattr, 1); - f->type = FATYPE_FACE; - f->u.face = g_strndup(&src[vstart+1], n-vstart-1); - if (!ftattr) - ftattr = g_queue_new(); - g_queue_push_tail(ftattr, f); - m = n; - break; - } else if (!g_ascii_strncasecmp(&src[*j+1], "SIZE", m - *j - 1)) { - fontattr *f; - - f = g_new(fontattr, 1); - f->type = FATYPE_SIZE; - f->u.size = POINT_SIZE(strtol(&src[vstart+1], NULL, 10)); - if (!ftattr) - ftattr = g_queue_new(); - g_queue_push_tail(ftattr, f); - m = n; - break; - } else if (!g_ascii_strncasecmp(&src[*j+1], "COLOR", m - *j - 1)) { - fontattr *f; - - f = g_new(fontattr, 1); - f->type = FATYPE_COLOR; - f->u.color = g_strndup(&src[vstart+1], n-vstart-1); - if (!ftattr) - ftattr = g_queue_new(); - g_queue_push_head(ftattr, f); - m = n; - break; - } else { - fontattr *f; - - f = g_new(fontattr, 1); - f->type = FATYPE_JUNK; - f->u.junk = g_strndup(&src[*j+1], n-*j); - if (!ftattr) - ftattr = g_queue_new(); - g_queue_push_tail(ftattr, f); - m = n; - break; - } + g_string_append_printf(dest, "size=\"%d\" ", + POINT_SIZE(strtol(attribute, NULL, 10))); + } - } - } - } - - if (src[m] == ' ') - *j = m; - - if (src[m] == '>') { - gboolean needendtag = FALSE; - fontattr *f; - GString *tmp = g_string_new(NULL); - - if (!g_queue_is_empty(ftattr)) { - while ((f = g_queue_pop_tail(ftattr))) { - switch (f->type) { - case FATYPE_SIZE: - if (!needendtag) { - needendtag = TRUE; - g_string_append(dest, "u.size); - break; - case FATYPE_FACE: - if (!needendtag) { - needendtag = TRUE; - g_string_append(dest, "u.face); - break; - case FATYPE_JUNK: - if (!needendtag) { - needendtag = TRUE; - g_string_append(dest, "str[dest->len-1] = '>'; + *tags = g_slist_prepend(*tags, g_strdup("")); + g_string_free(tmp, TRUE); + } else { + *tags = g_slist_prepend(*tags, tmp->str); + g_string_free(tmp, FALSE); + } - g_string_append(dest, f->u.junk); - break; - - case FATYPE_COLOR: - if (needendtag) { - g_string_append(tmp, ""); - dest->str[dest->len-1] = '>'; - needendtag = TRUE; - } - - g_string_append(tmp, *colors ? (*colors)->data : "\033[#000000m"); - g_string_append_printf(dest, "\033[%sm", f->u.color); - *colors = g_slist_prepend(*colors, - g_strdup_printf("\033[%sm", f->u.color)); - break; - } - fontattr_free(f); - } - - g_queue_free(ftattr); - ftattr = NULL; - - if (needendtag) { - dest->str[dest->len-1] = '>'; - *tags = g_slist_prepend(*tags, g_strdup("")); - g_string_free(tmp, TRUE); - } else { - *tags = g_slist_prepend(*tags, tmp->str); - g_string_free(tmp, FALSE); - } - } - - *i = *j = m; - break; - } - } + g_datalist_clear(&attributes); } char *yahoo_html_to_codes(const char *src) { GSList *colors = NULL; + + /** + * A stack of char*s where each char* is the string that should be + * appended to dest in order to close all the tags that were opened + * by a tag. + */ GSList *tags = NULL; + size_t src_len; int i, j; GString *dest; char *esc; - GQueue *ftattr = NULL; gboolean no_more_gt_brackets = FALSE; gchar *tag, *tag_name; gboolean is_closing_tag; @@ -929,35 +798,40 @@ tag_name = yahoo_markup_get_tag_name(tag, &is_closing_tag); if (g_str_equal(tag_name, "a")) { - j += 7; - g_string_append(dest, "\033[lm"); - if (purple_str_has_prefix(src + j, "mailto:")) - j += sizeof("mailto:") - 1; - while (1) { - g_string_append_c(dest, src[j]); - if (++j >= src_len) { - i = src_len; - break; - } - if (src[j] == '"') { - g_string_append(dest, "\033[xlm"); - while (1) { - if (++j >= src_len) { - i = src_len; - break; - } - if (!g_ascii_strncasecmp(&src[j], "", 4)) { - j += 3; - break; - } - } - i = j; - break; - } + const char *start; + const char *end; + GData *attributes; + const char *attribute; + + /* + * TODO: Ideally we would replace this: + * Pidgin + * with this: + * Pidgin (http://pidgin.im/) + * + * Currently we drop the text within the tag and + * just show the URL. Doing it the fancy way is + * complicated when dealing with HTML tags within the + * tag. + */ + + /* Append the URL */ + purple_markup_find_tag(tag_name, tag, &start, &end, &attributes); + attribute = g_datalist_get_data(&attributes, "href"); + if (attribute != NULL) { + if (purple_str_has_prefix(attribute, "mailto:")) + attribute += 7; + g_string_append(dest, attribute); } + g_datalist_clear(&attributes); + + /* Skip past the closing tag */ + end = purple_strcasestr(src + j, ""); + if (end != NULL) + j = end - src + 3; } else if (g_str_equal(tag_name, "font")) { - _parse_font_tag(src, dest, &i, &j, src_len, &colors, &tags, ftattr); + parse_font_tag(src, dest, tag_name, tag, src_len, &colors, &tags); } else if (g_str_equal(tag_name, "b")) { g_string_append(dest, "\033[1m"); current_state.bold = TRUE; @@ -983,7 +857,7 @@ current_state.underline = FALSE; } } else if (g_str_equal(tag_name, "/a")) { - g_string_append(dest, "\033[xlm"); + /* Do nothing */ } else if (g_str_equal(tag_name, "br")) { g_string_append_c(dest, '\n'); } else if (g_str_equal(tag_name, "/font")) { @@ -1023,7 +897,7 @@ } esc = g_strescape(dest->str, NULL); - purple_debug_misc("yahoo", "yahoo_html_to_codes: Returning string: '%s'.\n", esc); + purple_debug_misc("yahoo", "yahoo_html_to_codes(%s)=%s\n", src, esc); g_free(esc); yahoo_htc_list_cleanup(colors); diff -r 9fa1de6d508a -r df76369ffde4 libpurple/tests/test_yahoo_util.c --- a/libpurple/tests/test_yahoo_util.c Thu Aug 20 03:40:09 2009 +0000 +++ b/libpurple/tests/test_yahoo_util.c Thu Aug 20 03:40:18 2009 +0000 @@ -142,6 +142,30 @@ yahoo_html_to_codes("bold bolditalic italic")); assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m \x1B[4mitalicunderline\x1B[x4m\x1B[x2m", yahoo_html_to_codes("bold bolditalic italicunderline")); + + /* link */ + assert_string_equal_free("http://pidgin.im/", + yahoo_html_to_codes("http://pidgin.im/")); + assert_string_equal_free("mark@example.com", + yahoo_html_to_codes("mark@example.com")); +#if 0 + assert_string_equal_free("http://pidgin.im/", + yahoo_html_to_codes("Pidgin")); +#endif + + /* font nothing */ + assert_string_equal_free("nothing", + yahoo_html_to_codes("nothing")); + + /* font color */ + assert_string_equal_free("\x1B[#E71414mred\x1B[#000000m", + yahoo_html_to_codes("red")); + + /* font size */ + assert_string_equal_free("test", + yahoo_html_to_codes("test")); + assert_string_equal_free("test", + yahoo_html_to_codes("test")); } END_TEST