Mercurial > pidgin
changeset 28020:df76369ffde4
merge of 'a34b37757cd241377842a2da55e7c7ece45d69dd'
and 'e4c44c708110388bc6b4646a63b5749285e0e820'
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Thu, 20 Aug 2009 03:40:18 +0000 |
parents | 9fa1de6d508a (current diff) 5ff49aa05439 (diff) |
children | a3bcf06057f0 |
files | |
diffstat | 2 files changed, 108 insertions(+), 210 deletions(-) [+] |
line wrap: on
line diff
--- 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, "<font "); + g_string_append_printf(dest, "face=\"%s\" ", attribute); + } + + attribute = g_datalist_get_data(&attributes, "size"); + if (attribute != NULL) { + if (!needendtag) { + needendtag = TRUE; + g_string_append(dest, "<font "); } - if (src[m] == '=') { - n = vstart = m; - while (1) { - n++; - - if (n >= len) { - m = n; - break; - } - - if (src[n] == '"') { - if (!quote) { - quote = TRUE; - vstart = n; - continue; - } else { - done = 1; - } - } - - if (!quote && ((src[n] == ' ') || (src[n] == '>'))) - 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, "<font "); - } - - g_string_append_printf(dest, "size=\"%d\" ", f->u.size); - break; - case FATYPE_FACE: - if (!needendtag) { - needendtag = TRUE; - g_string_append(dest, "<font "); - } - - g_string_append_printf(dest, "face=\"%s\" ", f->u.face); - break; - case FATYPE_JUNK: - if (!needendtag) { - needendtag = TRUE; - g_string_append(dest, "<font "); - } + if (needendtag) { + dest->str[dest->len-1] = '>'; + *tags = g_slist_prepend(*tags, g_strdup("</font>")); + 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, "</font>"); - 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("</font>")); - 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 <font> 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], "</A>", 4)) { - j += 3; - break; - } - } - i = j; - break; - } + const char *start; + const char *end; + GData *attributes; + const char *attribute; + + /* + * TODO: Ideally we would replace this: + * <a href="http://pidgin.im/">Pidgin</a> + * with this: + * Pidgin (http://pidgin.im/) + * + * Currently we drop the text within the <a> tag and + * just show the URL. Doing it the fancy way is + * complicated when dealing with HTML tags within the + * <a> 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 </a> tag */ + end = purple_strcasestr(src + j, "</a>"); + 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);
--- 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("<b>bold <i>bolditalic</i></b><i> italic</i>")); assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m \x1B[4mitalicunderline\x1B[x4m\x1B[x2m", yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>")); + + /* link */ + assert_string_equal_free("http://pidgin.im/", + yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">http://pidgin.im/</A>")); + assert_string_equal_free("mark@example.com", + yahoo_html_to_codes("<A HREF=\"mailto:mark@example.com\">mark@example.com</A>")); +#if 0 + assert_string_equal_free("http://pidgin.im/", + yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">Pidgin</A>")); +#endif + + /* font nothing */ + assert_string_equal_free("nothing", + yahoo_html_to_codes("<font>nothing</font>")); + + /* font color */ + assert_string_equal_free("\x1B[#E71414mred\x1B[#000000m", + yahoo_html_to_codes("<font color=\"#E71414\">red</font>")); + + /* font size */ + assert_string_equal_free("<font size=\"10\">test</font>", + yahoo_html_to_codes("<font size=\"2\">test</font>")); + assert_string_equal_free("<font size=\"30\">test</font>", + yahoo_html_to_codes("<font size=\"6\">test</font>")); } END_TEST