# HG changeset patch # User Tim Ringenbach # Date 1112486389 0 # Node ID b640d066eb51d46589281527342f8280c6283be5 # Parent d47e82ac9918afdf252f6cca2ea11017c37e13c0 [gaim-migrate @ 12387] this makes us do full backgrounds only for body tags, and changes how full backgrounds work. Sean, I left a lot of your code there, #if 0'd out. This probably isn't prefect yet, and I think I might have removed one of Sean's more recent changes. So I'm hoping Sean finishes this for me. Or at least yells at me about what to fix. Or at least tries it. committer: Tailor Script diff -r d47e82ac9918 -r b640d066eb51 src/gtkimhtml.c --- a/src/gtkimhtml.c Sat Apr 02 19:48:42 2005 +0000 +++ b/src/gtkimhtml.c Sat Apr 02 23:59:49 2005 +0000 @@ -522,17 +522,100 @@ return FALSE; } -struct backcolor_tag { - GtkTextMark *start; - GtkTextMark *end; - char *color; -}; static gint gtk_imhtml_expose_event (GtkWidget *widget, GdkEventExpose *event) { - GSList *l = GTK_IMHTML(widget)->backcolor_tags; + GtkTextIter start, end, cur; + int buf_x, buf_y; + GSList *tags, *l; + GdkRectangle visible_rect; + + gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &visible_rect); + gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(widget), + GTK_TEXT_WINDOW_TEXT, + visible_rect.x, + visible_rect.y, + &visible_rect.x, + &visible_rect.y); + + gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT, + event->area.x, event->area.y, &buf_x, &buf_y); + + gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget), &start, buf_x, buf_y); + gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget), &end, + buf_x + event->area.width, buf_y + event->area.height); + + + + cur = start; + + while (gtk_text_iter_in_range(&cur, &start, &end)) { + GdkGC *gc = gdk_gc_new(GDK_DRAWABLE(event->window)); + tags = gtk_text_iter_get_tags(&cur); + + for (l = tags; l; l = l->next) { + GtkTextTag *tag = l->data; + GdkRectangle rect; + GdkRectangle tag_area; + const char *color; + GdkColor gcolor; + + if (strncmp(tag->name, "BACKGROUND ", 11)) + continue; + + if (gtk_text_iter_ends_tag(&cur, tag)) + continue; + + gtk_text_view_get_iter_location(GTK_TEXT_VIEW(widget), &cur, &tag_area); + gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(widget), + GTK_TEXT_WINDOW_TEXT, + tag_area.x, + tag_area.y, + &tag_area.x, + &tag_area.y); + rect.x = visible_rect.x; + rect.y = tag_area.y; + + while (!gtk_text_iter_is_end(&cur) && gtk_text_iter_begins_tag(&cur, tag)) + gtk_text_iter_forward_to_tag_toggle(&cur, tag); + gtk_text_view_get_iter_location(GTK_TEXT_VIEW(widget), &cur, &tag_area); + gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(widget), + GTK_TEXT_WINDOW_TEXT, + tag_area.x, + tag_area.y, + &tag_area.x, + &tag_area.y); + + rect.width = visible_rect.width; + if (gtk_text_iter_is_end(&cur)) + rect.height = visible_rect.y + visible_rect.height - rect.y; + else + rect.height = tag_area.y + tag_area.height - rect.y + + gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(widget)); + + color = tag->name + 11; + + gdk_color_parse(color, &gcolor); + gdk_gc_set_rgb_fg_color(gc, &gcolor); + + + gdk_draw_rectangle(event->window, + gc, + TRUE, + rect.x, rect.y, rect.width, rect.height); + gaim_debug_info("gtkimhtml", "drawing rect at %d,%d to %d,%d\n", + rect.x, rect.y, rect.x+rect.width, rect.y+rect.height); + gtk_text_iter_backward_char(&cur); + break; + } + + g_slist_free(tags); + gdk_gc_unref(gc); + gtk_text_iter_forward_to_tag_toggle(&cur, NULL); + } +#if 0 while (l) { struct backcolor_tag *tag = (struct backcolor_tag*)l->data; GdkRectangle visible_rect; @@ -543,7 +626,7 @@ GdkGC *gc = gdk_gc_new(GDK_DRAWABLE(event->window)); GdkColor color; - gtk_text_view_get_visible_rect (GTK_TEXT_VIEW(widget), &visible_rect); + gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &visible_rect); gtk_text_view_buffer_to_window_coords (GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT, visible_rect.x, @@ -600,9 +683,11 @@ gdk_gc_unref(gc); l = l->next; } +#endif if (GTK_WIDGET_CLASS (parent_class)->expose_event) return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event); + return FALSE; } @@ -1220,7 +1305,6 @@ /* Register HTML Format as desired clipboard format */ win_html_fmt = RegisterClipboardFormat("HTML Format"); #endif - imhtml->backcolor_tags = NULL; } GtkWidget *gtk_imhtml_new(void *a, void *b) @@ -2365,7 +2449,10 @@ case 33: /* HTML */ case 34: /* /HTML */ case 35: /* BODY */ + break; case 36: /* /BODY */ + gtk_imhtml_toggle_background(imhtml, NULL); + break; case 37: /* FONT */ case 38: /* HEAD */ case 39: /* /HEAD */ @@ -2449,7 +2536,7 @@ if (bg) g_free(bg); bg = bgcolor; - gtk_imhtml_toggle_backcolor(imhtml, bg); + gtk_imhtml_toggle_background(imhtml, bg); } } break; @@ -2793,18 +2880,9 @@ gtk_imhtml_clear (GtkIMHtml *imhtml) { GList *del; - GSList *dels; GtkTextIter start, end; GObject *object = g_object_ref(G_OBJECT(imhtml)); - for (dels = imhtml->backcolor_tags; dels; dels = dels->next) { - struct backcolor_tag *tag = dels->data; - g_free(tag->color); - g_free(tag); - } - g_slist_free(imhtml->backcolor_tags); - imhtml->backcolor_tags = NULL; - gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); gtk_text_buffer_delete(imhtml->text_buffer, &start, &end); @@ -3256,6 +3334,20 @@ return tag; } +static GtkTextTag *find_font_background_tag(GtkIMHtml *imhtml, gchar *color) +{ + gchar str[19]; + GtkTextTag *tag; + + g_snprintf(str, sizeof(str), "BACKGROUND %s", color); + + tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); + if (!tag) + tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, NULL); + + return tag; +} + static GtkTextTag *find_font_face_tag(GtkIMHtml *imhtml, gchar *face) { gchar str[256]; @@ -3354,6 +3446,11 @@ remove_tag_by_prefix(imhtml, i, e, "BACKCOLOR ", 10, homo); } +static void remove_font_background(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) +{ + remove_tag_by_prefix(imhtml, i, e, "BACKGROUND ", 10, homo); +} + static void remove_font_link(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) { remove_tag_by_prefix(imhtml, i, e, "LINK ", 5, homo); @@ -3424,6 +3521,12 @@ start, end); } + if (imhtml->edit.background) { + remove_font_background(imhtml, start, end, TRUE); + gtk_text_buffer_apply_tag(imhtml->text_buffer, + find_font_background_tag(imhtml, imhtml->edit.background), + start, end); + } if (imhtml->edit.fontface) { remove_font_face(imhtml, start, end, TRUE); gtk_text_buffer_apply_tag(imhtml->text_buffer, @@ -3788,135 +3891,63 @@ g_object_unref(object); } +#define gtk_imhtml_toggle_str_tag(imhtml, color, edit_field, remove_func, find_func) { \ + GObject *object; \ + GtkTextIter start, end; \ +\ + g_free(edit_field); \ + edit_field = NULL; \ +\ + if (color && strcmp(color, "") != 0) { \ + edit_field = g_strdup(color); \ +\ + if (imhtml->wbfo) { \ + gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); \ + remove_func(imhtml, &start, &end, TRUE); \ + gtk_text_buffer_apply_tag(imhtml->text_buffer, \ + find_func(imhtml, edit_field), &start, &end); \ + } else { \ + gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, \ + gtk_text_buffer_get_mark(imhtml->text_buffer, "insert")); \ + if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { \ + remove_func(imhtml, &start, &end, FALSE); \ + gtk_text_buffer_apply_tag(imhtml->text_buffer, \ + find_func(imhtml, \ + edit_field), \ + &start, &end); \ + } \ + } \ + } else { \ + if (imhtml->wbfo) { \ + gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); \ + remove_func(imhtml, &start, &end, TRUE); \ + } \ + } \ +\ + object = g_object_ref(G_OBJECT(imhtml)); \ + g_object_unref(object); \ +\ + return edit_field != NULL; \ +} + gboolean gtk_imhtml_toggle_forecolor(GtkIMHtml *imhtml, const char *color) { - GObject *object; - GtkTextIter start, end; - - if (imhtml->edit.forecolor != NULL) - g_free(imhtml->edit.forecolor); - - if (color && strcmp(color, "") != 0) { - imhtml->edit.forecolor = g_strdup(color); - if (imhtml->wbfo) { - gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); - remove_font_forecolor(imhtml, &start, &end, TRUE); - gtk_text_buffer_apply_tag(imhtml->text_buffer, - find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), &start, &end); - } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { - remove_font_forecolor(imhtml, &start, &end, FALSE); - gtk_text_buffer_apply_tag(imhtml->text_buffer, - find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), - &start, &end); - } - } else { - imhtml->edit.forecolor = NULL; - if (imhtml->wbfo) { - gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); - remove_font_forecolor(imhtml, &start, &end, TRUE); - } - } - - object = g_object_ref(G_OBJECT(imhtml)); - g_object_unref(object); - - return imhtml->edit.forecolor != NULL; + gtk_imhtml_toggle_str_tag(imhtml, color, imhtml->edit.forecolor, remove_font_forecolor, find_font_forecolor_tag); } gboolean gtk_imhtml_toggle_backcolor(GtkIMHtml *imhtml, const char *color) { - GObject *object; - GtkTextIter start, end; - struct backcolor_tag *bct = NULL; - - if (imhtml->edit.backcolor != NULL) - g_free(imhtml->edit.backcolor); - - imhtml->edit.backcolor = NULL; - - if (color && strcmp(color, "") != 0) { - imhtml->edit.backcolor = g_strdup(color); - - if (imhtml->wbfo) { - gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); - remove_font_backcolor(imhtml, &start, &end, TRUE); - gtk_text_buffer_apply_tag(imhtml->text_buffer, - find_font_backcolor_tag(imhtml, imhtml->edit.backcolor), &start, &end); - bct = g_malloc(sizeof(struct backcolor_tag)); - bct->color = strdup(imhtml->edit.backcolor); - bct->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &start, TRUE); - bct->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &end, TRUE); - imhtml->backcolor_tags = g_slist_prepend(imhtml->backcolor_tags, bct); - } else { - bct = g_malloc(sizeof(struct backcolor_tag)); - bct->color = strdup(imhtml->edit.backcolor); - gtk_text_buffer_get_iter_at_mark (imhtml->text_buffer, &start, - gtk_text_buffer_get_mark(imhtml->text_buffer, "insert")); - bct->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &start, TRUE); - bct->end = NULL; - imhtml->backcolor_tags = g_slist_prepend(imhtml->backcolor_tags, bct); - if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { - remove_font_backcolor(imhtml, &start, &end, FALSE); - gtk_text_buffer_apply_tag(imhtml->text_buffer, - find_font_backcolor_tag(imhtml, - imhtml->edit.backcolor), &start, &end); - } - } - } else { - if (imhtml->backcolor_tags) { - bct = ((struct backcolor_tag*)(imhtml->backcolor_tags->data)); - if (bct->end == NULL) { - gtk_text_buffer_get_iter_at_mark (imhtml->text_buffer, &end, - gtk_text_buffer_get_mark(imhtml->text_buffer, "insert")); - bct->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &end, TRUE); - } - } - if (imhtml->wbfo) { - gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); - remove_font_backcolor(imhtml, &start, &end, TRUE); - } - } - - object = g_object_ref(G_OBJECT(imhtml)); - g_object_unref(object); - - return imhtml->edit.backcolor != NULL; + gtk_imhtml_toggle_str_tag(imhtml, color, imhtml->edit.backcolor, remove_font_backcolor, find_font_backcolor_tag); +} + +gboolean gtk_imhtml_toggle_background(GtkIMHtml *imhtml, const char *color) +{ + gtk_imhtml_toggle_str_tag(imhtml, color, imhtml->edit.background, remove_font_background, find_font_background_tag); } gboolean gtk_imhtml_toggle_fontface(GtkIMHtml *imhtml, const char *face) { - GObject *object; - GtkTextIter start, end; - - if (imhtml->edit.fontface != NULL) - g_free(imhtml->edit.fontface); - - if (face && strcmp(face, "") != 0) { - imhtml->edit.fontface = g_strdup(face); - - if (imhtml->wbfo) { - gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); - remove_font_face(imhtml, &start, &end, TRUE); - gtk_text_buffer_apply_tag(imhtml->text_buffer, - find_font_face_tag(imhtml, imhtml->edit.fontface), &start, &end); - } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { - remove_font_face(imhtml, &start, &end, FALSE); - gtk_text_buffer_apply_tag(imhtml->text_buffer, - find_font_face_tag(imhtml, imhtml->edit.fontface), - &start, &end); - } - } else { - imhtml->edit.fontface = NULL; - if (imhtml->wbfo) { - gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); - remove_font_face(imhtml, &start, &end, TRUE); - } - } - - object = g_object_ref(G_OBJECT(imhtml)); - g_object_unref(object); - - return imhtml->edit.fontface != NULL; + gtk_imhtml_toggle_str_tag(imhtml, face, imhtml->edit.fontface, remove_font_face, find_font_face_tag); } void gtk_imhtml_toggle_link(GtkIMHtml *imhtml, const char *url) @@ -4116,6 +4147,9 @@ } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { g_snprintf(buf, sizeof(buf), "", &name[10]); return buf; + } else if (strncmp(name, "BACKGROUND ", 10) == 0) { + g_snprintf(buf, sizeof(buf), "", &name[11]); + return buf; } else if (strncmp(name, "FONT FACE ", 10) == 0) { g_snprintf(buf, sizeof(buf), "", &name[10]); return buf; @@ -4148,6 +4182,8 @@ return ""; } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { return ""; + } else if (strncmp(name, "BACKGROUND ", 10) == 0) { + return ""; } else if (strncmp(name, "FONT FACE ", 10) == 0) { return ""; } else if (strncmp(name, "FONT SIZE ", 10) == 0) { diff -r d47e82ac9918 -r b640d066eb51 src/gtkimhtml.h --- a/src/gtkimhtml.h Sat Apr 02 19:48:42 2005 +0000 +++ b/src/gtkimhtml.h Sat Apr 02 23:59:49 2005 +0000 @@ -55,20 +55,21 @@ typedef struct _GtkIMHtmlFuncs GtkIMHtmlFuncs; typedef enum { - GTK_IMHTML_BOLD = 1 << 0, - GTK_IMHTML_ITALIC = 1 << 1, - GTK_IMHTML_UNDERLINE = 1 << 2, - GTK_IMHTML_GROW = 1 << 3, - GTK_IMHTML_SHRINK = 1 << 4, - GTK_IMHTML_FACE = 1 << 5, - GTK_IMHTML_FORECOLOR = 1 << 6, - GTK_IMHTML_BACKCOLOR = 1 << 7, - GTK_IMHTML_LINK = 1 << 8, - GTK_IMHTML_IMAGE = 1 << 9, - GTK_IMHTML_SMILEY = 1 << 10, - GTK_IMHTML_LINKDESC = 1 << 11, - GTK_IMHTML_STRIKE = 1 << 12, - GTK_IMHTML_ALL = -1 + GTK_IMHTML_BOLD = 1 << 0, + GTK_IMHTML_ITALIC = 1 << 1, + GTK_IMHTML_UNDERLINE = 1 << 2, + GTK_IMHTML_GROW = 1 << 3, + GTK_IMHTML_SHRINK = 1 << 4, + GTK_IMHTML_FACE = 1 << 5, + GTK_IMHTML_FORECOLOR = 1 << 6, + GTK_IMHTML_BACKCOLOR = 1 << 7, + GTK_IMHTML_BACKGROUND = 1 << 8, + GTK_IMHTML_LINK = 1 << 9, + GTK_IMHTML_IMAGE = 1 << 10, + GTK_IMHTML_SMILEY = 1 << 11, + GTK_IMHTML_LINKDESC = 1 << 12, + GTK_IMHTML_STRIKE = 1 << 13, + GTK_IMHTML_ALL = -1 } GtkIMHtmlButtons; struct _GtkIMHtml { @@ -106,6 +107,7 @@ gboolean strike:1; gchar *forecolor; gchar *backcolor; + gchar *background; gchar *fontface; int fontsize; GtkTextTag *link; @@ -116,7 +118,6 @@ GSList *im_images; GtkIMHtmlFuncs *funcs; - GSList *backcolor_tags; }; struct _GtkIMHtmlClass { @@ -135,6 +136,7 @@ gchar *face; gchar *fore; gchar *back; + gchar *bg; gchar *sml; gboolean underline; }; @@ -523,6 +525,16 @@ char *gtk_imhtml_get_current_forecolor(GtkIMHtml *imhtml); /** + * Returns a string containing the selected font background color at the current + * position in a GTK IM/HTML. + * + * @param imhtml The GTK IM/HTML. + * + * @return A string containg the font background color or @c NULL if none is set. + */ +char *gtk_imhtml_get_current_backcolor(GtkIMHtml *imhtml); + +/** * Returns a string containing the selected background color at the current * position in a GTK IM/HTML. * @@ -530,7 +542,7 @@ * * @return A string containg the background color or @c NULL if none is set. */ -char *gtk_imhtml_get_current_backcolor(GtkIMHtml *imhtml); +char *gtk_imhtml_get_current_background(GtkIMHtml *imhtml); /** * Returns a integer containing the selected HTML font size at the current @@ -610,6 +622,17 @@ gboolean gtk_imhtml_toggle_backcolor(GtkIMHtml *imhtml, const char *color); /** + * Toggles a background color at the current location or selection in a GTK + * IM/HTML. + * + * @param imhtml The GTK IM/HTML. + * @param color The HTML-style color, or @c NULL or "" to clear the color. + * + * @return @c TRUE if a color was set, or @c FALSE if it was cleared. + */ +gboolean gtk_imhtml_toggle_background(GtkIMHtml *imhtml, const char *color); + +/** * Toggles a font face at the current location or selection in a GTK IM/HTML. * * @param imhtml The GTK IM/HTML.