# HG changeset patch # User Mark Doliner # Date 1064690241 0 # Node ID 083d1e4a9c787cf172fe32de691eae0927eadf90 # Parent abd3c684da311a1fa7eaa36893fe29aec20e9d18 [gaim-migrate @ 7538] This is Mr. Holland's Opus. And by Mr. Holland I mean Robot101. He rewrote the coreish IM image support so that the binary data gets ripped out in the prpl and put in an imgstore instead of just being passed in the same huge as char string as the actual message. This is good because it's prpl agnostic, or something. It also means we don't have a silly length of "-1" with pretty much every send or receive IM function. It should be crash free, bug free, and memleak free, but additional testing is always a good thing. If you like good stuff then you'll love this patch. But don't take my word for it--ba dun dunt! committer: Tailor Script diff -r abd3c684da31 -r 083d1e4a9c78 ChangeLog --- a/ChangeLog Sat Sep 27 15:45:49 2003 +0000 +++ b/ChangeLog Sat Sep 27 19:17:21 2003 +0000 @@ -1,6 +1,8 @@ Gaim: The Pimpin' Penguin IM Clone that's good for the soul! version 0.70: + * Robert "Robot101" McQueen cleaned and core/UI split IM + image support * Chinese (Traditional) translation updated (Ambrose C. Li) * Portuguese (Portugal) translation updated (Duarte Henriques) diff -r abd3c684da31 -r 083d1e4a9c78 configure.ac --- a/configure.ac Sat Sep 27 15:45:49 2003 +0000 +++ b/configure.ac Sat Sep 27 19:17:21 2003 +0000 @@ -1,7 +1,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(src/main.c) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE([gaim], [0.69]) +AM_INIT_AUTOMAKE([gaim], [0.70cvs]) AC_PREREQ([2.50]) diff -r abd3c684da31 -r 083d1e4a9c78 plugins/filectl.c --- a/plugins/filectl.c Sat Sep 27 15:45:49 2003 +0000 +++ b/plugins/filectl.c Sat Sep 27 19:17:21 2003 +0000 @@ -76,7 +76,7 @@ c = find_conversation(arg1); if (!c) c = gaim_conversation_new(GAIM_CONV_IM, arg1); write_to_conv(c, arg2, WFLAG_SEND, NULL, time(NULL), -1); - serv_send_im(c->gc, arg1, arg2, -1, 0); + serv_send_im(c->gc, arg1, arg2, 0); free(arg1); free(arg2); } else if (!strncasecmp(command, "away", 4)) { diff -r abd3c684da31 -r 083d1e4a9c78 plugins/gaim-remote/remote.c --- a/plugins/gaim-remote/remote.c Sat Sep 27 15:45:49 2003 +0000 +++ b/plugins/gaim-remote/remote.c Sat Sep 27 19:17:21 2003 +0000 @@ -434,7 +434,7 @@ pos += len; memcpy(&flags, data + pos, sizeof(flags)); - serv_send_im(gc, who, msg, -1, flags); + serv_send_im(gc, who, msg, flags); g_free(who); g_free(msg); diff -r abd3c684da31 -r 083d1e4a9c78 plugins/gaiminc.c --- a/plugins/gaiminc.c Sat Sep 27 15:45:49 2003 +0000 +++ b/plugins/gaiminc.c Sat Sep 27 19:17:21 2003 +0000 @@ -43,7 +43,7 @@ { /* whenever someone comes online, it sends them a message. if i * cared more, i'd make it so it popped up on your screen too */ - serv_send_im(gc, who, "Hello!", -1, 0); + serv_send_im(gc, who, "Hello!", 0); } /* diff -r abd3c684da31 -r 083d1e4a9c78 plugins/history.c --- a/plugins/history.c Sat Sep 27 15:45:49 2003 +0000 +++ b/plugins/history.c Sat Sep 27 19:17:21 2003 +0000 @@ -61,8 +61,8 @@ gtkconv = GAIM_GTK_CONVERSATION(c); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), tmp2, strlen(tmp2), options); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "
", -1, options); + gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), tmp2, options); + gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "
", options); gtk_text_buffer_get_end_iter(GTK_IMHTML(gtkconv->imhtml)->text_buffer, & end); gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(gtkconv->imhtml), &end, 0, 0, diff -r abd3c684da31 -r 083d1e4a9c78 plugins/notify.c --- a/plugins/notify.c Sat Sep 27 15:45:49 2003 +0000 +++ b/plugins/notify.c Sat Sep 27 19:17:21 2003 +0000 @@ -514,7 +514,7 @@ options_entry_cb(GtkWidget *widget, GdkEventFocus *evt, gpointer data) { if (data == NULL) - return; + return FALSE; if (!strcmp(data, "method_string")) { gaim_prefs_set_string("/plugins/gtk/X11/notify/title_string", gtk_entry_get_text(GTK_ENTRY(widget))); diff -r abd3c684da31 -r 083d1e4a9c78 plugins/perl/common/Conversation.xs --- a/plugins/perl/common/Conversation.xs Sat Sep 27 15:45:49 2003 +0000 +++ b/plugins/perl/common/Conversation.xs Sat Sep 27 19:17:21 2003 +0000 @@ -80,7 +80,7 @@ const char *message int flags CODE: - gaim_conversation_write(conv, who, message, -1, flags, time(NULL)); + gaim_conversation_write(conv, who, message, flags, time(NULL)); Gaim::Conversation::IM gaim_conversation_get_im_data(conv) diff -r abd3c684da31 -r 083d1e4a9c78 plugins/perl/common/Conversation_IM.xs --- a/plugins/perl/common/Conversation_IM.xs Sat Sep 27 15:45:49 2003 +0000 +++ b/plugins/perl/common/Conversation_IM.xs Sat Sep 27 19:17:21 2003 +0000 @@ -30,7 +30,7 @@ const char *message int flags CODE: - gaim_im_write(im, who, message, -1, flags, time(NULL)); + gaim_im_write(im, who, message, flags, time(NULL)); void gaim_im_send(im, message) diff -r abd3c684da31 -r 083d1e4a9c78 plugins/statenotify.c --- a/plugins/statenotify.c Sat Sep 27 15:45:49 2003 +0000 +++ b/plugins/statenotify.c Sat Sep 27 19:17:21 2003 +0000 @@ -21,7 +21,7 @@ g_snprintf(buf, sizeof(buf), message, who); - gaim_conversation_write(conv, NULL, buf, -1, GAIM_MESSAGE_SYSTEM, time(NULL)); + gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL)); } static void diff -r abd3c684da31 -r 083d1e4a9c78 plugins/tcl/tcl_cmds.c --- a/plugins/tcl/tcl_cmds.c Sat Sep 27 15:45:49 2003 +0000 +++ b/plugins/tcl/tcl_cmds.c Sat Sep 27 19:17:21 2003 +0000 @@ -601,7 +601,7 @@ if (gaim_conversation_get_type(convo) == GAIM_CONV_CHAT) gaim_chat_write(GAIM_CHAT(convo), from, what, flags, time(NULL)); else - gaim_im_write(GAIM_IM(convo), from, what, -1, flags, time(NULL)); + gaim_im_write(GAIM_IM(convo), from, what, flags, time(NULL)); break; } @@ -849,7 +849,7 @@ who = Tcl_GetString(objv[2]); text = Tcl_GetString(objv[3]); - serv_send_im(gc, who, text, -1, 0); + serv_send_im(gc, who, text, 0); return TCL_OK; } diff -r abd3c684da31 -r 083d1e4a9c78 plugins/timestamp.c --- a/plugins/timestamp.c Sat Sep 27 15:45:49 2003 +0000 +++ b/plugins/timestamp.c Sat Sep 27 19:17:21 2003 +0000 @@ -32,7 +32,7 @@ strftime(mdate, sizeof(mdate), "%H:%M", localtime(&tim)); buf = g_strdup_printf(" %s", mdate); - gaim_conversation_write(c, NULL, buf, -1, GAIM_MESSAGE_NO_LOG, tim); + gaim_conversation_write(c, NULL, buf, GAIM_MESSAGE_NO_LOG, tim); g_free(buf); return TRUE; } diff -r abd3c684da31 -r 083d1e4a9c78 src/Makefile.am --- a/src/Makefile.am Sat Sep 27 15:45:49 2003 +0000 +++ b/src/Makefile.am Sat Sep 27 19:17:21 2003 +0000 @@ -68,6 +68,8 @@ ft.h \ html.c \ html.h \ + imgstore.c \ + imgstore.h \ md5.c \ md5.h \ multi.h \ diff -r abd3c684da31 -r 083d1e4a9c78 src/about.c --- a/src/about.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/about.c Sat Sep 27 19:17:21 2003 +0000 @@ -89,15 +89,15 @@ _("Gaim is a modular Instant Messaging client capable of " "using AIM, ICQ, Yahoo!, MSN, IRC, Jabber, Napster, " "Zephyr, and Gadu-Gadu all at once. It is written using " - "Gtk+ and is licensed under the GPL.

"), -1, GTK_IMHTML_NO_SCROLL); + "Gtk+ and is licensed under the GPL.

"), GTK_IMHTML_NO_SCROLL); gtk_imhtml_append_text(GTK_IMHTML(text), "URL: " - GAIM_WEBSITE "

", -1, GTK_IMHTML_NO_SCROLL); + GAIM_WEBSITE "

", GTK_IMHTML_NO_SCROLL); gtk_imhtml_append_text(GTK_IMHTML(text), _("IRC: #gaim on irc.freenode.net" - "

"), -1, GTK_IMHTML_NO_SCROLL); + "

