# HG changeset patch # User Eric Warmenhoven # Date 1007804932 0 # Node ID b1e300a85678c05d4f3944e6dcb5829f4bb03108 # Parent 19f786779b084e44599cee211ed8431f51bf7c66 [gaim-migrate @ 2869] rewrote the html parser in gtkimhtml. yes, that's really all i did. the reason for the massive change is because i added a length argument, which then needed to be propogated down to everything that would ever receive anything that would get drawn to the window. the new parser isn't any faster. that wasn't my goal. it's much more understandable now (hopefully, anyway). committer: Tailor Script diff -r 19f786779b08 -r b1e300a85678 configure.ac --- a/configure.ac Sat Dec 08 08:46:00 2001 +0000 +++ b/configure.ac Sat Dec 08 09:48:52 2001 +0000 @@ -85,7 +85,7 @@ AC_ARG_ENABLE(gtk2, [ --enable-gtk2 compile using GTK 2 (BROKEN)],,enable_gtk2=no) AC_ARG_ENABLE(gnome, [ --disable-gnome compile without Gnome bits],,enable_gnome=yes) -AC_ARG_ENABLE(pixbuf, [ --disable-pixbuf compile without GdkPixbuf (needed for Buddy Icons)],,enable_pixbuf=yes) +AC_ARG_ENABLE(pixbuf, [ --disable-pixbuf compile without GdkPixbuf],,enable_pixbuf=yes) AC_ARG_ENABLE(panel, [ --enable-panel compile as a GNOME applet],,enable_panel=$enable_distrib) AM_CONDITIONAL(GNOMEAPPLET, test "x$enable_panel" = "xyes") @@ -428,9 +428,9 @@ echo UI Library.................... : GTK+ 1.2 fi if test "x$enable_gtk2" = "xyes" ; then - echo Use GdkPixbuf for Buddy Icons. : yes + echo Use GdkPixbuf................. : yes else - echo Use GdkPixbuf for Buddy Icons. : $use_pixbuf + echo Use GdkPixbuf................. : $use_pixbuf fi echo echo Build with Plugin support..... : $enable_plugins diff -r 19f786779b08 -r b1e300a85678 src/away.c --- a/src/away.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/away.c Sat Dec 08 09:48:52 2001 +0000 @@ -74,7 +74,7 @@ if (g_slist_index(connections, qm->gc) >= 0) set_convo_gc(cnv, qm->gc); - write_to_conv(cnv, qm->message, qm->flags, NULL, qm->tm); + write_to_conv(cnv, qm->message, qm->flags, NULL, qm->tm, qm->len); message_queue = g_slist_remove(message_queue, qm); @@ -111,7 +111,7 @@ if (g_slist_index(connections, qm->gc) >= 0) set_convo_gc(cnv, qm->gc); - write_to_conv(cnv, qm->message, qm->flags, NULL, qm->tm); + write_to_conv(cnv, qm->message, qm->flags, NULL, qm->tm, qm->len); g_free(qm->message); g_free(qm); templist = message_queue = g_slist_remove(message_queue, qm); @@ -222,10 +222,10 @@ gaim_setup_imhtml(awaytext); gtk_widget_show(awaytext); buf = stylize(a->message, BUF_LONG); - gtk_imhtml_append_text(GTK_IMHTML(awaytext), buf, GTK_IMHTML_NO_TITLE | + gtk_imhtml_append_text(GTK_IMHTML(awaytext), buf, -1, GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_SCROLL); g_free(buf); - gtk_imhtml_append_text(GTK_IMHTML(awaytext), "
", GTK_IMHTML_NO_TITLE | + gtk_imhtml_append_text(GTK_IMHTML(awaytext), "
", -1, GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_SCROLL); clistqueuesw = gtk_scrolled_window_new(NULL, NULL); diff -r 19f786779b08 -r b1e300a85678 src/buddy.c --- a/src/buddy.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/buddy.c Sat Dec 08 09:48:52 2001 +0000 @@ -1499,7 +1499,7 @@ set_convo_gc(c, u->gc); - write_to_conv(c, b->message, WFLAG_SEND, NULL, time((time_t) NULL)); + write_to_conv(c, b->message, WFLAG_SEND, NULL, time(NULL), -1); serv_send_im(u->gc, name, b->message, 0); } } @@ -2110,7 +2110,7 @@ if (c) { char tmp[1024]; g_snprintf(tmp, sizeof(tmp), _("%s logged in."), b->name); - write_to_conv(c, tmp, WFLAG_SYSTEM, NULL, time((time_t) NULL)); + write_to_conv(c, tmp, WFLAG_SYSTEM, NULL, time(NULL), -1); } } bs->sound = 2; @@ -2165,7 +2165,7 @@ if (c) { char tmp[1024]; g_snprintf(tmp, sizeof(tmp), _("%s logged out."), b->name); - write_to_conv(c, tmp, WFLAG_SYSTEM, NULL, time((time_t) NULL)); + write_to_conv(c, tmp, WFLAG_SYSTEM, NULL, time(NULL), -1); } } diff -r 19f786779b08 -r b1e300a85678 src/buddy_chat.c --- a/src/buddy_chat.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/buddy_chat.c Sat Dec 08 09:48:52 2001 +0000 @@ -605,7 +605,7 @@ g_free(tmp); matches = g_list_remove(matches, matches->data); } - write_to_conv(c, addthis, WFLAG_NOLOG, NULL, time(NULL)); + write_to_conv(c, addthis, WFLAG_NOLOG, NULL, time(NULL), -1); gtk_editable_insert_text(GTK_EDITABLE(c->entry), partial, strlen(partial), &start); if (t == start) { t = start + strlen(partial); @@ -618,7 +618,7 @@ g_free(partial); } -gboolean meify(char *message) +gboolean meify(char *message, int len) { /* read /me-ify : if the message (post-HTML) starts with /me, remove * the "/me " part of it (including that space) and return TRUE */ @@ -626,6 +626,8 @@ int inside_HTML = 0; /* i really don't like descriptive names */ if (!c) return FALSE; /* um... this would be very bad if this happens */ + if (len == -1) + len = strlen(message); while (*c) { if (inside_HTML) { if (*c == '>') @@ -637,12 +639,13 @@ break; } c++; /* i really don't like c++ either */ + len--; } /* k, so now we've gotten past all the HTML crap. */ if (!*c) return FALSE; if (!g_strncasecmp(c, "/me ", 4)) { - sprintf(c, "%s", c + 4); + memmove(c, c + 4, len - 4); return TRUE; } else return FALSE; @@ -721,7 +724,7 @@ if ((flag & WFLAG_RECV) && find_nick(b->gc, message)) flag |= WFLAG_NICK; - write_to_conv(b, message, flag, who, mtime); + write_to_conv(b, message, flag, who, mtime, -1); } @@ -884,7 +887,7 @@ if (chat_options & OPT_CHAT_LOGON) { g_snprintf(tmp, sizeof(tmp), _("%s entered the room."), name); - write_to_conv(b, tmp, WFLAG_SYSTEM, NULL, time(NULL)); + write_to_conv(b, tmp, WFLAG_SYSTEM, NULL, time(NULL), -1); } } @@ -958,7 +961,7 @@ if (chat_options & OPT_CHAT_LOGON) { g_snprintf(tmp, sizeof(tmp), _("%s is now known as %s"), old, new); - write_to_conv(b, tmp, WFLAG_SYSTEM, NULL, time(NULL)); + write_to_conv(b, tmp, WFLAG_SYSTEM, NULL, time(NULL), -1); } } @@ -1007,7 +1010,7 @@ g_snprintf(tmp, sizeof(tmp), _("%s left the room (%s)."), buddy, reason); else g_snprintf(tmp, sizeof(tmp), _("%s left the room."), buddy); - write_to_conv(b, tmp, WFLAG_SYSTEM, NULL, time(NULL)); + write_to_conv(b, tmp, WFLAG_SYSTEM, NULL, time(NULL), -1); } } diff -r 19f786779b08 -r b1e300a85678 src/conversation.c --- a/src/conversation.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/conversation.c Sat Dec 08 09:48:52 2001 +0000 @@ -451,14 +451,12 @@ } } else { if (chat_options & OPT_CHAT_ONE_WINDOW) { - if ((convo_options & OPT_CONVO_COMBINE) && - (im_options & OPT_IM_ONE_WINDOW) && conversations) { + if ((g_list_length(chats) > 1) || + ((convo_options & OPT_CONVO_COMBINE) && + (im_options & OPT_IM_ONE_WINDOW) && conversations)) { gtk_notebook_remove_page(GTK_NOTEBOOK(chat_notebook), g_list_index(chats, c) + g_list_length(conversations)); - } else if (g_list_length(chats) > 1) { - gtk_notebook_remove_page(GTK_NOTEBOOK(chat_notebook), - g_list_index(chats, c)); } else { if (c->window) gtk_widget_destroy(c->window); @@ -1005,7 +1003,7 @@ if (err > 0) { - write_to_conv(c, buf, WFLAG_SEND, NULL, time(NULL)); + write_to_conv(c, buf, WFLAG_SEND, NULL, time(NULL), -1); if (c->makesound && (sound_options & OPT_SOUND_SEND)) play_sound(SEND); @@ -1443,7 +1441,7 @@ /* this is going to be interesting since the conversation could either be a * normal IM conversation or a chat window. but hopefully it won't matter */ -void write_to_conv(struct conversation *c, char *what, int flags, char *who, time_t mtime) +void write_to_conv(struct conversation *c, char *what, int flags, char *who, time_t mtime, gint length) { char buf[BUF_LONG]; char *str; @@ -1455,7 +1453,7 @@ char buf2[BUF_LONG]; char mdate[64]; - if (c->is_chat && !g_list_find(chats, c)) + if (c->is_chat && (!c->gc || !g_slist_find(c->gc->buddy_chats, c))) return; if (!c->is_chat && !g_list_find(conversations, c)) @@ -1492,7 +1490,7 @@ int index = g_slist_index(connections, c->gc); int sconv = strlen(c->name); int sname = strlen(who); - int swhat = strlen(what); + int swhat = length == -1 ? strlen(what) : length; UI_build_broadcast(CUI_TYPE_MESSAGE, CUI_MESSAGE_RECV, sizeof(index), &index, sizeof(sconv), &sconv, @@ -1529,7 +1527,7 @@ g_snprintf(buf2, sizeof(buf2), "%s
", mdate, what); - gtk_imhtml_append_text(GTK_IMHTML(c->text), buf2, 0); + gtk_imhtml_append_text(GTK_IMHTML(c->text), buf2, -1, 0); if (logging_options & OPT_LOG_STRIP_HTML) { char *t1 = strip_html(buf); @@ -1569,11 +1567,11 @@ } } else if (flags & WFLAG_NOLOG) { g_snprintf(buf, BUF_LONG, "%s
", what); - gtk_imhtml_append_text(GTK_IMHTML(c->text), buf, 0); + gtk_imhtml_append_text(GTK_IMHTML(c->text), buf, -1, 0); } else { if (flags & WFLAG_WHISPER) { /* if we're whispering, it's not an autoresponse */ - if (meify(what)) { + if (meify(what, length)) { str = g_malloc(1024); g_snprintf(str, 1024, "***%s", who); strcpy(colour, "#6C2585"); @@ -1583,7 +1581,7 @@ strcpy(colour, "#00ff00"); } } else { - if (meify(what)) { + if (meify(what, length)) { str = g_malloc(1024); if (flags & WFLAG_AUTO) g_snprintf(str, 1024, "%s ***%s", AUTO_RESPONSE, who); @@ -1618,11 +1616,11 @@ g_free(str); - gtk_imhtml_append_text(GTK_IMHTML(c->text), buf2, 0); - - logstr = gtk_imhtml_append_text(GTK_IMHTML(c->text), what, gtk_font_options); - - gtk_imhtml_append_text(GTK_IMHTML(c->text), "
", 0); + gtk_imhtml_append_text(GTK_IMHTML(c->text), buf2, -1, 0); + + logstr = gtk_imhtml_append_text(GTK_IMHTML(c->text), what, length, gtk_font_options); + + gtk_imhtml_append_text(GTK_IMHTML(c->text), "
", -1, 0); if (logging_options & OPT_LOG_STRIP_HTML) { char *t1, *t2; diff -r 19f786779b08 -r b1e300a85678 src/convo.h --- a/src/convo.h Sat Dec 08 08:46:00 2001 +0000 +++ b/src/convo.h Sat Dec 08 09:48:52 2001 +0000 @@ -78,6 +78,6 @@ extern void send_callback(GtkWidget *, struct conversation *); extern int close_callback(GtkWidget *, struct conversation *); -extern gboolean meify(char *); +extern gboolean meify(char *, int); #endif /* _CONVO_H_ */ diff -r 19f786779b08 -r b1e300a85678 src/core.h --- a/src/core.h Sat Dec 08 08:46:00 2001 +0000 +++ b/src/core.h Sat Dec 08 09:48:52 2001 +0000 @@ -191,7 +191,7 @@ /* Functions in server.c */ extern void serv_got_update(struct gaim_connection *, char *, int, int, time_t, time_t, int, gushort); -extern void serv_got_im(struct gaim_connection *, char *, char *, guint32, time_t); +extern void serv_got_im(struct gaim_connection *, char *, char *, guint32, time_t, gint); extern void serv_got_eviled(struct gaim_connection *, char *, int); extern void serv_got_chat_invite(struct gaim_connection *, char *, char *, char *, GList *); extern struct conversation *serv_got_joined_chat(struct gaim_connection *, int, char *); diff -r 19f786779b08 -r b1e300a85678 src/dialogs.c --- a/src/dialogs.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/dialogs.c Sat Dec 08 09:48:52 2001 +0000 @@ -1846,14 +1846,14 @@ options ^= GTK_IMHTML_NO_NEWLINE; options ^= GTK_IMHTML_NO_SCROLL; - gtk_imhtml_append_text(GTK_IMHTML(b->text), info, options); + gtk_imhtml_append_text(GTK_IMHTML(b->text), info, -1, options); va_start(ap, info); while ((more_info = va_arg(ap, char *)) != NULL) - gtk_imhtml_append_text(GTK_IMHTML(b->text), more_info, options); + gtk_imhtml_append_text(GTK_IMHTML(b->text), more_info, -1, options); va_end(ap); - gtk_imhtml_append_text(GTK_IMHTML(b->text), "
", 0); + gtk_imhtml_append_text(GTK_IMHTML(b->text), "
", -1, 0); if (away) info_dlgs = g_slist_remove(info_dlgs, b); @@ -3584,7 +3584,7 @@ g_string_append(string, buf); if (i == 30) { - gtk_imhtml_append_text(GTK_IMHTML(view->layout), string->str, view->options); + gtk_imhtml_append_text(GTK_IMHTML(view->layout), string->str, -1, view->options); g_string_free(string, TRUE); string = g_string_new(""); /* you can't have these anymore. if someone clicks on another item while one is @@ -3596,8 +3596,8 @@ } } - gtk_imhtml_append_text(GTK_IMHTML(view->layout), string->str, view->options); - gtk_imhtml_append_text(GTK_IMHTML(view->layout), "
", view->options); + gtk_imhtml_append_text(GTK_IMHTML(view->layout), string->str, -1, view->options); + gtk_imhtml_append_text(GTK_IMHTML(view->layout), "
", -1, view->options); gtk_widget_set_sensitive(view->bbox, TRUE); gtk_signal_disconnect(GTK_OBJECT(view->window), block); diff -r 19f786779b08 -r b1e300a85678 src/gaim.h --- a/src/gaim.h Sat Dec 08 08:46:00 2001 +0000 +++ b/src/gaim.h Sat Dec 08 09:48:52 2001 +0000 @@ -331,7 +331,7 @@ extern void remove_chat_buddy(struct conversation *, char *, char *); /* Functions in conversation.c */ -extern void write_to_conv(struct conversation *, char *, int, char *, time_t); +extern void write_to_conv(struct conversation *, char *, int, char *, time_t, int); extern struct conversation *find_conversation(char *); /* Functions in dialogs.c */ diff -r 19f786779b08 -r b1e300a85678 src/gtkimhtml.c --- a/src/gtkimhtml.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/gtkimhtml.c Sat Dec 08 09:48:52 2001 +0000 @@ -36,10 +36,10 @@ #endif #if GTK_CHECK_VERSION(1,3,0) -#define GTK_IMHTML_GET_STYLE_FONT(style) gtk_style_get_font (style) +# define GTK_IMHTML_GET_STYLE_FONT(style) gtk_style_get_font (style) #else -#define GTK_IMHTML_GET_STYLE_FONT(style) (style)->font -#define GTK_CLASS_TYPE(class) (class)->type +# define GTK_IMHTML_GET_STYLE_FONT(style) (style)->font +# define GTK_CLASS_TYPE(class) (class)->type #endif #include "pixmaps/angel.xpm" @@ -289,7 +289,7 @@ GtkIMHtmlBit *bit; }; -struct url_widget { +struct clickable { gint x; gint y; gint width; @@ -327,56 +327,11 @@ imhtml = GTK_IMHTML (object); - while (imhtml->bits) { - GtkIMHtmlBit *bit = imhtml->bits->data; - imhtml->bits = g_list_remove (imhtml->bits, bit); - if (bit->text) - g_free (bit->text); - if (bit->font) - gdk_font_unref (bit->font); - if (bit->fore) - gdk_color_free (bit->fore); - if (bit->back) - gdk_color_free (bit->back); - if (bit->bg) - gdk_color_free (bit->bg); - if (bit->url) - g_free (bit->url); - if (bit->pm) - gdk_pixmap_unref (bit->pm); - if (bit->bm) - gdk_bitmap_unref (bit->bm); - while (bit->chunks) { - struct line_info *li = bit->chunks->data; - if (li->text) - g_free (li->text); - bit->chunks = g_list_remove (bit->chunks, li); - g_free (li); - } - g_free (bit); - } - - if (imhtml->line) - g_list_free (imhtml->line); - - while (imhtml->urls) { - g_free (imhtml->urls->data); - imhtml->urls = g_list_remove (imhtml->urls, imhtml->urls->data); - } + gtk_imhtml_clear (imhtml); if (imhtml->selected_text) g_string_free (imhtml->selected_text, TRUE); - if (imhtml->tip_timer) { - gtk_timeout_remove (imhtml->tip_timer); - imhtml->tip_timer = 0; - } - if (imhtml->tip_window) { - gtk_widget_destroy (imhtml->tip_window); - imhtml->tip_window = NULL; - } - imhtml->tip_bit = NULL; - if (imhtml->default_font) gdk_font_unref (imhtml->default_font); if (imhtml->default_fg_color) @@ -831,9 +786,9 @@ g_list_free (imhtml->line); imhtml->line = NULL; - while (imhtml->urls) { - g_free (imhtml->urls->data); - imhtml->urls = g_list_remove (imhtml->urls, imhtml->urls->data); + while (imhtml->click) { + g_free (imhtml->click->data); + imhtml->click = g_list_remove (imhtml->click, imhtml->click->data); } imhtml->x = 0; @@ -1454,11 +1409,11 @@ gtk_imhtml_select_in_chunk (imhtml, chunk); } } else { - GList *urls = imhtml->urls; - struct url_widget *uw; - - while (urls) { - uw = (struct url_widget *) urls->data; + GList *click = imhtml->click; + struct clickable *uw; + + while (click) { + uw = (struct clickable *) click->data; if ((x > uw->x) && (x < uw->x + uw->width) && (y > uw->y) && (y < uw->y + uw->height)) { if (imhtml->tip_bit != uw->bit) { @@ -1477,7 +1432,7 @@ imhtml->hand_cursor); return TRUE; } - urls = g_list_next (urls); + click = g_list_next (click); } } @@ -1519,7 +1474,7 @@ menu_open_url (GtkObject *object, gpointer data) { - struct url_widget *uw = data; + struct clickable *uw = data; gtk_signal_emit (GTK_OBJECT (uw->imhtml), signals [URL_CLICKED], uw->bit->url); } @@ -1528,7 +1483,7 @@ menu_copy_link (GtkObject *object, gpointer data) { - struct url_widget *uw = data; + struct clickable *uw = data; GtkIMHtml *imhtml = uw->imhtml; if (imhtml->selected_text) @@ -1562,29 +1517,31 @@ } if (event->button == 3) { - GList *urls = imhtml->urls; - struct url_widget *uw; - - while (urls) { - uw = urls->data; + GList *click = imhtml->click; + struct clickable *uw; + + while (click) { + uw = click->data; if ((x > uw->x) && (x < uw->x + uw->width) && (y > uw->y) && (y < uw->y + uw->height)) { GtkWidget *menu = gtk_menu_new (); - - GtkWidget *button = gtk_menu_item_new_with_label ("Open URL"); - gtk_signal_connect (GTK_OBJECT (button), "activate", - GTK_SIGNAL_FUNC (menu_open_url), uw); - gtk_menu_append (GTK_MENU (menu), button); - gtk_widget_show (button); - - button = gtk_menu_item_new_with_label ("Copy Link Location"); - gtk_signal_connect (GTK_OBJECT (button), "activate", - GTK_SIGNAL_FUNC (menu_copy_link), uw); - gtk_menu_append (GTK_MENU (menu), button); - gtk_widget_show (button); - - gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, - 3, event->time); + GtkWidget *button; + + if (uw->bit->url) { + button = gtk_menu_item_new_with_label ("Open URL"); + gtk_signal_connect (GTK_OBJECT (button), "activate", + GTK_SIGNAL_FUNC (menu_open_url), uw); + gtk_menu_append (GTK_MENU (menu), button); + gtk_widget_show (button); + + button = gtk_menu_item_new_with_label ("Copy Link Location"); + gtk_signal_connect (GTK_OBJECT (button), "activate", + GTK_SIGNAL_FUNC (menu_copy_link), uw); + gtk_menu_append (GTK_MENU (menu), button); + gtk_widget_show (button); + } + + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, event->time); if (imhtml->tip_timer) { gtk_timeout_remove (imhtml->tip_timer); @@ -1598,7 +1555,7 @@ return TRUE; } - urls = g_list_next (urls); + click = g_list_next (click); } } @@ -1632,18 +1589,18 @@ } if ((event->button == 1) && (imhtml->sel_startx == 0)) { - GList *urls = imhtml->urls; - struct url_widget *uw; - - while (urls) { - uw = (struct url_widget *) urls->data; + GList *click = imhtml->click; + struct clickable *uw; + + while (click) { + uw = (struct clickable *) click->data; if ((x > uw->x) && (x < uw->x + uw->width) && (y > uw->y) && (y < uw->y + uw->height)) { gtk_signal_emit (GTK_OBJECT (imhtml), signals [URL_CLICKED], uw->bit->url); return TRUE; } - urls = g_list_next (urls); + click = g_list_next (click); } } @@ -2092,7 +2049,7 @@ gtk_imhtml_set_adjustments (imhtml, hadj, vadj); imhtml->bits = NULL; - imhtml->urls = NULL; + imhtml->click = NULL; imhtml->x = 0; imhtml->y = TOP_BORDER; @@ -2222,7 +2179,7 @@ gint diff; GList *ls = NULL; struct line_info *li; - struct url_widget *uw; + struct clickable *uw; if (height > imhtml->llheight) { diff = height - imhtml->llheight; @@ -2238,7 +2195,7 @@ ls = g_list_next (ls); } - ls = imhtml->urls; + ls = imhtml->click; while (ls) { uw = ls->data; if (uw->y + diff > imhtml->y) @@ -2260,7 +2217,7 @@ gchar *text) { struct line_info *li; - struct url_widget *uw; + struct clickable *uw; gint width; if (text) @@ -2281,14 +2238,14 @@ li->bit = bit; if (bit->url) { - uw = g_new0 (struct url_widget, 1); + uw = g_new0 (struct clickable, 1); uw->x = imhtml->x; uw->y = imhtml->y; uw->width = width; uw->height = imhtml->llheight; uw->imhtml = imhtml; uw->bit = bit; - imhtml->urls = g_list_append (imhtml->urls, uw); + imhtml->click = g_list_append (imhtml->click, uw); } bit->chunks = g_list_append (bit->chunks, li); @@ -2300,7 +2257,7 @@ GtkIMHtmlBit *bit) { struct line_info *li; - struct url_widget *uw; + struct clickable *uw; gint width; gdk_window_get_size (bit->pm, &width, NULL); @@ -2314,14 +2271,14 @@ li->bit = bit; if (bit->url) { - uw = g_new0 (struct url_widget, 1); + uw = g_new0 (struct clickable, 1); uw->x = imhtml->x; uw->y = imhtml->y; uw->width = width; uw->height = imhtml->llheight; uw->imhtml = imhtml; uw->bit = bit; - imhtml->urls = g_list_append (imhtml->urls, uw); + imhtml->click = g_list_append (imhtml->click, uw); } bit->chunks = g_list_append (bit->chunks, li); @@ -2482,11 +2439,13 @@ return gdk_color_copy (&c); } -static gint +static gboolean gtk_imhtml_is_smiley (GtkIMHtml *imhtml, - const gchar *text) + const gchar *text, + gint *len) { - return gtk_smiley_tree_lookup (imhtml->smiley_data, text); + *len = gtk_smiley_tree_lookup (imhtml->smiley_data, text); + return (*len > 0); } static GtkIMHtmlBit * @@ -2500,7 +2459,9 @@ FontDetail *font, GdkColor *bg, gchar *url, - gint pre) + gint pre, + gint sub, + gint sup) { GtkIMHtmlBit *bit = NULL; @@ -2571,17 +2532,19 @@ } #define NEW_TEXT_BIT gtk_imhtml_new_bit (imhtml, TYPE_TEXT, ws, bold, italics, underline, strike, \ - fonts ? fonts->data : NULL, bg, url, pre) + fonts ? fonts->data : NULL, bg, url, pre, sub, sup) #define NEW_SMILEY_BIT gtk_imhtml_new_bit (imhtml, TYPE_SMILEY, ws, bold, italics, underline, strike, \ - fonts ? fonts->data : NULL, bg, url, pre) -#define NEW_SEP_BIT gtk_imhtml_new_bit (imhtml, TYPE_SEP, NULL, 0, 0, 0, 0, NULL, bg, NULL, 0) + fonts ? fonts->data : NULL, bg, url, pre, sub, sup) +#define NEW_SEP_BIT gtk_imhtml_new_bit (imhtml, TYPE_SEP, NULL, 0, 0, 0, 0, NULL, bg, NULL, 0, 0, 0) #define NEW_BR_BIT gtk_imhtml_new_bit (imhtml, TYPE_BR, NULL, 0, 0, 0, 0, \ - fonts ? fonts->data : NULL, bg, NULL, 0) + fonts ? fonts->data : NULL, bg, NULL, 0, 0, 0) #define NEW_COMMENT_BIT gtk_imhtml_new_bit (imhtml, TYPE_COMMENT, ws, bold, italics, underline, strike, \ - fonts ? fonts->data : NULL, bg, url, pre) - -#define NEW_BIT(bit) { GtkIMHtmlBit *tmp = bit; if (tmp != NULL) \ - newbits = g_list_append (newbits, tmp); } + fonts ? fonts->data : NULL, bg, url, pre, sub, sup) + +#define NEW_BIT(bit) ws [wpos] = '\0'; \ + { GtkIMHtmlBit *tmp = bit; if (tmp != NULL) \ + newbits = g_list_append (newbits, tmp); } \ + wpos = 0; ws [wpos] = '\0' #define UPDATE_BG_COLORS \ { \ @@ -2614,9 +2577,9 @@ } static gboolean -is_amp_escape (const gchar *string, - gchar *replace, - gint *length) +gtk_imhtml_is_amp_escape (const gchar *string, + gchar *replace, + gint *length) { g_return_val_if_fail (string != NULL, FALSE); g_return_val_if_fail (replace != NULL, FALSE); @@ -2662,20 +2625,169 @@ return TRUE; } +#define VALID_TAG(x) if (!g_strncasecmp (string, x ">", strlen (x ">"))) { \ + *tag = g_strndup (string, strlen (x)); \ + *len = strlen (x) + 1; \ + return TRUE; \ + } \ + (*type)++ + +#define VALID_OPT_TAG(x) if (!g_strncasecmp (string, x " ", strlen (x " "))) { \ + const gchar *c = string + strlen (x " "); \ + gchar e = '"'; \ + gboolean quote = FALSE; \ + while (*c) { \ + if (*c == '"' || *c == '\'') { \ + if (quote && (*c == e)) \ + quote = !quote; \ + else if (!quote) { \ + quote = !quote; \ + e = *c; \ + } \ + } else if (!quote && (*c == '>')) \ + break; \ + c++; \ + } \ + if (*c) { \ + *tag = g_strndup (string, c - string); \ + *len = c - string + 1; \ + return TRUE; \ + } \ + } \ + (*type)++ + +static gboolean +gtk_imhtml_is_tag (const gchar *string, + gchar **tag, + gint *len, + gint *type) +{ + *type = 1; + + if (!strchr (string, '>')) + return FALSE; + + VALID_TAG ("B"); + VALID_TAG ("BOLD"); + VALID_TAG ("/B"); + VALID_TAG ("/BOLD"); + VALID_TAG ("I"); + VALID_TAG ("ITALIC"); + VALID_TAG ("/I"); + VALID_TAG ("/ITALIC"); + VALID_TAG ("U"); + VALID_TAG ("UNDERLINE"); + VALID_TAG ("/U"); + VALID_TAG ("/UNDERLINE"); + VALID_TAG ("S"); + VALID_TAG ("STRIKE"); + VALID_TAG ("/S"); + VALID_TAG ("/STRIKE"); + VALID_TAG ("SUB"); + VALID_TAG ("/SUB"); + VALID_TAG ("SUP"); + VALID_TAG ("/SUP"); + VALID_TAG ("PRE"); + VALID_TAG ("/PRE"); + VALID_TAG ("TITLE"); + VALID_TAG ("/TITLE"); + VALID_TAG ("BR"); + VALID_TAG ("HR"); + VALID_TAG ("/FONT"); + VALID_TAG ("/A"); + VALID_TAG ("P"); + VALID_TAG ("/P"); + VALID_TAG ("H3"); + VALID_TAG ("/H3"); + VALID_TAG ("HTML"); + VALID_TAG ("/HTML"); + VALID_TAG ("BODY"); + VALID_TAG ("/BODY"); + VALID_TAG ("FONT"); + VALID_TAG ("HEAD"); + VALID_TAG ("HEAD"); + + VALID_OPT_TAG ("HR"); + VALID_OPT_TAG ("FONT"); + VALID_OPT_TAG ("BODY"); + VALID_OPT_TAG ("A"); + VALID_OPT_TAG ("IMG"); + VALID_OPT_TAG ("P"); + VALID_OPT_TAG ("H3"); + + if (!g_strncasecmp(string, "!--", strlen ("!--"))) { + gchar *e = strstr (string, "-->"); + if (e) { + *len = e - string + strlen ("-->"); + *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); + return TRUE; + } + } + + return FALSE; +} + +static gchar* +gtk_imhtml_get_html_opt (gchar *tag, + const gchar *opt) +{ + gchar *t = tag; + gchar *e, *a; + + while (g_strncasecmp (t, opt, strlen (opt))) { + gboolean quote = FALSE; + if (*t == '\0') break; + while (*t && !((*t == ' ') && !quote)) { + if (*t == '\"') + quote = ! quote; + t++; + } + while (*t && (*t == ' ')) t++; + } + + if (!g_strncasecmp (t, opt, strlen (opt))) { + t += strlen (opt); + } else { + return NULL; + } + + if ((*t == '\"') || (*t == '\'')) { + e = a = ++t; + while (*e && (*e != *(t - 1))) e++; + if (*e != '\0') { + *e = '\0'; + return g_strdup (a); + } else { + return NULL; + } + } else { + e = a = t; + while (*e && !isspace ((gint) *e)) e++; + *e = '\0'; + return g_strdup (a); + } +} + GString* gtk_imhtml_append_text (GtkIMHtml *imhtml, const gchar *text, + gint len, GtkIMHtmlOptions options) { const gchar *c; - gboolean intag = FALSE; - gint tagquote = 0; - gboolean incomment = FALSE; + gboolean binary = TRUE; gchar *ws; - gchar *tag; + gint pos = 0; gint wpos = 0; - gint tpos = 0; + + gchar *tag; + gint tlen; + gint type; + + gchar amp; + int smilelen; + GList *newbits = NULL; guint bold = 0, @@ -2708,345 +2820,184 @@ scrolldown = FALSE; c = text; - ws = g_malloc (strlen (text) + 1); - tag = g_malloc (strlen (text) + 1); - + if (len == -1) { + binary = FALSE; + len = strlen (text); + } + + ws = g_malloc (len + 1); ws [0] = '\0'; - while (*c) { - if (*c == '<') { - if (intag && (tagquote != 1)) { - char *d; - tag [tpos] = 0; - d = tag; - while (*d) { - if ((smilelen = gtk_imhtml_is_smiley (imhtml, d)) != 0) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - g_snprintf (ws, smilelen + 1, "%s", d); - NEW_BIT (NEW_SMILEY_BIT); - d += smilelen; - } else if (*d == '&') { - gchar replace; - gint length; - if (is_amp_escape (d, &replace, &length)) { - ws [wpos++] = replace; - d += length; - } else { - ws [wpos++] = *d++; - } - } else if (*d == '\n') { - if (!(options & GTK_IMHTML_NO_NEWLINE)) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_BR_BIT); - } - d++; - } else { - ws [wpos++] = *d++; - } - } - tpos = 0; - } - - if (incomment) { - ws [wpos++] = *c++; - continue; - } - - if (!g_strncasecmp (c, "", strlen ("-->"))) { - gchar *tmp; - ws [wpos] = 0; - wpos = 0; - tmp = g_strdup (ws); - ws [wpos] = 0; - strcat (ws, tag); - NEW_BIT (NEW_TEXT_BIT); - ws [wpos] = 0; - strcat (ws, tmp + strlen (""); - } else if (*c == '>' && intag && (tagquote != 1)) { - gboolean got_tag = FALSE; - tag [tpos++] = *c++; - tag [tpos] = 0; - ws [wpos] = 0; - - if (!g_strcasecmp (tag, "") || !g_strcasecmp (tag, "")) { - got_tag = TRUE; + while (pos < len) { + if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { + c++; + pos++; + switch (type) { + case 1: /* B */ + case 2: /* BOLD */ NEW_BIT (NEW_TEXT_BIT); bold++; - } else if (!g_strcasecmp (tag, "") || !g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 3: /* /B */ + case 4: /* /BOLD */ NEW_BIT (NEW_TEXT_BIT); - if (bold) { + if (bold) bold--; - } - } else if (!g_strcasecmp (tag, "") || !g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 5: /* I */ + case 6: /* ITALIC */ NEW_BIT (NEW_TEXT_BIT); italics++; - } else if (!g_strcasecmp (tag, "") || !g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 7: /* /I */ + case 8: /* /ITALIC */ NEW_BIT (NEW_TEXT_BIT); - if (italics) { + if (italics) italics--; - } - } else if (!g_strcasecmp (tag, "") || !g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 9: /* U */ + case 10: /* UNDERLINE */ NEW_BIT (NEW_TEXT_BIT); underline++; - } else if (!g_strcasecmp (tag, "") || !g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 11: /* /U */ + case 12: /* /UNDERLINE */ NEW_BIT (NEW_TEXT_BIT); - if (underline) { + if (underline) underline--; - } - } else if (!g_strcasecmp (tag, "") || !g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 13: /* S */ + case 14: /* STRIKE */ NEW_BIT (NEW_TEXT_BIT); strike++; - } else if (!g_strcasecmp (tag, "") || !g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 15: /* /S */ + case 16: /* /STRIKE */ NEW_BIT (NEW_TEXT_BIT); - if (strike) { + if (strike) strike--; - } - } else if (!g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 17: /* SUB */ NEW_BIT (NEW_TEXT_BIT); sub++; - } else if (!g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 18: /* /SUB */ NEW_BIT (NEW_TEXT_BIT); - if (sub) { + if (sub) sub--; - } - } else if (!g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 19: /* SUP */ NEW_BIT (NEW_TEXT_BIT); sup++; - } else if (!g_strcasecmp (tag, "")) { - got_tag = TRUE; + break; + case 20: /* /SUP */ NEW_BIT (NEW_TEXT_BIT); - if (sup) { + if (sup) sup--; - } - } else if (!g_strcasecmp (tag, "
")) {
-				got_tag = TRUE;
+				break;
+			case 21:	/* PRE */
 				NEW_BIT (NEW_TEXT_BIT);
 				pre++;
