comparison src/gtkconv.c @ 6982:083d1e4a9c78

[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 <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sat, 27 Sep 2003 19:17:21 +0000
parents 1b5b0cea6915
children ecce6b23ea25
comparison
equal deleted inserted replaced
6981:abd3c684da31 6982:083d1e4a9c78
28 #ifdef USE_GTKSPELL 28 #ifdef USE_GTKSPELL
29 # include <gtkspell/gtkspell.h> 29 # include <gtkspell/gtkspell.h>
30 #endif 30 #endif
31 31
32 #include <gdk/gdkkeysyms.h> 32 #include <gdk/gdkkeysyms.h>
33 #include <locale.h>
33 34
34 #include "debug.h" 35 #include "debug.h"
35 #include "html.h" 36 #include "html.h"
37 #include "imgstore.h"
36 #include "log.h" 38 #include "log.h"
37 #include "multi.h" 39 #include "multi.h"
38 #include "notify.h" 40 #include "notify.h"
39 #include "prefs.h" 41 #include "prefs.h"
40 #include "prpl.h" 42 #include "prpl.h"
193 do_insert_image_cb(GObject *obj, GtkWidget *wid) 195 do_insert_image_cb(GObject *obj, GtkWidget *wid)
194 { 196 {
195 GaimConversation *conv; 197 GaimConversation *conv;
196 GaimGtkConversation *gtkconv; 198 GaimGtkConversation *gtkconv;
197 GaimIm *im; 199 GaimIm *im;
198 const char *name; 200 char *name, *filename;
199 const char *filename; 201 char *buf, *data;
200 char *buf; 202 size_t size;
201 struct stat st; 203 GError *error;
202 int id; 204 int id;
203 205
204 conv = g_object_get_data(G_OBJECT(wid), "user_data"); 206 conv = g_object_get_data(G_OBJECT(wid), "user_data");
205 gtkconv = GAIM_GTK_CONVERSATION(conv); 207 gtkconv = GAIM_GTK_CONVERSATION(conv);
206 im = GAIM_IM(conv); 208 im = GAIM_IM(conv);
207 name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(wid)); 209 name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(wid)));
208 id = g_slist_length(im->images) + 1; 210
209 211 if (!name) {
210 if (gaim_gtk_check_if_dir(name, GTK_FILE_SELECTION(wid))) 212 gtk_widget_destroy(gtkconv->dialogs.image);
213 gtkconv->dialogs.image = NULL;
211 return; 214 return;
212 215 }
213 gtk_widget_destroy(wid); 216
214 217 if (gaim_gtk_check_if_dir(name, GTK_FILE_SELECTION(wid))) {
215 if (!name) 218 g_free(name);
216 return; 219 return;
217 220 }
218 if (stat(name, &st) != 0) { 221
219 gaim_debug(GAIM_DEBUG_ERROR, "gtkconv", 222 gtk_widget_destroy(gtkconv->dialogs.image);
220 "Could not stat image %s\n", name); 223 gtkconv->dialogs.image = NULL;
224
225 if (!g_file_get_contents(name, &data, &size, &error)) {
226 gaim_notify_error(NULL, NULL, error->message, NULL);
227
228 g_error_free(error);
229 g_free(name);
230
221 return; 231 return;
222 } 232 }
223 233
224 filename = name; 234 filename = name;
225 while (strchr(filename, '/')) 235 while (strchr(filename, '/'))
226 filename = strchr(filename, '/') + 1; 236 filename = strchr(filename, '/') + 1;
227 237
228 buf = g_strdup_printf("<IMG SRC=\"file://%s\" ID=\"%d\" DATASIZE=\"%d\">", 238 id = gaim_imgstore_add(data, size, filename);
229 filename, id, (int)st.st_size); 239 g_free(data);
230 im->images = g_slist_append(im->images, g_strdup(name)); 240
231 gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(gtkconv->entry_buffer), 241 if (!id) {
232 buf, -1); 242 buf = g_strdup_printf(_("Failed to store image: %s\n"), name);
243 gaim_notify_error(NULL, NULL, buf, NULL);
244
245 g_free(buf);
246 g_free(name);
247
248 return;
249 }
250
251 im->images = g_slist_append(im->images, GINT_TO_POINTER(id));
252
253 buf = g_strdup_printf("<IMG ID=\"%d\" SRC=\"file://%s\">", id, filename);
254 gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(gtkconv->entry_buffer), buf, -1);
233 g_free(buf); 255 g_free(buf);
256
257 g_free(name);
234 258
235 set_toggle(gtkconv->toolbar.image, FALSE); 259 set_toggle(gtkconv->toolbar.image, FALSE);
236 } 260 }
237 261
238 static gint 262 static gint
2698 addthis = g_strconcat(tmp, matches->data, " ", NULL); 2722 addthis = g_strconcat(tmp, matches->data, " ", NULL);
2699 g_free(tmp); 2723 g_free(tmp);
2700 matches = g_list_remove(matches, matches->data); 2724 matches = g_list_remove(matches, matches->data);
2701 } 2725 }
2702 2726
2703 gaim_conversation_write(conv, NULL, addthis, -1, GAIM_MESSAGE_NO_LOG, 2727 gaim_conversation_write(conv, NULL, addthis, GAIM_MESSAGE_NO_LOG,
2704 time(NULL)); 2728 time(NULL));
2705 gtk_text_buffer_insert_at_cursor(gtkconv->entry_buffer, partial, -1); 2729 gtk_text_buffer_insert_at_cursor(gtkconv->entry_buffer, partial, -1);
2706 g_free(addthis); 2730 g_free(addthis);
2707 } 2731 }
2708 2732
4218 g_free(gtkconv); 4242 g_free(gtkconv);
4219 } 4243 }
4220 4244
4221 static void 4245 static void
4222 gaim_gtkconv_write_im(GaimConversation *conv, const char *who, 4246 gaim_gtkconv_write_im(GaimConversation *conv, const char *who,
4223 const char *message, size_t len, GaimMessageFlags flags, 4247 const char *message, GaimMessageFlags flags,
4224 time_t mtime) 4248 time_t mtime)
4225 { 4249 {
4226 GaimGtkConversation *gtkconv; 4250 GaimGtkConversation *gtkconv;
4227 4251
4228 gtkconv = GAIM_GTK_CONVERSATION(conv); 4252 gtkconv = GAIM_GTK_CONVERSATION(conv);
4249 } 4273 }
4250 } 4274 }
4251 4275
4252 gtkconv->u.im->a_virgin = FALSE; 4276 gtkconv->u.im->a_virgin = FALSE;
4253 4277
4254 gaim_conversation_write(conv, who, message, len, flags, mtime); 4278 gaim_conversation_write(conv, who, message, flags, mtime);
4255 } 4279 }
4256 4280
4257 static void 4281 static void
4258 gaim_gtkconv_write_chat(GaimConversation *conv, const char *who, 4282 gaim_gtkconv_write_chat(GaimConversation *conv, const char *who,
4259 const char *message, GaimMessageFlags flags, time_t mtime) 4283 const char *message, GaimMessageFlags flags, time_t mtime)
4285 gaim_prefs_get_bool("/gaim/gtk/conversations/chat/raise_on_events")) { 4309 gaim_prefs_get_bool("/gaim/gtk/conversations/chat/raise_on_events")) {
4286 4310
4287 gaim_window_raise(gaim_conversation_get_window(conv)); 4311 gaim_window_raise(gaim_conversation_get_window(conv));
4288 } 4312 }
4289 4313
4290 gaim_conversation_write(conv, who, message, -1, flags, mtime); 4314 gaim_conversation_write(conv, who, message, flags, mtime);
4291 } 4315 }
4292 4316
4293 static void 4317 static void
4294 gaim_gtkconv_write_conv(GaimConversation *conv, const char *who, 4318 gaim_gtkconv_write_conv(GaimConversation *conv, const char *who,
4295 const char *message, size_t length, GaimMessageFlags flags, 4319 const char *message, GaimMessageFlags flags,
4296 time_t mtime) 4320 time_t mtime)
4297 { 4321 {
4298 GaimGtkConversation *gtkconv; 4322 GaimGtkConversation *gtkconv;
4299 GaimWindow *win; 4323 GaimWindow *win;
4300 GaimConnection *gc; 4324 GaimConnection *gc;
4301 int gtk_font_options = 0; 4325 int gtk_font_options = 0;
4302 GString *log_str; 4326 GString *log_str;
4327 GSList *images = NULL;
4303 FILE *fd; 4328 FILE *fd;
4304 char buf[BUF_LONG]; 4329 char buf[BUF_LONG];
4305 char buf2[BUF_LONG]; 4330 char buf2[BUF_LONG];
4306 char mdate[64]; 4331 char mdate[64];
4307 char color[10]; 4332 char color[10];
4308 char *str; 4333 char *str;
4309 char *with_font_tag; 4334 char *with_font_tag;
4310 char *sml_attrib = NULL; 4335 char *sml_attrib = NULL;
4311 4336 size_t length = strlen(message) + 1;
4312 if(length == -1)
4313 length = strlen(message) + 1;
4314 4337
4315 gtkconv = GAIM_GTK_CONVERSATION(conv); 4338 gtkconv = GAIM_GTK_CONVERSATION(conv);
4316 gc = gaim_conversation_get_gc(conv); 4339 gc = gaim_conversation_get_gc(conv);
4317 4340
4318 win = gaim_conversation_get_window(conv); 4341 win = gaim_conversation_get_window(conv);
4325 gaim_prefs_get_bool("/gaim/gtk/conversations/im/hide_on_send"))))) { 4348 gaim_prefs_get_bool("/gaim/gtk/conversations/im/hide_on_send"))))) {
4326 4349
4327 gaim_window_show(win); 4350 gaim_window_show(win);
4328 } 4351 }
4329 4352
4353 if (flags & GAIM_MESSAGE_IMAGES) {
4354 GData *attribs;
4355 GdkPixbuf *broken;
4356 const char *tmp, *start, *end;
4357
4358 broken = gtk_widget_render_icon(GTK_WIDGET(gtkconv->imhtml),
4359 GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON,
4360 "gaim-missing-image");
4361
4362 tmp = message;
4363 while (gaim_markup_find_tag("img", tmp, &start, &end, &attribs)) {
4364 GaimStoredImage *image = NULL;
4365 GdkPixbufLoader *loader;
4366 GError *error = NULL;
4367 char *id = NULL;
4368
4369 tmp = end + 1;
4370
4371 id = g_datalist_get_data(&attribs, "id");
4372
4373 if (id)
4374 image = gaim_imgstore_get(atoi(id));
4375
4376 g_datalist_clear(&attribs);
4377
4378 if (!image) {
4379 g_object_ref(G_OBJECT(broken));
4380 images = g_slist_append(images, broken);
4381 continue;
4382 }
4383
4384 loader = gdk_pixbuf_loader_new();
4385
4386 if (!gdk_pixbuf_loader_write(loader, image->data, image->size, &error)) {
4387 if (error) {
4388 gaim_debug(GAIM_DEBUG_ERROR, "gtkconv",
4389 "Failed to make pixbuf for IM Image: %s\n",
4390 error->message);
4391 g_error_free(error);
4392 }
4393 g_object_ref(G_OBJECT(broken));
4394 images = g_slist_append(images, broken);
4395 } else {
4396 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
4397 if (pixbuf) {
4398 if (image->filename)
4399 g_object_set_data_full(G_OBJECT(pixbuf), "filename",
4400 g_strdup(image->filename), g_free);
4401 g_object_ref(G_OBJECT(pixbuf));
4402 images = g_slist_append(images, pixbuf);
4403 } else {
4404 g_object_ref(G_OBJECT(broken));
4405 images = g_slist_append(images, broken);
4406 }
4407 }
4408
4409 gdk_pixbuf_loader_close(loader, NULL);
4410 }
4411
4412 g_object_unref(G_OBJECT(broken));
4413 }
4330 4414
4331 if(time(NULL) > mtime + 20*60) /* show date if older than 20 minutes */ 4415 if(time(NULL) > mtime + 20*60) /* show date if older than 20 minutes */
4332 strftime(mdate, sizeof(mdate), "%Y-%m-%d %H:%M:%S", localtime(&mtime)); 4416 strftime(mdate, sizeof(mdate), "%Y-%m-%d %H:%M:%S", localtime(&mtime));
4333 else 4417 else
4334 strftime(mdate, sizeof(mdate), "%H:%M:%S", localtime(&mtime)); 4418 strftime(mdate, sizeof(mdate), "%H:%M:%S", localtime(&mtime));
4365 4449
4366 g_snprintf(buf2, sizeof(buf2), 4450 g_snprintf(buf2, sizeof(buf2),
4367 "<!--(%s) --><B>%s</B><BR>", 4451 "<!--(%s) --><B>%s</B><BR>",
4368 mdate, message); 4452 mdate, message);
4369 4453
4370 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, -1, 0); 4454 gtk_imhtml_append_text_with_images(GTK_IMHTML(gtkconv->imhtml), buf2, 0, images);
4371 4455
4372 if (gaim_prefs_get_bool("/gaim/gtk/logging/strip_html")) { 4456 if (gaim_prefs_get_bool("/gaim/gtk/logging/strip_html")) {
4373 char *t1 = strip_html(buf); 4457 char *t1 = strip_html(buf);
4374 4458
4375 conv->history = g_string_append(conv->history, t1); 4459 conv->history = g_string_append(conv->history, t1);
4417 else if (flags & GAIM_MESSAGE_NO_LOG) { 4501 else if (flags & GAIM_MESSAGE_NO_LOG) {
4418 g_snprintf(buf, BUF_LONG, 4502 g_snprintf(buf, BUF_LONG,
4419 "<B><FONT COLOR=\"#777777\">%s</FONT></B><BR>", 4503 "<B><FONT COLOR=\"#777777\">%s</FONT></B><BR>",
4420 message); 4504 message);
4421 4505
4422 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf, -1, 0); 4506 gtk_imhtml_append_text_with_images(GTK_IMHTML(gtkconv->imhtml), buf, 0, images);
4423 } 4507 }
4424 else { 4508 else {
4425 char *new_message = g_memdup(message, length); 4509 char *new_message = g_memdup(message, length);
4426 4510
4427 if (flags & GAIM_MESSAGE_WHISPER) { 4511 if (flags & GAIM_MESSAGE_WHISPER) {
4496 "<B>%s</B></FONT> ", 4580 "<B>%s</B></FONT> ",
4497 color, sml_attrib ? sml_attrib : "", mdate, str); 4581 color, sml_attrib ? sml_attrib : "", mdate, str);
4498 4582
4499 g_free(str); 4583 g_free(str);
4500 4584
4501 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, -1, 0); 4585 gtk_imhtml_append_text_with_images(GTK_IMHTML(gtkconv->imhtml), buf2, 0, images);
4502 4586
4503 if(gc){ 4587 if(gc){
4504 char *pre = g_strdup_printf("<font %s>", sml_attrib ? sml_attrib : ""); 4588 char *pre = g_strdup_printf("<font %s>", sml_attrib ? sml_attrib : "");
4505 char *post = "</font>"; 4589 char *post = "</font>";
4506 int pre_len = strlen(pre); 4590 int pre_len = strlen(pre);
4516 g_free(pre); 4600 g_free(pre);
4517 } 4601 }
4518 else 4602 else
4519 with_font_tag = g_memdup(new_message, length); 4603 with_font_tag = g_memdup(new_message, length);
4520 4604
4521 log_str = gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), 4605 log_str = gtk_imhtml_append_text_with_images(GTK_IMHTML(gtkconv->imhtml),
4522 with_font_tag, length, gtk_font_options); 4606 with_font_tag, gtk_font_options, images);
4523 4607
4524 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", -1, 0); 4608 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", 0);
4525 4609
4526 /* XXX This needs to be updated for the new length argument. */
4527 if (gaim_prefs_get_bool("/gaim/gtk/logging/strip_html")) { 4610 if (gaim_prefs_get_bool("/gaim/gtk/logging/strip_html")) {
4528 char *t1, *t2; 4611 char *t1, *t2;
4529 4612
4530 t1 = strip_html(buf); 4613 t1 = strip_html(buf);
4531 t2 = strip_html(new_message); 4614 t2 = strip_html(new_message);
4551 4634
4552 g_free(t1); 4635 g_free(t1);
4553 g_free(t2); 4636 g_free(t2);
4554 } 4637 }
4555 4638
4556 /* XXX This needs to be updated for the new length argument. */
4557 if (gaim_conversation_is_logging(conv)) { 4639 if (gaim_conversation_is_logging(conv)) {
4558 char *t1, *t2; 4640 char *t1, *t2;
4559 char nm[256]; 4641 char nm[256];
4560 4642
4561 if (gaim_conversation_get_type(conv) == GAIM_CONV_CHAT) 4643 if (gaim_conversation_get_type(conv) == GAIM_CONV_CHAT)
4595 g_free(new_message); 4677 g_free(new_message);
4596 } 4678 }
4597 4679
4598 if(sml_attrib) 4680 if(sml_attrib)
4599 g_free(sml_attrib); 4681 g_free(sml_attrib);
4682
4683 if (images) {
4684 GSList *tmp = images;
4685 GdkPixbuf *pixbuf;
4686 while (tmp) {
4687 pixbuf = tmp->data;
4688 g_object_unref(G_OBJECT(pixbuf));
4689 tmp = tmp->next;
4690 }
4691 g_slist_free(images);
4692 }
4600 } 4693 }
4601 4694
4602 static void 4695 static void
4603 gaim_gtkconv_chat_add_user(GaimConversation *conv, const char *user) 4696 gaim_gtkconv_chat_add_user(GaimConversation *conv, const char *user)
4604 { 4697 {