"), GTK_IMHTML_NO_SCROLL); /* Active Developers */ str = g_strconcat( @@ -116,7 +116,7 @@ " Ethan 'Paco-Paco' Blanton (", _("developer"), ")
" " Luke 'LSchiere' Schierer (", _("support"), ")
" "
", NULL); - gtk_imhtml_append_text(GTK_IMHTML(text), str, -1, GTK_IMHTML_NO_SCROLL); + gtk_imhtml_append_text(GTK_IMHTML(text), str, GTK_IMHTML_NO_SCROLL); g_free(str); /* Crazy Patch Writers */ @@ -128,7 +128,7 @@ " Robert 'Robot101' McQueen
" " Tim 'marv' Ringenbach
" "
", NULL); - gtk_imhtml_append_text(GTK_IMHTML(text), str, -1, GTK_IMHTML_NO_SCROLL); + gtk_imhtml_append_text(GTK_IMHTML(text), str, GTK_IMHTML_NO_SCROLL); g_free(str); /* Just because */ @@ -136,7 +136,7 @@ "", "Just Because", ":
" " Rachel Shelton (Vampire & Dark Lord)
" "
", NULL); - gtk_imhtml_append_text(GTK_IMHTML(text), str, -1, GTK_IMHTML_NO_SCROLL); + gtk_imhtml_append_text(GTK_IMHTML(text), str, GTK_IMHTML_NO_SCROLL); g_free(str); /* Retired Developers */ @@ -154,7 +154,7 @@ " Syd Logan (", _("hacker and designated driver [lazy bum]"), ")
" "
", NULL); - gtk_imhtml_append_text(GTK_IMHTML(text), str, -1, GTK_IMHTML_NO_SCROLL); + gtk_imhtml_append_text(GTK_IMHTML(text), str, GTK_IMHTML_NO_SCROLL); g_free(str); /* Current Translators */ @@ -181,7 +181,7 @@ " ", _("Simplified Chinese"), " (zh_CN) - Funda Wang <fundawang@linux.net.cn>
" " ", _("Traditional Chinese"), " (zh_TW) - Ambrose C. Li <acli@ada.dhs.org>, Paladin R. Liu <paladin@ms1.hinet.net>
" "
", NULL); - gtk_imhtml_append_text(GTK_IMHTML(text), str, -1, GTK_IMHTML_NO_SCROLL); + gtk_imhtml_append_text(GTK_IMHTML(text), str, GTK_IMHTML_NO_SCROLL); g_free(str); /* Past Translators */ @@ -205,7 +205,7 @@ " ", _("Swedish"), " (sv) - Christian Rose
" " ", _("Chinese"), " (zh_CN, zh_TW) - Hashao, Rocky S. Lee
" "
", NULL); - gtk_imhtml_append_text(GTK_IMHTML(text), str, -1, GTK_IMHTML_NO_SCROLL); + gtk_imhtml_append_text(GTK_IMHTML(text), str, GTK_IMHTML_NO_SCROLL); g_free(str); gtk_adjustment_set_value(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(sw)), 0); diff -r abd3c684da31 -r 083d1e4a9c78 src/away.c --- a/src/away.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/away.c Sat Sep 27 19:17:21 2003 +0000 @@ -78,7 +78,7 @@ else gaim_conversation_set_account(cnv, account); - gaim_im_write(GAIM_IM(cnv), NULL, qm->message, qm->len, + gaim_im_write(GAIM_IM(cnv), NULL, qm->message, qm->flags, qm->tm); g_free(qm->message); g_free(qm); @@ -118,7 +118,7 @@ else gaim_conversation_set_account(cnv, account); - gaim_im_write(GAIM_IM(cnv), NULL, qm->message, -1, qm->flags, qm->tm); + gaim_im_write(GAIM_IM(cnv), NULL, qm->message, qm->flags, qm->tm); g_free(qm->message); g_free(qm); @@ -228,10 +228,10 @@ gaim_setup_imhtml(awaytext); gtk_widget_show(awaytext); buf = stylize(a->message, BUF_LONG); - gtk_imhtml_append_text(GTK_IMHTML(awaytext), buf, -1, GTK_IMHTML_NO_TITLE | + gtk_imhtml_append_text(GTK_IMHTML(awaytext), buf, GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_SCROLL); g_free(buf); - gtk_imhtml_append_text(GTK_IMHTML(awaytext), "
", -1, + gtk_imhtml_append_text(GTK_IMHTML(awaytext), "
", GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_SCROLL); diff -r abd3c684da31 -r 083d1e4a9c78 src/connection.h --- a/src/connection.h Sat Sep 27 15:45:49 2003 +0000 +++ b/src/connection.h Sat Sep 27 19:17:21 2003 +0000 @@ -35,9 +35,10 @@ */ typedef enum { - GAIM_CONNECTION_HTML = 0x0001, /**< Connection sends/receives in 'HTML'. */ - GAIM_CONNECTION_NO_BGCOLOR = 0x0002, /**< Connection does not send/recieve background colors. */ - GAIM_CONNECTION_AUTO_RESP = 0x0004 /**< Send auto responses when away. */ + GAIM_CONNECTION_HTML = 0x0001, /**< Connection sends/receives in 'HTML'. */ + GAIM_CONNECTION_NO_BGCOLOR = 0x0002, /**< Connection does not send/recieve + background colors. */ + GAIM_CONNECTION_AUTO_RESP = 0x0004 /**< Send auto responses when away. */ } GaimConnectionFlags; typedef enum diff -r abd3c684da31 -r 083d1e4a9c78 src/conversation.c --- a/src/conversation.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/conversation.c Sat Sep 27 19:17:21 2003 +0000 @@ -21,6 +21,7 @@ #include "blist.h" #include "conversation.h" #include "debug.h" +#include "imgstore.h" #include "notify.h" #include "prefs.h" #include "prpl.h" @@ -180,8 +181,6 @@ GaimConnection *gc; GaimConversationUiOps *ops; char *buf, *buf2, *buffy = NULL; - gulong length = 0; - gboolean binary = FALSE; int plugin_return; int limit; int err = 0; @@ -261,133 +260,34 @@ gaim_conversation_get_name(conv), &buffy); if (buffy != NULL) { - int imflags = 0; - - if (conv->u.im->images != NULL) { - int id = 0, offset = 0; - char *bigbuf = NULL; - GSList *tmplist; - - for (tmplist = conv->u.im->images; - tmplist != NULL; - tmplist = tmplist->next) { - - char *img_filename = (char *)tmplist->data; - FILE *imgfile; - char *filename, *c; - struct stat st; - char imgtag[1024]; - - id++; - - if (stat(img_filename, &st) != 0) { - gaim_debug(GAIM_DEBUG_ERROR, "conversation", - "Could not stat image %s\n", - img_filename); - - continue; - } - - /* - * Here we check to make sure the user still wants to send - * the image. He may have deleted the tag in which - * case we don't want to send the binary data. - */ - filename = img_filename; - - while ((c = strchr(filename, '/')) != NULL) - filename = c + 1; - - g_snprintf(imgtag, sizeof(imgtag), - "", - filename, id, (int)st.st_size); - - if (strstr(buffy, imgtag) == 0) { - gaim_debug(GAIM_DEBUG_ERROR, "conversation", - "Not sending image: %s\n", img_filename); - continue; - } - - if (!binary) { - length = strlen(buffy) + strlen(""); - bigbuf = g_malloc(length + 1); - g_snprintf(bigbuf, - strlen(buffy) + strlen(" ") + 1, - "%s", buffy); - - offset = strlen(buffy) + strlen(""); - binary = TRUE; - } - - g_snprintf(imgtag, sizeof(imgtag), - "", - id, (int)st.st_size); - - length += strlen(imgtag) + st.st_size + strlen(""); - - bigbuf = g_realloc(bigbuf, length + 1); - - if ((imgfile = fopen(img_filename, "r")) == NULL) { - gaim_debug(GAIM_DEBUG_ERROR, "conversation", - "Could not open image %s\n", img_filename); - continue; - } - - strncpy(bigbuf + offset, imgtag, strlen(imgtag) + 1); - - offset += strlen(imgtag); - offset += fread(bigbuf + offset, 1, st.st_size, imgfile); - - fclose(imgfile); - - strncpy(bigbuf + offset, "", - strlen("") + 1); - - offset += strlen(""); + GaimImFlags imflags = 0; + GaimMessageFlags msgflags = GAIM_MESSAGE_SEND; + + if (im->images != NULL) { + imflags |= GAIM_IM_IMAGES; + msgflags |= GAIM_MESSAGE_IMAGES; + } + + err = serv_send_im(gc, gaim_conversation_get_name(conv), + buffy, imflags); + + if (err > 0) + gaim_im_write(im, NULL, buf, msgflags, time(NULL)); + + if (im->images != NULL) { + GSList *tempy; + int image; + + for (tempy = im->images; + tempy != NULL; + tempy = tempy->next) { + + image = GPOINTER_TO_INT(tempy->data); + gaim_imgstore_unref(image); } - if (binary) { - strncpy(bigbuf + offset, "", - strlen("") + 1); - - err = serv_send_im(gc, gaim_conversation_get_name(conv), - bigbuf, length, imflags); - } - else - err = serv_send_im(gc, gaim_conversation_get_name(conv), - buffy, -1, imflags); - - if (err > 0) { - GSList *tempy; - - for (tempy = conv->u.im->images; - tempy != NULL; - tempy = tempy->next) { - - g_free(tempy->data); - } - - g_slist_free(conv->u.im->images); - conv->u.im->images = NULL; - - if (binary) - gaim_im_write(im, NULL, bigbuf, length, - GAIM_MESSAGE_SEND, time(NULL)); - else - gaim_im_write(im, NULL, buffy, -1, GAIM_MESSAGE_SEND, - time(NULL)); - } - - if (binary) - g_free(bigbuf); - } - else { - err = serv_send_im(gc, gaim_conversation_get_name(conv), - buffy, -1, imflags); - - if (err > 0) - gaim_im_write(im, NULL, buf, -1, GAIM_MESSAGE_SEND, time(NULL)); + g_slist_free(im->images); + im->images = NULL; } gaim_signal_emit(gaim_conversations_get_handle(), "sent-im-msg", @@ -1040,14 +940,18 @@ conversations = g_list_remove(conversations, conv); if (conv->type == GAIM_CONV_IM) { - GSList *snode; + GSList *tempy; + int image; gaim_im_stop_typing_timeout(conv->u.im); gaim_im_stop_type_again_timeout(conv->u.im); - for (snode = conv->u.im->images; snode != NULL; snode = snode->next) { - if (snode->data != NULL) - g_free(snode->data); + for (tempy = conv->u.im->images; + tempy != NULL; + tempy = tempy->next) { + + image = GPOINTER_TO_INT(tempy->data); + gaim_imgstore_unref(image); } g_slist_free(conv->u.im->images); @@ -1432,7 +1336,7 @@ void gaim_conversation_write(GaimConversation *conv, const char *who, - const char *message, size_t length, GaimMessageFlags flags, + const char *message, GaimMessageFlags flags, time_t mtime) { GaimPluginProtocolInfo *prpl_info = NULL; @@ -1504,7 +1408,7 @@ } } - ops->write_conv(conv, who, message, length, flags, mtime); + ops->write_conv(conv, who, message, flags, mtime); win = gaim_conversation_get_window(conv); @@ -1710,7 +1614,7 @@ void gaim_im_write(GaimIm *im, const char *who, const char *message, - size_t len, GaimMessageFlags flags, time_t mtime) + GaimMessageFlags flags, time_t mtime) { GaimConversation *c; @@ -1721,9 +1625,9 @@ /* Raise the window, if specified in prefs. */ if (c->ui_ops != NULL && c->ui_ops->write_im != NULL) - c->ui_ops->write_im(c, who, message, len, flags, mtime); + c->ui_ops->write_im(c, who, message, flags, mtime); else - gaim_conversation_write(c, who, message, -1, flags, mtime); + gaim_conversation_write(c, who, message, flags, mtime); } void @@ -1943,7 +1847,7 @@ if (conv->ui_ops != NULL && conv->ui_ops->write_chat != NULL) conv->ui_ops->write_chat(conv, who, message, flags, mtime); else - gaim_conversation_write(conv, who, message, -1, flags, mtime); + gaim_conversation_write(conv, who, message, flags, mtime); } void @@ -1986,7 +1890,7 @@ _("%s [%s] entered the room."), user, extra_msg); - gaim_conversation_write(conv, NULL, tmp, -1, GAIM_MESSAGE_SYSTEM, time(NULL)); + gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); } gaim_signal_emit(gaim_conversations_get_handle(), @@ -2070,7 +1974,7 @@ g_snprintf(tmp, sizeof(tmp), _("%s is now known as %s"), old_user, new_user); - gaim_conversation_write(conv, NULL, tmp, -1, GAIM_MESSAGE_SYSTEM, time(NULL)); + gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); } } @@ -2114,7 +2018,7 @@ else g_snprintf(tmp, sizeof(tmp), _("%s left the room."), user); - gaim_conversation_write(conv, NULL, tmp, -1, GAIM_MESSAGE_SYSTEM, time(NULL)); + gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); } gaim_signal_emit(gaim_conversations_get_handle(), "chat-buddy-left", @@ -2189,7 +2093,7 @@ g_snprintf(tmp, sizeof(tmp), _(" left the room (%s)."), reason); - gaim_conversation_write(conv, NULL, tmp, -1, + gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); } } diff -r abd3c684da31 -r 083d1e4a9c78 src/conversation.h --- a/src/conversation.h Sat Sep 27 15:45:49 2003 +0000 +++ b/src/conversation.h Sat Sep 27 19:17:21 2003 +0000 @@ -103,15 +103,15 @@ */ typedef enum { - GAIM_MESSAGE_SEND = 0x0001, /**< Outgoing message. */ - GAIM_MESSAGE_RECV = 0x0002, /**< Incoming message. */ - GAIM_MESSAGE_SYSTEM = 0x0004, /**< System message. */ - GAIM_MESSAGE_AUTO_RESP = 0x0008, /**< Auto response. */ - GAIM_MESSAGE_COLORIZE = 0x0010, /**< Colorize nicks. */ - GAIM_MESSAGE_NICK = 0x0020, /**< Contains your nick. */ - GAIM_MESSAGE_NO_LOG = 0x0040, /**< Do not log. */ - GAIM_MESSAGE_WHISPER = 0x0080 /**< Whispered message. */ - + GAIM_MESSAGE_SEND = 0x0001, /**< Outgoing message. */ + GAIM_MESSAGE_RECV = 0x0002, /**< Incoming message. */ + GAIM_MESSAGE_SYSTEM = 0x0004, /**< System message. */ + GAIM_MESSAGE_AUTO_RESP = 0x0008, /**< Auto response. */ + GAIM_MESSAGE_COLORIZE = 0x0010, /**< Colorize nicks. */ + GAIM_MESSAGE_NICK = 0x0020, /**< Contains your nick. */ + GAIM_MESSAGE_NO_LOG = 0x0040, /**< Do not log. */ + GAIM_MESSAGE_WHISPER = 0x0080, /**< Whispered message. */ + GAIM_MESSAGE_IMAGES = 0x0100 /**< Message contains images. */ } GaimMessageFlags; #include "account.h" @@ -156,9 +156,9 @@ void (*write_chat)(GaimConversation *conv, const char *who, const char *message, GaimMessageFlags flags, time_t mtime); void (*write_im)(GaimConversation *conv, const char *who, - const char *message, size_t len, GaimMessageFlags flags, time_t mtime); + const char *message, GaimMessageFlags flags, time_t mtime); void (*write_conv)(GaimConversation *conv, const char *who, - const char *message, size_t length, GaimMessageFlags flags, + const char *message, GaimMessageFlags flags, time_t mtime); void (*chat_add_user)(GaimConversation *conv, const char *user); @@ -754,7 +754,6 @@ * @param conv The conversation. * @param who The user who sent the message. * @param message The message. - * @param length The length of the message. * @param flags The message flags. * @param mtime The time the message was sent. * @@ -762,7 +761,7 @@ * @see gaim_chat_write() */ void gaim_conversation_write(GaimConversation *conv, const char *who, - const char *message, size_t length, GaimMessageFlags flags, + const char *message, GaimMessageFlags flags, time_t mtime); /** @@ -921,19 +920,14 @@ /** * Writes to an IM. * - * The @a len parameter is used for writing binary data, such as an - * image. If @c message is text, specify -1 for @a len. - * * @param im The IM. * @param who The user who sent the message. * @param message The message to write. - * @param len The length of the message, or -1 to specify the length - * of @a message. * @param flags The message flags. * @param mtime The time the message was sent. */ void gaim_im_write(GaimIm *im, const char *who, - const char *message, size_t len, GaimMessageFlags flags, time_t mtime); + const char *message, GaimMessageFlags flags, time_t mtime); /** * Sends a message to this IM conversation. diff -r abd3c684da31 -r 083d1e4a9c78 src/dialogs.c --- a/src/dialogs.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/dialogs.c Sat Sep 27 19:17:21 2003 +0000 @@ -1874,19 +1874,19 @@ if (gaim_prefs_get_bool("/gaim/gtk/conversations/show_urls_as_links")) { linkifyinated = linkify_text(info); - gtk_imhtml_append_text(GTK_IMHTML(b->text), linkifyinated, -1, options); + gtk_imhtml_append_text(GTK_IMHTML(b->text), linkifyinated, options); g_free(linkifyinated); } else - gtk_imhtml_append_text(GTK_IMHTML(b->text), info, -1, options); + gtk_imhtml_append_text(GTK_IMHTML(b->text), info, options); va_start(ap, info); while ((more_info = va_arg(ap, char *)) != NULL) { if (gaim_prefs_get_bool("/gaim/gtk/conversations/show_urls_as_links")) { linkifyinated = linkify_text(more_info); - gtk_imhtml_append_text(GTK_IMHTML(b->text), linkifyinated, -1, options); + gtk_imhtml_append_text(GTK_IMHTML(b->text), linkifyinated, options); g_free(linkifyinated); } else - gtk_imhtml_append_text(GTK_IMHTML(b->text), more_info, -1, options); + gtk_imhtml_append_text(GTK_IMHTML(b->text), more_info, options); } va_end(ap); @@ -3270,7 +3270,7 @@ g_string_append(string, buf); if (i == 30) { - gtk_imhtml_append_text(GTK_IMHTML(view->layout), string->str, -1, view->options); + gtk_imhtml_append_text(GTK_IMHTML(view->layout), string->str, 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 @@ -3282,8 +3282,8 @@ } } - 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_imhtml_append_text(GTK_IMHTML(view->layout), string->str, view->options); + gtk_imhtml_append_text(GTK_IMHTML(view->layout), "
", view->options); gtk_widget_set_sensitive(view->bbox, TRUE); g_signal_handler_disconnect(G_OBJECT(view->window), block); diff -r abd3c684da31 -r 083d1e4a9c78 src/gtkconv.c --- a/src/gtkconv.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/gtkconv.c Sat Sep 27 19:17:21 2003 +0000 @@ -30,9 +30,11 @@ #endif #include +#include #include "debug.h" #include "html.h" +#include "imgstore.h" #include "log.h" #include "multi.h" #include "notify.h" @@ -195,29 +197,37 @@ GaimConversation *conv; GaimGtkConversation *gtkconv; GaimIm *im; - const char *name; - const char *filename; - char *buf; - struct stat st; + char *name, *filename; + char *buf, *data; + size_t size; + GError *error; int id; conv = g_object_get_data(G_OBJECT(wid), "user_data"); gtkconv = GAIM_GTK_CONVERSATION(conv); im = GAIM_IM(conv); - name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(wid)); - id = g_slist_length(im->images) + 1; - - if (gaim_gtk_check_if_dir(name, GTK_FILE_SELECTION(wid))) + name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(wid))); + + if (!name) { + gtk_widget_destroy(gtkconv->dialogs.image); + gtkconv->dialogs.image = NULL; + return; + } + + if (gaim_gtk_check_if_dir(name, GTK_FILE_SELECTION(wid))) { + g_free(name); return; - - gtk_widget_destroy(wid); - - if (!name) - return; - - if (stat(name, &st) != 0) { - gaim_debug(GAIM_DEBUG_ERROR, "gtkconv", - "Could not stat image %s\n", name); + } + + gtk_widget_destroy(gtkconv->dialogs.image); + gtkconv->dialogs.image = NULL; + + if (!g_file_get_contents(name, &data, &size, &error)) { + gaim_notify_error(NULL, NULL, error->message, NULL); + + g_error_free(error); + g_free(name); + return; } @@ -225,13 +235,27 @@ while (strchr(filename, '/')) filename = strchr(filename, '/') + 1; - buf = g_strdup_printf("", - filename, id, (int)st.st_size); - im->images = g_slist_append(im->images, g_strdup(name)); - gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(gtkconv->entry_buffer), - buf, -1); + id = gaim_imgstore_add(data, size, filename); + g_free(data); + + if (!id) { + buf = g_strdup_printf(_("Failed to store image: %s\n"), name); + gaim_notify_error(NULL, NULL, buf, NULL); + + g_free(buf); + g_free(name); + + return; + } + + im->images = g_slist_append(im->images, GINT_TO_POINTER(id)); + + buf = g_strdup_printf("", id, filename); + gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(gtkconv->entry_buffer), buf, -1); g_free(buf); + g_free(name); + set_toggle(gtkconv->toolbar.image, FALSE); } @@ -2700,7 +2724,7 @@ matches = g_list_remove(matches, matches->data); } - gaim_conversation_write(conv, NULL, addthis, -1, GAIM_MESSAGE_NO_LOG, + gaim_conversation_write(conv, NULL, addthis, GAIM_MESSAGE_NO_LOG, time(NULL)); gtk_text_buffer_insert_at_cursor(gtkconv->entry_buffer, partial, -1); g_free(addthis); @@ -4220,7 +4244,7 @@ static void gaim_gtkconv_write_im(GaimConversation *conv, const char *who, - const char *message, size_t len, GaimMessageFlags flags, + const char *message, GaimMessageFlags flags, time_t mtime) { GaimGtkConversation *gtkconv; @@ -4251,7 +4275,7 @@ gtkconv->u.im->a_virgin = FALSE; - gaim_conversation_write(conv, who, message, len, flags, mtime); + gaim_conversation_write(conv, who, message, flags, mtime); } static void @@ -4287,12 +4311,12 @@ gaim_window_raise(gaim_conversation_get_window(conv)); } - gaim_conversation_write(conv, who, message, -1, flags, mtime); + gaim_conversation_write(conv, who, message, flags, mtime); } static void gaim_gtkconv_write_conv(GaimConversation *conv, const char *who, - const char *message, size_t length, GaimMessageFlags flags, + const char *message, GaimMessageFlags flags, time_t mtime) { GaimGtkConversation *gtkconv; @@ -4300,6 +4324,7 @@ GaimConnection *gc; int gtk_font_options = 0; GString *log_str; + GSList *images = NULL; FILE *fd; char buf[BUF_LONG]; char buf2[BUF_LONG]; @@ -4308,9 +4333,7 @@ char *str; char *with_font_tag; char *sml_attrib = NULL; - - if(length == -1) - length = strlen(message) + 1; + size_t length = strlen(message) + 1; gtkconv = GAIM_GTK_CONVERSATION(conv); gc = gaim_conversation_get_gc(conv); @@ -4327,6 +4350,67 @@ gaim_window_show(win); } + if (flags & GAIM_MESSAGE_IMAGES) { + GData *attribs; + GdkPixbuf *broken; + const char *tmp, *start, *end; + + broken = gtk_widget_render_icon(GTK_WIDGET(gtkconv->imhtml), + GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON, + "gaim-missing-image"); + + tmp = message; + while (gaim_markup_find_tag("img", tmp, &start, &end, &attribs)) { + GaimStoredImage *image = NULL; + GdkPixbufLoader *loader; + GError *error = NULL; + char *id = NULL; + + tmp = end + 1; + + id = g_datalist_get_data(&attribs, "id"); + + if (id) + image = gaim_imgstore_get(atoi(id)); + + g_datalist_clear(&attribs); + + if (!image) { + g_object_ref(G_OBJECT(broken)); + images = g_slist_append(images, broken); + continue; + } + + loader = gdk_pixbuf_loader_new(); + + if (!gdk_pixbuf_loader_write(loader, image->data, image->size, &error)) { + if (error) { + gaim_debug(GAIM_DEBUG_ERROR, "gtkconv", + "Failed to make pixbuf for IM Image: %s\n", + error->message); + g_error_free(error); + } + g_object_ref(G_OBJECT(broken)); + images = g_slist_append(images, broken); + } else { + GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); + if (pixbuf) { + if (image->filename) + g_object_set_data_full(G_OBJECT(pixbuf), "filename", + g_strdup(image->filename), g_free); + g_object_ref(G_OBJECT(pixbuf)); + images = g_slist_append(images, pixbuf); + } else { + g_object_ref(G_OBJECT(broken)); + images = g_slist_append(images, broken); + } + } + + gdk_pixbuf_loader_close(loader, NULL); + } + + g_object_unref(G_OBJECT(broken)); + } if(time(NULL) > mtime + 20*60) /* show date if older than 20 minutes */ strftime(mdate, sizeof(mdate), "%Y-%m-%d %H:%M:%S", localtime(&mtime)); @@ -4367,7 +4451,7 @@ "%s
", mdate, message); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, -1, 0); + gtk_imhtml_append_text_with_images(GTK_IMHTML(gtkconv->imhtml), buf2, 0, images); if (gaim_prefs_get_bool("/gaim/gtk/logging/strip_html")) { char *t1 = strip_html(buf); @@ -4419,7 +4503,7 @@ "%s
", message); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf, -1, 0); + gtk_imhtml_append_text_with_images(GTK_IMHTML(gtkconv->imhtml), buf, 0, images); } else { char *new_message = g_memdup(message, length); @@ -4498,7 +4582,7 @@ g_free(str); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, -1, 0); + gtk_imhtml_append_text_with_images(GTK_IMHTML(gtkconv->imhtml), buf2, 0, images); if(gc){ char *pre = g_strdup_printf("", sml_attrib ? sml_attrib : ""); @@ -4518,12 +4602,11 @@ else with_font_tag = g_memdup(new_message, length); - log_str = gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), - with_font_tag, length, gtk_font_options); - - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "
", -1, 0); - - /* XXX This needs to be updated for the new length argument. */ + log_str = gtk_imhtml_append_text_with_images(GTK_IMHTML(gtkconv->imhtml), + with_font_tag, gtk_font_options, images); + + gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "
", 0); + if (gaim_prefs_get_bool("/gaim/gtk/logging/strip_html")) { char *t1, *t2; @@ -4553,7 +4636,6 @@ g_free(t2); } - /* XXX This needs to be updated for the new length argument. */ if (gaim_conversation_is_logging(conv)) { char *t1, *t2; char nm[256]; @@ -4597,6 +4679,17 @@ if(sml_attrib) g_free(sml_attrib); + + if (images) { + GSList *tmp = images; + GdkPixbuf *pixbuf; + while (tmp) { + pixbuf = tmp->data; + g_object_unref(G_OBJECT(pixbuf)); + tmp = tmp->next; + } + g_slist_free(images); + } } static void diff -r abd3c684da31 -r 083d1e4a9c78 src/gtkdebug.c --- a/src/gtkdebug.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/gtkdebug.c Sat Sep 27 19:17:21 2003 +0000 @@ -319,7 +319,7 @@ g_free(cat_s); - gtk_imhtml_append_text(GTK_IMHTML(debug_win->text), s, -1, 0); + gtk_imhtml_append_text(GTK_IMHTML(debug_win->text), s, 0); g_free(s); } diff -r abd3c684da31 -r 083d1e4a9c78 src/gtkimhtml.c --- a/src/gtkimhtml.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/gtkimhtml.c Sat Sep 27 19:17:21 2003 +0000 @@ -853,6 +853,7 @@ VALID_OPT_TAG ("SPAN"); VALID_TAG ("/SPAN"); VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */ + VALID_TAG ("IMG"); if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { gchar *e = strstr (string + strlen("!--"), "-->"); @@ -995,10 +996,10 @@ -GString* gtk_imhtml_append_text (GtkIMHtml *imhtml, - const gchar *text, - gint len, - GtkIMHtmlOptions options) +GString* gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml, + const gchar *text, + GtkIMHtmlOptions options, + GSList *images) { gint pos = 0; GString *str = NULL; @@ -1009,6 +1010,7 @@ gchar *tag; gchar *url = NULL; gchar *bg = NULL; + gint len; gint tlen, smilelen, wpos=0; gint type; const gchar *c; @@ -1033,11 +1035,9 @@ 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); + len = strlen(text); ws = g_malloc(len + 1); ws[0] = 0; @@ -1154,7 +1154,7 @@ ws[wpos] = '\n'; wpos++; NEW_BIT (NEW_TEXT_BIT); - break; + break; case 26: /* HR */ case 42: /* HR (opt) */ ws[wpos++] = '\n'; @@ -1196,16 +1196,8 @@ case 37: /* FONT */ case 38: /* HEAD */ case 39: /* /HEAD */ - break; - case 40: /* BINARY */ - NEW_BIT (NEW_TEXT_BIT); - while (pos < len && g_ascii_strncasecmp("
", c, strlen("
"))) { - c++; - pos++; - } - c = c - tlen; /* Because it will add this later */ - break; - case 41: /* /BINARY */ + case 40: /* BINARY */ + case 41: /* /BINARY */ break; case 43: /* FONT (opt) */ { @@ -1290,53 +1282,25 @@ } break; case 46: /* IMG (opt) */ + case 59: /* IMG */ { - 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="); - gint im_len = datasize?atoi(datasize):0; - - if (src && id && im_len && im_len <= len - pos) { - /* This is an embedded IM image, or is it? */ - char *tmp = NULL; - const char *alltext; - guchar *imagedata = NULL; - - GdkPixbufLoader *load; - GdkPixbuf *imagepb = NULL; - GError *error = NULL; - - tmp = g_strdup_printf("", id, datasize); - alltext = strstr(c, tmp); - imagedata = g_memdup(alltext + strlen(tmp), im_len); - - g_free(tmp); + GdkPixbuf *img = NULL; + const gchar *filename = NULL; - load = gdk_pixbuf_loader_new(); - if (!gdk_pixbuf_loader_write(load, imagedata, im_len, &error)){ - fprintf(stderr, "IM Image corrupted or unreadable.: %s\n", error->message); - } else { - imagepb = gdk_pixbuf_loader_get_pixbuf(load); - if (imagepb) { - scalable = gtk_imhtml_image_new(imagepb, g_strdup(src)); - NEW_BIT(NEW_SCALABLE_BIT); - g_object_unref(imagepb); - } - } + if (images && images->data) { + img = images->data; + images = images->next; + filename = g_object_get_data(G_OBJECT(img), "filename"); + g_object_ref(G_OBJECT(img)); + } else { + img = gtk_widget_render_icon(GTK_WIDGET(imhtml), + GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON, + "gtkimhtml-missing-image"); + } - gdk_pixbuf_loader_close(load, NULL); - - - g_free(imagedata); - g_free(id); - g_free(datasize); - g_free(src); - - break; - } - g_free(id); - g_free(datasize); - g_free(src); + scalable = gtk_imhtml_image_new(img, filename); + NEW_BIT(NEW_SCALABLE_BIT); + g_object_unref(G_OBJECT(img)); } case 47: /* P (opt) */ case 48: /* H3 (opt) */ @@ -1346,7 +1310,7 @@ case 56: /* SPAN */ case 57: /* /SPAN */ break; - case 59: /* comment */ + case 60: /* comment */ NEW_BIT (NEW_TEXT_BIT); if (imhtml->show_comments) wpos = g_snprintf (ws, len, "%s", tag); @@ -1533,7 +1497,7 @@ } /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ -GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, gchar *filename) +GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename) { GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); @@ -1547,7 +1511,7 @@ im_image->width = gdk_pixbuf_get_width(img); im_image->height = gdk_pixbuf_get_height(img); im_image->mark = NULL; - im_image->filename = filename; + im_image->filename = filename ? g_strdup(filename) : NULL; g_object_ref(img); return GTK_IMHTML_SCALABLE(im_image); @@ -1668,7 +1632,8 @@ { GtkWidget *sel = gtk_file_selection_new(_("Save Image")); - gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename); + if (image->filename) + gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename); g_object_set_data(G_OBJECT(sel), "GtkIMHtmlImage", image); g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", G_CALLBACK(write_img_to_file), sel); @@ -1718,7 +1683,8 @@ GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; g_object_unref(image->pixbuf); - g_free(image->filename); + if (image->filename) + g_free(image->filename); g_free(scale); } diff -r abd3c684da31 -r 083d1e4a9c78 src/gtkimhtml.h --- a/src/gtkimhtml.h Sat Sep 27 15:45:49 2003 +0000 +++ b/src/gtkimhtml.h Sat Sep 27 19:17:21 2003 +0000 @@ -144,15 +144,20 @@ void gtk_imhtml_show_comments (GtkIMHtml *imhtml, gboolean show); -GString* gtk_imhtml_append_text (GtkIMHtml *imhtml, - const gchar *text, gint len, GtkIMHtmlOptions options); +#define gtk_imhtml_append_text(x, y, z) \ + gtk_imhtml_append_text_with_images(x, y, z, NULL) + +GString* gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml, + const gchar *text, + GtkIMHtmlOptions options, + GSList *images); void gtk_imhtml_clear (GtkIMHtml *imhtml); void gtk_imhtml_page_up (GtkIMHtml *imhtml); void gtk_imhtml_page_down (GtkIMHtml *imhtml); GtkIMHtmlScalable *gtk_imhtml_scalable_new(); -GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, gchar *filename); +GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename); void gtk_imhtml_image_free(GtkIMHtmlScalable *); void gtk_imhtml_image_scale(GtkIMHtmlScalable *, int, int); void gtk_imhtml_image_add_to(GtkIMHtmlScalable *, GtkIMHtml *, GtkTextIter *); diff -r abd3c684da31 -r 083d1e4a9c78 src/gtknotify.c --- a/src/gtknotify.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/gtknotify.c Sat Sep 27 19:17:21 2003 +0000 @@ -329,7 +329,7 @@ options ^= GTK_IMHTML_NO_NEWLINE; options ^= GTK_IMHTML_NO_SCROLL; - gtk_imhtml_append_text(GTK_IMHTML(imhtml), text, -1, options); + gtk_imhtml_append_text(GTK_IMHTML(imhtml), text, options); /* Show the window */ gtk_widget_show(window); diff -r abd3c684da31 -r 083d1e4a9c78 src/gtkpounce.c --- a/src/gtkpounce.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/gtkpounce.c Sat Sep 27 19:17:21 2003 +0000 @@ -859,10 +859,10 @@ if (conv == NULL) conv = gaim_conversation_new(GAIM_CONV_IM, account, pouncee); - gaim_conversation_write(conv, NULL, message, -1, + gaim_conversation_write(conv, NULL, message, GAIM_MESSAGE_SEND, time(NULL)); - serv_send_im(account->gc, (char *)pouncee, (char *)message, -1, 0); + serv_send_im(account->gc, (char *)pouncee, (char *)message, 0); } } diff -r abd3c684da31 -r 083d1e4a9c78 src/gtkprefs.c --- a/src/gtkprefs.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/gtkprefs.c Sat Sep 27 19:17:21 2003 +0000 @@ -2114,9 +2114,9 @@ gtk_imhtml_clear(GTK_IMHTML(away_text)); strncpy(buffer, am->message, BUF_LONG); tmp = stylize(buffer, BUF_LONG); - gtk_imhtml_append_text(GTK_IMHTML(away_text), tmp, -1, GTK_IMHTML_NO_TITLE | + gtk_imhtml_append_text(GTK_IMHTML(away_text), tmp, GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_SCROLL); - gtk_imhtml_append_text(GTK_IMHTML(away_text), "
", -1, GTK_IMHTML_NO_TITLE | + gtk_imhtml_append_text(GTK_IMHTML(away_text), "
", GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_SCROLL); g_free(tmp); g_value_unset (&val); diff -r abd3c684da31 -r 083d1e4a9c78 src/imgstore.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/imgstore.c Sat Sep 27 19:17:21 2003 +0000 @@ -0,0 +1,140 @@ +/** + * @file imgstore.h IM Image Store API + * @ingroup core + * + * gaim + * + * Copyright (C) 2003 Robert McQueen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include +#include +#include + +static GSList *imgstore = NULL; +static int nextid = 0; + +typedef struct +{ + int id; + int refcount; + GaimStoredImage *img; +} GaimStoredImagePriv; + +/* private functions */ + +static GaimStoredImagePriv *gaim_imgstore_get_priv(int id) { + GSList *tmp = imgstore; + GaimStoredImagePriv *priv = NULL; + + g_return_val_if_fail(id > 0, NULL); + + while (tmp && !priv) { + GaimStoredImagePriv *tmp_priv = tmp->data; + + if (tmp_priv->id == id) + priv = tmp_priv; + + tmp = tmp->next; + } + + if (!priv) + gaim_debug(GAIM_DEBUG_ERROR, "imgstore", "failed to find image id %d\n", id); + + return priv; +} + +static void gaim_imgstore_free_priv(GaimStoredImagePriv *priv) { + GaimStoredImage *img = NULL; + + g_return_if_fail(priv != NULL); + + img = priv->img; + if (img) { + if (img->data) + g_free(img->data); + if (img->filename) + g_free(img->filename); + g_free(img); + } + + gaim_debug(GAIM_DEBUG_INFO, "imgstore", "freed image id %d\n", priv->id); + + g_free(priv); + + imgstore = g_slist_remove(imgstore, priv); +} + +/* public functions */ + +int gaim_imgstore_add(const void *data, size_t size, const char *filename) { + GaimStoredImagePriv *priv; + GaimStoredImage *img; + + g_return_val_if_fail(data != NULL, 0); + g_return_val_if_fail(size > 0, 0); + + img = g_new0(GaimStoredImage, 1); + img->data = g_memdup(data, size); + img->size = size; + img->filename = g_strdup(filename); + + priv = g_new0(GaimStoredImagePriv, 1); + priv->id = ++nextid; + priv->refcount = 1; + priv->img = img; + + imgstore = g_slist_append(imgstore, priv); + gaim_debug(GAIM_DEBUG_INFO, "imgstore", "added image id %d\n", priv->id); + + return priv->id; +} + +GaimStoredImage *gaim_imgstore_get(int id) { + GaimStoredImagePriv *priv = gaim_imgstore_get_priv(id); + + g_return_val_if_fail(priv != NULL, NULL); + + gaim_debug(GAIM_DEBUG_INFO, "imgstore", "retrieved image id %d\n", priv->id); + + return priv->img; +} + +void gaim_imgstore_ref(int id) { + GaimStoredImagePriv *priv = gaim_imgstore_get_priv(id); + + g_return_if_fail(priv != NULL); + + (priv->refcount)++; + + gaim_debug(GAIM_DEBUG_INFO, "imgstore", "referenced image id %d (count now %d)\n", priv->id, priv->refcount); +} + +void gaim_imgstore_unref(int id) { + GaimStoredImagePriv *priv = gaim_imgstore_get_priv(id); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->refcount > 0); + + (priv->refcount)--; + + gaim_debug(GAIM_DEBUG_INFO, "imgstore", "unreferenced image id %d (count now %d)\n", priv->id, priv->refcount); + + if (priv->refcount == 0) + gaim_imgstore_free_priv(priv); +} diff -r abd3c684da31 -r 083d1e4a9c78 src/imgstore.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/imgstore.h Sat Sep 27 19:17:21 2003 +0000 @@ -0,0 +1,88 @@ +/** + * @file imgstore.h IM Image Store API + * @ingroup core + * + * gaim + * + * Copyright (C) 2003 Robert McQueen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _GAIM_IMGSTORE_H_ +#define _GAIM_IMGSTORE_H_ + +/** + * Stored image + * + * Represents a single IM image awaiting display and/or transmission. + */ +typedef struct +{ + char *data; /**< The image data. */ + size_t size; /**< The image data's size. */ + char *filename; /**< The filename (for the UI) */ +} GaimStoredImage; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Add an image to the store. The caller owns a reference + * to the image in the store, and must dereference the image + * with gaim_imgstore_unref for it to be freed. + * + * @param data Pointer to the image data. + * @param size Image data's size. + * @param filename Filename associated with image. + + * @return ID for the image. + */ +int gaim_imgstore_add(const void *data, size_t size, const char *filename); + +/** + * Retrieve an image from the store. The caller does not own a + * reference to the image. + * + * @param id The ID for the image. + * + * @return A pointer to the requested image, or NULL if it was not found. + */ +GaimStoredImage *gaim_imgstore_get(int id); + +/** + * Increment the reference count for an image in the store. The + * image will be removed from the store when the reference count + * is zero. + * + * @param id The ID for the image. + */ +void gaim_imgstore_ref(int id); + +/** + * Decrement the reference count for an image in the store. The + * image will be removed from the store when the reference count + * is zero. + * + * @param id The ID for the image. + */ +void gaim_imgstore_unref(int id); + +#ifdef __cplusplus +} +#endif + +#endif /* _GAIM_IMGSTORE_H_ */ diff -r abd3c684da31 -r 083d1e4a9c78 src/plugin.c --- a/src/plugin.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/plugin.c Sat Sep 27 19:17:21 2003 +0000 @@ -779,7 +779,6 @@ gaim_plugins_probe(const char *ext) { #ifdef GAIM_PLUGINS - GList *l, *l_next; GDir *dir; const gchar *file; gchar *path; diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/gg/gg.c --- a/src/protocols/gg/gg.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/gg/gg.c Sat Sep 27 19:17:21 2003 +0000 @@ -1,6 +1,6 @@ /* * gaim - Gadu-Gadu Protocol Plugin - * $Id: gg.c 7326 2003-09-07 23:47:00Z chipx86 $ + * $Id: gg.c 7538 2003-09-27 19:17:21Z thekingant $ * * Copyright (C) 2001 Arkadiusz Mi¶kiewicz * @@ -315,7 +315,7 @@ imsg = charset_convert(e->event.msg.message, "CP1250", "UTF-8"); strip_linefeed(imsg); /* e->event.msg.time - we don't know what this time is for */ - serv_got_im(gc, user, imsg, 0, time(NULL), -1); + serv_got_im(gc, user, imsg, 0, time(NULL)); g_free(imsg); } break; @@ -560,7 +560,7 @@ g_free(gc->proto_data); } -static int agg_send_im(GaimConnection *gc, const char *who, const char *msg, int len, GaimImFlags flags) +static int agg_send_im(GaimConnection *gc, const char *who, const char *msg, GaimImFlags flags) { struct agg_data *gd = (struct agg_data *)gc->proto_data; gchar *imsg; diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/irc/cmds.c --- a/src/protocols/irc/cmds.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/irc/cmds.c Sat Sep 27 19:17:21 2003 +0000 @@ -40,7 +40,7 @@ buf = g_strdup_printf(_("Unknown command: %s"), cmd); if (gaim_conversation_get_type(convo) == GAIM_CONV_IM) - gaim_im_write(GAIM_IM(convo), "", buf, -1, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); + gaim_im_write(GAIM_IM(convo), "", buf, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); else gaim_chat_write(GAIM_CHAT(convo), "", buf, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); g_free(buf); @@ -145,7 +145,7 @@ "AWAY JOIN ME MODE
" "MSG NICK OPERWALL PING
" "QUERY QUIT QUOTE UMODE
" - "WALLOPS WHOIS"), -1, GAIM_MESSAGE_NO_LOG, time(NULL)); + "WALLOPS WHOIS"), GAIM_MESSAGE_NO_LOG, time(NULL)); } return 0; @@ -413,7 +413,7 @@ gc = gaim_account_get_connection(irc->account); irc_cmd_privmsg(irc, cmd, target, args); gaim_im_write(GAIM_IM(convo), gaim_connection_get_display_name(gc), - args[1], -1, GAIM_MESSAGE_SEND, time(NULL)); + args[1], GAIM_MESSAGE_SEND, time(NULL)); } return 0; diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/irc/irc.c --- a/src/protocols/irc/irc.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/irc/irc.c Sat Sep 27 19:17:21 2003 +0000 @@ -43,7 +43,7 @@ static void irc_login(GaimAccount *account); static void irc_login_cb(gpointer data, gint source, GaimInputCondition cond); static void irc_close(GaimConnection *gc); -static int irc_im_send(GaimConnection *gc, const char *who, const char *what, int len, GaimImFlags flags); +static int irc_im_send(GaimConnection *gc, const char *who, const char *what, GaimImFlags flags); static int irc_chat_send(GaimConnection *gc, int id, const char *what); static void irc_chat_join (GaimConnection *gc, GHashTable *data); static void irc_input_cb(gpointer data, gint source, GaimInputCondition cond); @@ -245,7 +245,7 @@ g_free(irc); } -static int irc_im_send(GaimConnection *gc, const char *who, const char *what, int len, GaimImFlags flags) +static int irc_im_send(GaimConnection *gc, const char *who, const char *what, GaimImFlags flags) { struct irc_conn *irc = gc->proto_data; const char *args[2]; diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/irc/msgs.c --- a/src/protocols/irc/msgs.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/irc/msgs.c Sat Sep 27 19:17:21 2003 +0000 @@ -88,7 +88,7 @@ gc = gaim_account_get_connection(irc->account); if (gc) - serv_got_im(gc, args[1], args[2], GAIM_IM_AUTO_RESP, time(NULL), -1); + serv_got_im(gc, args[1], args[2], GAIM_IM_AUTO_RESP, time(NULL)); } void irc_msg_badmode(struct irc_conn *irc, const char *name, const char *from, char **args) @@ -289,7 +289,7 @@ if (gaim_conversation_get_type(convo) == GAIM_CONV_CHAT) gaim_chat_write(GAIM_CHAT(convo), "", msg, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); else - gaim_im_write(GAIM_IM(convo), "", msg, -1, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); + gaim_im_write(GAIM_IM(convo), "", msg, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); g_free(msg); g_free(irc->nameconv); irc->nameconv = NULL; @@ -369,7 +369,7 @@ gaim_chat_write(GAIM_CHAT(convo), args[1], _("no such channel"), GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); else - gaim_im_write(GAIM_IM(convo), args[1], _("User is not logged in"), -1, + gaim_im_write(GAIM_IM(convo), args[1], _("User is not logged in"), GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); } else { if ((gc = gaim_account_get_connection(irc->account)) == NULL) @@ -726,7 +726,7 @@ if (gaim_conversation_get_type (convo) == GAIM_CONV_CHAT) gaim_chat_write(GAIM_CHAT(convo), "PONG", msg, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); else - gaim_im_write(GAIM_IM(convo), "PONG", msg, -1, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); + gaim_im_write(GAIM_IM(convo), "PONG", msg, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); } else { gc = gaim_account_get_connection(irc->account); if (!gc) { @@ -765,9 +765,9 @@ } if (!gaim_utf8_strcasecmp(args[0], gaim_connection_get_display_name(gc))) { - serv_got_im(gc, nick, msg, 0, time(NULL), -1); + serv_got_im(gc, nick, msg, 0, time(NULL)); } else if (notice) { - serv_got_im(gc, nick, msg, 0, time(NULL), -1); + serv_got_im(gc, nick, msg, 0, time(NULL)); } else { convo = gaim_find_conversation_with_account(args[0], irc->account); if (convo) diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/jabber/jabber.c --- a/src/protocols/jabber/jabber.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/jabber/jabber.c Sat Sep 27 19:17:21 2003 +0000 @@ -1481,7 +1481,7 @@ jabber_track_convo_thread(gjc, from, thread_id); if (gaim_find_conversation_with_account(from, GJ_GC(gjc)->account)) serv_got_im(GJ_GC(gjc), from, m, flags, - time_sent, -1); + time_sent); else { if(p->from->user) { from = g_strdup_printf("%s@%s", p->from->user, @@ -1490,7 +1490,7 @@ /* server message? */ from = g_strdup(p->from->server); } - serv_got_im(GJ_GC(gjc), from, m, flags, time_sent, -1); + serv_got_im(GJ_GC(gjc), from, m, flags, time_sent); g_free(from); } } @@ -2603,7 +2603,7 @@ g_free(xhtml); } -static int jabber_send_im(GaimConnection *gc, const char *who, const char *message, int len, GaimImFlags flags) +static int jabber_send_im(GaimConnection *gc, const char *who, const char *message, GaimImFlags flags) { xmlnode x, y; char *thread_id = NULL; diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/msn/msn.c --- a/src/protocols/msn/msn.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/msn/msn.c Sat Sep 27 19:17:21 2003 +0000 @@ -478,7 +478,7 @@ static int msn_send_im(GaimConnection *gc, const char *who, const char *message, - int len, GaimImFlags flags) + GaimImFlags flags) { GaimAccount *account = gaim_connection_get_account(gc); MsnSession *session = gc->proto_data; @@ -525,7 +525,7 @@ */ serv_got_typing_stopped(gc, (char *)who); serv_got_im(gc, who, message, flags, - time(NULL), -1); + time(NULL)); } return 1; diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/msn/switchboard.c --- a/src/protocols/msn/switchboard.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/msn/switchboard.c Sat Sep 27 19:17:21 2003 +0000 @@ -157,7 +157,7 @@ } if (*buf != '\0' && (conv = gaim_find_conversation_with_account(user, account)) != NULL) { - gaim_conversation_write(conv, NULL, buf, -1, GAIM_MESSAGE_SYSTEM, + gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL)); } @@ -352,7 +352,7 @@ serv_got_chat_in(gc, gaim_chat_get_id(GAIM_CHAT(swboard->chat)), servconn->msg_passport, 0, body, time(NULL)); else - serv_got_im(gc, servconn->msg_passport, body, 0, time(NULL), -1); + serv_got_im(gc, servconn->msg_passport, body, 0, time(NULL)); g_free(body); @@ -633,7 +633,9 @@ char *buf; size_t len; int ret; +#if 0 FILE *fp; +#endif g_return_val_if_fail(swboard != NULL, FALSE); g_return_val_if_fail(msg != NULL, FALSE); diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/napster/napster.c --- a/src/protocols/napster/napster.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/napster/napster.c Sat Sep 27 19:17:21 2003 +0000 @@ -129,7 +129,7 @@ } /* 205 - MSG_CLIENT_PRIVMSG */ -static int nap_send_im(GaimConnection *gc, const char *who, const char *message, int len, GaimImFlags flags) +static int nap_send_im(GaimConnection *gc, const char *who, const char *message, GaimImFlags flags) { if ((strlen(message) < 2) || (message[0] != '/' ) || (message[1] == '/')) { @@ -284,7 +284,7 @@ case 205: /* MSG_CLIENT_PRIVMSG */ res = g_strsplit(buf, " ", 2); - serv_got_im(gc, res[0], res[1], 0, time(NULL), -1); + serv_got_im(gc, res[0], res[1], 0, time(NULL)); g_strfreev(res); break; @@ -305,7 +305,7 @@ case 214: /* MSG_SERVER_STATS */ res = g_strsplit(buf, " ", 3); buf2 = g_strdup_printf(_("users: %s, files: %s, size: %sGB"), res[0], res[1], res[2]); - serv_got_im(gc, "server", buf2, 0, time(NULL), -1); + serv_got_im(gc, "server", buf2, 0, time(NULL)); g_free(buf2); g_strfreev(res); break; @@ -343,7 +343,7 @@ case 404: /* MSG_SERVER_NOSUCH */ /* abused by opennap servers to broadcast stuff */ - serv_got_im(gc, "server", buf, 0, time(NULL), -1); + serv_got_im(gc, "server", buf, 0, time(NULL)); break; case 405: /* MSG_SERVER_JOIN_ACK */ @@ -380,7 +380,7 @@ case 603: /* MSG_CLIENT_WHOIS */ buf2 = g_strdup_printf(_("%s requested your information"), buf); - serv_got_im(gc, "server", buf2, 0, time(NULL), -1); + serv_got_im(gc, "server", buf2, 0, time(NULL)); g_free(buf2); break; @@ -394,16 +394,16 @@ case 621: case 622: /* MSG_CLIENT_MOTD */ /* also replaces MSG_SERVER_MOTD, so we should display it */ - serv_got_im(gc, "motd", buf, 0, time(NULL), -1); + serv_got_im(gc, "motd", buf, 0, time(NULL)); break; case 627: /* MSG_CLIENT_WALLOP */ /* abused by opennap server maintainers to broadcast stuff */ - serv_got_im(gc, "wallop", buf, 0, time(NULL), -1); + serv_got_im(gc, "wallop", buf, 0, time(NULL)); break; case 628: /* MSG_CLIENT_ANNOUNCE */ - serv_got_im(gc, "announce", buf, 0, time(NULL), -1); + serv_got_im(gc, "announce", buf, 0, time(NULL)); break; case 748: /* MSG_SERVER_GHOST */ @@ -416,7 +416,7 @@ case 751: /* MSG_CLIENT_PING */ buf2 = g_strdup_printf(_("%s requested a PING"), buf); - serv_got_im(gc, "server", buf2, 0, time(NULL), -1); + serv_got_im(gc, "server", buf2, 0, time(NULL)); g_free(buf2); /* send back a pong */ /* MSG_CLIENT_PONG */ diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/oscar/oscar.c --- a/src/protocols/oscar/oscar.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/oscar/oscar.c Sat Sep 27 19:17:21 2003 +0000 @@ -32,6 +32,7 @@ #include "conversation.h" #include "debug.h" #include "ft.h" +#include "imgstore.h" #include "multi.h" #include "notify.h" #include "privacy.h" @@ -270,7 +271,7 @@ static int gaim_odc_initiate (aim_session_t *, aim_frame_t *, ...); static int gaim_odc_incoming (aim_session_t *, aim_frame_t *, ...); static int gaim_odc_typing (aim_session_t *, aim_frame_t *, ...); -static int gaim_update_ui (aim_session_t *, aim_frame_t *, ...); +static int gaim_odc_update_ui (aim_session_t *, aim_frame_t *, ...); /* for file transfer */ static int oscar_sendfile_estblsh(aim_session_t *, aim_frame_t *, ...); @@ -480,7 +481,7 @@ cnv = gaim_find_conversation_with_account(sn, gaim_connection_get_account(gc)); if (cnv) - gaim_conversation_write(cnv, NULL, buf, -1, GAIM_MESSAGE_SYSTEM, time(NULL)); + gaim_conversation_write(cnv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL)); gaim_conversation_update_progress(cnv, 0); @@ -1912,7 +1913,7 @@ if (getpeername(source, &name, &name_len) == 0) { g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name); dim->connected = TRUE; - gaim_conversation_write(cnv, NULL, buf, -1, GAIM_MESSAGE_SYSTEM, time(NULL)); + gaim_conversation_write(cnv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL)); } od->direct_ims = g_slist_append(od->direct_ims, dim); @@ -2136,7 +2137,7 @@ aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, gaim_odc_typing, 0); aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER, - gaim_update_ui, 0); + gaim_odc_update_ui, 0); for (i = 0; i < (int)strlen(d->ip); i++) { if (d->ip[i] == ':') { port = atoi(&(d->ip[i+1])); @@ -2267,7 +2268,7 @@ } /* strip_linefeed(tmp); */ - serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL), -1); + serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL)); g_free(tmp); return 1; @@ -2583,9 +2584,9 @@ gchar *uin = g_strdup_printf("%u", args->uin); if (t) { /* This is an offline message */ /* I think this timestamp is in UTC, or something */ - serv_got_im(gc, uin, msg2[0], 0, t, -1); + serv_got_im(gc, uin, msg2[0], 0, t); } else { /* This is a message from MacICQ/Miranda */ - serv_got_im(gc, uin, msg2[0], 0, time(NULL), -1); + serv_got_im(gc, uin, msg2[0], 0, time(NULL)); } g_free(uin); } @@ -2595,7 +2596,7 @@ if (i >= 2) { gchar *uin = g_strdup_printf("%u", args->uin); gchar *message = g_strdup_printf("%s", msg2[1], msg2[0]); - serv_got_im(gc, uin, message, 0, time(NULL), -1); + serv_got_im(gc, uin, message, 0, time(NULL)); g_free(uin); g_free(message); } @@ -3057,6 +3058,7 @@ return 1; } +#if 0 static char *images(int flags) { static char buf[1024]; g_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s", @@ -3069,7 +3071,7 @@ (flags & AIM_FLAG_WIRELESS) ? "" : ""); return buf; } - +#endif static char *caps_string(guint caps) { @@ -3207,7 +3209,9 @@ "%s" "%s\n" "
\n"), - info->sn, images(info->flags), + info->sn, + /* images(info->flags), */ + "", (int)((info->warnlevel/10.0) + 0.5), onlinesince ? onlinesince : "", membersince ? membersince : "", @@ -4276,8 +4280,9 @@ return 0; } static void oscar_ask_direct_im(GaimConnection *gc, const char *name); - -static int oscar_send_im(GaimConnection *gc, const char *name, const char *message, int len, GaimImFlags imflags) { +static int gaim_odc_send_im(aim_session_t *, aim_conn_t *, const char *, GaimImFlags); + +static int oscar_send_im(GaimConnection *gc, const char *name, const char *message, GaimImFlags imflags) { struct oscar_data *od = (struct oscar_data *)gc->proto_data; struct direct_im *dim = find_direct_im(od, name); int ret = 0; @@ -4287,12 +4292,8 @@ if (dim && dim->connected) { /* If we're directly connected, send a direct IM */ - /* XXX - The last parameter below is the encoding. Let Paco-Paco do something with it. */ - if (imflags & GAIM_IM_AUTO_RESP) - ret = aim_odc_send_im(od->sess, dim->conn, message, len == -1 ? strlen(message) : len, 0, 1); - else - ret = aim_odc_send_im(od->sess, dim->conn, message, len == -1 ? strlen(message) : len, 0, 0); - } else if (len != -1) { + ret = gaim_odc_send_im(od->sess, dim->conn, message, imflags); + } else if (imflags & GAIM_IM_IMAGES) { /* Trying to send an IM image outside of a direct connection. */ oscar_ask_direct_im(gc, name); ret = -ENOTCONN; @@ -5625,16 +5626,21 @@ dim->connected = TRUE; g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), sn); g_free(sn); - gaim_conversation_write(cnv, NULL, buf, -1, GAIM_MESSAGE_SYSTEM, time(NULL)); + gaim_conversation_write(cnv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL)); aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, gaim_odc_incoming, 0); aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, gaim_odc_typing, 0); - aim_conn_addhandler(sess, newconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER, gaim_update_ui, 0); + aim_conn_addhandler(sess, newconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER, gaim_odc_update_ui, 0); return 1; } -static int gaim_update_ui(aim_session_t *sess, aim_frame_t *fr, ...) { +/* + * This is called when each chunk of an image is received. It can be used to + * update a progress bar, or to eat lots of dry cat food. Wet cat food is + * nasty, you sicko. + */ +static int gaim_odc_update_ui(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; char *sn; double percent; @@ -5654,10 +5660,11 @@ gaim_input_remove(dim->watcher); /* Otherwise, the callback will callback */ dim->watcher = 0; } + /* XXX is this really necessary? */ while (gtk_events_pending()) gtk_main_iteration(); - c = gaim_find_conversation(sn); + c = gaim_find_conversation_with_account(sn, gaim_connection_get_account(gc)); if (c != NULL) gaim_conversation_update_progress(c, percent); dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, @@ -5666,20 +5673,53 @@ return 1; } +/* + * This is called after a direct IM has been received in its entirety. This + * function is passed a long chunk of data which contains the IM with any + * data chunks (images) appended to it. + * + * This function rips out all the data chunks and creates an imgstore for + * each one. In order to do this, it first goes through the IM and takes + * out all the IMG tags. When doing so, it rewrites the original IMG tag + * with one compatable with the imgstore Gaim core code. For each one, we + * then read in chunks of data from the end of the message and actually + * create the img store using the given data. + * + * For somewhat easy reference, here's a sample message + * (without the whitespace and asterisks): + * + * + * + * This is a really stupid picture:
+ *
+ * Yeah it is
+ * Here is another one:
+ * + *
+ * + * + * datadatadatadata + * datadatadatadata + * + */ static int gaim_odc_incoming(aim_session_t *sess, aim_frame_t *fr, ...) { GaimConnection *gc = sess->aux_data; GaimImFlags imflags = 0; + GString *newmsg = g_string_new(""); + GSList *images = NULL; va_list ap; - char *sn, *msg; - int len, encoding, isawaymsg; + const char *sn, *msg, *msgend, *binary; + size_t len; + int encoding, isawaymsg; va_start(ap, fr); - sn = va_arg(ap, char *); - msg = va_arg(ap, char *); - len = va_arg(ap, int); + sn = va_arg(ap, const char *); + msg = va_arg(ap, const char *); + len = va_arg(ap, size_t); encoding = va_arg(ap, int); isawaymsg = va_arg(ap, int); va_end(ap); + msgend = msg + len; gaim_debug(GAIM_DEBUG_INFO, "oscar", "Got DirectIM message from %s\n", sn); @@ -5687,8 +5727,91 @@ if (isawaymsg) imflags |= GAIM_IM_AUTO_RESP; + /* message has a binary trailer */ + if ((binary = gaim_strcasestr(msg, ""))) { + GData *attribs; + const char *tmp, *start, *end, *last = NULL; + + tmp = msg; + + /* for each valid image tag... */ + while (gaim_markup_find_tag("img", tmp, &start, &end, &attribs)) { + const char *id, *src, *datasize; + const char *tag = NULL, *data = NULL; + size_t size; + int imgid = 0; + + /* update the location of the last img tag */ + last = end; + + /* grab attributes */ + id = g_datalist_get_data(&attribs, "id"); + src = g_datalist_get_data(&attribs, "src"); + datasize = g_datalist_get_data(&attribs, "datasize"); + + /* if we have id & datasize, build the data tag */ + if (id && datasize) + tag = g_strdup_printf("", id, datasize); + + /* if we have a tag, find the start of the data */ + if (tag && (data = gaim_strcasestr(binary, tag))) + data += strlen(tag); + + /* check the data is here and store it */ + if (data + (size = atoi(datasize)) <= msgend) + imgid = gaim_imgstore_add(data, size, src); + + /* if we have a stored image... */ + if (imgid) { + /* append the message up to the tag */ + newmsg = g_string_append_len(newmsg, tmp, start - tmp); + + /* write the new image tag */ + g_string_append_printf(newmsg, "", imgid); + + /* and record the image number */ + images = g_slist_append(images, GINT_TO_POINTER(imgid)); + } else { + /* otherwise, copy up to the end of the tag */ + newmsg = g_string_append_len(newmsg, tmp, (end + 1) - tmp); + } + + /* clear the attribute list */ + g_datalist_clear(&attribs); + + /* continue from the end of the tag */ + tmp = end + 1; + } + + /* append any remaining message data (without the > :-) */ + if (last++ && (last < binary)) + newmsg = g_string_append_len(newmsg, last, binary - last); + + /* set the flag if we caught any images */ + if (images) + imflags |= GAIM_IM_IMAGES; + } else { + g_string_append_len(newmsg, msg, len); + } + /* XXX - I imagine Paco-Paco will want to do some voodoo with the encoding here */ - serv_got_im(gc, sn, msg, imflags, time(NULL), len); + serv_got_im(gc, sn, newmsg->str, imflags, time(NULL)); + + /* free up the message */ + g_string_free(newmsg, TRUE); + + /* unref any images we allocated */ + if (images) { + GSList *tmp; + int id; + + for (tmp = images; tmp != NULL; tmp = tmp->next) { + id = GPOINTER_TO_INT(tmp->data); + gaim_imgstore_unref(id); + } + + g_slist_free(images); + } return 1; } @@ -5716,6 +5839,91 @@ return 1; } +static int gaim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *message, GaimImFlags imflags) { + char *buf; + size_t len; + int ret; + + if (imflags & GAIM_IM_IMAGES) { + GString *msg = g_string_new(""); + GString *data = g_string_new(""); + GData *attribs; + const char *tmp, *start, *end, *last = NULL; + int oscar_id = 0; + + tmp = message; + + /* for each valid IMG tag... */ + while (gaim_markup_find_tag("img", tmp, &start, &end, &attribs)) { + GaimStoredImage *image = NULL; + const char *id; + + last = end; + id = g_datalist_get_data(&attribs, "id"); + + /* ... if it refers to a valid gaim image ... */ + if (id && (image = gaim_imgstore_get(atoi(id)))) { + /* ... append the message from start to the tag ... */ + msg = g_string_append_len(msg, tmp, start - tmp); + oscar_id++; + + /* ... insert a new img tag with the oscar id ... */ + if (image->filename) + g_string_append_printf(msg, + "", + image->filename, oscar_id, image->size); + else + g_string_append_printf(msg, + "", + oscar_id, image->size); + + /* ... and append the data to the binary section ... */ + g_string_append_printf(data, "", + oscar_id, image->size); + data = g_string_append_len(data, image->data, image->size); + data = g_string_append(data, ""); + } else { + /* ... otherwise, allow the possibly invalid img tag through. */ + /* should we do something else? */ + msg = g_string_append_len(msg, tmp, (end + 1) - tmp); + } + + g_datalist_clear(&attribs); + + /* continue from the end of the tag */ + tmp = end + 1; + } + + /* append any remaining message data (without the > :-) */ + if (last++ && *last) + msg = g_string_append(msg, last); + + /* if we inserted any images in the binary section, append it */ + if (oscar_id) { + msg = g_string_append_len(msg, data->str, data->len); + msg = g_string_append(msg, ""); + } + + len = msg->len; + buf = msg->str; + g_string_free(msg, FALSE); + g_string_free(data, TRUE); + } else { + len = strlen(message); + buf = g_memdup(message, len+1); + } + + /* XXX - The last parameter below is the encoding. Let Paco-Paco do something with it. */ + if (imflags & GAIM_IM_AUTO_RESP) + ret = aim_odc_send_im(sess, conn, buf, len, 0, 1); + else + ret = aim_odc_send_im(sess, conn, buf, len, 0, 0); + + g_free(buf); + + return ret; +} + struct ask_do_dir_im { char *who; GaimConnection *gc; diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/toc/toc.c --- a/src/protocols/toc/toc.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/toc/toc.c Sat Sep 27 19:17:21 2003 +0000 @@ -740,7 +740,7 @@ a = (away && (*away == 'T')) ? GAIM_IM_AUTO_RESP : 0; - serv_got_im(gc, c, message, a, time(NULL), -1); + serv_got_im(gc, c, message, a, time(NULL)); } else if (!g_ascii_strcasecmp(c, "UPDATE_BUDDY")) { char *l, *uc, *tmp; int logged, evil, idle, type = 0; @@ -1059,7 +1059,7 @@ } } -static int toc_send_im(GaimConnection *gc, const char *name, const char *message, int len, GaimImFlags flags) +static int toc_send_im(GaimConnection *gc, const char *name, const char *message, GaimImFlags flags) { char *buf1, *buf2; @@ -1089,7 +1089,7 @@ * that length is passed to sflap_send(). */ - if (len + 52 > MSG_LEN) { + if (strlen(buf1) + 52 > MSG_LEN) { g_free(buf1); return -E2BIG; } diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/trepia/trepia.c --- a/src/protocols/trepia/trepia.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/trepia/trepia.c Sat Sep 27 19:17:21 2003 +0000 @@ -728,7 +728,7 @@ serv_got_im(session->gc, trepia_profile_get_login(profile), (char *)g_hash_table_lookup(info, "b"), - 0, time(NULL), -1); + 0, time(NULL)); break; case TREPIA_MEMBER_UPDATE: @@ -1174,7 +1174,7 @@ static int trepia_send_im(GaimConnection *gc, const char *who, const char *message, - int len, GaimImFlags flags) + GaimImFlags flags) { TrepiaSession *session = gc->proto_data; TrepiaProfile *profile; diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/yahoo/yahoo.c --- a/src/protocols/yahoo/yahoo.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/yahoo/yahoo.c Sat Sep 27 19:17:21 2003 +0000 @@ -682,7 +682,7 @@ strip_linefeed(msg); m = yahoo_codes_to_html(msg); - serv_got_im(gc, from, m, 0, tm, -1); + serv_got_im(gc, from, m, 0, tm); g_free(m); tm = time(NULL); @@ -1645,7 +1645,7 @@ return m; } -static int yahoo_send_im(GaimConnection *gc, const char *who, const char *what, int len, GaimImFlags flags) +static int yahoo_send_im(GaimConnection *gc, const char *who, const char *what, GaimImFlags flags) { struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, 0); diff -r abd3c684da31 -r 083d1e4a9c78 src/protocols/zephyr/zephyr.c --- a/src/protocols/zephyr/zephyr.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/protocols/zephyr/zephyr.c Sat Sep 27 19:17:21 2003 +0000 @@ -369,7 +369,7 @@ !g_ascii_strcasecmp(notice.z_class_inst, "PERSONAL")) { if (!g_ascii_strcasecmp(notice.z_message, "Automated reply:")) flags |= GAIM_IM_AUTO_RESP; - serv_got_im(zgc, notice.z_sender, buf2, flags, time(NULL), -1); + serv_got_im(zgc, notice.z_sender, buf2, flags, time(NULL)); } else { zephyr_triple *zt1, *zt2; zt1 = new_triple(notice.z_class, notice.z_class_inst, @@ -789,7 +789,7 @@ return 0; } -static int zephyr_send_im(GaimConnection *gc, const char *who, const char *im, int len, GaimImFlags flags) { +static int zephyr_send_im(GaimConnection *gc, const char *who, const char *im, GaimImFlags flags) { ZNotice_t notice; char *buf; const char *sig; diff -r abd3c684da31 -r 083d1e4a9c78 src/prpl.h --- a/src/prpl.h Sat Sep 27 15:45:49 2003 +0000 +++ b/src/prpl.h Sat Sep 27 19:17:21 2003 +0000 @@ -92,7 +92,8 @@ */ typedef enum { - GAIM_IM_AUTO_RESP = 0x01 /**< Auto response. */ + GAIM_IM_AUTO_RESP = 0x0001, /**< Auto response. */ + GAIM_IM_IMAGES = 0x0002 /**< Contains images. */ } GaimImFlags; /** @@ -241,7 +242,7 @@ void (*login)(GaimAccount *); void (*close)(GaimConnection *); int (*send_im)(GaimConnection *, const char *who, - const char *message, int len, + const char *message, GaimImFlags flags); void (*set_info)(GaimConnection *, const char *info); int (*send_typing)(GaimConnection *, const char *name, int typing); diff -r abd3c684da31 -r 083d1e4a9c78 src/server.c --- a/src/server.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/server.c Sat Sep 27 19:17:21 2003 +0000 @@ -258,7 +258,7 @@ } int serv_send_im(GaimConnection *gc, const char *name, const char *message, - int len, GaimImFlags imflags) + GaimImFlags imflags) { GaimConversation *c; int val = -EINVAL; @@ -270,7 +270,7 @@ c = gaim_find_conversation_with_account(name, gc->account); if (prpl_info && prpl_info->send_im) - val = prpl_info->send_im(gc, name, message, len, imflags); + val = prpl_info->send_im(gc, name, message, imflags); if (!(imflags & GAIM_IM_AUTO_RESP)) serv_touch_idle(gc); @@ -835,10 +835,10 @@ * sure to follow along, kids */ void serv_got_im(GaimConnection *gc, const char *who, const char *msg, - GaimImFlags imflags, time_t mtime, gint len) + GaimImFlags imflags, time_t mtime) { GaimConversation *cnv; - GaimMessageFlags auto_resp; + GaimMessageFlags msgflags; char *message, *name; char *angel, *buffy; int plugin_return; @@ -852,41 +852,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. 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. + * those instead. It's basically just to avoid segfaults. */ - if (len < 0) { - buffy = g_malloc(MAX(strlen(msg) + 1, BUF_LONG)); - strcpy(buffy, msg); - angel = g_strdup(who); - - plugin_return = GPOINTER_TO_INT( - gaim_signal_emit_return_1(gaim_conversations_get_handle(), - "received-im-msg", gc->account, - &angel, &buffy, &imflags)); + buffy = g_malloc(MAX(strlen(msg) + 1, BUF_LONG)); + strcpy(buffy, msg); + angel = g_strdup(who); - if (!buffy || !angel || plugin_return) { - if (buffy) - g_free(buffy); - if (angel) - g_free(angel); - return; - } - name = angel; - message = buffy; - } else { - name = g_strdup(who); - message = g_memdup(msg, len); + plugin_return = GPOINTER_TO_INT( + gaim_signal_emit_return_1(gaim_conversations_get_handle(), + "received-im-msg", gc->account, + &angel, &buffy, &imflags)); + + if (!buffy || !angel || plugin_return) { + if (buffy) + g_free(buffy); + if (angel) + g_free(angel); + return; } + name = angel; + message = buffy; /* * If you can't figure this out, stop reading right now. * "We're not worthy! We're not worthy!" */ - if (len < 0 && - gaim_prefs_get_bool("/gaim/gtk/conversations/show_urls_as_links")) { - + if (gaim_prefs_get_bool("/gaim/gtk/conversations/show_urls_as_links")) { buffy = linkify_text(message); g_free(message); message = buffy; @@ -896,12 +887,15 @@ * Um. When we call gaim_conversation_write with the message we received, * it's nice to pass whether or not it was an auto-response. So if it * was an auto-response, we set the appropriate flag. This is just so - * prpls don't have to know about GAIM_MESSAGE_* (though some do anyway) + * prpls don't have to know about GAIM_MESSAGE_* (though some do anyway). + * We also need to preserve the flag that tells the UI to look for the + * associated images. */ + msgflags = GAIM_MESSAGE_RECV; if (imflags & GAIM_IM_AUTO_RESP) - auto_resp = GAIM_MESSAGE_AUTO_RESP; - else - auto_resp = 0; + msgflags |= GAIM_MESSAGE_AUTO_RESP; + if (imflags & GAIM_IM_IMAGES) + msgflags |= GAIM_MESSAGE_IMAGES; /* * Alright. Two cases for how to handle this. Either we're away or @@ -940,11 +934,10 @@ qm = g_new0(struct queued_message, 1); g_snprintf(qm->name, sizeof(qm->name), "%s", name); - qm->message = g_memdup(message, len == -1 ? strlen(message) + 1 : len); + qm->message = g_strdup(message); qm->account = gc->account; qm->tm = mtime; - qm->flags = GAIM_MESSAGE_RECV | auto_resp; - qm->len = len; + qm->flags = msgflags; message_queue = g_slist_append(message_queue, qm); row = find_queue_row_by_name(qm->name); @@ -979,8 +972,7 @@ if (cnv == NULL) cnv = gaim_conversation_new(GAIM_CONV_IM, gc->account, name); - gaim_im_write(GAIM_IM(cnv), NULL, message, len, - GAIM_MESSAGE_RECV | auto_resp, mtime); + gaim_im_write(GAIM_IM(cnv), NULL, message, msgflags, mtime); } /* @@ -1026,7 +1018,7 @@ /* apply default fonts and colors */ tmpmsg = stylize(gc->away, MSG_LEN); - serv_send_im(gc, name, away_subs(tmpmsg, alias), -1, GAIM_IM_AUTO_RESP); + serv_send_im(gc, name, away_subs(tmpmsg, alias), GAIM_IM_AUTO_RESP); if (!cnv && awayqueue && gaim_prefs_get_bool("/gaim/gtk/away/queue_messages")) { @@ -1038,11 +1030,10 @@ qm->account = gc->account; qm->tm = mtime; qm->flags = GAIM_MESSAGE_SEND | GAIM_MESSAGE_AUTO_RESP; - qm->len = -1; message_queue = g_slist_append(message_queue, qm); } else if (cnv != NULL) gaim_im_write(GAIM_IM(cnv), NULL, away_subs(tmpmsg, alias), - len, GAIM_MESSAGE_SEND | GAIM_MESSAGE_AUTO_RESP, mtime); + GAIM_MESSAGE_SEND | GAIM_MESSAGE_AUTO_RESP, mtime); g_free(tmpmsg); } else { @@ -1070,16 +1061,14 @@ qm->message = g_strdup(message); qm->account = gc->account; qm->tm = mtime; - qm->flags = GAIM_MESSAGE_RECV | auto_resp; - qm->len = len; + qm->flags = msgflags; unread_message_queue = g_slist_append(unread_message_queue, qm); } else { if (cnv == NULL) cnv = gaim_conversation_new(GAIM_CONV_IM, gc->account, name); - gaim_im_write(GAIM_IM(cnv), NULL, message, len, - GAIM_MESSAGE_RECV | auto_resp, mtime); + gaim_im_write(GAIM_IM(cnv), NULL, message, msgflags, mtime); gaim_window_flash(gaim_conversation_get_window(cnv)); } } @@ -1156,7 +1145,7 @@ char *tmp = g_strdup_printf(_("%s logged in."), gaim_get_buddy_alias(b)); - gaim_conversation_write(c, NULL, tmp, -1, GAIM_MESSAGE_SYSTEM, + gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } @@ -1168,7 +1157,6 @@ qm->account = gc->account; qm->tm = time(NULL); qm->flags = GAIM_MESSAGE_SYSTEM; - qm->len = -1; message_queue = g_slist_append(message_queue, qm); } } @@ -1183,7 +1171,7 @@ char *tmp = g_strdup_printf(_("%s logged out."), gaim_get_buddy_alias(b)); - gaim_conversation_write(c, NULL, tmp, -1, + gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } else if (awayqueue && find_queue_total_by_name(b->name)) { @@ -1194,7 +1182,6 @@ qm->account = gc->account; qm->tm = time(NULL); qm->flags = GAIM_MESSAGE_SYSTEM; - qm->len = -1; message_queue = g_slist_append(message_queue, qm); } } @@ -1576,6 +1563,6 @@ gtk_widget_show_all(window); - gtk_imhtml_append_text(GTK_IMHTML(text), msg, -1, GTK_IMHTML_NO_NEWLINE); + gtk_imhtml_append_text(GTK_IMHTML(text), msg, GTK_IMHTML_NO_NEWLINE); } diff -r abd3c684da31 -r 083d1e4a9c78 src/server.h --- a/src/server.h Sat Sep 27 15:45:49 2003 +0000 +++ b/src/server.h Sat Sep 27 19:17:21 2003 +0000 @@ -39,7 +39,7 @@ void serv_login(GaimAccount *); void serv_close(GaimConnection *); void serv_touch_idle(GaimConnection *); -int serv_send_im(GaimConnection *, const char *, const char *, int, GaimImFlags); +int serv_send_im(GaimConnection *, const char *, const char *, GaimImFlags); void serv_get_info(GaimConnection *, const char *); void serv_get_dir(GaimConnection *, const char *); void serv_set_idle(GaimConnection *, int); @@ -82,7 +82,7 @@ void serv_set_buddyicon(GaimConnection *gc, const char *filename); void serv_got_typing_stopped(GaimConnection *gc, const char *name); void serv_got_im(GaimConnection *gc, const char *who, const char *msg, - GaimImFlags imflags, time_t mtime, gint len); + GaimImFlags imflags, time_t mtime); void serv_got_update(GaimConnection *gc, const char *name, int loggedin, int evil, time_t signon, time_t idle, int type); void serv_finish_login(GaimConnection *gc); diff -r abd3c684da31 -r 083d1e4a9c78 src/ui.h --- a/src/ui.h Sat Sep 27 15:45:49 2003 +0000 +++ b/src/ui.h Sat Sep 27 19:17:21 2003 +0000 @@ -84,7 +84,6 @@ time_t tm; GaimAccount *account; GaimMessageFlags flags; - int len; }; struct smiley_theme { diff -r abd3c684da31 -r 083d1e4a9c78 src/util.c --- a/src/util.c Sat Sep 27 15:45:49 2003 +0000 +++ b/src/util.c Sat Sep 27 19:17:21 2003 +0000 @@ -940,6 +940,31 @@ return ret; } +const char *gaim_strcasestr(const char *haystack, const char *needle) { + size_t hlen, nlen; + const char *tmp, *ret; + + g_return_val_if_fail(haystack != NULL, NULL); + g_return_val_if_fail(needle != NULL, NULL); + + hlen = strlen(haystack); + nlen = strlen(needle); + tmp = haystack, + ret = NULL; + + g_return_val_if_fail(hlen > 0, NULL); + g_return_val_if_fail(nlen > 0, NULL); + + while (*tmp && !ret) { + if (!g_ascii_strncasecmp(needle, tmp, nlen)) + ret = tmp; + else + tmp++; + } + + return ret; +} + char *gaim_get_size_string(size_t size) { static const char *size_str[4] = { "bytes", "KB", "MB", "GB" }; @@ -963,3 +988,138 @@ return g_strdup_printf("%.2f %s", size_mag, size_str[size_index]); } } + +gboolean gaim_markup_find_tag(const char *needle, const char *haystack, const char **start, const char **end, GData **attributes) { + GData *attribs; + const char *cur = haystack; + char *name = NULL; + gboolean found = FALSE; + gboolean in_tag = FALSE; + gboolean in_attr = FALSE; + gboolean in_quotes = FALSE; + size_t needlelen = strlen(needle); + + g_datalist_init(&attribs); + + while (*cur && !found) { + if (in_tag) { + if (in_quotes) { + const char *close = cur; + + while (*close && *close != '"') + close++; + + /* if we got the close quote, store the value and carry on from * + * after it. if we ran to the end of the string, point to the NULL * + * and we're outta here */ + if (*close) { + /* only store a value if we have an attribute name */ + if (name) { + size_t len = close - cur; + char *val = g_strndup(cur, len); + + g_datalist_set_data_full(&attribs, name, val, g_free); + g_free(name); + name = NULL; + } + + in_quotes = FALSE; + cur = close + 1; + } else { + cur = close; + } + } else if (in_attr) { + const char *close = cur; + + while (*close && *close != '>' && *close != '"' && *close != ' ' && *close != '=') + close++; + + /* if we got the equals, store the name of the attribute. if we got + * the quote, save the attribute and go straight to quote mode. + * otherwise the tag closed or we reached the end of the string, + * so we can get outta here */ + switch (*close) { + case '"': + in_quotes = TRUE; + case '=': + { + size_t len = close - cur; + + /* don't store a blank attribute name */ + if (len) { + if (name) + g_free(name); + name = g_ascii_strdown(cur, len); + } + + in_attr = FALSE; + cur = close + 1; + break; + } + case ' ': + case '>': + in_attr = FALSE; + default: + cur = close; + break; + } + } else { + switch (*cur) { + case ' ': + /* swallow extra spaces inside tag */ + while (*cur && *cur == ' ') cur++; + in_attr = TRUE; + break; + case '>': + found = TRUE; + *end = cur; + break; + case '"': + in_quotes = TRUE; + default: + cur++; + break; + } + } + } else { + /* if we hit a < followed by the name of our tag... */ + if (*cur == '<' && !g_ascii_strncasecmp(cur + 1, needle, needlelen)) { + *start = cur; + cur = cur + needlelen + 1; + + /* if we're pointing at a space or a >, we found the right tag. if * + * we're not, we've found a longer tag, so we need to skip to the * + * >, but not being distracted by >s inside quotes. */ + if (*cur == ' ' || *cur == '>') { + in_tag = TRUE; + } else { + while (*cur && *cur != '"' && *cur != '>') { + if (*cur == '"') { + cur++; + while (*cur && *cur != '"') + cur++; + } else { + cur++; + } + } + } + } else { + cur++; + } + } + } + + /* clean up any attribute name from a premature termination */ + if (name) + g_free(name); + + if (found) { + *attributes = attribs; + } else { + *start = NULL; + *end = NULL; + *attributes = NULL; + } + + return found; +} diff -r abd3c684da31 -r 083d1e4a9c78 src/util.h --- a/src/util.h Sat Sep 27 15:45:49 2003 +0000 +++ b/src/util.h Sat Sep 27 19:17:21 2003 +0000 @@ -314,6 +314,16 @@ const gchar *replacement); /** + * This is like strstr, except that it ignores ASCII case in + * searching for the substring. + * + * @param haystack The string to search in. + * @param needle The substring to find. + * @return the location of the substring if found, or NULL if not + */ +const char *gaim_strcasestr(const char *haystack, const char *needle); + +/** * Returns a string representing a filesize in the appropriate * units (MB, KB, GB, etc.) * @@ -321,6 +331,21 @@ */ char *gaim_get_size_string(size_t size); +/** + * Finds a HTML tag matching the given name, locating its start + * and end, and storing its attributes in a GData hash table. + * The names of the attributes are lower-cased in the hash table, + * and the name of the tag is case insensitive. + * + * @param needle the name of the tag + * @param haystack the null-delimited string to search in + * @param start a pointer to the start of the tag if found + * @param end a pointer to the end of the tag if found + * @param attributes the attributes, if the tag was found + * @return TRUE if the tag was found + */ +gboolean gaim_markup_find_tag(const char *needle, const char *haystack, const char **start, const char **end, GData **attributes); + #ifdef __cplusplus } #endif