--- src/gtkimhtml.c 10 Jan 2004 04:04:56 -0000 1.261 +++ src/gtkimhtml.c 16 Jan 2004 05:33:56 -0000 @@ -98,12 +98,12 @@ t->children [index] = g_new0 (GtkSmileyTree, 1); } else index = GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str); - + t = t->children [index]; - + x++; } - + t->image = smiley; } @@ -155,7 +155,7 @@ layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); - gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window, + gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, imhtml->tip_window, "tooltip", 0, 0, -1, -1); @@ -181,7 +181,7 @@ imhtml->tip_timer = 0; return FALSE; } - + if (imhtml->tip_window){ gtk_widget_destroy (imhtml->tip_window); imhtml->tip_window = NULL; @@ -203,12 +203,12 @@ pango_layout_get_pixel_size(layout, &scr_w, NULL); - gap = PANGO_PIXELS((pango_font_metrics_get_ascent(font) + + gap = PANGO_PIXELS((pango_font_metrics_get_ascent(font) + pango_font_metrics_get_descent(font))/ 4); if (gap < 2) gap = 2; - baseline_skip = PANGO_PIXELS(pango_font_metrics_get_ascent(font) + + baseline_skip = PANGO_PIXELS(pango_font_metrics_get_ascent(font) + pango_font_metrics_get_descent(font)); w = 8 + scr_w; h = 8 + baseline_skip; @@ -226,7 +226,7 @@ else if (x < 0) x = 0; - y = y + PANGO_PIXELS(pango_font_metrics_get_ascent(font) + + y = y + PANGO_PIXELS(pango_font_metrics_get_ascent(font) + pango_font_metrics_get_descent(font)); gtk_widget_set_size_request (imhtml->tip_window, w, h); @@ -240,7 +240,7 @@ } gboolean gtk_motion_event_notify(GtkWidget *imhtml, GdkEventMotion *event, gpointer data) -{ +{ GtkTextIter iter; GdkWindow *win = event->window; int x, y; @@ -260,7 +260,7 @@ break; templist = templist->next; } - + if (GTK_IMHTML(imhtml)->tip) { if ((tip == GTK_IMHTML(imhtml)->tip)) { return FALSE; @@ -275,13 +275,13 @@ g_source_remove(GTK_IMHTML(imhtml)->tip_timer); GTK_IMHTML(imhtml)->tip_timer = 0; } - + if(tip){ gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->hand_cursor); - GTK_IMHTML(imhtml)->tip_timer = g_timeout_add (TOOLTIP_TIMEOUT, + GTK_IMHTML(imhtml)->tip_timer = g_timeout_add (TOOLTIP_TIMEOUT, gtk_imhtml_tip, imhtml); } - + GTK_IMHTML(imhtml)->tip = tip; g_slist_free(tags); return FALSE; @@ -307,11 +307,11 @@ /* * XXX - This should be removed eventually. * - * This function exists to work around a gross bug in GtkTextView. - * Basically, we short circuit ctrl+a and ctrl+end because they make + * This function exists to work around a gross bug in GtkTextView. + * Basically, we short circuit ctrl+a and ctrl+end because they make * el program go boom. * - * It's supposed to be fixed in gtk2.2. You can view the bug report at + * It's supposed to be fixed in gtk2.2. You can view the bug report at * http://bugzilla.gnome.org/show_bug.cgi?id=107939 */ gboolean gtk_key_pressed_cb(GtkWidget *imhtml, GdkEventKey *event, gpointer data) @@ -335,7 +335,7 @@ } #if GTK_CHECK_VERSION(2,2,0) -static GtkIMHtmlCopyable *gtk_imhtml_copyable_new(GtkIMHtml *imhtml, GtkTextMark *mark, const gchar *text) +static GtkIMHtmlCopyable *gtk_imhtml_copyable_new(GtkIMHtml *imhtml, GtkTextMark *mark, const gchar *text) { GtkIMHtmlCopyable *copy = g_malloc(sizeof(GtkIMHtmlCopyable)); copy->mark = mark; @@ -353,13 +353,13 @@ char *text; GSList *copyables; - + gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel); gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins); - + if (gtk_text_iter_equal(&start, &end)) return; - + gtk_text_iter_order(&start, &end); last = start; @@ -380,10 +380,10 @@ text = gtk_text_buffer_get_text(imhtml->text_buffer, &last, &end, FALSE); str = g_string_append(str, text); g_free(text); - + if (!gtk_text_iter_equal(&start, &last)) - gtk_clipboard_set_text(clipboard ? clipboard : - gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), + gtk_clipboard_set_text(clipboard ? clipboard : + gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), str->str, str->len); g_string_free(str, TRUE); } @@ -413,7 +413,7 @@ #if GTK_CHECK_VERSION(2,2,0) GSList *copyables; #endif - + g_hash_table_destroy(imhtml->smiley_data); gtk_smiley_tree_destroy(imhtml->default_smilies); gdk_cursor_unref(imhtml->hand_cursor); @@ -472,9 +472,9 @@ gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), FALSE); /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ - + /* These tags will be used often and can be reused--we create them on init and then apply them by name - * other tags (color, size, face, etc.) will have to be created and applied dynamically */ + * other tags (color, size, face, etc.) will have to be created and applied dynamically */ gtk_text_buffer_create_tag(imhtml->text_buffer, "BOLD", "weight", PANGO_WEIGHT_BOLD, NULL); gtk_text_buffer_create_tag(imhtml->text_buffer, "ITALICS", "style", PANGO_STYLE_ITALIC, NULL); gtk_text_buffer_create_tag(imhtml->text_buffer, "UNDERLINE", "underline", PANGO_UNDERLINE_SINGLE, NULL); @@ -553,7 +553,7 @@ if(!data) return; g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); - + g_object_unref(data->object); g_free(data->url); g_free(data); @@ -574,7 +574,7 @@ GdkEventButton *event_button = (GdkEventButton *) event; if (event->type == GDK_BUTTON_RELEASE) { - if (event_button->button == 1) { + if (event_button->button == 1) { GtkTextIter start, end; /* we shouldn't open a URL if the user has selected something: */ gtk_text_buffer_get_selection_bounds( @@ -1035,6 +1035,69 @@ return val; } +/* Inline CSS Support - Douglas Thrift */ +static gchar* +gtk_imhtml_get_css_opt (gchar *style, + const gchar *opt) +{ + gchar *t = style; + gchar *e, *a; + gchar *val; + gint len; + gchar *c; + GString *ret; + + while (g_ascii_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_ascii_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') { + return NULL; + } else + val = g_strndup(a, e - a); + } else { + e = a = t; + while (*e && !isspace ((gint) *e)) e++; + val = g_strndup(a, e - a); + }*/ + + e = a = t; + while (*e && *e != ';') e++; + val = g_strndup(a, e - a); + + ret = g_string_new(""); + e = val; + while(*e) { + if(gtk_imhtml_is_amp_escape(e, &c, &len)) { + ret = g_string_append(ret, c); + e += len; + } else { + ret = g_string_append_c(ret, *e); + e++; + } + } + + g_free(val); + val = ret->str; + g_string_free(ret, FALSE); + return val; +} #define NEW_TEXT_BIT 0 @@ -1132,7 +1195,7 @@ sub = 0, sup = 0, title = 0, - pre = 0; + pre = 0; GSList *fonts = NULL; @@ -1156,10 +1219,10 @@ gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); mark = gtk_text_buffer_create_mark (imhtml->text_buffer, NULL, &iter, /* right grav */ FALSE); - gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); + gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); - if(((y + height) - (rect.y + rect.height)) > height + if(((y + height) - (rect.y + rect.height)) > height && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ options |= GTK_IMHTML_NO_SCROLL; } @@ -1168,7 +1231,7 @@ if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { c++; pos++; - switch (type) + switch (type) { case 1: /* B */ case 2: /* BOLD */ @@ -1319,9 +1382,9 @@ sml = gtk_imhtml_get_html_opt (tag, "SML="); if (!(color || back || face || size || sml)) break; - + NEW_BIT (NEW_TEXT_BIT); - + font = g_new0 (GtkIMHtmlFontDetail, 1); if (fonts) oldfont = fonts->data; @@ -1335,7 +1398,7 @@ font->back = back; else if (oldfont && oldfont->back) font->back = g_strdup(oldfont->back); - + if (face && !(options & GTK_IMHTML_NO_FONTS)) font->face = face; else if (oldfont && oldfont->face) @@ -1417,7 +1480,90 @@ case 50: /* CITE */ case 51: /* /CITE */ case 56: /* SPAN (opt) */ + /* Inline CSS Support - Douglas Thrift + * + * color + * font-family + * font-size + */ + { + gchar *style, *color, *family, *size; + GtkIMHtmlFontDetail *font, *oldfont = NULL; + style = gtk_imhtml_get_html_opt (tag, "style="); + + if (!style) break; + + color = gtk_imhtml_get_css_opt (style, "color: "); + family = gtk_imhtml_get_css_opt (style, + "font-family: "); + size = gtk_imhtml_get_css_opt (style, "font-size: "); + + if (!(color || family || size)) break; + + NEW_BIT (NEW_TEXT_BIT); + + font = g_new0 (GtkIMHtmlFontDetail, 1); + if (fonts) + oldfont = fonts->data; + + if (color && !(options & GTK_IMHTML_NO_COLOURS)) + font->fore = color; + else if (oldfont && oldfont->fore) + font->fore = g_strdup(oldfont->fore); + + if (oldfont && oldfont->back) + font->back = g_strdup(oldfont->back); + + if (family && !(options & GTK_IMHTML_NO_FONTS)) + font->face = family; + else if (oldfont && oldfont->face) + font->face = g_strdup(oldfont->face); + if (font->face && (atoi(font->face) > 100)) { + g_free(font->face); + font->face = g_strdup("100"); + } + + if (oldfont && oldfont->sml) + font->sml = g_strdup(oldfont->sml); + + if (size && !(options & GTK_IMHTML_NO_SIZES)) { + if (g_ascii_strcasecmp(size, "smaller") == 0) + { + font->size = 2; + } + else if (g_ascii_strcasecmp(size, "larger") == 0) + { + font->size = 4; + } + else + { + font->size = 3; + } + } else if (oldfont) + font->size = oldfont->size; + + g_free(style); + g_free(size); + fonts = g_slist_prepend (fonts, font); + } + break; case 57: /* /SPAN */ + /* Inline CSS Support - Douglas Thrift */ + if (fonts) { + GtkIMHtmlFontDetail *font = fonts->data; + NEW_BIT (NEW_TEXT_BIT); + fonts = g_slist_remove (fonts, font); + if (font->face) + g_free (font->face); + if (font->fore) + g_free (font->fore); + if (font->back) + g_free (font->back); + if (font->sml) + g_free (font->sml); + g_free (font); + } + break; case 60: /* SPAN */ break; case 61: /* comment */ @@ -1454,7 +1600,7 @@ GdkPixbufAnimation *annipixbuf = NULL; GdkPixbuf *pixbuf = NULL; GtkIMHtmlFontDetail *fd; - + gchar *sml = NULL; if (fonts) { fd = fonts->data; @@ -1478,25 +1624,25 @@ gtk_widget_show(icon); gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor); #if GTK_CHECK_VERSION(2,2,0) - gtk_imhtml_copyable_new(imhtml, - gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE), + gtk_imhtml_copyable_new(imhtml, + gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE), ws); #endif } - + copy = iter; gtk_text_iter_backward_char(©); - if (bg) { - texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", bg, NULL); - gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &iter, ©); - } - if (fonts) { - GtkIMHtmlFontDetail *fd = fonts->data; - if (fd->back) { - texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", fd->back, NULL); - gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &iter, ©); + if (bg) { + texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", bg, NULL); + gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &iter, ©); + } + if (fonts) { + GtkIMHtmlFontDetail *fd = fonts->data; + if (fd->back) { + texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", fd->back, NULL); + gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &iter, ©); } - } + } c += smilelen; pos += smilelen; wpos = 0; @@ -1508,14 +1654,14 @@ break; } } - + NEW_BIT(NEW_TEXT_BIT); if (url) { g_free (url); if (str) str = g_string_append (str, ""); } - + while (fonts) { GtkIMHtmlFontDetail *font = fonts->data; fonts = g_slist_remove (fonts, font); @@ -1623,7 +1769,7 @@ gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, rect.y - rect.height); gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); - + } void gtk_imhtml_page_down (GtkIMHtml *imhtml) { @@ -1781,7 +1927,7 @@ g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", G_CALLBACK(gtk_widget_destroy), sel); g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->cancel_button), "clicked", - G_CALLBACK(gtk_widget_destroy), sel); + G_CALLBACK(gtk_widget_destroy), sel); gtk_widget_show(sel); } @@ -1883,17 +2029,17 @@ g_return_val_if_fail(imhtml != NULL, FALSE); g_return_val_if_fail(text != NULL, FALSE); - + if (imhtml->search_string && !strcmp(text, imhtml->search_string)) new_search = FALSE; - - + + if (new_search) { gtk_imhtml_search_clear(imhtml); gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); } else { gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, - gtk_text_buffer_get_mark(imhtml->text_buffer, "search")); + gtk_text_buffer_get_mark(imhtml->text_buffer, "search")); } imhtml->search_string = g_strdup(text); @@ -1905,10 +2051,10 @@ gtk_text_buffer_create_mark(imhtml->text_buffer, "search", &end, FALSE); if (new_search) { gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &iter, &end); - do + do gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "search", &start, &end); - while (gtk_source_iter_forward_search(&end, imhtml->search_string, - GTK_SOURCE_SEARCH_VISIBLE_ONLY | + while (gtk_source_iter_forward_search(&end, imhtml->search_string, + GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_CASE_INSENSITIVE, &start, &end, NULL)); } @@ -1920,9 +2066,9 @@ void gtk_imhtml_search_clear(GtkIMHtml *imhtml) { GtkTextIter start, end; - + g_return_if_fail(imhtml != NULL); - + gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end);