Mercurial > pidgin.yaz
diff src/gtkimhtml.c @ 2856:b1e300a85678
[gaim-migrate @ 2869]
rewrote the html parser in gtkimhtml. yes, that's really all i did. the reason for the massive change is because i added a length argument, which then needed to be propogated down to everything that would ever receive anything that would get drawn to the window.
the new parser isn't any faster. that wasn't my goal. it's much more understandable now (hopefully, anyway).
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Sat, 08 Dec 2001 09:48:52 +0000 |
parents | d00066b2f71a |
children | 450392752988 |
line wrap: on
line diff
--- a/src/gtkimhtml.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/gtkimhtml.c Sat Dec 08 09:48:52 2001 +0000 @@ -36,10 +36,10 @@ #endif #if GTK_CHECK_VERSION(1,3,0) -#define GTK_IMHTML_GET_STYLE_FONT(style) gtk_style_get_font (style) +# define GTK_IMHTML_GET_STYLE_FONT(style) gtk_style_get_font (style) #else -#define GTK_IMHTML_GET_STYLE_FONT(style) (style)->font -#define GTK_CLASS_TYPE(class) (class)->type +# define GTK_IMHTML_GET_STYLE_FONT(style) (style)->font +# define GTK_CLASS_TYPE(class) (class)->type #endif #include "pixmaps/angel.xpm" @@ -289,7 +289,7 @@ GtkIMHtmlBit *bit; }; -struct url_widget { +struct clickable { gint x; gint y; gint width; @@ -327,56 +327,11 @@ imhtml = GTK_IMHTML (object); - while (imhtml->bits) { - GtkIMHtmlBit *bit = imhtml->bits->data; - imhtml->bits = g_list_remove (imhtml->bits, bit); - if (bit->text) - g_free (bit->text); - if (bit->font) - gdk_font_unref (bit->font); - if (bit->fore) - gdk_color_free (bit->fore); - if (bit->back) - gdk_color_free (bit->back); - if (bit->bg) - gdk_color_free (bit->bg); - if (bit->url) - g_free (bit->url); - if (bit->pm) - gdk_pixmap_unref (bit->pm); - if (bit->bm) - gdk_bitmap_unref (bit->bm); - while (bit->chunks) { - struct line_info *li = bit->chunks->data; - if (li->text) - g_free (li->text); - bit->chunks = g_list_remove (bit->chunks, li); - g_free (li); - } - g_free (bit); - } - - if (imhtml->line) - g_list_free (imhtml->line); - - while (imhtml->urls) { - g_free (imhtml->urls->data); - imhtml->urls = g_list_remove (imhtml->urls, imhtml->urls->data); - } + gtk_imhtml_clear (imhtml); if (imhtml->selected_text) g_string_free (imhtml->selected_text, TRUE); - if (imhtml->tip_timer) { - gtk_timeout_remove (imhtml->tip_timer); - imhtml->tip_timer = 0; - } - if (imhtml->tip_window) { - gtk_widget_destroy (imhtml->tip_window); - imhtml->tip_window = NULL; - } - imhtml->tip_bit = NULL; - if (imhtml->default_font) gdk_font_unref (imhtml->default_font); if (imhtml->default_fg_color) @@ -831,9 +786,9 @@ g_list_free (imhtml->line); imhtml->line = NULL; - while (imhtml->urls) { - g_free (imhtml->urls->data); - imhtml->urls = g_list_remove (imhtml->urls, imhtml->urls->data); + while (imhtml->click) { + g_free (imhtml->click->data); + imhtml->click = g_list_remove (imhtml->click, imhtml->click->data); } imhtml->x = 0; @@ -1454,11 +1409,11 @@ gtk_imhtml_select_in_chunk (imhtml, chunk); } } else { - GList *urls = imhtml->urls; - struct url_widget *uw; - - while (urls) { - uw = (struct url_widget *) urls->data; + GList *click = imhtml->click; + struct clickable *uw; + + while (click) { + uw = (struct clickable *) click->data; if ((x > uw->x) && (x < uw->x + uw->width) && (y > uw->y) && (y < uw->y + uw->height)) { if (imhtml->tip_bit != uw->bit) { @@ -1477,7 +1432,7 @@ imhtml->hand_cursor); return TRUE; } - urls = g_list_next (urls); + click = g_list_next (click); } } @@ -1519,7 +1474,7 @@ menu_open_url (GtkObject *object, gpointer data) { - struct url_widget *uw = data; + struct clickable *uw = data; gtk_signal_emit (GTK_OBJECT (uw->imhtml), signals [URL_CLICKED], uw->bit->url); } @@ -1528,7 +1483,7 @@ menu_copy_link (GtkObject *object, gpointer data) { - struct url_widget *uw = data; + struct clickable *uw = data; GtkIMHtml *imhtml = uw->imhtml; if (imhtml->selected_text) @@ -1562,29 +1517,31 @@ } if (event->button == 3) { - GList *urls = imhtml->urls; - struct url_widget *uw; - - while (urls) { - uw = urls->data; + GList *click = imhtml->click; + struct clickable *uw; + + while (click) { + uw = click->data; if ((x > uw->x) && (x < uw->x + uw->width) && (y > uw->y) && (y < uw->y + uw->height)) { GtkWidget *menu = gtk_menu_new (); - - GtkWidget *button = gtk_menu_item_new_with_label ("Open URL"); - gtk_signal_connect (GTK_OBJECT (button), "activate", - GTK_SIGNAL_FUNC (menu_open_url), uw); - gtk_menu_append (GTK_MENU (menu), button); - gtk_widget_show (button); - - button = gtk_menu_item_new_with_label ("Copy Link Location"); - gtk_signal_connect (GTK_OBJECT (button), "activate", - GTK_SIGNAL_FUNC (menu_copy_link), uw); - gtk_menu_append (GTK_MENU (menu), button); - gtk_widget_show (button); - - gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, - 3, event->time); + GtkWidget *button; + + if (uw->bit->url) { + button = gtk_menu_item_new_with_label ("Open URL"); + gtk_signal_connect (GTK_OBJECT (button), "activate", + GTK_SIGNAL_FUNC (menu_open_url), uw); + gtk_menu_append (GTK_MENU (menu), button); + gtk_widget_show (button); + + button = gtk_menu_item_new_with_label ("Copy Link Location"); + gtk_signal_connect (GTK_OBJECT (button), "activate", + GTK_SIGNAL_FUNC (menu_copy_link), uw); + gtk_menu_append (GTK_MENU (menu), button); + gtk_widget_show (button); + } + + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, event->time); if (imhtml->tip_timer) { gtk_timeout_remove (imhtml->tip_timer); @@ -1598,7 +1555,7 @@ return TRUE; } - urls = g_list_next (urls); + click = g_list_next (click); } } @@ -1632,18 +1589,18 @@ } if ((event->button == 1) && (imhtml->sel_startx == 0)) { - GList *urls = imhtml->urls; - struct url_widget *uw; - - while (urls) { - uw = (struct url_widget *) urls->data; + GList *click = imhtml->click; + struct clickable *uw; + + while (click) { + uw = (struct clickable *) click->data; if ((x > uw->x) && (x < uw->x + uw->width) && (y > uw->y) && (y < uw->y + uw->height)) { gtk_signal_emit (GTK_OBJECT (imhtml), signals [URL_CLICKED], uw->bit->url); return TRUE; } - urls = g_list_next (urls); + click = g_list_next (click); } } @@ -2092,7 +2049,7 @@ gtk_imhtml_set_adjustments (imhtml, hadj, vadj); imhtml->bits = NULL; - imhtml->urls = NULL; + imhtml->click = NULL; imhtml->x = 0; imhtml->y = TOP_BORDER; @@ -2222,7 +2179,7 @@ gint diff; GList *ls = NULL; struct line_info *li; - struct url_widget *uw; + struct clickable *uw; if (height > imhtml->llheight) { diff = height - imhtml->llheight; @@ -2238,7 +2195,7 @@ ls = g_list_next (ls); } - ls = imhtml->urls; + ls = imhtml->click; while (ls) { uw = ls->data; if (uw->y + diff > imhtml->y) @@ -2260,7 +2217,7 @@ gchar *text) { struct line_info *li; - struct url_widget *uw; + struct clickable *uw; gint width; if (text) @@ -2281,14 +2238,14 @@ li->bit = bit; if (bit->url) { - uw = g_new0 (struct url_widget, 1); + uw = g_new0 (struct clickable, 1); uw->x = imhtml->x; uw->y = imhtml->y; uw->width = width; uw->height = imhtml->llheight; uw->imhtml = imhtml; uw->bit = bit; - imhtml->urls = g_list_append (imhtml->urls, uw); + imhtml->click = g_list_append (imhtml->click, uw); } bit->chunks = g_list_append (bit->chunks, li); @@ -2300,7 +2257,7 @@ GtkIMHtmlBit *bit) { struct line_info *li; - struct url_widget *uw; + struct clickable *uw; gint width; gdk_window_get_size (bit->pm, &width, NULL); @@ -2314,14 +2271,14 @@ li->bit = bit; if (bit->url) { - uw = g_new0 (struct url_widget, 1); + uw = g_new0 (struct clickable, 1); uw->x = imhtml->x; uw->y = imhtml->y; uw->width = width; uw->height = imhtml->llheight; uw->imhtml = imhtml; uw->bit = bit; - imhtml->urls = g_list_append (imhtml->urls, uw); + imhtml->click = g_list_append (imhtml->click, uw); } bit->chunks = g_list_append (bit->chunks, li); @@ -2482,11 +2439,13 @@ return gdk_color_copy (&c); } -static gint +static gboolean gtk_imhtml_is_smiley (GtkIMHtml *imhtml, - const gchar *text) + const gchar *text, + gint *len) { - return gtk_smiley_tree_lookup (imhtml->smiley_data, text); + *len = gtk_smiley_tree_lookup (imhtml->smiley_data, text); + return (*len > 0); } static GtkIMHtmlBit * @@ -2500,7 +2459,9 @@ FontDetail *font, GdkColor *bg, gchar *url, - gint pre) + gint pre, + gint sub, + gint sup) { GtkIMHtmlBit *bit = NULL; @@ -2571,17 +2532,19 @@ } #define NEW_TEXT_BIT gtk_imhtml_new_bit (imhtml, TYPE_TEXT, ws, bold, italics, underline, strike, \ - fonts ? fonts->data : NULL, bg, url, pre) + fonts ? fonts->data : NULL, bg, url, pre, sub, sup) #define NEW_SMILEY_BIT gtk_imhtml_new_bit (imhtml, TYPE_SMILEY, ws, bold, italics, underline, strike, \ - fonts ? fonts->data : NULL, bg, url, pre) -#define NEW_SEP_BIT gtk_imhtml_new_bit (imhtml, TYPE_SEP, NULL, 0, 0, 0, 0, NULL, bg, NULL, 0) + fonts ? fonts->data : NULL, bg, url, pre, sub, sup) +#define NEW_SEP_BIT gtk_imhtml_new_bit (imhtml, TYPE_SEP, NULL, 0, 0, 0, 0, NULL, bg, NULL, 0, 0, 0) #define NEW_BR_BIT gtk_imhtml_new_bit (imhtml, TYPE_BR, NULL, 0, 0, 0, 0, \ - fonts ? fonts->data : NULL, bg, NULL, 0) + fonts ? fonts->data : NULL, bg, NULL, 0, 0, 0) #define NEW_COMMENT_BIT gtk_imhtml_new_bit (imhtml, TYPE_COMMENT, ws, bold, italics, underline, strike, \ - fonts ? fonts->data : NULL, bg, url, pre) - -#define NEW_BIT(bit) { GtkIMHtmlBit *tmp = bit; if (tmp != NULL) \ - newbits = g_list_append (newbits, tmp); } + fonts ? fonts->data : NULL, bg, url, pre, sub, sup) + +#define NEW_BIT(bit) ws [wpos] = '\0'; \ + { GtkIMHtmlBit *tmp = bit; if (tmp != NULL) \ + newbits = g_list_append (newbits, tmp); } \ + wpos = 0; ws [wpos] = '\0' #define UPDATE_BG_COLORS \ { \ @@ -2614,9 +2577,9 @@ } static gboolean -is_amp_escape (const gchar *string, - gchar *replace, - gint *length) +gtk_imhtml_is_amp_escape (const gchar *string, + gchar *replace, + gint *length) { g_return_val_if_fail (string != NULL, FALSE); g_return_val_if_fail (replace != NULL, FALSE); @@ -2662,20 +2625,169 @@ return TRUE; } +#define VALID_TAG(x) if (!g_strncasecmp (string, x ">", strlen (x ">"))) { \ + *tag = g_strndup (string, strlen (x)); \ + *len = strlen (x) + 1; \ + return TRUE; \ + } \ + (*type)++ + +#define VALID_OPT_TAG(x) if (!g_strncasecmp (string, x " ", strlen (x " "))) { \ + const gchar *c = string + strlen (x " "); \ + gchar e = '"'; \ + gboolean quote = FALSE; \ + while (*c) { \ + if (*c == '"' || *c == '\'') { \ + if (quote && (*c == e)) \ + quote = !quote; \ + else if (!quote) { \ + quote = !quote; \ + e = *c; \ + } \ + } else if (!quote && (*c == '>')) \ + break; \ + c++; \ + } \ + if (*c) { \ + *tag = g_strndup (string, c - string); \ + *len = c - string + 1; \ + return TRUE; \ + } \ + } \ + (*type)++ + +static gboolean +gtk_imhtml_is_tag (const gchar *string, + gchar **tag, + gint *len, + gint *type) +{ + *type = 1; + + if (!strchr (string, '>')) + return FALSE; + + VALID_TAG ("B"); + VALID_TAG ("BOLD"); + VALID_TAG ("/B"); + VALID_TAG ("/BOLD"); + VALID_TAG ("I"); + VALID_TAG ("ITALIC"); + VALID_TAG ("/I"); + VALID_TAG ("/ITALIC"); + VALID_TAG ("U"); + VALID_TAG ("UNDERLINE"); + VALID_TAG ("/U"); + VALID_TAG ("/UNDERLINE"); + VALID_TAG ("S"); + VALID_TAG ("STRIKE"); + VALID_TAG ("/S"); + VALID_TAG ("/STRIKE"); + VALID_TAG ("SUB"); + VALID_TAG ("/SUB"); + VALID_TAG ("SUP"); + VALID_TAG ("/SUP"); + VALID_TAG ("PRE"); + VALID_TAG ("/PRE"); + VALID_TAG ("TITLE"); + VALID_TAG ("/TITLE"); + VALID_TAG ("BR"); + VALID_TAG ("HR"); + VALID_TAG ("/FONT"); + VALID_TAG ("/A"); + VALID_TAG ("P"); + VALID_TAG ("/P"); + VALID_TAG ("H3"); + VALID_TAG ("/H3"); + VALID_TAG ("HTML"); + VALID_TAG ("/HTML"); + VALID_TAG ("BODY"); + VALID_TAG ("/BODY"); + VALID_TAG ("FONT"); + VALID_TAG ("HEAD"); + VALID_TAG ("HEAD"); + + VALID_OPT_TAG ("HR"); + VALID_OPT_TAG ("FONT"); + VALID_OPT_TAG ("BODY"); + VALID_OPT_TAG ("A"); + VALID_OPT_TAG ("IMG"); + VALID_OPT_TAG ("P"); + VALID_OPT_TAG ("H3"); + + if (!g_strncasecmp(string, "!--", strlen ("!--"))) { + gchar *e = strstr (string, "-->"); + if (e) { + *len = e - string + strlen ("-->"); + *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); + return TRUE; + } + } + + return FALSE; +} + +static gchar* +gtk_imhtml_get_html_opt (gchar *tag, + const gchar *opt) +{ + gchar *t = tag; + gchar *e, *a; + + while (g_strncasecmp (t, opt, strlen (opt))) { + gboolean quote = FALSE; + if (*t == '\0') break; + while (*t && !((*t == ' ') && !quote)) { + if (*t == '\"') + quote = ! quote; + t++; + } + while (*t && (*t == ' ')) t++; + } + + if (!g_strncasecmp (t, opt, strlen (opt))) { + t += strlen (opt); + } else { + return NULL; + } + + if ((*t == '\"') || (*t == '\'')) { + e = a = ++t; + while (*e && (*e != *(t - 1))) e++; + if (*e != '\0') { + *e = '\0'; + return g_strdup (a); + } else { + return NULL; + } + } else { + e = a = t; + while (*e && !isspace ((gint) *e)) e++; + *e = '\0'; + return g_strdup (a); + } +} + GString* gtk_imhtml_append_text (GtkIMHtml *imhtml, const gchar *text, + gint len, GtkIMHtmlOptions options) { const gchar *c; - gboolean intag = FALSE; - gint tagquote = 0; - gboolean incomment = FALSE; + gboolean binary = TRUE; gchar *ws; - gchar *tag; + gint pos = 0; gint wpos = 0; - gint tpos = 0; + + gchar *tag; + gint tlen; + gint type; + + gchar amp; + int smilelen; + GList *newbits = NULL; guint bold = 0, @@ -2708,345 +2820,184 @@ scrolldown = FALSE; c = text; - ws = g_malloc (strlen (text) + 1); - tag = g_malloc (strlen (text) + 1); - + if (len == -1) { + binary = FALSE; + len = strlen (text); + } + + ws = g_malloc (len + 1); ws [0] = '\0'; - while (*c) { - if (*c == '<') { - if (intag && (tagquote != 1)) { - char *d; - tag [tpos] = 0; - d = tag; - while (*d) { - if ((smilelen = gtk_imhtml_is_smiley (imhtml, d)) != 0) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - g_snprintf (ws, smilelen + 1, "%s", d); - NEW_BIT (NEW_SMILEY_BIT); - d += smilelen; - } else if (*d == '&') { - gchar replace; - gint length; - if (is_amp_escape (d, &replace, &length)) { - ws [wpos++] = replace; - d += length; - } else { - ws [wpos++] = *d++; - } - } else if (*d == '\n') { - if (!(options & GTK_IMHTML_NO_NEWLINE)) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_BR_BIT); - } - d++; - } else { - ws [wpos++] = *d++; - } - } - tpos = 0; - } - - if (incomment) { - ws [wpos++] = *c++; - continue; - } - - if (!g_strncasecmp (c, "<!--", strlen ("<!--"))) { - if (!(options & GTK_IMHTML_NO_COMMENTS)) { - ws [wpos] = 0; - wpos = 0; - tag [tpos] = 0; - strcat (tag, ws); - incomment = TRUE; - intag = FALSE; - } - ws [wpos++] = *c++; - ws [wpos++] = *c++; - ws [wpos++] = *c++; - ws [wpos++] = *c++; - continue; - } - - tag [tpos++] = *c++; - intag = TRUE; - tagquote = 0; - } else if (incomment && (*c == '-') && !g_strncasecmp (c, "-->", strlen ("-->"))) { - gchar *tmp; - ws [wpos] = 0; - wpos = 0; - tmp = g_strdup (ws); - ws [wpos] = 0; - strcat (ws, tag); - NEW_BIT (NEW_TEXT_BIT); - ws [wpos] = 0; - strcat (ws, tmp + strlen ("<!--")); - g_free (tmp); - NEW_BIT (NEW_COMMENT_BIT); - incomment = FALSE; - c += strlen ("-->"); - } else if (*c == '>' && intag && (tagquote != 1)) { - gboolean got_tag = FALSE; - tag [tpos++] = *c++; - tag [tpos] = 0; - ws [wpos] = 0; - - if (!g_strcasecmp (tag, "<B>") || !g_strcasecmp (tag, "<BOLD>")) { - got_tag = TRUE; + while (pos < len) { + if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { + c++; + pos++; + switch (type) { + case 1: /* B */ + case 2: /* BOLD */ NEW_BIT (NEW_TEXT_BIT); bold++; - } else if (!g_strcasecmp (tag, "</B>") || !g_strcasecmp (tag, "</BOLD>")) { - got_tag = TRUE; + break; + case 3: /* /B */ + case 4: /* /BOLD */ NEW_BIT (NEW_TEXT_BIT); - if (bold) { + if (bold) bold--; - } - } else if (!g_strcasecmp (tag, "<I>") || !g_strcasecmp (tag, "<ITALIC>")) { - got_tag = TRUE; + break; + case 5: /* I */ + case 6: /* ITALIC */ NEW_BIT (NEW_TEXT_BIT); italics++; - } else if (!g_strcasecmp (tag, "</I>") || !g_strcasecmp (tag, "</ITALIC>")) { - got_tag = TRUE; + break; + case 7: /* /I */ + case 8: /* /ITALIC */ NEW_BIT (NEW_TEXT_BIT); - if (italics) { + if (italics) italics--; - } - } else if (!g_strcasecmp (tag, "<U>") || !g_strcasecmp (tag, "<UNDERLINE>")) { - got_tag = TRUE; + break; + case 9: /* U */ + case 10: /* UNDERLINE */ NEW_BIT (NEW_TEXT_BIT); underline++; - } else if (!g_strcasecmp (tag, "</U>") || !g_strcasecmp (tag, "</UNDERLINE>")) { - got_tag = TRUE; + break; + case 11: /* /U */ + case 12: /* /UNDERLINE */ NEW_BIT (NEW_TEXT_BIT); - if (underline) { + if (underline) underline--; - } - } else if (!g_strcasecmp (tag, "<S>") || !g_strcasecmp (tag, "<STRIKE>")) { - got_tag = TRUE; + break; + case 13: /* S */ + case 14: /* STRIKE */ NEW_BIT (NEW_TEXT_BIT); strike++; - } else if (!g_strcasecmp (tag, "</S>") || !g_strcasecmp (tag, "</STRIKE>")) { - got_tag = TRUE; + break; + case 15: /* /S */ + case 16: /* /STRIKE */ NEW_BIT (NEW_TEXT_BIT); - if (strike) { + if (strike) strike--; - } - } else if (!g_strcasecmp (tag, "<SUB>")) { - got_tag = TRUE; + break; + case 17: /* SUB */ NEW_BIT (NEW_TEXT_BIT); sub++; - } else if (!g_strcasecmp (tag, "</SUB>")) { - got_tag = TRUE; + break; + case 18: /* /SUB */ NEW_BIT (NEW_TEXT_BIT); - if (sub) { + if (sub) sub--; - } - } else if (!g_strcasecmp (tag, "<SUP>")) { - got_tag = TRUE; + break; + case 19: /* SUP */ NEW_BIT (NEW_TEXT_BIT); sup++; - } else if (!g_strcasecmp (tag, "</SUP>")) { - got_tag = TRUE; + break; + case 20: /* /SUP */ NEW_BIT (NEW_TEXT_BIT); - if (sup) { + if (sup) sup--; - } - } else if (!g_strcasecmp (tag, "<PRE>")) { - got_tag = TRUE; + break; + case 21: /* PRE */ NEW_BIT (NEW_TEXT_BIT); pre++; - } else if (!g_strcasecmp (tag, "</PRE>")) { - got_tag = TRUE; + break; + case 22: /* /PRE */ + NEW_BIT (NEW_TEXT_BIT); + if (pre) + pre--; + break; + case 23: /* TITLE */ NEW_BIT (NEW_TEXT_BIT); - if (pre) { - pre--; + title++; + break; + case 24: /* /TITLE */ + if (title) { + if (options & GTK_IMHTML_NO_TITLE) { + wpos = 0; + ws [wpos] = '\0'; + } + title--; } - } else if (!g_strcasecmp (tag, "<TITLE>")) { - if (options & GTK_IMHTML_NO_TITLE) { - got_tag = TRUE; - NEW_BIT (NEW_TEXT_BIT); - title++; - } else { - intag = FALSE; - tpos = 0; - continue; - } - } else if (!g_strcasecmp (tag, "</TITLE>")) { - if (title) { - got_tag = TRUE; - wpos = 0; - ws [wpos] = '\0'; - title--; - } else { - intag = FALSE; - tpos = 0; - continue; - } - } else if (!g_strcasecmp (tag, "<BR>")) { - got_tag = TRUE; + break; + case 25: /* BR */ NEW_BIT (NEW_TEXT_BIT); NEW_BIT (NEW_BR_BIT); - } else if (!g_strcasecmp (tag, "<HR>") || - !g_strncasecmp (tag, "<HR ", strlen ("<HR "))) { - got_tag = TRUE; + break; + case 26: /* HR */ NEW_BIT (NEW_TEXT_BIT); NEW_BIT (NEW_SEP_BIT); - } else if (!g_strncasecmp (tag, "<FONT ", strlen ("<FONT "))) { - gchar *t, *e, *a, *value; - FontDetail *font = NULL; - GdkColor *clr; - gint saw; - gint i; - - t = tag + strlen ("<FONT "); - - while (*t != '\0') { - value = NULL; - saw = 0; - - while (g_strncasecmp (t, "COLOR=", strlen ("COLOR=")) - && g_strncasecmp (t, "BACK=", strlen ("BACK=")) - && g_strncasecmp (t, "FACE=", strlen ("FACE=")) - && g_strncasecmp (t, "SIZE=", strlen ("SIZE="))) { - gboolean quote = FALSE; - if (*t == '\0') break; - while (*t && !((*t == ' ') && !quote)) { - if (*t == '\"') - quote = ! quote; - t++; - } - while (*t && (*t == ' ')) t++; - } - - if (!g_strncasecmp (t, "COLOR=", strlen ("COLOR="))) { - t += strlen ("COLOR="); - saw = 1; - } else if (!g_strncasecmp (t, "BACK=", strlen ("BACK="))) { - t += strlen ("BACK="); - saw = 2; - } else if (!g_strncasecmp (t, "FACE=", strlen ("FACE="))) { - t += strlen ("FACE="); - saw = 3; - } else if (!g_strncasecmp (t, "SIZE=", strlen ("SIZE="))) { - t += strlen ("SIZE="); - saw = 4; - } - - if (!saw) - continue; - - if ((*t == '\"') || (*t == '\'')) { - e = a = ++t; - while (*e && (*e != *(t - 1))) e++; - if (*e != '\0') { - *e = '\0'; - t = e + 1; - value = g_strdup (a); - } else { - *t = '\0'; - } - } else { - e = a = t; - while (*e && !isspace ((gint) *e)) e++; - if (*e == '\0') e--; - *e = '\0'; - t = e + 1; - value = g_strdup (a); - } - - if (value == NULL) - continue; - - if (font == NULL) - font = g_new0 (FontDetail, 1); - - switch (saw) { - case 1: - clr = gtk_imhtml_get_color (value); - if (clr != NULL) { - if ( (font->fore == NULL) && - !(options & GTK_IMHTML_NO_COLOURS)) - font->fore = clr; - } - break; - case 2: - clr = gtk_imhtml_get_color (value); - if (clr != NULL) { - if ( (font->back == NULL) && - !(options & GTK_IMHTML_NO_COLOURS)) - font->back = clr; - } - break; - case 3: - if ( (font->face == NULL) && - !(options & GTK_IMHTML_NO_FONTS)) - font->face = g_strdup (value); - break; - case 4: - if ((font->size != 0) || - (options & GTK_IMHTML_NO_SIZES)) - break; - - if (isdigit ((gint) value [0])) { - for (i = 0; i < strlen (value); i++) - if (!isdigit ((gint) value [i])) - break; - if (i != strlen (value)) - break; - - sscanf (value, "%hd", &font->size); - break; - } - - if ((value [0] == '+') && (value [1] != '\0')) { - for (i = 1; i < strlen (value); i++) - if (!isdigit ((gint) value [i])) - break; - if (i != strlen (value)) - break; - - sscanf (value + 1, "%hd", &font->size); - font->size += DEFAULT_FONT_SIZE; - break; - } - - if ((value [0] == '-') && (value [1] != '\0')) { - for (i = 1; i < strlen (value); i++) - if (!isdigit ((gint) value [i])) - break; - if (i != strlen (value)) - break; - - sscanf (value + 1, "%hd", &font->size); - font->size = MIN (font->size, 2); - font->size = DEFAULT_FONT_SIZE - font->size; - break; - } - - break; - } - - g_free (value); + break; + case 27: /* /FONT */ + if (fonts) { + FontDetail *font = fonts->data; + NEW_BIT (NEW_TEXT_BIT); + fonts = g_slist_remove (fonts, font); + if (font->face) + g_free (font->face); + if (font->fore) + gdk_color_free (font->fore); + if (font->back) + gdk_color_free (font->back); + g_free (font); + } + break; + case 28: /* /A */ + if (url) { + NEW_BIT (NEW_TEXT_BIT); + g_free (url); + url = NULL; } - - if (!font || !(font->size || font->face || font->fore || font->back)) { - g_free (font); - intag = FALSE; - tpos = 0; - continue; - } + break; + case 29: /* P */ + case 30: /* /P */ + case 31: /* H3 */ + case 32: /* /H3 */ + case 33: /* HTML */ + case 34: /* /HTML */ + case 35: /* BODY */ + case 36: /* /BODY */ + case 37: /* FONT */ + case 38: /* HEAD */ + case 39: /* /HEAD */ + break; + + case 40: /* HR (opt) */ + NEW_BIT (NEW_TEXT_BIT); + NEW_BIT (NEW_SEP_BIT); + break; + case 41: /* FONT (opt) */ + { + gchar *color, *back, *face, *size; + FontDetail *font; + + color = gtk_imhtml_get_html_opt (tag, "COLOR="); + back = gtk_imhtml_get_html_opt (tag, "BACK="); + face = gtk_imhtml_get_html_opt (tag, "FACE="); + size = gtk_imhtml_get_html_opt (tag, "SIZE="); + + if (!(color || back || face || size)) + break; NEW_BIT (NEW_TEXT_BIT); + font = g_new0 (FontDetail, 1); + if (color && !(options & GTK_IMHTML_NO_COLOURS)) + font->fore = gtk_imhtml_get_color (color); + if (back && !(options & GTK_IMHTML_NO_COLOURS)) + font->back = gtk_imhtml_get_color (back); + if (face && !(options & GTK_IMHTML_NO_FONTS)) + font->face = g_strdup (face); + if (size && !(options & GTK_IMHTML_NO_SIZES)) + sscanf (size, "%hd", &font->size); + + g_free (color); + g_free (back); + g_free (face); + g_free (size); + if (fonts) { FontDetail *oldfont = fonts->data; if (!font->size) font->size = oldfont->size; - if (!font->face && oldfont->face) + if (!font->face && oldfont->face) font->face = g_strdup (oldfont->face); if (!font->fore && oldfont->fore) font->fore = gdk_color_copy (oldfont->fore); @@ -3058,192 +3009,47 @@ } fonts = g_slist_prepend (fonts, font); - got_tag = TRUE; - } else if (!g_strcasecmp (tag, "</FONT>")) { - FontDetail *font; - - if (fonts) { - got_tag = TRUE; - NEW_BIT (NEW_TEXT_BIT); - font = fonts->data; - fonts = g_slist_remove (fonts, font); - if (font->face) - g_free (font->face); - if (font->fore) - gdk_color_free (font->fore); - if (font->back) - gdk_color_free (font->back); - g_free (font); - } else { - intag = FALSE; - tpos = 0; - continue; - } - } else if (!g_strncasecmp (tag, "<BODY ", strlen ("<BODY "))) { - gchar *t, *e, *color = NULL; - GdkColor *tmp; - - got_tag = TRUE; - - if (!(options & GTK_IMHTML_NO_COLOURS)) { - t = tag + strlen ("<BODY"); - do { - gboolean quote = FALSE; - if (*t == '\0') break; - while (*t && !((*t == ' ') && !quote)) { - if (*t == '\"') - quote = ! quote; - t++; - } - while (*t && (*t == ' ')) t++; - } while (g_strncasecmp (t, "BGCOLOR=", strlen ("BGCOLOR="))); - - if (!g_strncasecmp (t, "BGCOLOR=", strlen ("BGCOLOR="))) { - t += strlen ("BGCOLOR="); - if ((*t == '\"') || (*t == '\'')) { - e = ++t; - while (*e && (*e != *(t - 1))) e++; - if (*e != '\0') { - *e = '\0'; - color = g_strdup (t); - } - } else { - e = t; - while (*e && !isspace ((gint) *e)) e++; - if (*e == '\0') e--; - *e = '\0'; - color = g_strdup (t); - } - - if (color != NULL) { - tmp = gtk_imhtml_get_color (color); - g_free (color); - if (tmp != NULL) { - NEW_BIT (NEW_TEXT_BIT); - bg = tmp; - UPDATE_BG_COLORS; - } - } + } + break; + case 42: /* BODY (opt) */ + { + gchar *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); + if (bgcolor) { + GdkColor *tmp = gtk_imhtml_get_color (bgcolor); + g_free (bgcolor); + if (tmp) { + NEW_BIT (NEW_TEXT_BIT); + bg = tmp; + UPDATE_BG_COLORS; } } - } else if (!g_strncasecmp (tag, "<A ", strlen ("<A "))) { - gchar *t, *e; - - got_tag = TRUE; - NEW_BIT (NEW_TEXT_BIT); - - if (url != NULL) - g_free (url); - url = NULL; - - t = tag + strlen ("<A"); - do { - gboolean quote = FALSE; - if (*t == '\0') break; - while (*t && !((*t == ' ') && !quote)) { - if (*t == '\"') - quote = ! quote; - t++; - } - while (*t && (*t == ' ')) t++; - } while (g_strncasecmp (t, "HREF=", strlen ("HREF="))); - - if (!g_strncasecmp (t, "HREF=", strlen ("HREF="))) { - t += strlen ("HREF="); - if ((*t == '\"') || (*t == '\'')) { - e = ++t; - while (*e && (*e != *(t - 1))) e++; - if (*e != '\0') { - *e = '\0'; - url = g_strdup (t); - } - } else { - e = t; - while (*e && !isspace ((gint) *e)) e++; - if (*e == '\0') e--; - *e = '\0'; - url = g_strdup (t); - } - } - } else if (!g_strcasecmp (tag, "</A>")) { - if (url != NULL) { - got_tag = TRUE; + } + break; + case 43: /* A (opt) */ + { + gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); + if (href) { NEW_BIT (NEW_TEXT_BIT); g_free (url); - url = NULL; - } else { - intag = FALSE; - tpos = 0; - continue; - } - } else if (!g_strncasecmp (tag, "<IMG ", strlen ("<IMG "))) { - gchar *t, *e, *src = NULL; - gchar *copy = g_strdup (tag); - gchar **xpm; - GdkColor *clr = NULL; - GtkIMHtmlBit *bit; - - intag = FALSE; - tpos = 0; - - if (imhtml->img == NULL) { - ws [wpos] = 0; - strcat (ws, copy); - wpos = strlen (ws); - g_free (copy); - continue; + url = href; } - - t = tag + strlen ("<IMG"); - do { - gboolean quote = FALSE; - if (*t == '\0') break; - while (*t && !((*t == ' ') && !quote)) { - if (*t == '\"') - quote = ! quote; - t++; - } - while (*t && (*t == ' ')) t++; - } while (g_strncasecmp (t, "SRC=", strlen ("SRC="))); - - if (!g_strncasecmp (t, "SRC=", strlen ("SRC="))) { - t += strlen ("SRC="); - if ((*t == '\"') || (*t == '\'')) { - e = ++t; - while (*e && (*e != *(t - 1))) e++; - if (*e != '\0') { - *e = '\0'; - src = g_strdup (t); - } - } else { - e = t; - while (*e && !isspace ((gint) *e)) e++; - if (*e == '\0') e--; - *e = '\0'; - src = g_strdup (t); - } + } + break; + case 44: /* IMG (opt) */ + { + gchar *src = gtk_imhtml_get_html_opt (tag, "SRC="); + gchar **xpm; + GdkColor *clr; + GtkIMHtmlBit *bit; + + if (!src) + break; + + if (!imhtml->img || ((xpm = imhtml->img (src)) == NULL)) { + g_free (src); + break; } - if (src == NULL) { - ws [wpos] = 0; - strcat (ws, copy); - wpos = strlen (ws); - g_free (copy); - continue; - } - - xpm = (* imhtml->img) (src); - if (xpm == NULL) { - g_free (src); - ws [wpos] = 0; - strcat (ws, copy); - wpos = strlen (ws); - g_free (copy); - continue; - } - - g_free (copy); - if (!fonts || ((clr = ((FontDetail *) fonts->data)->back) == NULL)) clr = (bg != NULL) ? bg : imhtml->default_bg_color; @@ -3253,96 +3059,33 @@ bit = g_new0 (GtkIMHtmlBit, 1); bit->type = TYPE_IMG; bit->pm = gdk_pixmap_create_from_xpm_d (GTK_WIDGET (imhtml)->window, - &bit->bm, - clr, - xpm); + &bit->bm, clr, xpm); if (url) bit->url = g_strdup (url); NEW_BIT (bit); g_free (src); - - continue; - } else if (!g_strcasecmp (tag, "<P>") || - !g_strcasecmp (tag, "</P>") || - !g_strncasecmp (tag, "<P ", strlen ("<P ")) || - !g_strcasecmp (tag, "<H3>") || - !g_strncasecmp (tag, "<H3 ", strlen ("<H3 ")) || - !g_strcasecmp (tag, "</H3>") || - !g_strcasecmp (tag, "<HTML>") || - !g_strcasecmp (tag, "</HTML>") || - !g_strcasecmp (tag, "<BODY>") || - !g_strcasecmp (tag, "</BODY>") || - !g_strcasecmp (tag, "<FONT>") || - !g_strcasecmp (tag, "<HEAD>") || - !g_strcasecmp (tag, "</HEAD>")) { - intag = FALSE; - tpos = 0; - continue; } - - if (!got_tag) { - char *d; - tag [tpos] = 0; - d = tag; - while (*d) { - if ((smilelen = gtk_imhtml_is_smiley (imhtml, d)) != 0) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - g_snprintf (ws, smilelen + 1, "%s", d); - NEW_BIT (NEW_SMILEY_BIT); - d += smilelen; - } else if (*d == '&') { - gchar replace; - gint length; - if (is_amp_escape (d, &replace, &length)) { - ws [wpos++] = replace; - d += length; - } else { - ws [wpos++] = *d++; - } - } else if (*d == '\n') { - if (!(options & GTK_IMHTML_NO_NEWLINE)) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_BR_BIT); - } - d++; - } else { - ws [wpos++] = *d++; - } - } - tpos = 0; - } else { - wpos = 0; + break; + case 45: /* P (opt) */ + case 46: /* H3 (opt) */ + break; + case 47: /* comment */ + NEW_BIT (NEW_TEXT_BIT); + wpos = g_snprintf (ws, len, "%s", tag); + NEW_BIT (NEW_COMMENT_BIT); + break; + default: + break; } - intag = FALSE; - tpos = 0; - } else if (*c == '&' && !intag) { - gchar replace; - gint length; - if (is_amp_escape (c, &replace, &length)) { - ws [wpos++] = replace; - c += length; - } else { - ws [wpos++] = *c++; - } - } else if (intag) { - if (*c == '\"') - tagquote++; - tag [tpos++] = *c++; - } else if (incomment) { - ws [wpos++] = *c++; - } else if (((smilelen = gtk_imhtml_is_smiley (imhtml, c)) != 0)) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - g_snprintf (ws, smilelen + 1, "%s", c); - NEW_BIT (NEW_SMILEY_BIT); - c += smilelen; + g_free (tag); + c += tlen; + pos += tlen; + } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { + ws [wpos++] = amp; + c += tlen; + pos += tlen; } else if (*c == '\n') { if (!(options & GTK_IMHTML_NO_NEWLINE)) { ws [wpos] = 0; @@ -3351,77 +3094,21 @@ NEW_BIT (NEW_BR_BIT); } c++; - } else { + pos++; + } else if (gtk_imhtml_is_smiley (imhtml, c, &smilelen)) { + ws [wpos] = 0; + wpos = 0; + NEW_BIT (NEW_TEXT_BIT); + g_snprintf (ws, smilelen + 1, "%s", c); + wpos = smilelen + 1; + NEW_BIT (NEW_SMILEY_BIT); + c += smilelen; + pos += smilelen; + } else if (*c) { ws [wpos++] = *c++; - } - } - - if (intag) { - tag [tpos] = 0; - c = tag; - while (*c) { - if ((smilelen = gtk_imhtml_is_smiley (imhtml, c)) != 0) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - g_snprintf (ws, smilelen + 1, "%s", c); - NEW_BIT (NEW_SMILEY_BIT); - c += smilelen; - } else if (*c == '&') { - gchar replace; - gint length; - if (is_amp_escape (c, &replace, &length)) { - ws [wpos++] = replace; - c += length; - } else { - ws [wpos++] = *c++; - } - } else if (*c == '\n') { - if (!(options & GTK_IMHTML_NO_NEWLINE)) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_BR_BIT); - } - c++; - } else { - ws [wpos++] = *c++; - } - } - } else if (incomment) { - ws [wpos] = 0; - wpos = 0; - strcat (tag, ws); - ws [wpos] = 0; - c = tag; - while (*c) { - if ((smilelen = gtk_imhtml_is_smiley (imhtml, c)) != 0) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - g_snprintf (ws, smilelen + 1, "%s", c); - NEW_BIT (NEW_SMILEY_BIT); - c += smilelen; - } else if (*c == '&') { - gchar replace; - gint length; - if (is_amp_escape (c, &replace, &length)) { - ws [wpos++] = replace; - c += length; - } else { - ws [wpos++] = *c++; - } - } else if (*c == '\n') { - if (!(options & GTK_IMHTML_NO_NEWLINE)) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_BR_BIT); - } - c++; - } else { - ws [wpos++] = *c++; - } + pos++; + } else { + break; } } @@ -3518,7 +3205,6 @@ } } g_free (ws); - g_free (tag); return retval; } @@ -3562,9 +3248,9 @@ g_free (bit); } - while (imhtml->urls) { - g_free (imhtml->urls->data); - imhtml->urls = g_list_remove (imhtml->urls, imhtml->urls->data); + while (imhtml->click) { + g_free (imhtml->click->data); + imhtml->click = g_list_remove (imhtml->click, imhtml->click->data); } if (imhtml->selected_text) { @@ -3593,8 +3279,6 @@ imhtml->scroll_timer = 0; } - gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window, imhtml->arrow_cursor); - imhtml->x = 0; imhtml->y = TOP_BORDER; imhtml->xsize = 0; @@ -3616,11 +3300,12 @@ layout->vadjustment->upper = imhtml->y; gtk_adjustment_set_value (layout->vadjustment, 0); - gtk_signal_emit_by_name (GTK_OBJECT (layout->hadjustment), "changed"); - gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed"); - - if (GTK_WIDGET_REALIZED (GTK_WIDGET (imhtml))) + if (GTK_WIDGET_REALIZED (GTK_WIDGET (imhtml))) { + gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window, imhtml->arrow_cursor); gdk_window_clear (GTK_LAYOUT (imhtml)->bin_window); + gtk_signal_emit_by_name (GTK_OBJECT (layout->hadjustment), "changed"); + gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed"); + } } void