-			} else if (!g_strcasecmp (tag, "
")) { - got_tag = TRUE; + break; + case 22: /* /PRE */ + NEW_BIT (NEW_TEXT_BIT); + if (pre) + pre--; + break; + case 23: /* TITLE */ NEW_BIT (NEW_TEXT_BIT); - if (pre) { - pre--; + title++; + break; + case 24: /* /TITLE */ + if (title) { + if (options & GTK_IMHTML_NO_TITLE) { + wpos = 0; + ws [wpos] = '\0'; + } + title--; } - } else if (!g_strcasecmp (tag, "")) { - if (options & GTK_IMHTML_NO_TITLE) { - got_tag = TRUE; - NEW_BIT (NEW_TEXT_BIT); - title++; - } else { - intag = FALSE; - tpos = 0; - continue; - } - } else if (!g_strcasecmp (tag, "")) { - if (title) { - got_tag = TRUE; - wpos = 0; - ws [wpos] = '\0'; - title--; - } else { - intag = FALSE; - tpos = 0; - continue; - } - } else if (!g_strcasecmp (tag, "
")) { - got_tag = TRUE; + break; + case 25: /* BR */ NEW_BIT (NEW_TEXT_BIT); NEW_BIT (NEW_BR_BIT); - } else if (!g_strcasecmp (tag, "
") || - !g_strncasecmp (tag, "
fore == NULL) && - !(options & GTK_IMHTML_NO_COLOURS)) - font->fore = clr; - } - break; - case 2: - clr = gtk_imhtml_get_color (value); - if (clr != NULL) { - if ( (font->back == NULL) && - !(options & GTK_IMHTML_NO_COLOURS)) - font->back = clr; - } - break; - case 3: - if ( (font->face == NULL) && - !(options & GTK_IMHTML_NO_FONTS)) - font->face = g_strdup (value); - break; - case 4: - if ((font->size != 0) || - (options & GTK_IMHTML_NO_SIZES)) - break; - - if (isdigit ((gint) value [0])) { - for (i = 0; i < strlen (value); i++) - if (!isdigit ((gint) value [i])) - break; - if (i != strlen (value)) - break; - - sscanf (value, "%hd", &font->size); - break; - } - - if ((value [0] == '+') && (value [1] != '\0')) { - for (i = 1; i < strlen (value); i++) - if (!isdigit ((gint) value [i])) - break; - if (i != strlen (value)) - break; - - sscanf (value + 1, "%hd", &font->size); - font->size += DEFAULT_FONT_SIZE; - break; - } - - if ((value [0] == '-') && (value [1] != '\0')) { - for (i = 1; i < strlen (value); i++) - if (!isdigit ((gint) value [i])) - break; - if (i != strlen (value)) - break; - - sscanf (value + 1, "%hd", &font->size); - font->size = MIN (font->size, 2); - font->size = DEFAULT_FONT_SIZE - font->size; - break; - } - - break; - } - - g_free (value); + break; + case 27: /* /FONT */ + if (fonts) { + FontDetail *font = fonts->data; + NEW_BIT (NEW_TEXT_BIT); + fonts = g_slist_remove (fonts, font); + if (font->face) + g_free (font->face); + if (font->fore) + gdk_color_free (font->fore); + if (font->back) + gdk_color_free (font->back); + g_free (font); + } + break; + case 28: /* /A */ + if (url) { + NEW_BIT (NEW_TEXT_BIT); + g_free (url); + url = NULL; } - - if (!font || !(font->size || font->face || font->fore || font->back)) { - g_free (font); - intag = FALSE; - tpos = 0; - continue; - } + break; + case 29: /* P */ + case 30: /* /P */ + case 31: /* H3 */ + case 32: /* /H3 */ + case 33: /* HTML */ + case 34: /* /HTML */ + case 35: /* BODY */ + case 36: /* /BODY */ + case 37: /* FONT */ + case 38: /* HEAD */ + case 39: /* /HEAD */ + break; + + case 40: /* HR (opt) */ + NEW_BIT (NEW_TEXT_BIT); + NEW_BIT (NEW_SEP_BIT); + break; + case 41: /* FONT (opt) */ + { + gchar *color, *back, *face, *size; + FontDetail *font; + + color = gtk_imhtml_get_html_opt (tag, "COLOR="); + back = gtk_imhtml_get_html_opt (tag, "BACK="); + face = gtk_imhtml_get_html_opt (tag, "FACE="); + size = gtk_imhtml_get_html_opt (tag, "SIZE="); + + if (!(color || back || face || size)) + break; NEW_BIT (NEW_TEXT_BIT); + font = g_new0 (FontDetail, 1); + if (color && !(options & GTK_IMHTML_NO_COLOURS)) + font->fore = gtk_imhtml_get_color (color); + if (back && !(options & GTK_IMHTML_NO_COLOURS)) + font->back = gtk_imhtml_get_color (back); + if (face && !(options & GTK_IMHTML_NO_FONTS)) + font->face = g_strdup (face); + if (size && !(options & GTK_IMHTML_NO_SIZES)) + sscanf (size, "%hd", &font->size); + + g_free (color); + g_free (back); + g_free (face); + g_free (size); + if (fonts) { FontDetail *oldfont = fonts->data; if (!font->size) font->size = oldfont->size; - if (!font->face && oldfont->face) + if (!font->face && oldfont->face) font->face = g_strdup (oldfont->face); if (!font->fore && oldfont->fore) font->fore = gdk_color_copy (oldfont->fore); @@ -3058,192 +3009,47 @@ } fonts = g_slist_prepend (fonts, font); - got_tag = TRUE; - } else if (!g_strcasecmp (tag, "")) { - FontDetail *font; - - if (fonts) { - got_tag = TRUE; - NEW_BIT (NEW_TEXT_BIT); - font = fonts->data; - fonts = g_slist_remove (fonts, font); - if (font->face) - g_free (font->face); - if (font->fore) - gdk_color_free (font->fore); - if (font->back) - gdk_color_free (font->back); - g_free (font); - } else { - intag = FALSE; - tpos = 0; - continue; - } - } else if (!g_strncasecmp (tag, "")) { - if (url != NULL) { - got_tag = TRUE; + } + break; + case 43: /* A (opt) */ + { + gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); + if (href) { NEW_BIT (NEW_TEXT_BIT); g_free (url); - url = NULL; - } else { - intag = FALSE; - tpos = 0; - continue; - } - } else if (!g_strncasecmp (tag, "img == NULL) { - ws [wpos] = 0; - strcat (ws, copy); - wpos = strlen (ws); - g_free (copy); - continue; + url = href; } - - t = tag + strlen ("") || - !g_strcasecmp (tag, "

") || - !g_strncasecmp (tag, "

") || - !g_strncasecmp (tag, "

") || - !g_strcasecmp (tag, "") || - !g_strcasecmp (tag, "") || - !g_strcasecmp (tag, "") || - !g_strcasecmp (tag, "") || - !g_strcasecmp (tag, "") || - !g_strcasecmp (tag, "") || - !g_strcasecmp (tag, "")) { - intag = FALSE; - tpos = 0; - continue; } - - if (!got_tag) { - char *d; - tag [tpos] = 0; - d = tag; - while (*d) { - if ((smilelen = gtk_imhtml_is_smiley (imhtml, d)) != 0) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - g_snprintf (ws, smilelen + 1, "%s", d); - NEW_BIT (NEW_SMILEY_BIT); - d += smilelen; - } else if (*d == '&') { - gchar replace; - gint length; - if (is_amp_escape (d, &replace, &length)) { - ws [wpos++] = replace; - d += length; - } else { - ws [wpos++] = *d++; - } - } else if (*d == '\n') { - if (!(options & GTK_IMHTML_NO_NEWLINE)) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_BR_BIT); - } - d++; - } else { - ws [wpos++] = *d++; - } - } - tpos = 0; - } else { - wpos = 0; + break; + case 45: /* P (opt) */ + case 46: /* H3 (opt) */ + break; + case 47: /* comment */ + NEW_BIT (NEW_TEXT_BIT); + wpos = g_snprintf (ws, len, "%s", tag); + NEW_BIT (NEW_COMMENT_BIT); + break; + default: + break; } - intag = FALSE; - tpos = 0; - } else if (*c == '&' && !intag) { - gchar replace; - gint length; - if (is_amp_escape (c, &replace, &length)) { - ws [wpos++] = replace; - c += length; - } else { - ws [wpos++] = *c++; - } - } else if (intag) { - if (*c == '\"') - tagquote++; - tag [tpos++] = *c++; - } else if (incomment) { - ws [wpos++] = *c++; - } else if (((smilelen = gtk_imhtml_is_smiley (imhtml, c)) != 0)) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - g_snprintf (ws, smilelen + 1, "%s", c); - NEW_BIT (NEW_SMILEY_BIT); - c += smilelen; + g_free (tag); + c += tlen; + pos += tlen; + } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { + ws [wpos++] = amp; + c += tlen; + pos += tlen; } else if (*c == '\n') { if (!(options & GTK_IMHTML_NO_NEWLINE)) { ws [wpos] = 0; @@ -3351,77 +3094,21 @@ NEW_BIT (NEW_BR_BIT); } c++; - } else { + pos++; + } else if (gtk_imhtml_is_smiley (imhtml, c, &smilelen)) { + ws [wpos] = 0; + wpos = 0; + NEW_BIT (NEW_TEXT_BIT); + g_snprintf (ws, smilelen + 1, "%s", c); + wpos = smilelen + 1; + NEW_BIT (NEW_SMILEY_BIT); + c += smilelen; + pos += smilelen; + } else if (*c) { ws [wpos++] = *c++; - } - } - - if (intag) { - tag [tpos] = 0; - c = tag; - while (*c) { - if ((smilelen = gtk_imhtml_is_smiley (imhtml, c)) != 0) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - g_snprintf (ws, smilelen + 1, "%s", c); - NEW_BIT (NEW_SMILEY_BIT); - c += smilelen; - } else if (*c == '&') { - gchar replace; - gint length; - if (is_amp_escape (c, &replace, &length)) { - ws [wpos++] = replace; - c += length; - } else { - ws [wpos++] = *c++; - } - } else if (*c == '\n') { - if (!(options & GTK_IMHTML_NO_NEWLINE)) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_BR_BIT); - } - c++; - } else { - ws [wpos++] = *c++; - } - } - } else if (incomment) { - ws [wpos] = 0; - wpos = 0; - strcat (tag, ws); - ws [wpos] = 0; - c = tag; - while (*c) { - if ((smilelen = gtk_imhtml_is_smiley (imhtml, c)) != 0) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - g_snprintf (ws, smilelen + 1, "%s", c); - NEW_BIT (NEW_SMILEY_BIT); - c += smilelen; - } else if (*c == '&') { - gchar replace; - gint length; - if (is_amp_escape (c, &replace, &length)) { - ws [wpos++] = replace; - c += length; - } else { - ws [wpos++] = *c++; - } - } else if (*c == '\n') { - if (!(options & GTK_IMHTML_NO_NEWLINE)) { - ws [wpos] = 0; - wpos = 0; - NEW_BIT (NEW_TEXT_BIT); - NEW_BIT (NEW_BR_BIT); - } - c++; - } else { - ws [wpos++] = *c++; - } + pos++; + } else { + break; } } @@ -3518,7 +3205,6 @@ } } g_free (ws); - g_free (tag); return retval; } @@ -3562,9 +3248,9 @@ g_free (bit); } - while (imhtml->urls) { - g_free (imhtml->urls->data); - imhtml->urls = g_list_remove (imhtml->urls, imhtml->urls->data); + while (imhtml->click) { + g_free (imhtml->click->data); + imhtml->click = g_list_remove (imhtml->click, imhtml->click->data); } if (imhtml->selected_text) { @@ -3593,8 +3279,6 @@ imhtml->scroll_timer = 0; } - gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window, imhtml->arrow_cursor); - imhtml->x = 0; imhtml->y = TOP_BORDER; imhtml->xsize = 0; @@ -3616,11 +3300,12 @@ layout->vadjustment->upper = imhtml->y; gtk_adjustment_set_value (layout->vadjustment, 0); - gtk_signal_emit_by_name (GTK_OBJECT (layout->hadjustment), "changed"); - gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed"); - - if (GTK_WIDGET_REALIZED (GTK_WIDGET (imhtml))) + if (GTK_WIDGET_REALIZED (GTK_WIDGET (imhtml))) { + gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window, imhtml->arrow_cursor); gdk_window_clear (GTK_LAYOUT (imhtml)->bin_window); + gtk_signal_emit_by_name (GTK_OBJECT (layout->hadjustment), "changed"); + gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed"); + } } void diff -r 19f786779b08 -r b1e300a85678 src/gtkimhtml.h --- a/src/gtkimhtml.h Sat Dec 08 08:46:00 2001 +0000 +++ b/src/gtkimhtml.h Sat Dec 08 09:48:52 2001 +0000 @@ -53,7 +53,7 @@ GdkCursor *arrow_cursor; GList *bits; - GList *urls; + GList *click; struct _GtkIMHtmlBit *tip_bit; GtkWidget *tip_window; guint tip_timer; @@ -127,6 +127,7 @@ GString* gtk_imhtml_append_text (GtkIMHtml *imhtml, const gchar *text, + gint len, GtkIMHtmlOptions options); void gtk_imhtml_clear (GtkIMHtml *imhtml); diff -r 19f786779b08 -r b1e300a85678 src/perl.c --- a/src/perl.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/perl.c Sat Dec 08 09:48:52 2001 +0000 @@ -564,7 +564,7 @@ if (!c) c = new_conversation(nick); - write_to_conv(c, what, wflags, who, time((time_t)NULL)); + write_to_conv(c, what, wflags, who, time(NULL), -1); XSRETURN(0); } @@ -612,7 +612,7 @@ if (!c) c = new_conversation(nick); set_convo_gc(c, gc); - write_to_conv(c, what, WFLAG_SEND | (isauto ? WFLAG_AUTO : 0), NULL, time((time_t)NULL)); + write_to_conv(c, what, WFLAG_SEND | (isauto ? WFLAG_AUTO : 0), NULL, time(NULL), -1); serv_send_im(c->gc, nick, what, isauto ? IM_FLAG_AWAY : 0); XSRETURN(0); } diff -r 19f786779b08 -r b1e300a85678 src/prefs.c --- a/src/prefs.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/prefs.c Sat Dec 08 09:48:52 2001 +0000 @@ -1738,9 +1738,9 @@ /* Fill the text box with new message */ strcpy(buffer, a->message); tmp = stylize(buffer, BUF_LONG); - gtk_imhtml_append_text(GTK_IMHTML(away_text), tmp, GTK_IMHTML_NO_TITLE | + gtk_imhtml_append_text(GTK_IMHTML(away_text), tmp, -1, GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_SCROLL); - gtk_imhtml_append_text(GTK_IMHTML(away_text), "
", GTK_IMHTML_NO_TITLE | + gtk_imhtml_append_text(GTK_IMHTML(away_text), "
", -1, GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_SCROLL); g_free(tmp); } @@ -1988,9 +1988,9 @@ a = (struct away_message *)awy->data; g_snprintf(buffer, sizeof(buffer), "%s", a->message); tmp = stylize(buffer, BUF_LONG); - gtk_imhtml_append_text(GTK_IMHTML(away_text), tmp, GTK_IMHTML_NO_TITLE | + gtk_imhtml_append_text(GTK_IMHTML(away_text), tmp, -1, GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_SCROLL); - gtk_imhtml_append_text(GTK_IMHTML(away_text), "
", GTK_IMHTML_NO_TITLE | + gtk_imhtml_append_text(GTK_IMHTML(away_text), "
", -1, GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_SCROLL); g_free(tmp); } diff -r 19f786779b08 -r b1e300a85678 src/protocols/gg/gg.c --- a/src/protocols/gg/gg.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/protocols/gg/gg.c Sat Dec 08 09:48:52 2001 +0000 @@ -1,6 +1,6 @@ /* * gaim - Gadu-Gadu Protocol Plugin - * $Id: gg.c 2859 2001-12-05 09:48:56Z warmenhoven $ + * $Id: gg.c 2869 2001-12-08 09:48:52Z warmenhoven $ * * Copyright (C) 2001 Arkadiusz Mi¶kiewicz * @@ -369,7 +369,7 @@ imsg = charset_convert(e->event.msg.message, "CP1250", find_local_charset()); strip_linefeed(imsg); /* e->event.msg.time - we don't know what this time is for */ - serv_got_im(gc, user, imsg, 0, time((time_t) NULL)); + serv_got_im(gc, user, imsg, 0, time(NULL), -1); g_free(imsg); } break; diff -r 19f786779b08 -r b1e300a85678 src/protocols/icq/gaim_icq.c --- a/src/protocols/icq/gaim_icq.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/protocols/icq/gaim_icq.c Sat Dec 08 09:48:52 2001 +0000 @@ -114,7 +114,7 @@ g_snprintf(tmp, BUF_LONG, "%s", data); g_snprintf(buf, sizeof buf, "%lu", uin); strip_linefeed(tmp); - serv_got_im(gc, buf, tmp, 0, time((time_t)NULL)); + serv_got_im(gc, buf, tmp, 0, time(NULL), -1); g_free(tmp); } @@ -169,7 +169,7 @@ char *msg = g_malloc(BUF_LONG), buf[256]; g_snprintf(msg, BUF_LONG, "%s", url, descr); g_snprintf(buf, 256, "%lu", uin); - serv_got_im(gc, buf, msg, 0, time((time_t)NULL)); + serv_got_im(gc, buf, msg, 0, time(NULL), -1); g_free(msg); } @@ -211,7 +211,7 @@ char *who = g_strdup_printf("ICQ Web Pager: %s (%s)", nick, email); char *what = g_malloc(BUF_LONG); g_snprintf(what, BUF_LONG, "%s", msg); - serv_got_im(gc, who, what, 0, time((time_t)NULL)); + serv_got_im(gc, who, what, 0, time(NULL), -1); g_free(who); g_free(what); } @@ -223,7 +223,7 @@ char *who = g_strdup_printf("ICQ Mail Express: %s (%s)", nick, email); char *what = g_malloc(BUF_LONG); g_snprintf(what, BUF_LONG, "%s", msg); - serv_got_im(gc, who, what, 0, time((time_t)NULL)); + serv_got_im(gc, who, what, 0, time(NULL), -1); g_free(who); g_free(what); } diff -r 19f786779b08 -r b1e300a85678 src/protocols/irc/irc.c --- a/src/protocols/irc/irc.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/protocols/irc/irc.c Sat Dec 08 09:48:52 2001 +0000 @@ -322,7 +322,7 @@ static void irc_got_im(struct gaim_connection *gc, char *who, char *what, int flags, time_t t) { GString *str = decode_html(what); - serv_got_im(gc, who, str->str, flags, t); + serv_got_im(gc, who, str->str, flags, t, -1); g_string_free(str, TRUE); } @@ -428,7 +428,7 @@ chat_set_topic(c, NULL, po); g_snprintf(buf, sizeof(buf), _("%s has changed the topic to: %s"), text, po); - write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL)); + write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); } } @@ -961,7 +961,7 @@ chat_set_topic(c, nick, topic); g_snprintf(buf, sizeof(buf), _("%s has changed the topic to: %s"), nick, topic); - write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL)); + write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); } } else if (!strcmp(cmd, "WALLOPS")) { /* */ } @@ -1377,7 +1377,7 @@ "JOIN PART TOPIC KICK
" "OP DEOP VOICE DEVOICE
" "ME MSG QUOTE SAY", - WFLAG_NOLOG, NULL, time(NULL)); + WFLAG_NOLOG, NULL, time(NULL), -1); } else { struct conversation *c = NULL; if (is_channel(gc, who)) { @@ -1387,7 +1387,7 @@ } if (!c) return -EINVAL; - write_to_conv(c, "Unknown command", WFLAG_NOLOG, NULL, time(NULL)); + write_to_conv(c, "Unknown command", WFLAG_NOLOG, NULL, time(NULL), -1); } return 0; diff -r 19f786779b08 -r b1e300a85678 src/protocols/jabber/jabber.c --- a/src/protocols/jabber/jabber.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/protocols/jabber/jabber.c Sat Dec 08 09:48:52 2001 +0000 @@ -622,10 +622,10 @@ if (xmlnode_get_tag(p->x, "gaim")) flags = IM_FLAG_GAIMUSER; if (find_conversation(jid_full(p->from))) - serv_got_im(GJ_GC(j), jid_full(p->from), m, flags, time(NULL)); + serv_got_im(GJ_GC(j), jid_full(p->from), m, flags, time(NULL), -1); else { from = g_strdup_printf("%s@%s", p->from->user, p->from->server); - serv_got_im(GJ_GC(j), from, m, flags, time(NULL)); + serv_got_im(GJ_GC(j), from, m, flags, time(NULL), -1); g_free(from); } } @@ -690,7 +690,7 @@ msg = xmlnode_get_data(y); g_snprintf(buf, sizeof(buf), "%s now has status: %s", p->from->resource, msg); - write_to_conv(jc->b, buf, WFLAG_SYSTEM, NULL, time(NULL)); + write_to_conv(jc->b, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); } } else if (jc->b && msg) { char buf[8192]; @@ -847,7 +847,7 @@ char *msg = xmlnode_get_data(y); g_snprintf(buf, sizeof(buf), "%s now has status: %s", p->from->resource, msg); - write_to_conv(jc->b, buf, WFLAG_SYSTEM, NULL, time(NULL)); + write_to_conv(jc->b, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); } } } diff -r 19f786779b08 -r b1e300a85678 src/protocols/msn/msn.c --- a/src/protocols/msn/msn.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/protocols/msn/msn.c Sat Dec 08 09:48:52 2001 +0000 @@ -520,7 +520,7 @@ if (ms->chat) serv_got_chat_in(ms->gc, ms->chat->id, ms->msguser, flags, utf, time(NULL)); else - serv_got_im(ms->gc, ms->msguser, utf, flags, time(NULL)); + serv_got_im(ms->gc, ms->msguser, utf, flags, time(NULL), -1); g_free(utf); } @@ -1084,7 +1084,7 @@ utf = utf8_to_str(skiphead); strip_linefeed(utf); - serv_got_im(gc, md->msguser, utf, 0, time(NULL)); + serv_got_im(gc, md->msguser, utf, 0, time(NULL), -1); g_free(utf); } @@ -1498,7 +1498,7 @@ ms->fd = -1; } else /* in msn you can't send messages to yourself, so we'll fake like we received it ;) */ - serv_got_im(gc, who, message, flags | IM_FLAG_GAIMUSER, time(NULL)); + serv_got_im(gc, who, message, flags | IM_FLAG_GAIMUSER, time(NULL), -1); return 1; } diff -r 19f786779b08 -r b1e300a85678 src/protocols/napster/napster.c --- a/src/protocols/napster/napster.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/protocols/napster/napster.c Sat Dec 08 09:48:52 2001 +0000 @@ -201,7 +201,7 @@ if (command == 0xCD) { res = g_strsplit(buf, " ", 1); - serv_got_im(gc, res[0], res[1], 0, time((time_t)NULL)); + serv_got_im(gc, res[0], res[1], 0, time(NULL), -1); g_strfreev(res); g_free(buf); return; diff -r 19f786779b08 -r b1e300a85678 src/protocols/oscar/oscar.c --- a/src/protocols/oscar/oscar.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/protocols/oscar/oscar.c Sat Dec 08 09:48:52 2001 +0000 @@ -304,7 +304,7 @@ g_snprintf(buf, sizeof buf, _("Direct IM with %s closed"), sn); if ((cnv = find_conversation(sn))) - write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL)); + write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); g_free(dim); /* I guess? I don't see it anywhere else... -- mid */ g_free(sn); @@ -1202,7 +1202,7 @@ if (!(cnv = find_conversation(dim->name))) cnv = new_conversation(dim->name); g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name); - write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL)); + write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); od->direct_ims = g_slist_append(od->direct_ims, dim); @@ -1342,7 +1342,7 @@ g_snprintf(tmp, BUF_LONG, "%s", args->msg); strip_linefeed(tmp); - serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL)); + serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL), -1); g_free(tmp); return 1; @@ -2070,7 +2070,7 @@ time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); g_snprintf(sender, sizeof(sender), "%lu", msg->sender); strip_linefeed(tmp); - serv_got_im(gc, sender, tmp, 0, t); + serv_got_im(gc, sender, tmp, 0, t, -1); g_free(tmp); } else { debug_printf("unknown offline message type 0x%04x\n", msg->type); @@ -2640,7 +2640,7 @@ oscar_callback, dim->conn); g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), sn); g_free(sn); - write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL)); + write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, gaim_directim_incoming, 0); @@ -2662,7 +2662,7 @@ debug_printf("Got DirectIM message from %s\n", sn); - serv_got_im(gc, sn, msg, 0, time((time_t)NULL)); + serv_got_im(gc, sn, msg, 0, time(NULL), -1); return 1; } diff -r 19f786779b08 -r b1e300a85678 src/protocols/toc/toc.c --- a/src/protocols/toc/toc.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/protocols/toc/toc.c Sat Dec 08 09:48:52 2001 +0000 @@ -619,7 +619,7 @@ a = (away && (*away == 'T')) ? IM_FLAG_AWAY : 0; - serv_got_im(gc, c, message, a, time((time_t)NULL)); + serv_got_im(gc, c, message, a, time(NULL), -1); } else if (!strcasecmp(c, "UPDATE_BUDDY")) { char *l, *uc, *tmp; int logged, evil, idle, type = 0; diff -r 19f786779b08 -r b1e300a85678 src/protocols/yahoo/yahoo.c --- a/src/protocols/yahoo/yahoo.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/protocols/yahoo/yahoo.c Sat Dec 08 09:48:52 2001 +0000 @@ -488,7 +488,7 @@ msg[j++] = m[i]; } msg[j] = 0; - serv_got_im(gc, from, msg, 0, tm); + serv_got_im(gc, from, msg, 0, tm, -1); } else if (pkt->status == 2) { do_error_dialog(_("Your message did not get sent."), _("Gaim - Error")); } diff -r 19f786779b08 -r b1e300a85678 src/protocols/zephyr/zephyr.c --- a/src/protocols/zephyr/zephyr.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/protocols/zephyr/zephyr.c Sat Dec 08 09:48:52 2001 +0000 @@ -374,7 +374,7 @@ away = TRUE; else away = FALSE; - serv_got_im(zgc, notice.z_sender, buf2, 0, time((time_t)NULL)); + serv_got_im(zgc, notice.z_sender, buf2, 0, time(NULL), -1); } else { zephyr_triple *zt1, *zt2; zt1 = new_triple(notice.z_class, notice.z_class_inst, diff -r 19f786779b08 -r b1e300a85678 src/server.c --- a/src/server.c Sat Dec 08 08:46:00 2001 +0000 +++ b/src/server.c Sat Dec 08 09:48:52 2001 +0000 @@ -427,7 +427,7 @@ } /* woo. i'm actually going to comment this function. isn't that fun. make sure to follow along, kids */ -void serv_got_im(struct gaim_connection *gc, char *name, char *message, guint32 flags, time_t mtime) +void serv_got_im(struct gaim_connection *gc, char *name, char *message, guint32 flags, time_t mtime, gint len) { char *buffy; char *angel; @@ -457,26 +457,32 @@ /* plugin stuff. we pass a char ** but we don't want to pass what's been given us * by the prpls. so we create temp holders and pass those instead. it's basically - * just to avoid segfaults. */ - buffy = g_malloc(MAX(strlen(message) + 1, BUF_LONG)); - strcpy(buffy, message); - angel = g_strdup(name); - plugin_return = plugin_event(event_im_recv, gc, &angel, &buffy, (void *)flags); + * just to avoid segfaults. of course, if the data is binary, plugins don't see it. + * bitch all you want; i really don't want you to be dealing with it. */ + if (len < 0) { + buffy = g_malloc(MAX(strlen(message) + 1, BUF_LONG)); + strcpy(buffy, message); + angel = g_strdup(name); + plugin_return = plugin_event(event_im_recv, gc, &angel, &buffy, (void *)flags); - if (!buffy || !angel || plugin_return) { - if (buffy) - g_free(buffy); - if (angel) - g_free(angel); - return; + if (!buffy || !angel || plugin_return) { + if (buffy) + g_free(buffy); + if (angel) + g_free(angel); + return; + } + name = angel; + message = buffy; + } else { + name = g_strdup(name); + message = g_memdup(message, len); } - name = angel; - message = buffy; /* TiK, using TOC, sends an automated message in order to get your away message. Now, * this is one of the biggest hacks I think I've seen. But, in order to be nice to * TiK, we're going to give users the option to ignore it. */ - if ((away_options & OPT_AWAY_TIK_HACK) && gc->away && strlen(gc->away) && + if ((away_options & OPT_AWAY_TIK_HACK) && gc->away && strlen(gc->away) && (len < 0) && !strcmp(message, ">>>Automated Message: Getting Away Message<<<")) { char *tmpmsg = stylize(awaymessage->message, MSG_LEN); serv_send_im(gc, name, tmpmsg, IM_FLAG_AWAY); @@ -488,7 +494,7 @@ /* if you can't figure this out, stop reading right now. * "we're not worthy! we're not worthy!" */ - if (convo_options & OPT_CONVO_SEND_LINKS) + if ((len < 0) && (convo_options & OPT_CONVO_SEND_LINKS)) linkify_text(message); /* um. when we call write_to_conv with the message we received, it's nice to pass whether @@ -523,10 +529,11 @@ qm = g_new0(struct queued_message, 1); g_snprintf(qm->name, sizeof(qm->name), "%s", name); - qm->message = g_strdup(message); + qm->message = g_memdup(message, len == -1 ? strlen(message) + 1 : len); qm->gc = gc; qm->tm = mtime; qm->flags = WFLAG_RECV | away; + qm->len = len; message_queue = g_slist_append(message_queue, qm); #ifdef USE_APPLET @@ -572,7 +579,7 @@ else if (cnv->makesound && (sound_options & OPT_SOUND_RECV)) play_sound(RECEIVE); - write_to_conv(cnv, message, away | WFLAG_RECV, NULL, mtime); + write_to_conv(cnv, message, away | WFLAG_RECV, NULL, mtime, len); } /* regardless of whether we queue it or not, we should send an auto-response. That is, @@ -616,7 +623,7 @@ message_queue = g_slist_append(message_queue, qm); } else if (cnv != NULL) write_to_conv(cnv, away_subs(tmpmsg, alias), WFLAG_SEND | WFLAG_AUTO, NULL, - mtime); + mtime, len); g_free(tmpmsg); } else { /* we're not away. this is easy. if the convo window doesn't exist, create and update @@ -631,7 +638,7 @@ else if (cnv->makesound && (sound_options & OPT_SOUND_RECV)) play_sound(RECEIVE); - write_to_conv(cnv, message, away | WFLAG_RECV, NULL, mtime); + write_to_conv(cnv, message, away | WFLAG_RECV, NULL, mtime, len); } plugin_event(event_im_displayed_rcvd, gc, name, message, (void *)flags); @@ -986,5 +993,5 @@ gtk_widget_show_all(window); - gtk_imhtml_append_text(GTK_IMHTML(text), msg, GTK_IMHTML_NO_NEWLINE); + gtk_imhtml_append_text(GTK_IMHTML(text), msg, -1, GTK_IMHTML_NO_NEWLINE); } diff -r 19f786779b08 -r b1e300a85678 src/ui.h --- a/src/ui.h Sat Dec 08 08:46:00 2001 +0000 +++ b/src/ui.h Sat Dec 08 09:48:52 2001 +0000 @@ -202,6 +202,7 @@ time_t tm; struct gaim_connection *gc; int flags; + int len; }; struct mod_user {