comparison src/gtkimhtml.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 4f8258b2bb8d
children 48cc5d5d5a6c
comparison
equal deleted inserted replaced
6981:abd3c684da31 6982:083d1e4a9c78
851 VALID_TAG ("/STRONG"); 851 VALID_TAG ("/STRONG");
852 852
853 VALID_OPT_TAG ("SPAN"); 853 VALID_OPT_TAG ("SPAN");
854 VALID_TAG ("/SPAN"); 854 VALID_TAG ("/SPAN");
855 VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */ 855 VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */
856 VALID_TAG ("IMG");
856 857
857 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { 858 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) {
858 gchar *e = strstr (string + strlen("!--"), "-->"); 859 gchar *e = strstr (string + strlen("!--"), "-->");
859 if (e) { 860 if (e) {
860 *len = e - string + strlen ("-->"); 861 *len = e - string + strlen ("-->");
993 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ 994 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \
994 } \ 995 } \
995 996
996 997
997 998
998 GString* gtk_imhtml_append_text (GtkIMHtml *imhtml, 999 GString* gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml,
999 const gchar *text, 1000 const gchar *text,
1000 gint len, 1001 GtkIMHtmlOptions options,
1001 GtkIMHtmlOptions options) 1002 GSList *images)
1002 { 1003 {
1003 gint pos = 0; 1004 gint pos = 0;
1004 GString *str = NULL; 1005 GString *str = NULL;
1005 GtkTextIter iter, siter; 1006 GtkTextIter iter, siter;
1006 GtkTextMark *mark, *mark2; 1007 GtkTextMark *mark, *mark2;
1007 GtkTextTag *texttag; 1008 GtkTextTag *texttag;
1008 gchar *ws; 1009 gchar *ws;
1009 gchar *tag; 1010 gchar *tag;
1010 gchar *url = NULL; 1011 gchar *url = NULL;
1011 gchar *bg = NULL; 1012 gchar *bg = NULL;
1013 gint len;
1012 gint tlen, smilelen, wpos=0; 1014 gint tlen, smilelen, wpos=0;
1013 gint type; 1015 gint type;
1014 const gchar *c; 1016 const gchar *c;
1015 gchar amp; 1017 gchar amp;
1016 1018
1031 GtkIMHtmlScalable *scalable = NULL; 1033 GtkIMHtmlScalable *scalable = NULL;
1032 1034
1033 g_return_val_if_fail (imhtml != NULL, NULL); 1035 g_return_val_if_fail (imhtml != NULL, NULL);
1034 g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL); 1036 g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL);
1035 g_return_val_if_fail (text != NULL, NULL); 1037 g_return_val_if_fail (text != NULL, NULL);
1036 g_return_val_if_fail (len != 0, NULL); 1038
1037
1038 c = text; 1039 c = text;
1039 if (len == -1) 1040 len = strlen(text);
1040 len = strlen(text);
1041 ws = g_malloc(len + 1); 1041 ws = g_malloc(len + 1);
1042 ws[0] = 0; 1042 ws[0] = 0;
1043 1043
1044 if (options & GTK_IMHTML_RETURN_LOG) 1044 if (options & GTK_IMHTML_RETURN_LOG)
1045 str = g_string_new(""); 1045 str = g_string_new("");
1152 case 25: /* BR */ 1152 case 25: /* BR */
1153 case 58: /* BR/ */ 1153 case 58: /* BR/ */
1154 ws[wpos] = '\n'; 1154 ws[wpos] = '\n';
1155 wpos++; 1155 wpos++;
1156 NEW_BIT (NEW_TEXT_BIT); 1156 NEW_BIT (NEW_TEXT_BIT);
1157 break; 1157 break;
1158 case 26: /* HR */ 1158 case 26: /* HR */
1159 case 42: /* HR (opt) */ 1159 case 42: /* HR (opt) */
1160 ws[wpos++] = '\n'; 1160 ws[wpos++] = '\n';
1161 scalable = gtk_imhtml_hr_new(); 1161 scalable = gtk_imhtml_hr_new();
1162 NEW_BIT(NEW_SCALABLE_BIT); 1162 NEW_BIT(NEW_SCALABLE_BIT);
1194 case 35: /* BODY */ 1194 case 35: /* BODY */
1195 case 36: /* /BODY */ 1195 case 36: /* /BODY */
1196 case 37: /* FONT */ 1196 case 37: /* FONT */
1197 case 38: /* HEAD */ 1197 case 38: /* HEAD */
1198 case 39: /* /HEAD */ 1198 case 39: /* /HEAD */
1199 break; 1199 case 40: /* BINARY */
1200 case 40: /* BINARY */ 1200 case 41: /* /BINARY */
1201 NEW_BIT (NEW_TEXT_BIT);
1202 while (pos < len && g_ascii_strncasecmp("</BINARY>", c, strlen("</BINARY>"))) {
1203 c++;
1204 pos++;
1205 }
1206 c = c - tlen; /* Because it will add this later */
1207 break;
1208 case 41: /* /BINARY */
1209 break; 1201 break;
1210 case 43: /* FONT (opt) */ 1202 case 43: /* FONT (opt) */
1211 { 1203 {
1212 gchar *color, *back, *face, *size, *sml; 1204 gchar *color, *back, *face, *size, *sml;
1213 GtkIMHtmlFontDetail *font, *oldfont = NULL; 1205 GtkIMHtmlFontDetail *font, *oldfont = NULL;
1288 url = href; 1280 url = href;
1289 } 1281 }
1290 } 1282 }
1291 break; 1283 break;
1292 case 46: /* IMG (opt) */ 1284 case 46: /* IMG (opt) */
1285 case 59: /* IMG */
1293 { 1286 {
1294 gchar *src = gtk_imhtml_get_html_opt (tag, "SRC="); 1287 GdkPixbuf *img = NULL;
1295 gchar *id = gtk_imhtml_get_html_opt (tag, "ID="); 1288 const gchar *filename = NULL;
1296 gchar *datasize = gtk_imhtml_get_html_opt (tag, "DATASIZE="); 1289
1297 gint im_len = datasize?atoi(datasize):0; 1290 if (images && images->data) {
1298 1291 img = images->data;
1299 if (src && id && im_len && im_len <= len - pos) { 1292 images = images->next;
1300 /* This is an embedded IM image, or is it? */ 1293 filename = g_object_get_data(G_OBJECT(img), "filename");
1301 char *tmp = NULL; 1294 g_object_ref(G_OBJECT(img));
1302 const char *alltext; 1295 } else {
1303 guchar *imagedata = NULL; 1296 img = gtk_widget_render_icon(GTK_WIDGET(imhtml),
1304 1297 GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON,
1305 GdkPixbufLoader *load; 1298 "gtkimhtml-missing-image");
1306 GdkPixbuf *imagepb = NULL;
1307 GError *error = NULL;
1308
1309 tmp = g_strdup_printf("<DATA ID=\"%s\" SIZE=\"%s\">", id, datasize);
1310 alltext = strstr(c, tmp);
1311 imagedata = g_memdup(alltext + strlen(tmp), im_len);
1312
1313 g_free(tmp);
1314
1315 load = gdk_pixbuf_loader_new();
1316 if (!gdk_pixbuf_loader_write(load, imagedata, im_len, &error)){
1317 fprintf(stderr, "IM Image corrupted or unreadable.: %s\n", error->message);
1318 } else {
1319 imagepb = gdk_pixbuf_loader_get_pixbuf(load);
1320 if (imagepb) {
1321 scalable = gtk_imhtml_image_new(imagepb, g_strdup(src));
1322 NEW_BIT(NEW_SCALABLE_BIT);
1323 g_object_unref(imagepb);
1324 }
1325 }
1326
1327 gdk_pixbuf_loader_close(load, NULL);
1328
1329
1330 g_free(imagedata);
1331 g_free(id);
1332 g_free(datasize);
1333 g_free(src);
1334
1335 break;
1336 } 1299 }
1337 g_free(id); 1300
1338 g_free(datasize); 1301 scalable = gtk_imhtml_image_new(img, filename);
1339 g_free(src); 1302 NEW_BIT(NEW_SCALABLE_BIT);
1303 g_object_unref(G_OBJECT(img));
1340 } 1304 }
1341 case 47: /* P (opt) */ 1305 case 47: /* P (opt) */
1342 case 48: /* H3 (opt) */ 1306 case 48: /* H3 (opt) */
1343 case 49: /* HTML (opt) */ 1307 case 49: /* HTML (opt) */
1344 case 50: /* CITE */ 1308 case 50: /* CITE */
1345 case 51: /* /CITE */ 1309 case 51: /* /CITE */
1346 case 56: /* SPAN */ 1310 case 56: /* SPAN */
1347 case 57: /* /SPAN */ 1311 case 57: /* /SPAN */
1348 break; 1312 break;
1349 case 59: /* comment */ 1313 case 60: /* comment */
1350 NEW_BIT (NEW_TEXT_BIT); 1314 NEW_BIT (NEW_TEXT_BIT);
1351 if (imhtml->show_comments) 1315 if (imhtml->show_comments)
1352 wpos = g_snprintf (ws, len, "%s", tag); 1316 wpos = g_snprintf (ws, len, "%s", tag);
1353 NEW_BIT (NEW_COMMENT_BIT); 1317 NEW_BIT (NEW_COMMENT_BIT);
1354 break; 1318 break;
1531 rect.y + rect.height); 1495 rect.y + rect.height);
1532 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); 1496 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0);
1533 } 1497 }
1534 1498
1535 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ 1499 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */
1536 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, gchar *filename) 1500 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename)
1537 { 1501 {
1538 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); 1502 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage));
1539 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); 1503 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img));
1540 1504
1541 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; 1505 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
1545 im_image->pixbuf = img; 1509 im_image->pixbuf = img;
1546 im_image->image = image; 1510 im_image->image = image;
1547 im_image->width = gdk_pixbuf_get_width(img); 1511 im_image->width = gdk_pixbuf_get_width(img);
1548 im_image->height = gdk_pixbuf_get_height(img); 1512 im_image->height = gdk_pixbuf_get_height(img);
1549 im_image->mark = NULL; 1513 im_image->mark = NULL;
1550 im_image->filename = filename; 1514 im_image->filename = filename ? g_strdup(filename) : NULL;
1551 1515
1552 g_object_ref(img); 1516 g_object_ref(img);
1553 return GTK_IMHTML_SCALABLE(im_image); 1517 return GTK_IMHTML_SCALABLE(im_image);
1554 } 1518 }
1555 1519
1666 1630
1667 static void gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image) 1631 static void gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image)
1668 { 1632 {
1669 GtkWidget *sel = gtk_file_selection_new(_("Save Image")); 1633 GtkWidget *sel = gtk_file_selection_new(_("Save Image"));
1670 1634
1671 gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename); 1635 if (image->filename)
1636 gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename);
1672 g_object_set_data(G_OBJECT(sel), "GtkIMHtmlImage", image); 1637 g_object_set_data(G_OBJECT(sel), "GtkIMHtmlImage", image);
1673 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", 1638 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked",
1674 G_CALLBACK(write_img_to_file), sel); 1639 G_CALLBACK(write_img_to_file), sel);
1675 1640
1676 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", 1641 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked",
1716 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) 1681 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale)
1717 { 1682 {
1718 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; 1683 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
1719 1684
1720 g_object_unref(image->pixbuf); 1685 g_object_unref(image->pixbuf);
1721 g_free(image->filename); 1686 if (image->filename)
1687 g_free(image->filename);
1722 g_free(scale); 1688 g_free(scale);
1723 } 1689 }
1724 1690
1725 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) 1691 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
1726 { 1692 {