Mercurial > pidgin
changeset 3922:30f52e7afd1d
[gaim-migrate @ 4094]
This is gtkimhtml2--it's a subclass of gtktextview. It's not done yet. It doesn't
do smileys or images, and what it does do so far, it doesn't do perfectly. But it's
perfectly 100% usable, and like 80,000 times faster than gtkimhtml + Pango.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Fri, 08 Nov 2002 06:10:35 +0000 |
parents | 67209a7ee924 |
children | b8398b505b03 |
files | src/away.c src/buddy_chat.c src/conversation.c src/dialogs.c src/gtkimhtml.c src/gtkimhtml.h src/prefs.c src/server.c |
diffstat | 8 files changed, 445 insertions(+), 3396 deletions(-) [+] |
line wrap: on
line diff
--- a/src/away.c Fri Nov 08 06:05:03 2002 +0000 +++ b/src/away.c Fri Nov 08 06:10:35 2002 +0000 @@ -203,8 +203,6 @@ awaytext = gtk_imhtml_new(NULL, NULL); gtk_container_add(GTK_CONTAINER(sw), awaytext); - GTK_LAYOUT(awaytext)->hadjustment->step_increment = 10.0; - GTK_LAYOUT(awaytext)->vadjustment->step_increment = 10.0; gaim_setup_imhtml(awaytext); gtk_widget_show(awaytext); buf = stylize(a->message, BUF_LONG);
--- a/src/buddy_chat.c Fri Nov 08 06:05:03 2002 +0000 +++ b/src/buddy_chat.c Fri Nov 08 06:10:35 2002 +0000 @@ -1316,8 +1316,6 @@ text = gtk_imhtml_new(NULL, NULL); b->text = text; gtk_container_add(GTK_CONTAINER(sw), text); - GTK_LAYOUT(text)->hadjustment->step_increment = 10.0; - GTK_LAYOUT(text)->vadjustment->step_increment = 10.0; if (convo_options & OPT_CONVO_SHOW_TIME) gtk_imhtml_show_comments(GTK_IMHTML(text), TRUE); gaim_setup_imhtml(text);
--- a/src/conversation.c Fri Nov 08 06:05:03 2002 +0000 +++ b/src/conversation.c Fri Nov 08 06:10:35 2002 +0000 @@ -191,7 +191,7 @@ update_checkbox(c); update_smilies(c); plugin_event(event_new_conversation, name); - gtk_imhtml_to_bottom(GTK_IMHTML(c->text)); + /*gtk_imhtml_to_bottom(c->text);*/ return c; } @@ -2620,7 +2620,7 @@ update_convo_status(c); - gtk_imhtml_to_bottom(GTK_IMHTML(c->text)); + /*gtk_imhtml_to_bottom(c->text);*/ } void update_convo_status(struct conversation *c) { @@ -2848,8 +2848,6 @@ text = gtk_imhtml_new(NULL, NULL); c->text = text; gtk_container_add(GTK_CONTAINER(sw), text); - GTK_LAYOUT(text)->hadjustment->step_increment = 10.0; - GTK_LAYOUT(text)->vadjustment->step_increment = 10.0; if (convo_options & OPT_CONVO_SHOW_TIME) gtk_imhtml_show_comments(GTK_IMHTML(text), TRUE); gaim_setup_imhtml(text);
--- a/src/dialogs.c Fri Nov 08 06:05:03 2002 +0000 +++ b/src/dialogs.c Fri Nov 08 06:10:35 2002 +0000 @@ -2365,8 +2365,6 @@ text = gtk_imhtml_new(NULL, NULL); b->text = text; gtk_container_add(GTK_CONTAINER(sw), text); - GTK_LAYOUT(text)->hadjustment->step_increment = 10.0; - GTK_LAYOUT(text)->vadjustment->step_increment = 10.0; gtk_widget_set_usize(sw, 300, 250); gtk_imhtml_set_img_handler(GTK_IMHTML(text), info_img_handler); gaim_setup_imhtml(text); @@ -4227,8 +4225,6 @@ gtk_signal_connect(GTK_OBJECT(layout), "url_clicked", GTK_SIGNAL_FUNC(open_url), NULL); gtk_container_add(GTK_CONTAINER(sw), layout); - GTK_LAYOUT(layout)->hadjustment->step_increment = 10.0; - GTK_LAYOUT(layout)->vadjustment->step_increment = 10.0; gaim_setup_imhtml(layout); gtk_box_pack_start(GTK_BOX(box), bbox, FALSE, FALSE, 0);
--- a/src/gtkimhtml.c Fri Nov 08 06:05:03 2002 +0000 +++ b/src/gtkimhtml.c Fri Nov 08 06:10:35 2002 +0000 @@ -23,15 +23,6 @@ #include <config.h> #endif #include "gtkimhtml.h" - -#ifndef _WIN32 -#include <X11/Xlib.h> -#include <gdk/gdkx.h> -#else -#include <gdk/gdkwin32.h> -#endif - -#include <stdlib.h> #include <gtk/gtk.h> #include <string.h> #include <ctype.h> @@ -42,2770 +33,143 @@ #include <locale.h> #endif -#ifdef _WIN32 -/* GDK_SELECTION_PRIMARY is ignored win32 GTK */ -#undef GDK_SELECTION_PRIMARY -#define GDK_SELECTION_PRIMARY GDK_SELECTION_CLIPBOARD -#endif - -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <gdk-pixbuf/gdk-pixbuf-loader.h> - -#include <pango/pango.h> - -#include "pixmaps/angel.xpm" -#include "pixmaps/bigsmile.xpm" -#include "pixmaps/burp.xpm" -#include "pixmaps/crossedlips.xpm" -#include "pixmaps/cry.xpm" -#include "pixmaps/embarrassed.xpm" -#include "pixmaps/kiss.xpm" -#include "pixmaps/moneymouth.xpm" -#include "pixmaps/sad.xpm" -#include "pixmaps/scream.xpm" -#include "pixmaps/smile.xpm" -#include "pixmaps/smile8.xpm" -#include "pixmaps/think.xpm" -#include "pixmaps/tongue.xpm" -#include "pixmaps/wink.xpm" -#include "pixmaps/yell.xpm" - -#define MAX_FONT_SIZE 7 - -#define POINT_SIZE(x) (_point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) -static gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 }; - -#define DEFAULT_PRE_FACE "sans" - -#define BORDER_SIZE 2 -#define TOP_BORDER 10 -#define MIN_HEIGHT 20 -#define HR_HEIGHT 2 -#define TOOLTIP_TIMEOUT 500 - -#define DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) -#define COLOR_MOD 0x8000 -#define COLOR_DIFF 0x800 - -#define TYPE_TEXT 0 -#define TYPE_SMILEY 1 -#define TYPE_IMG 2 -#define TYPE_SEP 3 -#define TYPE_BR 4 -#define TYPE_COMMENT 5 - -#define GTK_IMHTML_GET_STYLE_FONT(style) gtk_style_get_font (style) - -#define DRAW_IMG(x) (((x)->type == TYPE_IMG) || (imhtml->smileys && ((x)->type == TYPE_SMILEY))) - -typedef struct _GtkIMHtmlBit GtkIMHtmlBit; -typedef struct _FontDetail FontDetail; - -struct _GtkSmileyTree { - GString *values; - GtkSmileyTree **children; - gchar **image; -}; - -/* - * PROTOS - */ -extern void debug_printf(char * fmt, ...); - -static GtkSmileyTree* -gtk_smiley_tree_new () -{ - return g_new0 (GtkSmileyTree, 1); -} - -static void -gtk_smiley_tree_insert (GtkSmileyTree *tree, - const gchar *text, - gchar **image) -{ - GtkSmileyTree *t = tree; - const gchar *x = text; - - if (!strlen (x)) - return; - - while (*x) { - gchar *pos; - gint index; - - if (!t->values) - t->values = g_string_new (""); - - pos = strchr (t->values->str, *x); - if (!pos) { - t->values = g_string_append_c (t->values, *x); - index = t->values->len - 1; - t->children = g_realloc (t->children, t->values->len * sizeof (GtkSmileyTree *)); - t->children [index] = g_new0 (GtkSmileyTree, 1); - } else - index = (int) pos - (int) t->values->str; - - t = t->children [index]; - - x++; - } - - t->image = image; -} - -static void -gtk_smiley_tree_remove (GtkSmileyTree *tree, - const gchar *text) -{ - GtkSmileyTree *t = tree; - const gchar *x = text; - gint len = 0; - - while (*x) { - gchar *pos; - - if (!t->values) - return; - - pos = strchr (t->values->str, *x); - if (pos) - t = t->children [(int) pos - (int) t->values->str]; - else - return; - x++; len++; - } - - if (t->image) - t->image = NULL; -} - -static gint -gtk_smiley_tree_lookup (GtkSmileyTree *tree, - const gchar *text) -{ - GtkSmileyTree *t = tree; - const gchar *x = text; - gint len = 0; - - while (*x) { - gchar *pos; - - if (!t->values) - break; - - pos = strchr (t->values->str, *x); - if (pos) - t = t->children [(int) pos - (int) t->values->str]; - else - break; - - x++; len++; - } - - if (t->image) - return len; - - return 0; -} - -static gchar** -gtk_smiley_tree_image (GtkSmileyTree *tree, - const gchar *text) -{ - GtkSmileyTree *t = tree; - const gchar *x = text; - - while (*x) { - gchar *pos; - - if (!t->values) - return NULL; - - pos = strchr (t->values->str, *x); - if (pos) { - t = t->children [(int) pos - (int) t->values->str]; - } else - return NULL; - - x++; - } - - return t->image; -} +/* POINT_SIZE converts from AIM font sizes to point sizes. It probably should be redone in such a + * way that it base the sizes off the default font size rather than using arbitrary font sizes. */ +#define MAX_FONT_SIZE 7 +#define POINT_SIZE(x) (_point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) +static gint _point_sizes [] = { 4, 6, 8, 10, 20, 30, 40 }; -static void -gtk_smiley_tree_destroy (GtkSmileyTree *tree) -{ - GSList *list = g_slist_append (NULL, tree); - - while (list) { - GtkSmileyTree *t = list->data; - gint i; - list = g_slist_remove(list, t); - if (t->values) { - for (i = 0; i < t->values->len; i++) - list = g_slist_append (list, t->children [i]); - g_string_free (t->values, TRUE); - g_free (t->children); - } - g_free (t); - } -} - -void -gtk_imhtml_remove_smileys (GtkIMHtml *imhtml) -{ - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - gtk_smiley_tree_destroy (imhtml->smiley_data); - imhtml->smiley_data = gtk_smiley_tree_new (); -} - -void -gtk_imhtml_reset_smileys (GtkIMHtml *imhtml) -{ - gtk_imhtml_remove_smileys(imhtml); - gtk_imhtml_init_smileys (imhtml); -} - - -struct im_image { - gchar *filename; - - gint len; - gpointer data; - - gint x,y; - gint width,height; - GtkIMHtml *imhtml; - GtkIMHtmlBit *bit; - GdkPixbuf *pb; -}; - -struct _GtkIMHtmlBit { - gint type; - - gchar *text; - struct im_image *img; - GdkPixmap *pm; - GdkBitmap *bm; - - PangoFontDescription *font; - GdkColor *fore; - GdkColor *back; - GdkColor *bg; - gboolean underline; - gboolean strike; - gchar *url; - - GList *chunks; -}; - +/* The four elements present in a <FONT> tag contained in a struct */ +typedef struct _FontDetail FontDetail; struct _FontDetail { gushort size; gchar *face; - GdkColor *fore; - GdkColor *back; + gchar *fore; + gchar *back; }; -struct line_info { - gint x; - gint y; - gint width; - gint height; - gint ascent; - - gboolean selected; - gchar *sel_start; - gchar *sel_end; - - gchar *text; - GtkIMHtmlBit *bit; -}; - -struct clickable { - gint x; - gint y; - gint width; - gint height; - GtkIMHtml *imhtml; - GtkIMHtmlBit *bit; -}; - -static GtkLayoutClass *parent_class = NULL; - -enum { - TARGET_STRING, - TARGET_TEXT, - TARGET_COMPOUND_TEXT -}; - +/* GtkIMHtml has one signal--URL_CLICKED */ enum { URL_CLICKED, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0 }; -static void gtk_imhtml_draw_bit (GtkIMHtml *, GtkIMHtmlBit *); -static GdkColor *gtk_imhtml_get_color (const gchar *); -static gint gtk_imhtml_motion_notify_event (GtkWidget *, GdkEventMotion *); -static void -gtk_imhtml_finalize (GObject *object) -{ - GtkIMHtml *imhtml; - - imhtml = GTK_IMHTML (object); - - gtk_imhtml_clear (imhtml); - - if (imhtml->selected_text) - g_string_free (imhtml->selected_text, TRUE); - - if (imhtml->default_font) - pango_font_description_free (imhtml->default_font); - if (imhtml->default_fg_color) - gdk_color_free (imhtml->default_fg_color); - if (imhtml->default_bg_color) - gdk_color_free (imhtml->default_bg_color); - if (imhtml->default_hl_color) - gdk_color_free (imhtml->default_hl_color); - if (imhtml->default_hlfg_color) - gdk_color_free (imhtml->default_hlfg_color); - - gdk_cursor_destroy (imhtml->hand_cursor); - gdk_cursor_destroy (imhtml->arrow_cursor); - - gtk_smiley_tree_destroy (imhtml->smiley_data); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gtk_imhtml_realize (GtkWidget *widget) -{ - GtkIMHtml *imhtml; - GdkWindowAttr attributes; - gint attributes_mask; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_IMHTML (widget)); - - imhtml = GTK_IMHTML (widget); - GTK_WIDGET_SET_FLAGS (imhtml, GTK_REALIZED); - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x; - attributes.y = widget->allocation.y; - attributes.width = widget->allocation.width; - attributes.height = widget->allocation.height; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK; - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - gdk_window_set_user_data (widget->window, widget); - - attributes.x = widget->style->xthickness + BORDER_SIZE; - attributes.y = widget->style->xthickness + BORDER_SIZE; - attributes.width = MAX (1, (gint) widget->allocation.width - (gint) attributes.x * 2); - attributes.height = MAX (1, (gint) widget->allocation.height - (gint) attributes.y * 2); - attributes.event_mask = gtk_widget_get_events (widget) - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_POINTER_MOTION_MASK | GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK; - - GTK_LAYOUT (imhtml)->bin_window = gdk_window_new (widget->window, - &attributes, attributes_mask); - gdk_window_set_user_data (GTK_LAYOUT (imhtml)->bin_window, widget); - - widget->style = gtk_style_attach (widget->style, widget->window); - - gdk_window_set_cursor (widget->window, imhtml->arrow_cursor); - - imhtml->context = gtk_widget_get_pango_context(widget); - imhtml->default_font = pango_font_description_copy(pango_context_get_font_description(imhtml->context)); - - gdk_window_set_background (widget->window, &widget->style->base [GTK_STATE_NORMAL]); - gdk_window_set_background (GTK_LAYOUT (imhtml)->bin_window, - &widget->style->base [GTK_STATE_NORMAL]); - - imhtml->default_fg_color = gdk_color_copy (>K_WIDGET (imhtml)->style->fg [GTK_STATE_NORMAL]); - imhtml->default_bg_color = gdk_color_copy (>K_WIDGET (imhtml)->style->base [GTK_STATE_NORMAL]); - imhtml->default_hl_color = gdk_color_copy (>K_WIDGET (imhtml)->style->bg [GTK_STATE_SELECTED]); - imhtml->default_hlfg_color=gdk_color_copy (>K_WIDGET (imhtml)->style->fg [GTK_STATE_SELECTED]); - - gdk_window_show (GTK_LAYOUT (imhtml)->bin_window); -} - -static gboolean -similar_colors (GdkColor *bg, - GdkColor *fg) -{ - if ((DIFF (bg->red, fg->red) < COLOR_DIFF) && - (DIFF (bg->green, fg->green) < COLOR_DIFF) && - (DIFF (bg->blue, fg->blue) < COLOR_DIFF)) { - fg->red = (0xff00 - COLOR_MOD > bg->red) ? - bg->red + COLOR_MOD : bg->red - COLOR_MOD; - fg->green = (0xff00 - COLOR_MOD > bg->green) ? - bg->green + COLOR_MOD : bg->green - COLOR_MOD; - fg->blue = (0xff00 - COLOR_MOD > bg->blue) ? - bg->blue + COLOR_MOD : bg->blue - COLOR_MOD; - return TRUE; - } - return FALSE; -} - -/* This is an expensive function! Don't blame me. I only stole it from eel */ -static gint -text_width(PangoContext *context, PangoFontDescription *desc, - const char *text, gint len) -{ - static PangoLayout *layout = NULL; - int width; - - if (layout == NULL) - layout = pango_layout_new(context); - - pango_layout_set_font_description(layout, desc); - pango_layout_set_text(layout, text, len); - pango_layout_get_pixel_size(layout, &width, NULL); - - /* g_object_unref(G_OBJECT(layout)); */ - - return width; -} - -static gint -string_width(PangoContext *context, PangoFontDescription *desc, - const char *text) -{ - return text_width(context, desc, text, -1); -} - -static void -set_layout_font(PangoLayout *layout, const char *text, guint len, - PangoFontDescription *desc) -{ - PangoAttribute *attr; - PangoAttrList *list; - - if (len == -1) - len = strlen(text); - - attr = pango_attr_font_desc_new(desc); - - attr->start_index = 0; - attr->end_index = len; - - list = pango_attr_list_new(); - pango_attr_list_insert(list, attr); - - pango_layout_set_attributes(layout, list); - pango_attr_list_unref(list); - - pango_layout_set_indent(layout, 0); - pango_layout_set_justify(layout, FALSE); - pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT); -} - -static gint -get_layout_first_baseline(PangoLayout* layout) -{ - PangoLayoutIter* iter = pango_layout_get_iter(layout); - gint result = pango_layout_iter_get_baseline(iter) / PANGO_SCALE; - pango_layout_iter_free(iter); - return result; -} - -static void -draw_text (GtkIMHtml *imhtml, - struct line_info *line) +/* Boring GTK stuff */ +static void gtk_imhtml_class_init (GtkIMHtmlClass *class) { - GtkIMHtmlBit *bit; - GdkGC *gc; - GdkColormap *cmap; - GdkWindow *window = GTK_LAYOUT (imhtml)->bin_window; - gfloat xoff, yoff; - GdkColor *bg, *fg; - PangoLayout *layout; - PangoFontMetrics *metrics; - gchar *start = NULL, *end = NULL; - - if (GTK_LAYOUT (imhtml)->freeze_count) - return; - - bit = line->bit; - gc = gdk_gc_new (window); - cmap = gtk_widget_get_colormap (GTK_WIDGET (imhtml)); - xoff = GTK_LAYOUT (imhtml)->hadjustment->value; - yoff = GTK_LAYOUT (imhtml)->vadjustment->value; - - if (bit->bg != NULL) { - gdk_color_alloc (cmap, bit->bg); - gdk_gc_set_foreground (gc, bit->bg); - bg = bit->bg; - } else { - gdk_color_alloc (cmap, imhtml->default_bg_color); - gdk_gc_set_foreground (gc, imhtml->default_bg_color); - bg = imhtml->default_bg_color; - } - - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff, - line->width ? line->width : imhtml->xsize, line->height); - - if (!line->text) { - gdk_gc_unref (gc); - return; - } - - if (bit->back != NULL) { - gdk_color_alloc (cmap, bit->back); - gdk_gc_set_foreground (gc, bit->back); - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff, - string_width (imhtml->context, bit->font, line->text), line->height); - bg = bit->back; - } - - bg = gdk_color_copy (bg); - - if (line->selected) { - gint width, x; - - if ((line->sel_start > line->sel_end) && (line->sel_end != NULL)) { - start = line->sel_end; - end = line->sel_start; - } else { - start = line->sel_start; - end = line->sel_end; - } - - if (start == NULL) - x = 0; - else - x = text_width (imhtml->context, bit->font, line->text, start - line->text); - - if (end == NULL) - end = strchr(line->text, '\0'); - - width = text_width (imhtml->context, bit->font, line->text, end - line->text) - x; - - gdk_gc_set_foreground (gc, imhtml->default_hl_color); - - gdk_draw_rectangle (window, gc, TRUE, x + line->x - xoff, line->y - yoff, - width, line->height); - gdk_gc_set_foreground (gc, imhtml->default_hlfg_color); - fg = gdk_color_copy(imhtml->default_hlfg_color); - } - if (bit->url) { - GdkColor *tc = gtk_imhtml_get_color ("#0000a0"); - gdk_color_alloc (cmap, tc); - gdk_gc_set_foreground (gc, tc); - fg = gdk_color_copy (tc); - gdk_color_free (tc); - } else if (bit->fore) { - gdk_color_alloc (cmap, bit->fore); - gdk_gc_set_foreground (gc, bit->fore); - fg = gdk_color_copy (bit->fore); - } else { - gdk_color_alloc (cmap, imhtml->default_fg_color); - gdk_gc_set_foreground (gc, imhtml->default_fg_color); - fg = gdk_color_copy (imhtml->default_fg_color); - } - - if (similar_colors (bg, fg)) { - gdk_color_alloc (cmap, fg); - gdk_gc_set_foreground (gc, fg); - } - - metrics = pango_context_get_metrics(imhtml->context, bit->font, NULL); - - if (start) { - int offset = 0; - - layout = gtk_widget_create_pango_layout(GTK_WIDGET(imhtml), NULL); - pango_layout_set_text(layout, line->text, start - line->text); - set_layout_font(layout, line->text, start - line->text, bit->font); - gdk_draw_layout(window, gc, line->x - xoff, - line->y - yoff + line->ascent - - get_layout_first_baseline(layout), layout); - g_object_unref(G_OBJECT(layout)); - - offset = text_width (imhtml->context, bit->font, line->text, start - line->text); - if (bit->underline || bit->url) - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, - line->y - yoff + line->ascent + 1, - offset, 1); - if (bit->strike) - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, - line->y - yoff + line->ascent - - ((pango_font_metrics_get_ascent(metrics) / PANGO_SCALE) / 2), - offset, 1); - gdk_gc_set_foreground (gc, imhtml->default_hlfg_color); - - layout = gtk_widget_create_pango_layout(GTK_WIDGET(imhtml), NULL); - pango_layout_set_text(layout, start, end - start); - set_layout_font(layout, start, end - start, bit->font); - gdk_draw_layout(window, gc, line->x - xoff + offset, - line->y - yoff + line->ascent - - get_layout_first_baseline(layout), layout); - g_object_unref(G_OBJECT(layout)); - - if (bit->underline || bit->url) - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, - line->y - yoff + line->ascent + 1, - text_width (imhtml->context, bit->font, line->text, end - start), 1); - if (bit->strike) - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, - line->y - yoff + line->ascent - - ((pango_font_metrics_get_ascent(metrics) / PANGO_SCALE) / 2), - text_width (imhtml->context, bit->font, line->text, end - start), 1); - offset = text_width (imhtml->context, bit->font, line->text, end - line->text); - gdk_gc_set_foreground (gc, fg); - - layout = gtk_widget_create_pango_layout(GTK_WIDGET(imhtml), end); - set_layout_font(layout, end, -1, bit->font); - gdk_draw_layout(window, gc, line->x - xoff + offset, - line->y - yoff + line->ascent - - get_layout_first_baseline(layout), layout); - - g_object_unref(G_OBJECT(layout)); - - if (bit->underline || bit->url) - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, - line->y - yoff + line->ascent + 1, - string_width (imhtml->context, bit->font, end), 1); - if (bit->strike) - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, - line->y - yoff + line->ascent - - ((pango_font_metrics_get_ascent(metrics) / PANGO_SCALE) / 2), - string_width (imhtml->context, bit->font, end), 1); - } else { - layout = gtk_widget_create_pango_layout(GTK_WIDGET(imhtml), line->text); - set_layout_font(layout, line->text, -1, bit->font); - gdk_draw_layout(window, gc, line->x - xoff, - line->y - yoff + line->ascent - - get_layout_first_baseline(layout), layout); - g_object_unref(G_OBJECT(layout)); - - if (bit->underline || bit->url) - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff + line->ascent + 1, - string_width (imhtml->context, bit->font, line->text), 1); - if (bit->strike) - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, - line->y - yoff + line->ascent - - ((pango_font_metrics_get_ascent(metrics) / PANGO_SCALE) / 2), - string_width (imhtml->context, bit->font, line->text), 1); - } - - pango_font_metrics_unref(metrics); - - gdk_color_free (bg); - gdk_color_free (fg); - - gdk_gc_unref (gc); -} - -static void -draw_img (GtkIMHtml *imhtml, - struct line_info *line) -{ - GtkIMHtmlBit *bit; - GdkGC *gc; - GdkColormap *cmap; - gint width, height, hoff; - GdkWindow *window = GTK_LAYOUT (imhtml)->bin_window; - gfloat xoff, yoff; - - if (GTK_LAYOUT (imhtml)->freeze_count) - return; - - bit = line->bit; - gdk_window_get_size (bit->pm, &width, &height); - hoff = (line->height - height) / 2; - xoff = GTK_LAYOUT (imhtml)->hadjustment->value; - yoff = GTK_LAYOUT (imhtml)->vadjustment->value; - gc = gdk_gc_new (window); - cmap = gtk_widget_get_colormap (GTK_WIDGET (imhtml)); - - if (bit->bg != NULL) { - gdk_color_alloc (cmap, bit->bg); - gdk_gc_set_foreground (gc, bit->bg); - } else { - gdk_color_alloc (cmap, imhtml->default_bg_color); - gdk_gc_set_foreground (gc, imhtml->default_bg_color); - } - - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff, line->width, line->height); - - if (line->selected) { - gdk_color_alloc (cmap, imhtml->default_hl_color); - gdk_gc_set_foreground(gc, imhtml->default_hl_color); - gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff, - width, line->height); - } else if (bit->back != NULL) { - gdk_color_alloc (cmap, bit->back); - gdk_gc_set_foreground (gc, bit->back); - } - - if (bit->bm) { - gdk_gc_set_clip_mask(gc, bit->bm); - gdk_gc_set_clip_origin(gc, line->x - xoff, line->y - yoff + hoff); - } - gdk_draw_pixmap (window, gc, bit->pm, 0, 0, line->x - xoff, line->y - yoff + hoff, -1, -1); - - gdk_gc_unref (gc); -} - -static void -draw_line (GtkIMHtml *imhtml, - struct line_info *line) -{ - GtkIMHtmlBit *bit; - GdkDrawable *drawable; - GdkColormap *cmap; - GdkGC *gc; - guint line_height; - gfloat xoff, yoff; - - if (GTK_LAYOUT (imhtml)->freeze_count) - return; - - xoff = GTK_LAYOUT (imhtml)->hadjustment->value; - yoff = GTK_LAYOUT (imhtml)->vadjustment->value; - bit = line->bit; - drawable = GTK_LAYOUT (imhtml)->bin_window; - cmap = gtk_widget_get_colormap (GTK_WIDGET (imhtml)); - gc = gdk_gc_new (drawable); - - if (line->selected) { - gdk_color_alloc (cmap, imhtml->default_hl_color); - gdk_gc_set_foreground (gc, imhtml->default_hl_color); - } else if (bit->bg != NULL) { - gdk_color_alloc (cmap, bit->bg); - gdk_gc_set_foreground (gc, bit->bg); - } else { - gdk_color_alloc (cmap, imhtml->default_bg_color); - gdk_gc_set_foreground (gc, imhtml->default_bg_color); - } - - gdk_draw_rectangle (drawable, gc, TRUE, line->x - xoff, line->y - yoff, - line->width, line->height); - - - if (line->selected) { - gdk_color_alloc (cmap, imhtml->default_hlfg_color); - gdk_gc_set_foreground (gc, imhtml->default_hlfg_color); - } else { - gdk_color_alloc (cmap, imhtml->default_fg_color); - gdk_gc_set_foreground (gc, imhtml->default_fg_color); - } - - line_height = line->height / 2; - - gdk_draw_rectangle (drawable, gc, TRUE, line->x - xoff, line->y - yoff + line_height / 2, - line->width, line_height); - - gdk_gc_unref (gc); -} - -static void -gtk_imhtml_draw_focus (GtkWidget *widget) -{ - GtkIMHtml *imhtml; - gint x = 0, - y = 0, - w = 0, - h = 0; - - imhtml = GTK_IMHTML (widget); - - if (!GTK_WIDGET_DRAWABLE (widget)) - return; - - if (GTK_WIDGET_HAS_FOCUS (widget)) { - gtk_paint_focus (widget->style, widget->window, GTK_STATE_NORMAL, NULL, widget, "text", - 0, 0, widget->allocation.width - 1, widget->allocation.height - 1); - x = 1; y = 1; w = 2; h = 2; - } - - gtk_paint_shadow (widget->style, widget->window, GTK_STATE_NORMAL, - GTK_SHADOW_IN, NULL, widget, "text", x, y, - widget->allocation.width - w, widget->allocation.height - h); -} - -static void -gtk_imhtml_draw_exposed (GtkIMHtml *imhtml) -{ - GList *bits; - GtkIMHtmlBit *bit; - GList *chunks; - struct line_info *line; - gfloat x, y; - guint32 width, height; - - x = GTK_LAYOUT (imhtml)->hadjustment->value; - y = GTK_LAYOUT (imhtml)->vadjustment->value; - gdk_window_get_size (GTK_LAYOUT (imhtml)->bin_window, &width, &height); - - bits = imhtml->bits; - - while (bits) { - bit = bits->data; - chunks = bit->chunks; - if (DRAW_IMG (bit)) { - if (chunks) { - line = chunks->data; - if ((line->x <= x + width) && - (line->y <= y + height) && - (x <= line->x + line->width) && - (y <= line->y + line->height)) - draw_img (imhtml, line); - } - } else if (bit->type == TYPE_SEP) { - if (chunks) { - line = chunks->data; - if ((line->x <= x + width) && - (line->y <= y + height) && - (x <= line->x + line->width) && - (y <= line->y + line->height)) - draw_line (imhtml, line); - - line = chunks->next->data; - if ((line->x <= x + width) && - (line->y <= y + height) && - (x <= line->x + line->width) && - (y <= line->y + line->height)) - draw_text (imhtml, line); - } - } else { - while (chunks) { - line = chunks->data; - if ((line->x <= x + width) && - (line->y <= y + height) && - (x <= line->x + line->width) && - (y <= line->y + line->height)) - draw_text (imhtml, line); - chunks = g_list_next (chunks); - } - } - bits = g_list_next (bits); - } - - gtk_imhtml_draw_focus (GTK_WIDGET (imhtml)); -} - -static void -gtk_imhtml_style_set (GtkWidget *widget, - GtkStyle *style) -{ - GtkIMHtml *imhtml; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_IMHTML (widget)); - - if (GTK_WIDGET_CLASS (parent_class)->style_set) - (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, style); - - if (!GTK_WIDGET_REALIZED (widget)) - return; - - imhtml = GTK_IMHTML (widget); - if (imhtml->default_fg_color) - gdk_color_free(imhtml->default_fg_color); - if (imhtml->default_bg_color) - gdk_color_free(imhtml->default_bg_color); - if (imhtml->default_hl_color) - gdk_color_free(imhtml->default_hl_color); - if (imhtml->default_hlfg_color) - gdk_color_free(imhtml->default_hlfg_color); - imhtml->default_fg_color = gdk_color_copy (>K_WIDGET (imhtml)->style->fg [GTK_STATE_NORMAL]); - imhtml->default_bg_color = gdk_color_copy (>K_WIDGET (imhtml)->style->base [GTK_STATE_NORMAL]); - imhtml->default_hl_color = gdk_color_copy (>K_WIDGET (imhtml)->style->bg [GTK_STATE_SELECTED]); - imhtml->default_hlfg_color=gdk_color_copy (>K_WIDGET (imhtml)->style->fg [GTK_STATE_SELECTED]); - gdk_window_set_background (widget->window, &widget->style->base [GTK_STATE_NORMAL]); - gdk_window_set_background (GTK_LAYOUT (imhtml)->bin_window, - &widget->style->base [GTK_STATE_NORMAL]); - gtk_imhtml_draw_exposed (imhtml); -} - -static gint -gtk_imhtml_expose_event (GtkWidget *widget, - GdkEventExpose *event) -{ - GtkIMHtml *imhtml; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_IMHTML (widget), FALSE); - - imhtml = GTK_IMHTML (widget); - gtk_imhtml_draw_exposed (imhtml); - - return FALSE; -} - -static void -gtk_imhtml_redraw_all (GtkIMHtml *imhtml) -{ - GList *b; - GtkIMHtmlBit *bit; - GtkAdjustment *vadj; - gfloat oldvalue; - gint oldy; - - vadj = GTK_LAYOUT (imhtml)->vadjustment; - oldvalue = vadj->value / vadj->upper; - oldy = imhtml->y; - - gtk_layout_freeze (GTK_LAYOUT (imhtml)); - - g_list_free (imhtml->line); - imhtml->line = NULL; - - while (imhtml->click) { - g_free (imhtml->click->data); - imhtml->click = g_list_remove (imhtml->click, imhtml->click->data); - } - - imhtml->x = 0; - imhtml->y = TOP_BORDER; - imhtml->llheight = 0; - imhtml->llascent = 0; - - if (GTK_LAYOUT (imhtml)->vadjustment->value < TOP_BORDER) - gdk_window_clear_area (GTK_LAYOUT (imhtml)->bin_window, 0, 0, - imhtml->xsize, - TOP_BORDER - GTK_LAYOUT (imhtml)->vadjustment->value); - - b = imhtml->bits; - while (b) { - bit = b->data; - b = g_list_next (b); - 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); - } - gtk_imhtml_draw_bit (imhtml, bit); - } - - GTK_LAYOUT (imhtml)->height = imhtml->y; - GTK_LAYOUT (imhtml)->vadjustment->upper = imhtml->y; - gtk_signal_emit_by_name (GTK_OBJECT (GTK_LAYOUT (imhtml)->vadjustment), "changed"); - - gtk_widget_set_usize (GTK_WIDGET (imhtml), -1, imhtml->y); - gtk_adjustment_set_value (vadj, vadj->upper * oldvalue); - - if (GTK_LAYOUT (imhtml)->bin_window && (imhtml->y < oldy)) { - GdkGC *gc; - GdkColormap *cmap; - - gc = gdk_gc_new (GTK_LAYOUT (imhtml)->bin_window); - cmap = gtk_widget_get_colormap (GTK_WIDGET (imhtml)); - - gdk_color_alloc (cmap, imhtml->default_bg_color); - gdk_gc_set_foreground (gc, imhtml->default_bg_color); - - gdk_draw_rectangle (GTK_LAYOUT (imhtml)->bin_window, gc, TRUE, - 0, imhtml->y - GTK_LAYOUT (imhtml)->vadjustment->value, - GTK_WIDGET (imhtml)->allocation.width, - oldy - imhtml->y); - - gdk_gc_unref (gc); - } - - gtk_layout_thaw (GTK_LAYOUT (imhtml)); - gtk_imhtml_draw_focus (GTK_WIDGET (imhtml)); + GtkObjectClass *object_class; + object_class = (GtkObjectClass*) class; + signals[URL_CLICKED] = gtk_signal_new("url_clicked", + GTK_RUN_FIRST, + GTK_CLASS_TYPE(object_class), + GTK_SIGNAL_OFFSET(GtkIMHtmlClass, url_clicked), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GTK_TYPE_POINTER); } -static void -gtk_imhtml_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GtkIMHtml *imhtml; - GtkLayout *layout; - gint new_xsize, new_ysize; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_IMHTML (widget)); - g_return_if_fail (allocation != NULL); - - imhtml = GTK_IMHTML (widget); - layout = GTK_LAYOUT (widget); - - widget->allocation = *allocation; - - new_xsize = MAX (1, (gint) allocation->width - - (gint) (widget->style->xthickness + BORDER_SIZE) * 2); - new_ysize = MAX (1, (gint) allocation->height - - (gint) (widget->style->ythickness + BORDER_SIZE) * 2); - - if (GTK_WIDGET_REALIZED (widget)) { - gint x = widget->style->xthickness + BORDER_SIZE; - gint y = widget->style->ythickness + BORDER_SIZE; - gdk_window_move_resize (widget->window, - allocation->x, allocation->y, - allocation->width, allocation->height); - gdk_window_move_resize (layout->bin_window, - x, y, new_xsize, new_ysize); - } - - layout->hadjustment->page_size = new_xsize; - layout->hadjustment->page_increment = new_xsize / 2; - layout->hadjustment->lower = 0; - layout->hadjustment->upper = imhtml->x; - - layout->vadjustment->page_size = new_ysize; - layout->vadjustment->page_increment = new_ysize / 2; - layout->vadjustment->lower = 0; - layout->vadjustment->upper = imhtml->y; - - gtk_signal_emit_by_name (GTK_OBJECT (layout->hadjustment), "changed"); - gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed"); - - if (new_xsize == imhtml->xsize) { - if ((GTK_LAYOUT (imhtml)->vadjustment->value > imhtml->y - new_ysize)) { - if (imhtml->y > new_ysize) - gtk_adjustment_set_value (GTK_LAYOUT (imhtml)->vadjustment, - imhtml->y - new_ysize); - else - gtk_adjustment_set_value (GTK_LAYOUT (imhtml)->vadjustment, 0); - } - return; - } - - imhtml->xsize = new_xsize; - - if (GTK_WIDGET_REALIZED (widget)) - gtk_imhtml_redraw_all (imhtml); -} - -static void -gtk_imhtml_select_none (GtkIMHtml *imhtml) -{ - GList *bits; - GList *chunks; - GtkIMHtmlBit *bit; - struct line_info *chunk; - - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - bits = imhtml->bits; - while (bits) { - bit = bits->data; - chunks = bit->chunks; - - while (chunks) { - chunk = chunks->data; - - if (chunk->selected) { - chunk->selected = FALSE; - chunk->sel_start = chunk->text; - chunk->sel_end = NULL; - if (DRAW_IMG (bit)) - draw_img (imhtml, chunk); - else if ((bit->type == TYPE_SEP) && (bit->chunks->data == chunk)) - draw_line (imhtml, chunk); - else if (chunk->width) - draw_text (imhtml, chunk); - } - - chunks = g_list_next (chunks); - } - - bits = g_list_next (bits); - } - imhtml->sel_endchunk = NULL; -} - -static gchar* -get_position (GtkIMHtml *imhtml, - struct line_info *chunk, - gint x, - gboolean smileys) -{ - gint width = x - chunk->x; - gchar *text; - gchar *pos; - guint total = 0; - - switch (chunk->bit->type) { - case TYPE_TEXT: - case TYPE_COMMENT: - text = chunk->text; - break; - case TYPE_SMILEY: - if (smileys) - return NULL; - else - text = chunk->text; - break; - default: - return NULL; - break; - } - - if (width <= 0) - return text; - - for (pos = text; *pos != '\0'; pos++) { - gint char_width = text_width (imhtml->context, chunk->bit->font, pos, 1); - if ((width > total) && (width <= total + char_width)) { - if (width < total + (char_width / 2)) - return pos; - else - return ++pos; - } - total += char_width; - } - - return pos; -} - -static GString* -append_to_sel (GString *string, - struct line_info *chunk, - gboolean smileys) -{ - GString *new_string; - gchar *buf; - gchar *start; - gint length; - - switch (chunk->bit->type) { - case TYPE_TEXT: - case TYPE_COMMENT: - start = (chunk->sel_start == NULL) ? chunk->text : chunk->sel_start; - length = (chunk->sel_end == NULL) ? strlen (start) : chunk->sel_end - start; - if (length <= 0) - return string; - buf = g_strndup (start, length); - break; - case TYPE_SMILEY: - if (smileys) { - start = (chunk->sel_start == NULL) ? chunk->bit->text : chunk->sel_start; - length = (chunk->sel_end == NULL) ? strlen (start) : chunk->sel_end - start; - if (length <= 0) - return string; - buf = g_strndup (start, length); - } else { - start = (chunk->sel_start == NULL) ? chunk->text : chunk->sel_start; - length = (chunk->sel_end == NULL) ? strlen (start) : chunk->sel_end - start; - if (length <= 0) - return string; - buf = g_strndup (start, length); - } - break; - case TYPE_BR: - buf = g_strdup ("\n"); - break; - default: - return string; - break; - } - - new_string = g_string_append (string, buf); - g_free (buf); - - return new_string; -} - -static void -chunk_select_words (struct line_info *chunk) -{ - char *start, *end; - - start = chunk->sel_start; - end = chunk->sel_end; - - if (start != chunk->text) { - if (isalnum(*start) || *start == '\'') - while (start > chunk->text && - (isalnum(*(start-1)) || *(start-1) == '\'')) - start--; - else if (isspace(*start)) - while (start > chunk->text && isspace(*(start-1))) - start--; - else if (ispunct(*start)) - while (start > chunk->text && ispunct(*(start-1))) - start--; - } - chunk->sel_start = start; - - if (end != NULL) { - if (isalnum(*end) || *end == '\'') - while (*end != '\0' && - (isalnum(*end) || *end == '\'')) - end++; - else if (isspace(*end)) - while (*end != '\0' && isspace(*end)) - end++; - else if (ispunct(*end)) - while (*end != '\0' && ispunct(*end)) - end++; - } - chunk->sel_end = end; -} - -#define COORDS_IN_CHUNK(xx, yy) (((xx) < chunk->x + chunk->width) && \ - ((yy) < chunk->y + chunk->height)) - -static void -gtk_imhtml_select_bits (GtkIMHtml *imhtml) +static void gtk_imhtml_init (GtkIMHtml *imhtml) { - GList *bits; - GList *chunks; - GtkIMHtmlBit *bit; - struct line_info *chunk; - - guint startx = imhtml->sel_startx, - starty = imhtml->sel_starty, - endx = imhtml->sel_endx, - endy = imhtml->sel_endy; - gchar *new_pos; - gint selection = 0; - guint mode = imhtml->sel_mode; - gboolean smileys = imhtml->smileys; - gboolean redraw = FALSE; - gboolean got_start = FALSE; - gboolean got_end = FALSE; - - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - if (!imhtml->selection) - return; - - if (imhtml->selected_text) { - g_string_free (imhtml->selected_text, TRUE); - imhtml->selected_text = g_string_new (""); - } - - if (mode == 2) - startx = endx = 0; - - bits = imhtml->bits; - while (bits) { - bit = bits->data; - chunks = bit->chunks; - - while (chunks) { - chunk = chunks->data; - - switch (selection) { - case 0: - if (COORDS_IN_CHUNK (startx, starty)) { - new_pos = get_position (imhtml, chunk, startx, smileys); - if (!chunk->selected || - (chunk->sel_start != new_pos) || - (chunk->sel_end != NULL)) - redraw = TRUE; - chunk->selected = TRUE; - chunk->sel_start = new_pos; - chunk->sel_end = NULL; - selection++; - got_start = TRUE; - if (mode == 2) - endy += chunk->height; - if (mode == 1) - chunk_select_words (chunk); - } - - if (COORDS_IN_CHUNK (endx, endy)) { - if (got_start) { - new_pos = get_position (imhtml, chunk, endx, smileys); - if (chunk->sel_end != new_pos) - redraw = TRUE; - if (chunk->sel_start > new_pos) { - chunk->sel_end = chunk->sel_start; - chunk->sel_start = new_pos; - } else - chunk->sel_end = new_pos; - selection = 2; - imhtml->sel_endchunk = chunk; - got_end = TRUE; - if (mode == 1) - chunk_select_words (chunk); - } else { - new_pos = get_position (imhtml, chunk, endx, smileys); - if ( !chunk->selected || - (chunk->sel_start != new_pos) || - (chunk->sel_end != NULL)) - redraw = TRUE; - chunk->selected = TRUE; - chunk->sel_start = new_pos; - chunk->sel_end = NULL; - selection++; - imhtml->sel_endchunk = chunk; - got_end = TRUE; - if (mode == 2) - starty += chunk->height; - if (mode == 1) - chunk_select_words (chunk); - } - } else if (!COORDS_IN_CHUNK (startx, starty) && !got_start) { - if (chunk->selected) - redraw = TRUE; - chunk->selected = FALSE; - chunk->sel_start = chunk->text; - chunk->sel_end = NULL; - } - - break; - case 1: - if (!got_start && COORDS_IN_CHUNK (startx, starty)) { - new_pos = get_position (imhtml, chunk, startx, smileys); - if ( !chunk->selected || - (chunk->sel_end != new_pos) || - (chunk->sel_start != chunk->text)) - redraw = TRUE; - chunk->selected = TRUE; - chunk->sel_start = chunk->text; - chunk->sel_end = new_pos; - selection++; - got_start = TRUE; - if (mode == 1) - chunk_select_words (chunk); - } else if (!got_end && COORDS_IN_CHUNK (endx, endy)) { - new_pos = get_position (imhtml, chunk, endx, smileys); - if ( !chunk->selected || - (chunk->sel_end != new_pos) || - (chunk->sel_start != chunk->text)) - redraw = TRUE; - chunk->selected = TRUE; - chunk->sel_start = chunk->text; - chunk->sel_end = new_pos; - selection++; - imhtml->sel_endchunk = chunk; - got_end = TRUE; - if (mode == 1) - chunk_select_words (chunk); - } else { - if ( !chunk->selected || - (chunk->sel_end != NULL) || - (chunk->sel_start != chunk->text)) - redraw = TRUE; - chunk->selected = TRUE; - chunk->sel_start = chunk->text; - chunk->sel_end = NULL; - } - - break; - case 2: - if (chunk->selected) - redraw = TRUE; - chunk->selected = FALSE; - chunk->sel_start = chunk->text; - chunk->sel_end = NULL; - break; - } - - if (chunk->selected == TRUE) - imhtml->selected_text = append_to_sel (imhtml->selected_text, - chunk, smileys); - - if (redraw) { - if (DRAW_IMG (bit)) - draw_img (imhtml, chunk); - else if ((bit->type == TYPE_SEP) && (bit->chunks->data == chunk)) - draw_line (imhtml, chunk); - else if (chunk->width) - draw_text (imhtml, chunk); - redraw = FALSE; - } - - chunks = g_list_next (chunks); - } - - bits = g_list_next (bits); - } -} - -static void -gtk_imhtml_select_in_chunk (GtkIMHtml *imhtml, - struct line_info *chunk) -{ - GtkIMHtmlBit *bit = chunk->bit; - gchar *new_pos; - guint endx = imhtml->sel_endx; - guint startx = imhtml->sel_startx; - guint starty = imhtml->sel_starty; - gboolean smileys = imhtml->smileys; - gboolean redraw = FALSE; - - new_pos = get_position (imhtml, chunk, endx, smileys); - if ((starty < chunk->y) || - ((starty < chunk->y + chunk->height) && (startx < endx))) { - if (chunk->sel_end != new_pos) - redraw = TRUE; - chunk->sel_end = new_pos; - } else { - if (chunk->sel_start != new_pos) - redraw = TRUE; - chunk->sel_start = new_pos; - } - - if (redraw) { - if (DRAW_IMG (bit)) - draw_img (imhtml, chunk); - else if ((bit->type == TYPE_SEP) && - (bit->chunks->data == chunk)) - draw_line (imhtml, chunk); - else if (chunk->width) - draw_text (imhtml, chunk); - } -} - -static gint -scroll_timeout (GtkIMHtml *imhtml) -{ - GdkEventMotion event; - gint x, y; - GdkModifierType mask; - - imhtml->scroll_timer = 0; - - gdk_window_get_pointer (GTK_LAYOUT (imhtml)->bin_window, &x, &y, &mask); - - if (mask & GDK_BUTTON1_MASK) { - event.is_hint = 0; - event.x = x; - event.y = y; - event.state = mask; - - gtk_imhtml_motion_notify_event (GTK_WIDGET (imhtml), &event); - } - - return FALSE; -} - -static gint -gtk_imhtml_tip_paint (GtkIMHtml *imhtml) -{ - int x,y; - GtkStyle *style; - PangoLayout *layout; - if (imhtml->tip_bit->url) - layout = gtk_widget_create_pango_layout (imhtml->tip_window, imhtml->tip_bit->url); - else if (imhtml->tip_bit->img) - layout = gtk_widget_create_pango_layout (imhtml->tip_window, imhtml->tip_bit->img->filename); - else - return FALSE; - - style = imhtml->tip_window->style; - pango_layout_get_size (layout, &x, &y); - - if (!imhtml->tip_bit) - return FALSE; + GtkTextIter iter; + imhtml->text_buffer = gtk_text_buffer_new(NULL); + gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); + imhtml->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, FALSE); + gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD); + gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), FALSE); + 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);*/ - gtk_paint_flat_box (style, imhtml->tip_window->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - NULL, imhtml->tip_window, "tooltip", 0, 0, -1, -1); - - gtk_paint_layout (style, imhtml->tip_window->window, GTK_STATE_NORMAL, TRUE, - NULL, imhtml->tip_window, "tooltip", 4, 4, layout); - - g_object_unref (layout); - return FALSE; -} - -static gint -gtk_imhtml_tip (gpointer data) -{ - GtkIMHtml *imhtml = data; - GtkWidget *widget = GTK_WIDGET (imhtml); - GtkStyle *style; - PangoLayout *layout; - gint x, y, w, h, scr_w, scr_h; - - if (!imhtml->tip_bit || !GTK_WIDGET_DRAWABLE (widget)) { - imhtml->tip_timer = 0; - return FALSE; - } - - if (imhtml->tip_window) - gtk_widget_destroy (imhtml->tip_window); - - imhtml->tip_window = gtk_window_new (GTK_WINDOW_POPUP); - gtk_widget_set_app_paintable (imhtml->tip_window, TRUE); - gtk_window_set_policy (GTK_WINDOW (imhtml->tip_window), FALSE, FALSE, TRUE); - gtk_widget_set_name (imhtml->tip_window, "gtk-tooltips"); - gtk_signal_connect_object (GTK_OBJECT (imhtml->tip_window), "expose_event", - GTK_SIGNAL_FUNC (gtk_imhtml_tip_paint), GTK_OBJECT (imhtml)); - - gtk_widget_ensure_style (imhtml->tip_window); - style = imhtml->tip_window->style; - layout = gtk_widget_create_pango_layout(imhtml->tip_window, - imhtml->tip_bit->url ? imhtml->tip_bit->url : imhtml->tip_bit->img->filename); - - scr_w = gdk_screen_width (); - scr_h = gdk_screen_height (); - - pango_layout_get_size(layout, &w, &h); - - w = PANGO_PIXELS(w) + 8; - h = PANGO_PIXELS(h) + 8; - - gdk_window_get_pointer (NULL, &x, &y, NULL); - if (GTK_WIDGET_NO_WINDOW (widget)) - y += widget->allocation.y; - - x -= ((w >> 1) + 4); - - if ((x + w) > scr_w) - x -= (x + w) - scr_w; - else if (x < 0) - x = 0; - - if ((y + h + + 4) > scr_h) - y = y - h; - else - y = y + h - 4; + /* 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 */ + 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); + gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); + gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); + gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); + gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); - gtk_widget_set_usize (imhtml->tip_window, w, h); - gtk_widget_set_uposition (imhtml->tip_window, x, y); - gtk_widget_show (imhtml->tip_window); - - imhtml->tip_timer = 0; - g_object_unref(layout); - - return FALSE; -} - -static gint -gtk_imhtml_motion_notify_event (GtkWidget *widget, - GdkEventMotion *event) -{ - gint x, y; - GdkModifierType state; - GtkIMHtml *imhtml = GTK_IMHTML (widget); - GtkAdjustment *vadj = GTK_LAYOUT (widget)->vadjustment; - GtkAdjustment *hadj = GTK_LAYOUT (widget)->hadjustment; - - if (event->is_hint) - gdk_window_get_pointer (event->window, &x, &y, &state); - else { - x = event->x + hadj->value; - y = event->y + vadj->value; - state = event->state; - } - - if (state & GDK_BUTTON1_MASK) { - gint diff; - gint height = vadj->page_size; - gint yy = y - vadj->value; - - if (((yy < 0) || (yy > height)) && - (imhtml->scroll_timer == 0) && - (vadj->upper > vadj->page_size)) { - imhtml->scroll_timer = gtk_timeout_add (100, - (GtkFunction) scroll_timeout, - imhtml); - diff = (yy < 0) ? (yy / 2) : ((yy - height) / 2); - gtk_adjustment_set_value (vadj, - MIN (vadj->value + diff, vadj->upper - height)); - } - - if (imhtml->selection) { - struct line_info *chunk = imhtml->sel_endchunk; - imhtml->sel_endx = MAX (x, 0); - imhtml->sel_endy = MAX (y, 0); - if ((chunk == NULL) || - (x < chunk->x) || - (x > chunk->x + chunk->width) || - (y < chunk->y) || - (y > chunk->y + chunk->height) || - (imhtml->sel_mode > 0)) - gtk_imhtml_select_bits (imhtml); - else - gtk_imhtml_select_in_chunk (imhtml, chunk); - } - } else { - GList *click = imhtml->click; - struct clickable *uw; - - while (click) { - uw = (struct clickable *) click->data; - if ((uw->bit->url) && (x > uw->x) && (x < uw->x + uw->width) && - (y > uw->y) && (y < uw->y + uw->height) && - (uw->bit->url || uw->bit->img)) { - if (imhtml->tip_bit != uw->bit) { - imhtml->tip_bit = uw->bit; - if (imhtml->tip_timer != 0) - gtk_timeout_remove (imhtml->tip_timer); - if (imhtml->tip_window) { - gtk_widget_destroy (imhtml->tip_window); - imhtml->tip_window = NULL; - } - imhtml->tip_timer = gtk_timeout_add (TOOLTIP_TIMEOUT, - gtk_imhtml_tip, - imhtml); - } - if (uw->bit->url) - gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window, - imhtml->hand_cursor); - return TRUE; - } - click = g_list_next (click); - } - } - - 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; - - gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window, imhtml->arrow_cursor); - - return TRUE; -} - -static gint -gtk_imhtml_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - GtkIMHtml *imhtml = GTK_IMHTML (widget); - - 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; -return TRUE; -} -struct imgsv { - GtkWidget *savedialog; - struct im_image *img; -}; - -static void -save_img (GtkObject *object, - gpointer data) -{ - struct imgsv *is = data; - struct im_image *img = is->img; - const gchar *filename; - FILE *f; - filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(is->savedialog)); - debug_printf("Saving %s\n", filename); - if (! (f=fopen(filename, "w"))) { - /* There should be some sort of dialog */ - debug_printf("Could not open file for writing.\n"); - gtk_widget_destroy(is->savedialog); - g_free(is); - return; - } - - fwrite(img->data, 1, img->len, f); - fclose(f); - gtk_widget_destroy(is->savedialog); - g_free(is); -} - -static void -save_img_dialog (GtkObject *object, - gpointer data) -{ - struct imgsv *is = g_malloc(sizeof(struct imgsv)); - struct im_image *img = data; - GtkWidget *savedialog = gtk_file_selection_new ("Gaim - Save Image"); - gtk_file_selection_set_filename (GTK_FILE_SELECTION(savedialog), img->filename); - gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(savedialog)->cancel_button), - "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), - (gpointer) savedialog); - - is->img = img; - is->savedialog = savedialog; - - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(savedialog)->ok_button), - "clicked", GTK_SIGNAL_FUNC (save_img), is); - gtk_widget_show (savedialog); - + /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ + imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); + imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); } - -static void -menu_open_url (GtkObject *object, - gpointer data) -{ - struct clickable *uw = data; - - gtk_signal_emit (GTK_OBJECT (uw->imhtml), signals [URL_CLICKED], uw->bit->url); -} - -static void -menu_copy_link (GtkObject *object, - gpointer data) -{ - struct clickable *uw = data; - GtkIMHtml *imhtml = uw->imhtml; - - if (imhtml->selected_text) - g_string_free (imhtml->selected_text, TRUE); - - gtk_imhtml_select_none (uw->imhtml); - - imhtml->selection = TRUE; - imhtml->selected_text = g_string_new (uw->bit->url); - - gtk_selection_owner_set (GTK_WIDGET (imhtml), GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); -} - -static gint -gtk_imhtml_button_press_event (GtkWidget *widget, - GdkEventButton *event) +GtkWidget *gtk_imhtml_new(void *a, void *b) { - GtkIMHtml *imhtml = GTK_IMHTML (widget); - GtkAdjustment *vadj = GTK_LAYOUT (widget)->vadjustment; - GtkAdjustment *hadj = GTK_LAYOUT (widget)->hadjustment; - gint x, y; - - x = event->x + hadj->value; - y = event->y + vadj->value; - - if (event->button == 1) { - imhtml->sel_startx = imhtml->sel_endx = x; - imhtml->sel_starty = imhtml->sel_endy = y; - imhtml->selection = TRUE; - if (event->type == GDK_BUTTON_PRESS) { - imhtml->sel_mode = 0; /* select by letter */ - gtk_imhtml_select_none (imhtml); - } else if (event->type == GDK_2BUTTON_PRESS) { - imhtml->sel_mode = 1; /* select by word */ - gtk_imhtml_select_none (imhtml); - } else if (event->type == GDK_3BUTTON_PRESS) { - imhtml->sel_mode = 2; /* select by line */ - gtk_imhtml_select_bits (imhtml); - } - } - - if (event->button == 3) { - 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)) { - static GtkWidget *menu = NULL; - GtkWidget *button; - - /* - * If a menu already exists, destroy it before creating a new one, - * thus freeing-up the memory it occupied. - */ - if(menu) - gtk_widget_destroy(menu); - - menu = gtk_menu_new(); - - 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); - } - - if (uw->bit->img) { - button = gtk_menu_item_new_with_label ("Save Image"); - gtk_signal_connect (GTK_OBJECT (button), "activate", - GTK_SIGNAL_FUNC (save_img_dialog), uw->bit->img); - 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); - imhtml->tip_timer = 0; - } - if (imhtml->tip_window) { - gtk_widget_destroy (imhtml->tip_window); - imhtml->tip_window = NULL; - } - imhtml->tip_bit = NULL; - - return TRUE; - } - click = g_list_next (click); - } - } - - return TRUE; -} - -static gint -gtk_imhtml_button_release_event (GtkWidget *widget, - GdkEventButton *event) -{ - GtkIMHtml *imhtml = GTK_IMHTML (widget); - GtkAdjustment *vadj = GTK_LAYOUT (widget)->vadjustment; - GtkAdjustment *hadj = GTK_LAYOUT (widget)->hadjustment; - gint x, y; - - x = event->x + hadj->value; - y = event->y + vadj->value; - - if ((event->button == 1) && imhtml->selection) { - if ((x == imhtml->sel_startx) && (y == imhtml->sel_starty) && - (imhtml->sel_mode == 0)) { - imhtml->sel_startx = imhtml->sel_starty = 0; - imhtml->selection = FALSE; - gtk_imhtml_select_none (imhtml); - } else { - imhtml->sel_endx = MAX (x, 0); - imhtml->sel_endy = MAX (y, 0); - gtk_imhtml_select_bits (imhtml); - } - - gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, event->time); - } - - if ((event->button == 1) && (imhtml->sel_startx == 0)) { - 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; - } - click = g_list_next (click); - } - } - - return TRUE; -} - -static void -gtk_imhtml_selection_get (GtkWidget *widget, - GtkSelectionData *sel_data, - guint sel_info, - guint32 time) -{ - GtkIMHtml *imhtml; - gchar *string; - gint length; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_IMHTML (widget)); - g_return_if_fail (sel_data->selection == GDK_SELECTION_PRIMARY); - - imhtml = GTK_IMHTML (widget); - - g_return_if_fail (imhtml->selected_text != NULL); - g_return_if_fail (imhtml->selected_text->str != NULL); - - if (imhtml->selected_text->len <= 0) - return; - - string = g_strdup (imhtml->selected_text->str); - length = strlen (string); - - if (sel_info == TARGET_STRING) { - gtk_selection_data_set (sel_data, - GDK_SELECTION_TYPE_STRING, - 8 * sizeof (gchar), - (guchar *) string, - length); - } else if ((sel_info == TARGET_TEXT) || (sel_info == TARGET_COMPOUND_TEXT)) { - guchar *text; - GdkAtom encoding; - gint format; - gint new_length; - - gdk_string_to_compound_text (string, &encoding, &format, &text, &new_length); - gtk_selection_data_set (sel_data, encoding, format, text, new_length); - gdk_free_compound_text (text); - } - - g_free (string); + return GTK_WIDGET(gtk_type_new(gtk_imhtml_get_type())); } -static gint -gtk_imhtml_selection_clear_event (GtkWidget *widget, - GdkEventSelection *event) -{ - GtkIMHtml *imhtml; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_IMHTML (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - g_return_val_if_fail (event->selection == GDK_SELECTION_PRIMARY, TRUE); - - if (!gtk_selection_clear (widget, event)) - return FALSE; - - imhtml = GTK_IMHTML (widget); - - gtk_imhtml_select_none (imhtml); - - return TRUE; -} - -static void -gtk_imhtml_adjustment_changed (GtkAdjustment *adjustment, - GtkIMHtml *imhtml) -{ - GtkLayout *layout = GTK_LAYOUT (imhtml); - - if (!GTK_WIDGET_MAPPED (imhtml) || !GTK_WIDGET_REALIZED (imhtml)) - return; - - if (layout->freeze_count) - return; - - if (layout->vadjustment->value < TOP_BORDER) - gdk_window_clear_area (layout->bin_window, 0, 0, - imhtml->xsize, TOP_BORDER - layout->vadjustment->value); - - gtk_imhtml_draw_exposed (imhtml); -} - -static void -gtk_imhtml_set_scroll_adjustments (GtkLayout *layout, - GtkAdjustment *hadj, - GtkAdjustment *vadj) -{ - gboolean need_adjust = FALSE; - - g_return_if_fail (layout != NULL); - g_return_if_fail (GTK_IS_IMHTML (layout)); - - if (hadj) - g_return_if_fail (GTK_IS_ADJUSTMENT (hadj)); - else - hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); - if (vadj) - g_return_if_fail (GTK_IS_ADJUSTMENT (vadj)); - else - vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); - - if (layout->hadjustment && (layout->hadjustment != hadj)) { - gtk_signal_disconnect_by_data (GTK_OBJECT (layout->hadjustment), layout); - gtk_object_unref (GTK_OBJECT (layout->hadjustment)); - } - - if (layout->vadjustment && (layout->vadjustment != vadj)) { - gtk_signal_disconnect_by_data (GTK_OBJECT (layout->vadjustment), layout); - gtk_object_unref (GTK_OBJECT (layout->vadjustment)); - } - - if (layout->hadjustment != hadj) { - layout->hadjustment = hadj; - gtk_object_ref (GTK_OBJECT (layout->hadjustment)); - gtk_object_sink (GTK_OBJECT (layout->hadjustment)); - - gtk_signal_connect (GTK_OBJECT (layout->hadjustment), "value_changed", - (GtkSignalFunc) gtk_imhtml_adjustment_changed, layout); - need_adjust = TRUE; - } - - if (layout->vadjustment != vadj) { - layout->vadjustment = vadj; - gtk_object_ref (GTK_OBJECT (layout->vadjustment)); - gtk_object_sink (GTK_OBJECT (layout->vadjustment)); - - gtk_signal_connect (GTK_OBJECT (layout->vadjustment), "value_changed", - (GtkSignalFunc) gtk_imhtml_adjustment_changed, layout); - need_adjust = TRUE; - } - - if (need_adjust) - gtk_imhtml_adjustment_changed (NULL, GTK_IMHTML (layout)); -} - -static void -gtk_imhtml_class_init (GtkIMHtmlClass *class) +GtkType gtk_imhtml_get_type() { - GObjectClass *gobject_class; - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - GtkLayoutClass *layout_class; - - gobject_class = (GObjectClass*) class; - object_class = (GtkObjectClass*) class; - widget_class = (GtkWidgetClass*) class; - layout_class = (GtkLayoutClass*) class; - - parent_class = gtk_type_class (GTK_TYPE_LAYOUT); - - signals [URL_CLICKED] = - gtk_signal_new ("url_clicked", - GTK_RUN_FIRST, - GTK_CLASS_TYPE (object_class), - GTK_SIGNAL_OFFSET (GtkIMHtmlClass, url_clicked), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - - gobject_class->finalize = gtk_imhtml_finalize; - - widget_class->realize = gtk_imhtml_realize; - widget_class->style_set = gtk_imhtml_style_set; - widget_class->expose_event = gtk_imhtml_expose_event; - widget_class->size_allocate = gtk_imhtml_size_allocate; - widget_class->motion_notify_event = gtk_imhtml_motion_notify_event; - widget_class->leave_notify_event = gtk_imhtml_leave_notify_event; - widget_class->button_press_event = gtk_imhtml_button_press_event; - widget_class->button_release_event = gtk_imhtml_button_release_event; - widget_class->selection_get = gtk_imhtml_selection_get; - widget_class->selection_clear_event = gtk_imhtml_selection_clear_event; - - layout_class->set_scroll_adjustments = gtk_imhtml_set_scroll_adjustments; -} - -/* the font stuff is the most insane stuff. i don't understand it half - * the time. so we're going to comment it. isn't that wonderful. */ - -/* when you g_strsplit a valid font name, these are the positions of all the various parts of it. */ -#define FNDRY 1 -#define FMLY 2 -#define WGHT 3 -#define SLANT 4 -#define SWDTH 5 -#define ADSTYL 6 -#define PXLSZ 7 -#define PTSZ 8 -#define RESX 9 -#define RESY 10 -#define SPC 11 -#define AVGWDTH 12 -#define RGSTRY 13 -#define ENCDNG 14 - -#if 0 -static const gchar* -gtk_imhtml_get_font_name (PangoFontDescription *font) -{ - return pango_font_description_get_family(font); -} -#endif - -static PangoFontDescription * -gtk_imhtml_font_load (GtkIMHtml *imhtml, - gchar *name, - gboolean bold, - gboolean italics, - gint fontsize) -{ - PangoFontDescription *default_font = imhtml->default_font; - PangoFontDescription *ret_font; - - if (!name && !bold && !italics && !fontsize) - return default_font; -// return pango_font_description_copy(default_font); - - ret_font = pango_font_description_copy(default_font); - - if (name) - pango_font_description_set_family(ret_font, name); - - if (italics) - pango_font_description_set_style(ret_font, PANGO_STYLE_ITALIC); - - if (bold) - pango_font_description_set_weight(ret_font, PANGO_WEIGHT_BOLD); - - if (fontsize) - { - pango_font_description_set_size(ret_font, - POINT_SIZE(fontsize) * PANGO_SCALE); - } - - return ret_font; -} - -static void -gtk_imhtml_init (GtkIMHtml *imhtml) -{ - static const GtkTargetEntry targets [] = { - { "STRING", 0, TARGET_STRING }, - { "TEXT", 0, TARGET_TEXT }, - { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT } - }; - - imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); - imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); - - GTK_WIDGET_SET_FLAGS (GTK_WIDGET (imhtml), GTK_CAN_FOCUS); - gtk_selection_add_targets (GTK_WIDGET (imhtml), GDK_SELECTION_PRIMARY, targets, 3); -} - -GtkType -gtk_imhtml_get_type (void) -{ - static GtkType imhtml_type = 0; + static guint imhtml_type = 0; if (!imhtml_type) { - static const GtkTypeInfo imhtml_info = { + GtkTypeInfo imhtml_info = { "GtkIMHtml", sizeof (GtkIMHtml), sizeof (GtkIMHtmlClass), (GtkClassInitFunc) gtk_imhtml_class_init, (GtkObjectInitFunc) gtk_imhtml_init, NULL, - NULL, NULL }; - - imhtml_type = gtk_type_unique (GTK_TYPE_LAYOUT, &imhtml_info); + + imhtml_type = gtk_type_unique (gtk_text_view_get_type (), &imhtml_info); } return imhtml_type; } -void -gtk_imhtml_init_smileys (GtkIMHtml *imhtml) -{ - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - imhtml->smiley_data = gtk_smiley_tree_new (); - - gtk_imhtml_associate_smiley (imhtml, ":)", smile_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-)", smile_xpm); - - gtk_imhtml_associate_smiley (imhtml, ":(", sad_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-(", sad_xpm); - - gtk_imhtml_associate_smiley (imhtml, ";)", wink_xpm); - gtk_imhtml_associate_smiley (imhtml, ";-)", wink_xpm); - - gtk_imhtml_associate_smiley (imhtml, ":-p", tongue_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-P", tongue_xpm); - - gtk_imhtml_associate_smiley (imhtml, "=-O", scream_xpm); - gtk_imhtml_associate_smiley (imhtml, "=-o", scream_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-*", kiss_xpm); - gtk_imhtml_associate_smiley (imhtml, ">:O", yell_xpm); - gtk_imhtml_associate_smiley (imhtml, ">:o", yell_xpm); - gtk_imhtml_associate_smiley (imhtml, "8-)", smile8_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-$", moneymouth_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-!", burp_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-[", embarrassed_xpm); - gtk_imhtml_associate_smiley (imhtml, ":'(", cry_xpm); - - gtk_imhtml_associate_smiley (imhtml, ":-/", think_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-\\", think_xpm); - - gtk_imhtml_associate_smiley (imhtml, ":-X", crossedlips_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-x", crossedlips_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-D", bigsmile_xpm); - gtk_imhtml_associate_smiley (imhtml, ":-d", bigsmile_xpm); - gtk_imhtml_associate_smiley (imhtml, "O:-)", angel_xpm); -} - -GtkWidget* -gtk_imhtml_new (GtkAdjustment *hadj, - GtkAdjustment *vadj) -{ - GtkIMHtml *imhtml = gtk_type_new (GTK_TYPE_IMHTML); - - gtk_imhtml_set_adjustments (imhtml, hadj, vadj); - - imhtml->im_images = NULL; - - imhtml->bits = NULL; - imhtml->click = NULL; - - imhtml->x = 0; - imhtml->y = TOP_BORDER; - imhtml->llheight = 0; - imhtml->llascent = 0; - imhtml->line = NULL; - - imhtml->selected_text = g_string_new (""); - imhtml->scroll_timer = 0; - - imhtml->img = NULL; - - imhtml->smileys = TRUE; - imhtml->comments = FALSE; - - gtk_imhtml_init_smileys (imhtml); - - return GTK_WIDGET (imhtml); -} - -void -gtk_imhtml_set_adjustments (GtkIMHtml *imhtml, - GtkAdjustment *hadj, - GtkAdjustment *vadj) -{ - gtk_layout_set_hadjustment (GTK_LAYOUT (imhtml), hadj); - gtk_layout_set_vadjustment (GTK_LAYOUT (imhtml), vadj); -} - -void -gtk_imhtml_set_defaults (GtkIMHtml *imhtml, - PangoFontDescription *font, - GdkColor *fg_color, - GdkColor *bg_color) -{ - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - if (font) { - if (imhtml->default_font) - pango_font_description_free(imhtml->default_font); - imhtml->default_font = pango_font_description_copy(font); - } - - if (fg_color) { - if (imhtml->default_fg_color) - gdk_color_free (imhtml->default_fg_color); - imhtml->default_fg_color = gdk_color_copy (fg_color); - } - - if (bg_color) { - if (imhtml->default_bg_color) - gdk_color_free (imhtml->default_bg_color); - imhtml->default_bg_color = gdk_color_copy (bg_color); - gdk_window_set_background (GTK_LAYOUT (imhtml)->bin_window, imhtml->default_bg_color); - } -} - -void -gtk_imhtml_set_img_handler (GtkIMHtml *imhtml, - GtkIMHtmlImage handler) -{ - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - imhtml->img = handler; -} - -void -gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, - gchar *text, - gchar **xpm) -{ - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - g_return_if_fail (text != NULL); - - if (xpm == NULL) - gtk_smiley_tree_remove (imhtml->smiley_data, text); - else - gtk_smiley_tree_insert (imhtml->smiley_data, text, xpm); -} - -static void -new_line (GtkIMHtml *imhtml) -{ - GList *last = g_list_last (imhtml->line); - struct line_info *li; - - if (last) { - li = last->data; - if (li->x + li->width != imhtml->xsize) - li->width = imhtml->xsize - li->x; - } - - last = imhtml->line; - if (last) { - li = last->data; - if (li->height < MIN_HEIGHT) { - while (last) { - gint diff; - li = last->data; - diff = MIN_HEIGHT - li->height; - li->height = MIN_HEIGHT; - li->ascent += diff / 2; - last = g_list_next (last); - } - imhtml->llheight = MIN_HEIGHT; - } - } - - g_list_free (imhtml->line); - imhtml->line = NULL; - - imhtml->x = 0; - imhtml->y += imhtml->llheight; - imhtml->llheight = 0; - imhtml->llascent = 0; -} - -static void -backwards_update (GtkIMHtml *imhtml, - GtkIMHtmlBit *bit, - gint height, - gint ascent) -{ - gint diff; - GList *ls = NULL; - struct line_info *li; - struct clickable *uw; - struct im_image *img; - - if (height > imhtml->llheight) { - diff = height - imhtml->llheight; - - ls = imhtml->line; - while (ls) { - li = ls->data; - li->height += diff; - if (ascent) - li->ascent = ascent; - else - li->ascent += diff / 2; - ls = g_list_next (ls); - } - - ls = imhtml->click; - while (ls) { - uw = ls->data; - if (uw->y + diff > imhtml->y) - uw->y += diff; - ls = g_list_next (ls); - } - - ls = imhtml->im_images; - while(ls) { - img = ls->data; - if (img->y + diff > imhtml->y) - img->y += diff; - ls = g_list_next(ls); - } - - imhtml->llheight = height; - if (ascent) - imhtml->llascent = ascent; - else - imhtml->llascent += diff / 2; +/* The call back for an event on a link tag. */ +void tag_event(GtkTextTag *tag, GObject *arg1, GdkEvent *event, GtkTextIter *arg2, char *url) { + if (event->type == GDK_BUTTON_RELEASE) { + /* A link was clicked--we emit the "url_clicked" signal with the URL as the argument */ + // if ((GdkEventButton)(event)->button == 1) + gtk_signal_emit (G_OBJECT(arg1), signals[URL_CLICKED], url); + } else if (event->type == GDK_ENTER_NOTIFY) { + /* make a hand cursor and a tooltip timeout -- if GTK worked as it should */ + } else if (event->type == GDK_LEAVE_NOTIFY) { + /* clear timeout and make an arrow cursor again --if GTK worked as it should */ } } -static void -add_text_renderer (GtkIMHtml *imhtml, - GtkIMHtmlBit *bit, - gchar *text) -{ - struct line_info *li; - struct clickable *uw; - PangoFontMetrics *metrics; - gint width; - - if (text) - width = string_width (imhtml->context, bit->font, text); - else - width = 0; - - li = g_new0 (struct line_info, 1); - li->x = imhtml->x; - li->y = imhtml->y; - li->width = width; - li->height = imhtml->llheight; - if (text) { - metrics = pango_context_get_metrics(imhtml->context, bit->font, NULL); - li->ascent = MAX (imhtml->llascent, pango_font_metrics_get_ascent(metrics) / PANGO_SCALE); - pango_font_metrics_unref(metrics); - } else - li->ascent = 0; - li->text = text; - li->bit = bit; - - if (bit->url) { - 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->click = g_list_append (imhtml->click, uw); - } - - bit->chunks = g_list_append (bit->chunks, li); - imhtml->line = g_list_append (imhtml->line, li); -} - -static void -add_img_renderer (GtkIMHtml *imhtml, - GtkIMHtmlBit *bit) -{ - struct line_info *li; - struct clickable *uw; - gint width; - - gdk_window_get_size (bit->pm, &width, NULL); - - li = g_new0 (struct line_info, 1); - li->x = imhtml->x; - li->y = imhtml->y; - li->width = width; - li->height = imhtml->llheight; - li->ascent = 0; - li->bit = bit; - - - if (bit->url || bit->img) { - 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->click = g_list_append (imhtml->click, uw); - } - - bit->chunks = g_list_append (bit->chunks, li); - imhtml->line = g_list_append (imhtml->line, li); - - imhtml->x += width; -} - -static void -gtk_imhtml_draw_bit (GtkIMHtml *imhtml, - GtkIMHtmlBit *bit) -{ - PangoFontMetrics *metrics; - gint width, height; - - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - g_return_if_fail (bit != NULL); - - - if ( ((bit->type == TYPE_TEXT) || - ((bit->type == TYPE_SMILEY) && !imhtml->smileys) || - ((bit->type == TYPE_COMMENT) && imhtml->comments)) && - bit->text) { - gchar *copy = g_strdup (bit->text); - gint pos = 0; - gboolean seenspace = FALSE; - gchar *tmp; - - metrics = pango_context_get_metrics(imhtml->context, bit->font, NULL); - height = (pango_font_metrics_get_ascent(metrics) + pango_font_metrics_get_descent(metrics)) / PANGO_SCALE; - width = string_width (imhtml->context, bit->font, bit->text); - - if ((imhtml->x != 0) && ((imhtml->x + width) > imhtml->xsize)) { - gint remain = imhtml->xsize - imhtml->x; - while (text_width (imhtml->context, bit->font, copy, pos) < remain) { - if (copy [pos] == ' ') - seenspace = TRUE; - pos++; - } - if (seenspace) { - while (copy [pos - 1] != ' ') pos--; - - tmp = g_strndup (copy, pos); - - backwards_update (imhtml, bit, height, pango_font_metrics_get_ascent(metrics) / PANGO_SCALE); - add_text_renderer (imhtml, bit, tmp); - } else - pos = 0; - seenspace = FALSE; - new_line (imhtml); - } - - backwards_update (imhtml, bit, height, pango_font_metrics_get_ascent(metrics) / PANGO_SCALE); - - while (pos < strlen (bit->text)) { - width = string_width (imhtml->context, bit->font, copy + pos); - if (imhtml->x + width > imhtml->xsize) { - gint newpos = 0; - gint remain = imhtml->xsize - imhtml->x; - while (text_width (imhtml->context, bit->font, copy + pos, newpos) < remain) { - if (copy [pos + newpos] == ' ') - seenspace = TRUE; - newpos++; - } - - if (seenspace) - while (copy [pos + newpos - 1] != ' ') newpos--; - - if (newpos == 0) - break; - - tmp = g_strndup (copy + pos, newpos); - pos += newpos; - - backwards_update (imhtml, bit, height, pango_font_metrics_get_ascent(metrics) / PANGO_SCALE); - add_text_renderer (imhtml, bit, tmp); - - seenspace = FALSE; - new_line (imhtml); - } else { - tmp = g_strdup (copy + pos); - - backwards_update (imhtml, bit, height, pango_font_metrics_get_ascent(metrics) / PANGO_SCALE); - add_text_renderer (imhtml, bit, tmp); - - pos = strlen (bit->text); - - imhtml->x += width; - } - } - - pango_font_metrics_unref(metrics); - g_free(copy); - } else if ((bit->type == TYPE_SMILEY) || (bit->type == TYPE_IMG)) { - if (bit->img) { - GdkPixbuf *imagepb = bit->img->pb; - GdkPixbuf *tmp = NULL; - if (gdk_pixbuf_get_width(imagepb) > imhtml->xsize - imhtml->x) - new_line (imhtml); - - if (gdk_pixbuf_get_width(imagepb) > imhtml->xsize) { - tmp = gdk_pixbuf_scale_simple(imagepb, imhtml->xsize, - gdk_pixbuf_get_height(imagepb) * - imhtml->xsize/ - gdk_pixbuf_get_width(imagepb), - GDK_INTERP_TILES); - if (bit->pm) - gdk_pixmap_unref (bit->pm); - if (bit->bm) - gdk_bitmap_unref (bit->bm); - gdk_pixbuf_render_pixmap_and_mask(tmp, &(bit->pm), &(bit->bm), 100); - gdk_pixbuf_unref(tmp); - } - else { - if (bit->pm) - gdk_pixmap_unref (bit->pm); - if (bit->bm) - gdk_bitmap_unref (bit->bm); - gdk_pixbuf_render_pixmap_and_mask(imagepb, &(bit->pm), &(bit->bm), 100); - } - } - - gdk_window_get_size (bit->pm, &width, &height); +#define VALID_TAG(x) if (!g_strncasecmp (string, x ">", strlen (x ">"))) { \ + *tag = g_strndup (string, strlen (x)); \ + *len = strlen (x) + 1; \ + return TRUE; \ + } \ + (*type)++ - if ((imhtml->x != 0) && ((imhtml->x + width) > imhtml->xsize)) - new_line (imhtml); - else - backwards_update (imhtml, bit, height, 0); - - add_img_renderer (imhtml, bit); - } else if (bit->type == TYPE_BR) { - new_line (imhtml); - add_text_renderer (imhtml, bit, NULL); - } else if (bit->type == TYPE_SEP) { - struct line_info *li; - if (imhtml->llheight) - new_line (imhtml); - - li = g_new0 (struct line_info, 1); - li->x = imhtml->x; - li->y = imhtml->y; - li->width = imhtml->xsize; - li->height = HR_HEIGHT * 2; - li->ascent = 0; - li->text = NULL; - li->bit = bit; - - bit->chunks = g_list_append (bit->chunks, li); - - imhtml->llheight = HR_HEIGHT * 2; - new_line (imhtml); - add_text_renderer (imhtml, bit, NULL); - } - -} - -void -gtk_imhtml_show_smileys (GtkIMHtml *imhtml, - gboolean show) -{ - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - imhtml->smileys = show; - - if (GTK_WIDGET_VISIBLE (GTK_WIDGET (imhtml))) - gtk_imhtml_redraw_all (imhtml); -} - -void -gtk_imhtml_show_comments (GtkIMHtml *imhtml, - gboolean show) -{ - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - imhtml->comments = show; - - if (GTK_WIDGET_VISIBLE (GTK_WIDGET (imhtml))) - gtk_imhtml_redraw_all (imhtml); -} - -static GdkColor * -gtk_imhtml_get_color (const gchar *color) -{ - GdkColor c; - - if (!gdk_color_parse (color, &c)) - return NULL; - - return gdk_color_copy (&c); -} - -static gboolean -gtk_imhtml_is_smiley (GtkIMHtml *imhtml, - const gchar *text, - gint *len) -{ - *len = gtk_smiley_tree_lookup (imhtml->smiley_data, text); - return (*len > 0); -} - -static GtkIMHtmlBit * -gtk_imhtml_new_bit (GtkIMHtml *imhtml, - gint type, - gchar *text, - gint bold, - gint italics, - gint underline, - gint strike, - FontDetail *font, - GdkColor *bg, - gchar *url, - gint pre, - gint sub, - gint sup) -{ - GtkIMHtmlBit *bit = NULL; - - g_return_val_if_fail (imhtml != NULL, NULL); - g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL); - - if ((type == TYPE_TEXT) && ((text == NULL) || (strlen (text) == 0))) - return NULL; +#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)++ - bit = g_new0 (GtkIMHtmlBit, 1); - bit->type = type; - - if ((text != NULL) && (strlen (text) != 0)) - bit->text = g_strdup (text); - - if ((font != NULL) || bold || italics || pre) { - if (font && (bold || italics || font->size || font->face || pre)) { - if (pre) { - bit->font = gtk_imhtml_font_load (imhtml, DEFAULT_PRE_FACE, bold, italics, font->size); - } else { - bit->font = gtk_imhtml_font_load (imhtml, font->face, bold, italics, font->size); - } - } else if (bold || italics || pre) { - if (pre) { - bit->font = gtk_imhtml_font_load (imhtml, DEFAULT_PRE_FACE, bold, italics, 0); - } else { - bit->font = gtk_imhtml_font_load (imhtml, NULL, bold, italics, 0); - } - } - - if (font && (type != TYPE_BR)) { - if (font->fore != NULL) - bit->fore = gdk_color_copy (font->fore); - - if (font->back != NULL) - bit->back = gdk_color_copy (font->back); - } - } - - if (((bit->type == TYPE_TEXT) || (bit->type == TYPE_SMILEY) || (bit->type == TYPE_COMMENT)) && - (bit->font == NULL)) - bit->font = pango_font_description_copy (imhtml->default_font); - - if (bg != NULL) - bit->bg = gdk_color_copy (bg); - - bit->underline = underline; - bit->strike = strike; - - if (url != NULL) - bit->url = g_strdup (url); - - if (type == TYPE_SMILEY) { - GdkColor *clr; - - if ((font != NULL) && (font->back != NULL)) - clr = font->back; - else - clr = (bg != NULL) ? bg : imhtml->default_bg_color; - - bit->pm = gdk_pixmap_create_from_xpm_d (GTK_WIDGET (imhtml)->window, - &bit->bm, - clr, - gtk_smiley_tree_image (imhtml->smiley_data, text)); - } - - return bit; -} - -#define NEW_TEXT_BIT gtk_imhtml_new_bit (imhtml, TYPE_TEXT, ws, bold, italics, underline, strike, \ - 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, 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, 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, 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 \ - { \ - GdkColormap *cmap; \ - GList *rev; \ - cmap = gtk_widget_get_colormap (GTK_WIDGET (imhtml)); \ - rev = g_list_last (newbits); \ - while (rev) { \ - GtkIMHtmlBit *bit = rev->data; \ - if (bit->bg) \ - gdk_color_free (bit->bg); \ - bit->bg = gdk_color_copy (bg); \ - if (bit->type == TYPE_BR) \ - break; \ - rev = g_list_previous (rev); \ - } \ - if (!rev) { \ - rev = g_list_last (imhtml->bits); \ - while (rev) { \ - GtkIMHtmlBit *bit = rev->data; \ - if (bit->bg) \ - gdk_color_free (bit->bg); \ - bit->bg = gdk_color_copy (bg); \ - gdk_color_alloc (cmap, bit->bg); \ - if (bit->type == TYPE_BR) \ - break; \ - rev = g_list_previous (rev); \ - } \ - } \ - } static gboolean gtk_imhtml_is_amp_escape (const gchar *string, @@ -2856,37 +220,6 @@ 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, @@ -2998,28 +331,94 @@ } } -GString* -gtk_imhtml_append_text (GtkIMHtml *imhtml, - const gchar *text, - gint len, - GtkIMHtmlOptions options) + + +#define NEW_TEXT_BIT 0 +#define NEW_HR_BIT 1 +#define NEW_BIT(x) ws [wpos] = '\0'; \ + mark2 = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); \ + gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, -1); \ + gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ + gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, mark2); \ + gtk_text_buffer_delete_mark(imhtml->text_buffer, mark2); \ + if (bold) \ + gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &siter, &iter); \ + if (italics) \ + gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &siter, &iter); \ + if (underline) \ + gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &siter, &iter); \ + if (strike) \ + gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", &siter, &iter); \ + if (sub) \ + gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUB", &siter, &iter); \ + if (sup) \ + gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUP", &siter, &iter); \ + if (pre) \ + gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "PRE", &siter, &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, &siter, &iter); \ + } \ + if (fonts) { \ + FontDetail *fd = fonts->data; \ + if (fd->fore) { \ + texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", fd->fore, NULL); \ + gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ + } \ + 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, &siter, &iter); \ + } \ + if (fd->face) { \ + texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "font", fd->face, NULL); \ + gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ + } \ + if (fd->size) { \ + texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "size-points", (double)POINT_SIZE(fd->size), NULL); \ + gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ + } \ + } \ + if (url) { \ + texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); \ + g_signal_connect(G_OBJECT(texttag), "event", G_CALLBACK(tag_event), strdup(url)); \ + gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ + } \ + wpos = 0; \ + ws[0] = 0; \ + gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ + + +/* if (x == NEW_HR_BIT) { \ + sep = gtk_hseparator_new(); \ + gtk_widget_size_request(GTK_WIDGET(imhtml), &req); \ + gtk_widget_set_size_request(sep, 20, -1); \ + anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, &iter); \ + gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), sep, anchor); \ + gtk_widget_show(sep); \ + } */ + +GString* gtk_imhtml_append_text (GtkIMHtml *imhtml, + const gchar *text, + gint len, + GtkIMHtmlOptions options) { - const gchar *c; - gboolean binary = TRUE; - gchar *ws; gint pos = 0; - gint wpos = 0; - + GString *str = NULL; + GtkTextIter iter, siter; + GtkTextMark *mark, *mark2; + GtkTextChildAnchor *anchor; + GtkTextTag *texttag; + GtkWidget *sep; + GtkRequisition req; + gchar *ws; gchar *tag; - gint tlen; + gchar *url = NULL; + gchar *bg = NULL; + gint tlen, wpos=0; gint type; - + const gchar *c; gchar amp; - gint smilelen; - - GList *newbits = NULL; - guint bold = 0, italics = 0, underline = 0, @@ -3027,386 +426,244 @@ sub = 0, sup = 0, title = 0, - pre = 0; - GSList *fonts = NULL; - GdkColor *bg = NULL; - gchar *url = NULL; + pre = 0; - GtkAdjustment *vadj; - gboolean scrolldown = TRUE; - - GString *retval = NULL; + GSList *fonts = NULL; g_return_val_if_fail (imhtml != NULL, NULL); g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL); g_return_val_if_fail (text != NULL, NULL); + g_return_val_if_fail (len != 0, NULL); + + c = text; + if (len == -1) + len = strlen(text); + ws = g_malloc(len + 1); + ws[0] = 0; if (options & GTK_IMHTML_RETURN_LOG) - retval = g_string_new (""); - - vadj = GTK_LAYOUT (imhtml)->vadjustment; - if ((vadj->value < imhtml->y - GTK_WIDGET (imhtml)->allocation.height) && - (vadj->upper >= GTK_WIDGET (imhtml)->allocation.height)) - scrolldown = FALSE; + str = g_string_new(""); - c = text; - if (len == -1) { - binary = FALSE; - len = strlen (text); - } - - ws = g_malloc (len + 1); - ws [0] = '\0'; - + gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); + mark = gtk_text_buffer_create_mark (imhtml->text_buffer, NULL, &iter, /* right grav */ FALSE); 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++; - break; - case 3: /* /B */ - case 4: /* /BOLD */ - NEW_BIT (NEW_TEXT_BIT); - if (bold) - bold--; - break; - case 5: /* I */ - case 6: /* ITALIC */ - NEW_BIT (NEW_TEXT_BIT); - italics++; - break; - case 7: /* /I */ - case 8: /* /ITALIC */ - NEW_BIT (NEW_TEXT_BIT); - if (italics) - italics--; - break; - case 9: /* U */ - case 10: /* UNDERLINE */ - NEW_BIT (NEW_TEXT_BIT); - underline++; - break; - case 11: /* /U */ - case 12: /* /UNDERLINE */ - NEW_BIT (NEW_TEXT_BIT); - if (underline) - underline--; - break; - case 13: /* S */ - case 14: /* STRIKE */ - NEW_BIT (NEW_TEXT_BIT); - strike++; - break; - case 15: /* /S */ - case 16: /* /STRIKE */ - NEW_BIT (NEW_TEXT_BIT); - if (strike) - strike--; + switch (type) + { + case 1: /* B */ + case 2: /* BOLD */ + NEW_BIT (NEW_TEXT_BIT); + bold++; + break; + case 3: /* /B */ + case 4: /* /BOLD */ + NEW_BIT (NEW_TEXT_BIT); + if (bold) + bold--; + break; + case 5: /* I */ + case 6: /* ITALIC */ + NEW_BIT (NEW_TEXT_BIT); + italics++; + break; + case 7: /* /I */ + case 8: /* /ITALIC */ + NEW_BIT (NEW_TEXT_BIT); + if (italics) + italics--; + break; + case 9: /* U */ + case 10: /* UNDERLINE */ + NEW_BIT (NEW_TEXT_BIT); + underline++; + break; + case 11: /* /U */ + case 12: /* /UNDERLINE */ + NEW_BIT (NEW_TEXT_BIT); + if (underline) + underline--; + break; + case 13: /* S */ + case 14: /* STRIKE */ + NEW_BIT (NEW_TEXT_BIT); + strike++; + break; + case 15: /* /S */ + case 16: /* /STRIKE */ + NEW_BIT (NEW_TEXT_BIT); + if (strike) + strike--; + break; + case 17: /* SUB */ + NEW_BIT (NEW_TEXT_BIT); + sub++; + break; + case 18: /* /SUB */ + NEW_BIT (NEW_TEXT_BIT); + if (sub) + sub--; + break; + case 19: /* SUP */ + NEW_BIT (NEW_TEXT_BIT); + sup++; break; - case 17: /* SUB */ - NEW_BIT (NEW_TEXT_BIT); - sub++; - break; - case 18: /* /SUB */ - NEW_BIT (NEW_TEXT_BIT); - if (sub) - sub--; - break; - case 19: /* SUP */ - NEW_BIT (NEW_TEXT_BIT); - sup++; - break; - case 20: /* /SUP */ - NEW_BIT (NEW_TEXT_BIT); - if (sup) - sup--; - break; - case 21: /* PRE */ - NEW_BIT (NEW_TEXT_BIT); - pre++; - break; - case 22: /* /PRE */ - NEW_BIT (NEW_TEXT_BIT); - if (pre) - pre--; - break; - case 23: /* TITLE */ - NEW_BIT (NEW_TEXT_BIT); - title++; - break; - case 24: /* /TITLE */ - if (title) { - if (options & GTK_IMHTML_NO_TITLE) { - wpos = 0; - ws [wpos] = '\0'; + case 20: /* /SUP */ + NEW_BIT (NEW_TEXT_BIT); + if (sup) + sup--; + break; + case 21: /* PRE */ + NEW_BIT (NEW_TEXT_BIT); + pre++; + break; + case 22: /* /PRE */ + NEW_BIT (NEW_TEXT_BIT); + if (pre) + pre--; + break; + case 23: /* TITLE */ + NEW_BIT (NEW_TEXT_BIT); + title++; + break; + case 24: /* /TITLE */ + if (title) { + if (options & GTK_IMHTML_NO_TITLE) { + wpos = 0; + ws [wpos] = '\0'; + } + title--; } - title--; - } - break; - case 25: /* BR */ - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_BR_BIT); - break; - case 26: /* HR */ - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_SEP_BIT); - break; - case 27: /* /FONT */ - if (fonts) { - FontDetail *font = fonts->data; + break; + case 25: /* BR */ + ws[wpos] = '\n'; + wpos++; 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; - } - 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: /* BINARY */ - - NEW_BIT (NEW_TEXT_BIT); - while (pos < len) { - if (!g_strncasecmp("</BINARY>", c, strlen("</BINARY>"))) + break; + case 26: /* HR */ + case 42: /* HR (opt) */ + ws[wpos++] = '\n'; + NEW_BIT(NEW_HR_BIT); + 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) + g_free (font->fore); + if (font->back) + g_free (font->back); + g_free (font); + } + break; + case 28: /* /A */ + if (url) { + NEW_BIT(NEW_TEXT_BIT); + g_free(url); + url = NULL; break; - else { - c++; - pos++; } - } - c = c - tlen; /* Because it will add this later */ - break; - case 41: /* /BINARY */ - break; - - case 42: /* HR (opt) */ - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_SEP_BIT); - break; - case 43: /* FONT (opt) */ - { - gchar *color, *back, *face, *size; - FontDetail *font; + 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: /* BINARY */ + case 41: /* /BINARY */ + break; + case 43: /* FONT (opt) */ + { + gchar *color, *back, *face, *size; + FontDetail *font, *oldfont = NULL; + 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 (fonts) + oldfont = fonts->data; - 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)) { - if (*size == '+') { - sscanf (size + 1, "%hd", &font->size); - font->size += 3; - } else if (*size == '-') { - sscanf (size + 1, "%hd", &font->size); - font->size = MAX (0, 3 - font->size); - } else if (isdigit (*size)) { - sscanf (size, "%hd", &font->size); - } - } + if (color && !(options & GTK_IMHTML_NO_COLOURS)) + font->fore = color; + else if (oldfont && oldfont->fore) + font->fore = g_strdup(oldfont->fore); - 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) - font->face = g_strdup (oldfont->face); - if (!font->fore && oldfont->fore) - font->fore = gdk_color_copy (oldfont->fore); - if (!font->back && oldfont->back) - font->back = gdk_color_copy (oldfont->back); - } - - fonts = g_slist_prepend (fonts, font); - } - break; - case 44: /* BODY (opt) */ - if (!(options & GTK_IMHTML_NO_COLOURS)) { - 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; + if (back && !(options & GTK_IMHTML_NO_COLOURS)) + 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) + font->face = g_strdup(oldfont->face); + + if (size && !(options & GTK_IMHTML_NO_SIZES)) { + if (*size == '+') { + sscanf (size + 1, "%hd", &font->size); + font->size += 3; + } else if (*size == '-') { + sscanf (size + 1, "%hd", &font->size); + font->size = MAX (0, 3 - font->size); + } else if (isdigit (*size)) { + sscanf (size, "%hd", &font->size); + } + } else if (oldfont) + font->size = oldfont->size; + g_free(size); + fonts = g_slist_prepend (fonts, font); + } + break; + case 44: /* BODY (opt) */ + if (!(options & GTK_IMHTML_NO_COLOURS)) { + char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); + if (bgcolor) { + NEW_BIT(NEW_TEXT_BIT); + if (bg) + g_free(bg); + bg = bgcolor; } } - } - break; - case 45: /* A (opt) */ - { - gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); - if (href) { - NEW_BIT (NEW_TEXT_BIT); - g_free (url); - url = href; - } - } - break; - case 46: /* IMG (opt) */ - { - gchar *src = gtk_imhtml_get_html_opt (tag, "SRC="); - gchar *id = gtk_imhtml_get_html_opt (tag, "ID="); - gchar *datasize = gtk_imhtml_get_html_opt (tag, "DATASIZE="); - gchar **xpm; - GdkColor *clr; - GtkIMHtmlBit *bit; - - if (!src) break; - - if (!imhtml->img && id && datasize) { /* This is an embedded IM image */ - char *tmp, *imagedata, *e; - const gchar *alltext; - struct im_image *img; - GdkPixbufLoader *load; - GdkPixbuf *imagepb = NULL; - GError *err; - NEW_BIT (NEW_TEXT_BIT); - if (!id || !datasize) - break; - tmp = g_malloc(strlen("<DATA ID=\"\" SIZE=\"\">") + - strlen(id) + strlen(datasize)); - g_snprintf(tmp, strlen("<DATA ID=\"\" SIZE=\"\">") + - strlen(id) + strlen(datasize) + 1, - "<DATA ID=\"%s\" SIZE=\"%s\">", id, datasize); - alltext = c; - while (g_strncasecmp(alltext, tmp, strlen(tmp)) && alltext < (c + len)) - alltext++; - alltext = alltext + strlen("<DATA ID=\"\" SIZE=\"\">") + strlen(id) + strlen(datasize); - g_free(tmp); - if (atoi(datasize) > len - pos) - break; - imagedata = g_malloc(atoi(datasize)); - memcpy(imagedata, alltext, atoi(datasize)); - - if (!GTK_WIDGET_REALIZED (imhtml)) - gtk_widget_realize (GTK_WIDGET (imhtml)); - - img = g_new0 (struct im_image, 1); - tmp = e = src; - while (*tmp){ - if (*tmp == '/' || *tmp == '\\') { - tmp++; - src = tmp; - } else - tmp++; + case 45: /* A (opt) */ + { + gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); + if (href) { + NEW_BIT (NEW_TEXT_BIT); + if (url) + g_free (url); + url = href; + } } - - *tmp = '\0'; - - img->filename = g_strdup(src); - img->len = atoi(datasize); - if (img->len) { - img->data = g_malloc(img->len); - memcpy(img->data, imagedata, img->len); - load = gdk_pixbuf_loader_new(); - - if (!gdk_pixbuf_loader_write(load, imagedata, - img->len, &err)) - debug_printf("IM Image corrupt or unreadable.\n"); - else - imagepb = gdk_pixbuf_loader_get_pixbuf(load); - img->pb = imagepb; - } - if (imagepb) { - bit = g_new0 (GtkIMHtmlBit, 1); - bit->type = TYPE_IMG; - bit->img = img; - if (url) - bit->url = g_strdup (url); - - NEW_BIT (bit); - } else { - g_free(img->filename); - g_free(img->data); - } - g_free(imagedata); - g_free(e); - g_free(id); - g_free(datasize); - + break; + case 47: /* P (opt) */ + case 48: /* H3 (opt) */ break; + case 49: /* comment */ + NEW_BIT (NEW_TEXT_BIT); + wpos = g_snprintf (ws, len, "%s", tag); + NEW_BIT (NEW_COMMENT_BIT); + break; + default: + break; } - - if (!imhtml->img || ((xpm = imhtml->img (src)) == NULL)) { - g_free (src); - break; - } - - if (!fonts || ((clr = ((FontDetail *) fonts->data)->back) == NULL)) - clr = (bg != NULL) ? bg : imhtml->default_bg_color; - - if (!GTK_WIDGET_REALIZED (imhtml)) - gtk_widget_realize (GTK_WIDGET (imhtml)); - - 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); - if (url) - bit->url = g_strdup (url); - - NEW_BIT (bit); - - g_free (src); - } - break; - case 47: /* P (opt) */ - case 48: /* H3 (opt) */ - break; - case 49: /* comment */ - NEW_BIT (NEW_TEXT_BIT); - wpos = g_snprintf (ws, len, "%s", tag); - NEW_BIT (NEW_COMMENT_BIT); - break; - default: - break; - } - g_free (tag); c += tlen; pos += tlen; } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { @@ -3415,17 +672,12 @@ pos += tlen; } else if (*c == '\n') { if (!(options & GTK_IMHTML_NO_NEWLINE)) { + ws[wpos] = '\n'; + wpos++; NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_BR_BIT); } c++; pos++; - } else if (gtk_imhtml_is_smiley (imhtml, c, &smilelen)) { - NEW_BIT (NEW_TEXT_BIT); - wpos = g_snprintf (ws, smilelen + 1, "%s", c); - NEW_BIT (NEW_SMILEY_BIT); - c += smilelen; - pos += smilelen; } else if (*c) { ws [wpos++] = *c++; pos++; @@ -3433,242 +685,88 @@ break; } } - - NEW_BIT (NEW_TEXT_BIT); - - while (newbits) { - GtkIMHtmlBit *bit = newbits->data; - imhtml->bits = g_list_append (imhtml->bits, bit); - newbits = g_list_remove (newbits, bit); - gtk_imhtml_draw_bit (imhtml, bit); - } - - GTK_LAYOUT (imhtml)->height = imhtml->y; - GTK_LAYOUT (imhtml)->vadjustment->upper = imhtml->y; - gtk_signal_emit_by_name (GTK_OBJECT (GTK_LAYOUT (imhtml)->vadjustment), "changed"); - - gtk_widget_set_usize (GTK_WIDGET (imhtml), -1, imhtml->y); - - if (!(options & GTK_IMHTML_NO_SCROLL) && - scrolldown && - (imhtml->y >= MAX (1, - (GTK_WIDGET (imhtml)->allocation.height - - (GTK_WIDGET (imhtml)->style->ythickness + BORDER_SIZE) * 2)))) - gtk_adjustment_set_value (vadj, imhtml->y - - MAX (1, (GTK_WIDGET (imhtml)->allocation.height - - (GTK_WIDGET (imhtml)->style->ythickness + - BORDER_SIZE) * 2))); - + + NEW_BIT(NEW_TEXT_BIT); if (url) { g_free (url); - if (retval) - retval = g_string_append (retval, "</A>"); + if (str) + str = g_string_append (str, "</A>"); } - if (bg) - gdk_color_free (bg); - while (fonts) { - FontDetail *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); - if (retval) - retval = g_string_append (retval, "</FONT>"); - } - if (retval) { + + if (str) { while (bold) { - retval = g_string_append (retval, "</B>"); + str = g_string_append (str, "</B>"); bold--; } while (italics) { - retval = g_string_append (retval, "</I>"); + str = g_string_append (str, "</I>"); italics--; } while (underline) { - retval = g_string_append (retval, "</U>"); + str = g_string_append (str, "</U>"); underline--; } while (strike) { - retval = g_string_append (retval, "</S>"); + str = g_string_append (str, "</S>"); strike--; } while (sub) { - retval = g_string_append (retval, "</SUB>"); + str = g_string_append (str, "</SUB>"); sub--; } while (sup) { - retval = g_string_append (retval, "</SUP>"); + str = g_string_append (str, "</SUP>"); sup--; } while (title) { - retval = g_string_append (retval, "</TITLE>"); + str = g_string_append (str, "</TITLE>"); title--; } while (pre) { - retval = g_string_append (retval, "</PRE>"); + str = g_string_append (str, "</PRE>"); pre--; } } - g_free (ws); + //g_free (ws); + gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (imhtml), mark, + 0, TRUE, 0.0, 1.0); + gtk_text_buffer_delete_mark (imhtml->text_buffer, mark); + return str; +} + +void gtk_imhtml_set_adjustments (GtkIMHtml *imhtml, + GtkAdjustment *hadj, + GtkAdjustment *vadj){} - return retval; -} +void gtk_imhtml_set_defaults (GtkIMHtml *imhtml, + PangoFontDescription *font, + GdkColor *fg_color, + GdkColor *bg_color){} + +void gtk_imhtml_set_img_handler (GtkIMHtml *imhtml, + GtkIMHtmlImage handler){} + +void gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, + gchar *text, + gchar **xpm){} +void gtk_imhtml_init_smileys (GtkIMHtml *imhtml){} +void gtk_imhtml_remove_smileys (GtkIMHtml *imhtml){} +void gtk_imhtml_reset_smileys (GtkIMHtml *imhtml){} +void gtk_imhtml_show_smileys (GtkIMHtml *imhtml, + gboolean show){} + +void gtk_imhtml_show_comments (GtkIMHtml *imhtml, + gboolean show){} void gtk_imhtml_clear (GtkIMHtml *imhtml) { - GtkLayout *layout; - - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - layout = GTK_LAYOUT (imhtml); - - 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) - pango_font_description_free(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); - if (bit->img) { - g_free(bit->img->filename); - g_free(bit->img->data); - gdk_pixbuf_unref(bit->img->pb); - g_free(bit->img); - } - - 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); - } - - while (imhtml->click) { - g_free (imhtml->click->data); - imhtml->click = g_list_remove (imhtml->click, imhtml->click->data); - } - - while (imhtml->im_images) { - imhtml->im_images = g_list_remove(imhtml->im_images, imhtml->im_images->data); - } + GtkTextIter start, end; - if (imhtml->selected_text) { - g_string_free (imhtml->selected_text, TRUE); - imhtml->selected_text = g_string_new (""); - } - - imhtml->sel_startx = 0; - imhtml->sel_starty = 0; - imhtml->sel_endx = 0; - imhtml->sel_endx = 0; - imhtml->sel_endchunk = NULL; - - 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->scroll_timer) { - gtk_timeout_remove (imhtml->scroll_timer); - imhtml->scroll_timer = 0; - } - - g_list_free(imhtml->im_images); - imhtml->im_images = NULL; - - imhtml->x = 0; - imhtml->y = TOP_BORDER; - imhtml->xsize = 0; - imhtml->llheight = 0; - imhtml->llascent = 0; - if (imhtml->line) - g_list_free (imhtml->line); - imhtml->line = NULL; - - layout->hadjustment->page_size = 0; - layout->hadjustment->page_increment = 0; - layout->hadjustment->lower = 0; - layout->hadjustment->upper = imhtml->x; - gtk_adjustment_set_value (layout->hadjustment, 0); - - layout->vadjustment->page_size = 0; - layout->vadjustment->page_increment = 0; - layout->vadjustment->lower = 0; - layout->vadjustment->upper = imhtml->y; - gtk_adjustment_set_value (layout->vadjustment, 0); - - 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"); - } + 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); } -void -gtk_imhtml_page_up (GtkIMHtml *imhtml) -{ - GtkAdjustment *vadj; - - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - vadj = GTK_LAYOUT (imhtml)->vadjustment; - gtk_adjustment_set_value (vadj, MAX (vadj->value - vadj->page_increment, - vadj->lower)); - gtk_signal_emit_by_name (GTK_OBJECT (vadj), "changed"); -} - -void -gtk_imhtml_page_down (GtkIMHtml *imhtml) -{ - GtkAdjustment *vadj; - - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - vadj = GTK_LAYOUT (imhtml)->vadjustment; - gtk_adjustment_set_value (vadj, MIN (vadj->value + vadj->page_increment, - vadj->upper - vadj->page_size)); - gtk_signal_emit_by_name (GTK_OBJECT (vadj), "changed"); -} - -void -gtk_imhtml_to_bottom (GtkIMHtml *imhtml) -{ - GtkAdjustment *vadj; - - g_return_if_fail (imhtml != NULL); - g_return_if_fail (GTK_IS_IMHTML (imhtml)); - - vadj = GTK_LAYOUT (imhtml)->vadjustment; - gtk_adjustment_set_value (vadj, vadj->upper - vadj->page_size); - gtk_signal_emit_by_name (GTK_OBJECT (vadj), "changed"); -} +void gtk_imhtml_page_up (GtkIMHtml *imhtml){} +void gtk_imhtml_page_down (GtkIMHtml *imhtml){}
--- a/src/gtkimhtml.h Fri Nov 08 06:05:03 2002 +0000 +++ b/src/gtkimhtml.h Fri Nov 08 06:10:35 2002 +0000 @@ -23,7 +23,7 @@ #define __GTK_IMHTML_H #include <gdk/gdk.h> -#include <gtk/gtklayout.h> +#include <gtk/gtktextview.h> #ifdef __cplusplus extern "C" { @@ -43,50 +43,16 @@ typedef struct _GtkIMHtmlClass GtkIMHtmlClass; struct _GtkIMHtml { - GtkLayout layout; - - PangoContext *context; - PangoFontDescription *default_font; - //GdkFont *default_font; - GdkColor *default_fg_color; - GdkColor *default_bg_color; - GdkColor *default_hl_color; - GdkColor *default_hlfg_color; - + GtkTextView text_view; + GtkTextBuffer *text_buffer; + GtkTextMark *end; + gboolean comments, smileys; GdkCursor *hand_cursor; GdkCursor *arrow_cursor; - - GList *bits; - GList *click; - struct _GtkIMHtmlBit *tip_bit; - GList *im_images; - GtkWidget *tip_window; - guint tip_timer; - - guint sel_startx, sel_starty; - guint sel_endx, sel_endy; - gboolean selection; - guint sel_mode; - GString *selected_text; - struct line_info *sel_endchunk; - guint scroll_timer; - - guint x, y; - guint xsize; - guint llheight; - guint llascent; - GList *line; - - GtkIMHtmlImage img; - - gboolean smileys; - gboolean comments; - - GtkSmileyTree *smiley_data; }; struct _GtkIMHtmlClass { - GtkLayoutClass parent_class; + GtkTextViewClass parent_class; void (*url_clicked) (GtkIMHtml *, const gchar *); }; @@ -104,8 +70,7 @@ } GtkIMHtmlOptions; GtkType gtk_imhtml_get_type (void); -GtkWidget* gtk_imhtml_new (GtkAdjustment *hadj, - GtkAdjustment *vadj); +GtkWidget* gtk_imhtml_new (void *, void *); void gtk_imhtml_set_adjustments (GtkIMHtml *imhtml, GtkAdjustment *hadj,
--- a/src/prefs.c Fri Nov 08 06:05:03 2002 +0000 +++ b/src/prefs.c Fri Nov 08 06:10:35 2002 +0000 @@ -1325,8 +1325,6 @@ gtk_box_pack_start(GTK_BOX(ret), sw2, TRUE, TRUE, 0); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw2), away_text); - GTK_LAYOUT(away_text)->hadjustment->step_increment = 10.0; - GTK_LAYOUT(away_text)->vadjustment->step_increment = 10.0; gaim_setup_imhtml(away_text); gtk_imhtml_set_defaults(GTK_IMHTML(away_text), NULL, NULL, NULL); sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_view));
--- a/src/server.c Fri Nov 08 06:05:03 2002 +0000 +++ b/src/server.c Fri Nov 08 06:10:35 2002 +0000 @@ -1157,8 +1157,6 @@ text = gtk_imhtml_new(NULL, NULL); gtk_container_add(GTK_CONTAINER(sw), text); - GTK_LAYOUT(text)->hadjustment->step_increment = 10.0; - GTK_LAYOUT(text)->vadjustment->step_increment = 10.0; gaim_setup_imhtml(text); hbox = gtk_hbox_new(FALSE, 5);