comparison pidgin/gtkconv.c @ 32779:d72f2f13b60f

merge of 'c8c73eea7431e6f940916315ace40a41c8da3faa' and 'fec428131bde0ae8247941bd6a3d996c984c9189'
author Ethan Blanton <elb@pidgin.im>
date Fri, 21 Oct 2011 14:36:18 +0000
parents 2ec94166be43
children 75104780b1a3
comparison
equal deleted inserted replaced
32778:14787acaf9d7 32779:d72f2f13b60f
50 #include "imgstore.h" 50 #include "imgstore.h"
51 #include "log.h" 51 #include "log.h"
52 #include "notify.h" 52 #include "notify.h"
53 #include "prpl.h" 53 #include "prpl.h"
54 #include "request.h" 54 #include "request.h"
55 #include "theme-loader.h"
56 #include "theme-manager.h"
55 #include "util.h" 57 #include "util.h"
56 #include "version.h" 58 #include "version.h"
57 59
58 #include "gtkdnd-hints.h" 60 #include "gtkdnd-hints.h"
59 #include "gtkblist.h" 61 #include "gtkblist.h"
60 #include "gtkconv.h" 62 #include "gtkconv.h"
61 #include "gtkconvwin.h" 63 #include "gtkconvwin.h"
64 #include "gtkconv-theme.h"
65 #include "gtkconv-theme-loader.h"
62 #include "gtkdialogs.h" 66 #include "gtkdialogs.h"
63 #include "gtkimhtml.h" 67 #include "gtkimhtml.h"
64 #include "gtkimhtmltoolbar.h" 68 #include "gtkimhtmltoolbar.h"
65 #include "gtklog.h" 69 #include "gtklog.h"
66 #include "gtkmenutray.h" 70 #include "gtkmenutray.h"
67 #include "gtkpounce.h" 71 #include "gtkpounce.h"
68 #include "gtkprefs.h" 72 #include "gtkprefs.h"
69 #include "gtkprivacy.h" 73 #include "gtkprivacy.h"
70 #include "gtkthemes.h" 74 #include "gtkthemes.h"
71 #include "gtkutils.h" 75 #include "gtkutils.h"
76 #include "gtkwebview.h"
72 #include "pidginstock.h" 77 #include "pidginstock.h"
73 #include "pidgintooltip.h" 78 #include "pidgintooltip.h"
79 #include "smileyparser.h"
74 80
75 #include "gtknickcolors.h" 81 #include "gtknickcolors.h"
82
83 /**
84 * A GTK+ Instant Message pane.
85 */
86 struct _PidginImPane
87 {
88 GtkWidget *block;
89 GtkWidget *send_file;
90 GtkWidget *sep1;
91 GtkWidget *sep2;
92 GtkWidget *check;
93 GtkWidget *progress;
94 guint32 typing_timer;
95
96 /* Buddy icon stuff */
97 GtkWidget *icon_container;
98 GtkWidget *icon;
99 gboolean show_icon;
100 gboolean animate;
101 GdkPixbufAnimation *anim;
102 GdkPixbufAnimationIter *iter;
103 guint32 icon_timer;
104 };
105
106 /**
107 * GTK+ Chat panes.
108 */
109 struct _PidginChatPane
110 {
111 GtkWidget *count;
112 GtkWidget *list;
113 GtkWidget *topic_text;
114 };
76 115
77 #define CLOSE_CONV_TIMEOUT_SECS (10 * 60) 116 #define CLOSE_CONV_TIMEOUT_SECS (10 * 60)
78 117
79 #define AUTO_RESPONSE "&lt;AUTO-REPLY&gt; : " 118 #define AUTO_RESPONSE "&lt;AUTO-REPLY&gt; : "
80 119
174 static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y); 213 static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y);
175 214
176 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) 215 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name)
177 { 216 {
178 static GdkColor col; 217 static GdkColor col;
179 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); 218 GtkStyle *style = gtk_widget_get_style(gtkconv->webview);
180 float scale; 219 float scale;
181 220
182 col = nick_colors[g_str_hash(name) % nbr_nick_colors]; 221 col = nick_colors[g_str_hash(name) % nbr_nick_colors];
183 scale = ((1-(LUMINANCE(style->base[GTK_STATE_NORMAL]) / LUMINANCE(style->white))) * 222 scale = ((1-(LUMINANCE(style->base[GTK_STATE_NORMAL]) / LUMINANCE(style->white))) *
184 (LUMINANCE(style->white)/MAX(MAX(col.red, col.blue), col.green))); 223 (LUMINANCE(style->white)/MAX(MAX(col.red, col.blue), col.green)));
194 } 233 }
195 234
196 static PurpleBlistNode * 235 static PurpleBlistNode *
197 get_conversation_blist_node(PurpleConversation *conv) 236 get_conversation_blist_node(PurpleConversation *conv)
198 { 237 {
238 PurpleAccount *account = purple_conversation_get_account(conv);
199 PurpleBlistNode *node = NULL; 239 PurpleBlistNode *node = NULL;
200 240
201 switch (purple_conversation_get_type(conv)) { 241 switch (purple_conversation_get_type(conv)) {
202 case PURPLE_CONV_TYPE_IM: 242 case PURPLE_CONV_TYPE_IM:
203 node = PURPLE_BLIST_NODE(purple_find_buddy(conv->account, conv->name)); 243 node = PURPLE_BLIST_NODE(purple_find_buddy(account, purple_conversation_get_name(conv)));
204 node = node ? node->parent : NULL; 244 node = node ? node->parent : NULL;
205 break; 245 break;
206 case PURPLE_CONV_TYPE_CHAT: 246 case PURPLE_CONV_TYPE_CHAT:
207 node = PURPLE_BLIST_NODE(purple_blist_find_chat(conv->account, conv->name)); 247 node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, purple_conversation_get_name(conv)));
208 break; 248 break;
209 default: 249 default:
210 break; 250 break;
211 } 251 }
212 return node; 252 return node;
274 314
275 static void 315 static void
276 default_formatize(PidginConversation *c) 316 default_formatize(PidginConversation *c)
277 { 317 {
278 PurpleConversation *conv = c->active_conv; 318 PurpleConversation *conv = c->active_conv;
279 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features); 319 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), purple_conversation_get_features(conv));
280 } 320 }
281 321
282 static void 322 static void
283 conversation_entry_clear(PidginConversation *gtkconv) 323 conversation_entry_clear(PidginConversation *gtkconv)
284 { 324 {
354 } else { 394 } else {
355 str = g_string_append(str, "(none)"); 395 str = g_string_append(str, "(none)");
356 } 396 }
357 397
358 tmp = g_string_free(str, FALSE); 398 tmp = g_string_free(str, FALSE);
399 } else if (!g_ascii_strcasecmp(args[0], "unsafe")) {
400 if (purple_debug_is_unsafe()) {
401 purple_debug_set_unsafe(FALSE);
402 purple_conversation_write(conv, NULL, _("Unsafe debugging is now disabled."),
403 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
404 } else {
405 purple_debug_set_unsafe(TRUE);
406 purple_conversation_write(conv, NULL, _("Unsafe debugging is now enabled."),
407 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
408 }
409
410 return PURPLE_CMD_RET_OK;
411 } else if (!g_ascii_strcasecmp(args[0], "verbose")) {
412 if (purple_debug_is_verbose()) {
413 purple_debug_set_verbose(FALSE);
414 purple_conversation_write(conv, NULL, _("Verbose debugging is now disabled."),
415 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
416 } else {
417 purple_debug_set_verbose(TRUE);
418 purple_conversation_write(conv, NULL, _("Verbose debugging is now enabled."),
419 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
420 }
421
422 return PURPLE_CMD_RET_OK;
359 } else { 423 } else {
360 purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version"), 424 purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version unsafe verbose"),
361 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL)); 425 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL));
362 return PURPLE_CMD_RET_OK; 426 return PURPLE_CMD_RET_OK;
363 } 427 }
364 428
365 markup = g_markup_escape_text(tmp, -1); 429 markup = g_markup_escape_text(tmp, -1);
377 void *data) 441 void *data)
378 { 442 {
379 PidginConversation *gtkconv = NULL; 443 PidginConversation *gtkconv = NULL;
380 444
381 gtkconv = PIDGIN_CONVERSATION(conv); 445 gtkconv = PIDGIN_CONVERSATION(conv);
382 if (gtkconv) 446
383 gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); 447 if (PIDGIN_CONVERSATION(conv))
448 webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(gtkconv->webview), "", "");
384 } 449 }
385 450
386 static PurpleCmdRet 451 static PurpleCmdRet
387 clear_command_cb(PurpleConversation *conv, 452 clear_command_cb(PurpleConversation *conv,
388 const char *cmd, char **args, char **error, void *data) 453 const char *cmd, char **args, char **error, void *data)
497 { 562 {
498 PurplePluginProtocolInfo *prpl_info = NULL; 563 PurplePluginProtocolInfo *prpl_info = NULL;
499 PurpleConnection *gc; 564 PurpleConnection *gc;
500 565
501 if ((gc = purple_conversation_get_gc(conv))) 566 if ((gc = purple_conversation_get_gc(conv)))
502 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 567 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
503 568
504 if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) { 569 if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) {
505 char *spaceslash; 570 char *spaceslash;
506 571
507 /* If the first word in the entered text has a '/' in it, then the user 572 /* If the first word in the entered text has a '/' in it, then the user
576 buf = gtk_imhtml_get_markup(GTK_IMHTML(gtkconv->entry)); 641 buf = gtk_imhtml_get_markup(GTK_IMHTML(gtkconv->entry));
577 clean = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL); 642 clean = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL);
578 643
579 gtk_widget_grab_focus(gtkconv->entry); 644 gtk_widget_grab_focus(gtkconv->entry);
580 645
581 if (strlen(clean) == 0) { 646 if (!*clean) {
582 g_free(buf); 647 g_free(buf);
583 g_free(clean); 648 g_free(clean);
584 return; 649 return;
585 } 650 }
586 651
589 /* XXX: is there a better way to tell if the message has images? */ 654 /* XXX: is there a better way to tell if the message has images? */
590 if (GTK_IMHTML(gtkconv->entry)->im_images != NULL) 655 if (GTK_IMHTML(gtkconv->entry)->im_images != NULL)
591 flags |= PURPLE_MESSAGE_IMAGES; 656 flags |= PURPLE_MESSAGE_IMAGES;
592 657
593 gc = purple_account_get_connection(account); 658 gc = purple_account_get_connection(account);
594 if (gc && (conv->features & PURPLE_CONNECTION_NO_NEWLINES)) { 659 if (gc && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_NO_NEWLINES)) {
595 char **bufs; 660 char **bufs;
596 int i; 661 int i;
597 662
598 bufs = gtk_imhtml_get_markup_lines(GTK_IMHTML(gtkconv->entry)); 663 bufs = gtk_imhtml_get_markup_lines(GTK_IMHTML(gtkconv->entry));
599 for (i = 0; bufs[i]; i++) { 664 for (i = 0; bufs[i]; i++) {
986 } 1051 }
987 1052
988 static void 1053 static void
989 savelog_writefile_cb(void *user_data, const char *filename) 1054 savelog_writefile_cb(void *user_data, const char *filename)
990 { 1055 {
1056 /* TODO WEBKIT: I don't know how to support this using webkit yet. */
1057 #if 0
991 PurpleConversation *conv = (PurpleConversation *)user_data; 1058 PurpleConversation *conv = (PurpleConversation *)user_data;
992 FILE *fp; 1059 FILE *fp;
993 const char *name; 1060 const char *name;
994 char **lines; 1061 char **lines;
995 gchar *text; 1062 gchar *text;
1012 g_free(text); 1079 g_free(text);
1013 g_strfreev(lines); 1080 g_strfreev(lines);
1014 1081
1015 fprintf(fp, "\n</body>\n</html>\n"); 1082 fprintf(fp, "\n</body>\n</html>\n");
1016 fclose(fp); 1083 fclose(fp);
1084 #endif /* if 0 */
1017 } 1085 }
1018 1086
1019 /* 1087 /*
1020 * It would be kinda cool if this gave the option of saving a 1088 * It would be kinda cool if this gave the option of saving a
1021 * plaintext v. HTML file. 1089 * plaintext v. HTML file.
1023 static void 1091 static void
1024 menu_save_as_cb(gpointer data, guint action, GtkWidget *widget) 1092 menu_save_as_cb(gpointer data, guint action, GtkWidget *widget)
1025 { 1093 {
1026 PidginWindow *win = data; 1094 PidginWindow *win = data;
1027 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); 1095 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
1028 PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); 1096 PurpleAccount *account = purple_conversation_get_account(conv);
1097 PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
1029 const char *name; 1098 const char *name;
1030 gchar *buf; 1099 gchar *buf;
1031 gchar *c; 1100 gchar *c;
1032 1101
1033 if (buddy != NULL) 1102 if (buddy != NULL)
1034 name = purple_buddy_get_contact_alias(buddy); 1103 name = purple_buddy_get_contact_alias(buddy);
1035 else 1104 else
1036 name = purple_normalize(conv->account, conv->name); 1105 name = purple_normalize(account, purple_conversation_get_name(conv));
1037 1106
1038 buf = g_strdup_printf("%s.html", name); 1107 buf = g_strdup_printf("%s.html", name);
1039 for (c = buf ; *c ; c++) 1108 for (c = buf ; *c ; c++)
1040 { 1109 {
1041 if (*c == '/' || *c == '\\') 1110 if (*c == '/' || *c == '\\')
1354 /* Enable logging first so the message below can be logged. */ 1423 /* Enable logging first so the message below can be logged. */
1355 purple_conversation_set_logging(conv, TRUE); 1424 purple_conversation_set_logging(conv, TRUE);
1356 1425
1357 purple_conversation_write(conv, NULL, 1426 purple_conversation_write(conv, NULL,
1358 _("Logging started. Future messages in this conversation will be logged."), 1427 _("Logging started. Future messages in this conversation will be logged."),
1359 conv->logs ? (PURPLE_MESSAGE_SYSTEM) : 1428 PURPLE_MESSAGE_SYSTEM,
1360 (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG),
1361 time(NULL)); 1429 time(NULL));
1362 } 1430 }
1363 else 1431 else
1364 { 1432 {
1365 purple_conversation_write(conv, NULL, 1433 purple_conversation_write(conv, NULL,
1366 _("Logging stopped. Future messages in this conversation will not be logged."), 1434 _("Logging stopped. Future messages in this conversation will not be logged."),
1367 conv->logs ? (PURPLE_MESSAGE_SYSTEM) : 1435 PURPLE_MESSAGE_SYSTEM,
1368 (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG),
1369 time(NULL)); 1436 time(NULL));
1370 1437
1371 /* Disable the logging second, so that the above message can be logged. */ 1438 /* Disable the logging second, so that the above message can be logged. */
1372 purple_conversation_set_logging(conv, FALSE); 1439 purple_conversation_set_logging(conv, FALSE);
1373 } 1440 }
1374 1441
1375 /* Save the setting IFF it's different than the pref. */ 1442 /* Save the setting IFF it's different than the pref. */
1376 switch (conv->type) 1443 switch (purple_conversation_get_type(conv))
1377 { 1444 {
1378 case PURPLE_CONV_TYPE_IM: 1445 case PURPLE_CONV_TYPE_IM:
1379 if (logging == purple_prefs_get_bool("/purple/logging/log_ims")) 1446 if (logging == purple_prefs_get_bool("/purple/logging/log_ims"))
1380 purple_blist_node_remove_setting(node, "enable-logging"); 1447 purple_blist_node_remove_setting(node, "enable-logging");
1381 else 1448 else
1443 g_return_if_fail(account != NULL); 1510 g_return_if_fail(account != NULL);
1444 1511
1445 gc = purple_account_get_connection(account); 1512 gc = purple_account_get_connection(account);
1446 g_return_if_fail(gc != NULL); 1513 g_return_if_fail(gc != NULL);
1447 1514
1448 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 1515 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1449 1516
1450 if (prpl_info && prpl_info->get_cb_real_name) 1517 if (prpl_info && prpl_info->get_cb_real_name)
1451 real_who = prpl_info->get_cb_real_name(gc, 1518 real_who = prpl_info->get_cb_real_name(gc,
1452 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); 1519 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
1453 1520
1499 PurpleConnection *gc = purple_conversation_get_gc(conv); 1566 PurpleConnection *gc = purple_conversation_get_gc(conv);
1500 gchar *real_who = NULL; 1567 gchar *real_who = NULL;
1501 1568
1502 g_return_if_fail(gc != NULL); 1569 g_return_if_fail(gc != NULL);
1503 1570
1504 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 1571 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1505 1572
1506 if (prpl_info && prpl_info->get_cb_real_name) 1573 if (prpl_info && prpl_info->get_cb_real_name)
1507 real_who = prpl_info->get_cb_real_name(gc, 1574 real_who = prpl_info->get_cb_real_name(gc,
1508 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); 1575 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
1509 1576
1517 char *who; 1584 char *who;
1518 1585
1519 who = g_object_get_data(G_OBJECT(w), "user_data"); 1586 who = g_object_get_data(G_OBJECT(w), "user_data");
1520 1587
1521 chat_do_info(gtkconv, who); 1588 chat_do_info(gtkconv, who);
1522 }
1523
1524 static void
1525 menu_chat_get_away_cb(GtkWidget *w, PidginConversation *gtkconv)
1526 {
1527 PurpleConversation *conv = gtkconv->active_conv;
1528 PurplePluginProtocolInfo *prpl_info = NULL;
1529 PurpleConnection *gc;
1530 char *who;
1531
1532 gc = purple_conversation_get_gc(conv);
1533 who = g_object_get_data(G_OBJECT(w), "user_data");
1534
1535 if (gc != NULL) {
1536 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
1537
1538 /*
1539 * May want to expand this to work similarly to menu_info_cb?
1540 */
1541
1542 if (prpl_info->get_cb_away != NULL)
1543 {
1544 prpl_info->get_cb_away(gc,
1545 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
1546 }
1547 }
1548 } 1589 }
1549 1590
1550 static void 1591 static void
1551 menu_chat_add_remove_cb(GtkWidget *w, PidginConversation *gtkconv) 1592 menu_chat_add_remove_cb(GtkWidget *w, PidginConversation *gtkconv)
1552 { 1593 {
1568 } 1609 }
1569 1610
1570 static GtkTextMark * 1611 static GtkTextMark *
1571 get_mark_for_user(PidginConversation *gtkconv, const char *who) 1612 get_mark_for_user(PidginConversation *gtkconv, const char *who)
1572 { 1613 {
1573 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)); 1614 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->webview));
1574 char *tmp = g_strconcat("user:", who, NULL); 1615 char *tmp = g_strconcat("user:", who, NULL);
1575 GtkTextMark *mark = gtk_text_buffer_get_mark(buf, tmp); 1616 GtkTextMark *mark = gtk_text_buffer_get_mark(buf, tmp);
1576 1617
1577 g_free(tmp); 1618 g_free(tmp);
1578 return mark; 1619 return mark;
1579 } 1620 }
1580 1621
1581 static void 1622 static void
1582 menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv) 1623 menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv)
1583 { 1624 {
1625 /* TODO WEBKIT: This doesn't work yet, of course... */
1626 #if 0
1584 GtkTextMark *mark; 1627 GtkTextMark *mark;
1585 const char *who; 1628 const char *who;
1586 1629
1587 who = g_object_get_data(G_OBJECT(w), "user_data"); 1630 who = g_object_get_data(G_OBJECT(w), "user_data");
1588 mark = get_mark_for_user(gtkconv, who); 1631 mark = get_mark_for_user(gtkconv, who);
1589 1632
1590 if (mark != NULL) 1633 if (mark != NULL)
1591 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0); 1634 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0);
1592 else 1635 else
1593 g_return_if_reached(); 1636 g_return_if_reached();
1637 #endif /* if 0 */
1594 } 1638 }
1595 1639
1596 static GtkWidget * 1640 static GtkWidget *
1597 create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc) 1641 create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc)
1598 { 1642 {
1599 static GtkWidget *menu = NULL; 1643 static GtkWidget *menu = NULL;
1600 PurplePluginProtocolInfo *prpl_info = NULL; 1644 PurplePluginProtocolInfo *prpl_info = NULL;
1601 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); 1645 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
1646 PurpleAccount *account = purple_conversation_get_account(conv);
1602 gboolean is_me = FALSE; 1647 gboolean is_me = FALSE;
1603 GtkWidget *button; 1648 GtkWidget *button;
1604 PurpleBuddy *buddy = NULL; 1649 PurpleBuddy *buddy = NULL;
1605 1650
1606 if (gc != NULL) 1651 if (gc != NULL)
1607 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 1652 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1608 1653
1609 /* 1654 /*
1610 * If a menu already exists, destroy it before creating a new one, 1655 * If a menu already exists, destroy it before creating a new one,
1611 * thus freeing-up the memory it occupied. 1656 * thus freeing-up the memory it occupied.
1612 */ 1657 */
1613 if (menu) 1658 if (menu)
1614 gtk_widget_destroy(menu); 1659 gtk_widget_destroy(menu);
1615 1660
1616 if (!strcmp(chat->nick, purple_normalize(conv->account, who))) 1661 if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, who)))
1617 is_me = TRUE; 1662 is_me = TRUE;
1618 1663
1619 menu = gtk_menu_new(); 1664 menu = gtk_menu_new();
1620 1665
1621 if (!is_me) { 1666 if (!is_me) {
1676 gtk_widget_set_sensitive(button, FALSE); 1721 gtk_widget_set_sensitive(button, FALSE);
1677 else 1722 else
1678 g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free); 1723 g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
1679 } 1724 }
1680 1725
1681 if (prpl_info && prpl_info->get_cb_away) {
1682 button = pidgin_new_item_from_stock(menu, _("Get Away Message"), PIDGIN_STOCK_AWAY,
1683 G_CALLBACK(menu_chat_get_away_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
1684
1685 if (gc == NULL)
1686 gtk_widget_set_sensitive(button, FALSE);
1687 else
1688 g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
1689 }
1690
1691 if (!is_me && prpl_info && !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { 1726 if (!is_me && prpl_info && !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
1692 if ((buddy = purple_find_buddy(conv->account, who)) != NULL) 1727 if ((buddy = purple_find_buddy(account, who)) != NULL)
1693 button = pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE, 1728 button = pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE,
1694 G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); 1729 G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
1695 else 1730 else
1696 button = pidgin_new_item_from_stock(menu, _("Add"), GTK_STOCK_ADD, 1731 button = pidgin_new_item_from_stock(menu, _("Add"), GTK_STOCK_ADD,
1697 G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); 1732 G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
1708 if (!get_mark_for_user(PIDGIN_CONVERSATION(conv), who)) 1743 if (!get_mark_for_user(PIDGIN_CONVERSATION(conv), who))
1709 gtk_widget_set_sensitive(button, FALSE); 1744 gtk_widget_set_sensitive(button, FALSE);
1710 1745
1711 if (buddy != NULL) 1746 if (buddy != NULL)
1712 { 1747 {
1713 if (purple_account_is_connected(conv->account)) 1748 if (purple_account_is_connected(account))
1714 pidgin_append_blist_node_proto_menu(menu, conv->account->gc, 1749 pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account),
1715 (PurpleBlistNode *)buddy); 1750 (PurpleBlistNode *)buddy);
1716 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy); 1751 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy);
1717 gtk_widget_show_all(menu); 1752 gtk_widget_show_all(menu);
1718 } 1753 }
1719 1754
1735 gchar *who; 1770 gchar *who;
1736 1771
1737 gtkconv = PIDGIN_CONVERSATION(conv); 1772 gtkconv = PIDGIN_CONVERSATION(conv);
1738 gtkchat = gtkconv->u.chat; 1773 gtkchat = gtkconv->u.chat;
1739 account = purple_conversation_get_account(conv); 1774 account = purple_conversation_get_account(conv);
1740 gc = account->gc; 1775 gc = purple_account_get_connection(account);
1741 1776
1742 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 1777 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
1743 1778
1744 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkchat->list)); 1779 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkchat->list));
1745 if(!gtk_tree_selection_get_selected(sel, NULL, &iter)) 1780 if(!gtk_tree_selection_get_selected(sel, NULL, &iter))
1771 gchar *who; 1806 gchar *who;
1772 int x, y; 1807 int x, y;
1773 1808
1774 gtkchat = gtkconv->u.chat; 1809 gtkchat = gtkconv->u.chat;
1775 account = purple_conversation_get_account(conv); 1810 account = purple_conversation_get_account(conv);
1776 gc = account->gc; 1811 gc = purple_account_get_connection(account);
1777 1812
1778 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 1813 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
1779 1814
1780 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list), 1815 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list),
1781 event->x, event->y, &path, &column, &x, &y); 1816 event->x, event->y, &path, &column, &x, &y);
1803 1838
1804 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { 1839 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) {
1805 chat_do_im(gtkconv, who); 1840 chat_do_im(gtkconv, who);
1806 } else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) { 1841 } else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) {
1807 /* Move to user's anchor */ 1842 /* Move to user's anchor */
1843 /* TODO WEBKIT: This isn't implemented yet. */
1844 #if 0
1808 GtkTextMark *mark = get_mark_for_user(gtkconv, who); 1845 GtkTextMark *mark = get_mark_for_user(gtkconv, who);
1809 1846
1810 if(mark != NULL) 1847 if(mark != NULL)
1811 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0); 1848 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0);
1849 #endif /* if 0 */
1812 } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { 1850 } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
1813 GtkWidget *menu = create_chat_menu (conv, who, gc); 1851 GtkWidget *menu = create_chat_menu (conv, who, gc);
1814 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 1852 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1815 event->button, event->time); 1853 event->button, event->time);
1816 } 1854 }
1883 GtkWidget *next = NULL; 1921 GtkWidget *next = NULL;
1884 struct { 1922 struct {
1885 GtkWidget *from; 1923 GtkWidget *from;
1886 GtkWidget *to; 1924 GtkWidget *to;
1887 } transitions[] = { 1925 } transitions[] = {
1888 {gtkconv->entry, gtkconv->imhtml}, 1926 {gtkconv->entry, gtkconv->webview},
1889 {gtkconv->imhtml, chat ? gtkconv->u.chat->list : gtkconv->entry}, 1927 {gtkconv->webview, chat ? gtkconv->u.chat->list : gtkconv->entry},
1890 {chat ? gtkconv->u.chat->list : NULL, gtkconv->entry}, 1928 {chat ? gtkconv->u.chat->list : NULL, gtkconv->entry},
1891 {NULL, NULL} 1929 {NULL, NULL}
1892 }, *ptr; 1930 }, *ptr;
1893 1931
1894 for (ptr = transitions; !next && ptr->from; ptr++) { 1932 for (ptr = transitions; !next && ptr->from; ptr++) {
2140 return plugin_return ? TRUE : tab_complete(conv); 2178 return plugin_return ? TRUE : tab_complete(conv);
2141 } 2179 }
2142 break; 2180 break;
2143 2181
2144 case GDK_Page_Up: 2182 case GDK_Page_Up:
2145 case GDK_KP_Page_Up: 2183 case GDK_KP_Page_Up:
2184 /* TODO WEBKIT: Write this. */
2185 #if 0
2146 gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml)); 2186 gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml));
2187 #endif /* if 0 */
2147 return TRUE; 2188 return TRUE;
2148 break; 2189 break;
2149 2190
2150 case GDK_Page_Down: 2191 case GDK_Page_Down:
2151 case GDK_KP_Page_Down: 2192 case GDK_KP_Page_Down:
2193 /* TODO WEBKIT: Write this. */
2194 #if 0
2152 gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml)); 2195 gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml));
2196 #endif /* if 0 */
2153 return TRUE; 2197 return TRUE;
2154 break; 2198 break;
2155 2199
2156 } 2200 }
2157 } 2201 }
2234 { 2278 {
2235 PidginConversation *gtkconv; 2279 PidginConversation *gtkconv;
2236 PurpleConversation *old_conv; 2280 PurpleConversation *old_conv;
2237 GtkIMHtml *entry; 2281 GtkIMHtml *entry;
2238 const char *protocol_name; 2282 const char *protocol_name;
2283 PurpleConnectionFlags features;
2239 2284
2240 g_return_if_fail(conv != NULL); 2285 g_return_if_fail(conv != NULL);
2241 2286
2242 gtkconv = PIDGIN_CONVERSATION(conv); 2287 gtkconv = PIDGIN_CONVERSATION(conv);
2243 old_conv = gtkconv->active_conv; 2288 old_conv = gtkconv->active_conv;
2255 2300
2256 purple_conversation_set_logging(conv, 2301 purple_conversation_set_logging(conv,
2257 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging))); 2302 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging)));
2258 2303
2259 entry = GTK_IMHTML(gtkconv->entry); 2304 entry = GTK_IMHTML(gtkconv->entry);
2260 protocol_name = purple_account_get_protocol_name(conv->account); 2305 protocol_name = purple_account_get_protocol_name(purple_conversation_get_account(conv));
2261 gtk_imhtml_set_protocol_name(entry, protocol_name); 2306 gtk_imhtml_set_protocol_name(entry, protocol_name);
2262 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); 2307 /* TODO WEBKIT: gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); */
2263 2308
2264 if (!(conv->features & PURPLE_CONNECTION_HTML)) 2309 features = purple_conversation_get_features(conv);
2310 if (!(features & PURPLE_CONNECTION_HTML))
2265 gtk_imhtml_clear_formatting(GTK_IMHTML(gtkconv->entry)); 2311 gtk_imhtml_clear_formatting(GTK_IMHTML(gtkconv->entry));
2266 else if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO && 2312 else if (features & PURPLE_CONNECTION_FORMATTING_WBFO &&
2267 !(old_conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)) 2313 !(purple_conversation_get_features(old_conv) & PURPLE_CONNECTION_FORMATTING_WBFO))
2268 { 2314 {
2269 /* The old conversation allowed formatting on parts of the 2315 /* The old conversation allowed formatting on parts of the
2270 * buffer, but the new one only allows it on the whole 2316 * buffer, but the new one only allows it on the whole
2271 * buffer. This code saves the formatting from the current 2317 * buffer. This code saves the formatting from the current
2272 * position of the cursor, clears the formatting, then 2318 * position of the cursor, clears the formatting, then
2302 if (underline != underline2) 2348 if (underline != underline2)
2303 gtk_imhtml_toggle_underline(entry); 2349 gtk_imhtml_toggle_underline(entry);
2304 2350
2305 gtk_imhtml_toggle_fontface(entry, fontface); 2351 gtk_imhtml_toggle_fontface(entry, fontface);
2306 2352
2307 if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE)) 2353 if (!(features & PURPLE_CONNECTION_NO_FONTSIZE))
2308 gtk_imhtml_font_set_size(entry, fontsize); 2354 gtk_imhtml_font_set_size(entry, fontsize);
2309 2355
2310 gtk_imhtml_toggle_forecolor(entry, forecolor); 2356 gtk_imhtml_toggle_forecolor(entry, forecolor);
2311 2357
2312 if (!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR)) 2358 if (!(features & PURPLE_CONNECTION_NO_BGCOLOR))
2313 { 2359 {
2314 gtk_imhtml_toggle_backcolor(entry, backcolor); 2360 gtk_imhtml_toggle_backcolor(entry, backcolor);
2315 gtk_imhtml_toggle_background(entry, background); 2361 gtk_imhtml_toggle_background(entry, background);
2316 } 2362 }
2317 2363
2325 /* This is done in default_formatize, which is called from clear_formatting_cb, 2371 /* This is done in default_formatize, which is called from clear_formatting_cb,
2326 * which is (obviously) a clear_formatting signal handler. However, if we're 2372 * which is (obviously) a clear_formatting signal handler. However, if we're
2327 * here, we didn't call gtk_imhtml_clear_formatting() (because we want to 2373 * here, we didn't call gtk_imhtml_clear_formatting() (because we want to
2328 * preserve the formatting exactly as it is), so we have to do this now. */ 2374 * preserve the formatting exactly as it is), so we have to do this now. */
2329 gtk_imhtml_set_whole_buffer_formatting_only(entry, 2375 gtk_imhtml_set_whole_buffer_formatting_only(entry,
2330 (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)); 2376 (features & PURPLE_CONNECTION_FORMATTING_WBFO));
2331 } 2377 }
2332 2378
2333 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv); 2379 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv);
2334 2380
2335 gray_stuff_out(gtkconv); 2381 gray_stuff_out(gtkconv);
2555 return; 2601 return;
2556 2602
2557 status = infopane_status = pidgin_conv_get_icon_stock(conv); 2603 status = infopane_status = pidgin_conv_get_icon_stock(conv);
2558 2604
2559 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 2605 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
2560 PurpleBuddy *b = purple_find_buddy(conv->account, conv->name); 2606 PurpleBuddy *b = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
2561 if (b) 2607 if (b)
2562 emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b); 2608 emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b);
2563 } 2609 }
2564 2610
2565 g_return_if_fail(status != NULL); 2611 g_return_if_fail(status != NULL);
2576 CONV_EMBLEM_COLUMN, emblem, -1); 2622 CONV_EMBLEM_COLUMN, emblem, -1);
2577 if (emblem) 2623 if (emblem)
2578 g_object_unref(emblem); 2624 g_object_unref(emblem);
2579 2625
2580 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) { 2626 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) {
2581 emblem = pidgin_create_prpl_icon(gtkconv->active_conv->account, PIDGIN_PRPL_ICON_SMALL); 2627 emblem = pidgin_create_prpl_icon(purple_conversation_get_account(gtkconv->active_conv), PIDGIN_PRPL_ICON_SMALL);
2582 } else { 2628 } else {
2583 emblem = NULL; 2629 emblem = NULL;
2584 } 2630 }
2585 2631
2586 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model), 2632 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model),
2632 int size; 2678 int size;
2633 2679
2634 gtkconv = PIDGIN_CONVERSATION(conv); 2680 gtkconv = PIDGIN_CONVERSATION(conv);
2635 account = purple_conversation_get_account(conv); 2681 account = purple_conversation_get_account(conv);
2636 2682
2637 if (!(account && account->gc)) { 2683 if (!(account && purple_account_get_connection(account))) {
2638 gtkconv->u.im->icon_timer = 0; 2684 gtkconv->u.im->icon_timer = 0;
2639 return FALSE; 2685 return FALSE;
2640 } 2686 }
2641 2687
2642 gdk_pixbuf_animation_iter_advance(gtkconv->u.im->iter, NULL); 2688 gdk_pixbuf_animation_iter_advance(gtkconv->u.im->iter, NULL);
2839 2885
2840 g_return_if_fail(conv != NULL); 2886 g_return_if_fail(conv != NULL);
2841 2887
2842 ext = purple_buddy_icon_get_extension(purple_conv_im_get_icon(PURPLE_CONV_IM(conv))); 2888 ext = purple_buddy_icon_get_extension(purple_conv_im_get_icon(PURPLE_CONV_IM(conv)));
2843 2889
2844 buf = g_strdup_printf("%s.%s", purple_normalize(conv->account, conv->name), ext); 2890 buf = g_strdup_printf("%s.%s", purple_normalize(purple_conversation_get_account(conv), purple_conversation_get_name(conv)), ext);
2845 2891
2846 purple_request_file(gtkconv, _("Save Icon"), buf, TRUE, 2892 purple_request_file(gtkconv, _("Save Icon"), buf, TRUE,
2847 G_CALLBACK(saveicon_writefile_cb), NULL, 2893 G_CALLBACK(saveicon_writefile_cb), NULL,
2848 conv->account, NULL, conv, 2894 purple_conversation_get_account(conv), NULL, conv,
2849 gtkconv); 2895 gtkconv);
2850 2896
2851 g_free(buf); 2897 g_free(buf);
2852 } 2898 }
2853 2899
3183 static gboolean 3229 static gboolean
3184 populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolean all) 3230 populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolean all)
3185 { 3231 {
3186 GList *list; 3232 GList *list;
3187 PurpleConversation *conv; 3233 PurpleConversation *conv;
3234 PurpleAccount *account;
3188 PurpleBlistNode *node = NULL; 3235 PurpleBlistNode *node = NULL;
3189 PurpleChat *chat = NULL; 3236 PurpleChat *chat = NULL;
3190 PurpleBuddy *buddy = NULL; 3237 PurpleBuddy *buddy = NULL;
3191 gboolean ret; 3238 gboolean ret;
3192 3239
3193 conv = gtkconv->active_conv; 3240 conv = gtkconv->active_conv;
3241 account = purple_conversation_get_account(conv);
3194 3242
3195 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 3243 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
3196 chat = purple_blist_find_chat(conv->account, conv->name); 3244 chat = purple_blist_find_chat(account, purple_conversation_get_name(conv));
3197 3245
3198 if ((chat == NULL) && (gtkconv->imhtml != NULL)) { 3246 if ((chat == NULL) && (gtkconv->webview != NULL)) {
3199 chat = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); 3247 chat = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat");
3200 } 3248 }
3201 3249
3202 if ((chat == NULL) && (gtkconv->imhtml != NULL)) { 3250 if ((chat == NULL) && (gtkconv->webview != NULL)) {
3203 GHashTable *components; 3251 GHashTable *components;
3204 PurpleAccount *account = purple_conversation_get_account(conv); 3252 PurpleAccount *account = purple_conversation_get_account(conv);
3205 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); 3253 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
3206 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 3254 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
3207 if (purple_account_get_connection(account) != NULL && 3255 if (purple_account_get_connection(account) != NULL &&
3212 components = g_hash_table_new_full(g_str_hash, g_str_equal, 3260 components = g_hash_table_new_full(g_str_hash, g_str_equal,
3213 g_free, g_free); 3261 g_free, g_free);
3214 g_hash_table_replace(components, g_strdup("channel"), 3262 g_hash_table_replace(components, g_strdup("channel"),
3215 g_strdup(purple_conversation_get_name(conv))); 3263 g_strdup(purple_conversation_get_name(conv)));
3216 } 3264 }
3217 chat = purple_chat_new(conv->account, NULL, components); 3265 chat = purple_chat_new(account, NULL, components);
3218 purple_blist_node_set_flags((PurpleBlistNode *)chat, 3266 purple_blist_node_set_flags((PurpleBlistNode *)chat,
3219 PURPLE_BLIST_NODE_FLAG_NO_SAVE); 3267 PURPLE_BLIST_NODE_FLAG_NO_SAVE);
3220 g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_chat", 3268 g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_chat",
3221 chat, (GDestroyNotify)purple_blist_remove_chat); 3269 chat, (GDestroyNotify)purple_blist_remove_chat);
3222 } 3270 }
3223 } else { 3271 } else {
3224 if (!purple_account_is_connected(conv->account)) 3272 if (!purple_account_is_connected(account))
3225 return FALSE; 3273 return FALSE;
3226 3274
3227 buddy = purple_find_buddy(conv->account, conv->name); 3275 buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
3228 3276
3229 /* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle 3277 /* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle
3230 * removing "isolated" buddy nodes well */ 3278 * removing "isolated" buddy nodes well */
3231 if (purple_version_check(2, 0, 2) == NULL) { 3279 if (purple_version_check(2, 0, 2) == NULL) {
3232 if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { 3280 if ((buddy == NULL) && (gtkconv->webview != NULL)) {
3233 buddy = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); 3281 buddy = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy");
3234 } 3282 }
3235 3283
3236 if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { 3284 if ((buddy == NULL) && (gtkconv->webview != NULL)) {
3237 buddy = purple_buddy_new(conv->account, conv->name, NULL); 3285 buddy = purple_buddy_new(account, purple_conversation_get_name(conv), NULL);
3238 purple_blist_node_set_flags((PurpleBlistNode *)buddy, 3286 purple_blist_node_set_flags((PurpleBlistNode *)buddy,
3239 PURPLE_BLIST_NODE_FLAG_NO_SAVE); 3287 PURPLE_BLIST_NODE_FLAG_NO_SAVE);
3240 g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_buddy", 3288 g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_buddy",
3241 buddy, (GDestroyNotify)purple_buddy_destroy); 3289 buddy, (GDestroyNotify)purple_buddy_destroy);
3242 } 3290 }
3243 } 3291 }
3244 } 3292 }
3245 3293
3254 pidgin_blist_make_buddy_menu(menu, buddy, TRUE); 3302 pidgin_blist_make_buddy_menu(menu, buddy, TRUE);
3255 else if (chat) { 3303 else if (chat) {
3256 /* XXX: */ 3304 /* XXX: */
3257 } 3305 }
3258 } else if (node) { 3306 } else if (node) {
3259 if (purple_account_is_connected(conv->account)) 3307 if (purple_account_is_connected(account))
3260 pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node); 3308 pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account), node);
3261 pidgin_append_blist_node_extended_menu(menu, node); 3309 pidgin_append_blist_node_extended_menu(menu, node);
3262 } 3310 }
3263 3311
3264 if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL) { 3312 if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL) {
3265 ret = FALSE; 3313 ret = FALSE;
3646 #endif 3694 #endif
3647 3695
3648 static void 3696 static void
3649 update_typing_message(PidginConversation *gtkconv, const char *message) 3697 update_typing_message(PidginConversation *gtkconv, const char *message)
3650 { 3698 {
3699 /* TODO WEBKIT: this is not handled at all */
3700 #if 0
3651 GtkTextBuffer *buffer; 3701 GtkTextBuffer *buffer;
3652 GtkTextMark *stmark, *enmark; 3702 GtkTextMark *stmark, *enmark;
3653 3703
3654 if (g_object_get_data(G_OBJECT(gtkconv->imhtml), "disable-typing-notification")) 3704 if (g_object_get_data(G_OBJECT(gtkconv->imhtml), "disable-typing-notification"))
3655 return; 3705 return;
3678 gtk_text_buffer_create_mark(buffer, "typing-notification-start", &iter, TRUE); 3728 gtk_text_buffer_create_mark(buffer, "typing-notification-start", &iter, TRUE);
3679 gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, message, -1, "TYPING-NOTIFICATION", NULL); 3729 gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, message, -1, "TYPING-NOTIFICATION", NULL);
3680 gtk_text_buffer_get_end_iter(buffer, &iter); 3730 gtk_text_buffer_get_end_iter(buffer, &iter);
3681 gtk_text_buffer_create_mark(buffer, "typing-notification-end", &iter, TRUE); 3731 gtk_text_buffer_create_mark(buffer, "typing-notification-end", &iter, TRUE);
3682 } 3732 }
3733 #endif /* if 0 */
3683 } 3734 }
3684 3735
3685 static void 3736 static void
3686 update_typing_icon(PidginConversation *gtkconv) 3737 update_typing_icon(PidginConversation *gtkconv)
3687 { 3738 {
3734 return FALSE; 3785 return FALSE;
3735 3786
3736 if (win->menu.send_to == NULL) 3787 if (win->menu.send_to == NULL)
3737 return FALSE; 3788 return FALSE;
3738 3789
3739 if (!(b = purple_find_buddy(account, conv->name))) 3790 if (!(b = purple_find_buddy(account, purple_conversation_get_name(conv))))
3740 return FALSE; 3791 return FALSE;
3741 3792
3742 3793
3743 gtk_widget_show(win->menu.send_to); 3794 gtk_widget_show(win->menu.send_to);
3744 3795
3894 win->menu.send_to, 2); 3945 win->menu.send_to, 2);
3895 gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.send_to), menu); 3946 gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.send_to), menu);
3896 3947
3897 gtk_widget_show(menu); 3948 gtk_widget_show(menu);
3898 3949
3899 if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM) { 3950 if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM) {
3900 buds = purple_find_buddies(gtkconv->active_conv->account, gtkconv->active_conv->name); 3951 buds = purple_find_buddies(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv));
3901 3952
3902 if (buds == NULL) 3953 if (buds == NULL)
3903 { 3954 {
3904 /* The user isn't on the buddy list. So we don't create any sendto menu. */ 3955 /* The user isn't on the buddy list. So we don't create any sendto menu. */
3905 } 3956 }
3919 3970
3920 if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) 3971 if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
3921 continue; 3972 continue;
3922 3973
3923 account = purple_buddy_get_account(buddy); 3974 account = purple_buddy_get_account(buddy);
3924 if (purple_account_is_connected(account) || account == gtkconv->active_conv->account) 3975 /* TODO WEBKIT: (I'm not actually sure if this is webkit-related --Mark Doliner) */
3976 if (purple_account_is_connected(account) /*|| account == purple_conversation_get_account(gtkconv->active_conv)*/)
3925 { 3977 {
3926 /* Use the PurplePresence to get unique buddies. */ 3978 /* Use the PurplePresence to get unique buddies. */
3927 PurplePresence *presence = purple_buddy_get_presence(buddy); 3979 PurplePresence *presence = purple_buddy_get_presence(buddy);
3928 if (!g_list_find_custom(list, presence, (GCompareFunc)compare_buddy_presence)) 3980 if (!g_list_find_custom(list, presence, (GCompareFunc)compare_buddy_presence))
3929 list = g_list_prepend(list, presence); 3981 list = g_list_prepend(list, presence);
3978 } 4030 }
3979 4031
3980 static void 4032 static void
3981 deleting_chat_buddy_cb(PurpleConvChatBuddy *cb) 4033 deleting_chat_buddy_cb(PurpleConvChatBuddy *cb)
3982 { 4034 {
3983 if (cb->ui_data) { 4035 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
3984 GtkTreeRowReference *ref = cb->ui_data; 4036
4037 if (ref) {
3985 gtk_tree_row_reference_free(ref); 4038 gtk_tree_row_reference_free(ref);
3986 cb->ui_data = NULL; 4039 purple_conv_chat_cb_set_ui_data(cb, NULL);
3987 } 4040 }
3988 } 4041 }
3989 4042
3990 static void 4043 static void
3991 add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const char *old_name) 4044 add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const char *old_name)
4000 GtkTreePath *newpath; 4053 GtkTreePath *newpath;
4001 const char *stock; 4054 const char *stock;
4002 GtkTreeIter iter; 4055 GtkTreeIter iter;
4003 gboolean is_me = FALSE; 4056 gboolean is_me = FALSE;
4004 gboolean is_buddy; 4057 gboolean is_buddy;
4005 gchar *tmp, *alias_key, *name, *alias; 4058 const gchar *name, *alias;
4059 gchar *tmp, *alias_key;
4006 PurpleConvChatBuddyFlags flags; 4060 PurpleConvChatBuddyFlags flags;
4007 GdkColor *color = NULL; 4061 GdkColor *color = NULL;
4008 4062
4009 alias = cb->alias; 4063 alias = purple_conv_chat_cb_get_alias(cb);
4010 name = cb->name; 4064 name = purple_conv_chat_cb_get_name(cb);
4011 flags = cb->flags; 4065 flags = purple_conv_chat_cb_get_flags(cb);
4012 4066
4013 chat = PURPLE_CONV_CHAT(conv); 4067 chat = PURPLE_CONV_CHAT(conv);
4014 gtkconv = PIDGIN_CONVERSATION(conv); 4068 gtkconv = PIDGIN_CONVERSATION(conv);
4015 gtkchat = gtkconv->u.chat; 4069 gtkchat = gtkconv->u.chat;
4016 gc = purple_conversation_get_gc(conv); 4070 gc = purple_conversation_get_gc(conv);
4017 4071
4018 if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl))) 4072 if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
4019 return; 4073 return;
4020 4074
4021 tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 4075 tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
4022 ls = GTK_LIST_STORE(tm); 4076 ls = GTK_LIST_STORE(tm);
4023 4077
4024 stock = get_chat_buddy_status_icon(chat, name, flags); 4078 stock = get_chat_buddy_status_icon(chat, name, flags);
4025 4079
4026 if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name))) 4080 if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(purple_conversation_get_account(conv), old_name != NULL ? old_name : name)))
4027 is_me = TRUE; 4081 is_me = TRUE;
4028 4082
4029 is_buddy = cb->buddy; 4083 is_buddy = purple_conv_chat_cb_is_buddy(cb);
4030 4084
4031 tmp = g_utf8_casefold(alias, -1); 4085 tmp = g_utf8_casefold(alias, -1);
4032 alias_key = g_utf8_collate_key(tmp, -1); 4086 alias_key = g_utf8_collate_key(tmp, -1);
4033 g_free(tmp); 4087 g_free(tmp);
4034 4088
4035 if (is_me) { 4089 if (is_me) {
4090 #if 0
4091 /* TODO WEBKIT: No tags in webkit stuff, yet. */
4036 GtkTextTag *tag = gtk_text_tag_table_lookup( 4092 GtkTextTag *tag = gtk_text_tag_table_lookup(
4037 gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->imhtml)->text_buffer), 4093 gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->webview)->text_buffer),
4038 "send-name"); 4094 "send-name");
4039 g_object_get(tag, "foreground-gdk", &color, NULL); 4095 g_object_get(tag, "foreground-gdk", &color, NULL);
4096 #endif /* if 0 */
4040 } else { 4097 } else {
4041 GtkTextTag *tag; 4098 GtkTextTag *tag;
4042 if ((tag = get_buddy_tag(conv, name, 0, FALSE))) 4099 if ((tag = get_buddy_tag(conv, name, 0, FALSE)))
4043 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); 4100 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL);
4044 if ((tag = get_buddy_tag(conv, name, PURPLE_MESSAGE_NICK, FALSE))) 4101 if ((tag = get_buddy_tag(conv, name, PURPLE_MESSAGE_NICK, FALSE)))
4062 CHAT_USERS_FLAGS_COLUMN, flags, 4119 CHAT_USERS_FLAGS_COLUMN, flags,
4063 CHAT_USERS_COLOR_COLUMN, color, 4120 CHAT_USERS_COLOR_COLUMN, color,
4064 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, 4121 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
4065 -1); 4122 -1);
4066 4123
4067 if (cb->ui_data) { 4124 if (purple_conv_chat_cb_get_ui_data(cb)) {
4068 GtkTreeRowReference *ref = cb->ui_data; 4125 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
4069 gtk_tree_row_reference_free(ref); 4126 gtk_tree_row_reference_free(ref);
4070 } 4127 }
4071 4128
4072 newpath = gtk_tree_model_get_path(tm, &iter); 4129 newpath = gtk_tree_model_get_path(tm, &iter);
4073 cb->ui_data = gtk_tree_row_reference_new(tm, newpath); 4130 purple_conv_chat_cb_set_ui_data(cb, gtk_tree_row_reference_new(tm, newpath));
4074 gtk_tree_path_free(newpath); 4131 gtk_tree_path_free(newpath);
4075 4132
4076 if (is_me && color) 4133 if (is_me && color)
4077 gdk_color_free(color); 4134 gdk_color_free(color);
4078 g_free(alias_key); 4135 g_free(alias_key);
4098 * @param name The buddy name or alias or slash command name that we're 4155 * @param name The buddy name or alias or slash command name that we're
4099 * checking for a match. 4156 * checking for a match.
4100 */ 4157 */
4101 static void 4158 static void
4102 tab_complete_process_item(int *most_matched, const char *entered, gsize entered_bytes, char **partial, char *nick_partial, 4159 tab_complete_process_item(int *most_matched, const char *entered, gsize entered_bytes, char **partial, char *nick_partial,
4103 GList **matches, char *name) 4160 GList **matches, const char *name)
4104 { 4161 {
4105 memcpy(nick_partial, name, entered_bytes); 4162 memcpy(nick_partial, name, entered_bytes);
4106 if (purple_utf8_strcasecmp(nick_partial, entered)) 4163 if (purple_utf8_strcasecmp(nick_partial, entered))
4107 return; 4164 return;
4108 4165
4220 int f; 4277 int f;
4221 4278
4222 /* Users */ 4279 /* Users */
4223 for (; l != NULL; l = l->next) { 4280 for (; l != NULL; l = l->next) {
4224 tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, 4281 tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial,
4225 &matches, ((PurpleConvChatBuddy *)l->data)->name); 4282 &matches, purple_conv_chat_cb_get_name((PurpleConvChatBuddy *)l->data));
4226 } 4283 }
4227 4284
4228 4285
4229 /* Aliases */ 4286 /* Aliases */
4230 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 4287 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
4320 char *new_topic; 4377 char *new_topic;
4321 const char *current_topic; 4378 const char *current_topic;
4322 4379
4323 gc = purple_conversation_get_gc(conv); 4380 gc = purple_conversation_get_gc(conv);
4324 4381
4325 if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl))) 4382 if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
4326 return; 4383 return;
4327 4384
4328 if(prpl_info->set_chat_topic == NULL) 4385 if(prpl_info->set_chat_topic == NULL)
4329 return; 4386 return;
4330 4387
4395 static void 4452 static void
4396 update_chat_alias(PurpleBuddy *buddy, PurpleConversation *conv, PurpleConnection *gc, PurplePluginProtocolInfo *prpl_info) 4453 update_chat_alias(PurpleBuddy *buddy, PurpleConversation *conv, PurpleConnection *gc, PurplePluginProtocolInfo *prpl_info)
4397 { 4454 {
4398 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); 4455 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
4399 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); 4456 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
4457 PurpleAccount *account = purple_conversation_get_account(conv);
4400 GtkTreeModel *model; 4458 GtkTreeModel *model;
4401 char *normalized_name; 4459 char *normalized_name;
4402 GtkTreeIter iter; 4460 GtkTreeIter iter;
4403 int f; 4461 int f;
4404 4462
4409 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkconv->u.chat->list)); 4467 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkconv->u.chat->list));
4410 4468
4411 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 4469 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
4412 return; 4470 return;
4413 4471
4414 normalized_name = g_strdup(purple_normalize(conv->account, buddy->name)); 4472 normalized_name = g_strdup(purple_normalize(account, buddy->name));
4415 4473
4416 do { 4474 do {
4417 char *name; 4475 char *name;
4418 4476
4419 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1); 4477 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1);
4420 4478
4421 if (!strcmp(normalized_name, purple_normalize(conv->account, name))) { 4479 if (!strcmp(normalized_name, purple_normalize(account, name))) {
4422 const char *alias = name; 4480 const char *alias = name;
4423 char *tmp; 4481 char *tmp;
4424 char *alias_key = NULL; 4482 char *alias_key = NULL;
4425 PurpleBuddy *buddy2; 4483 PurpleBuddy *buddy2;
4426 4484
4427 if (strcmp(chat->nick, purple_normalize(conv->account, name))) { 4485 if (strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, name))) {
4428 /* This user is not me, so look into updating the alias. */ 4486 /* This user is not me, so look into updating the alias. */
4429 4487
4430 if ((buddy2 = purple_find_buddy(conv->account, name)) != NULL) { 4488 if ((buddy2 = purple_find_buddy(account, name)) != NULL) {
4431 alias = purple_buddy_get_contact_alias(buddy2); 4489 alias = purple_buddy_get_contact_alias(buddy2);
4432 } 4490 }
4433 4491
4434 tmp = g_utf8_casefold(alias, -1); 4492 tmp = g_utf8_casefold(alias, -1);
4435 alias_key = g_utf8_collate_key(tmp, -1); 4493 alias_key = g_utf8_collate_key(tmp, -1);
4462 g_return_if_fail(node != NULL); 4520 g_return_if_fail(node != NULL);
4463 g_return_if_fail(conv != NULL); 4521 g_return_if_fail(conv != NULL);
4464 4522
4465 gc = purple_conversation_get_gc(conv); 4523 gc = purple_conversation_get_gc(conv);
4466 g_return_if_fail(gc != NULL); 4524 g_return_if_fail(gc != NULL);
4467 g_return_if_fail(gc->prpl != NULL); 4525 g_return_if_fail(purple_connection_get_prpl(gc) != NULL);
4468 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 4526 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
4469 4527
4470 if (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME) 4528 if (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)
4471 return; 4529 return;
4472 4530
4473 if (PURPLE_BLIST_NODE_IS_CONTACT(node)) 4531 if (PURPLE_BLIST_NODE_IS_CONTACT(node))
4512 model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list)); 4570 model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list));
4513 4571
4514 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 4572 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
4515 return; 4573 return;
4516 4574
4517 normalized_name = g_strdup(purple_normalize(conv->account, buddy->name)); 4575 normalized_name = g_strdup(purple_normalize(purple_conversation_get_account(conv), buddy->name));
4518 4576
4519 do { 4577 do {
4520 char *name; 4578 char *name;
4521 4579
4522 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1); 4580 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1);
4523 4581
4524 if (!strcmp(normalized_name, purple_normalize(conv->account, name))) { 4582 if (!strcmp(normalized_name, purple_normalize(purple_conversation_get_account(conv), name))) {
4525 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 4583 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
4526 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1); 4584 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1);
4527 g_free(name); 4585 g_free(name);
4528 break; 4586 break;
4529 } 4587 }
4598 GtkTextIter iter; 4656 GtkTextIter iter;
4599 int lines; 4657 int lines;
4600 GdkRectangle oneline; 4658 GdkRectangle oneline;
4601 int height, diff; 4659 int height, diff;
4602 int pad_top, pad_inside, pad_bottom; 4660 int pad_top, pad_inside, pad_bottom;
4603 int total_height = (gtkconv->imhtml->allocation.height + gtkconv->entry->allocation.height); 4661 int total_height = (gtkconv->webview->allocation.height + gtkconv->entry->allocation.height);
4604 int max_height = total_height / 2; 4662 int max_height = total_height / 2;
4605 int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines"); 4663 int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines");
4606 int min_height; 4664 int min_height;
4607 gboolean interior_focus; 4665 gboolean interior_focus;
4608 int focus_width; 4666 int focus_width;
4671 static void 4729 static void
4672 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox) 4730 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox)
4673 { 4731 {
4674 PurpleConversation *conv = gtkconv->active_conv; 4732 PurpleConversation *conv = gtkconv->active_conv;
4675 PurpleConnection *gc = purple_conversation_get_gc(conv); 4733 PurpleConnection *gc = purple_conversation_get_gc(conv);
4676 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 4734 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
4677 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) 4735 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC)
4678 { 4736 {
4679 GtkWidget *hbox, *label; 4737 GtkWidget *hbox, *label;
4680 PidginChatPane *gtkchat = gtkconv->u.chat; 4738 PidginChatPane *gtkchat = gtkconv->u.chat;
4681 4739
4712 PurpleBlistNode *node; 4770 PurpleBlistNode *node;
4713 PurplePluginProtocolInfo *prpl_info; 4771 PurplePluginProtocolInfo *prpl_info;
4714 PurpleAccount *account = purple_conversation_get_account(conv); 4772 PurpleAccount *account = purple_conversation_get_account(conv);
4715 char *who = NULL; 4773 char *who = NULL;
4716 4774
4717 if (account->gc == NULL) 4775 if (purple_account_get_connection(account) == NULL)
4718 return FALSE; 4776 return FALSE;
4719 4777
4720 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path)) 4778 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path))
4721 return FALSE; 4779 return FALSE;
4722 4780
4723 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1); 4781 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1);
4724 4782
4725 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl); 4783 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account)));
4726 node = (PurpleBlistNode*)(purple_find_buddy(conv->account, who)); 4784 node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), who));
4727 if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) 4785 if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME))
4728 pidgin_blist_draw_tooltip(node, gtkconv->infopane); 4786 pidgin_blist_draw_tooltip(node, gtkconv->infopane);
4729 4787
4730 g_free(who); 4788 g_free(who);
4731 return FALSE; 4789 return FALSE;
4822 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE); 4880 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE);
4823 gtk_widget_show(list); 4881 gtk_widget_show(list);
4824 4882
4825 gtkchat->list = list; 4883 gtkchat->list = list;
4826 4884
4827 gtk_box_pack_start(GTK_BOX(lbox), 4885 gtk_box_pack_start(GTK_BOX(lbox),
4828 pidgin_make_scrollable(list, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1), 4886 pidgin_make_scrollable(list, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1),
4829 TRUE, TRUE, 0); 4887 TRUE, TRUE, 0);
4830 } 4888 }
4831 4889
4832 static gboolean 4890 static gboolean
4836 PurpleConversation *conv; 4894 PurpleConversation *conv;
4837 PidginConversation *gtkconv = userdata; 4895 PidginConversation *gtkconv = userdata;
4838 4896
4839 conv = gtkconv->active_conv; 4897 conv = gtkconv->active_conv;
4840 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 4898 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
4841 node = (PurpleBlistNode*)(purple_blist_find_chat(conv->account, conv->name)); 4899 node = (PurpleBlistNode*)(purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv)));
4842 if (!node) 4900 if (!node)
4843 node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); 4901 node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat");
4844 } else { 4902 } else {
4845 node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name)); 4903 node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)));
4846 #if 0 4904 #if 0
4847 /* Using the transient blist nodes to show the tooltip doesn't quite work yet. */ 4905 /* Using the transient blist nodes to show the tooltip doesn't quite work yet. */
4848 if (!node) 4906 if (!node)
4849 node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); 4907 node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy");
4850 #endif 4908 #endif
4851 } 4909 }
4852 4910
4853 if (node) 4911 if (node)
4854 pidgin_blist_draw_tooltip(node, gtkconv->infopane); 4912 pidgin_blist_draw_tooltip(node, gtkconv->infopane);
4859 static gboolean 4917 static gboolean
4860 pidgin_conv_end_quickfind(PidginConversation *gtkconv) 4918 pidgin_conv_end_quickfind(PidginConversation *gtkconv)
4861 { 4919 {
4862 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); 4920 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL);
4863 4921
4864 gtk_imhtml_search_clear(GTK_IMHTML(gtkconv->imhtml)); 4922 webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(gtkconv->webview));
4865 gtk_widget_hide_all(gtkconv->quickfind.container); 4923 gtk_widget_hide_all(gtkconv->quickfind.container);
4866 4924
4867 gtk_widget_grab_focus(gtkconv->entry); 4925 gtk_widget_grab_focus(gtkconv->entry);
4868 return TRUE; 4926 return TRUE;
4869 } 4927 }
4872 quickfind_process_input(GtkWidget *entry, GdkEventKey *event, PidginConversation *gtkconv) 4930 quickfind_process_input(GtkWidget *entry, GdkEventKey *event, PidginConversation *gtkconv)
4873 { 4931 {
4874 switch (event->keyval) { 4932 switch (event->keyval) {
4875 case GDK_Return: 4933 case GDK_Return:
4876 case GDK_KP_Enter: 4934 case GDK_KP_Enter:
4877 if (gtk_imhtml_search_find(GTK_IMHTML(gtkconv->imhtml), gtk_entry_get_text(GTK_ENTRY(entry)))) { 4935 if (webkit_web_view_search_text(WEBKIT_WEB_VIEW(gtkconv->webview), gtk_entry_get_text(GTK_ENTRY(entry)), FALSE, TRUE, TRUE)) {
4878 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); 4936 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL);
4879 } else { 4937 } else {
4880 GdkColor col; 4938 GdkColor col;
4881 col.red = 0xffff; 4939 col.red = 0xffff;
4882 col.green = 0xafff; 4940 col.green = 0xafff;
4922 G_CALLBACK(pidgin_conv_end_quickfind), gtkconv); 4980 G_CALLBACK(pidgin_conv_end_quickfind), gtkconv);
4923 } 4981 }
4924 4982
4925 /* }}} */ 4983 /* }}} */
4926 4984
4985 static char *
4986 replace_header_tokens(PurpleConversation *conv, const char *text)
4987 {
4988 PurpleAccount *account = purple_conversation_get_account(conv);
4989 GString *str;
4990 const char *cur = text;
4991 const char *prev = cur;
4992
4993 if (text == NULL || *text == '\0')
4994 return NULL;
4995
4996 str = g_string_new(NULL);
4997 while ((cur = strchr(cur, '%'))) {
4998 const char *replace = NULL;
4999 const char *fin = NULL;
5000
5001 if (g_str_has_prefix(cur, "%chatName%")) {
5002 replace = purple_conversation_get_name(conv);
5003
5004 } else if (g_str_has_prefix(cur, "%sourceName%")) {
5005 replace = purple_account_get_alias(account);
5006 if (replace == NULL)
5007 replace = purple_account_get_username(account);
5008
5009 } else if (g_str_has_prefix(cur, "%destinationName%")) {
5010 PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
5011 if (buddy) {
5012 replace = purple_buddy_get_alias(buddy);
5013 } else {
5014 replace = purple_conversation_get_name(conv);
5015 }
5016
5017 } else if (g_str_has_prefix(cur, "%incomingIconPath%")) {
5018 PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
5019 if (icon)
5020 replace = purple_buddy_icon_get_full_path(icon);
5021
5022 } else if (g_str_has_prefix(cur, "%outgoingIconPath%")) {
5023 replace = purple_account_get_buddy_icon_path(account);
5024
5025 } else if (g_str_has_prefix(cur, "%timeOpened")) {
5026 const char *tmp = cur + strlen("%timeOpened");
5027 char *format = NULL;
5028 if (*tmp == '{') {
5029 const char *end;
5030 tmp++;
5031 end = strstr(tmp, "}%");
5032 if (!end) /* Invalid string */
5033 continue;
5034 format = g_strndup(tmp, end - tmp);
5035 fin = end + 1;
5036 }
5037 replace = purple_utf8_strftime(format ? format : "%X", NULL);
5038 g_free(format);
5039
5040 } else {
5041 continue;
5042 }
5043
5044 /* Here we have a replacement to make */
5045 g_string_append_len(str, prev, cur - prev);
5046 if (replace)
5047 g_string_append(str, replace);
5048
5049 /* And update the pointers */
5050 if (fin) {
5051 prev = cur = fin + 1;
5052 } else {
5053 prev = cur = strchr(cur + 1, '%') + 1;
5054 }
5055 }
5056
5057 /* And wrap it up */
5058 g_string_append(str, prev);
5059 return g_string_free(str, FALSE);
5060 }
5061
5062 static char *
5063 replace_template_tokens(PidginConvTheme *theme, const char *header, const char *footer)
5064 {
5065 GString *str;
5066 const char *text;
5067 char **ms;
5068 char *path;
5069
5070 text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN);
5071 if (text == NULL)
5072 return NULL;
5073
5074 ms = g_strsplit(text, "%@", 6);
5075 if (ms[0] == NULL || ms[1] == NULL || ms[2] == NULL || ms[3] == NULL || ms[4] == NULL || ms[5] == NULL) {
5076 g_strfreev(ms);
5077 return NULL;
5078 }
5079
5080 str = g_string_new(NULL);
5081
5082 g_string_append(str, ms[0]);
5083 g_string_append(str, "file://");
5084 path = pidgin_conversation_theme_get_template_path(theme);
5085 g_string_append(str, path);
5086 g_free(path);
5087
5088 g_string_append(str, ms[1]);
5089
5090 text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS);
5091 g_string_append(str, text);
5092
5093 g_string_append(str, ms[2]);
5094
5095 g_string_append(str, "file://");
5096 path = pidgin_conversation_theme_get_css_path(theme);
5097 g_string_append(str, path);
5098 g_free(path);
5099
5100 g_string_append(str, ms[3]);
5101 if (header)
5102 g_string_append(str, header);
5103 g_string_append(str, ms[4]);
5104 if (footer)
5105 g_string_append(str, footer);
5106 g_string_append(str, ms[5]);
5107
5108 g_strfreev(ms);
5109
5110 return g_string_free(str, FALSE);
5111 }
5112
5113 static void
5114 set_theme_webkit_settings(WebKitWebView *webview, PidginConvTheme *theme)
5115 {
5116 WebKitWebSettings *settings;
5117 const GValue *val;
5118
5119 g_object_get(G_OBJECT(webview), "settings", &settings, NULL);
5120
5121 val = pidgin_conversation_theme_lookup(theme, "DefaultFontFamily", TRUE);
5122 if (val && G_VALUE_HOLDS_STRING(val))
5123 g_object_set(G_OBJECT(settings), "default-font-family", g_value_get_string(val), NULL);
5124
5125 val = pidgin_conversation_theme_lookup(theme, "DefaultFontSize", TRUE);
5126 if (val && G_VALUE_HOLDS_INT(val))
5127 g_object_set(G_OBJECT(settings), "default-font-size", GINT_TO_POINTER(g_value_get_int(val)), NULL);
5128
5129 val = pidgin_conversation_theme_lookup(theme, "DefaultBackgroundIsTransparent", TRUE);
5130 if (val && G_VALUE_HOLDS_BOOLEAN(val))
5131 /* this does not work :( */
5132 webkit_web_view_set_transparent(webview, g_value_get_boolean(val));
5133 }
5134
5135 static void
5136 conv_variant_changed_cb(GObject *gobject, GParamSpec *pspec, gpointer user_data)
5137 {
5138 PidginConversation *gtkconv = user_data;
5139 const char *path;
5140 char *js;
5141
5142 path = pidgin_conversation_theme_get_css_path(PIDGIN_CONV_THEME(gobject));
5143 js = g_strdup_printf("setStylesheet(\"mainStyle\", \"file://%s\");", path);
5144 gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), js);
5145 g_free(js);
5146 }
5147
4927 static GtkWidget * 5148 static GtkWidget *
4928 setup_common_pane(PidginConversation *gtkconv) 5149 setup_common_pane(PidginConversation *gtkconv)
4929 { 5150 {
4930 GtkWidget *vbox, *frame, *imhtml_sw, *event_box; 5151 GtkWidget *vbox, *frame, *webview_sw, *event_box;
4931 GtkCellRenderer *rend; 5152 GtkCellRenderer *rend;
4932 GtkTreePath *path; 5153 GtkTreePath *path;
4933 PurpleConversation *conv = gtkconv->active_conv; 5154 PurpleConversation *conv = gtkconv->active_conv;
4934 PurpleBuddy *buddy; 5155 PurpleBuddy *buddy;
4935 gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT); 5156 gboolean chat = (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT);
4936 int buddyicon_size = 0; 5157 int buddyicon_size = 0;
5158 char *header, *footer;
5159 char *template;
4937 5160
4938 /* Setup the top part of the pane */ 5161 /* Setup the top part of the pane */
4939 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 5162 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4940 gtk_widget_show(vbox); 5163 gtk_widget_show(vbox);
4941 5164
5021 rend = gtk_cell_renderer_pixbuf_new(); 5244 rend = gtk_cell_renderer_pixbuf_new();
5022 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE); 5245 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE);
5023 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_EMBLEM_COLUMN, NULL); 5246 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_EMBLEM_COLUMN, NULL);
5024 g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL); 5247 g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL);
5025 5248
5026 /* Setup the gtkimhtml widget */ 5249 /* Setup the webkit widget */
5027 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw); 5250 frame = pidgin_create_webview(FALSE, &gtkconv->webview, NULL, &webview_sw);
5028 gtk_widget_set_size_request(gtkconv->imhtml, -1, 0); 5251 gtk_widget_set_size_request(gtkconv->webview, -1, 0);
5252
5253 header = replace_header_tokens(conv,
5254 pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER));
5255 footer = replace_header_tokens(conv,
5256 pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER));
5257 template = replace_template_tokens(gtkconv->theme, header, footer);
5258 g_free(header);
5259 g_free(footer);
5260
5261 if (template != NULL) {
5262 char *basedir;
5263 char *baseuri;
5264
5265 purple_debug_info("webkit", "template: %s\n", template);
5266
5267 set_theme_webkit_settings(WEBKIT_WEB_VIEW(gtkconv->webview), gtkconv->theme);
5268
5269 basedir = pidgin_conversation_theme_get_template_path(gtkconv->theme);
5270 baseuri = g_strdup_printf("file://%s", basedir);
5271 webkit_web_view_load_string(WEBKIT_WEB_VIEW(gtkconv->webview), template, "text/html", "UTF-8", baseuri);
5272
5273 if (chat)
5274 gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), "document.getElementById('Chat').className = 'groupchat'");
5275
5276 g_signal_connect(G_OBJECT(gtkconv->theme), "notify::variant",
5277 G_CALLBACK(conv_variant_changed_cb), gtkconv);
5278
5279 g_free(basedir);
5280 g_free(baseuri);
5281 g_free(template);
5282 }
5283
5029 if (chat) { 5284 if (chat) {
5030 GtkWidget *hpaned; 5285 GtkWidget *hpaned;
5031 5286
5032 /* Add the topic */ 5287 /* Add the topic */
5033 setup_chat_topic(gtkconv, vbox); 5288 setup_chat_topic(gtkconv, vbox);
5041 /* Now add the userlist */ 5296 /* Now add the userlist */
5042 setup_chat_userlist(gtkconv, hpaned); 5297 setup_chat_userlist(gtkconv, hpaned);
5043 } else { 5298 } else {
5044 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); 5299 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
5045 } 5300 }
5046 gtk_widget_show(frame); 5301 gtk_widget_show_all(frame);
5047 5302
5048 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); 5303 gtk_widget_set_name(gtkconv->webview, "pidgin_conv_webview");
5049 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE); 5304 g_object_set_data(G_OBJECT(gtkconv->webview), "gtkconv", gtkconv);
5050 g_object_set_data(G_OBJECT(gtkconv->imhtml), "gtkconv", gtkconv); 5305
5051 5306 g_signal_connect_after(G_OBJECT(gtkconv->webview), "button_press_event",
5052 g_object_set(G_OBJECT(imhtml_sw), "vscrollbar-policy", GTK_POLICY_ALWAYS, NULL);
5053
5054 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
5055 G_CALLBACK(entry_stop_rclick_cb), NULL); 5307 G_CALLBACK(entry_stop_rclick_cb), NULL);
5056 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", 5308 g_signal_connect(G_OBJECT(gtkconv->webview), "key_press_event",
5057 G_CALLBACK(refocus_entry_cb), gtkconv); 5309 G_CALLBACK(refocus_entry_cb), gtkconv);
5058 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", 5310 g_signal_connect(G_OBJECT(gtkconv->webview), "key_release_event",
5059 G_CALLBACK(refocus_entry_cb), gtkconv); 5311 G_CALLBACK(refocus_entry_cb), gtkconv);
5060 5312
5061 pidgin_conv_setup_quickfind(gtkconv, vbox); 5313 pidgin_conv_setup_quickfind(gtkconv, vbox);
5062 5314
5063 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 5315 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
5069 gtk_box_pack_start(GTK_BOX(gtkconv->lower_hbox), frame, TRUE, TRUE, 0); 5321 gtk_box_pack_start(GTK_BOX(gtkconv->lower_hbox), frame, TRUE, TRUE, 0);
5070 gtk_widget_show(frame); 5322 gtk_widget_show(frame);
5071 5323
5072 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); 5324 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
5073 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), 5325 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
5074 purple_account_get_protocol_name(conv->account)); 5326 purple_account_get_protocol_name(purple_conversation_get_account(conv)));
5075 5327
5076 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", 5328 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
5077 G_CALLBACK(entry_popup_menu_cb), gtkconv); 5329 G_CALLBACK(entry_popup_menu_cb), gtkconv);
5078 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 5330 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event",
5079 G_CALLBACK(entry_key_press_cb), gtkconv); 5331 G_CALLBACK(entry_key_press_cb), gtkconv);
5116 PurpleConversation *conv = gtkconv->active_conv; 5368 PurpleConversation *conv = gtkconv->active_conv;
5117 PidginWindow *win = gtkconv->win; 5369 PidginWindow *win = gtkconv->win;
5118 PurpleConversation *c; 5370 PurpleConversation *c;
5119 PurpleAccount *convaccount = purple_conversation_get_account(conv); 5371 PurpleAccount *convaccount = purple_conversation_get_account(conv);
5120 PurpleConnection *gc = purple_account_get_connection(convaccount); 5372 PurpleConnection *gc = purple_account_get_connection(convaccount);
5121 PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL; 5373 PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL;
5122 5374
5123 if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) 5375 if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
5124 { 5376 {
5125 PurpleBlistNode *n = NULL; 5377 PurpleBlistNode *n = NULL;
5126 PurpleBuddy *b; 5378 PurpleBuddy *b;
5236 }; 5488 };
5237 5489
5238 static PidginConversation * 5490 static PidginConversation *
5239 pidgin_conv_find_gtkconv(PurpleConversation * conv) 5491 pidgin_conv_find_gtkconv(PurpleConversation * conv)
5240 { 5492 {
5241 PurpleBuddy *bud = purple_find_buddy(conv->account, conv->name); 5493 PurpleBuddy *bud = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
5242 PurpleContact *c; 5494 PurpleContact *c;
5243 PurpleBlistNode *cn, *bn; 5495 PurpleBlistNode *cn, *bn;
5244 5496
5245 if (!bud) 5497 if (!bud)
5246 return NULL; 5498 return NULL;
5251 cn = PURPLE_BLIST_NODE(c); 5503 cn = PURPLE_BLIST_NODE(c);
5252 for (bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) { 5504 for (bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) {
5253 PurpleBuddy *b = PURPLE_BUDDY(bn); 5505 PurpleBuddy *b = PURPLE_BUDDY(bn);
5254 PurpleConversation *conv; 5506 PurpleConversation *conv;
5255 if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, b->account))) { 5507 if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, b->account))) {
5256 if (conv->ui_data) 5508 if (PIDGIN_CONVERSATION(conv))
5257 return conv->ui_data; 5509 return PIDGIN_CONVERSATION(conv);
5258 } 5510 }
5259 } 5511 }
5260 5512
5261 return NULL; 5513 return NULL;
5262 } 5514 }
5294 return FALSE; 5546 return FALSE;
5295 } 5547 }
5296 5548
5297 static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv) 5549 static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv)
5298 { 5550 {
5551 /* TODO WEBKIT */
5552 #if 0
5299 static PangoFontDescription *font_desc = NULL; 5553 static PangoFontDescription *font_desc = NULL;
5300 static GdkColor *color = NULL; 5554 static GdkColor *color = NULL;
5301 static gboolean enable = TRUE; 5555 static gboolean enable = TRUE;
5302 5556
5303 if (font_desc == NULL) { 5557 if (font_desc == NULL) {
5324 g_object_set_data(G_OBJECT(widget), "disable-typing-notification", GINT_TO_POINTER(TRUE)); 5578 g_object_set_data(G_OBJECT(widget), "disable-typing-notification", GINT_TO_POINTER(TRUE));
5325 /* or may be 'gtkconv->disable_typing = TRUE;' instead? */ 5579 /* or may be 'gtkconv->disable_typing = TRUE;' instead? */
5326 } 5580 }
5327 5581
5328 g_signal_handlers_disconnect_by_func(G_OBJECT(widget), set_typing_font, gtkconv); 5582 g_signal_handlers_disconnect_by_func(G_OBJECT(widget), set_typing_font, gtkconv);
5583 #endif /* if 0 */
5329 } 5584 }
5330 5585
5331 /************************************************************************** 5586 /**************************************************************************
5332 * Conversation UI operations 5587 * Conversation UI operations
5333 **************************************************************************/ 5588 **************************************************************************/
5334 static void 5589 static void
5335 private_gtkconv_new(PurpleConversation *conv, gboolean hidden) 5590 private_gtkconv_new(PurpleConversation *conv, gboolean hidden)
5336 { 5591 {
5337 PidginConversation *gtkconv; 5592 PidginConversation *gtkconv;
5593 PurpleTheme *theme;
5338 PurpleConversationType conv_type = purple_conversation_get_type(conv); 5594 PurpleConversationType conv_type = purple_conversation_get_type(conv);
5339 GtkWidget *pane = NULL; 5595 GtkWidget *pane = NULL;
5340 GtkWidget *tab_cont; 5596 GtkWidget *tab_cont;
5341 PurpleBlistNode *convnode; 5597 PurpleBlistNode *convnode;
5342 PurpleValue *value; 5598 PurpleValue *value;
5343 5599
5344 if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) { 5600 if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) {
5345 conv->ui_data = gtkconv; 5601 purple_conversation_set_ui_data(conv, gtkconv);
5346 if (!g_list_find(gtkconv->convs, conv)) 5602 if (!g_list_find(gtkconv->convs, conv))
5347 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); 5603 gtkconv->convs = g_list_prepend(gtkconv->convs, conv);
5348 pidgin_conv_switch_active_conversation(conv); 5604 pidgin_conv_switch_active_conversation(conv);
5349 return; 5605 return;
5350 } 5606 }
5351 5607
5352 gtkconv = g_new0(PidginConversation, 1); 5608 gtkconv = g_new0(PidginConversation, 1);
5353 conv->ui_data = gtkconv; 5609 purple_conversation_set_ui_data(conv, gtkconv);
5354 gtkconv->active_conv = conv; 5610 gtkconv->active_conv = conv;
5355 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); 5611 gtkconv->convs = g_list_prepend(gtkconv->convs, conv);
5356 gtkconv->send_history = g_list_append(NULL, NULL); 5612 gtkconv->send_history = g_list_append(NULL, NULL);
5357 5613
5358 /* Setup some initial variables. */ 5614 /* Setup some initial variables. */
5359 gtkconv->tooltips = gtk_tooltips_new(); 5615 gtkconv->tooltips = gtk_tooltips_new();
5360 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; 5616 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
5361 gtkconv->unseen_count = 0; 5617 gtkconv->unseen_count = 0;
5618 theme = purple_theme_manager_find_theme(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/theme"), "conversation");
5619 if (!theme)
5620 theme = purple_theme_manager_find_theme("Default", "conversation");
5621 gtkconv->theme = PIDGIN_CONV_THEME(g_object_ref(theme));
5622 gtkconv->last_flags = 0;
5362 5623
5363 if (conv_type == PURPLE_CONV_TYPE_IM) { 5624 if (conv_type == PURPLE_CONV_TYPE_IM) {
5364 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); 5625 gtkconv->u.im = g_malloc0(sizeof(PidginImPane));
5365 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { 5626 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) {
5366 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); 5627 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane));
5367 } 5628 }
5368 pane = setup_common_pane(gtkconv); 5629 pane = setup_common_pane(gtkconv);
5369
5370 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml),
5371 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE);
5372 5630
5373 if (pane == NULL) { 5631 if (pane == NULL) {
5374 if (conv_type == PURPLE_CONV_TYPE_CHAT) 5632 if (conv_type == PURPLE_CONV_TYPE_CHAT)
5375 g_free(gtkconv->u.chat); 5633 g_free(gtkconv->u.chat);
5376 else if (conv_type == PURPLE_CONV_TYPE_IM) 5634 else if (conv_type == PURPLE_CONV_TYPE_IM)
5377 g_free(gtkconv->u.im); 5635 g_free(gtkconv->u.im);
5378 5636
5379 g_free(gtkconv); 5637 g_free(gtkconv);
5380 conv->ui_data = NULL; 5638 purple_conversation_set_ui_data(conv, NULL);
5381 return; 5639 return;
5382 } 5640 }
5383 5641
5384 /* Setup drag-and-drop */ 5642 /* Setup drag-and-drop */
5385 gtk_drag_dest_set(pane, 5643 gtk_drag_dest_set(pane,
5390 gtk_drag_dest_set(pane, 5648 gtk_drag_dest_set(pane,
5391 GTK_DEST_DEFAULT_MOTION | 5649 GTK_DEST_DEFAULT_MOTION |
5392 GTK_DEST_DEFAULT_DROP, 5650 GTK_DEST_DEFAULT_DROP,
5393 te, sizeof(te) / sizeof(GtkTargetEntry), 5651 te, sizeof(te) / sizeof(GtkTargetEntry),
5394 GDK_ACTION_COPY); 5652 GDK_ACTION_COPY);
5395 gtk_drag_dest_set(gtkconv->imhtml, 0, 5653 gtk_drag_dest_set(gtkconv->webview, 0,
5396 te, sizeof(te) / sizeof(GtkTargetEntry), 5654 te, sizeof(te) / sizeof(GtkTargetEntry),
5397 GDK_ACTION_COPY); 5655 GDK_ACTION_COPY);
5398 5656
5399 gtk_drag_dest_set(gtkconv->entry, 0, 5657 gtk_drag_dest_set(gtkconv->entry, 0,
5400 te, sizeof(te) / sizeof(GtkTargetEntry), 5658 te, sizeof(te) / sizeof(GtkTargetEntry),
5402 5660
5403 g_signal_connect(G_OBJECT(pane), "button_press_event", 5661 g_signal_connect(G_OBJECT(pane), "button_press_event",
5404 G_CALLBACK(ignore_middle_click), NULL); 5662 G_CALLBACK(ignore_middle_click), NULL);
5405 g_signal_connect(G_OBJECT(pane), "drag_data_received", 5663 g_signal_connect(G_OBJECT(pane), "drag_data_received",
5406 G_CALLBACK(conv_dnd_recv), gtkconv); 5664 G_CALLBACK(conv_dnd_recv), gtkconv);
5407 g_signal_connect(G_OBJECT(gtkconv->imhtml), "drag_data_received", 5665 g_signal_connect(G_OBJECT(gtkconv->webview), "drag_data_received",
5408 G_CALLBACK(conv_dnd_recv), gtkconv); 5666 G_CALLBACK(conv_dnd_recv), gtkconv);
5409 g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received", 5667 g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received",
5410 G_CALLBACK(conv_dnd_recv), gtkconv); 5668 G_CALLBACK(conv_dnd_recv), gtkconv);
5411 5669
5412 g_signal_connect(gtkconv->imhtml, "style-set", G_CALLBACK(set_typing_font), gtkconv); 5670 g_signal_connect(gtkconv->webview, "style-set", G_CALLBACK(set_typing_font), gtkconv);
5413 5671
5414 /* Setup the container for the tab. */ 5672 /* Setup the container for the tab. */
5415 gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 5673 gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
5416 g_object_set_data(G_OBJECT(tab_cont), "PidginConversation", gtkconv); 5674 g_object_set_data(G_OBJECT(tab_cont), "PidginConversation", gtkconv);
5417 gtk_container_set_border_width(GTK_CONTAINER(tab_cont), PIDGIN_HIG_BOX_SPACE); 5675 gtk_container_set_border_width(GTK_CONTAINER(tab_cont), PIDGIN_HIG_BOX_SPACE);
5437 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons")) 5695 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons"))
5438 gtk_widget_show(gtkconv->infopane_hbox); 5696 gtk_widget_show(gtkconv->infopane_hbox);
5439 else 5697 else
5440 gtk_widget_hide(gtkconv->infopane_hbox); 5698 gtk_widget_hide(gtkconv->infopane_hbox);
5441 5699
5442 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),
5443 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps"));
5444 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml),
5445 purple_account_get_protocol_name(conv->account));
5446 5700
5447 g_signal_connect_swapped(G_OBJECT(pane), "focus", 5701 g_signal_connect_swapped(G_OBJECT(pane), "focus",
5448 G_CALLBACK(gtk_widget_grab_focus), 5702 G_CALLBACK(gtk_widget_grab_focus),
5449 gtkconv->entry); 5703 gtkconv->entry);
5450 5704
5453 else 5707 else
5454 pidgin_conv_placement_place(gtkconv); 5708 pidgin_conv_placement_place(gtkconv);
5455 5709
5456 if (nick_colors == NULL) { 5710 if (nick_colors == NULL) {
5457 nbr_nick_colors = NUM_NICK_COLORS; 5711 nbr_nick_colors = NUM_NICK_COLORS;
5458 nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->imhtml)->base[GTK_STATE_NORMAL]); 5712 nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]);
5459 } 5713 }
5460 5714
5461 if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) 5715 if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
5462 pidgin_themes_smiley_themeize_custom(gtkconv->entry); 5716 pidgin_themes_smiley_themeize_custom(gtkconv->entry);
5463 } 5717 }
5464 5718
5465 static void 5719 static void
5466 pidgin_conv_new_hidden(PurpleConversation *conv) 5720 pidgin_conv_new_hidden(PurpleConversation *conv)
5566 g_list_free(gtkconv->send_history); 5820 g_list_free(gtkconv->send_history);
5567 5821
5568 if (gtkconv->attach.timer) { 5822 if (gtkconv->attach.timer) {
5569 g_source_remove(gtkconv->attach.timer); 5823 g_source_remove(gtkconv->attach.timer);
5570 } 5824 }
5825
5826 g_object_disconnect(G_OBJECT(gtkconv->theme), "any_signal::notify",
5827 conv_variant_changed_cb, gtkconv, NULL);
5828 g_object_unref(gtkconv->theme);
5571 5829
5572 g_free(gtkconv); 5830 g_free(gtkconv);
5573 } 5831 }
5574 5832
5575 5833
5594 } 5852 }
5595 5853
5596 purple_conversation_write(conv, who, message, flags, mtime); 5854 purple_conversation_write(conv, who, message, flags, mtime);
5597 } 5855 }
5598 5856
5857 #if 0
5599 static const char * 5858 static const char *
5600 get_text_tag_color(GtkTextTag *tag) 5859 get_text_tag_color(GtkTextTag *tag)
5601 { 5860 {
5602 GdkColor *color = NULL; 5861 GdkColor *color = NULL;
5603 gboolean set = FALSE; 5862 gboolean set = FALSE;
5674 } 5933 }
5675 } 5934 }
5676 5935
5677 return FALSE; 5936 return FALSE;
5678 } 5937 }
5938 #endif
5679 5939
5680 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, 5940 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag,
5681 gboolean create) 5941 gboolean create)
5682 { 5942 {
5943 /* TODO WEBKIT */
5944 #if 0
5683 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); 5945 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
5684 GtkTextTag *buddytag; 5946 GtkTextTag *buddytag;
5685 gchar *str; 5947 gchar *str;
5686 gboolean highlight = (flag & PURPLE_MESSAGE_NICK); 5948 gboolean highlight = (flag & PURPLE_MESSAGE_NICK);
5687 GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer; 5949 GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer;
5711 } 5973 }
5712 5974
5713 g_free(str); 5975 g_free(str);
5714 5976
5715 return buddytag; 5977 return buddytag;
5716 } 5978 #endif /* if 0 */
5717 5979 return NULL;
5980 }
5981
5982 #if 0
5718 static void pidgin_conv_calculate_newday(PidginConversation *gtkconv, time_t mtime) 5983 static void pidgin_conv_calculate_newday(PidginConversation *gtkconv, time_t mtime)
5719 { 5984 {
5720 struct tm *tm = localtime(&mtime); 5985 struct tm *tm = localtime(&mtime);
5721 5986
5722 tm->tm_hour = tm->tm_min = tm->tm_sec = 0; 5987 tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
5758 6023
5759 g_free(*str); 6024 g_free(*str);
5760 *str = ret; 6025 *str = ret;
5761 #endif 6026 #endif
5762 } 6027 }
6028 #endif
6029
6030 static char *
6031 replace_message_tokens(
6032 const char *text,
6033 PurpleConversation *conv,
6034 const char *name,
6035 const char *alias,
6036 const char *message,
6037 PurpleMessageFlags flags,
6038 time_t mtime)
6039 {
6040 GString *str;
6041 const char *cur = text;
6042 const char *prev = cur;
6043
6044 if (text == NULL)
6045 return g_strdup("");
6046
6047 str = g_string_new(NULL);
6048 while ((cur = strchr(cur, '%'))) {
6049 const char *replace = NULL;
6050 const char *fin = NULL;
6051
6052 if (g_str_has_prefix(cur, "%message%")) {
6053 replace = message;
6054
6055 } else if (g_str_has_prefix(cur, "%messageClasses%")) {
6056 replace = flags & PURPLE_MESSAGE_SEND ? "outgoing" :
6057 flags & PURPLE_MESSAGE_RECV ? "incoming" : "event";
6058
6059 } else if (g_str_has_prefix(cur, "%time")) {
6060 const char *tmp = cur + strlen("%time");
6061 char *format = NULL;
6062 if (*tmp == '{') {
6063 char *end;
6064 tmp++;
6065 end = strstr(tmp, "}%");
6066 if (!end) /* Invalid string */
6067 continue;
6068 format = g_strndup(tmp, end - tmp);
6069 fin = end + 1;
6070 }
6071 replace = purple_utf8_strftime(format ? format : "%X", NULL);
6072 g_free(format);
6073
6074 } else if (g_str_has_prefix(cur, "%userIconPath%")) {
6075 if (flags & PURPLE_MESSAGE_SEND) {
6076 if (purple_account_get_bool(purple_conversation_get_account(conv), "use-global-buddyicon", TRUE)) {
6077 replace = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon");
6078 } else {
6079 PurpleStoredImage *img = purple_buddy_icons_find_account_icon(purple_conversation_get_account(conv));
6080 replace = purple_imgstore_get_filename(img);
6081 }
6082 if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) {
6083 replace = g_build_filename("Outgoing", "buddy_icon.png", NULL);
6084 }
6085 } else if (flags & PURPLE_MESSAGE_RECV) {
6086 PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
6087 if (icon)
6088 replace = purple_buddy_icon_get_full_path(icon);
6089 if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) {
6090 replace = g_build_filename("Incoming", "buddy_icon.png", NULL);
6091 }
6092 }
6093
6094 } else if (g_str_has_prefix(cur, "%senderScreenName%")) {
6095 replace = name;
6096
6097 } else if (g_str_has_prefix(cur, "%sender%")) {
6098 replace = alias;
6099
6100 } else if (g_str_has_prefix(cur, "%service%")) {
6101 replace = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6102
6103 } else {
6104 cur++;
6105 continue;
6106 }
6107
6108 /* Here we have a replacement to make */
6109 g_string_append_len(str, prev, cur - prev);
6110 if (replace)
6111 g_string_append(str, replace);
6112
6113 /* And update the pointers */
6114 if (fin) {
6115 prev = cur = fin + 1;
6116 } else {
6117 prev = cur = strchr(cur + 1, '%') + 1;
6118 }
6119
6120 }
6121
6122 /* And wrap it up */
6123 g_string_append(str, prev);
6124
6125 return g_string_free(str, FALSE);
6126 }
5763 6127
5764 static void 6128 static void
5765 pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias, 6129 pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias,
5766 const char *message, PurpleMessageFlags flags, 6130 const char *message, PurpleMessageFlags flags,
5767 time_t mtime) 6131 time_t mtime)
5768 { 6132 {
5769 PidginConversation *gtkconv; 6133 PidginConversation *gtkconv;
5770 PurpleConnection *gc; 6134 PurpleConnection *gc;
5771 PurpleAccount *account; 6135 PurpleAccount *account;
6136 #if 0
5772 int gtk_font_options = 0; 6137 int gtk_font_options = 0;
5773 int gtk_font_options_all = 0; 6138 int gtk_font_options_all = 0;
5774 int max_scrollback_lines;
5775 int line_count;
5776 char buf2[BUF_LONG]; 6139 char buf2[BUF_LONG];
5777 gboolean show_date; 6140 gboolean show_date;
5778 char *mdate; 6141 char *mdate;
5779 char *str; 6142 char *str;
5780 char *with_font_tag; 6143 char *with_font_tag;
5781 char *sml_attrib = NULL; 6144 char *sml_attrib = NULL;
6145 #endif
5782 size_t length; 6146 size_t length;
5783 PurpleConversationType type; 6147 PurpleConversationType type;
5784 char *displaying; 6148 char *displaying;
5785 gboolean plugin_return; 6149 gboolean plugin_return;
5786 char *bracket; 6150 #if 0
5787 int tag_count = 0;
5788 gboolean is_rtl_message = FALSE; 6151 gboolean is_rtl_message = FALSE;
6152 #endif
6153
6154 const char *message_html;
6155 char *msg;
6156 char *escape;
6157 char *script;
6158 char *smileyed;
6159 PurpleMessageFlags old_flags;
6160 const char *func = "appendMessage";
5789 6161
5790 g_return_if_fail(conv != NULL); 6162 g_return_if_fail(conv != NULL);
5791 gtkconv = PIDGIN_CONVERSATION(conv); 6163 gtkconv = PIDGIN_CONVERSATION(conv);
5792 g_return_if_fail(gtkconv != NULL); 6164 g_return_if_fail(gtkconv != NULL);
5793 6165
5840 g_free(displaying); 6212 g_free(displaying);
5841 return; 6213 return;
5842 } 6214 }
5843 length = strlen(displaying) + 1; 6215 length = strlen(displaying) + 1;
5844 6216
5845 /* Awful hack to work around GtkIMHtml's inefficient rendering of messages with lots of formatting changes. 6217 old_flags = gtkconv->last_flags;
5846 * If a message has over 100 '<' characters, strip formatting before appending it. Hopefully nobody actually 6218 if ((flags & PURPLE_MESSAGE_SEND) && (old_flags & PURPLE_MESSAGE_SEND)) {
5847 * needs that much formatting, anyway. 6219 message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT);
5848 */ 6220 func = "appendNextMessage";
5849 for (bracket = strchr(displaying, '<'); bracket && *(bracket + 1); bracket = strchr(bracket + 1, '<')) 6221 } else if (flags & PURPLE_MESSAGE_SEND) {
5850 tag_count++; 6222 message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT);
5851 6223 } else if ((flags & PURPLE_MESSAGE_RECV) && (old_flags & PURPLE_MESSAGE_RECV)) {
5852 if (tag_count > 100) { 6224 message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT);
5853 char *tmp = displaying; 6225 func = "appendNextMessage";
5854 displaying = purple_markup_strip_html(tmp); 6226 } else if (flags & PURPLE_MESSAGE_RECV) {
5855 g_free(tmp); 6227 message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT);
5856 } 6228 } else {
5857 6229 message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS);
5858 line_count = gtk_text_buffer_get_line_count( 6230 }
5859 gtk_text_view_get_buffer(GTK_TEXT_VIEW( 6231 gtkconv->last_flags = flags;
5860 gtkconv->imhtml))); 6232
5861 6233 smileyed = smiley_parse_markup(message, purple_account_get_protocol_id(account));
5862 max_scrollback_lines = purple_prefs_get_int( 6234 msg = replace_message_tokens(message_html, conv, name, alias, smileyed, flags, mtime);
5863 PIDGIN_PREFS_ROOT "/conversations/scrollback_lines"); 6235 escape = gtk_webview_quote_js_string(msg);
5864 /* If we're sitting at more than 100 lines more than the 6236 script = g_strdup_printf("%s(%s)", func, escape);
5865 max scrollback, trim down to max scrollback */ 6237
5866 if (max_scrollback_lines > 0 6238 purple_debug_info("webkit", "JS: %s\n", script);
5867 && line_count > (max_scrollback_lines + 100)) { 6239 gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), script);
5868 GtkTextBuffer *text_buffer = gtk_text_view_get_buffer( 6240
5869 GTK_TEXT_VIEW(gtkconv->imhtml)); 6241 g_free(script);
5870 GtkTextIter start, end; 6242 g_free(smileyed);
5871 6243 g_free(msg);
5872 gtk_text_buffer_get_start_iter(text_buffer, &start); 6244 g_free(escape);
5873 gtk_text_buffer_get_iter_at_line(text_buffer, &end, 6245
5874 (line_count - max_scrollback_lines)); 6246 #if 0
5875 gtk_imhtml_delete(GTK_IMHTML(gtkconv->imhtml), &start, &end); 6247 /* if the buffer is not empty add a <br> */
5876 } 6248 if (!gtk_webview_is_empty(GTK_WEBVIEW(gtkconv->webview)))
5877 6249 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<br />");
5878 if (type == PURPLE_CONV_TYPE_CHAT)
5879 {
5880 /* Create anchor for user */
5881 GtkTextIter iter;
5882 char *tmp = g_strconcat("user:", name, NULL);
5883
5884 gtk_text_buffer_get_end_iter(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)), &iter);
5885 gtk_text_buffer_create_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)),
5886 tmp, &iter, TRUE);
5887 g_free(tmp);
5888 }
5889
5890 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling"))
5891 gtk_font_options_all |= GTK_IMHTML_USE_SMOOTHSCROLLING;
5892
5893 if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml))))
5894 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", gtk_font_options_all | GTK_IMHTML_NO_SCROLL);
5895 6250
5896 /* First message in a conversation. */ 6251 /* First message in a conversation. */
5897 if (gtkconv->newday == 0) 6252 if (gtkconv->newday == 0)
5898 pidgin_conv_calculate_newday(gtkconv, mtime); 6253 pidgin_conv_calculate_newday(gtkconv, mtime);
5899 6254
5932 if ((flags & PURPLE_MESSAGE_RECV) && 6287 if ((flags & PURPLE_MESSAGE_RECV) &&
5933 !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting")) 6288 !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting"))
5934 gtk_font_options |= GTK_IMHTML_NO_COLOURS | GTK_IMHTML_NO_FONTS | GTK_IMHTML_NO_SIZES | GTK_IMHTML_NO_FORMATTING; 6289 gtk_font_options |= GTK_IMHTML_NO_COLOURS | GTK_IMHTML_NO_FONTS | GTK_IMHTML_NO_SIZES | GTK_IMHTML_NO_FORMATTING;
5935 6290
5936 /* this is gonna crash one day, I can feel it. */ 6291 /* this is gonna crash one day, I can feel it. */
5937 if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(conv->account)))->options & 6292 if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(purple_conversation_get_account(conv))))->options &
5938 OPT_PROTO_USE_POINTSIZE) { 6293 OPT_PROTO_USE_POINTSIZE) {
5939 gtk_font_options |= GTK_IMHTML_USE_POINTSIZE; 6294 gtk_font_options |= GTK_IMHTML_USE_POINTSIZE;
5940 } 6295 }
5941 6296
5942 if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) 6297 if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY))
5943 { 6298 {
5944 /* We want to see our own smileys. Need to revert it after send*/ 6299 /* We want to see our own smileys. Need to revert it after send*/
5945 pidgin_themes_smiley_themeize_custom(gtkconv->imhtml); 6300 pidgin_themes_smiley_themeize_custom(gtkconv->webview);
5946 } 6301 }
5947 6302
5948 /* TODO: These colors should not be hardcoded so log.c can use them */ 6303 /* TODO: These colors should not be hardcoded so log.c can use them */
5949 if (flags & PURPLE_MESSAGE_RAW) { 6304 if (flags & PURPLE_MESSAGE_RAW) {
5950 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, gtk_font_options_all); 6305 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), message);
5951 } else if (flags & PURPLE_MESSAGE_SYSTEM) { 6306 } else if (flags & PURPLE_MESSAGE_SYSTEM) {
5952 g_snprintf(buf2, sizeof(buf2), 6307 g_snprintf(buf2, sizeof(buf2),
5953 "<FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT>", 6308 "<font %s><font size=\"2\"><span class='timestamp'>%s</span></font><b>%s</b></font>",
5954 sml_attrib ? sml_attrib : "", mdate, displaying); 6309 sml_attrib ? sml_attrib : "", mdate, displaying);
5955 6310
5956 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); 6311 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
5957 6312
5958 } else if (flags & PURPLE_MESSAGE_ERROR) { 6313 } else if (flags & PURPLE_MESSAGE_ERROR) {
5959 g_snprintf(buf2, sizeof(buf2), 6314 g_snprintf(buf2, sizeof(buf2),
5960 "<FONT COLOR=\"#ff0000\"><FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT></FONT>", 6315 "<font color=\"#ff0000\"><font %s><font size=\"2\"><span class='timestamp'>%s</span> </font><b>%s</b></font></font>",
5961 sml_attrib ? sml_attrib : "", mdate, displaying); 6316 sml_attrib ? sml_attrib : "", mdate, displaying);
5962 6317
5963 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); 6318 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
5964 6319
5965 } else if (flags & PURPLE_MESSAGE_NO_LOG) { 6320 } else if (flags & PURPLE_MESSAGE_NO_LOG) {
5966 g_snprintf(buf2, BUF_LONG, 6321 g_snprintf(buf2, BUF_LONG,
5967 "<B><FONT %s COLOR=\"#777777\">%s</FONT></B>", 6322 "<b><font %s color=\"#777777\">%s</font></b>",
5968 sml_attrib ? sml_attrib : "", displaying); 6323 sml_attrib ? sml_attrib : "", displaying);
5969 6324
5970 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); 6325 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
5971 } else { 6326 } else {
5972 char *new_message = g_memdup(displaying, length); 6327 char *new_message = g_memdup(displaying, length);
5973 char *alias_escaped = (alias ? g_markup_escape_text(alias, strlen(alias)) : g_strdup("")); 6328 char *alias_escaped = (alias ? g_markup_escape_text(alias, strlen(alias)) : g_strdup(""));
5974 /* The initial offset is to deal with 6329 /* The initial offset is to deal with
5975 * escaped entities making the string longer */ 6330 * escaped entities making the string longer */
5976 int tag_start_offset = 0; 6331 int tag_start_offset = 0;
5977 int tag_end_offset = 0; 6332 int tag_end_offset = 0;
5978 const char *tagname = NULL; 6333 const char *tagname = NULL;
5979
5980 GtkTextIter start, end;
5981 GtkTextMark *mark;
5982 GtkTextTag *tag;
5983 GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer;
5984 6334
5985 /* Enforce direction on alias */ 6335 /* Enforce direction on alias */
5986 if (is_rtl_message) 6336 if (is_rtl_message)
5987 str_embed_direction_chars(&alias_escaped); 6337 str_embed_direction_chars(&alias_escaped);
5988 6338
6040 } 6390 }
6041 } 6391 }
6042 6392
6043 g_free(alias_escaped); 6393 g_free(alias_escaped);
6044 6394
6395 /* TODO WEBKIT */
6396 #if 0
6045 if (tagname) 6397 if (tagname)
6046 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname); 6398 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname);
6047 else 6399 else
6048 tag = get_buddy_tag(conv, name, flags, TRUE); 6400 tag = get_buddy_tag(conv, name, flags, TRUE);
6049 6401
6050 if (GTK_IMHTML(gtkconv->imhtml)->show_comments) { 6402 if (GTK_IMHTML(gtkconv->imhtml)->show_comments) {
6403 {
6051 /* The color for the timestamp has to be set in the font-tags, unfortunately. 6404 /* The color for the timestamp has to be set in the font-tags, unfortunately.
6052 * Applying the nick-tag to timestamps would work, but that can make it 6405 * Applying the nick-tag to timestamps would work, but that can make it
6053 * bold. I thought applying the "comment" tag again, which has "weight" set 6406 * bold. I thought applying the "comment" tag again, which has "weight" set
6054 * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So 6407 * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So
6055 * this will have to do. I don't terribly like it. -- sadrul */ 6408 * this will have to do. I don't terribly like it. -- sadrul */
6056 const char *color = get_text_tag_color(tag); 6409 /* const char *color = get_text_tag_color(tag); */
6057 g_snprintf(buf2, BUF_LONG, "<FONT %s%s%s SIZE=\"2\"><!--%s --></FONT>", 6410 g_snprintf(buf2, BUF_LONG, "<FONT %s%s%s SIZE=\"2\"><!--%s --></FONT>",
6058 color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate); 6411 color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate);
6059 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); 6412 gtk_webview_append_html (GTK_WEBVIEW(gtkconv->webview), buf2);
6060 } 6413 }
6061 6414 #endif /* if 0 */
6062 gtk_text_buffer_get_end_iter(buffer, &end); 6415 g_snprintf(buf2, BUF_LONG, "<font %s>%s</font> ", sml_attrib ? sml_attrib : "", str);
6063 mark = gtk_text_buffer_create_mark(buffer, NULL, &end, TRUE); 6416 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
6064
6065 g_snprintf(buf2, BUF_LONG, "<FONT %s>%s</FONT> ", sml_attrib ? sml_attrib : "", str);
6066 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL);
6067
6068 gtk_text_buffer_get_end_iter(buffer, &end);
6069 gtk_text_buffer_get_iter_at_mark(buffer, &start, mark);
6070 gtk_text_buffer_apply_tag(buffer, tag, &start, &end);
6071 gtk_text_buffer_delete_mark(buffer, mark);
6072 6417
6073 g_free(str); 6418 g_free(str);
6074 6419
6075 if(gc){ 6420 if (gc) {
6076 char *pre = g_strdup_printf("<font %s>", sml_attrib ? sml_attrib : ""); 6421 char *pre = g_strdup_printf("<font %s>", sml_attrib ? sml_attrib : "");
6077 char *post = "</font>"; 6422 char *post = "</font>";
6078 int pre_len = strlen(pre); 6423 with_font_tag = g_strdup_printf("%s%s%s", pre, new_message, post);
6079 int post_len = strlen(post);
6080
6081 with_font_tag = g_malloc(length + pre_len + post_len + 1);
6082
6083 strcpy(with_font_tag, pre);
6084 memcpy(with_font_tag + pre_len, new_message, length);
6085 strcpy(with_font_tag + pre_len + length, post);
6086
6087 length += pre_len + post_len;
6088 g_free(pre); 6424 g_free(pre);
6089 } else 6425 } else
6090 with_font_tag = g_memdup(new_message, length); 6426 with_font_tag = g_memdup(new_message, length);
6091 6427
6092 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), 6428 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview),
6093 with_font_tag, gtk_font_options | gtk_font_options_all); 6429 with_font_tag);
6094 6430
6095 g_free(with_font_tag); 6431 g_free(with_font_tag);
6096 g_free(new_message); 6432 g_free(new_message);
6097 } 6433 }
6098 6434
6099 g_free(mdate); 6435 g_free(mdate);
6100 g_free(sml_attrib); 6436 g_free(sml_attrib);
6437
6438 #endif
6101 6439
6102 /* Tab highlighting stuff */ 6440 /* Tab highlighting stuff */
6103 if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv)) 6441 if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv))
6104 { 6442 {
6105 PidginUnseenState unseen = PIDGIN_UNSEEN_NONE; 6443 PidginUnseenState unseen = PIDGIN_UNSEEN_NONE;
6115 unseen = PIDGIN_UNSEEN_TEXT; 6453 unseen = PIDGIN_UNSEEN_TEXT;
6116 6454
6117 gtkconv_set_unseen(gtkconv, unseen); 6455 gtkconv_set_unseen(gtkconv, unseen);
6118 } 6456 }
6119 6457
6120 if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) 6458 #if 0
6459 if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY))
6121 { 6460 {
6122 /* Restore the smiley-data */ 6461 /* Restore the smiley-data */
6123 pidgin_themes_smiley_themeize(gtkconv->imhtml); 6462 pidgin_themes_smiley_themeize(gtkconv->webview);
6124 } 6463 }
6464 #endif
6125 6465
6126 purple_signal_emit(pidgin_conversations_get_handle(), 6466 purple_signal_emit(pidgin_conversations_get_handle(),
6127 (type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"), 6467 (type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"),
6128 account, name, displaying, conv, flags); 6468 account, name, displaying, conv, flags);
6129 g_free(displaying); 6469 g_free(displaying);
6130 update_typing_message(gtkconv, NULL); 6470 update_typing_message(gtkconv, NULL);
6131 } 6471 }
6132 6472
6133 static gboolean get_iter_from_chatbuddy(PurpleConvChatBuddy *cb, GtkTreeIter *iter) 6473 static gboolean get_iter_from_chatbuddy(PurpleConvChatBuddy *cb, GtkTreeIter *iter)
6134 { 6474 {
6135 GtkTreeRowReference *ref = cb->ui_data; 6475 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
6136 GtkTreePath *path; 6476 GtkTreePath *path;
6137 GtkTreeModel *model; 6477 GtkTreeModel *model;
6138 6478
6139 if (!ref) 6479 if (!ref)
6140 return FALSE; 6480 return FALSE;
6216 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 6556 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
6217 return; 6557 return;
6218 6558
6219 old_cbuddy = purple_conv_chat_cb_find(chat, old_name); 6559 old_cbuddy = purple_conv_chat_cb_find(chat, old_name);
6220 if (get_iter_from_chatbuddy(old_cbuddy, &iter)) { 6560 if (get_iter_from_chatbuddy(old_cbuddy, &iter)) {
6221 GtkTreeRowReference *ref = old_cbuddy->ui_data; 6561 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(old_cbuddy);
6222 6562
6223 gtk_list_store_remove(GTK_LIST_STORE(model), &iter); 6563 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
6224 gtk_tree_row_reference_free(ref); 6564 gtk_tree_row_reference_free(ref);
6225 old_cbuddy->ui_data = NULL; 6565 purple_conv_chat_cb_set_ui_data(old_cbuddy, NULL);
6226 } 6566 }
6227 6567
6228 if ((tag = get_buddy_tag(conv, old_name, 0, FALSE))) 6568 if ((tag = get_buddy_tag(conv, old_name, 0, FALSE)))
6229 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL); 6569 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
6230 if ((tag = get_buddy_tag(conv, old_name, PURPLE_MESSAGE_NICK, FALSE))) 6570 if ((tag = get_buddy_tag(conv, old_name, PURPLE_MESSAGE_NICK, FALSE)))
6314 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 6654 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
6315 return; 6655 return;
6316 6656
6317 cbuddy = purple_conv_chat_cb_find(chat, user); 6657 cbuddy = purple_conv_chat_cb_find(chat, user);
6318 if (get_iter_from_chatbuddy(cbuddy, &iter)) { 6658 if (get_iter_from_chatbuddy(cbuddy, &iter)) {
6319 GtkTreeRowReference *ref = cbuddy->ui_data; 6659 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cbuddy);
6320 gtk_list_store_remove(GTK_LIST_STORE(model), &iter); 6660 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
6321 gtk_tree_row_reference_free(ref); 6661 gtk_tree_row_reference_free(ref);
6322 cbuddy->ui_data = NULL; 6662 purple_conv_chat_cb_set_ui_data(cbuddy, NULL);
6323 } 6663 }
6324 6664
6325 if (cbuddy) 6665 if (cbuddy)
6326 add_chat_buddy_common(conv, cbuddy, NULL); 6666 add_chat_buddy_common(conv, cbuddy, NULL);
6327 } 6667 }
6364 6704
6365 return TRUE; 6705 return TRUE;
6366 } 6706 }
6367 6707
6368 static gboolean 6708 static gboolean
6709 add_custom_smiley_for_webview(GtkWebView *webview, const char *sml, const char *smile)
6710 {
6711 /* TODO WEBKIT: Smileys need to be added to webkit stuff */
6712 return TRUE;
6713 }
6714
6715 static gboolean
6369 pidgin_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, gboolean remote) 6716 pidgin_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, gboolean remote)
6370 { 6717 {
6371 PidginConversation *gtkconv; 6718 PidginConversation *gtkconv;
6372 struct smiley_list *list; 6719 struct smiley_list *list;
6373 const char *sml = NULL, *conv_sml; 6720 const char *sml = NULL, *conv_sml;
6380 if (pidgin_themes_smileys_disabled()) 6727 if (pidgin_themes_smileys_disabled())
6381 return FALSE; 6728 return FALSE;
6382 6729
6383 /* If possible add this smiley to the current theme. 6730 /* If possible add this smiley to the current theme.
6384 * The addition is only temporary: custom smilies aren't saved to disk. */ 6731 * The addition is only temporary: custom smilies aren't saved to disk. */
6385 conv_sml = purple_account_get_protocol_name(conv->account); 6732 conv_sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6386 gtkconv = PIDGIN_CONVERSATION(conv); 6733 gtkconv = PIDGIN_CONVERSATION(conv);
6387 6734
6388 for (list = (struct smiley_list *)current_smiley_theme->list; list; list = list->next) { 6735 for (list = (struct smiley_list *)current_smiley_theme->list; list; list = list->next) {
6389 if (!strcmp(list->sml, conv_sml)) { 6736 if (!strcmp(list->sml, conv_sml)) {
6390 sml = list->sml; 6737 sml = list->sml;
6391 break; 6738 break;
6392 } 6739 }
6393 } 6740 }
6394 6741
6395 if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->imhtml), sml, smile)) 6742 if (!add_custom_smiley_for_webview(GTK_WEBVIEW(gtkconv->webview), sml, smile))
6396 return FALSE; 6743 return FALSE;
6397 6744
6398 if (!remote) /* If it's a local custom smiley, then add it for the entry */ 6745 if (!remote) /* If it's a local custom smiley, then add it for the entry */
6399 if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->entry), sml, smile)) 6746 if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->entry), sml, smile))
6400 return FALSE; 6747 return FALSE;
6404 6751
6405 static void 6752 static void
6406 pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile, 6753 pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile,
6407 const guchar *data, gsize size) 6754 const guchar *data, gsize size)
6408 { 6755 {
6756 /* TODO WEBKIT */
6757 #if 0
6409 PidginConversation *gtkconv; 6758 PidginConversation *gtkconv;
6410 GtkIMHtmlSmiley *smiley; 6759 GtkIMHtmlSmiley *smiley;
6411 const char *sml; 6760 const char *sml;
6412 GError *error = NULL; 6761 GError *error = NULL;
6413 6762
6414 sml = purple_account_get_protocol_name(conv->account); 6763 sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6415 gtkconv = PIDGIN_CONVERSATION(conv); 6764 gtkconv = PIDGIN_CONVERSATION(conv);
6416 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); 6765 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile);
6417 6766
6418 if (!smiley) 6767 if (!smiley)
6419 return; 6768 return;
6425 if (!smiley->loader) 6774 if (!smiley->loader)
6426 return; 6775 return;
6427 6776
6428 if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) { 6777 if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) {
6429 purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() " 6778 purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() "
6430 "failed with size=%zu: %s\n", size, 6779 "failed with size=%" G_GSIZE_FORMAT ": %s\n", size,
6431 error ? error->message : "(no error message)"); 6780 error ? error->message : "(no error message)");
6432 if (error) 6781 if (error)
6433 g_error_free(error); 6782 g_error_free(error);
6434 /* We must stop using the GdkPixbufLoader because trying to load 6783 /* We must stop using the GdkPixbufLoader because trying to load
6435 certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return 6784 certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return
6438 But we also don't want to set smiley->loader to NULL because our 6787 But we also don't want to set smiley->loader to NULL because our
6439 code might expect it to be set. So create a new loader. */ 6788 code might expect it to be set. So create a new loader. */
6440 g_object_unref(G_OBJECT(smiley->loader)); 6789 g_object_unref(G_OBJECT(smiley->loader));
6441 smiley->loader = gdk_pixbuf_loader_new(); 6790 smiley->loader = gdk_pixbuf_loader_new();
6442 } 6791 }
6792 #endif /* if 0 */
6443 } 6793 }
6444 6794
6445 static void 6795 static void
6446 pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile) 6796 pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile)
6447 { 6797 {
6798 /* TODO WEBKIT */
6799 #if 0
6448 PidginConversation *gtkconv; 6800 PidginConversation *gtkconv;
6449 GtkIMHtmlSmiley *smiley; 6801 GtkIMHtmlSmiley *smiley;
6450 const char *sml; 6802 const char *sml;
6451 GError *error = NULL; 6803 GError *error = NULL;
6452 6804
6453 g_return_if_fail(conv != NULL); 6805 g_return_if_fail(conv != NULL);
6454 g_return_if_fail(smile != NULL); 6806 g_return_if_fail(smile != NULL);
6455 6807
6456 sml = purple_account_get_protocol_name(conv->account); 6808 sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6457 gtkconv = PIDGIN_CONVERSATION(conv); 6809 gtkconv = PIDGIN_CONVERSATION(conv);
6458 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); 6810 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile);
6459 6811
6460 if (!smiley) 6812 if (!smiley)
6461 return; 6813 return;
6479 to set smiley->loader to NULL because our code might expect it 6831 to set smiley->loader to NULL because our code might expect it
6480 to be set. So create a new loader. */ 6832 to be set. So create a new loader. */
6481 g_object_unref(G_OBJECT(smiley->loader)); 6833 g_object_unref(G_OBJECT(smiley->loader));
6482 smiley->loader = gdk_pixbuf_loader_new(); 6834 smiley->loader = gdk_pixbuf_loader_new();
6483 } 6835 }
6836 #endif /* if 0 */
6484 } 6837 }
6485 6838
6486 static void 6839 static void
6487 pidgin_conv_send_confirm(PurpleConversation *conv, const char *message) 6840 pidgin_conv_send_confirm(PurpleConversation *conv, const char *message)
6488 { 6841 {
6510 win = pidgin_conv_get_window(gtkconv); 6863 win = pidgin_conv_get_window(gtkconv);
6511 gc = purple_conversation_get_gc(conv); 6864 gc = purple_conversation_get_gc(conv);
6512 account = purple_conversation_get_account(conv); 6865 account = purple_conversation_get_account(conv);
6513 6866
6514 if (gc != NULL) 6867 if (gc != NULL)
6515 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 6868 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
6516 6869
6517 if (win->menu.send_to != NULL) 6870 if (win->menu.send_to != NULL)
6518 update_send_to_selection(win); 6871 update_send_to_selection(win);
6519 6872
6520 /* 6873 /*
6588 */ 6941 */
6589 if ((gc != NULL) && 6942 if ((gc != NULL) &&
6590 ((purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) || 6943 ((purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) ||
6591 !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) )) 6944 !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) ))
6592 { 6945 {
6946 PurpleConnectionFlags features = purple_conversation_get_features(conv);
6593 /* Account is online */ 6947 /* Account is online */
6594 /* Deal with the toolbar */ 6948 /* Deal with the toolbar */
6595 if (conv->features & PURPLE_CONNECTION_HTML) 6949 if (features & PURPLE_CONNECTION_HTML)
6596 { 6950 {
6597 buttons = GTK_IMHTML_ALL; /* Everything on */ 6951 buttons = GTK_IMHTML_ALL; /* Everything on */
6598 if (conv->features & PURPLE_CONNECTION_NO_BGCOLOR) 6952 if (features & PURPLE_CONNECTION_NO_BGCOLOR)
6599 buttons &= ~GTK_IMHTML_BACKCOLOR; 6953 buttons &= ~GTK_IMHTML_BACKCOLOR;
6600 if (conv->features & PURPLE_CONNECTION_NO_FONTSIZE) 6954 if (features & PURPLE_CONNECTION_NO_FONTSIZE)
6601 { 6955 {
6602 buttons &= ~GTK_IMHTML_GROW; 6956 buttons &= ~GTK_IMHTML_GROW;
6603 buttons &= ~GTK_IMHTML_SHRINK; 6957 buttons &= ~GTK_IMHTML_SHRINK;
6604 } 6958 }
6605 if (conv->features & PURPLE_CONNECTION_NO_URLDESC) 6959 if (features & PURPLE_CONNECTION_NO_URLDESC)
6606 buttons &= ~GTK_IMHTML_LINKDESC; 6960 buttons &= ~GTK_IMHTML_LINKDESC;
6607 } else { 6961 } else {
6608 buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE; 6962 buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE;
6609 } 6963 }
6610 6964
6611 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)) 6965 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)
6612 conv->features |= PURPLE_CONNECTION_NO_IMAGES; 6966 && !(features & PURPLE_CONNECTION_NO_IMAGES)) {
6613 6967 features |= PURPLE_CONNECTION_NO_IMAGES;
6614 if(conv->features & PURPLE_CONNECTION_NO_IMAGES) 6968 purple_conversation_set_features(conv, features);
6969 }
6970
6971 if (features & PURPLE_CONNECTION_NO_IMAGES)
6615 buttons &= ~GTK_IMHTML_IMAGE; 6972 buttons &= ~GTK_IMHTML_IMAGE;
6616 6973
6617 if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) 6974 if (features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
6618 buttons |= GTK_IMHTML_CUSTOM_SMILEY; 6975 buttons |= GTK_IMHTML_CUSTOM_SMILEY;
6619 else 6976 else
6620 buttons &= ~GTK_IMHTML_CUSTOM_SMILEY; 6977 buttons &= ~GTK_IMHTML_CUSTOM_SMILEY;
6621 6978
6622 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons); 6979 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons);
6626 /* Deal with menu items */ 6983 /* Deal with menu items */
6627 gtk_widget_set_sensitive(win->menu.view_log, TRUE); 6984 gtk_widget_set_sensitive(win->menu.view_log, TRUE);
6628 gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); 6985 gtk_widget_set_sensitive(win->menu.add_pounce, TRUE);
6629 gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); 6986 gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL));
6630 gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); 6987 gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL));
6631 gtk_widget_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML)); 6988 gtk_widget_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_HTML));
6632 gtk_widget_set_sensitive(win->menu.insert_image, !(conv->features & PURPLE_CONNECTION_NO_IMAGES)); 6989 gtk_widget_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_NO_IMAGES));
6633 6990
6634 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) 6991 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
6635 { 6992 {
6636 gtk_widget_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL) || (prpl_info->add_buddy_with_invite != NULL)); 6993 gtk_widget_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL));
6637 gtk_widget_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); 6994 gtk_widget_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL));
6638 gtk_widget_set_sensitive(win->menu.send_file, 6995 gtk_widget_set_sensitive(win->menu.send_file,
6639 (prpl_info->send_file != NULL && (!prpl_info->can_receive_file || 6996 (prpl_info->send_file != NULL && (!prpl_info->can_receive_file ||
6640 prpl_info->can_receive_file(gc, purple_conversation_get_name(conv))))); 6997 prpl_info->can_receive_file(gc, purple_conversation_get_name(conv)))));
6641 gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(win->window), "get_attention"), (prpl_info->send_attention != NULL)); 6998 gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(win->window), "get_attention"), (prpl_info->send_attention != NULL));
6678 { 7035 {
6679 GList *l = NULL; 7036 GList *l = NULL;
6680 if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && 7037 if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) &&
6681 (gtkconv->u.im->anim)) 7038 (gtkconv->u.im->anim))
6682 { 7039 {
6683 PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); 7040 PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
6684 window_icon = 7041 window_icon =
6685 gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); 7042 gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim);
6686 7043
6687 if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy)) 7044 if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy))
6688 gdk_pixbuf_saturate_and_pixelate(window_icon, window_icon, 0.0, FALSE); 7045 gdk_pixbuf_saturate_and_pixelate(window_icon, window_icon, 0.0, FALSE);
6751 gtk_tooltips_set_tip(gtkconv->tooltips, gtkchat->topic_text, 7108 gtk_tooltips_set_tip(gtkconv->tooltips, gtkchat->topic_text,
6752 topic ? topic : "", NULL); 7109 topic ? topic : "", NULL);
6753 } 7110 }
6754 } 7111 }
6755 7112
7113 #if 0
6756 if (fields & PIDGIN_CONV_SMILEY_THEME) 7114 if (fields & PIDGIN_CONV_SMILEY_THEME)
6757 pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->imhtml); 7115 pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->webview);
7116 #endif
6758 7117
6759 if ((fields & PIDGIN_CONV_COLORIZE_TITLE) || 7118 if ((fields & PIDGIN_CONV_COLORIZE_TITLE) ||
6760 (fields & PIDGIN_CONV_SET_TITLE) || 7119 (fields & PIDGIN_CONV_SET_TITLE) ||
6761 (fields & PIDGIN_CONV_TOPIC)) 7120 (fields & PIDGIN_CONV_TOPIC))
6762 { 7121 {
6779 title = g_strdup_printf("(%s)", purple_conversation_get_title(conv)); 7138 title = g_strdup_printf("(%s)", purple_conversation_get_title(conv));
6780 else 7139 else
6781 title = g_strdup(purple_conversation_get_title(conv)); 7140 title = g_strdup(purple_conversation_get_title(conv));
6782 7141
6783 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 7142 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
6784 buddy = purple_find_buddy(account, conv->name); 7143 buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
6785 if (buddy) { 7144 if (buddy) {
6786 markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE); 7145 markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE);
6787 } else { 7146 } else {
6788 markup = title; 7147 markup = title;
6789 } 7148 }
6824 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) { 7183 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) {
6825 atk_object_set_description(accessibility_obj, _("Nick Said")); 7184 atk_object_set_description(accessibility_obj, _("Nick Said"));
6826 style = "tab-label-attention"; 7185 style = "tab-label-attention";
6827 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) { 7186 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) {
6828 atk_object_set_description(accessibility_obj, _("Unread Messages")); 7187 atk_object_set_description(accessibility_obj, _("Unread Messages"));
6829 if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_CHAT) 7188 if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT)
6830 style = "tab-label-unreadchat"; 7189 style = "tab-label-unreadchat";
6831 else 7190 else
6832 style = "tab-label-attention"; 7191 style = "tab-label-attention";
6833 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) { 7192 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) {
6834 atk_object_set_description(accessibility_obj, _("New Event")); 7193 atk_object_set_description(accessibility_obj, _("New Event"));
7330 7689
7331 gtk_check_menu_item_set_active( 7690 gtk_check_menu_item_set_active(
7332 GTK_CHECK_MENU_ITEM(win->menu.show_timestamps), 7691 GTK_CHECK_MENU_ITEM(win->menu.show_timestamps),
7333 (gboolean)GPOINTER_TO_INT(value)); 7692 (gboolean)GPOINTER_TO_INT(value));
7334 7693
7694 /* TODO WEBKIT: Use WebKit version of this. */
7695 #if 0
7335 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), 7696 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),
7336 (gboolean)GPOINTER_TO_INT(value)); 7697 (gboolean)GPOINTER_TO_INT(value));
7698 #endif /* if 0 */
7337 } 7699 }
7338 } 7700 }
7339 7701
7340 static void 7702 static void
7341 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type, 7703 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type,
7499 gtkconv = l->data; 7861 gtkconv = l->data;
7500 l = l->next; 7862 l = l->next;
7501 7863
7502 conv = gtkconv->active_conv; 7864 conv = gtkconv->active_conv;
7503 7865
7504 if (conv->type == PURPLE_CONV_TYPE_CHAT || 7866 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT ||
7505 gtkconv->unseen_count == 0 || 7867 gtkconv->unseen_count == 0 ||
7506 (when_away && !purple_status_is_available( 7868 (when_away && !purple_status_is_available(
7507 purple_account_get_active_status( 7869 purple_account_get_active_status(
7508 purple_conversation_get_account(conv))))) 7870 purple_conversation_get_account(conv)))))
7509 continue; 7871 continue;
7564 /* if (purple_conversation_get_account(conv) == account) */ 7926 /* if (purple_conversation_get_account(conv) == account) */
7565 pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON | 7927 pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON |
7566 PIDGIN_CONV_MENU | PIDGIN_CONV_COLORIZE_TITLE); 7928 PIDGIN_CONV_MENU | PIDGIN_CONV_COLORIZE_TITLE);
7567 7929
7568 if (PURPLE_CONNECTION_IS_CONNECTED(gc) && 7930 if (PURPLE_CONNECTION_IS_CONNECTED(gc) &&
7569 conv->type == PURPLE_CONV_TYPE_CHAT && 7931 purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT &&
7570 conv->account == gc->account && 7932 purple_conversation_get_account(conv) == purple_connection_get_account(gc) &&
7571 purple_conversation_get_data(conv, "want-to-rejoin")) { 7933 purple_conversation_get_data(conv, "want-to-rejoin")) {
7572 GHashTable *comps = NULL; 7934 GHashTable *comps = NULL;
7573 PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); 7935 PurpleChat *chat = purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
7574 if (chat == NULL) { 7936 if (chat == NULL) {
7575 if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) 7937 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
7576 comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, conv->name); 7938
7939 if (prpl_info->chat_info_defaults != NULL)
7940 comps = prpl_info->chat_info_defaults(gc, purple_conversation_get_name(conv));
7577 } else { 7941 } else {
7578 comps = chat->components; 7942 comps = chat->components;
7579 } 7943 }
7580 serv_join_chat(gc, comps); 7944 serv_join_chat(gc, comps);
7581 if (chat == NULL && comps != NULL) 7945 if (chat == NULL && comps != NULL)
7726 { 8090 {
7727 PidginConversation *gtkconv = data; 8091 PidginConversation *gtkconv = data;
7728 int count = 0; 8092 int count = 0;
7729 int timer = gtkconv->attach.timer; 8093 int timer = gtkconv->attach.timer;
7730 time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time")); 8094 time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time"));
7731 gboolean im = (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM); 8095 gboolean im = (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM);
7732 8096
7733 gtkconv->attach.timer = 0; 8097 gtkconv->attach.timer = 0;
7734 while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */ 8098 while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */
7735 PurpleConvMessage *msg = gtkconv->attach.current->data; 8099 PurpleConvMessage *msg = gtkconv->attach.current->data;
7736 if (!im && when && when < msg->when) { 8100 if (!im && when && when < msg->when) {
7737 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0); 8101 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<BR><HR>");
7738 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); 8102 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
7739 } 8103 }
7740 pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when); 8104 pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when);
7741 if (im) { 8105 if (im) {
7742 gtkconv->attach.current = g_list_delete_link(gtkconv->attach.current, gtkconv->attach.current); 8106 gtkconv->attach.current = g_list_delete_link(gtkconv->attach.current, gtkconv->attach.current);
7767 msgs = g_list_sort(msgs, message_compare); 8131 msgs = g_list_sort(msgs, message_compare);
7768 for (; msgs; msgs = g_list_delete_link(msgs, msgs)) { 8132 for (; msgs; msgs = g_list_delete_link(msgs, msgs)) {
7769 PurpleConvMessage *msg = msgs->data; 8133 PurpleConvMessage *msg = msgs->data;
7770 pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when); 8134 pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when);
7771 } 8135 }
7772 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0); 8136 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<BR><HR>");
7773 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); 8137 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
7774 } 8138 }
7775 8139
7776 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); 8140 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
7777 purple_signal_emit(pidgin_conversations_get_handle(), 8141 purple_signal_emit(pidgin_conversations_get_handle(),
7850 } else { 8214 } else {
7851 purple_signal_emit(pidgin_conversations_get_handle(), 8215 purple_signal_emit(pidgin_conversations_get_handle(),
7852 "conversation-displayed", gtkconv); 8216 "conversation-displayed", gtkconv);
7853 } 8217 }
7854 8218
7855 if (conv->type == PURPLE_CONV_TYPE_CHAT) { 8219 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
7856 pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); 8220 pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC);
7857 pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE); 8221 pidgin_conv_chat_add_users(conv, purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)), TRUE);
7858 } 8222 }
7859 8223
7860 return TRUE; 8224 return TRUE;
7861 } 8225 }
7862 8226
7874 void *handle = pidgin_conversations_get_handle(); 8238 void *handle = pidgin_conversations_get_handle();
7875 void *blist_handle = purple_blist_get_handle(); 8239 void *blist_handle = purple_blist_get_handle();
7876 8240
7877 /* Conversations */ 8241 /* Conversations */
7878 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations"); 8242 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations");
8243 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/themes");
7879 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", TRUE); 8244 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", TRUE);
7880 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", TRUE); 8245 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", TRUE);
7881 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE); 8246 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE);
7882 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", FALSE); 8247 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", FALSE);
7883 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE); 8248 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE);
8157 purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", handle, 8522 purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", handle,
8158 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); 8523 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL);
8159 purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle, 8524 purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle,
8160 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); 8525 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL);
8161 8526
8527 purple_theme_manager_register_type(g_object_new(PIDGIN_TYPE_CONV_THEME_LOADER, "type", "conversation", NULL));
8528
8162 { 8529 {
8163 /* Set default tab colors */ 8530 /* Set default tab colors */
8164 GString *str = g_string_new(NULL); 8531 GString *str = g_string_new(NULL);
8165 GtkSettings *settings = gtk_settings_get_default(); 8532 GtkSettings *settings = gtk_settings_get_default();
8166 GtkStyle *parent = gtk_rc_get_style_by_paths(settings, "tab-container.tab-label*", NULL, G_TYPE_NONE), *now; 8533 GtkStyle *parent = gtk_rc_get_style_by_paths(settings, "tab-container.tab-label*", NULL, G_TYPE_NONE), *now;
9045 if (!GTK_WIDGET_VISIBLE(gtkconv->infopane)) { 9412 if (!GTK_WIDGET_VISIBLE(gtkconv->infopane)) {
9046 /* There's already an entry for alias. Let's not create another one. */ 9413 /* There's already an entry for alias. Let's not create another one. */
9047 return FALSE; 9414 return FALSE;
9048 } 9415 }
9049 9416
9050 if (!purple_account_is_connected(gtkconv->active_conv->account)) { 9417 if (!purple_account_is_connected(purple_conversation_get_account(gtkconv->active_conv))) {
9051 /* Do not allow aliasing someone on a disconnected account. */ 9418 /* Do not allow aliasing someone on a disconnected account. */
9052 return FALSE; 9419 return FALSE;
9053 } 9420 }
9054 9421
9055 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 9422 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
9056 PurpleBuddy *buddy = purple_find_buddy(gtkconv->active_conv->account, gtkconv->active_conv->name); 9423 PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv));
9057 if (!buddy) 9424 if (!buddy)
9058 /* This buddy isn't in your buddy list, so we can't alias him */ 9425 /* This buddy isn't in your buddy list, so we can't alias him */
9059 return FALSE; 9426 return FALSE;
9060 9427
9061 text = purple_buddy_get_contact_alias(buddy); 9428 text = purple_buddy_get_contact_alias(buddy);
9063 PurpleConnection *gc; 9430 PurpleConnection *gc;
9064 PurplePluginProtocolInfo *prpl_info = NULL; 9431 PurplePluginProtocolInfo *prpl_info = NULL;
9065 9432
9066 gc = purple_conversation_get_gc(conv); 9433 gc = purple_conversation_get_gc(conv);
9067 if (gc != NULL) 9434 if (gc != NULL)
9068 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 9435 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
9069 if (prpl_info && prpl_info->set_chat_topic == NULL) 9436 if (prpl_info && prpl_info->set_chat_topic == NULL)
9070 /* This protocol doesn't support setting the chat room topic */ 9437 /* This protocol doesn't support setting the chat room topic */
9071 return FALSE; 9438 return FALSE;
9072 9439
9073 text = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv)); 9440 text = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv));