comparison pidgin/gtkconv.c @ 32815:3d6528f36877

propagate from branch 'im.pidgin.pidgin.2.x.y' (head 5ca378b115ef36cfafb203fb88623734a7c6bb23) to branch 'im.pidgin.pidgin' (head ccfb262bb9e313a5281f05015530ef94fc58a573)
author Paul Aurich <paul@darkrain42.org>
date Thu, 31 May 2012 03:48:16 +0000
parents 626c339b60ae 0dd2cbee5b80
children
comparison
equal deleted inserted replaced
32814:626c339b60ae 32815:3d6528f36877
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 #if !GTK_CHECK_VERSION(2,20,0)
84 #define gtk_widget_get_realized(x) GTK_WIDGET_REALIZED(x)
85
86 #if !GTK_CHECK_VERSION(2,18,0)
87 #define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x)
88 #define gtk_widget_is_drawable(x) GTK_WIDGET_DRAWABLE(x)
89 #endif
90 #endif
91
92 /**
93 * A GTK+ Instant Message pane.
94 */
95 struct _PidginImPane
96 {
97 GtkWidget *block;
98 GtkWidget *send_file;
99 GtkWidget *sep1;
100 GtkWidget *sep2;
101 GtkWidget *check;
102 GtkWidget *progress;
103 guint32 typing_timer;
104
105 /* Buddy icon stuff */
106 GtkWidget *icon_container;
107 GtkWidget *icon;
108 gboolean show_icon;
109 gboolean animate;
110 GdkPixbufAnimation *anim;
111 GdkPixbufAnimationIter *iter;
112 guint32 icon_timer;
113 };
114
115 /**
116 * GTK+ Chat panes.
117 */
118 struct _PidginChatPane
119 {
120 GtkWidget *count;
121 GtkWidget *list;
122 GtkWidget *topic_text;
123 };
76 124
77 #define CLOSE_CONV_TIMEOUT_SECS (10 * 60) 125 #define CLOSE_CONV_TIMEOUT_SECS (10 * 60)
78 126
79 #define AUTO_RESPONSE "&lt;AUTO-REPLY&gt; : " 127 #define AUTO_RESPONSE "&lt;AUTO-REPLY&gt; : "
80 128
142 static GList *busy_list = NULL; 190 static GList *busy_list = NULL;
143 static GList *xa_list = NULL; 191 static GList *xa_list = NULL;
144 static GList *offline_list = NULL; 192 static GList *offline_list = NULL;
145 static GHashTable *prpl_lists = NULL; 193 static GHashTable *prpl_lists = NULL;
146 194
195 static PurpleTheme *default_conv_theme = NULL;
196
147 static gboolean update_send_to_selection(PidginWindow *win); 197 static gboolean update_send_to_selection(PidginWindow *win);
148 static void generate_send_to_items(PidginWindow *win); 198 static void generate_send_to_items(PidginWindow *win);
149 199
150 /* Prototypes. <-- because Paco-Paco hates this comment. */ 200 /* Prototypes. <-- because Paco-Paco hates this comment. */
201 static void load_conv_theme(PidginConversation *gtkconv);
151 static gboolean infopane_entry_activate(PidginConversation *gtkconv); 202 static gboolean infopane_entry_activate(PidginConversation *gtkconv);
152 static void got_typing_keypress(PidginConversation *gtkconv, gboolean first); 203 static void got_typing_keypress(PidginConversation *gtkconv, gboolean first);
153 static void gray_stuff_out(PidginConversation *gtkconv); 204 static void gray_stuff_out(PidginConversation *gtkconv);
154 static void add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const char *old_name); 205 static void add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const char *old_name);
155 static gboolean tab_complete(PurpleConversation *conv); 206 static gboolean tab_complete(PurpleConversation *conv);
156 static void pidgin_conv_updated(PurpleConversation *conv, PurpleConvUpdateType type); 207 static void pidgin_conv_updated(PurpleConversation *conv, PurpleConvUpdateType type);
157 static void conv_set_unseen(PurpleConversation *gtkconv, PidginUnseenState state); 208 static void conv_set_unseen(PurpleConversation *gtkconv, PidginUnseenState state);
158 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); 209 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state);
159 static void update_typing_icon(PidginConversation *gtkconv); 210 static void update_typing_icon(PidginConversation *gtkconv);
160 static void update_typing_message(PidginConversation *gtkconv, const char *message); 211 static void update_typing_message(PidginConversation *gtkconv, const char *message);
161 static const char *item_factory_translate_func (const char *path, gpointer func_data);
162 gboolean pidgin_conv_has_focus(PurpleConversation *conv); 212 gboolean pidgin_conv_has_focus(PurpleConversation *conv);
163 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); 213 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background);
164 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); 214 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast);
165 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, gboolean create); 215 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, gboolean create);
166 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); 216 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields);
174 static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y); 224 static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y);
175 225
176 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) 226 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name)
177 { 227 {
178 static GdkColor col; 228 static GdkColor col;
179 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); 229 GtkStyle *style = gtk_widget_get_style(gtkconv->webview);
180 float scale; 230 float scale;
181 231
182 col = nick_colors[g_str_hash(name) % nbr_nick_colors]; 232 col = nick_colors[g_str_hash(name) % nbr_nick_colors];
183 scale = ((1-(LUMINANCE(style->base[GTK_STATE_NORMAL]) / LUMINANCE(style->white))) * 233 scale = ((1-(LUMINANCE(style->base[GTK_STATE_NORMAL]) / LUMINANCE(style->white))) *
184 (LUMINANCE(style->white)/MAX(MAX(col.red, col.blue), col.green))); 234 (LUMINANCE(style->white)/MAX(MAX(col.red, col.blue), col.green)));
194 } 244 }
195 245
196 static PurpleBlistNode * 246 static PurpleBlistNode *
197 get_conversation_blist_node(PurpleConversation *conv) 247 get_conversation_blist_node(PurpleConversation *conv)
198 { 248 {
249 PurpleAccount *account = purple_conversation_get_account(conv);
199 PurpleBlistNode *node = NULL; 250 PurpleBlistNode *node = NULL;
200 251
201 switch (purple_conversation_get_type(conv)) { 252 switch (purple_conversation_get_type(conv)) {
202 case PURPLE_CONV_TYPE_IM: 253 case PURPLE_CONV_TYPE_IM:
203 node = PURPLE_BLIST_NODE(purple_find_buddy(conv->account, conv->name)); 254 node = PURPLE_BLIST_NODE(purple_find_buddy(account, purple_conversation_get_name(conv)));
204 node = node ? node->parent : NULL; 255 node = node ? node->parent : NULL;
205 break; 256 break;
206 case PURPLE_CONV_TYPE_CHAT: 257 case PURPLE_CONV_TYPE_CHAT:
207 node = PURPLE_BLIST_NODE(purple_blist_find_chat(conv->account, conv->name)); 258 node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, purple_conversation_get_name(conv)));
208 break; 259 break;
209 default: 260 default:
210 break; 261 break;
211 } 262 }
212 return node; 263 return node;
274 325
275 static void 326 static void
276 default_formatize(PidginConversation *c) 327 default_formatize(PidginConversation *c)
277 { 328 {
278 PurpleConversation *conv = c->active_conv; 329 PurpleConversation *conv = c->active_conv;
279 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features); 330 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), purple_conversation_get_features(conv));
280 } 331 }
281 332
282 static void 333 static void
283 conversation_entry_clear(PidginConversation *gtkconv) 334 conversation_entry_clear(PidginConversation *gtkconv)
284 { 335 {
354 } else { 405 } else {
355 str = g_string_append(str, "(none)"); 406 str = g_string_append(str, "(none)");
356 } 407 }
357 408
358 tmp = g_string_free(str, FALSE); 409 tmp = g_string_free(str, FALSE);
410 } else if (!g_ascii_strcasecmp(args[0], "unsafe")) {
411 if (purple_debug_is_unsafe()) {
412 purple_debug_set_unsafe(FALSE);
413 purple_conversation_write(conv, NULL, _("Unsafe debugging is now disabled."),
414 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
415 } else {
416 purple_debug_set_unsafe(TRUE);
417 purple_conversation_write(conv, NULL, _("Unsafe debugging is now enabled."),
418 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
419 }
420
421 return PURPLE_CMD_RET_OK;
422 } else if (!g_ascii_strcasecmp(args[0], "verbose")) {
423 if (purple_debug_is_verbose()) {
424 purple_debug_set_verbose(FALSE);
425 purple_conversation_write(conv, NULL, _("Verbose debugging is now disabled."),
426 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
427 } else {
428 purple_debug_set_verbose(TRUE);
429 purple_conversation_write(conv, NULL, _("Verbose debugging is now enabled."),
430 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
431 }
432
433 return PURPLE_CMD_RET_OK;
359 } else { 434 } else {
360 purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version"), 435 purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version unsafe verbose"),
361 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL)); 436 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL));
362 return PURPLE_CMD_RET_OK; 437 return PURPLE_CMD_RET_OK;
363 } 438 }
364 439
365 markup = g_markup_escape_text(tmp, -1); 440 markup = g_markup_escape_text(tmp, -1);
374 } 449 }
375 450
376 static void clear_conversation_scrollback_cb(PurpleConversation *conv, 451 static void clear_conversation_scrollback_cb(PurpleConversation *conv,
377 void *data) 452 void *data)
378 { 453 {
379 PidginConversation *gtkconv = NULL; 454 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
380 455
381 gtkconv = PIDGIN_CONVERSATION(conv); 456 if (PIDGIN_CONVERSATION(conv)) {
382 if (gtkconv) 457 load_conv_theme(gtkconv);
383 gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); 458 gtkconv->last_flags = 0;
459 }
384 } 460 }
385 461
386 static PurpleCmdRet 462 static PurpleCmdRet
387 clear_command_cb(PurpleConversation *conv, 463 clear_command_cb(PurpleConversation *conv,
388 const char *cmd, char **args, char **error, void *data) 464 const char *cmd, char **args, char **error, void *data)
418 g_string_append_printf(s, "%s", (char *)l->data); 494 g_string_append_printf(s, "%s", (char *)l->data);
419 } else { 495 } else {
420 g_string_append(s, _("No such command (in this context).")); 496 g_string_append(s, _("No such command (in this context)."));
421 } 497 }
422 } else { 498 } else {
423 s = g_string_new(_("Use \"/help &lt;command&gt;\" for help on a specific command.\n" 499 s = g_string_new(_("Use \"/help &lt;command&gt;\" for help on a specific command.<br/>"
424 "The following commands are available in this context:\n")); 500 "The following commands are available in this context:<br/>"));
425 501
426 text = purple_cmd_list(conv); 502 text = purple_cmd_list(conv);
427 for (l = text; l; l = l->next) 503 for (l = text; l; l = l->next)
428 if (l->next) 504 if (l->next)
429 g_string_append_printf(s, "%s, ", (char *)l->data); 505 g_string_append_printf(s, "%s, ", (char *)l->data);
496 case PURPLE_CMD_STATUS_NOT_FOUND: 572 case PURPLE_CMD_STATUS_NOT_FOUND:
497 { 573 {
498 PurplePluginProtocolInfo *prpl_info = NULL; 574 PurplePluginProtocolInfo *prpl_info = NULL;
499 PurpleConnection *gc; 575 PurpleConnection *gc;
500 576
501 if ((gc = purple_conversation_get_gc(conv))) 577 if ((gc = purple_conversation_get_connection(conv)))
502 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 578 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
503 579
504 if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) { 580 if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) {
505 char *spaceslash; 581 char *spaceslash;
506 582
507 /* If the first word in the entered text has a '/' in it, then the user 583 /* 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)); 652 buf = gtk_imhtml_get_markup(GTK_IMHTML(gtkconv->entry));
577 clean = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL); 653 clean = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL);
578 654
579 gtk_widget_grab_focus(gtkconv->entry); 655 gtk_widget_grab_focus(gtkconv->entry);
580 656
581 if (strlen(clean) == 0) { 657 if (!*clean) {
582 g_free(buf); 658 g_free(buf);
583 g_free(clean); 659 g_free(clean);
584 return; 660 return;
585 } 661 }
586 662
589 /* XXX: is there a better way to tell if the message has images? */ 665 /* XXX: is there a better way to tell if the message has images? */
590 if (GTK_IMHTML(gtkconv->entry)->im_images != NULL) 666 if (GTK_IMHTML(gtkconv->entry)->im_images != NULL)
591 flags |= PURPLE_MESSAGE_IMAGES; 667 flags |= PURPLE_MESSAGE_IMAGES;
592 668
593 gc = purple_account_get_connection(account); 669 gc = purple_account_get_connection(account);
594 if (gc && (conv->features & PURPLE_CONNECTION_NO_NEWLINES)) { 670 if (gc && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_NO_NEWLINES)) {
595 char **bufs; 671 char **bufs;
596 int i; 672 int i;
597 673
598 bufs = gtk_imhtml_get_markup_lines(GTK_IMHTML(gtkconv->entry)); 674 bufs = gtk_imhtml_get_markup_lines(GTK_IMHTML(gtkconv->entry));
599 for (i = 0; bufs[i]; i++) { 675 for (i = 0; bufs[i]; i++) {
655 static void chat_do_info(PidginConversation *gtkconv, const char *who) 731 static void chat_do_info(PidginConversation *gtkconv, const char *who)
656 { 732 {
657 PurpleConversation *conv = gtkconv->active_conv; 733 PurpleConversation *conv = gtkconv->active_conv;
658 PurpleConnection *gc; 734 PurpleConnection *gc;
659 735
660 if ((gc = purple_conversation_get_gc(conv))) { 736 if ((gc = purple_conversation_get_connection(conv))) {
661 pidgin_retrieve_user_info_in_chat(gc, who, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); 737 pidgin_retrieve_user_info_in_chat(gc, who, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)));
662 } 738 }
663 } 739 }
664 740
665 741
667 info_cb(GtkWidget *widget, PidginConversation *gtkconv) 743 info_cb(GtkWidget *widget, PidginConversation *gtkconv)
668 { 744 {
669 PurpleConversation *conv = gtkconv->active_conv; 745 PurpleConversation *conv = gtkconv->active_conv;
670 746
671 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 747 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
672 pidgin_retrieve_user_info(purple_conversation_get_gc(conv), 748 pidgin_retrieve_user_info(purple_conversation_get_connection(conv),
673 purple_conversation_get_name(conv)); 749 purple_conversation_get_name(conv));
674 gtk_widget_grab_focus(gtkconv->entry); 750 gtk_widget_grab_focus(gtkconv->entry);
675 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 751 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
676 /* Get info of the person currently selected in the GtkTreeView */ 752 /* Get info of the person currently selected in the GtkTreeView */
677 PidginChatPane *gtkchat; 753 PidginChatPane *gtkchat;
755 message = gtk_entry_get_text(GTK_ENTRY(info->message)); 831 message = gtk_entry_get_text(GTK_ENTRY(info->message));
756 832
757 if (!g_ascii_strcasecmp(buddy, "")) 833 if (!g_ascii_strcasecmp(buddy, ""))
758 return; 834 return;
759 835
760 serv_chat_invite(purple_conversation_get_gc(conv), 836 serv_chat_invite(purple_conversation_get_connection(conv),
761 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), 837 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)),
762 message, buddy); 838 message, buddy);
763 } 839 }
764 840
765 gtk_widget_destroy(invite_dialog); 841 gtk_widget_destroy(invite_dialog);
790 else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) 866 else if (PURPLE_BLIST_NODE_IS_BUDDY(node))
791 buddy = (PurpleBuddy *)node; 867 buddy = (PurpleBuddy *)node;
792 else 868 else
793 return; 869 return;
794 870
795 if (strcmp(convprotocol, purple_account_get_protocol_id(buddy->account))) 871 if (strcmp(convprotocol, purple_account_get_protocol_id(purple_buddy_get_account(buddy))))
796 { 872 {
797 purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL, 873 purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL,
798 _("That buddy is not on the same protocol as this " 874 _("That buddy is not on the same protocol as this "
799 "chat."), NULL); 875 "chat."), NULL);
800 success = FALSE; 876 success = FALSE;
875 951
876 gtk_dialog_set_default_response(GTK_DIALOG(invite_dialog), 952 gtk_dialog_set_default_response(GTK_DIALOG(invite_dialog),
877 GTK_RESPONSE_OK); 953 GTK_RESPONSE_OK);
878 gtk_container_set_border_width(GTK_CONTAINER(invite_dialog), PIDGIN_HIG_BOX_SPACE); 954 gtk_container_set_border_width(GTK_CONTAINER(invite_dialog), PIDGIN_HIG_BOX_SPACE);
879 gtk_window_set_resizable(GTK_WINDOW(invite_dialog), FALSE); 955 gtk_window_set_resizable(GTK_WINDOW(invite_dialog), FALSE);
956 #if !GTK_CHECK_VERSION(2,22,0)
880 gtk_dialog_set_has_separator(GTK_DIALOG(invite_dialog), FALSE); 957 gtk_dialog_set_has_separator(GTK_DIALOG(invite_dialog), FALSE);
958 #endif
881 959
882 info->window = GTK_WIDGET(invite_dialog); 960 info->window = GTK_WIDGET(invite_dialog);
883 961
884 /* Setup the outside spacing. */ 962 /* Setup the outside spacing. */
885 vbox = GTK_DIALOG(invite_dialog)->vbox; 963 vbox = GTK_DIALOG(invite_dialog)->vbox;
972 if (info != NULL) 1050 if (info != NULL)
973 gtk_widget_grab_focus(info->entry); 1051 gtk_widget_grab_focus(info->entry);
974 } 1052 }
975 1053
976 static void 1054 static void
977 menu_new_conv_cb(gpointer data, guint action, GtkWidget *widget) 1055 menu_new_conv_cb(GtkAction *action, gpointer data)
978 { 1056 {
979 pidgin_dialogs_im(); 1057 pidgin_dialogs_im();
980 } 1058 }
981 1059
982 static void 1060 static void
983 menu_join_chat_cb(gpointer data, guint action, GtkWidget *widget) 1061 menu_join_chat_cb(GtkAction *action, gpointer data)
984 { 1062 {
985 pidgin_blist_joinchat_show(); 1063 pidgin_blist_joinchat_show();
986 } 1064 }
987 1065
988 static void 1066 static void
989 savelog_writefile_cb(void *user_data, const char *filename) 1067 savelog_writefile_cb(void *user_data, const char *filename)
990 { 1068 {
1069 /* TODO WEBKIT: I don't know how to support this using webkit yet. */
1070 #if 0
991 PurpleConversation *conv = (PurpleConversation *)user_data; 1071 PurpleConversation *conv = (PurpleConversation *)user_data;
992 FILE *fp; 1072 FILE *fp;
993 const char *name; 1073 const char *name;
994 char **lines; 1074 char **lines;
995 gchar *text; 1075 gchar *text;
1012 g_free(text); 1092 g_free(text);
1013 g_strfreev(lines); 1093 g_strfreev(lines);
1014 1094
1015 fprintf(fp, "\n</body>\n</html>\n"); 1095 fprintf(fp, "\n</body>\n</html>\n");
1016 fclose(fp); 1096 fclose(fp);
1097 #endif /* if 0 */
1017 } 1098 }
1018 1099
1019 /* 1100 /*
1020 * It would be kinda cool if this gave the option of saving a 1101 * It would be kinda cool if this gave the option of saving a
1021 * plaintext v. HTML file. 1102 * plaintext v. HTML file.
1022 */ 1103 */
1023 static void 1104 static void
1024 menu_save_as_cb(gpointer data, guint action, GtkWidget *widget) 1105 menu_save_as_cb(GtkAction *action, gpointer data)
1025 { 1106 {
1026 PidginWindow *win = data; 1107 PidginWindow *win = data;
1027 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); 1108 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
1028 PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); 1109 PurpleAccount *account = purple_conversation_get_account(conv);
1110 PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
1029 const char *name; 1111 const char *name;
1030 gchar *buf; 1112 gchar *buf;
1031 gchar *c; 1113 gchar *c;
1032 1114
1033 if (buddy != NULL) 1115 if (buddy != NULL)
1034 name = purple_buddy_get_contact_alias(buddy); 1116 name = purple_buddy_get_contact_alias(buddy);
1035 else 1117 else
1036 name = purple_normalize(conv->account, conv->name); 1118 name = purple_normalize(account, purple_conversation_get_name(conv));
1037 1119
1038 buf = g_strdup_printf("%s.html", name); 1120 buf = g_strdup_printf("%s.html", name);
1039 for (c = buf ; *c ; c++) 1121 for (c = buf ; *c ; c++)
1040 { 1122 {
1041 if (*c == '/' || *c == '\\') 1123 if (*c == '/' || *c == '\\')
1049 1131
1050 g_free(buf); 1132 g_free(buf);
1051 } 1133 }
1052 1134
1053 static void 1135 static void
1054 menu_view_log_cb(gpointer data, guint action, GtkWidget *widget) 1136 menu_view_log_cb(GtkAction *action, gpointer data)
1055 { 1137 {
1056 PidginWindow *win = data; 1138 PidginWindow *win = data;
1057 PurpleConversation *conv; 1139 PurpleConversation *conv;
1058 PurpleLogType type; 1140 PurpleLogType type;
1059 PidginBuddyList *gtkblist; 1141 PidginBuddyList *gtkblist;
1076 1158
1077 cursor = gdk_cursor_new(GDK_WATCH); 1159 cursor = gdk_cursor_new(GDK_WATCH);
1078 gdk_window_set_cursor(gtkblist->window->window, cursor); 1160 gdk_window_set_cursor(gtkblist->window->window, cursor);
1079 gdk_window_set_cursor(win->window->window, cursor); 1161 gdk_window_set_cursor(win->window->window, cursor);
1080 gdk_cursor_unref(cursor); 1162 gdk_cursor_unref(cursor);
1081 gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window)));
1082 1163
1083 name = purple_conversation_get_name(conv); 1164 name = purple_conversation_get_name(conv);
1084 account = purple_conversation_get_account(conv); 1165 account = purple_conversation_get_account(conv);
1085 1166
1086 buddies = purple_find_buddies(account, name); 1167 buddies = purple_find_buddies(account, name);
1103 gdk_window_set_cursor(gtkblist->window->window, NULL); 1184 gdk_window_set_cursor(gtkblist->window->window, NULL);
1104 gdk_window_set_cursor(win->window->window, NULL); 1185 gdk_window_set_cursor(win->window->window, NULL);
1105 } 1186 }
1106 1187
1107 static void 1188 static void
1108 menu_clear_cb(gpointer data, guint action, GtkWidget *widget) 1189 menu_clear_cb(GtkAction *action, gpointer data)
1109 { 1190 {
1110 PidginWindow *win = data; 1191 PidginWindow *win = data;
1111 PurpleConversation *conv; 1192 PurpleConversation *conv;
1112 1193
1113 conv = pidgin_conv_window_get_active_conversation(win); 1194 conv = pidgin_conv_window_get_active_conversation(win);
1114 purple_conversation_clear_message_history(conv); 1195 purple_conversation_clear_message_history(conv);
1115 } 1196 }
1116 1197
1117 static void 1198 static void
1118 menu_find_cb(gpointer data, guint action, GtkWidget *widget) 1199 menu_find_cb(GtkAction *action, gpointer data)
1119 { 1200 {
1120 PidginWindow *gtkwin = data; 1201 PidginWindow *gtkwin = data;
1121 PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(gtkwin); 1202 PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(gtkwin);
1122 gtk_widget_show_all(gtkconv->quickfind.container); 1203 gtk_widget_show_all(gtkconv->quickfind.container);
1123 gtk_widget_grab_focus(gtkconv->quickfind.entry); 1204 gtk_widget_grab_focus(gtkconv->quickfind.entry);
1124 } 1205 }
1125 1206
1126 #ifdef USE_VV 1207 #ifdef USE_VV
1127 static void 1208 static void
1128 menu_initiate_media_call_cb(gpointer data, guint action, GtkWidget *widget) 1209 menu_initiate_media_call_cb(GtkAction *action, gpointer data)
1129 { 1210 {
1130 PidginWindow *win = (PidginWindow *)data; 1211 PidginWindow *win = (PidginWindow *)data;
1131 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); 1212 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
1132 PurpleAccount *account = purple_conversation_get_account(conv); 1213 PurpleAccount *account = purple_conversation_get_account(conv);
1133 1214
1134 purple_prpl_initiate_media(account, 1215 purple_prpl_initiate_media(account,
1135 purple_conversation_get_name(conv), 1216 purple_conversation_get_name(conv),
1136 action == 0 ? PURPLE_MEDIA_AUDIO : 1217 action == win->audio_call ? PURPLE_MEDIA_AUDIO :
1137 action == 1 ? PURPLE_MEDIA_VIDEO : 1218 action == win->video_call ? PURPLE_MEDIA_VIDEO :
1138 action == 2 ? PURPLE_MEDIA_AUDIO | 1219 action == win->audio_video_call ? PURPLE_MEDIA_AUDIO |
1139 PURPLE_MEDIA_VIDEO : PURPLE_MEDIA_NONE); 1220 PURPLE_MEDIA_VIDEO : PURPLE_MEDIA_NONE);
1140 } 1221 }
1141 #endif 1222 #endif
1142 1223
1143 static void 1224 static void
1144 menu_send_file_cb(gpointer data, guint action, GtkWidget *widget) 1225 menu_send_file_cb(GtkAction *action, gpointer data)
1145 { 1226 {
1146 PidginWindow *win = data; 1227 PidginWindow *win = data;
1147 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); 1228 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
1148 1229
1149 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 1230 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
1150 serv_send_file(purple_conversation_get_gc(conv), purple_conversation_get_name(conv), NULL); 1231 serv_send_file(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), NULL);
1151 } 1232 }
1152 1233
1153 } 1234 }
1154 1235
1155 static void 1236 static void
1156 menu_get_attention_cb(gpointer data, guint action, GtkWidget *widget) 1237 menu_get_attention_cb(GObject *obj, gpointer data)
1157 { 1238 {
1158 PidginWindow *win = data; 1239 PidginWindow *win = data;
1159 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); 1240 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
1160 1241
1161 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 1242 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
1162 purple_prpl_send_attention(purple_conversation_get_gc(conv), 1243 int index;
1163 purple_conversation_get_name(conv), 0); 1244 if ((GtkAction *)obj == win->menu.get_attention)
1164 } 1245 index = 0;
1165 } 1246 else
1166 1247 index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(obj), "index"));
1167 static void 1248 purple_prpl_send_attention(purple_conversation_get_connection(conv),
1168 menu_add_pounce_cb(gpointer data, guint action, GtkWidget *widget) 1249 purple_conversation_get_name(conv), index);
1250 }
1251 }
1252
1253 static void
1254 menu_add_pounce_cb(GtkAction *action, gpointer data)
1169 { 1255 {
1170 PidginWindow *win = data; 1256 PidginWindow *win = data;
1171 PurpleConversation *conv; 1257 PurpleConversation *conv;
1172 1258
1173 conv = pidgin_conv_window_get_active_gtkconv(win)->active_conv; 1259 conv = pidgin_conv_window_get_active_gtkconv(win)->active_conv;
1175 pidgin_pounce_editor_show(purple_conversation_get_account(conv), 1261 pidgin_pounce_editor_show(purple_conversation_get_account(conv),
1176 purple_conversation_get_name(conv), NULL); 1262 purple_conversation_get_name(conv), NULL);
1177 } 1263 }
1178 1264
1179 static void 1265 static void
1180 menu_insert_link_cb(gpointer data, guint action, GtkWidget *widget) 1266 menu_insert_link_cb(GtkAction *action, gpointer data)
1181 { 1267 {
1182 PidginWindow *win = data; 1268 PidginWindow *win = data;
1183 PidginConversation *gtkconv; 1269 PidginConversation *gtkconv;
1184 GtkIMHtmlToolbar *toolbar; 1270 GtkIMHtmlToolbar *toolbar;
1185 1271
1189 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->link), 1275 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->link),
1190 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->link))); 1276 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->link)));
1191 } 1277 }
1192 1278
1193 static void 1279 static void
1194 menu_insert_image_cb(gpointer data, guint action, GtkWidget *widget) 1280 menu_insert_image_cb(GtkAction *action, gpointer data)
1195 { 1281 {
1196 PidginWindow *win = data; 1282 PidginWindow *win = data;
1197 PidginConversation *gtkconv; 1283 PidginConversation *gtkconv;
1198 GtkIMHtmlToolbar *toolbar; 1284 GtkIMHtmlToolbar *toolbar;
1199 1285
1204 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->image))); 1290 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->image)));
1205 } 1291 }
1206 1292
1207 1293
1208 static void 1294 static void
1209 menu_alias_cb(gpointer data, guint action, GtkWidget *widget) 1295 menu_alias_cb(GtkAction *action, gpointer data)
1210 { 1296 {
1211 PidginWindow *win = data; 1297 PidginWindow *win = data;
1212 PurpleConversation *conv; 1298 PurpleConversation *conv;
1213 PurpleAccount *account; 1299 PurpleAccount *account;
1214 const char *name; 1300 const char *name;
1231 pidgin_dialogs_alias_chat(c); 1317 pidgin_dialogs_alias_chat(c);
1232 } 1318 }
1233 } 1319 }
1234 1320
1235 static void 1321 static void
1236 menu_get_info_cb(gpointer data, guint action, GtkWidget *widget) 1322 menu_get_info_cb(GtkAction *action, gpointer data)
1237 { 1323 {
1238 PidginWindow *win = data; 1324 PidginWindow *win = data;
1239 PurpleConversation *conv; 1325 PurpleConversation *conv;
1240 1326
1241 conv = pidgin_conv_window_get_active_conversation(win); 1327 conv = pidgin_conv_window_get_active_conversation(win);
1242 1328
1243 info_cb(NULL, PIDGIN_CONVERSATION(conv)); 1329 info_cb(NULL, PIDGIN_CONVERSATION(conv));
1244 } 1330 }
1245 1331
1246 static void 1332 static void
1247 menu_invite_cb(gpointer data, guint action, GtkWidget *widget) 1333 menu_invite_cb(GtkAction *action, gpointer data)
1248 { 1334 {
1249 PidginWindow *win = data; 1335 PidginWindow *win = data;
1250 PurpleConversation *conv; 1336 PurpleConversation *conv;
1251 1337
1252 conv = pidgin_conv_window_get_active_conversation(win); 1338 conv = pidgin_conv_window_get_active_conversation(win);
1253 1339
1254 invite_cb(NULL, PIDGIN_CONVERSATION(conv)); 1340 invite_cb(NULL, PIDGIN_CONVERSATION(conv));
1255 } 1341 }
1256 1342
1257 static void 1343 static void
1258 menu_block_cb(gpointer data, guint action, GtkWidget *widget) 1344 menu_block_cb(GtkAction *action, gpointer data)
1259 { 1345 {
1260 PidginWindow *win = data; 1346 PidginWindow *win = data;
1261 PurpleConversation *conv; 1347 PurpleConversation *conv;
1262 1348
1263 conv = pidgin_conv_window_get_active_conversation(win); 1349 conv = pidgin_conv_window_get_active_conversation(win);
1264 1350
1265 block_cb(NULL, PIDGIN_CONVERSATION(conv)); 1351 block_cb(NULL, PIDGIN_CONVERSATION(conv));
1266 } 1352 }
1267 1353
1268 static void 1354 static void
1269 menu_unblock_cb(gpointer data, guint action, GtkWidget *widget) 1355 menu_unblock_cb(GtkAction *action, gpointer data)
1270 { 1356 {
1271 PidginWindow *win = data; 1357 PidginWindow *win = data;
1272 PurpleConversation *conv; 1358 PurpleConversation *conv;
1273 1359
1274 conv = pidgin_conv_window_get_active_conversation(win); 1360 conv = pidgin_conv_window_get_active_conversation(win);
1275 1361
1276 unblock_cb(NULL, PIDGIN_CONVERSATION(conv)); 1362 unblock_cb(NULL, PIDGIN_CONVERSATION(conv));
1277 } 1363 }
1278 1364
1279 static void 1365 static void
1280 menu_add_remove_cb(gpointer data, guint action, GtkWidget *widget) 1366 menu_add_remove_cb(GtkAction *action, gpointer data)
1281 { 1367 {
1282 PidginWindow *win = data; 1368 PidginWindow *win = data;
1283 PurpleConversation *conv; 1369 PurpleConversation *conv;
1284 1370
1285 conv = pidgin_conv_window_get_active_conversation(win); 1371 conv = pidgin_conv_window_get_active_conversation(win);
1320 #endif 1406 #endif
1321 } 1407 }
1322 } 1408 }
1323 1409
1324 static void 1410 static void
1325 menu_close_conv_cb(gpointer data, guint action, GtkWidget *widget) 1411 menu_close_conv_cb(GtkAction *action, gpointer data)
1326 { 1412 {
1327 PidginWindow *win = data; 1413 PidginWindow *win = data;
1328 1414
1329 close_conv_cb(NULL, PIDGIN_CONVERSATION(pidgin_conv_window_get_active_conversation(win))); 1415 close_conv_cb(NULL, PIDGIN_CONVERSATION(pidgin_conv_window_get_active_conversation(win)));
1330 } 1416 }
1331 1417
1332 static void 1418 static void
1333 menu_logging_cb(gpointer data, guint action, GtkWidget *widget) 1419 menu_logging_cb(GtkAction *action, gpointer data)
1334 { 1420 {
1335 PidginWindow *win = data; 1421 PidginWindow *win = data;
1336 PurpleConversation *conv; 1422 PurpleConversation *conv;
1337 gboolean logging; 1423 gboolean logging;
1338 PurpleBlistNode *node; 1424 PurpleBlistNode *node;
1340 conv = pidgin_conv_window_get_active_conversation(win); 1426 conv = pidgin_conv_window_get_active_conversation(win);
1341 1427
1342 if (conv == NULL) 1428 if (conv == NULL)
1343 return; 1429 return;
1344 1430
1345 logging = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); 1431 logging = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
1346 1432
1347 if (logging == purple_conversation_is_logging(conv)) 1433 if (logging == purple_conversation_is_logging(conv))
1348 return; 1434 return;
1349 1435
1350 node = get_conversation_blist_node(conv); 1436 node = get_conversation_blist_node(conv);
1354 /* Enable logging first so the message below can be logged. */ 1440 /* Enable logging first so the message below can be logged. */
1355 purple_conversation_set_logging(conv, TRUE); 1441 purple_conversation_set_logging(conv, TRUE);
1356 1442
1357 purple_conversation_write(conv, NULL, 1443 purple_conversation_write(conv, NULL,
1358 _("Logging started. Future messages in this conversation will be logged."), 1444 _("Logging started. Future messages in this conversation will be logged."),
1359 conv->logs ? (PURPLE_MESSAGE_SYSTEM) : 1445 PURPLE_MESSAGE_SYSTEM,
1360 (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG),
1361 time(NULL)); 1446 time(NULL));
1362 } 1447 }
1363 else 1448 else
1364 { 1449 {
1365 purple_conversation_write(conv, NULL, 1450 purple_conversation_write(conv, NULL,
1366 _("Logging stopped. Future messages in this conversation will not be logged."), 1451 _("Logging stopped. Future messages in this conversation will not be logged."),
1367 conv->logs ? (PURPLE_MESSAGE_SYSTEM) : 1452 PURPLE_MESSAGE_SYSTEM,
1368 (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG),
1369 time(NULL)); 1453 time(NULL));
1370 1454
1371 /* Disable the logging second, so that the above message can be logged. */ 1455 /* Disable the logging second, so that the above message can be logged. */
1372 purple_conversation_set_logging(conv, FALSE); 1456 purple_conversation_set_logging(conv, FALSE);
1373 } 1457 }
1374 1458
1375 /* Save the setting IFF it's different than the pref. */ 1459 /* Save the setting IFF it's different than the pref. */
1376 switch (conv->type) 1460 switch (purple_conversation_get_type(conv))
1377 { 1461 {
1378 case PURPLE_CONV_TYPE_IM: 1462 case PURPLE_CONV_TYPE_IM:
1379 if (logging == purple_prefs_get_bool("/purple/logging/log_ims")) 1463 if (logging == purple_prefs_get_bool("/purple/logging/log_ims"))
1380 purple_blist_node_remove_setting(node, "enable-logging"); 1464 purple_blist_node_remove_setting(node, "enable-logging");
1381 else 1465 else
1393 break; 1477 break;
1394 } 1478 }
1395 } 1479 }
1396 1480
1397 static void 1481 static void
1398 menu_toolbar_cb(gpointer data, guint action, GtkWidget *widget) 1482 menu_toolbar_cb(GtkAction *action, gpointer data)
1399 { 1483 {
1400 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar", 1484 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar",
1401 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); 1485 gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)));
1402 } 1486 }
1403 1487
1404 static void 1488 static void
1405 menu_sounds_cb(gpointer data, guint action, GtkWidget *widget) 1489 menu_sounds_cb(GtkAction *action, gpointer data)
1406 { 1490 {
1407 PidginWindow *win = data; 1491 PidginWindow *win = data;
1408 PurpleConversation *conv; 1492 PurpleConversation *conv;
1409 PidginConversation *gtkconv; 1493 PidginConversation *gtkconv;
1410 PurpleBlistNode *node; 1494 PurpleBlistNode *node;
1415 return; 1499 return;
1416 1500
1417 gtkconv = PIDGIN_CONVERSATION(conv); 1501 gtkconv = PIDGIN_CONVERSATION(conv);
1418 1502
1419 gtkconv->make_sound = 1503 gtkconv->make_sound =
1420 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); 1504 gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
1421 node = get_conversation_blist_node(conv); 1505 node = get_conversation_blist_node(conv);
1422 if (node) 1506 if (node)
1423 purple_blist_node_set_bool(node, "gtk-mute-sound", !gtkconv->make_sound); 1507 purple_blist_node_set_bool(node, "gtk-mute-sound", !gtkconv->make_sound);
1424 }
1425
1426 static void
1427 menu_timestamps_cb(gpointer data, guint action, GtkWidget *widget)
1428 {
1429 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps",
1430 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)));
1431 } 1508 }
1432 1509
1433 static void 1510 static void
1434 chat_do_im(PidginConversation *gtkconv, const char *who) 1511 chat_do_im(PidginConversation *gtkconv, const char *who)
1435 { 1512 {
1443 g_return_if_fail(account != NULL); 1520 g_return_if_fail(account != NULL);
1444 1521
1445 gc = purple_account_get_connection(account); 1522 gc = purple_account_get_connection(account);
1446 g_return_if_fail(gc != NULL); 1523 g_return_if_fail(gc != NULL);
1447 1524
1448 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 1525 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1449 1526
1450 if (prpl_info && prpl_info->get_cb_real_name) 1527 if (prpl_info && prpl_info->get_cb_real_name)
1451 real_who = prpl_info->get_cb_real_name(gc, 1528 real_who = prpl_info->get_cb_real_name(gc,
1452 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); 1529 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
1453 1530
1494 menu_chat_send_file_cb(GtkWidget *w, PidginConversation *gtkconv) 1571 menu_chat_send_file_cb(GtkWidget *w, PidginConversation *gtkconv)
1495 { 1572 {
1496 PurplePluginProtocolInfo *prpl_info; 1573 PurplePluginProtocolInfo *prpl_info;
1497 PurpleConversation *conv = gtkconv->active_conv; 1574 PurpleConversation *conv = gtkconv->active_conv;
1498 const char *who = g_object_get_data(G_OBJECT(w), "user_data"); 1575 const char *who = g_object_get_data(G_OBJECT(w), "user_data");
1499 PurpleConnection *gc = purple_conversation_get_gc(conv); 1576 PurpleConnection *gc = purple_conversation_get_connection(conv);
1500 gchar *real_who = NULL; 1577 gchar *real_who = NULL;
1501 1578
1502 g_return_if_fail(gc != NULL); 1579 g_return_if_fail(gc != NULL);
1503 1580
1504 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 1581 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1505 1582
1506 if (prpl_info && prpl_info->get_cb_real_name) 1583 if (prpl_info && prpl_info->get_cb_real_name)
1507 real_who = prpl_info->get_cb_real_name(gc, 1584 real_who = prpl_info->get_cb_real_name(gc,
1508 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); 1585 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
1509 1586
1517 char *who; 1594 char *who;
1518 1595
1519 who = g_object_get_data(G_OBJECT(w), "user_data"); 1596 who = g_object_get_data(G_OBJECT(w), "user_data");
1520 1597
1521 chat_do_info(gtkconv, who); 1598 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 } 1599 }
1549 1600
1550 static void 1601 static void
1551 menu_chat_add_remove_cb(GtkWidget *w, PidginConversation *gtkconv) 1602 menu_chat_add_remove_cb(GtkWidget *w, PidginConversation *gtkconv)
1552 { 1603 {
1568 } 1619 }
1569 1620
1570 static GtkTextMark * 1621 static GtkTextMark *
1571 get_mark_for_user(PidginConversation *gtkconv, const char *who) 1622 get_mark_for_user(PidginConversation *gtkconv, const char *who)
1572 { 1623 {
1573 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)); 1624 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->webview));
1574 char *tmp = g_strconcat("user:", who, NULL); 1625 char *tmp = g_strconcat("user:", who, NULL);
1575 GtkTextMark *mark = gtk_text_buffer_get_mark(buf, tmp); 1626 GtkTextMark *mark = gtk_text_buffer_get_mark(buf, tmp);
1576 1627
1577 g_free(tmp); 1628 g_free(tmp);
1578 return mark; 1629 return mark;
1579 } 1630 }
1580 1631
1581 static void 1632 static void
1582 menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv) 1633 menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv)
1583 { 1634 {
1635 /* TODO WEBKIT: This doesn't work yet, of course... */
1636 #if 0
1584 GtkTextMark *mark; 1637 GtkTextMark *mark;
1585 const char *who; 1638 const char *who;
1586 1639
1587 who = g_object_get_data(G_OBJECT(w), "user_data"); 1640 who = g_object_get_data(G_OBJECT(w), "user_data");
1588 mark = get_mark_for_user(gtkconv, who); 1641 mark = get_mark_for_user(gtkconv, who);
1589 1642
1590 if (mark != NULL) 1643 if (mark != NULL)
1591 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0); 1644 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0);
1592 else 1645 else
1593 g_return_if_reached(); 1646 g_return_if_reached();
1647 #endif /* if 0 */
1594 } 1648 }
1595 1649
1596 static GtkWidget * 1650 static GtkWidget *
1597 create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc) 1651 create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc)
1598 { 1652 {
1599 static GtkWidget *menu = NULL; 1653 static GtkWidget *menu = NULL;
1600 PurplePluginProtocolInfo *prpl_info = NULL; 1654 PurplePluginProtocolInfo *prpl_info = NULL;
1601 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); 1655 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
1656 PurpleAccount *account = purple_conversation_get_account(conv);
1602 gboolean is_me = FALSE; 1657 gboolean is_me = FALSE;
1603 GtkWidget *button; 1658 GtkWidget *button;
1604 PurpleBuddy *buddy = NULL; 1659 PurpleBuddy *buddy = NULL;
1605 1660
1606 if (gc != NULL) 1661 if (gc != NULL)
1607 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 1662 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1608 1663
1609 /* 1664 /*
1610 * If a menu already exists, destroy it before creating a new one, 1665 * If a menu already exists, destroy it before creating a new one,
1611 * thus freeing-up the memory it occupied. 1666 * thus freeing-up the memory it occupied.
1612 */ 1667 */
1613 if (menu) 1668 if (menu)
1614 gtk_widget_destroy(menu); 1669 gtk_widget_destroy(menu);
1615 1670
1616 if (!strcmp(chat->nick, purple_normalize(conv->account, who))) 1671 if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, who)))
1617 is_me = TRUE; 1672 is_me = TRUE;
1618 1673
1619 menu = gtk_menu_new(); 1674 menu = gtk_menu_new();
1620 1675
1621 if (!is_me) { 1676 if (!is_me) {
1676 gtk_widget_set_sensitive(button, FALSE); 1731 gtk_widget_set_sensitive(button, FALSE);
1677 else 1732 else
1678 g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free); 1733 g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
1679 } 1734 }
1680 1735
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)) { 1736 if (!is_me && prpl_info && !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
1692 if ((buddy = purple_find_buddy(conv->account, who)) != NULL) 1737 if ((buddy = purple_find_buddy(account, who)) != NULL)
1693 button = pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE, 1738 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); 1739 G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
1695 else 1740 else
1696 button = pidgin_new_item_from_stock(menu, _("Add"), GTK_STOCK_ADD, 1741 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); 1742 G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
1708 if (!get_mark_for_user(PIDGIN_CONVERSATION(conv), who)) 1753 if (!get_mark_for_user(PIDGIN_CONVERSATION(conv), who))
1709 gtk_widget_set_sensitive(button, FALSE); 1754 gtk_widget_set_sensitive(button, FALSE);
1710 1755
1711 if (buddy != NULL) 1756 if (buddy != NULL)
1712 { 1757 {
1713 if (purple_account_is_connected(conv->account)) 1758 if (purple_account_is_connected(account))
1714 pidgin_append_blist_node_proto_menu(menu, conv->account->gc, 1759 pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account),
1715 (PurpleBlistNode *)buddy); 1760 (PurpleBlistNode *)buddy);
1716 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy); 1761 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy);
1717 gtk_widget_show_all(menu); 1762 gtk_widget_show_all(menu);
1718 } 1763 }
1719 1764
1735 gchar *who; 1780 gchar *who;
1736 1781
1737 gtkconv = PIDGIN_CONVERSATION(conv); 1782 gtkconv = PIDGIN_CONVERSATION(conv);
1738 gtkchat = gtkconv->u.chat; 1783 gtkchat = gtkconv->u.chat;
1739 account = purple_conversation_get_account(conv); 1784 account = purple_conversation_get_account(conv);
1740 gc = account->gc; 1785 gc = purple_account_get_connection(account);
1741 1786
1742 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 1787 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
1743 1788
1744 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkchat->list)); 1789 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkchat->list));
1745 if(!gtk_tree_selection_get_selected(sel, NULL, &iter)) 1790 if(!gtk_tree_selection_get_selected(sel, NULL, &iter))
1771 gchar *who; 1816 gchar *who;
1772 int x, y; 1817 int x, y;
1773 1818
1774 gtkchat = gtkconv->u.chat; 1819 gtkchat = gtkconv->u.chat;
1775 account = purple_conversation_get_account(conv); 1820 account = purple_conversation_get_account(conv);
1776 gc = account->gc; 1821 gc = purple_account_get_connection(account);
1777 1822
1778 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 1823 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
1779 1824
1780 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list), 1825 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list),
1781 event->x, event->y, &path, &column, &x, &y); 1826 event->x, event->y, &path, &column, &x, &y);
1803 1848
1804 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { 1849 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) {
1805 chat_do_im(gtkconv, who); 1850 chat_do_im(gtkconv, who);
1806 } else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) { 1851 } else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) {
1807 /* Move to user's anchor */ 1852 /* Move to user's anchor */
1853 /* TODO WEBKIT: This isn't implemented yet. */
1854 #if 0
1808 GtkTextMark *mark = get_mark_for_user(gtkconv, who); 1855 GtkTextMark *mark = get_mark_for_user(gtkconv, who);
1809 1856
1810 if(mark != NULL) 1857 if(mark != NULL)
1811 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0); 1858 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0);
1859 #endif /* if 0 */
1812 } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { 1860 } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
1813 GtkWidget *menu = create_chat_menu (conv, who, gc); 1861 GtkWidget *menu = create_chat_menu (conv, who, gc);
1814 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 1862 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1815 event->button, event->time); 1863 event->button, event->time);
1816 } 1864 }
1883 GtkWidget *next = NULL; 1931 GtkWidget *next = NULL;
1884 struct { 1932 struct {
1885 GtkWidget *from; 1933 GtkWidget *from;
1886 GtkWidget *to; 1934 GtkWidget *to;
1887 } transitions[] = { 1935 } transitions[] = {
1888 {gtkconv->entry, gtkconv->imhtml}, 1936 {gtkconv->entry, gtkconv->webview},
1889 {gtkconv->imhtml, chat ? gtkconv->u.chat->list : gtkconv->entry}, 1937 {gtkconv->webview, chat ? gtkconv->u.chat->list : gtkconv->entry},
1890 {chat ? gtkconv->u.chat->list : NULL, gtkconv->entry}, 1938 {chat ? gtkconv->u.chat->list : NULL, gtkconv->entry},
1891 {NULL, NULL} 1939 {NULL, NULL}
1892 }, *ptr; 1940 }, *ptr;
1893 1941
1894 for (ptr = transitions; !next && ptr->from; ptr++) { 1942 for (ptr = transitions; !next && ptr->from; ptr++) {
2140 return plugin_return ? TRUE : tab_complete(conv); 2188 return plugin_return ? TRUE : tab_complete(conv);
2141 } 2189 }
2142 break; 2190 break;
2143 2191
2144 case GDK_Page_Up: 2192 case GDK_Page_Up:
2145 case GDK_KP_Page_Up: 2193 case GDK_KP_Page_Up:
2146 gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml)); 2194 gtk_webview_page_up(GTK_WEBVIEW(gtkconv->webview));
2147 return TRUE; 2195 return TRUE;
2148 break; 2196 break;
2149 2197
2150 case GDK_Page_Down: 2198 case GDK_Page_Down:
2151 case GDK_KP_Page_Down: 2199 case GDK_KP_Page_Down:
2152 gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml)); 2200 gtk_webview_page_down(GTK_WEBVIEW(gtkconv->webview));
2153 return TRUE; 2201 return TRUE;
2154 break; 2202 break;
2155 2203
2156 } 2204 }
2157 } 2205 }
2234 { 2282 {
2235 PidginConversation *gtkconv; 2283 PidginConversation *gtkconv;
2236 PurpleConversation *old_conv; 2284 PurpleConversation *old_conv;
2237 GtkIMHtml *entry; 2285 GtkIMHtml *entry;
2238 const char *protocol_name; 2286 const char *protocol_name;
2287 PurpleConnectionFlags features;
2239 2288
2240 g_return_if_fail(conv != NULL); 2289 g_return_if_fail(conv != NULL);
2241 2290
2242 gtkconv = PIDGIN_CONVERSATION(conv); 2291 gtkconv = PIDGIN_CONVERSATION(conv);
2243 old_conv = gtkconv->active_conv; 2292 old_conv = gtkconv->active_conv;
2252 2301
2253 purple_conversation_close_logs(old_conv); 2302 purple_conversation_close_logs(old_conv);
2254 gtkconv->active_conv = conv; 2303 gtkconv->active_conv = conv;
2255 2304
2256 purple_conversation_set_logging(conv, 2305 purple_conversation_set_logging(conv,
2257 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging))); 2306 gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(gtkconv->win->menu.logging)));
2258 2307
2259 entry = GTK_IMHTML(gtkconv->entry); 2308 entry = GTK_IMHTML(gtkconv->entry);
2260 protocol_name = purple_account_get_protocol_name(conv->account); 2309 protocol_name = purple_account_get_protocol_name(purple_conversation_get_account(conv));
2261 gtk_imhtml_set_protocol_name(entry, protocol_name); 2310 gtk_imhtml_set_protocol_name(entry, protocol_name);
2262 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); 2311 /* TODO WEBKIT: gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); */
2263 2312
2264 if (!(conv->features & PURPLE_CONNECTION_HTML)) 2313 features = purple_conversation_get_features(conv);
2314 if (!(features & PURPLE_CONNECTION_HTML))
2265 gtk_imhtml_clear_formatting(GTK_IMHTML(gtkconv->entry)); 2315 gtk_imhtml_clear_formatting(GTK_IMHTML(gtkconv->entry));
2266 else if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO && 2316 else if (features & PURPLE_CONNECTION_FORMATTING_WBFO &&
2267 !(old_conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)) 2317 !(purple_conversation_get_features(old_conv) & PURPLE_CONNECTION_FORMATTING_WBFO))
2268 { 2318 {
2269 /* The old conversation allowed formatting on parts of the 2319 /* The old conversation allowed formatting on parts of the
2270 * buffer, but the new one only allows it on the whole 2320 * buffer, but the new one only allows it on the whole
2271 * buffer. This code saves the formatting from the current 2321 * buffer. This code saves the formatting from the current
2272 * position of the cursor, clears the formatting, then 2322 * position of the cursor, clears the formatting, then
2302 if (underline != underline2) 2352 if (underline != underline2)
2303 gtk_imhtml_toggle_underline(entry); 2353 gtk_imhtml_toggle_underline(entry);
2304 2354
2305 gtk_imhtml_toggle_fontface(entry, fontface); 2355 gtk_imhtml_toggle_fontface(entry, fontface);
2306 2356
2307 if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE)) 2357 if (!(features & PURPLE_CONNECTION_NO_FONTSIZE))
2308 gtk_imhtml_font_set_size(entry, fontsize); 2358 gtk_imhtml_font_set_size(entry, fontsize);
2309 2359
2310 gtk_imhtml_toggle_forecolor(entry, forecolor); 2360 gtk_imhtml_toggle_forecolor(entry, forecolor);
2311 2361
2312 if (!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR)) 2362 if (!(features & PURPLE_CONNECTION_NO_BGCOLOR))
2313 { 2363 {
2314 gtk_imhtml_toggle_backcolor(entry, backcolor); 2364 gtk_imhtml_toggle_backcolor(entry, backcolor);
2315 gtk_imhtml_toggle_background(entry, background); 2365 gtk_imhtml_toggle_background(entry, background);
2316 } 2366 }
2317 2367
2325 /* This is done in default_formatize, which is called from clear_formatting_cb, 2375 /* 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 2376 * 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 2377 * 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. */ 2378 * preserve the formatting exactly as it is), so we have to do this now. */
2329 gtk_imhtml_set_whole_buffer_formatting_only(entry, 2379 gtk_imhtml_set_whole_buffer_formatting_only(entry,
2330 (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)); 2380 (features & PURPLE_CONNECTION_FORMATTING_WBFO));
2331 } 2381 }
2332 2382
2333 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv); 2383 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv);
2334 2384
2335 gray_stuff_out(gtkconv); 2385 gray_stuff_out(gtkconv);
2390 if (gtk_text_iter_is_start(start_pos) && gtk_text_iter_is_end(end_pos)) { 2440 if (gtk_text_iter_is_start(start_pos) && gtk_text_iter_is_end(end_pos)) {
2391 2441
2392 /* We deleted all the text, so turn off typing. */ 2442 /* We deleted all the text, so turn off typing. */
2393 purple_conv_im_stop_send_typed_timeout(im); 2443 purple_conv_im_stop_send_typed_timeout(im);
2394 2444
2395 serv_send_typing(purple_conversation_get_gc(conv), 2445 serv_send_typing(purple_conversation_get_connection(conv),
2396 purple_conversation_get_name(conv), 2446 purple_conversation_get_name(conv),
2397 PURPLE_NOT_TYPING); 2447 PURPLE_NOT_TYPING);
2398 } 2448 }
2399 else { 2449 else {
2400 /* We're deleting, but not all of it, so it counts as typing. */ 2450 /* We're deleting, but not all of it, so it counts as typing. */
2555 return; 2605 return;
2556 2606
2557 status = infopane_status = pidgin_conv_get_icon_stock(conv); 2607 status = infopane_status = pidgin_conv_get_icon_stock(conv);
2558 2608
2559 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 2609 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
2560 PurpleBuddy *b = purple_find_buddy(conv->account, conv->name); 2610 PurpleBuddy *b = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
2561 if (b) 2611 if (b)
2562 emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b); 2612 emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b);
2563 } 2613 }
2564 2614
2565 g_return_if_fail(status != NULL); 2615 g_return_if_fail(status != NULL);
2576 CONV_EMBLEM_COLUMN, emblem, -1); 2626 CONV_EMBLEM_COLUMN, emblem, -1);
2577 if (emblem) 2627 if (emblem)
2578 g_object_unref(emblem); 2628 g_object_unref(emblem);
2579 2629
2580 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) { 2630 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); 2631 emblem = pidgin_create_prpl_icon(purple_conversation_get_account(gtkconv->active_conv), PIDGIN_PRPL_ICON_SMALL);
2582 } else { 2632 } else {
2583 emblem = NULL; 2633 emblem = NULL;
2584 } 2634 }
2585 2635
2586 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model), 2636 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model),
2632 int size; 2682 int size;
2633 2683
2634 gtkconv = PIDGIN_CONVERSATION(conv); 2684 gtkconv = PIDGIN_CONVERSATION(conv);
2635 account = purple_conversation_get_account(conv); 2685 account = purple_conversation_get_account(conv);
2636 2686
2637 if (!(account && account->gc)) { 2687 if (!(account && purple_account_get_connection(account))) {
2638 gtkconv->u.im->icon_timer = 0; 2688 gtkconv->u.im->icon_timer = 0;
2639 return FALSE; 2689 return FALSE;
2640 } 2690 }
2641 2691
2642 gdk_pixbuf_animation_iter_advance(gtkconv->u.im->iter, NULL); 2692 gdk_pixbuf_animation_iter_advance(gtkconv->u.im->iter, NULL);
2839 2889
2840 g_return_if_fail(conv != NULL); 2890 g_return_if_fail(conv != NULL);
2841 2891
2842 ext = purple_buddy_icon_get_extension(purple_conv_im_get_icon(PURPLE_CONV_IM(conv))); 2892 ext = purple_buddy_icon_get_extension(purple_conv_im_get_icon(PURPLE_CONV_IM(conv)));
2843 2893
2844 buf = g_strdup_printf("%s.%s", purple_normalize(conv->account, conv->name), ext); 2894 buf = g_strdup_printf("%s.%s", purple_normalize(purple_conversation_get_account(conv), purple_conversation_get_name(conv)), ext);
2845 2895
2846 purple_request_file(gtkconv, _("Save Icon"), buf, TRUE, 2896 purple_request_file(gtkconv, _("Save Icon"), buf, TRUE,
2847 G_CALLBACK(saveicon_writefile_cb), NULL, 2897 G_CALLBACK(saveicon_writefile_cb), NULL,
2848 conv->account, NULL, conv, 2898 purple_conversation_get_account(conv), NULL, conv,
2849 gtkconv); 2899 gtkconv);
2850 2900
2851 g_free(buf); 2901 g_free(buf);
2852 } 2902 }
2853 2903
3066 { 3116 {
3067 g_return_val_if_fail(gtkconv != NULL, NULL); 3117 g_return_val_if_fail(gtkconv != NULL, NULL);
3068 return gtkconv->win; 3118 return gtkconv->win;
3069 } 3119 }
3070 3120
3071 static GtkItemFactoryEntry menu_items[] = 3121 static GtkActionEntry menu_entries[] =
3122 /* TODO: fill out tooltips... */
3072 { 3123 {
3073 /* Conversation menu */ 3124 /* Conversation menu */
3074 { N_("/_Conversation"), NULL, NULL, 0, "<Branch>", NULL }, 3125 { "ConversationMenu", NULL, N_("_Conversation"), NULL, NULL, NULL },
3075 3126 { "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "<control>M", NULL, G_CALLBACK(menu_new_conv_cb) },
3076 { N_("/Conversation/New Instant _Message..."), "<CTL>M", menu_new_conv_cb, 3127 { "JoinAChat", PIDGIN_STOCK_CHAT, N_("Join a _Chat..."), NULL, NULL, G_CALLBACK(menu_join_chat_cb) },
3077 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW }, 3128 { "Find", GTK_STOCK_FIND, N_("_Find..."), NULL, NULL, G_CALLBACK(menu_find_cb) },
3078 { N_("/Conversation/Join a _Chat..."), NULL, menu_join_chat_cb, 3129 { "ViewLog", NULL, N_("View _Log"), NULL, NULL, G_CALLBACK(menu_view_log_cb) },
3079 0, "<StockItem>", PIDGIN_STOCK_CHAT }, 3130 { "SaveAs", GTK_STOCK_SAVE_AS, N_("_Save As..."), NULL, NULL, G_CALLBACK(menu_save_as_cb) },
3080 3131 { "ClearScrollback", GTK_STOCK_CLEAR, N_("Clea_r Scrollback"), "<control>L", NULL, G_CALLBACK(menu_clear_cb) },
3081 { "/Conversation/sep0", NULL, NULL, 0, "<Separator>", NULL },
3082
3083 { N_("/Conversation/_Find..."), NULL, menu_find_cb, 0,
3084 "<StockItem>", GTK_STOCK_FIND },
3085 { N_("/Conversation/View _Log"), NULL, menu_view_log_cb, 0, "<Item>", NULL },
3086 { N_("/Conversation/_Save As..."), NULL, menu_save_as_cb, 0,
3087 "<StockItem>", GTK_STOCK_SAVE_AS },
3088 { N_("/Conversation/Clea_r Scrollback"), "<CTL>L", menu_clear_cb, 0, "<StockItem>", GTK_STOCK_CLEAR },
3089
3090 { "/Conversation/sep1", NULL, NULL, 0, "<Separator>", NULL },
3091 3132
3092 #ifdef USE_VV 3133 #ifdef USE_VV
3093 { N_("/Conversation/M_edia"), NULL, NULL, 0, "<Branch>", NULL }, 3134 { "MediaMenu", NULL, N_("M_edia"), NULL, NULL, NULL },
3094 3135 { "AudioCall", PIDGIN_STOCK_TOOLBAR_AUDIO_CALL, N_("_Audio Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) },
3095 { N_("/Conversation/Media/_Audio Call"), NULL, menu_initiate_media_call_cb, 0, 3136 { "VideoCall", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, N_("_Video Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) },
3096 "<StockItem>", PIDGIN_STOCK_TOOLBAR_AUDIO_CALL }, 3137 { "AudioVideoCall", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, N_("Audio/Video _Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) },
3097 { N_("/Conversation/Media/_Video Call"), NULL, menu_initiate_media_call_cb, 1,
3098 "<StockItem>", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL },
3099 { N_("/Conversation/Media/Audio\\/Video _Call"), NULL, menu_initiate_media_call_cb, 2,
3100 "<StockItem>", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL },
3101 #endif 3138 #endif
3102 3139
3103 { N_("/Conversation/Se_nd File..."), NULL, menu_send_file_cb, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SEND_FILE }, 3140 { "SendFile", PIDGIN_STOCK_TOOLBAR_SEND_FILE, N_("Se_nd File..."), NULL, NULL, G_CALLBACK(menu_send_file_cb) },
3104 { N_("/Conversation/Get _Attention"), NULL, menu_get_attention_cb, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION }, 3141 { "GetAttention", PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION, N_("Get _Attention"), NULL, NULL, G_CALLBACK(menu_get_attention_cb) },
3105 { N_("/Conversation/Add Buddy _Pounce..."), NULL, menu_add_pounce_cb, 3142 { "AddBuddyPounce", NULL, N_("Add Buddy _Pounce..."), NULL, NULL, G_CALLBACK(menu_add_pounce_cb) },
3106 0, "<Item>", NULL }, 3143 { "GetInfo", PIDGIN_STOCK_TOOLBAR_USER_INFO, N_("_Get Info"), "<control>O", NULL, G_CALLBACK(menu_get_info_cb) },
3107 { N_("/Conversation/_Get Info"), "<CTL>O", menu_get_info_cb, 0, 3144 { "Invite", NULL, N_("In_vite..."), NULL, NULL, G_CALLBACK(menu_invite_cb) },
3108 "<StockItem>", PIDGIN_STOCK_TOOLBAR_USER_INFO }, 3145 { "MoreMenu", NULL, N_("M_ore"), NULL, NULL, NULL },
3109 { N_("/Conversation/In_vite..."), NULL, menu_invite_cb, 0, 3146 { "Alias", NULL, N_("Al_ias..."), NULL, NULL, G_CALLBACK(menu_alias_cb) },
3110 "<Item>", NULL }, 3147 { "Block", PIDGIN_STOCK_TOOLBAR_BLOCK, N_("_Block..."), NULL, NULL, G_CALLBACK(menu_block_cb) },
3111 { N_("/Conversation/M_ore"), NULL, NULL, 0, "<Branch>", NULL }, 3148 { "Unblock", PIDGIN_STOCK_TOOLBAR_UNBLOCK, N_("_Unblock..."), NULL, NULL, G_CALLBACK(menu_unblock_cb) },
3112 3149 { "Add", GTK_STOCK_ADD, N_("_Add..."), NULL, NULL, G_CALLBACK(menu_add_remove_cb) },
3113 { "/Conversation/sep2", NULL, NULL, 0, "<Separator>", NULL }, 3150 { "Remove", GTK_STOCK_REMOVE, N_("_Remove..."), NULL, NULL, G_CALLBACK(menu_add_remove_cb) },
3114 3151 { "InsertLink", PIDGIN_STOCK_TOOLBAR_INSERT_LINK, N_("Insert Lin_k..."), NULL, NULL, G_CALLBACK(menu_insert_link_cb) },
3115 { N_("/Conversation/Al_ias..."), NULL, menu_alias_cb, 0, 3152 { "InsertImage", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, N_("Insert Imag_e..."), NULL, NULL, G_CALLBACK(menu_insert_image_cb) },
3116 "<Item>", NULL }, 3153 { "Close", GTK_STOCK_CLOSE, N_("_Close"), NULL, NULL, G_CALLBACK(menu_close_conv_cb) },
3117 { N_("/Conversation/_Block..."), NULL, menu_block_cb, 0,
3118 "<StockItem>", PIDGIN_STOCK_TOOLBAR_BLOCK },
3119 { N_("/Conversation/_Unblock..."), NULL, menu_unblock_cb, 0,
3120 "<StockItem>", PIDGIN_STOCK_TOOLBAR_UNBLOCK },
3121 { N_("/Conversation/_Add..."), NULL, menu_add_remove_cb, 0,
3122 "<StockItem>", GTK_STOCK_ADD },
3123 { N_("/Conversation/_Remove..."), NULL, menu_add_remove_cb, 0,
3124 "<StockItem>", GTK_STOCK_REMOVE },
3125
3126 { "/Conversation/sep3", NULL, NULL, 0, "<Separator>", NULL },
3127
3128 { N_("/Conversation/Insert Lin_k..."), NULL, menu_insert_link_cb, 0,
3129 "<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_LINK },
3130 { N_("/Conversation/Insert Imag_e..."), NULL, menu_insert_image_cb, 0,
3131 "<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE },
3132
3133 { "/Conversation/sep4", NULL, NULL, 0, "<Separator>", NULL },
3134
3135
3136 { N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0,
3137 "<StockItem>", GTK_STOCK_CLOSE },
3138 3154
3139 /* Options */ 3155 /* Options */
3140 { N_("/_Options"), NULL, NULL, 0, "<Branch>", NULL }, 3156 { "OptionsMenu", NULL, N_("_Options"), NULL, NULL, NULL },
3141 { N_("/Options/Enable _Logging"), NULL, menu_logging_cb, 0, "<CheckItem>", NULL },
3142 { N_("/Options/Enable _Sounds"), NULL, menu_sounds_cb, 0, "<CheckItem>", NULL },
3143 { "/Options/sep0", NULL, NULL, 0, "<Separator>", NULL },
3144 { N_("/Options/Show Formatting _Toolbars"), NULL, menu_toolbar_cb, 0, "<CheckItem>", NULL },
3145 { N_("/Options/Show Ti_mestamps"), NULL, menu_timestamps_cb, 0, "<CheckItem>", NULL },
3146 }; 3157 };
3147 3158
3148 static const int menu_item_count = 3159 /* Toggle items */
3149 sizeof(menu_items) / sizeof(*menu_items); 3160 static const GtkToggleActionEntry menu_toggle_entries[] = {
3150 3161 { "EnableLogging", NULL, N_("Enable _Logging"), NULL, NULL, G_CALLBACK(menu_logging_cb), FALSE },
3151 static const char * 3162 { "EnableSounds", NULL, N_("Enable _Sounds"), NULL, NULL, G_CALLBACK(menu_sounds_cb), FALSE },
3152 item_factory_translate_func (const char *path, gpointer func_data) 3163 { "ShowFormattingToolbars", NULL, N_("Show Formatting _Toolbars"), NULL, NULL, G_CALLBACK(menu_toolbar_cb), FALSE },
3153 { 3164 };
3154 return _(path); 3165
3155 } 3166 static const char *conversation_menu =
3167 "<ui>"
3168 "<menubar name='Conversation'>"
3169 "<menu action='ConversationMenu'>"
3170 "<menuitem action='NewInstantMessage'/>"
3171 "<menuitem action='JoinAChat'/>"
3172 "<separator/>"
3173 "<menuitem action='Find'/>"
3174 "<menuitem action='ViewLog'/>"
3175 "<menuitem action='SaveAs'/>"
3176 "<menuitem action='ClearScrollback'/>"
3177 "<separator/>"
3178 #ifdef USE_VV
3179 "<menu action='MediaMenu'>"
3180 "<menuitem action='AudioCall'/>"
3181 "<menuitem action='VideoCall'/>"
3182 "<menuitem action='AudioVideoCall'/>"
3183 "</menu>"
3184 #endif
3185 "<menuitem action='SendFile'/>"
3186 "<menuitem action='GetAttention'/>"
3187 "<menuitem action='AddBuddyPounce'/>"
3188 "<menuitem action='GetInfo'/>"
3189 "<menuitem action='Invite'/>"
3190 "<menu action='MoreMenu'/>"
3191 "<separator/>"
3192 "<menuitem action='Alias'/>"
3193 "<menuitem action='Block'/>"
3194 "<menuitem action='Unblock'/>"
3195 "<menuitem action='Add'/>"
3196 "<menuitem action='Remove'/>"
3197 "<separator/>"
3198 "<menuitem action='InsertLink'/>"
3199 "<menuitem action='InsertImage'/>"
3200 "<separator/>"
3201 "<menuitem action='Close'/>"
3202 "</menu>"
3203 "<menu action='OptionsMenu'>"
3204 "<menuitem action='EnableLogging'/>"
3205 "<menuitem action='EnableSounds'/>"
3206 "<separator/>"
3207 "<menuitem action='ShowFormattingToolbars'/>"
3208 "</menu>"
3209 "</menubar>"
3210 "</ui>";
3156 3211
3157 static void 3212 static void
3158 sound_method_pref_changed_cb(const char *name, PurplePrefType type, 3213 sound_method_pref_changed_cb(const char *name, PurplePrefType type,
3159 gconstpointer value, gpointer data) 3214 gconstpointer value, gpointer data)
3160 { 3215 {
3161 PidginWindow *win = data; 3216 PidginWindow *win = data;
3162 const char *method = value; 3217 const char *method = value;
3163 3218
3164 if (!strcmp(method, "none")) 3219 if (!strcmp(method, "none"))
3165 { 3220 {
3166 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), 3221 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds),
3167 FALSE); 3222 FALSE);
3168 gtk_widget_set_sensitive(win->menu.sounds, FALSE); 3223 gtk_action_set_sensitive(win->menu.sounds, FALSE);
3169 } 3224 }
3170 else 3225 else
3171 { 3226 {
3172 PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win); 3227 PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win);
3173 3228
3174 if (gtkconv != NULL) 3229 if (gtkconv != NULL)
3175 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), 3230 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds),
3176 gtkconv->make_sound); 3231 gtkconv->make_sound);
3177 gtk_widget_set_sensitive(win->menu.sounds, TRUE); 3232 gtk_action_set_sensitive(win->menu.sounds, TRUE);
3178
3179 } 3233 }
3180 } 3234 }
3181 3235
3182 /* Returns TRUE if some items were added to the menu, FALSE otherwise */ 3236 /* Returns TRUE if some items were added to the menu, FALSE otherwise */
3183 static gboolean 3237 static gboolean
3184 populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolean all) 3238 populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolean all)
3185 { 3239 {
3186 GList *list; 3240 GList *list;
3187 PurpleConversation *conv; 3241 PurpleConversation *conv;
3242 PurpleAccount *account;
3188 PurpleBlistNode *node = NULL; 3243 PurpleBlistNode *node = NULL;
3189 PurpleChat *chat = NULL; 3244 PurpleChat *chat = NULL;
3190 PurpleBuddy *buddy = NULL; 3245 PurpleBuddy *buddy = NULL;
3191 gboolean ret; 3246 gboolean ret;
3192 3247
3193 conv = gtkconv->active_conv; 3248 conv = gtkconv->active_conv;
3249 account = purple_conversation_get_account(conv);
3194 3250
3195 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 3251 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
3196 chat = purple_blist_find_chat(conv->account, conv->name); 3252 chat = purple_blist_find_chat(account, purple_conversation_get_name(conv));
3197 3253
3198 if ((chat == NULL) && (gtkconv->imhtml != NULL)) { 3254 if ((chat == NULL) && (gtkconv->webview != NULL)) {
3199 chat = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); 3255 chat = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat");
3200 } 3256 }
3201 3257
3202 if ((chat == NULL) && (gtkconv->imhtml != NULL)) { 3258 if ((chat == NULL) && (gtkconv->webview != NULL)) {
3203 GHashTable *components; 3259 GHashTable *components;
3204 PurpleAccount *account = purple_conversation_get_account(conv); 3260 PurpleAccount *account = purple_conversation_get_account(conv);
3205 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); 3261 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
3206 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 3262 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
3207 if (purple_account_get_connection(account) != NULL && 3263 if (purple_account_get_connection(account) != NULL &&
3212 components = g_hash_table_new_full(g_str_hash, g_str_equal, 3268 components = g_hash_table_new_full(g_str_hash, g_str_equal,
3213 g_free, g_free); 3269 g_free, g_free);
3214 g_hash_table_replace(components, g_strdup("channel"), 3270 g_hash_table_replace(components, g_strdup("channel"),
3215 g_strdup(purple_conversation_get_name(conv))); 3271 g_strdup(purple_conversation_get_name(conv)));
3216 } 3272 }
3217 chat = purple_chat_new(conv->account, NULL, components); 3273 chat = purple_chat_new(account, NULL, components);
3218 purple_blist_node_set_flags((PurpleBlistNode *)chat, 3274 purple_blist_node_set_flags((PurpleBlistNode *)chat,
3219 PURPLE_BLIST_NODE_FLAG_NO_SAVE); 3275 PURPLE_BLIST_NODE_FLAG_NO_SAVE);
3220 g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_chat", 3276 g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_chat",
3221 chat, (GDestroyNotify)purple_blist_remove_chat); 3277 chat, (GDestroyNotify)purple_blist_remove_chat);
3222 } 3278 }
3223 } else { 3279 } else {
3224 if (!purple_account_is_connected(conv->account)) 3280 if (!purple_account_is_connected(account))
3225 return FALSE; 3281 return FALSE;
3226 3282
3227 buddy = purple_find_buddy(conv->account, conv->name); 3283 buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
3228 3284
3229 /* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle 3285 /* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle
3230 * removing "isolated" buddy nodes well */ 3286 * removing "isolated" buddy nodes well */
3231 if (purple_version_check(2, 0, 2) == NULL) { 3287 if (purple_version_check(2, 0, 2) == NULL) {
3232 if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { 3288 if ((buddy == NULL) && (gtkconv->webview != NULL)) {
3233 buddy = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); 3289 buddy = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy");
3234 } 3290 }
3235 3291
3236 if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { 3292 if ((buddy == NULL) && (gtkconv->webview != NULL)) {
3237 buddy = purple_buddy_new(conv->account, conv->name, NULL); 3293 buddy = purple_buddy_new(account, purple_conversation_get_name(conv), NULL);
3238 purple_blist_node_set_flags((PurpleBlistNode *)buddy, 3294 purple_blist_node_set_flags((PurpleBlistNode *)buddy,
3239 PURPLE_BLIST_NODE_FLAG_NO_SAVE); 3295 PURPLE_BLIST_NODE_FLAG_NO_SAVE);
3240 g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_buddy", 3296 g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_buddy",
3241 buddy, (GDestroyNotify)purple_buddy_destroy); 3297 buddy, (GDestroyNotify)purple_buddy_destroy);
3242 } 3298 }
3243 } 3299 }
3244 } 3300 }
3245 3301
3254 pidgin_blist_make_buddy_menu(menu, buddy, TRUE); 3310 pidgin_blist_make_buddy_menu(menu, buddy, TRUE);
3255 else if (chat) { 3311 else if (chat) {
3256 /* XXX: */ 3312 /* XXX: */
3257 } 3313 }
3258 } else if (node) { 3314 } else if (node) {
3259 if (purple_account_is_connected(conv->account)) 3315 if (purple_account_is_connected(account))
3260 pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node); 3316 pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account), node);
3261 pidgin_append_blist_node_extended_menu(menu, node); 3317 pidgin_append_blist_node_extended_menu(menu, node);
3262 } 3318 }
3263 3319
3264 if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL) { 3320 if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL) {
3265 ret = FALSE; 3321 ret = FALSE;
3301 == PURPLE_CONV_TYPE_IM) { 3357 == PURPLE_CONV_TYPE_IM) {
3302 PurpleMediaCaps caps = 3358 PurpleMediaCaps caps =
3303 purple_prpl_get_media_caps(account, 3359 purple_prpl_get_media_caps(account,
3304 purple_conversation_get_name(conv)); 3360 purple_conversation_get_name(conv));
3305 3361
3306 gtk_widget_set_sensitive(win->audio_call, 3362 gtk_action_set_sensitive(win->audio_call,
3307 caps & PURPLE_MEDIA_CAPS_AUDIO 3363 caps & PURPLE_MEDIA_CAPS_AUDIO
3308 ? TRUE : FALSE); 3364 ? TRUE : FALSE);
3309 gtk_widget_set_sensitive(win->video_call, 3365 gtk_action_set_sensitive(win->video_call,
3310 caps & PURPLE_MEDIA_CAPS_VIDEO 3366 caps & PURPLE_MEDIA_CAPS_VIDEO
3311 ? TRUE : FALSE); 3367 ? TRUE : FALSE);
3312 gtk_widget_set_sensitive(win->audio_video_call, 3368 gtk_action_set_sensitive(win->audio_video_call,
3313 caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO 3369 caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO
3314 ? TRUE : FALSE); 3370 ? TRUE : FALSE);
3315 } else if (purple_conversation_get_type(conv) 3371 } else if (purple_conversation_get_type(conv)
3316 == PURPLE_CONV_TYPE_CHAT) { 3372 == PURPLE_CONV_TYPE_CHAT) {
3317 /* for now, don't care about chats... */ 3373 /* for now, don't care about chats... */
3318 gtk_widget_set_sensitive(win->audio_call, FALSE); 3374 gtk_action_set_sensitive(win->audio_call, FALSE);
3319 gtk_widget_set_sensitive(win->video_call, FALSE); 3375 gtk_action_set_sensitive(win->video_call, FALSE);
3320 gtk_widget_set_sensitive(win->audio_video_call, FALSE); 3376 gtk_action_set_sensitive(win->audio_video_call, FALSE);
3321 } else { 3377 } else {
3322 gtk_widget_set_sensitive(win->audio_call, FALSE); 3378 gtk_action_set_sensitive(win->audio_call, FALSE);
3323 gtk_widget_set_sensitive(win->video_call, FALSE); 3379 gtk_action_set_sensitive(win->video_call, FALSE);
3324 gtk_widget_set_sensitive(win->audio_video_call, FALSE); 3380 gtk_action_set_sensitive(win->audio_video_call, FALSE);
3325 } 3381 }
3326 #endif 3382 #endif
3383 }
3384
3385 static void
3386 regenerate_attention_items(PidginWindow *win)
3387 {
3388 GtkWidget *attention;
3389 GtkWidget *menu;
3390 PurpleConversation *conv;
3391 PurpleConnection *pc;
3392 PurplePlugin *prpl = NULL;
3393 PurplePluginProtocolInfo *prpl_info = NULL;
3394 GList *list;
3395
3396 conv = pidgin_conv_window_get_active_conversation(win);
3397 if (!conv)
3398 return;
3399
3400 attention = gtk_ui_manager_get_widget(win->menu.ui,
3401 "/Conversation/ConversationMenu/GetAttention");
3402
3403 /* Remove the previous entries */
3404 gtk_menu_item_set_submenu(GTK_MENU_ITEM(attention), NULL);
3405
3406 pc = purple_conversation_get_connection(conv);
3407 if (pc != NULL)
3408 prpl = purple_connection_get_prpl(pc);
3409 if (prpl != NULL)
3410 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
3411
3412 if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_attention_types)) {
3413 list = prpl_info->get_attention_types(purple_connection_get_account(pc));
3414
3415 /* Multiple attention types */
3416 if (list && list->next) {
3417 int index = 0;
3418
3419 menu = gtk_menu_new();
3420 while (list) {
3421 PurpleAttentionType *type;
3422 GtkWidget *menuitem;
3423
3424 type = list->data;
3425
3426 menuitem = gtk_menu_item_new_with_label(purple_attention_type_get_name(type));
3427 g_object_set_data(G_OBJECT(menuitem), "index", GINT_TO_POINTER(index));
3428 g_signal_connect(G_OBJECT(menuitem), "activate",
3429 G_CALLBACK(menu_get_attention_cb),
3430 win);
3431 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
3432
3433 index++;
3434 list = g_list_delete_link(list, list);
3435 }
3436
3437 gtk_menu_item_set_submenu(GTK_MENU_ITEM(attention), menu);
3438 gtk_widget_show_all(menu);
3439 }
3440 }
3327 } 3441 }
3328 3442
3329 static void 3443 static void
3330 regenerate_options_items(PidginWindow *win) 3444 regenerate_options_items(PidginWindow *win)
3331 { 3445 {
3332 GtkWidget *menu; 3446 GtkWidget *menu;
3333 PidginConversation *gtkconv; 3447 PidginConversation *gtkconv;
3334 GList *list; 3448 GList *list;
3449 GtkWidget *more_menu;
3335 3450
3336 gtkconv = pidgin_conv_window_get_active_gtkconv(win); 3451 gtkconv = pidgin_conv_window_get_active_gtkconv(win);
3337 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More")); 3452 more_menu = gtk_ui_manager_get_widget(win->menu.ui,
3453 "/Conversation/ConversationMenu/MoreMenu");
3454 gtk_widget_show(more_menu);
3455 menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(more_menu));
3338 3456
3339 /* Remove the previous entries */ 3457 /* Remove the previous entries */
3340 for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; ) 3458 for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; )
3341 { 3459 {
3342 GtkWidget *w = list->data; 3460 GtkWidget *w = list->data;
3388 G_CALLBACK(remove_from_list), win); 3506 G_CALLBACK(remove_from_list), win);
3389 gtk_widget_destroy(action_items->data); 3507 gtk_widget_destroy(action_items->data);
3390 action_items = g_list_delete_link(action_items, action_items); 3508 action_items = g_list_delete_link(action_items, action_items);
3391 } 3509 }
3392 3510
3393 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options")); 3511 item = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/OptionsMenu");
3512 menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item));
3394 3513
3395 list = purple_conversation_get_extended_menu(conv); 3514 list = purple_conversation_get_extended_menu(conv);
3396 if (list) { 3515 if (list) {
3397 action_items = g_list_prepend(NULL, (item = pidgin_separator(menu))); 3516 action_items = g_list_prepend(NULL, (item = pidgin_separator(menu)));
3398 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win); 3517 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
3412 { 3531 {
3413 PidginWindow *win = data; 3532 PidginWindow *win = data;
3414 regenerate_media_items(win); 3533 regenerate_media_items(win);
3415 regenerate_options_items(win); 3534 regenerate_options_items(win);
3416 regenerate_plugins_items(win); 3535 regenerate_plugins_items(win);
3536 regenerate_attention_items(win);
3417 3537
3418 /* The following are to make sure the 'More' submenu is not regenerated every time 3538 /* The following are to make sure the 'More' submenu is not regenerated every time
3419 * the focus shifts from 'Conversations' to some other menu and back. */ 3539 * the focus shifts from 'Conversations' to some other menu and back. */
3420 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data); 3540 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data);
3421 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data); 3541 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data);
3424 static void 3544 static void
3425 focus_out_from_menubar(GtkWidget *wid, PidginWindow *win) 3545 focus_out_from_menubar(GtkWidget *wid, PidginWindow *win)
3426 { 3546 {
3427 /* The menubar has been deactivated. Make sure the 'More' submenu is regenerated next time 3547 /* The menubar has been deactivated. Make sure the 'More' submenu is regenerated next time
3428 * the 'Conversation' menu pops up. */ 3548 * the 'Conversation' menu pops up. */
3429 GtkWidget *menuitem = gtk_item_factory_get_item(win->menu.item_factory, N_("/Conversation")); 3549 GtkWidget *menuitem = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/ConversationMenu");
3430 g_signal_handlers_unblock_by_func(G_OBJECT(menuitem), G_CALLBACK(menubar_activated), win); 3550 g_signal_handlers_unblock_by_func(G_OBJECT(menuitem), G_CALLBACK(menubar_activated), win);
3431 g_signal_handlers_disconnect_by_func(G_OBJECT(win->menu.menubar), 3551 g_signal_handlers_disconnect_by_func(G_OBJECT(win->menu.menubar),
3432 G_CALLBACK(focus_out_from_menubar), win); 3552 G_CALLBACK(focus_out_from_menubar), win);
3433 } 3553 }
3434 3554
3435 static GtkWidget * 3555 static GtkWidget *
3436 setup_menubar(PidginWindow *win) 3556 setup_menubar(PidginWindow *win)
3437 { 3557 {
3438 GtkAccelGroup *accel_group; 3558 GtkAccelGroup *accel_group;
3439 const char *method; 3559 const char *method;
3560 GtkActionGroup *action_group;
3561 GError *error;
3440 GtkWidget *menuitem; 3562 GtkWidget *menuitem;
3441 3563
3442 accel_group = gtk_accel_group_new (); 3564 action_group = gtk_action_group_new("ConversationActions");
3565 gtk_action_group_add_actions(action_group,
3566 menu_entries,
3567 G_N_ELEMENTS(menu_entries),
3568 win);
3569 gtk_action_group_add_toggle_actions(action_group,
3570 menu_toggle_entries,
3571 G_N_ELEMENTS(menu_toggle_entries),
3572 win);
3573 #ifdef ENABLE_NLS
3574 gtk_action_group_set_translation_domain(action_group,
3575 PACKAGE);
3576 #endif
3577
3578 win->menu.ui = gtk_ui_manager_new();
3579 gtk_ui_manager_insert_action_group(win->menu.ui, action_group, 0);
3580
3581 accel_group = gtk_ui_manager_get_accel_group(win->menu.ui);
3443 gtk_window_add_accel_group(GTK_WINDOW(win->window), accel_group); 3582 gtk_window_add_accel_group(GTK_WINDOW(win->window), accel_group);
3444 g_object_unref(accel_group);
3445
3446 win->menu.item_factory =
3447 gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
3448
3449 gtk_item_factory_set_translate_func(win->menu.item_factory,
3450 (GtkTranslateFunc)item_factory_translate_func,
3451 NULL, NULL);
3452
3453 gtk_item_factory_create_items(win->menu.item_factory, menu_item_count,
3454 menu_items, win);
3455 g_signal_connect(G_OBJECT(accel_group), "accel-changed", 3583 g_signal_connect(G_OBJECT(accel_group), "accel-changed",
3456 G_CALLBACK(pidgin_save_accels_cb), NULL); 3584 G_CALLBACK(pidgin_save_accels_cb), NULL);
3585
3586 error = NULL;
3587 if (!gtk_ui_manager_add_ui_from_string(win->menu.ui, conversation_menu, -1, &error))
3588 {
3589 g_message("building menus failed: %s", error->message);
3590 g_error_free(error);
3591 exit(EXIT_FAILURE);
3592 }
3593
3594 win->menu.menubar =
3595 gtk_ui_manager_get_widget(win->menu.ui, "/Conversation");
3457 3596
3458 /* Make sure the 'Conversation -> More' menuitems are regenerated whenever 3597 /* Make sure the 'Conversation -> More' menuitems are regenerated whenever
3459 * the 'Conversation' menu pops up because the entries can change after the 3598 * the 'Conversation' menu pops up because the entries can change after the
3460 * conversation is created. */ 3599 * conversation is created. */
3461 menuitem = gtk_item_factory_get_item(win->menu.item_factory, N_("/Conversation")); 3600 menuitem = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/ConversationMenu");
3462 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menubar_activated), win); 3601 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menubar_activated), win);
3463 3602
3464 win->menu.menubar =
3465 gtk_item_factory_get_widget(win->menu.item_factory, "<main>");
3466
3467 win->menu.view_log = 3603 win->menu.view_log =
3468 gtk_item_factory_get_widget(win->menu.item_factory, 3604 gtk_ui_manager_get_action(win->menu.ui,
3469 N_("/Conversation/View Log")); 3605 "/Conversation/ConversationMenu/ViewLog");
3470 3606
3471 #ifdef USE_VV 3607 #ifdef USE_VV
3472 win->audio_call = 3608 win->audio_call =
3473 gtk_item_factory_get_widget(win->menu.item_factory, 3609 gtk_ui_manager_get_action(win->menu.ui,
3474 N_("/Conversation/Media/Audio Call")); 3610 "/Conversation/ConversationMenu/MediaMenu/AudioCall");
3475 win->video_call = 3611 win->video_call =
3476 gtk_item_factory_get_widget(win->menu.item_factory, 3612 gtk_ui_manager_get_action(win->menu.ui,
3477 N_("/Conversation/Media/Video Call")); 3613 "/Conversation/ConversationMenu/MediaMenu/VideoCall");
3478 win->audio_video_call = 3614 win->audio_video_call =
3479 gtk_item_factory_get_widget(win->menu.item_factory, 3615 gtk_ui_manager_get_action(win->menu.ui,
3480 N_("/Conversation/Media/Audio\\/Video Call")); 3616 "/Conversation/ConversationMenu/MediaMenu/AudioVideoCall");
3481 #endif 3617 #endif
3482 3618
3483 /* --- */ 3619 /* --- */
3484 3620
3485 win->menu.send_file = 3621 win->menu.send_file =
3486 gtk_item_factory_get_widget(win->menu.item_factory, 3622 gtk_ui_manager_get_action(win->menu.ui,
3487 N_("/Conversation/Send File...")); 3623 "/Conversation/ConversationMenu/SendFile");
3488 3624
3489 g_object_set_data(G_OBJECT(win->window), "get_attention", 3625 win->menu.get_attention =
3490 gtk_item_factory_get_widget(win->menu.item_factory, 3626 gtk_ui_manager_get_action(win->menu.ui,
3491 N_("/Conversation/Get Attention"))); 3627 "/Conversation/ConversationMenu/GetAttention");
3628
3492 win->menu.add_pounce = 3629 win->menu.add_pounce =
3493 gtk_item_factory_get_widget(win->menu.item_factory, 3630 gtk_ui_manager_get_action(win->menu.ui,
3494 N_("/Conversation/Add Buddy Pounce...")); 3631 "/Conversation/ConversationMenu/AddBuddyPounce");
3495 3632
3496 /* --- */ 3633 /* --- */
3497 3634
3498 win->menu.get_info = 3635 win->menu.get_info =
3499 gtk_item_factory_get_widget(win->menu.item_factory, 3636 gtk_ui_manager_get_action(win->menu.ui,
3500 N_("/Conversation/Get Info")); 3637 "/Conversation/ConversationMenu/GetInfo");
3501 3638
3502 win->menu.invite = 3639 win->menu.invite =
3503 gtk_item_factory_get_widget(win->menu.item_factory, 3640 gtk_ui_manager_get_action(win->menu.ui,
3504 N_("/Conversation/Invite...")); 3641 "/Conversation/ConversationMenu/Invite");
3505 3642
3506 /* --- */ 3643 /* --- */
3507 3644
3508 win->menu.alias = 3645 win->menu.alias =
3509 gtk_item_factory_get_widget(win->menu.item_factory, 3646 gtk_ui_manager_get_action(win->menu.ui,
3510 N_("/Conversation/Alias...")); 3647 "/Conversation/ConversationMenu/Alias");
3511 3648
3512 win->menu.block = 3649 win->menu.block =
3513 gtk_item_factory_get_widget(win->menu.item_factory, 3650 gtk_ui_manager_get_action(win->menu.ui,
3514 N_("/Conversation/Block...")); 3651 "/Conversation/ConversationMenu/Block");
3515 3652
3516 win->menu.unblock = 3653 win->menu.unblock =
3517 gtk_item_factory_get_widget(win->menu.item_factory, 3654 gtk_ui_manager_get_action(win->menu.ui,
3518 N_("/Conversation/Unblock...")); 3655 "/Conversation/ConversationMenu/Unblock");
3519 3656
3520 win->menu.add = 3657 win->menu.add =
3521 gtk_item_factory_get_widget(win->menu.item_factory, 3658 gtk_ui_manager_get_action(win->menu.ui,
3522 N_("/Conversation/Add...")); 3659 "/Conversation/ConversationMenu/Add");
3523 3660
3524 win->menu.remove = 3661 win->menu.remove =
3525 gtk_item_factory_get_widget(win->menu.item_factory, 3662 gtk_ui_manager_get_action(win->menu.ui,
3526 N_("/Conversation/Remove...")); 3663 "/Conversation/ConversationMenu/Remove");
3527 3664
3528 /* --- */ 3665 /* --- */
3529 3666
3530 win->menu.insert_link = 3667 win->menu.insert_link =
3531 gtk_item_factory_get_widget(win->menu.item_factory, 3668 gtk_ui_manager_get_action(win->menu.ui,
3532 N_("/Conversation/Insert Link...")); 3669 "/Conversation/ConversationMenu/InsertLink");
3533 3670
3534 win->menu.insert_image = 3671 win->menu.insert_image =
3535 gtk_item_factory_get_widget(win->menu.item_factory, 3672 gtk_ui_manager_get_action(win->menu.ui,
3536 N_("/Conversation/Insert Image...")); 3673 "/Conversation/ConversationMenu/InsertImage");
3537 3674
3538 /* --- */ 3675 /* --- */
3539 3676
3540 win->menu.logging = 3677 win->menu.logging =
3541 gtk_item_factory_get_widget(win->menu.item_factory, 3678 gtk_ui_manager_get_action(win->menu.ui,
3542 N_("/Options/Enable Logging")); 3679 "/Conversation/OptionsMenu/EnableLogging");
3543 win->menu.sounds = 3680 win->menu.sounds =
3544 gtk_item_factory_get_widget(win->menu.item_factory, 3681 gtk_ui_manager_get_action(win->menu.ui,
3545 N_("/Options/Enable Sounds")); 3682 "/Conversation/OptionsMenu/EnableSounds");
3546 method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); 3683 method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method");
3547 if (method != NULL && !strcmp(method, "none")) 3684 if (method != NULL && !strcmp(method, "none"))
3548 { 3685 {
3549 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), 3686 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds),
3550 FALSE); 3687 FALSE);
3551 gtk_widget_set_sensitive(win->menu.sounds, FALSE); 3688 gtk_action_set_sensitive(win->menu.sounds, FALSE);
3552 } 3689 }
3553 purple_prefs_connect_callback(win, PIDGIN_PREFS_ROOT "/sound/method", 3690 purple_prefs_connect_callback(win, PIDGIN_PREFS_ROOT "/sound/method",
3554 sound_method_pref_changed_cb, win); 3691 sound_method_pref_changed_cb, win);
3555 3692
3556 win->menu.show_formatting_toolbar = 3693 win->menu.show_formatting_toolbar =
3557 gtk_item_factory_get_widget(win->menu.item_factory, 3694 gtk_ui_manager_get_action(win->menu.ui,
3558 N_("/Options/Show Formatting Toolbars")); 3695 "/Conversation/OptionsMenu/ShowFormattingToolbars");
3559 win->menu.show_timestamps =
3560 gtk_item_factory_get_widget(win->menu.item_factory,
3561 N_("/Options/Show Timestamps"));
3562 win->menu.show_icon = NULL;
3563 3696
3564 win->menu.tray = pidgin_menu_tray_new(); 3697 win->menu.tray = pidgin_menu_tray_new();
3565 gtk_menu_shell_append(GTK_MENU_SHELL(win->menu.menubar), 3698 gtk_menu_shell_append(GTK_MENU_SHELL(win->menu.menubar),
3566 win->menu.tray); 3699 win->menu.tray);
3567 gtk_widget_show(win->menu.tray); 3700 gtk_widget_show(win->menu.tray);
3595 /* Check if we need to send another PURPLE_TYPING message */ 3728 /* Check if we need to send another PURPLE_TYPING message */
3596 if (first || (purple_conv_im_get_type_again(im) != 0 && 3729 if (first || (purple_conv_im_get_type_again(im) != 0 &&
3597 time(NULL) > purple_conv_im_get_type_again(im))) 3730 time(NULL) > purple_conv_im_get_type_again(im)))
3598 { 3731 {
3599 unsigned int timeout; 3732 unsigned int timeout;
3600 timeout = serv_send_typing(purple_conversation_get_gc(conv), 3733 timeout = serv_send_typing(purple_conversation_get_connection(conv),
3601 purple_conversation_get_name(conv), 3734 purple_conversation_get_name(conv),
3602 PURPLE_TYPING); 3735 PURPLE_TYPING);
3603 purple_conv_im_set_type_again(im, timeout); 3736 purple_conv_im_set_type_again(im, timeout);
3604 } 3737 }
3605 } 3738 }
3646 #endif 3779 #endif
3647 3780
3648 static void 3781 static void
3649 update_typing_message(PidginConversation *gtkconv, const char *message) 3782 update_typing_message(PidginConversation *gtkconv, const char *message)
3650 { 3783 {
3784 /* TODO WEBKIT: this is not handled at all */
3785 #if 0
3651 GtkTextBuffer *buffer; 3786 GtkTextBuffer *buffer;
3652 GtkTextMark *stmark, *enmark; 3787 GtkTextMark *stmark, *enmark;
3653 3788
3654 if (g_object_get_data(G_OBJECT(gtkconv->imhtml), "disable-typing-notification")) 3789 if (g_object_get_data(G_OBJECT(gtkconv->imhtml), "disable-typing-notification"))
3655 return; 3790 return;
3678 gtk_text_buffer_create_mark(buffer, "typing-notification-start", &iter, TRUE); 3813 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); 3814 gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, message, -1, "TYPING-NOTIFICATION", NULL);
3680 gtk_text_buffer_get_end_iter(buffer, &iter); 3815 gtk_text_buffer_get_end_iter(buffer, &iter);
3681 gtk_text_buffer_create_mark(buffer, "typing-notification-end", &iter, TRUE); 3816 gtk_text_buffer_create_mark(buffer, "typing-notification-end", &iter, TRUE);
3682 } 3817 }
3818 #endif /* if 0 */
3683 } 3819 }
3684 3820
3685 static void 3821 static void
3686 update_typing_icon(PidginConversation *gtkconv) 3822 update_typing_icon(PidginConversation *gtkconv)
3687 { 3823 {
3734 return FALSE; 3870 return FALSE;
3735 3871
3736 if (win->menu.send_to == NULL) 3872 if (win->menu.send_to == NULL)
3737 return FALSE; 3873 return FALSE;
3738 3874
3739 if (!(b = purple_find_buddy(account, conv->name))) 3875 if (!(b = purple_find_buddy(account, purple_conversation_get_name(conv))))
3740 return FALSE; 3876 return FALSE;
3741
3742 3877
3743 gtk_widget_show(win->menu.send_to); 3878 gtk_widget_show(win->menu.send_to);
3744 3879
3745 menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(win->menu.send_to)); 3880 menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(win->menu.send_to));
3746 3881
3894 win->menu.send_to, 2); 4029 win->menu.send_to, 2);
3895 gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.send_to), menu); 4030 gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.send_to), menu);
3896 4031
3897 gtk_widget_show(menu); 4032 gtk_widget_show(menu);
3898 4033
3899 if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM) { 4034 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); 4035 buds = purple_find_buddies(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv));
3901 4036
3902 if (buds == NULL) 4037 if (buds == NULL)
3903 { 4038 {
3904 /* The user isn't on the buddy list. So we don't create any sendto menu. */ 4039 /* The user isn't on the buddy list. So we don't create any sendto menu. */
3905 } 4040 }
3919 4054
3920 if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) 4055 if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
3921 continue; 4056 continue;
3922 4057
3923 account = purple_buddy_get_account(buddy); 4058 account = purple_buddy_get_account(buddy);
3924 if (purple_account_is_connected(account) || account == gtkconv->active_conv->account) 4059 /* TODO WEBKIT: (I'm not actually sure if this is webkit-related --Mark Doliner) */
4060 if (purple_account_is_connected(account) /*|| account == purple_conversation_get_account(gtkconv->active_conv)*/)
3925 { 4061 {
3926 /* Use the PurplePresence to get unique buddies. */ 4062 /* Use the PurplePresence to get unique buddies. */
3927 PurplePresence *presence = purple_buddy_get_presence(buddy); 4063 PurplePresence *presence = purple_buddy_get_presence(buddy);
3928 if (!g_list_find_custom(list, presence, (GCompareFunc)compare_buddy_presence)) 4064 if (!g_list_find_custom(list, presence, (GCompareFunc)compare_buddy_presence))
3929 list = g_list_prepend(list, presence); 4065 list = g_list_prepend(list, presence);
3978 } 4114 }
3979 4115
3980 static void 4116 static void
3981 deleting_chat_buddy_cb(PurpleConvChatBuddy *cb) 4117 deleting_chat_buddy_cb(PurpleConvChatBuddy *cb)
3982 { 4118 {
3983 if (cb->ui_data) { 4119 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
3984 GtkTreeRowReference *ref = cb->ui_data; 4120
4121 if (ref) {
3985 gtk_tree_row_reference_free(ref); 4122 gtk_tree_row_reference_free(ref);
3986 cb->ui_data = NULL; 4123 purple_conv_chat_cb_set_ui_data(cb, NULL);
3987 } 4124 }
3988 } 4125 }
3989 4126
3990 static void 4127 static void
3991 add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const char *old_name) 4128 add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const char *old_name)
4000 GtkTreePath *newpath; 4137 GtkTreePath *newpath;
4001 const char *stock; 4138 const char *stock;
4002 GtkTreeIter iter; 4139 GtkTreeIter iter;
4003 gboolean is_me = FALSE; 4140 gboolean is_me = FALSE;
4004 gboolean is_buddy; 4141 gboolean is_buddy;
4005 gchar *tmp, *alias_key, *name, *alias; 4142 const gchar *name, *alias;
4143 gchar *tmp, *alias_key;
4006 PurpleConvChatBuddyFlags flags; 4144 PurpleConvChatBuddyFlags flags;
4007 GdkColor *color = NULL; 4145 GdkColor *color = NULL;
4008 4146
4009 alias = cb->alias; 4147 alias = purple_conv_chat_cb_get_alias(cb);
4010 name = cb->name; 4148 name = purple_conv_chat_cb_get_name(cb);
4011 flags = cb->flags; 4149 flags = purple_conv_chat_cb_get_flags(cb);
4012 4150
4013 chat = PURPLE_CONV_CHAT(conv); 4151 chat = PURPLE_CONV_CHAT(conv);
4014 gtkconv = PIDGIN_CONVERSATION(conv); 4152 gtkconv = PIDGIN_CONVERSATION(conv);
4015 gtkchat = gtkconv->u.chat; 4153 gtkchat = gtkconv->u.chat;
4016 gc = purple_conversation_get_gc(conv); 4154 gc = purple_conversation_get_connection(conv);
4017 4155
4018 if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl))) 4156 if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
4019 return; 4157 return;
4020 4158
4021 tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 4159 tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
4022 ls = GTK_LIST_STORE(tm); 4160 ls = GTK_LIST_STORE(tm);
4023 4161
4024 stock = get_chat_buddy_status_icon(chat, name, flags); 4162 stock = get_chat_buddy_status_icon(chat, name, flags);
4025 4163
4026 if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name))) 4164 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; 4165 is_me = TRUE;
4028 4166
4029 is_buddy = cb->buddy; 4167 is_buddy = purple_conv_chat_cb_is_buddy(cb);
4030 4168
4031 tmp = g_utf8_casefold(alias, -1); 4169 tmp = g_utf8_casefold(alias, -1);
4032 alias_key = g_utf8_collate_key(tmp, -1); 4170 alias_key = g_utf8_collate_key(tmp, -1);
4033 g_free(tmp); 4171 g_free(tmp);
4034 4172
4035 if (is_me) { 4173 if (is_me) {
4174 #if 0
4175 /* TODO WEBKIT: No tags in webkit stuff, yet. */
4036 GtkTextTag *tag = gtk_text_tag_table_lookup( 4176 GtkTextTag *tag = gtk_text_tag_table_lookup(
4037 gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->imhtml)->text_buffer), 4177 gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->webview)->text_buffer),
4038 "send-name"); 4178 "send-name");
4039 g_object_get(tag, "foreground-gdk", &color, NULL); 4179 g_object_get(tag, "foreground-gdk", &color, NULL);
4180 #endif /* if 0 */
4040 } else { 4181 } else {
4041 GtkTextTag *tag; 4182 GtkTextTag *tag;
4042 if ((tag = get_buddy_tag(conv, name, 0, FALSE))) 4183 if ((tag = get_buddy_tag(conv, name, 0, FALSE)))
4043 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); 4184 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL);
4044 if ((tag = get_buddy_tag(conv, name, PURPLE_MESSAGE_NICK, FALSE))) 4185 if ((tag = get_buddy_tag(conv, name, PURPLE_MESSAGE_NICK, FALSE)))
4062 CHAT_USERS_FLAGS_COLUMN, flags, 4203 CHAT_USERS_FLAGS_COLUMN, flags,
4063 CHAT_USERS_COLOR_COLUMN, color, 4204 CHAT_USERS_COLOR_COLUMN, color,
4064 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, 4205 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
4065 -1); 4206 -1);
4066 4207
4067 if (cb->ui_data) { 4208 if (purple_conv_chat_cb_get_ui_data(cb)) {
4068 GtkTreeRowReference *ref = cb->ui_data; 4209 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
4069 gtk_tree_row_reference_free(ref); 4210 gtk_tree_row_reference_free(ref);
4070 } 4211 }
4071 4212
4072 newpath = gtk_tree_model_get_path(tm, &iter); 4213 newpath = gtk_tree_model_get_path(tm, &iter);
4073 cb->ui_data = gtk_tree_row_reference_new(tm, newpath); 4214 purple_conv_chat_cb_set_ui_data(cb, gtk_tree_row_reference_new(tm, newpath));
4074 gtk_tree_path_free(newpath); 4215 gtk_tree_path_free(newpath);
4075 4216
4076 if (is_me && color) 4217 if (is_me && color)
4077 gdk_color_free(color); 4218 gdk_color_free(color);
4078 g_free(alias_key); 4219 g_free(alias_key);
4098 * @param name The buddy name or alias or slash command name that we're 4239 * @param name The buddy name or alias or slash command name that we're
4099 * checking for a match. 4240 * checking for a match.
4100 */ 4241 */
4101 static void 4242 static void
4102 tab_complete_process_item(int *most_matched, const char *entered, gsize entered_bytes, char **partial, char *nick_partial, 4243 tab_complete_process_item(int *most_matched, const char *entered, gsize entered_bytes, char **partial, char *nick_partial,
4103 GList **matches, char *name) 4244 GList **matches, const char *name)
4104 { 4245 {
4105 memcpy(nick_partial, name, entered_bytes); 4246 memcpy(nick_partial, name, entered_bytes);
4106 if (purple_utf8_strcasecmp(nick_partial, entered)) 4247 if (purple_utf8_strcasecmp(nick_partial, entered))
4107 return; 4248 return;
4108 4249
4220 int f; 4361 int f;
4221 4362
4222 /* Users */ 4363 /* Users */
4223 for (; l != NULL; l = l->next) { 4364 for (; l != NULL; l = l->next) {
4224 tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, 4365 tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial,
4225 &matches, ((PurpleConvChatBuddy *)l->data)->name); 4366 &matches, purple_conv_chat_cb_get_name((PurpleConvChatBuddy *)l->data));
4226 } 4367 }
4227 4368
4228 4369
4229 /* Aliases */ 4370 /* Aliases */
4230 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 4371 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
4318 PurpleConversation *conv = gtkconv->active_conv; 4459 PurpleConversation *conv = gtkconv->active_conv;
4319 PidginChatPane *gtkchat; 4460 PidginChatPane *gtkchat;
4320 char *new_topic; 4461 char *new_topic;
4321 const char *current_topic; 4462 const char *current_topic;
4322 4463
4323 gc = purple_conversation_get_gc(conv); 4464 gc = purple_conversation_get_connection(conv);
4324 4465
4325 if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl))) 4466 if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
4326 return; 4467 return;
4327 4468
4328 if(prpl_info->set_chat_topic == NULL) 4469 if(prpl_info->set_chat_topic == NULL)
4329 return; 4470 return;
4330 4471
4395 static void 4536 static void
4396 update_chat_alias(PurpleBuddy *buddy, PurpleConversation *conv, PurpleConnection *gc, PurplePluginProtocolInfo *prpl_info) 4537 update_chat_alias(PurpleBuddy *buddy, PurpleConversation *conv, PurpleConnection *gc, PurplePluginProtocolInfo *prpl_info)
4397 { 4538 {
4398 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); 4539 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
4399 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); 4540 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
4541 PurpleAccount *account = purple_conversation_get_account(conv);
4400 GtkTreeModel *model; 4542 GtkTreeModel *model;
4401 char *normalized_name; 4543 char *normalized_name;
4402 GtkTreeIter iter; 4544 GtkTreeIter iter;
4403 int f; 4545 int f;
4404 4546
4409 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkconv->u.chat->list)); 4551 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkconv->u.chat->list));
4410 4552
4411 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 4553 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
4412 return; 4554 return;
4413 4555
4414 normalized_name = g_strdup(purple_normalize(conv->account, buddy->name)); 4556 normalized_name = g_strdup(purple_normalize(account, purple_buddy_get_name(buddy)));
4415 4557
4416 do { 4558 do {
4417 char *name; 4559 char *name;
4418 4560
4419 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1); 4561 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1);
4420 4562
4421 if (!strcmp(normalized_name, purple_normalize(conv->account, name))) { 4563 if (!strcmp(normalized_name, purple_normalize(account, name))) {
4422 const char *alias = name; 4564 const char *alias = name;
4423 char *tmp; 4565 char *tmp;
4424 char *alias_key = NULL; 4566 char *alias_key = NULL;
4425 PurpleBuddy *buddy2; 4567 PurpleBuddy *buddy2;
4426 4568
4427 if (strcmp(chat->nick, purple_normalize(conv->account, name))) { 4569 if (strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, name))) {
4428 /* This user is not me, so look into updating the alias. */ 4570 /* This user is not me, so look into updating the alias. */
4429 4571
4430 if ((buddy2 = purple_find_buddy(conv->account, name)) != NULL) { 4572 if ((buddy2 = purple_find_buddy(account, name)) != NULL) {
4431 alias = purple_buddy_get_contact_alias(buddy2); 4573 alias = purple_buddy_get_contact_alias(buddy2);
4432 } 4574 }
4433 4575
4434 tmp = g_utf8_casefold(alias, -1); 4576 tmp = g_utf8_casefold(alias, -1);
4435 alias_key = g_utf8_collate_key(tmp, -1); 4577 alias_key = g_utf8_collate_key(tmp, -1);
4460 PurplePluginProtocolInfo *prpl_info; 4602 PurplePluginProtocolInfo *prpl_info;
4461 4603
4462 g_return_if_fail(node != NULL); 4604 g_return_if_fail(node != NULL);
4463 g_return_if_fail(conv != NULL); 4605 g_return_if_fail(conv != NULL);
4464 4606
4465 gc = purple_conversation_get_gc(conv); 4607 gc = purple_conversation_get_connection(conv);
4466 g_return_if_fail(gc != NULL); 4608 g_return_if_fail(gc != NULL);
4467 g_return_if_fail(gc->prpl != NULL); 4609 g_return_if_fail(purple_connection_get_prpl(gc) != NULL);
4468 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 4610 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
4469 4611
4470 if (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME) 4612 if (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)
4471 return; 4613 return;
4472 4614
4473 if (PURPLE_BLIST_NODE_IS_CONTACT(node)) 4615 if (PURPLE_BLIST_NODE_IS_CONTACT(node))
4483 } 4625 }
4484 } 4626 }
4485 else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) 4627 else if (PURPLE_BLIST_NODE_IS_BUDDY(node))
4486 update_chat_alias((PurpleBuddy *)node, conv, gc, prpl_info); 4628 update_chat_alias((PurpleBuddy *)node, conv, gc, prpl_info);
4487 else if (PURPLE_BLIST_NODE_IS_CHAT(node) && 4629 else if (PURPLE_BLIST_NODE_IS_CHAT(node) &&
4488 purple_conversation_get_account(conv) == ((PurpleChat*)node)->account) 4630 purple_conversation_get_account(conv) == purple_chat_get_account((PurpleChat*)node))
4489 { 4631 {
4490 if (old_alias == NULL || g_utf8_collate(old_alias, purple_conversation_get_title(conv)) == 0) 4632 if (old_alias == NULL || g_utf8_collate(old_alias, purple_conversation_get_title(conv)) == 0)
4491 pidgin_conv_update_fields(conv, PIDGIN_CONV_SET_TITLE); 4633 pidgin_conv_update_fields(conv, PIDGIN_CONV_SET_TITLE);
4492 } 4634 }
4493 } 4635 }
4512 model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list)); 4654 model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list));
4513 4655
4514 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 4656 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
4515 return; 4657 return;
4516 4658
4517 normalized_name = g_strdup(purple_normalize(conv->account, buddy->name)); 4659 normalized_name = g_strdup(purple_normalize(purple_conversation_get_account(conv), purple_buddy_get_name(buddy)));
4518 4660
4519 do { 4661 do {
4520 char *name; 4662 char *name;
4521 4663
4522 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1); 4664 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1);
4523 4665
4524 if (!strcmp(normalized_name, purple_normalize(conv->account, name))) { 4666 if (!strcmp(normalized_name, purple_normalize(purple_conversation_get_account(conv), name))) {
4525 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 4667 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
4526 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1); 4668 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1);
4527 g_free(name); 4669 g_free(name);
4528 break; 4670 break;
4529 } 4671 }
4598 GtkTextIter iter; 4740 GtkTextIter iter;
4599 int lines; 4741 int lines;
4600 GdkRectangle oneline; 4742 GdkRectangle oneline;
4601 int height, diff; 4743 int height, diff;
4602 int pad_top, pad_inside, pad_bottom; 4744 int pad_top, pad_inside, pad_bottom;
4603 int total_height = (gtkconv->imhtml->allocation.height + gtkconv->entry->allocation.height); 4745 int total_height = (gtkconv->webview->allocation.height + gtkconv->entry->allocation.height);
4604 int max_height = total_height / 2; 4746 int max_height = total_height / 2;
4605 int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines"); 4747 int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines");
4606 int min_height; 4748 int min_height;
4607 gboolean interior_focus; 4749 gboolean interior_focus;
4608 int focus_width; 4750 int focus_width;
4670 4812
4671 static void 4813 static void
4672 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox) 4814 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox)
4673 { 4815 {
4674 PurpleConversation *conv = gtkconv->active_conv; 4816 PurpleConversation *conv = gtkconv->active_conv;
4675 PurpleConnection *gc = purple_conversation_get_gc(conv); 4817 PurpleConnection *gc = purple_conversation_get_connection(conv);
4676 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 4818 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
4677 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) 4819 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC)
4678 { 4820 {
4679 GtkWidget *hbox, *label; 4821 GtkWidget *hbox, *label;
4680 PidginChatPane *gtkchat = gtkconv->u.chat; 4822 PidginChatPane *gtkchat = gtkconv->u.chat;
4681 4823
4712 PurpleBlistNode *node; 4854 PurpleBlistNode *node;
4713 PurplePluginProtocolInfo *prpl_info; 4855 PurplePluginProtocolInfo *prpl_info;
4714 PurpleAccount *account = purple_conversation_get_account(conv); 4856 PurpleAccount *account = purple_conversation_get_account(conv);
4715 char *who = NULL; 4857 char *who = NULL;
4716 4858
4717 if (account->gc == NULL) 4859 if (purple_account_get_connection(account) == NULL)
4718 return FALSE; 4860 return FALSE;
4719 4861
4720 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path)) 4862 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path))
4721 return FALSE; 4863 return FALSE;
4722 4864
4723 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1); 4865 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1);
4724 4866
4725 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl); 4867 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account)));
4726 node = (PurpleBlistNode*)(purple_find_buddy(conv->account, who)); 4868 node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), who));
4727 if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) 4869 if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME))
4728 pidgin_blist_draw_tooltip(node, gtkconv->infopane); 4870 pidgin_blist_draw_tooltip(node, gtkconv->infopane);
4729 4871
4730 g_free(who); 4872 g_free(who);
4731 return FALSE; 4873 return FALSE;
4822 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE); 4964 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE);
4823 gtk_widget_show(list); 4965 gtk_widget_show(list);
4824 4966
4825 gtkchat->list = list; 4967 gtkchat->list = list;
4826 4968
4827 gtk_box_pack_start(GTK_BOX(lbox), 4969 gtk_box_pack_start(GTK_BOX(lbox),
4828 pidgin_make_scrollable(list, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1), 4970 pidgin_make_scrollable(list, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1),
4829 TRUE, TRUE, 0); 4971 TRUE, TRUE, 0);
4830 } 4972 }
4831 4973
4832 static gboolean 4974 static gboolean
4836 PurpleConversation *conv; 4978 PurpleConversation *conv;
4837 PidginConversation *gtkconv = userdata; 4979 PidginConversation *gtkconv = userdata;
4838 4980
4839 conv = gtkconv->active_conv; 4981 conv = gtkconv->active_conv;
4840 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 4982 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
4841 node = (PurpleBlistNode*)(purple_blist_find_chat(conv->account, conv->name)); 4983 node = (PurpleBlistNode*)(purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv)));
4842 if (!node) 4984 if (!node)
4843 node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); 4985 node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat");
4844 } else { 4986 } else {
4845 node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name)); 4987 node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)));
4846 #if 0 4988 #if 0
4847 /* Using the transient blist nodes to show the tooltip doesn't quite work yet. */ 4989 /* Using the transient blist nodes to show the tooltip doesn't quite work yet. */
4848 if (!node) 4990 if (!node)
4849 node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); 4991 node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy");
4850 #endif 4992 #endif
4851 } 4993 }
4852 4994
4853 if (node) 4995 if (node)
4854 pidgin_blist_draw_tooltip(node, gtkconv->infopane); 4996 pidgin_blist_draw_tooltip(node, gtkconv->infopane);
4859 static gboolean 5001 static gboolean
4860 pidgin_conv_end_quickfind(PidginConversation *gtkconv) 5002 pidgin_conv_end_quickfind(PidginConversation *gtkconv)
4861 { 5003 {
4862 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); 5004 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL);
4863 5005
4864 gtk_imhtml_search_clear(GTK_IMHTML(gtkconv->imhtml)); 5006 webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(gtkconv->webview));
4865 gtk_widget_hide_all(gtkconv->quickfind.container); 5007 gtk_widget_hide_all(gtkconv->quickfind.container);
4866 5008
4867 gtk_widget_grab_focus(gtkconv->entry); 5009 gtk_widget_grab_focus(gtkconv->entry);
4868 return TRUE; 5010 return TRUE;
4869 } 5011 }
4872 quickfind_process_input(GtkWidget *entry, GdkEventKey *event, PidginConversation *gtkconv) 5014 quickfind_process_input(GtkWidget *entry, GdkEventKey *event, PidginConversation *gtkconv)
4873 { 5015 {
4874 switch (event->keyval) { 5016 switch (event->keyval) {
4875 case GDK_Return: 5017 case GDK_Return:
4876 case GDK_KP_Enter: 5018 case GDK_KP_Enter:
4877 if (gtk_imhtml_search_find(GTK_IMHTML(gtkconv->imhtml), gtk_entry_get_text(GTK_ENTRY(entry)))) { 5019 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); 5020 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL);
4879 } else { 5021 } else {
4880 GdkColor col; 5022 GdkColor col;
4881 col.red = 0xffff; 5023 col.red = 0xffff;
4882 col.green = 0xafff; 5024 col.green = 0xafff;
4901 5043
4902 gtk_box_pack_start(GTK_BOX(container), widget, FALSE, FALSE, 0); 5044 gtk_box_pack_start(GTK_BOX(container), widget, FALSE, FALSE, 0);
4903 5045
4904 close = pidgin_create_small_button(gtk_label_new("×")); 5046 close = pidgin_create_small_button(gtk_label_new("×"));
4905 gtk_box_pack_start(GTK_BOX(widget), close, FALSE, FALSE, 0); 5047 gtk_box_pack_start(GTK_BOX(widget), close, FALSE, FALSE, 0);
5048 #if GTK_CHECK_VERSION(2,12,0)
5049 gtk_widget_set_tooltip_text(close, _("Close Find bar"));
5050 #else
4906 gtk_tooltips_set_tip(gtkconv->tooltips, close, 5051 gtk_tooltips_set_tip(gtkconv->tooltips, close,
4907 _("Close Find bar"), NULL); 5052 _("Close Find bar"), NULL);
5053 #endif
4908 5054
4909 label = gtk_label_new(_("Find:")); 5055 label = gtk_label_new(_("Find:"));
4910 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 10); 5056 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 10);
4911 5057
4912 entry = gtk_entry_new(); 5058 entry = gtk_entry_new();
4922 G_CALLBACK(pidgin_conv_end_quickfind), gtkconv); 5068 G_CALLBACK(pidgin_conv_end_quickfind), gtkconv);
4923 } 5069 }
4924 5070
4925 /* }}} */ 5071 /* }}} */
4926 5072
5073 static char *
5074 replace_header_tokens(PurpleConversation *conv, const char *text)
5075 {
5076 PurpleAccount *account = purple_conversation_get_account(conv);
5077 GString *str;
5078 const char *cur = text;
5079 const char *prev = cur;
5080 time_t mtime;
5081 struct tm *tm = NULL;
5082
5083 if (text == NULL || *text == '\0')
5084 return NULL;
5085
5086 str = g_string_new(NULL);
5087 while ((cur = strchr(cur, '%'))) {
5088 const char *replace = NULL;
5089 const char *fin = NULL;
5090
5091 if (g_str_has_prefix(cur, "%chatName%")) {
5092 replace = purple_conversation_get_name(conv);
5093
5094 } else if (g_str_has_prefix(cur, "%sourceName%")) {
5095 replace = purple_account_get_alias(account);
5096 if (replace == NULL)
5097 replace = purple_account_get_username(account);
5098
5099 } else if (g_str_has_prefix(cur, "%destinationName%")) {
5100 PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
5101 if (buddy) {
5102 replace = purple_buddy_get_alias(buddy);
5103 } else {
5104 replace = purple_conversation_get_name(conv);
5105 }
5106
5107 } else if (g_str_has_prefix(cur, "%incomingIconPath%")) {
5108 PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
5109 if (icon)
5110 replace = purple_buddy_icon_get_full_path(icon);
5111
5112 } else if (g_str_has_prefix(cur, "%outgoingIconPath%")) {
5113 replace = purple_account_get_buddy_icon_path(account);
5114
5115 } else if (g_str_has_prefix(cur, "%timeOpened")) {
5116 const char *tmp = cur + strlen("%timeOpened");
5117 char *format = NULL;
5118
5119 if (*tmp == '{') {
5120 const char *end;
5121 tmp++;
5122 end = strstr(tmp, "}%");
5123 if (!end) /* Invalid string */
5124 continue;
5125 format = g_strndup(tmp, end - tmp);
5126 fin = end + 1;
5127 }
5128
5129 if (!tm) {
5130 mtime = time(NULL);
5131 tm = localtime(&mtime);
5132 }
5133
5134 replace = purple_utf8_strftime(format ? format : "%X", tm);
5135 g_free(format);
5136
5137 } else if (g_str_has_prefix(cur, "%dateOpened%")) {
5138 if (!tm) {
5139 mtime = time(NULL);
5140 tm = localtime(&mtime);
5141 }
5142
5143 replace = purple_date_format_short(tm);
5144
5145 } else {
5146 cur++;
5147 continue;
5148 }
5149
5150 /* Here we have a replacement to make */
5151 g_string_append_len(str, prev, cur - prev);
5152 if (replace)
5153 g_string_append(str, replace);
5154
5155 /* And update the pointers */
5156 if (fin) {
5157 prev = cur = fin + 1;
5158 } else {
5159 prev = cur = strchr(cur + 1, '%') + 1;
5160 }
5161 }
5162
5163 /* And wrap it up */
5164 g_string_append(str, prev);
5165 return g_string_free(str, FALSE);
5166 }
5167
5168 static char *
5169 replace_template_tokens(PidginConvTheme *theme, const char *header, const char *footer)
5170 {
5171 GString *str;
5172 const char *text;
5173 char **ms;
5174 char *path;
5175
5176 text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN);
5177 if (text == NULL)
5178 return NULL;
5179
5180 ms = g_strsplit(text, "%@", 6);
5181 if (ms[0] == NULL || ms[1] == NULL || ms[2] == NULL || ms[3] == NULL || ms[4] == NULL || ms[5] == NULL) {
5182 g_strfreev(ms);
5183 return NULL;
5184 }
5185
5186 str = g_string_new(NULL);
5187
5188 g_string_append(str, ms[0]);
5189 g_string_append(str, "file://");
5190 path = pidgin_conversation_theme_get_template_path(theme);
5191 g_string_append(str, path);
5192 g_free(path);
5193
5194 g_string_append(str, ms[1]);
5195
5196 text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS);
5197 g_string_append(str, text);
5198
5199 g_string_append(str, ms[2]);
5200
5201 g_string_append(str, "file://");
5202 path = pidgin_conversation_theme_get_css_path(theme);
5203 g_string_append(str, path);
5204 g_free(path);
5205
5206 g_string_append(str, ms[3]);
5207 if (header)
5208 g_string_append(str, header);
5209 g_string_append(str, ms[4]);
5210 if (footer)
5211 g_string_append(str, footer);
5212 g_string_append(str, ms[5]);
5213
5214 g_strfreev(ms);
5215
5216 return g_string_free(str, FALSE);
5217 }
5218
5219 static void
5220 set_theme_webkit_settings(WebKitWebView *webview, PidginConvTheme *theme)
5221 {
5222 WebKitWebSettings *settings;
5223 const GValue *val;
5224
5225 g_object_get(G_OBJECT(webview), "settings", &settings, NULL);
5226
5227 val = pidgin_conversation_theme_lookup(theme, "DefaultFontFamily", TRUE);
5228 if (val && G_VALUE_HOLDS_STRING(val))
5229 g_object_set(G_OBJECT(settings), "default-font-family", g_value_get_string(val), NULL);
5230
5231 val = pidgin_conversation_theme_lookup(theme, "DefaultFontSize", TRUE);
5232 if (val && G_VALUE_HOLDS_INT(val))
5233 g_object_set(G_OBJECT(settings), "default-font-size", GINT_TO_POINTER(g_value_get_int(val)), NULL);
5234
5235 val = pidgin_conversation_theme_lookup(theme, "DefaultBackgroundIsTransparent", TRUE);
5236 if (val && G_VALUE_HOLDS_BOOLEAN(val))
5237 /* this does not work :( */
5238 webkit_web_view_set_transparent(webview, g_value_get_boolean(val));
5239 }
5240
5241 static void
5242 conv_variant_changed_cb(GObject *gobject, GParamSpec *pspec, gpointer user_data)
5243 {
5244 PidginConversation *gtkconv = user_data;
5245 char *path, *js;
5246
5247 path = pidgin_conversation_theme_get_css_path(PIDGIN_CONV_THEME(gobject));
5248 js = g_strdup_printf("setStylesheet(\"mainStyle\", \"file://%s\");", path);
5249 g_free(path);
5250 gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), js);
5251 g_free(js);
5252 }
5253
5254 static void
5255 load_conv_theme(PidginConversation *gtkconv)
5256 {
5257 char *header, *footer;
5258 char *template;
5259 char *basedir, *baseuri;
5260
5261 header = replace_header_tokens(gtkconv->active_conv,
5262 pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER));
5263 footer = replace_header_tokens(gtkconv->active_conv,
5264 pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER));
5265 template = replace_template_tokens(gtkconv->theme, header, footer);
5266 g_free(header);
5267 g_free(footer);
5268
5269 if (template == NULL)
5270 return;
5271
5272 set_theme_webkit_settings(WEBKIT_WEB_VIEW(gtkconv->webview), gtkconv->theme);
5273
5274 basedir = pidgin_conversation_theme_get_template_path(gtkconv->theme);
5275 baseuri = g_strdup_printf("file://%s", basedir);
5276 webkit_web_view_load_string(WEBKIT_WEB_VIEW(gtkconv->webview), template,
5277 "text/html", "UTF-8", baseuri);
5278
5279 if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT)
5280 gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview),
5281 "document.getElementById('Chat').className = 'groupchat'");
5282
5283 g_signal_connect(G_OBJECT(gtkconv->theme), "notify::variant",
5284 G_CALLBACK(conv_variant_changed_cb), gtkconv);
5285
5286 g_free(basedir);
5287 g_free(baseuri);
5288 g_free(template);
5289 }
5290
4927 static GtkWidget * 5291 static GtkWidget *
4928 setup_common_pane(PidginConversation *gtkconv) 5292 setup_common_pane(PidginConversation *gtkconv)
4929 { 5293 {
4930 GtkWidget *vbox, *frame, *imhtml_sw, *event_box; 5294 GtkWidget *vbox, *frame, *webview_sw, *event_box;
4931 GtkCellRenderer *rend; 5295 GtkCellRenderer *rend;
4932 GtkTreePath *path; 5296 GtkTreePath *path;
4933 PurpleConversation *conv = gtkconv->active_conv; 5297 PurpleConversation *conv = gtkconv->active_conv;
4934 PurpleBuddy *buddy; 5298 PurpleBuddy *buddy;
4935 gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT); 5299 gboolean chat = (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT);
4936 int buddyicon_size = 0; 5300 int buddyicon_size = 0;
4937 5301
4938 /* Setup the top part of the pane */ 5302 /* Setup the top part of the pane */
4939 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 5303 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4940 gtk_widget_show(vbox); 5304 gtk_widget_show(vbox);
5021 rend = gtk_cell_renderer_pixbuf_new(); 5385 rend = gtk_cell_renderer_pixbuf_new();
5022 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE); 5386 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); 5387 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); 5388 g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL);
5025 5389
5026 /* Setup the gtkimhtml widget */ 5390 /* Setup the webkit widget */
5027 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw); 5391 frame = pidgin_create_webview(FALSE, &gtkconv->webview, NULL, &webview_sw);
5028 gtk_widget_set_size_request(gtkconv->imhtml, -1, 0); 5392 gtk_widget_set_size_request(gtkconv->webview, -1, 0);
5393
5394 load_conv_theme(gtkconv);
5395
5029 if (chat) { 5396 if (chat) {
5030 GtkWidget *hpaned; 5397 GtkWidget *hpaned;
5031 5398
5032 /* Add the topic */ 5399 /* Add the topic */
5033 setup_chat_topic(gtkconv, vbox); 5400 setup_chat_topic(gtkconv, vbox);
5041 /* Now add the userlist */ 5408 /* Now add the userlist */
5042 setup_chat_userlist(gtkconv, hpaned); 5409 setup_chat_userlist(gtkconv, hpaned);
5043 } else { 5410 } else {
5044 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); 5411 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
5045 } 5412 }
5046 gtk_widget_show(frame); 5413 gtk_widget_show_all(frame);
5047 5414
5048 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); 5415 gtk_widget_set_name(gtkconv->webview, "pidgin_conv_webview");
5049 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE); 5416 g_object_set_data(G_OBJECT(gtkconv->webview), "gtkconv", gtkconv);
5050 g_object_set_data(G_OBJECT(gtkconv->imhtml), "gtkconv", gtkconv); 5417
5051 5418 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); 5419 G_CALLBACK(entry_stop_rclick_cb), NULL);
5056 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", 5420 g_signal_connect(G_OBJECT(gtkconv->webview), "key_press_event",
5057 G_CALLBACK(refocus_entry_cb), gtkconv); 5421 G_CALLBACK(refocus_entry_cb), gtkconv);
5058 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", 5422 g_signal_connect(G_OBJECT(gtkconv->webview), "key_release_event",
5059 G_CALLBACK(refocus_entry_cb), gtkconv); 5423 G_CALLBACK(refocus_entry_cb), gtkconv);
5060 5424
5061 pidgin_conv_setup_quickfind(gtkconv, vbox); 5425 pidgin_conv_setup_quickfind(gtkconv, vbox);
5062 5426
5063 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 5427 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); 5433 gtk_box_pack_start(GTK_BOX(gtkconv->lower_hbox), frame, TRUE, TRUE, 0);
5070 gtk_widget_show(frame); 5434 gtk_widget_show(frame);
5071 5435
5072 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); 5436 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
5073 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), 5437 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
5074 purple_account_get_protocol_name(conv->account)); 5438 purple_account_get_protocol_name(purple_conversation_get_account(conv)));
5075 5439
5076 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", 5440 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
5077 G_CALLBACK(entry_popup_menu_cb), gtkconv); 5441 G_CALLBACK(entry_popup_menu_cb), gtkconv);
5078 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 5442 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event",
5079 G_CALLBACK(entry_key_press_cb), gtkconv); 5443 G_CALLBACK(entry_key_press_cb), gtkconv);
5116 PurpleConversation *conv = gtkconv->active_conv; 5480 PurpleConversation *conv = gtkconv->active_conv;
5117 PidginWindow *win = gtkconv->win; 5481 PidginWindow *win = gtkconv->win;
5118 PurpleConversation *c; 5482 PurpleConversation *c;
5119 PurpleAccount *convaccount = purple_conversation_get_account(conv); 5483 PurpleAccount *convaccount = purple_conversation_get_account(conv);
5120 PurpleConnection *gc = purple_account_get_connection(convaccount); 5484 PurpleConnection *gc = purple_account_get_connection(convaccount);
5121 PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL; 5485 PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL;
5122 5486
5123 if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) 5487 if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
5124 { 5488 {
5125 PurpleBlistNode *n = NULL; 5489 PurpleBlistNode *n = NULL;
5126 PurpleBuddy *b; 5490 PurpleBuddy *b;
5236 }; 5600 };
5237 5601
5238 static PidginConversation * 5602 static PidginConversation *
5239 pidgin_conv_find_gtkconv(PurpleConversation * conv) 5603 pidgin_conv_find_gtkconv(PurpleConversation * conv)
5240 { 5604 {
5241 PurpleBuddy *bud = purple_find_buddy(conv->account, conv->name); 5605 PurpleBuddy *bud = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
5242 PurpleContact *c; 5606 PurpleContact *c;
5243 PurpleBlistNode *cn, *bn; 5607 PurpleBlistNode *cn, *bn;
5244 5608
5245 if (!bud) 5609 if (!bud)
5246 return NULL; 5610 return NULL;
5250 5614
5251 cn = PURPLE_BLIST_NODE(c); 5615 cn = PURPLE_BLIST_NODE(c);
5252 for (bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) { 5616 for (bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) {
5253 PurpleBuddy *b = PURPLE_BUDDY(bn); 5617 PurpleBuddy *b = PURPLE_BUDDY(bn);
5254 PurpleConversation *conv; 5618 PurpleConversation *conv;
5255 if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, b->account))) { 5619 if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(b), purple_buddy_get_account(b)))) {
5256 if (conv->ui_data) 5620 if (PIDGIN_CONVERSATION(conv))
5257 return conv->ui_data; 5621 return PIDGIN_CONVERSATION(conv);
5258 } 5622 }
5259 } 5623 }
5260 5624
5261 return NULL; 5625 return NULL;
5262 } 5626 }
5294 return FALSE; 5658 return FALSE;
5295 } 5659 }
5296 5660
5297 static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv) 5661 static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv)
5298 { 5662 {
5663 /* TODO WEBKIT */
5664 #if 0
5299 static PangoFontDescription *font_desc = NULL; 5665 static PangoFontDescription *font_desc = NULL;
5300 static GdkColor *color = NULL; 5666 static GdkColor *color = NULL;
5301 static gboolean enable = TRUE; 5667 static gboolean enable = TRUE;
5302 5668
5303 if (font_desc == NULL) { 5669 if (font_desc == NULL) {
5324 g_object_set_data(G_OBJECT(widget), "disable-typing-notification", GINT_TO_POINTER(TRUE)); 5690 g_object_set_data(G_OBJECT(widget), "disable-typing-notification", GINT_TO_POINTER(TRUE));
5325 /* or may be 'gtkconv->disable_typing = TRUE;' instead? */ 5691 /* or may be 'gtkconv->disable_typing = TRUE;' instead? */
5326 } 5692 }
5327 5693
5328 g_signal_handlers_disconnect_by_func(G_OBJECT(widget), set_typing_font, gtkconv); 5694 g_signal_handlers_disconnect_by_func(G_OBJECT(widget), set_typing_font, gtkconv);
5695 #endif /* if 0 */
5329 } 5696 }
5330 5697
5331 /************************************************************************** 5698 /**************************************************************************
5332 * Conversation UI operations 5699 * Conversation UI operations
5333 **************************************************************************/ 5700 **************************************************************************/
5334 static void 5701 static void
5335 private_gtkconv_new(PurpleConversation *conv, gboolean hidden) 5702 private_gtkconv_new(PurpleConversation *conv, gboolean hidden)
5336 { 5703 {
5337 PidginConversation *gtkconv; 5704 PidginConversation *gtkconv;
5705 const char *theme_name;
5706 PurpleTheme *theme = NULL;
5338 PurpleConversationType conv_type = purple_conversation_get_type(conv); 5707 PurpleConversationType conv_type = purple_conversation_get_type(conv);
5339 GtkWidget *pane = NULL; 5708 GtkWidget *pane = NULL;
5340 GtkWidget *tab_cont; 5709 GtkWidget *tab_cont;
5341 PurpleBlistNode *convnode; 5710 PurpleBlistNode *convnode;
5342 PurpleValue *value;
5343 5711
5344 if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) { 5712 if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) {
5345 conv->ui_data = gtkconv; 5713 purple_conversation_set_ui_data(conv, gtkconv);
5346 if (!g_list_find(gtkconv->convs, conv)) 5714 if (!g_list_find(gtkconv->convs, conv))
5347 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); 5715 gtkconv->convs = g_list_prepend(gtkconv->convs, conv);
5348 pidgin_conv_switch_active_conversation(conv); 5716 pidgin_conv_switch_active_conversation(conv);
5349 return; 5717 return;
5350 } 5718 }
5351 5719
5352 gtkconv = g_new0(PidginConversation, 1); 5720 gtkconv = g_new0(PidginConversation, 1);
5353 conv->ui_data = gtkconv; 5721 purple_conversation_set_ui_data(conv, gtkconv);
5354 gtkconv->active_conv = conv; 5722 gtkconv->active_conv = conv;
5355 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); 5723 gtkconv->convs = g_list_prepend(gtkconv->convs, conv);
5356 gtkconv->send_history = g_list_append(NULL, NULL); 5724 gtkconv->send_history = g_list_append(NULL, NULL);
5357 5725
5358 /* Setup some initial variables. */ 5726 /* Setup some initial variables. */
5727 #if !GTK_CHECK_VERSION(2,12,0)
5359 gtkconv->tooltips = gtk_tooltips_new(); 5728 gtkconv->tooltips = gtk_tooltips_new();
5729 #endif
5360 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; 5730 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
5361 gtkconv->unseen_count = 0; 5731 gtkconv->unseen_count = 0;
5732 theme_name = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/theme");
5733 if (theme_name && *theme_name)
5734 theme = purple_theme_manager_find_theme(theme_name, "conversation");
5735 if (!theme)
5736 theme = default_conv_theme;
5737 gtkconv->theme = PIDGIN_CONV_THEME(g_object_ref(theme));
5738 gtkconv->last_flags = 0;
5362 5739
5363 if (conv_type == PURPLE_CONV_TYPE_IM) { 5740 if (conv_type == PURPLE_CONV_TYPE_IM) {
5364 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); 5741 gtkconv->u.im = g_malloc0(sizeof(PidginImPane));
5365 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { 5742 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) {
5366 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); 5743 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane));
5367 } 5744 }
5368 pane = setup_common_pane(gtkconv); 5745 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 5746
5373 if (pane == NULL) { 5747 if (pane == NULL) {
5374 if (conv_type == PURPLE_CONV_TYPE_CHAT) 5748 if (conv_type == PURPLE_CONV_TYPE_CHAT)
5375 g_free(gtkconv->u.chat); 5749 g_free(gtkconv->u.chat);
5376 else if (conv_type == PURPLE_CONV_TYPE_IM) 5750 else if (conv_type == PURPLE_CONV_TYPE_IM)
5377 g_free(gtkconv->u.im); 5751 g_free(gtkconv->u.im);
5378 5752
5379 g_free(gtkconv); 5753 g_free(gtkconv);
5380 conv->ui_data = NULL; 5754 purple_conversation_set_ui_data(conv, NULL);
5381 return; 5755 return;
5382 } 5756 }
5383 5757
5384 /* Setup drag-and-drop */ 5758 /* Setup drag-and-drop */
5385 gtk_drag_dest_set(pane, 5759 gtk_drag_dest_set(pane,
5390 gtk_drag_dest_set(pane, 5764 gtk_drag_dest_set(pane,
5391 GTK_DEST_DEFAULT_MOTION | 5765 GTK_DEST_DEFAULT_MOTION |
5392 GTK_DEST_DEFAULT_DROP, 5766 GTK_DEST_DEFAULT_DROP,
5393 te, sizeof(te) / sizeof(GtkTargetEntry), 5767 te, sizeof(te) / sizeof(GtkTargetEntry),
5394 GDK_ACTION_COPY); 5768 GDK_ACTION_COPY);
5395 gtk_drag_dest_set(gtkconv->imhtml, 0, 5769 gtk_drag_dest_set(gtkconv->webview, 0,
5396 te, sizeof(te) / sizeof(GtkTargetEntry), 5770 te, sizeof(te) / sizeof(GtkTargetEntry),
5397 GDK_ACTION_COPY); 5771 GDK_ACTION_COPY);
5398 5772
5399 gtk_drag_dest_set(gtkconv->entry, 0, 5773 gtk_drag_dest_set(gtkconv->entry, 0,
5400 te, sizeof(te) / sizeof(GtkTargetEntry), 5774 te, sizeof(te) / sizeof(GtkTargetEntry),
5402 5776
5403 g_signal_connect(G_OBJECT(pane), "button_press_event", 5777 g_signal_connect(G_OBJECT(pane), "button_press_event",
5404 G_CALLBACK(ignore_middle_click), NULL); 5778 G_CALLBACK(ignore_middle_click), NULL);
5405 g_signal_connect(G_OBJECT(pane), "drag_data_received", 5779 g_signal_connect(G_OBJECT(pane), "drag_data_received",
5406 G_CALLBACK(conv_dnd_recv), gtkconv); 5780 G_CALLBACK(conv_dnd_recv), gtkconv);
5407 g_signal_connect(G_OBJECT(gtkconv->imhtml), "drag_data_received", 5781 g_signal_connect(G_OBJECT(gtkconv->webview), "drag_data_received",
5408 G_CALLBACK(conv_dnd_recv), gtkconv); 5782 G_CALLBACK(conv_dnd_recv), gtkconv);
5409 g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received", 5783 g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received",
5410 G_CALLBACK(conv_dnd_recv), gtkconv); 5784 G_CALLBACK(conv_dnd_recv), gtkconv);
5411 5785
5412 g_signal_connect(gtkconv->imhtml, "style-set", G_CALLBACK(set_typing_font), gtkconv); 5786 g_signal_connect(gtkconv->webview, "style-set", G_CALLBACK(set_typing_font), gtkconv);
5413 5787
5414 /* Setup the container for the tab. */ 5788 /* Setup the container for the tab. */
5415 gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 5789 gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
5416 g_object_set_data(G_OBJECT(tab_cont), "PidginConversation", gtkconv); 5790 g_object_set_data(G_OBJECT(tab_cont), "PidginConversation", gtkconv);
5417 gtk_container_set_border_width(GTK_CONTAINER(tab_cont), PIDGIN_HIG_BOX_SPACE); 5791 gtk_container_set_border_width(GTK_CONTAINER(tab_cont), PIDGIN_HIG_BOX_SPACE);
5420 5794
5421 convnode = get_conversation_blist_node(conv); 5795 convnode = get_conversation_blist_node(conv);
5422 if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound")) 5796 if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound"))
5423 gtkconv->make_sound = TRUE; 5797 gtkconv->make_sound = TRUE;
5424 5798
5425 if (convnode != NULL && 5799 if (convnode != NULL && purple_blist_node_has_setting(convnode, "enable-logging")) {
5426 (value = g_hash_table_lookup(convnode->settings, "enable-logging")) && 5800 gboolean logging = purple_blist_node_get_bool(convnode, "enable-logging");
5427 purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN) 5801 purple_conversation_set_logging(conv, logging);
5428 {
5429 purple_conversation_set_logging(conv, purple_value_get_boolean(value));
5430 } 5802 }
5431 5803
5432 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar")) 5804 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar"))
5433 gtk_widget_show(gtkconv->toolbar); 5805 gtk_widget_show(gtkconv->toolbar);
5434 else 5806 else
5437 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons")) 5809 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons"))
5438 gtk_widget_show(gtkconv->infopane_hbox); 5810 gtk_widget_show(gtkconv->infopane_hbox);
5439 else 5811 else
5440 gtk_widget_hide(gtkconv->infopane_hbox); 5812 gtk_widget_hide(gtkconv->infopane_hbox);
5441 5813
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 5814
5447 g_signal_connect_swapped(G_OBJECT(pane), "focus", 5815 g_signal_connect_swapped(G_OBJECT(pane), "focus",
5448 G_CALLBACK(gtk_widget_grab_focus), 5816 G_CALLBACK(gtk_widget_grab_focus),
5449 gtkconv->entry); 5817 gtkconv->entry);
5450 5818
5453 else 5821 else
5454 pidgin_conv_placement_place(gtkconv); 5822 pidgin_conv_placement_place(gtkconv);
5455 5823
5456 if (nick_colors == NULL) { 5824 if (nick_colors == NULL) {
5457 nbr_nick_colors = NUM_NICK_COLORS; 5825 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]); 5826 nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]);
5459 } 5827 }
5460 5828
5461 if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) 5829 if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
5462 pidgin_themes_smiley_themeize_custom(gtkconv->entry); 5830 pidgin_themes_smiley_themeize_custom(gtkconv->entry);
5463 } 5831 }
5464 5832
5465 static void 5833 static void
5466 pidgin_conv_new_hidden(PurpleConversation *conv) 5834 pidgin_conv_new_hidden(PurpleConversation *conv)
5557 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 5925 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
5558 purple_signals_disconnect_by_handle(gtkconv->u.chat); 5926 purple_signals_disconnect_by_handle(gtkconv->u.chat);
5559 g_free(gtkconv->u.chat); 5927 g_free(gtkconv->u.chat);
5560 } 5928 }
5561 5929
5930 #if !GTK_CHECK_VERSION(2,12,0)
5562 gtk_object_sink(GTK_OBJECT(gtkconv->tooltips)); 5931 gtk_object_sink(GTK_OBJECT(gtkconv->tooltips));
5932 #endif
5563 5933
5564 gtkconv->send_history = g_list_first(gtkconv->send_history); 5934 gtkconv->send_history = g_list_first(gtkconv->send_history);
5565 g_list_foreach(gtkconv->send_history, (GFunc)g_free, NULL); 5935 g_list_foreach(gtkconv->send_history, (GFunc)g_free, NULL);
5566 g_list_free(gtkconv->send_history); 5936 g_list_free(gtkconv->send_history);
5567 5937
5568 if (gtkconv->attach.timer) { 5938 if (gtkconv->attach.timer) {
5569 g_source_remove(gtkconv->attach.timer); 5939 g_source_remove(gtkconv->attach.timer);
5570 } 5940 }
5941
5942 g_object_disconnect(G_OBJECT(gtkconv->theme), "any_signal::notify",
5943 conv_variant_changed_cb, gtkconv, NULL);
5944 g_object_unref(gtkconv->theme);
5571 5945
5572 g_free(gtkconv); 5946 g_free(gtkconv);
5573 } 5947 }
5574 5948
5575 5949
5594 } 5968 }
5595 5969
5596 purple_conversation_write(conv, who, message, flags, mtime); 5970 purple_conversation_write(conv, who, message, flags, mtime);
5597 } 5971 }
5598 5972
5973 #if 0
5599 static const char * 5974 static const char *
5600 get_text_tag_color(GtkTextTag *tag) 5975 get_text_tag_color(GtkTextTag *tag)
5601 { 5976 {
5602 GdkColor *color = NULL; 5977 GdkColor *color = NULL;
5603 gboolean set = FALSE; 5978 gboolean set = FALSE;
5657 if (!gtk_text_buffer_get_selection_bounds( 6032 if (!gtk_text_buffer_get_selection_bounds(
5658 gtk_text_iter_get_buffer(arg2), 6033 gtk_text_iter_get_buffer(arg2),
5659 &start, &end)) { 6034 &start, &end)) {
5660 GtkWidget *menu = NULL; 6035 GtkWidget *menu = NULL;
5661 PurpleConnection *gc = 6036 PurpleConnection *gc =
5662 purple_conversation_get_gc(conv); 6037 purple_conversation_get_connection(conv);
5663 6038
5664 6039
5665 menu = create_chat_menu(conv, buddyname, gc); 6040 menu = create_chat_menu(conv, buddyname, gc);
5666 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, 6041 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
5667 NULL, GTK_WIDGET(imhtml), 6042 NULL, GTK_WIDGET(imhtml),
5674 } 6049 }
5675 } 6050 }
5676 6051
5677 return FALSE; 6052 return FALSE;
5678 } 6053 }
6054 #endif
5679 6055
5680 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, 6056 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag,
5681 gboolean create) 6057 gboolean create)
5682 { 6058 {
6059 /* TODO WEBKIT */
6060 #if 0
5683 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); 6061 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
5684 GtkTextTag *buddytag; 6062 GtkTextTag *buddytag;
5685 gchar *str; 6063 gchar *str;
5686 gboolean highlight = (flag & PURPLE_MESSAGE_NICK); 6064 gboolean highlight = (flag & PURPLE_MESSAGE_NICK);
5687 GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer; 6065 GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer;
5711 } 6089 }
5712 6090
5713 g_free(str); 6091 g_free(str);
5714 6092
5715 return buddytag; 6093 return buddytag;
5716 } 6094 #endif /* if 0 */
5717 6095 return NULL;
6096 }
6097
6098 #if 0
5718 static void pidgin_conv_calculate_newday(PidginConversation *gtkconv, time_t mtime) 6099 static void pidgin_conv_calculate_newday(PidginConversation *gtkconv, time_t mtime)
5719 { 6100 {
5720 struct tm *tm = localtime(&mtime); 6101 struct tm *tm = localtime(&mtime);
5721 6102
5722 tm->tm_hour = tm->tm_min = tm->tm_sec = 0; 6103 tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
5758 6139
5759 g_free(*str); 6140 g_free(*str);
5760 *str = ret; 6141 *str = ret;
5761 #endif 6142 #endif
5762 } 6143 }
6144 #endif
6145
6146 static char *
6147 replace_message_tokens(
6148 const char *text,
6149 PurpleConversation *conv,
6150 const char *name,
6151 const char *alias,
6152 const char *message,
6153 PurpleMessageFlags flags,
6154 time_t mtime)
6155 {
6156 GString *str;
6157 const char *cur = text;
6158 const char *prev = cur;
6159 struct tm *tm = NULL;
6160
6161 if (text == NULL || *text == '\0')
6162 return NULL;
6163
6164 str = g_string_new(NULL);
6165 while ((cur = strchr(cur, '%'))) {
6166 const char *replace = NULL;
6167 const char *fin = NULL;
6168 gpointer freeval = NULL;
6169
6170 if (g_str_has_prefix(cur, "%message%")) {
6171 replace = message;
6172
6173 } else if (g_str_has_prefix(cur, "%messageClasses%")) {
6174 GString *classes = g_string_new(NULL);
6175 #define ADD_CLASS(f, class) \
6176 if (flags & f) \
6177 g_string_append(classes, class);
6178 ADD_CLASS(PURPLE_MESSAGE_SEND, "outgoing ");
6179 ADD_CLASS(PURPLE_MESSAGE_RECV, "incoming ");
6180 ADD_CLASS(PURPLE_MESSAGE_SYSTEM, "event ");
6181 ADD_CLASS(PURPLE_MESSAGE_AUTO_RESP, "autoreply ");
6182 ADD_CLASS(PURPLE_MESSAGE_DELAYED, "history ");
6183 ADD_CLASS(PURPLE_MESSAGE_NICK, "mention ");
6184 #undef ADD_CLASS
6185
6186 replace = freeval = g_string_free(classes, FALSE);
6187
6188 } else if (g_str_has_prefix(cur, "%time")) {
6189 const char *tmp = cur + strlen("%time");
6190 char *format = NULL;
6191
6192 if (*tmp == '{') {
6193 char *end;
6194 tmp++;
6195 end = strstr(tmp, "}%");
6196 if (!end) /* Invalid string */
6197 continue;
6198 format = g_strndup(tmp, end - tmp);
6199 fin = end + 1;
6200 }
6201
6202 if (!tm)
6203 tm = localtime(&mtime);
6204
6205 replace = purple_utf8_strftime(format ? format : "%X", tm);
6206 g_free(format);
6207
6208 } else if (g_str_has_prefix(cur, "%shortTime%")) {
6209 if (!tm)
6210 tm = localtime(&mtime);
6211
6212 replace = purple_utf8_strftime("%H:%M", tm);
6213
6214 } else if (g_str_has_prefix(cur, "%userIconPath%")) {
6215 if (flags & PURPLE_MESSAGE_SEND) {
6216 if (purple_account_get_bool(purple_conversation_get_account(conv), "use-global-buddyicon", TRUE)) {
6217 replace = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon");
6218 } else {
6219 PurpleStoredImage *img = purple_buddy_icons_find_account_icon(purple_conversation_get_account(conv));
6220 replace = purple_imgstore_get_filename(img);
6221 }
6222 if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) {
6223 replace = freeval = g_build_filename("Outgoing", "buddy_icon.png", NULL);
6224 }
6225 } else if (flags & PURPLE_MESSAGE_RECV) {
6226 PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
6227 if (icon)
6228 replace = purple_buddy_icon_get_full_path(icon);
6229 if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) {
6230 replace = freeval = g_build_filename("Incoming", "buddy_icon.png", NULL);
6231 }
6232 }
6233
6234 } else if (g_str_has_prefix(cur, "%senderScreenName%")) {
6235 replace = name;
6236
6237 } else if (g_str_has_prefix(cur, "%sender%")) {
6238 replace = alias;
6239
6240 } else if (g_str_has_prefix(cur, "%service%")) {
6241 replace = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6242
6243 } else if (g_str_has_prefix(cur, "%messageDirection%")) {
6244 replace = purple_markup_is_rtl(message) ? "rtl" : "ltr";
6245
6246 } else if (g_str_has_prefix(cur, "%status%")) {
6247 GString *classes = g_string_new(NULL);
6248
6249 if (flags & PURPLE_MESSAGE_ERROR)
6250 g_string_append(classes, "error ");
6251
6252 replace = freeval = g_string_free(classes, FALSE);
6253
6254 } else {
6255 cur++;
6256 continue;
6257 }
6258
6259 /* Here we have a replacement to make */
6260 g_string_append_len(str, prev, cur - prev);
6261 if (replace)
6262 g_string_append(str, replace);
6263 g_free(freeval);
6264 replace = freeval = NULL;
6265
6266 /* And update the pointers */
6267 if (fin) {
6268 prev = cur = fin + 1;
6269 } else {
6270 prev = cur = strchr(cur + 1, '%') + 1;
6271 }
6272
6273 }
6274
6275 /* And wrap it up */
6276 g_string_append(str, prev);
6277
6278 return g_string_free(str, FALSE);
6279 }
5763 6280
5764 static void 6281 static void
5765 pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias, 6282 pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias,
5766 const char *message, PurpleMessageFlags flags, 6283 const char *message, PurpleMessageFlags flags,
5767 time_t mtime) 6284 time_t mtime)
5768 { 6285 {
5769 PidginConversation *gtkconv; 6286 PidginConversation *gtkconv;
5770 PurpleConnection *gc; 6287 PurpleConnection *gc;
5771 PurpleAccount *account; 6288 PurpleAccount *account;
6289 #if 0
5772 int gtk_font_options = 0; 6290 int gtk_font_options = 0;
5773 int gtk_font_options_all = 0; 6291 int gtk_font_options_all = 0;
5774 int max_scrollback_lines;
5775 int line_count;
5776 char buf2[BUF_LONG]; 6292 char buf2[BUF_LONG];
5777 gboolean show_date; 6293 gboolean show_date;
5778 char *mdate; 6294 char *mdate;
5779 char *str; 6295 char *str;
5780 char *with_font_tag; 6296 char *with_font_tag;
5781 char *sml_attrib = NULL; 6297 char *sml_attrib = NULL;
6298 #endif
5782 size_t length; 6299 size_t length;
5783 PurpleConversationType type; 6300 PurpleConversationType type;
5784 char *displaying; 6301 char *displaying;
5785 gboolean plugin_return; 6302 gboolean plugin_return;
5786 char *bracket; 6303 #if 0
5787 int tag_count = 0;
5788 gboolean is_rtl_message = FALSE; 6304 gboolean is_rtl_message = FALSE;
6305 #endif
6306
6307 const char *message_html;
6308 char *msg;
6309 char *escape;
6310 char *script;
6311 char *smileyed;
6312 PurpleMessageFlags old_flags;
6313 const char *func = "appendMessage";
5789 6314
5790 g_return_if_fail(conv != NULL); 6315 g_return_if_fail(conv != NULL);
5791 gtkconv = PIDGIN_CONVERSATION(conv); 6316 gtkconv = PIDGIN_CONVERSATION(conv);
5792 g_return_if_fail(gtkconv != NULL); 6317 g_return_if_fail(gtkconv != NULL);
5793 6318
5840 g_free(displaying); 6365 g_free(displaying);
5841 return; 6366 return;
5842 } 6367 }
5843 length = strlen(displaying) + 1; 6368 length = strlen(displaying) + 1;
5844 6369
5845 /* Awful hack to work around GtkIMHtml's inefficient rendering of messages with lots of formatting changes. 6370 old_flags = gtkconv->last_flags;
5846 * If a message has over 100 '<' characters, strip formatting before appending it. Hopefully nobody actually 6371 if ((flags & PURPLE_MESSAGE_SEND) && (old_flags & PURPLE_MESSAGE_SEND)) {
5847 * needs that much formatting, anyway. 6372 message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
5848 */ 6373 PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT);
5849 for (bracket = strchr(displaying, '<'); bracket && *(bracket + 1); bracket = strchr(bracket + 1, '<')) 6374 func = "appendNextMessage";
5850 tag_count++; 6375
5851 6376 } else if (flags & PURPLE_MESSAGE_SEND) {
5852 if (tag_count > 100) { 6377 message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
5853 char *tmp = displaying; 6378 PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT);
5854 displaying = purple_markup_strip_html(tmp); 6379
5855 g_free(tmp); 6380 } else if ((flags & PURPLE_MESSAGE_RECV) && (old_flags & PURPLE_MESSAGE_RECV)) {
5856 } 6381 GList *history = purple_conversation_get_message_history(conv);
5857 6382 PurpleConvMessage *last_msg = (PurpleConvMessage *)history->data;
5858 line_count = gtk_text_buffer_get_line_count( 6383
5859 gtk_text_view_get_buffer(GTK_TEXT_VIEW( 6384 /* If the senders are the same, use appendNextMessage */
5860 gtkconv->imhtml))); 6385 if (purple_strequal(purple_conversation_message_get_sender(last_msg), name)) {
5861 6386 message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
5862 max_scrollback_lines = purple_prefs_get_int( 6387 PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT);
5863 PIDGIN_PREFS_ROOT "/conversations/scrollback_lines"); 6388 func = "appendNextMessage";
5864 /* If we're sitting at more than 100 lines more than the 6389 } else {
5865 max scrollback, trim down to max scrollback */ 6390 message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
5866 if (max_scrollback_lines > 0 6391 PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT);
5867 && line_count > (max_scrollback_lines + 100)) { 6392 }
5868 GtkTextBuffer *text_buffer = gtk_text_view_get_buffer( 6393 } else if (flags & PURPLE_MESSAGE_RECV) {
5869 GTK_TEXT_VIEW(gtkconv->imhtml)); 6394 message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
5870 GtkTextIter start, end; 6395 PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT);
5871 6396
5872 gtk_text_buffer_get_start_iter(text_buffer, &start); 6397 } else {
5873 gtk_text_buffer_get_iter_at_line(text_buffer, &end, 6398 message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
5874 (line_count - max_scrollback_lines)); 6399 PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS);
5875 gtk_imhtml_delete(GTK_IMHTML(gtkconv->imhtml), &start, &end); 6400 }
5876 } 6401 gtkconv->last_flags = flags;
5877 6402
5878 if (type == PURPLE_CONV_TYPE_CHAT) 6403 smileyed = smiley_parse_markup(displaying, purple_account_get_protocol_id(account));
5879 { 6404 msg = replace_message_tokens(message_html, conv, name, alias, smileyed, flags, mtime);
5880 /* Create anchor for user */ 6405 escape = gtk_webview_quote_js_string(msg ? msg : "");
5881 GtkTextIter iter; 6406 script = g_strdup_printf("%s(%s)", func, escape);
5882 char *tmp = g_strconcat("user:", name, NULL); 6407
5883 6408 purple_debug_info("webkit", "JS: %s\n", script);
5884 gtk_text_buffer_get_end_iter(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)), &iter); 6409 gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), script);
5885 gtk_text_buffer_create_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)), 6410
5886 tmp, &iter, TRUE); 6411 g_free(script);
5887 g_free(tmp); 6412 g_free(smileyed);
5888 } 6413 g_free(msg);
5889 6414 g_free(escape);
5890 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling")) 6415
5891 gtk_font_options_all |= GTK_IMHTML_USE_SMOOTHSCROLLING; 6416 #if 0
5892 6417 /* if the buffer is not empty add a <br> */
5893 if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)))) 6418 if (!gtk_webview_is_empty(GTK_WEBVIEW(gtkconv->webview)))
5894 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", gtk_font_options_all | GTK_IMHTML_NO_SCROLL); 6419 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<br />");
5895 6420
5896 /* First message in a conversation. */ 6421 /* First message in a conversation. */
5897 if (gtkconv->newday == 0) 6422 if (gtkconv->newday == 0)
5898 pidgin_conv_calculate_newday(gtkconv, mtime); 6423 pidgin_conv_calculate_newday(gtkconv, mtime);
5899 6424
5932 if ((flags & PURPLE_MESSAGE_RECV) && 6457 if ((flags & PURPLE_MESSAGE_RECV) &&
5933 !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting")) 6458 !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; 6459 gtk_font_options |= GTK_IMHTML_NO_COLOURS | GTK_IMHTML_NO_FONTS | GTK_IMHTML_NO_SIZES | GTK_IMHTML_NO_FORMATTING;
5935 6460
5936 /* this is gonna crash one day, I can feel it. */ 6461 /* 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 & 6462 if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(purple_conversation_get_account(conv))))->options &
5938 OPT_PROTO_USE_POINTSIZE) { 6463 OPT_PROTO_USE_POINTSIZE) {
5939 gtk_font_options |= GTK_IMHTML_USE_POINTSIZE; 6464 gtk_font_options |= GTK_IMHTML_USE_POINTSIZE;
5940 } 6465 }
5941 6466
5942 if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) 6467 if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY))
5943 { 6468 {
5944 /* We want to see our own smileys. Need to revert it after send*/ 6469 /* We want to see our own smileys. Need to revert it after send*/
5945 pidgin_themes_smiley_themeize_custom(gtkconv->imhtml); 6470 pidgin_themes_smiley_themeize_custom(gtkconv->webview);
5946 } 6471 }
5947 6472
5948 /* TODO: These colors should not be hardcoded so log.c can use them */ 6473 /* TODO: These colors should not be hardcoded so log.c can use them */
5949 if (flags & PURPLE_MESSAGE_RAW) { 6474 if (flags & PURPLE_MESSAGE_RAW) {
5950 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, gtk_font_options_all); 6475 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), message);
5951 } else if (flags & PURPLE_MESSAGE_SYSTEM) { 6476 } else if (flags & PURPLE_MESSAGE_SYSTEM) {
5952 g_snprintf(buf2, sizeof(buf2), 6477 g_snprintf(buf2, sizeof(buf2),
5953 "<FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT>", 6478 "<font %s><font size=\"2\"><span class='timestamp'>%s</span></font><b>%s</b></font>",
5954 sml_attrib ? sml_attrib : "", mdate, displaying); 6479 sml_attrib ? sml_attrib : "", mdate, displaying);
5955 6480
5956 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); 6481 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
5957 6482
5958 } else if (flags & PURPLE_MESSAGE_ERROR) { 6483 } else if (flags & PURPLE_MESSAGE_ERROR) {
5959 g_snprintf(buf2, sizeof(buf2), 6484 g_snprintf(buf2, sizeof(buf2),
5960 "<FONT COLOR=\"#ff0000\"><FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT></FONT>", 6485 "<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); 6486 sml_attrib ? sml_attrib : "", mdate, displaying);
5962 6487
5963 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); 6488 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
5964 6489
5965 } else if (flags & PURPLE_MESSAGE_NO_LOG) { 6490 } else if (flags & PURPLE_MESSAGE_NO_LOG) {
5966 g_snprintf(buf2, BUF_LONG, 6491 g_snprintf(buf2, BUF_LONG,
5967 "<B><FONT %s COLOR=\"#777777\">%s</FONT></B>", 6492 "<b><font %s color=\"#777777\">%s</font></b>",
5968 sml_attrib ? sml_attrib : "", displaying); 6493 sml_attrib ? sml_attrib : "", displaying);
5969 6494
5970 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); 6495 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
5971 } else { 6496 } else {
5972 char *new_message = g_memdup(displaying, length); 6497 char *new_message = g_memdup(displaying, length);
5973 char *alias_escaped = (alias ? g_markup_escape_text(alias, strlen(alias)) : g_strdup("")); 6498 char *alias_escaped = (alias ? g_markup_escape_text(alias, strlen(alias)) : g_strdup(""));
5974 /* The initial offset is to deal with 6499 /* The initial offset is to deal with
5975 * escaped entities making the string longer */ 6500 * escaped entities making the string longer */
5976 int tag_start_offset = 0; 6501 int tag_start_offset = 0;
5977 int tag_end_offset = 0; 6502 int tag_end_offset = 0;
5978 const char *tagname = NULL; 6503 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 6504
5985 /* Enforce direction on alias */ 6505 /* Enforce direction on alias */
5986 if (is_rtl_message) 6506 if (is_rtl_message)
5987 str_embed_direction_chars(&alias_escaped); 6507 str_embed_direction_chars(&alias_escaped);
5988 6508
6040 } 6560 }
6041 } 6561 }
6042 6562
6043 g_free(alias_escaped); 6563 g_free(alias_escaped);
6044 6564
6565 /* TODO WEBKIT */
6566 #if 0
6045 if (tagname) 6567 if (tagname)
6046 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname); 6568 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname);
6047 else 6569 else
6048 tag = get_buddy_tag(conv, name, flags, TRUE); 6570 tag = get_buddy_tag(conv, name, flags, TRUE);
6049 6571
6050 if (GTK_IMHTML(gtkconv->imhtml)->show_comments) { 6572 if (GTK_IMHTML(gtkconv->imhtml)->show_comments) {
6573 {
6051 /* The color for the timestamp has to be set in the font-tags, unfortunately. 6574 /* 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 6575 * 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 6576 * 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 6577 * 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 */ 6578 * this will have to do. I don't terribly like it. -- sadrul */
6056 const char *color = get_text_tag_color(tag); 6579 /* const char *color = get_text_tag_color(tag); */
6057 g_snprintf(buf2, BUF_LONG, "<FONT %s%s%s SIZE=\"2\"><!--%s --></FONT>", 6580 g_snprintf(buf2, BUF_LONG, "<FONT %s%s%s SIZE=\"2\"><!--%s --></FONT>",
6058 color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate); 6581 color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate);
6059 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); 6582 gtk_webview_append_html (GTK_WEBVIEW(gtkconv->webview), buf2);
6060 } 6583 }
6061 6584 #endif /* if 0 */
6062 gtk_text_buffer_get_end_iter(buffer, &end); 6585 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); 6586 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 6587
6073 g_free(str); 6588 g_free(str);
6074 6589
6075 if(gc){ 6590 if (gc) {
6076 char *pre = g_strdup_printf("<font %s>", sml_attrib ? sml_attrib : ""); 6591 char *pre = g_strdup_printf("<font %s>", sml_attrib ? sml_attrib : "");
6077 char *post = "</font>"; 6592 char *post = "</font>";
6078 int pre_len = strlen(pre); 6593 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); 6594 g_free(pre);
6089 } else 6595 } else
6090 with_font_tag = g_memdup(new_message, length); 6596 with_font_tag = g_memdup(new_message, length);
6091 6597
6092 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), 6598 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview),
6093 with_font_tag, gtk_font_options | gtk_font_options_all); 6599 with_font_tag);
6094 6600
6095 g_free(with_font_tag); 6601 g_free(with_font_tag);
6096 g_free(new_message); 6602 g_free(new_message);
6097 } 6603 }
6098 6604
6099 g_free(mdate); 6605 g_free(mdate);
6100 g_free(sml_attrib); 6606 g_free(sml_attrib);
6607
6608 #endif
6101 6609
6102 /* Tab highlighting stuff */ 6610 /* Tab highlighting stuff */
6103 if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv)) 6611 if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv))
6104 { 6612 {
6105 PidginUnseenState unseen = PIDGIN_UNSEEN_NONE; 6613 PidginUnseenState unseen = PIDGIN_UNSEEN_NONE;
6115 unseen = PIDGIN_UNSEEN_TEXT; 6623 unseen = PIDGIN_UNSEEN_TEXT;
6116 6624
6117 gtkconv_set_unseen(gtkconv, unseen); 6625 gtkconv_set_unseen(gtkconv, unseen);
6118 } 6626 }
6119 6627
6120 if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) 6628 #if 0
6629 if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY))
6121 { 6630 {
6122 /* Restore the smiley-data */ 6631 /* Restore the smiley-data */
6123 pidgin_themes_smiley_themeize(gtkconv->imhtml); 6632 pidgin_themes_smiley_themeize(gtkconv->webview);
6124 } 6633 }
6634 #endif
6125 6635
6126 purple_signal_emit(pidgin_conversations_get_handle(), 6636 purple_signal_emit(pidgin_conversations_get_handle(),
6127 (type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"), 6637 (type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"),
6128 account, name, displaying, conv, flags); 6638 account, name, displaying, conv, flags);
6129 g_free(displaying); 6639 g_free(displaying);
6136 GtkTreePath *path; 6646 GtkTreePath *path;
6137 GtkTreeModel *model; 6647 GtkTreeModel *model;
6138 6648
6139 g_return_val_if_fail(cb != NULL, FALSE); 6649 g_return_val_if_fail(cb != NULL, FALSE);
6140 6650
6141 ref = cb->ui_data; 6651 ref = purple_conv_chat_cb_get_ui_data(cb);
6142 if (!ref) 6652 if (!ref)
6143 return FALSE; 6653 return FALSE;
6144 6654
6145 if ((path = gtk_tree_row_reference_get_path(ref)) == NULL) 6655 if ((path = gtk_tree_row_reference_get_path(ref)) == NULL)
6146 return FALSE; 6656 return FALSE;
6227 old_cbuddy = purple_conv_chat_cb_find(chat, old_name); 6737 old_cbuddy = purple_conv_chat_cb_find(chat, old_name);
6228 if (!old_cbuddy) 6738 if (!old_cbuddy)
6229 return; 6739 return;
6230 6740
6231 if (get_iter_from_chatbuddy(old_cbuddy, &iter)) { 6741 if (get_iter_from_chatbuddy(old_cbuddy, &iter)) {
6232 GtkTreeRowReference *ref = old_cbuddy->ui_data; 6742 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(old_cbuddy);
6233 6743
6234 gtk_list_store_remove(GTK_LIST_STORE(model), &iter); 6744 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
6235 gtk_tree_row_reference_free(ref); 6745 gtk_tree_row_reference_free(ref);
6236 old_cbuddy->ui_data = NULL; 6746 purple_conv_chat_cb_set_ui_data(old_cbuddy, NULL);
6237 } 6747 }
6238 6748
6239 g_return_if_fail(new_alias != NULL); 6749 g_return_if_fail(new_alias != NULL);
6240 6750
6241 new_cbuddy = purple_conv_chat_cb_find(chat, new_name); 6751 new_cbuddy = purple_conv_chat_cb_find(chat, new_name);
6320 cbuddy = purple_conv_chat_cb_find(chat, user); 6830 cbuddy = purple_conv_chat_cb_find(chat, user);
6321 if (!cbuddy) 6831 if (!cbuddy)
6322 return; 6832 return;
6323 6833
6324 if (get_iter_from_chatbuddy(cbuddy, &iter)) { 6834 if (get_iter_from_chatbuddy(cbuddy, &iter)) {
6325 GtkTreeRowReference *ref = cbuddy->ui_data; 6835 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cbuddy);
6326 gtk_list_store_remove(GTK_LIST_STORE(model), &iter); 6836 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
6327 gtk_tree_row_reference_free(ref); 6837 gtk_tree_row_reference_free(ref);
6328 cbuddy->ui_data = NULL; 6838 purple_conv_chat_cb_set_ui_data(cbuddy, NULL);
6329 } 6839 }
6330 6840
6331 if (cbuddy) 6841 if (cbuddy)
6332 add_chat_buddy_common(conv, cbuddy, NULL); 6842 add_chat_buddy_common(conv, cbuddy, NULL);
6333 } 6843 }
6370 6880
6371 return TRUE; 6881 return TRUE;
6372 } 6882 }
6373 6883
6374 static gboolean 6884 static gboolean
6885 add_custom_smiley_for_webview(GtkWebView *webview, const char *sml, const char *smile)
6886 {
6887 /* TODO WEBKIT: Smileys need to be added to webkit stuff */
6888 return TRUE;
6889 }
6890
6891 static gboolean
6375 pidgin_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, gboolean remote) 6892 pidgin_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, gboolean remote)
6376 { 6893 {
6377 PidginConversation *gtkconv; 6894 PidginConversation *gtkconv;
6378 struct smiley_list *list; 6895 struct smiley_list *list;
6379 const char *sml = NULL, *conv_sml; 6896 const char *sml = NULL, *conv_sml;
6386 if (pidgin_themes_smileys_disabled()) 6903 if (pidgin_themes_smileys_disabled())
6387 return FALSE; 6904 return FALSE;
6388 6905
6389 /* If possible add this smiley to the current theme. 6906 /* If possible add this smiley to the current theme.
6390 * The addition is only temporary: custom smilies aren't saved to disk. */ 6907 * The addition is only temporary: custom smilies aren't saved to disk. */
6391 conv_sml = purple_account_get_protocol_name(conv->account); 6908 conv_sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6392 gtkconv = PIDGIN_CONVERSATION(conv); 6909 gtkconv = PIDGIN_CONVERSATION(conv);
6393 6910
6394 for (list = (struct smiley_list *)current_smiley_theme->list; list; list = list->next) { 6911 for (list = (struct smiley_list *)current_smiley_theme->list; list; list = list->next) {
6395 if (!strcmp(list->sml, conv_sml)) { 6912 if (!strcmp(list->sml, conv_sml)) {
6396 sml = list->sml; 6913 sml = list->sml;
6397 break; 6914 break;
6398 } 6915 }
6399 } 6916 }
6400 6917
6401 if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->imhtml), sml, smile)) 6918 if (!add_custom_smiley_for_webview(GTK_WEBVIEW(gtkconv->webview), sml, smile))
6402 return FALSE; 6919 return FALSE;
6403 6920
6404 if (!remote) /* If it's a local custom smiley, then add it for the entry */ 6921 if (!remote) /* If it's a local custom smiley, then add it for the entry */
6405 if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->entry), sml, smile)) 6922 if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->entry), sml, smile))
6406 return FALSE; 6923 return FALSE;
6410 6927
6411 static void 6928 static void
6412 pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile, 6929 pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile,
6413 const guchar *data, gsize size) 6930 const guchar *data, gsize size)
6414 { 6931 {
6932 /* TODO WEBKIT */
6933 #if 0
6415 PidginConversation *gtkconv; 6934 PidginConversation *gtkconv;
6416 GtkIMHtmlSmiley *smiley; 6935 GtkIMHtmlSmiley *smiley;
6417 const char *sml; 6936 const char *sml;
6418 GError *error = NULL; 6937 GError *error = NULL;
6419 6938
6420 sml = purple_account_get_protocol_name(conv->account); 6939 sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6421 gtkconv = PIDGIN_CONVERSATION(conv); 6940 gtkconv = PIDGIN_CONVERSATION(conv);
6422 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); 6941 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile);
6423 6942
6424 if (!smiley) 6943 if (!smiley)
6425 return; 6944 return;
6431 if (!smiley->loader) 6950 if (!smiley->loader)
6432 return; 6951 return;
6433 6952
6434 if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) { 6953 if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) {
6435 purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() " 6954 purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() "
6436 "failed with size=%zu: %s\n", size, 6955 "failed with size=%" G_GSIZE_FORMAT ": %s\n", size,
6437 error ? error->message : "(no error message)"); 6956 error ? error->message : "(no error message)");
6438 if (error) 6957 if (error)
6439 g_error_free(error); 6958 g_error_free(error);
6440 /* We must stop using the GdkPixbufLoader because trying to load 6959 /* We must stop using the GdkPixbufLoader because trying to load
6441 certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return 6960 certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return
6444 But we also don't want to set smiley->loader to NULL because our 6963 But we also don't want to set smiley->loader to NULL because our
6445 code might expect it to be set. So create a new loader. */ 6964 code might expect it to be set. So create a new loader. */
6446 g_object_unref(G_OBJECT(smiley->loader)); 6965 g_object_unref(G_OBJECT(smiley->loader));
6447 smiley->loader = gdk_pixbuf_loader_new(); 6966 smiley->loader = gdk_pixbuf_loader_new();
6448 } 6967 }
6968 #endif /* if 0 */
6449 } 6969 }
6450 6970
6451 static void 6971 static void
6452 pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile) 6972 pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile)
6453 { 6973 {
6974 /* TODO WEBKIT */
6975 #if 0
6454 PidginConversation *gtkconv; 6976 PidginConversation *gtkconv;
6455 GtkIMHtmlSmiley *smiley; 6977 GtkIMHtmlSmiley *smiley;
6456 const char *sml; 6978 const char *sml;
6457 GError *error = NULL; 6979 GError *error = NULL;
6458 6980
6459 g_return_if_fail(conv != NULL); 6981 g_return_if_fail(conv != NULL);
6460 g_return_if_fail(smile != NULL); 6982 g_return_if_fail(smile != NULL);
6461 6983
6462 sml = purple_account_get_protocol_name(conv->account); 6984 sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6463 gtkconv = PIDGIN_CONVERSATION(conv); 6985 gtkconv = PIDGIN_CONVERSATION(conv);
6464 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); 6986 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile);
6465 6987
6466 if (!smiley) 6988 if (!smiley)
6467 return; 6989 return;
6485 to set smiley->loader to NULL because our code might expect it 7007 to set smiley->loader to NULL because our code might expect it
6486 to be set. So create a new loader. */ 7008 to be set. So create a new loader. */
6487 g_object_unref(G_OBJECT(smiley->loader)); 7009 g_object_unref(G_OBJECT(smiley->loader));
6488 smiley->loader = gdk_pixbuf_loader_new(); 7010 smiley->loader = gdk_pixbuf_loader_new();
6489 } 7011 }
7012 #endif /* if 0 */
6490 } 7013 }
6491 7014
6492 static void 7015 static void
6493 pidgin_conv_send_confirm(PurpleConversation *conv, const char *message) 7016 pidgin_conv_send_confirm(PurpleConversation *conv, const char *message)
6494 { 7017 {
6512 GdkPixbuf *window_icon = NULL; 7035 GdkPixbuf *window_icon = NULL;
6513 GtkIMHtmlButtons buttons; 7036 GtkIMHtmlButtons buttons;
6514 PurpleAccount *account; 7037 PurpleAccount *account;
6515 7038
6516 win = pidgin_conv_get_window(gtkconv); 7039 win = pidgin_conv_get_window(gtkconv);
6517 gc = purple_conversation_get_gc(conv); 7040 gc = purple_conversation_get_connection(conv);
6518 account = purple_conversation_get_account(conv); 7041 account = purple_conversation_get_account(conv);
6519 7042
6520 if (gc != NULL) 7043 if (gc != NULL)
6521 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 7044 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
6522 7045
6523 if (win->menu.send_to != NULL) 7046 if (win->menu.send_to != NULL)
6524 update_send_to_selection(win); 7047 update_send_to_selection(win);
6525 7048
6526 /* 7049 /*
6533 */ 7056 */
6534 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 7057 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
6535 /* Show stuff that applies to IMs, hide stuff that applies to chats */ 7058 /* Show stuff that applies to IMs, hide stuff that applies to chats */
6536 7059
6537 /* Deal with menu items */ 7060 /* Deal with menu items */
6538 gtk_widget_show(win->menu.view_log); 7061 gtk_action_set_visible(win->menu.view_log, TRUE);
6539 gtk_widget_show(win->menu.send_file); 7062 gtk_action_set_visible(win->menu.send_file, TRUE);
6540 gtk_widget_show(g_object_get_data(G_OBJECT(win->window), "get_attention")); 7063 gtk_action_set_visible(win->menu.get_attention, TRUE);
6541 gtk_widget_show(win->menu.add_pounce); 7064 gtk_action_set_visible(win->menu.add_pounce, TRUE);
6542 gtk_widget_show(win->menu.get_info); 7065 gtk_action_set_visible(win->menu.get_info, TRUE);
6543 gtk_widget_hide(win->menu.invite); 7066 gtk_action_set_visible(win->menu.invite, FALSE);
6544 gtk_widget_show(win->menu.alias); 7067 gtk_action_set_visible(win->menu.alias, TRUE);
6545 if (purple_privacy_check(account, purple_conversation_get_name(conv))) { 7068 if (purple_privacy_check(account, purple_conversation_get_name(conv))) {
6546 gtk_widget_hide(win->menu.unblock); 7069 gtk_action_set_visible(win->menu.unblock, FALSE);
6547 gtk_widget_show(win->menu.block); 7070 gtk_action_set_visible(win->menu.block, TRUE);
6548 } else { 7071 } else {
6549 gtk_widget_hide(win->menu.block); 7072 gtk_action_set_visible(win->menu.block, FALSE);
6550 gtk_widget_show(win->menu.unblock); 7073 gtk_action_set_visible(win->menu.unblock, TRUE);
6551 } 7074 }
6552 7075
6553 if ((account == NULL) || purple_find_buddy(account, purple_conversation_get_name(conv)) == NULL) { 7076 if ((account == NULL) || purple_find_buddy(account, purple_conversation_get_name(conv)) == NULL) {
6554 gtk_widget_show(win->menu.add); 7077 gtk_action_set_visible(win->menu.add, TRUE);
6555 gtk_widget_hide(win->menu.remove); 7078 gtk_action_set_visible(win->menu.remove, FALSE);
6556 } else { 7079 } else {
6557 gtk_widget_show(win->menu.remove); 7080 gtk_action_set_visible(win->menu.remove, TRUE);
6558 gtk_widget_hide(win->menu.add); 7081 gtk_action_set_visible(win->menu.add, FALSE);
6559 } 7082 }
6560 7083
6561 gtk_widget_show(win->menu.insert_link); 7084 gtk_action_set_visible(win->menu.insert_link, TRUE);
6562 gtk_widget_show(win->menu.insert_image); 7085 gtk_action_set_visible(win->menu.insert_image, TRUE);
6563 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 7086 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
6564 /* Show stuff that applies to Chats, hide stuff that applies to IMs */ 7087 /* Show stuff that applies to Chats, hide stuff that applies to IMs */
6565 7088
6566 /* Deal with menu items */ 7089 /* Deal with menu items */
6567 gtk_widget_show(win->menu.view_log); 7090 gtk_action_set_visible(win->menu.view_log, TRUE);
6568 gtk_widget_hide(win->menu.send_file); 7091 gtk_action_set_visible(win->menu.send_file, FALSE);
6569 gtk_widget_hide(g_object_get_data(G_OBJECT(win->window), "get_attention")); 7092 gtk_action_set_visible(win->menu.get_attention, FALSE);
6570 gtk_widget_hide(win->menu.add_pounce); 7093 gtk_action_set_visible(win->menu.add_pounce, FALSE);
6571 gtk_widget_hide(win->menu.get_info); 7094 gtk_action_set_visible(win->menu.get_info, FALSE);
6572 gtk_widget_show(win->menu.invite); 7095 gtk_action_set_visible(win->menu.invite, TRUE);
6573 gtk_widget_show(win->menu.alias); 7096 gtk_action_set_visible(win->menu.alias, TRUE);
6574 gtk_widget_hide(win->menu.block); 7097 gtk_action_set_visible(win->menu.block, FALSE);
6575 gtk_widget_hide(win->menu.unblock); 7098 gtk_action_set_visible(win->menu.unblock, FALSE);
6576 7099
6577 if ((account == NULL) || purple_blist_find_chat(account, purple_conversation_get_name(conv)) == NULL) { 7100 if ((account == NULL) || purple_blist_find_chat(account, purple_conversation_get_name(conv)) == NULL) {
6578 /* If the chat is NOT in the buddy list */ 7101 /* If the chat is NOT in the buddy list */
6579 gtk_widget_show(win->menu.add); 7102 gtk_action_set_visible(win->menu.add, TRUE);
6580 gtk_widget_hide(win->menu.remove); 7103 gtk_action_set_visible(win->menu.remove, FALSE);
6581 } else { 7104 } else {
6582 /* If the chat IS in the buddy list */ 7105 /* If the chat IS in the buddy list */
6583 gtk_widget_hide(win->menu.add); 7106 gtk_action_set_visible(win->menu.add, FALSE);
6584 gtk_widget_show(win->menu.remove); 7107 gtk_action_set_visible(win->menu.remove, TRUE);
6585 } 7108 }
6586 7109
6587 gtk_widget_show(win->menu.insert_link); 7110 gtk_action_set_visible(win->menu.insert_link, TRUE);
6588 gtk_widget_show(win->menu.insert_image); 7111 gtk_action_set_visible(win->menu.insert_image, TRUE);
6589 } 7112 }
6590 7113
6591 /* 7114 /*
6592 * Handle graying stuff out based on whether an account is connected 7115 * Handle graying stuff out based on whether an account is connected
6593 * and what features that account supports. 7116 * and what features that account supports.
6594 */ 7117 */
6595 if ((gc != NULL) && 7118 if ((gc != NULL) &&
6596 ((purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) || 7119 ((purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) ||
6597 !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) )) 7120 !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) ))
6598 { 7121 {
7122 PurpleConnectionFlags features = purple_conversation_get_features(conv);
6599 /* Account is online */ 7123 /* Account is online */
6600 /* Deal with the toolbar */ 7124 /* Deal with the toolbar */
6601 if (conv->features & PURPLE_CONNECTION_HTML) 7125 if (features & PURPLE_CONNECTION_HTML)
6602 { 7126 {
6603 buttons = GTK_IMHTML_ALL; /* Everything on */ 7127 buttons = GTK_IMHTML_ALL; /* Everything on */
6604 if (conv->features & PURPLE_CONNECTION_NO_BGCOLOR) 7128 if (features & PURPLE_CONNECTION_NO_BGCOLOR)
6605 buttons &= ~GTK_IMHTML_BACKCOLOR; 7129 buttons &= ~GTK_IMHTML_BACKCOLOR;
6606 if (conv->features & PURPLE_CONNECTION_NO_FONTSIZE) 7130 if (features & PURPLE_CONNECTION_NO_FONTSIZE)
6607 { 7131 {
6608 buttons &= ~GTK_IMHTML_GROW; 7132 buttons &= ~GTK_IMHTML_GROW;
6609 buttons &= ~GTK_IMHTML_SHRINK; 7133 buttons &= ~GTK_IMHTML_SHRINK;
6610 } 7134 }
6611 if (conv->features & PURPLE_CONNECTION_NO_URLDESC) 7135 if (features & PURPLE_CONNECTION_NO_URLDESC)
6612 buttons &= ~GTK_IMHTML_LINKDESC; 7136 buttons &= ~GTK_IMHTML_LINKDESC;
6613 } else { 7137 } else {
6614 buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE; 7138 buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE;
6615 } 7139 }
6616 7140
6617 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)) 7141 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)
6618 conv->features |= PURPLE_CONNECTION_NO_IMAGES; 7142 && !(features & PURPLE_CONNECTION_NO_IMAGES)) {
6619 7143 features |= PURPLE_CONNECTION_NO_IMAGES;
6620 if(conv->features & PURPLE_CONNECTION_NO_IMAGES) 7144 purple_conversation_set_features(conv, features);
7145 }
7146
7147 if (features & PURPLE_CONNECTION_NO_IMAGES)
6621 buttons &= ~GTK_IMHTML_IMAGE; 7148 buttons &= ~GTK_IMHTML_IMAGE;
6622 7149
6623 if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) 7150 if (features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
6624 buttons |= GTK_IMHTML_CUSTOM_SMILEY; 7151 buttons |= GTK_IMHTML_CUSTOM_SMILEY;
6625 else 7152 else
6626 buttons &= ~GTK_IMHTML_CUSTOM_SMILEY; 7153 buttons &= ~GTK_IMHTML_CUSTOM_SMILEY;
6627 7154
6628 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons); 7155 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons);
6629 if (account != NULL) 7156 if (account != NULL)
6630 gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(gtkconv->toolbar), purple_account_get_protocol_id(account)); 7157 gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(gtkconv->toolbar), purple_account_get_protocol_id(account));
6631 7158
6632 /* Deal with menu items */ 7159 /* Deal with menu items */
6633 gtk_widget_set_sensitive(win->menu.view_log, TRUE); 7160 gtk_action_set_sensitive(win->menu.view_log, TRUE);
6634 gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); 7161 gtk_action_set_sensitive(win->menu.add_pounce, TRUE);
6635 gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); 7162 gtk_action_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL));
6636 gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); 7163 gtk_action_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL));
6637 gtk_widget_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML)); 7164 gtk_action_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_HTML));
6638 gtk_widget_set_sensitive(win->menu.insert_image, !(conv->features & PURPLE_CONNECTION_NO_IMAGES)); 7165 gtk_action_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_NO_IMAGES));
6639 7166
6640 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) 7167 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
6641 { 7168 {
6642 gtk_widget_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL) || (prpl_info->add_buddy_with_invite != NULL)); 7169 gtk_action_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL));
6643 gtk_widget_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); 7170 gtk_action_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL));
6644 gtk_widget_set_sensitive(win->menu.send_file, 7171 gtk_action_set_sensitive(win->menu.send_file,
6645 (prpl_info->send_file != NULL && (!prpl_info->can_receive_file || 7172 (prpl_info->send_file != NULL && (!prpl_info->can_receive_file ||
6646 prpl_info->can_receive_file(gc, purple_conversation_get_name(conv))))); 7173 prpl_info->can_receive_file(gc, purple_conversation_get_name(conv)))));
6647 gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(win->window), "get_attention"), (prpl_info->send_attention != NULL)); 7174 gtk_action_set_sensitive(win->menu.get_attention, (prpl_info->send_attention != NULL));
6648 gtk_widget_set_sensitive(win->menu.alias, 7175 gtk_action_set_sensitive(win->menu.alias,
6649 (account != NULL) && 7176 (account != NULL) &&
6650 (purple_find_buddy(account, purple_conversation_get_name(conv)) != NULL)); 7177 (purple_find_buddy(account, purple_conversation_get_name(conv)) != NULL));
6651 } 7178 }
6652 else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) 7179 else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)
6653 { 7180 {
6654 gtk_widget_set_sensitive(win->menu.add, (prpl_info->join_chat != NULL)); 7181 gtk_action_set_sensitive(win->menu.add, (prpl_info->join_chat != NULL));
6655 gtk_widget_set_sensitive(win->menu.remove, (prpl_info->join_chat != NULL)); 7182 gtk_action_set_sensitive(win->menu.remove, (prpl_info->join_chat != NULL));
6656 gtk_widget_set_sensitive(win->menu.alias, 7183 gtk_action_set_sensitive(win->menu.alias,
6657 (account != NULL) && 7184 (account != NULL) &&
6658 (purple_blist_find_chat(account, purple_conversation_get_name(conv)) != NULL)); 7185 (purple_blist_find_chat(account, purple_conversation_get_name(conv)) != NULL));
6659 } 7186 }
6660 7187
6661 } else { 7188 } else {
6662 /* Account is offline */ 7189 /* Account is offline */
6663 /* Or it's a chat that we've left. */ 7190 /* Or it's a chat that we've left. */
6664 7191
6665 /* Then deal with menu items */ 7192 /* Then deal with menu items */
6666 gtk_widget_set_sensitive(win->menu.view_log, TRUE); 7193 gtk_action_set_sensitive(win->menu.view_log, TRUE);
6667 gtk_widget_set_sensitive(win->menu.send_file, FALSE); 7194 gtk_action_set_sensitive(win->menu.send_file, FALSE);
6668 gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(win->window), 7195 gtk_action_set_sensitive(win->menu.get_attention, FALSE);
6669 "get_attention"), FALSE); 7196 gtk_action_set_sensitive(win->menu.add_pounce, TRUE);
6670 gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); 7197 gtk_action_set_sensitive(win->menu.get_info, FALSE);
6671 gtk_widget_set_sensitive(win->menu.get_info, FALSE); 7198 gtk_action_set_sensitive(win->menu.invite, FALSE);
6672 gtk_widget_set_sensitive(win->menu.invite, FALSE); 7199 gtk_action_set_sensitive(win->menu.alias, FALSE);
6673 gtk_widget_set_sensitive(win->menu.alias, FALSE); 7200 gtk_action_set_sensitive(win->menu.add, FALSE);
6674 gtk_widget_set_sensitive(win->menu.add, FALSE); 7201 gtk_action_set_sensitive(win->menu.remove, FALSE);
6675 gtk_widget_set_sensitive(win->menu.remove, FALSE); 7202 gtk_action_set_sensitive(win->menu.insert_link, TRUE);
6676 gtk_widget_set_sensitive(win->menu.insert_link, TRUE); 7203 gtk_action_set_sensitive(win->menu.insert_image, FALSE);
6677 gtk_widget_set_sensitive(win->menu.insert_image, FALSE);
6678 } 7204 }
6679 7205
6680 /* 7206 /*
6681 * Update the window's icon 7207 * Update the window's icon
6682 */ 7208 */
6684 { 7210 {
6685 GList *l = NULL; 7211 GList *l = NULL;
6686 if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && 7212 if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) &&
6687 (gtkconv->u.im->anim)) 7213 (gtkconv->u.im->anim))
6688 { 7214 {
6689 PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); 7215 PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
6690 window_icon = 7216 window_icon =
6691 gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); 7217 gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim);
6692 7218
6693 if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy)) 7219 if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy))
6694 gdk_pixbuf_saturate_and_pixelate(window_icon, window_icon, 0.0, FALSE); 7220 gdk_pixbuf_saturate_and_pixelate(window_icon, window_icon, 0.0, FALSE);
6732 7258
6733 if (fields & PIDGIN_CONV_MENU) 7259 if (fields & PIDGIN_CONV_MENU)
6734 { 7260 {
6735 gray_stuff_out(PIDGIN_CONVERSATION(conv)); 7261 gray_stuff_out(PIDGIN_CONVERSATION(conv));
6736 generate_send_to_items(win); 7262 generate_send_to_items(win);
7263 regenerate_plugins_items(win);
6737 } 7264 }
6738 7265
6739 if (fields & PIDGIN_CONV_TAB_ICON) 7266 if (fields & PIDGIN_CONV_TAB_ICON)
6740 { 7267 {
6741 update_tab_icon(conv); 7268 update_tab_icon(conv);
6752 if (gtkchat->topic_text != NULL) 7279 if (gtkchat->topic_text != NULL)
6753 { 7280 {
6754 topic = purple_conv_chat_get_topic(chat); 7281 topic = purple_conv_chat_get_topic(chat);
6755 7282
6756 gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), topic ? topic : ""); 7283 gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), topic ? topic : "");
7284 #if GTK_CHECK_VERSION(2,12,0)
7285 gtk_widget_set_tooltip_text(gtkchat->topic_text,
7286 topic ? topic : "");
7287 #else
6757 gtk_tooltips_set_tip(gtkconv->tooltips, gtkchat->topic_text, 7288 gtk_tooltips_set_tip(gtkconv->tooltips, gtkchat->topic_text,
6758 topic ? topic : "", NULL); 7289 topic ? topic : "", NULL);
6759 } 7290 #endif
6760 } 7291 }
6761 7292 }
7293
7294 #if 0
6762 if (fields & PIDGIN_CONV_SMILEY_THEME) 7295 if (fields & PIDGIN_CONV_SMILEY_THEME)
6763 pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->imhtml); 7296 pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->webview);
7297 #endif
6764 7298
6765 if ((fields & PIDGIN_CONV_COLORIZE_TITLE) || 7299 if ((fields & PIDGIN_CONV_COLORIZE_TITLE) ||
6766 (fields & PIDGIN_CONV_SET_TITLE) || 7300 (fields & PIDGIN_CONV_SET_TITLE) ||
6767 (fields & PIDGIN_CONV_TOPIC)) 7301 (fields & PIDGIN_CONV_TOPIC))
6768 { 7302 {
6785 title = g_strdup_printf("(%s)", purple_conversation_get_title(conv)); 7319 title = g_strdup_printf("(%s)", purple_conversation_get_title(conv));
6786 else 7320 else
6787 title = g_strdup(purple_conversation_get_title(conv)); 7321 title = g_strdup(purple_conversation_get_title(conv));
6788 7322
6789 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 7323 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
6790 buddy = purple_find_buddy(account, conv->name); 7324 buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
6791 if (buddy) { 7325 if (buddy) {
6792 markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE); 7326 markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE);
6793 } else { 7327 } else {
6794 markup = title; 7328 markup = title;
6795 } 7329 }
6813 gtk_widget_queue_draw(gtkconv->infopane); 7347 gtk_widget_queue_draw(gtkconv->infopane);
6814 7348
6815 if (title != markup) 7349 if (title != markup)
6816 g_free(markup); 7350 g_free(markup);
6817 7351
6818 if (!GTK_WIDGET_REALIZED(gtkconv->tab_label)) 7352 if (!gtk_widget_get_realized(gtkconv->tab_label))
6819 gtk_widget_realize(gtkconv->tab_label); 7353 gtk_widget_realize(gtkconv->tab_label);
6820 7354
6821 accessibility_obj = gtk_widget_get_accessible(gtkconv->tab_cont); 7355 accessibility_obj = gtk_widget_get_accessible(gtkconv->tab_cont);
6822 if (im != NULL && 7356 if (im != NULL &&
6823 purple_conv_im_get_typing_state(im) == PURPLE_TYPING) { 7357 purple_conv_im_get_typing_state(im) == PURPLE_TYPING) {
6830 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) { 7364 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) {
6831 atk_object_set_description(accessibility_obj, _("Nick Said")); 7365 atk_object_set_description(accessibility_obj, _("Nick Said"));
6832 style = "tab-label-attention"; 7366 style = "tab-label-attention";
6833 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) { 7367 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) {
6834 atk_object_set_description(accessibility_obj, _("Unread Messages")); 7368 atk_object_set_description(accessibility_obj, _("Unread Messages"));
6835 if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_CHAT) 7369 if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT)
6836 style = "tab-label-unreadchat"; 7370 style = "tab-label-unreadchat";
6837 else 7371 else
6838 style = "tab-label-attention"; 7372 style = "tab-label-attention";
6839 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) { 7373 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) {
6840 atk_object_set_description(accessibility_obj, _("New Event")); 7374 atk_object_set_description(accessibility_obj, _("New Event"));
7042 gtkconv->u.im->iter = NULL; 7576 gtkconv->u.im->iter = NULL;
7043 7577
7044 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons")) 7578 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons"))
7045 return; 7579 return;
7046 7580
7047 if (purple_conversation_get_gc(conv) == NULL) 7581 if (purple_conversation_get_connection(conv) == NULL)
7048 return; 7582 return;
7049 7583
7050 buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); 7584 buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
7051 if (buddy) 7585 if (buddy)
7052 { 7586 {
7207 7741
7208 page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i); 7742 page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i);
7209 tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page); 7743 tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);
7210 7744
7211 /* Make sure the tab is not hidden beyond an arrow */ 7745 /* Make sure the tab is not hidden beyond an arrow */
7212 if (!GTK_WIDGET_DRAWABLE(tab) && gtk_notebook_get_show_tabs(notebook)) 7746 if (!gtk_widget_is_drawable(tab) && gtk_notebook_get_show_tabs(notebook))
7213 continue; 7747 continue;
7214 7748
7215 if (horiz) { 7749 if (horiz) {
7216 if (x_rel >= tab->allocation.x - PIDGIN_HIG_BOX_SPACE && 7750 if (x_rel >= tab->allocation.x - PIDGIN_HIG_BOX_SPACE &&
7217 x_rel <= tab->allocation.x + tab->allocation.width + PIDGIN_HIG_BOX_SPACE) { 7751 x_rel <= tab->allocation.x + tab->allocation.width + PIDGIN_HIG_BOX_SPACE) {
7314 } 7848 }
7315 } 7849 }
7316 } 7850 }
7317 7851
7318 static void 7852 static void
7319 show_timestamps_pref_cb(const char *name, PurplePrefType type, 7853 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type,
7320 gconstpointer value, gpointer data) 7854 gconstpointer value, gpointer data)
7321 { 7855 {
7322 GList *l; 7856 GList *l;
7323 PurpleConversation *conv; 7857 PurpleConversation *conv;
7324 PidginConversation *gtkconv; 7858 PidginConversation *gtkconv;
7325 PidginWindow *win; 7859 PidginWindow *win;
7332 continue; 7866 continue;
7333 7867
7334 gtkconv = PIDGIN_CONVERSATION(conv); 7868 gtkconv = PIDGIN_CONVERSATION(conv);
7335 win = gtkconv->win; 7869 win = gtkconv->win;
7336 7870
7337 gtk_check_menu_item_set_active( 7871 gtk_toggle_action_set_active(
7338 GTK_CHECK_MENU_ITEM(win->menu.show_timestamps), 7872 GTK_TOGGLE_ACTION(win->menu.show_formatting_toolbar),
7339 (gboolean)GPOINTER_TO_INT(value));
7340
7341 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),
7342 (gboolean)GPOINTER_TO_INT(value));
7343 }
7344 }
7345
7346 static void
7347 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type,
7348 gconstpointer value, gpointer data)
7349 {
7350 GList *l;
7351 PurpleConversation *conv;
7352 PidginConversation *gtkconv;
7353 PidginWindow *win;
7354
7355 for (l = purple_get_conversations(); l != NULL; l = l->next)
7356 {
7357 conv = (PurpleConversation *)l->data;
7358
7359 if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv))
7360 continue;
7361
7362 gtkconv = PIDGIN_CONVERSATION(conv);
7363 win = gtkconv->win;
7364
7365 gtk_check_menu_item_set_active(
7366 GTK_CHECK_MENU_ITEM(win->menu.show_formatting_toolbar),
7367 (gboolean)GPOINTER_TO_INT(value)); 7873 (gboolean)GPOINTER_TO_INT(value));
7368 7874
7369 if ((gboolean)GPOINTER_TO_INT(value)) 7875 if ((gboolean)GPOINTER_TO_INT(value))
7370 gtk_widget_show(gtkconv->toolbar); 7876 gtk_widget_show(gtkconv->toolbar);
7371 else 7877 else
7505 gtkconv = l->data; 8011 gtkconv = l->data;
7506 l = l->next; 8012 l = l->next;
7507 8013
7508 conv = gtkconv->active_conv; 8014 conv = gtkconv->active_conv;
7509 8015
7510 if (conv->type == PURPLE_CONV_TYPE_CHAT || 8016 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT ||
7511 gtkconv->unseen_count == 0 || 8017 gtkconv->unseen_count == 0 ||
7512 (when_away && !purple_status_is_available( 8018 (when_away && !purple_status_is_available(
7513 purple_account_get_active_status( 8019 purple_account_get_active_status(
7514 purple_conversation_get_account(conv))))) 8020 purple_conversation_get_account(conv)))))
7515 continue; 8021 continue;
7545 8051
7546 for (; node; node = node->next) 8052 for (; node; node = node->next)
7547 { 8053 {
7548 PurpleBuddy *buddy = (PurpleBuddy*)node; 8054 PurpleBuddy *buddy = (PurpleBuddy*)node;
7549 PurpleConversation *conv; 8055 PurpleConversation *conv;
7550 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); 8056 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
7551 if (conv) 8057 if (conv)
7552 return PIDGIN_CONVERSATION(conv); 8058 return PIDGIN_CONVERSATION(conv);
7553 } 8059 }
7554 return NULL; 8060 return NULL;
7555 } 8061 }
7570 /* if (purple_conversation_get_account(conv) == account) */ 8076 /* if (purple_conversation_get_account(conv) == account) */
7571 pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON | 8077 pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON |
7572 PIDGIN_CONV_MENU | PIDGIN_CONV_COLORIZE_TITLE); 8078 PIDGIN_CONV_MENU | PIDGIN_CONV_COLORIZE_TITLE);
7573 8079
7574 if (PURPLE_CONNECTION_IS_CONNECTED(gc) && 8080 if (PURPLE_CONNECTION_IS_CONNECTED(gc) &&
7575 conv->type == PURPLE_CONV_TYPE_CHAT && 8081 purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT &&
7576 conv->account == gc->account && 8082 purple_conversation_get_account(conv) == purple_connection_get_account(gc) &&
7577 purple_conversation_get_data(conv, "want-to-rejoin")) { 8083 purple_conversation_get_data(conv, "want-to-rejoin")) {
7578 GHashTable *comps = NULL; 8084 GHashTable *comps = NULL;
7579 PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); 8085 PurpleChat *chat = purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
7580 if (chat == NULL) { 8086 if (chat == NULL) {
7581 if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) 8087 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
7582 comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, conv->name); 8088
8089 if (prpl_info->chat_info_defaults != NULL)
8090 comps = prpl_info->chat_info_defaults(gc, purple_conversation_get_name(conv));
7583 } else { 8091 } else {
7584 comps = chat->components; 8092 comps = purple_chat_get_components(chat);
7585 } 8093 }
7586 serv_join_chat(gc, comps); 8094 serv_join_chat(gc, comps);
7587 if (chat == NULL && comps != NULL) 8095 if (chat == NULL && comps != NULL)
7588 g_hash_table_destroy(comps); 8096 g_hash_table_destroy(comps);
7589 } 8097 }
7646 static void 8154 static void
7647 update_buddy_idle_changed(PurpleBuddy *buddy, gboolean old, gboolean newidle) 8155 update_buddy_idle_changed(PurpleBuddy *buddy, gboolean old, gboolean newidle)
7648 { 8156 {
7649 PurpleConversation *conv; 8157 PurpleConversation *conv;
7650 8158
7651 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); 8159 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
7652 if (conv) 8160 if (conv)
7653 pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON); 8161 pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON);
7654 } 8162 }
7655 8163
7656 static void 8164 static void
7657 update_buddy_icon(PurpleBuddy *buddy) 8165 update_buddy_icon(PurpleBuddy *buddy)
7658 { 8166 {
7659 PurpleConversation *conv; 8167 PurpleConversation *conv;
7660 8168
7661 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); 8169 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
7662 if (conv) 8170 if (conv)
7663 pidgin_conv_update_fields(conv, PIDGIN_CONV_BUDDY_ICON); 8171 pidgin_conv_update_fields(conv, PIDGIN_CONV_BUDDY_ICON);
7664 } 8172 }
7665 8173
7666 static void 8174 static void
7721 /* Compare two PurpleConvMessage's, according to time in ascending order. */ 8229 /* Compare two PurpleConvMessage's, according to time in ascending order. */
7722 static int 8230 static int
7723 message_compare(gconstpointer p1, gconstpointer p2) 8231 message_compare(gconstpointer p1, gconstpointer p2)
7724 { 8232 {
7725 const PurpleConvMessage *m1 = p1, *m2 = p2; 8233 const PurpleConvMessage *m1 = p1, *m2 = p2;
7726 return (m1->when > m2->when); 8234 return (purple_conversation_message_get_timestamp(m1) > purple_conversation_message_get_timestamp(m2));
7727 } 8235 }
7728 8236
7729 /* Adds some message history to the gtkconv. This happens in a idle-callback. */ 8237 /* Adds some message history to the gtkconv. This happens in a idle-callback. */
7730 static gboolean 8238 static gboolean
7731 add_message_history_to_gtkconv(gpointer data) 8239 add_message_history_to_gtkconv(gpointer data)
7732 { 8240 {
7733 PidginConversation *gtkconv = data; 8241 PidginConversation *gtkconv = data;
8242 GtkWebView *webview = GTK_WEBVIEW(gtkconv->webview);
7734 int count = 0; 8243 int count = 0;
7735 int timer = gtkconv->attach.timer; 8244 int timer = gtkconv->attach.timer;
7736 time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time")); 8245 time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time"));
7737 gboolean im = (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM); 8246 gboolean im = (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM);
7738 8247
7739 gtkconv->attach.timer = 0; 8248 gtkconv->attach.timer = 0;
7740 while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */ 8249 while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */
7741 PurpleConvMessage *msg = gtkconv->attach.current->data; 8250 PurpleConvMessage *msg = gtkconv->attach.current->data;
7742 if (!im && when && when < msg->when) { 8251 if (!im && when && when < purple_conversation_message_get_timestamp(msg)) {
7743 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0); 8252 gtk_webview_append_html(webview, "<BR><HR>");
8253 gtk_webview_scroll_to_end(webview, TRUE);
7744 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); 8254 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
7745 } 8255 }
7746 pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when); 8256 pidgin_conv_write_conv(
8257 purple_conversation_message_get_conv(msg),
8258 purple_conversation_message_get_sender(msg),
8259 purple_conversation_message_get_alias(msg),
8260 purple_conversation_message_get_message(msg),
8261 purple_conversation_message_get_flags(msg),
8262 purple_conversation_message_get_timestamp(msg));
7747 if (im) { 8263 if (im) {
7748 gtkconv->attach.current = g_list_delete_link(gtkconv->attach.current, gtkconv->attach.current); 8264 gtkconv->attach.current = g_list_delete_link(gtkconv->attach.current, gtkconv->attach.current);
7749 } else { 8265 } else {
7750 gtkconv->attach.current = gtkconv->attach.current->prev; 8266 gtkconv->attach.current = gtkconv->attach.current->prev;
7751 } 8267 }
7764 for (; iter; iter = iter->next) { 8280 for (; iter; iter = iter->next) {
7765 PurpleConversation *conv = iter->data; 8281 PurpleConversation *conv = iter->data;
7766 GList *history = purple_conversation_get_message_history(conv); 8282 GList *history = purple_conversation_get_message_history(conv);
7767 for (; history; history = history->next) { 8283 for (; history; history = history->next) {
7768 PurpleConvMessage *msg = history->data; 8284 PurpleConvMessage *msg = history->data;
7769 if (msg->when > when) 8285 if (purple_conversation_message_get_timestamp(msg) > when)
7770 msgs = g_list_prepend(msgs, msg); 8286 msgs = g_list_prepend(msgs, msg);
7771 } 8287 }
7772 } 8288 }
7773 msgs = g_list_sort(msgs, message_compare); 8289 msgs = g_list_sort(msgs, message_compare);
7774 for (; msgs; msgs = g_list_delete_link(msgs, msgs)) { 8290 for (; msgs; msgs = g_list_delete_link(msgs, msgs)) {
7775 PurpleConvMessage *msg = msgs->data; 8291 PurpleConvMessage *msg = msgs->data;
7776 pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when); 8292 pidgin_conv_write_conv(
7777 } 8293 purple_conversation_message_get_conv(msg),
7778 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0); 8294 purple_conversation_message_get_sender(msg),
8295 purple_conversation_message_get_alias(msg),
8296 purple_conversation_message_get_message(msg),
8297 purple_conversation_message_get_flags(msg),
8298 purple_conversation_message_get_timestamp(msg));
8299 }
8300 gtk_webview_append_html(webview, "<BR><HR>");
8301 gtk_webview_scroll_to_end(webview, TRUE);
7779 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); 8302 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
7780 } 8303 }
7781 8304
7782 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); 8305 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
7783 purple_signal_emit(pidgin_conversations_get_handle(), 8306 purple_signal_emit(pidgin_conversations_get_handle(),
7849 break; 8372 break;
7850 default: 8373 default:
7851 g_return_val_if_reached(TRUE); 8374 g_return_val_if_reached(TRUE);
7852 } 8375 }
7853 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", 8376 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time",
7854 GINT_TO_POINTER(((PurpleConvMessage*)(list->data))->when)); 8377 GINT_TO_POINTER(purple_conversation_message_get_timestamp((PurpleConvMessage*)(list->data))));
7855 gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv); 8378 gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv);
7856 } else { 8379 } else {
7857 purple_signal_emit(pidgin_conversations_get_handle(), 8380 purple_signal_emit(pidgin_conversations_get_handle(),
7858 "conversation-displayed", gtkconv); 8381 "conversation-displayed", gtkconv);
7859 } 8382 }
7860 8383
7861 if (conv->type == PURPLE_CONV_TYPE_CHAT) { 8384 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
7862 pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); 8385 pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC);
7863 pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE); 8386 pidgin_conv_chat_add_users(conv, purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)), TRUE);
7864 } 8387 }
7865 8388
7866 return TRUE; 8389 return TRUE;
8390 }
8391
8392 PurpleTheme *
8393 pidgin_conversations_get_default_theme(void)
8394 {
8395 return default_conv_theme;
7867 } 8396 }
7868 8397
7869 void * 8398 void *
7870 pidgin_conversations_get_handle(void) 8399 pidgin_conversations_get_handle(void)
7871 { 8400 {
7877 void 8406 void
7878 pidgin_conversations_init(void) 8407 pidgin_conversations_init(void)
7879 { 8408 {
7880 void *handle = pidgin_conversations_get_handle(); 8409 void *handle = pidgin_conversations_get_handle();
7881 void *blist_handle = purple_blist_get_handle(); 8410 void *blist_handle = purple_blist_get_handle();
8411 char *theme_dir;
7882 8412
7883 /* Conversations */ 8413 /* Conversations */
7884 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations"); 8414 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations");
8415 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/themes");
7885 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", TRUE); 8416 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", TRUE);
7886 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", TRUE); 8417 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", TRUE);
7887 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE); 8418 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE);
7888 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", FALSE); 8419 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", FALSE);
7889 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE); 8420 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE);
8421 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_strike", FALSE);
7890 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/spellcheck", TRUE); 8422 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/spellcheck", TRUE);
7891 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting", TRUE); 8423 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting", TRUE);
7892 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/resize_custom_smileys", TRUE); 8424 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/resize_custom_smileys", TRUE);
7893 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/custom_smileys_size", 96); 8425 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/custom_smileys_size", 96);
7894 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines", 2); 8426 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines", 2);
7895 8427
7896 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps", TRUE);
7897 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar", TRUE); 8428 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar", TRUE);
7898 8429
7899 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/placement", "last"); 8430 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/placement", "last");
7900 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/placement_number", 1); 8431 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/placement_number", 1);
7901 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor", ""); 8432 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor", "");
7940 #endif 8471 #endif
7941 8472
7942 /* Connect callbacks. */ 8473 /* Connect callbacks. */
7943 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", 8474 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/close_on_tabs",
7944 close_on_tabs_pref_cb, NULL); 8475 close_on_tabs_pref_cb, NULL);
7945 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/show_timestamps",
7946 show_timestamps_pref_cb, NULL);
7947 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar", 8476 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar",
7948 show_formatting_toolbar_pref_cb, NULL); 8477 show_formatting_toolbar_pref_cb, NULL);
7949 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/spellcheck", 8478 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/spellcheck",
7950 spellcheck_pref_cb, NULL); 8479 spellcheck_pref_cb, NULL);
7951 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/tab_side", 8480 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/tab_side",
8163 purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", handle, 8692 purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", handle,
8164 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); 8693 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL);
8165 purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle, 8694 purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle,
8166 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); 8695 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL);
8167 8696
8697 purple_theme_manager_register_type(g_object_new(PIDGIN_TYPE_CONV_THEME_LOADER, "type", "conversation", NULL));
8698 theme_dir = g_build_filename(DATADIR, "pidgin", "theme", NULL);
8699 default_conv_theme = purple_theme_manager_load_theme(theme_dir, "conversation");
8700 g_free(theme_dir);
8701
8168 { 8702 {
8169 /* Set default tab colors */ 8703 /* Set default tab colors */
8170 GString *str = g_string_new(NULL); 8704 GString *str = g_string_new(NULL);
8171 GtkSettings *settings = gtk_settings_get_default(); 8705 GtkSettings *settings = gtk_settings_get_default();
8172 GtkStyle *parent = gtk_rc_get_style_by_paths(settings, "tab-container.tab-label*", NULL, G_TYPE_NONE), *now; 8706 GtkStyle *parent = gtk_rc_get_style_by_paths(settings, "tab-container.tab-label*", NULL, G_TYPE_NONE), *now;
8308 GTK_RESPONSE_OK); 8842 GTK_RESPONSE_OK);
8309 8843
8310 gtk_container_set_border_width(GTK_CONTAINER(warn_close_dialog), 8844 gtk_container_set_border_width(GTK_CONTAINER(warn_close_dialog),
8311 6); 8845 6);
8312 gtk_window_set_resizable(GTK_WINDOW(warn_close_dialog), FALSE); 8846 gtk_window_set_resizable(GTK_WINDOW(warn_close_dialog), FALSE);
8313 gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), 8847 #if !GTK_CHECK_VERSION(2,22,0)
8314 FALSE); 8848 gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), FALSE);
8849 #endif
8315 8850
8316 /* Setup the outside spacing. */ 8851 /* Setup the outside spacing. */
8317 vbox = GTK_DIALOG(warn_close_dialog)->vbox; 8852 vbox = GTK_DIALOG(warn_close_dialog)->vbox;
8318 8853
8319 gtk_box_set_spacing(GTK_BOX(vbox), 12); 8854 gtk_box_set_spacing(GTK_BOX(vbox), 12);
8611 9146
8612 if (e->button == 3) { 9147 if (e->button == 3) {
8613 /* Right click was pressed. Popup the context menu. */ 9148 /* Right click was pressed. Popup the context menu. */
8614 GtkWidget *menu = gtk_menu_new(), *sub; 9149 GtkWidget *menu = gtk_menu_new(), *sub;
8615 gboolean populated = populate_menu_with_options(menu, gtkconv, TRUE); 9150 gboolean populated = populate_menu_with_options(menu, gtkconv, TRUE);
9151
8616 sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to)); 9152 sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to));
8617 9153 if (sub && gtk_widget_is_sensitive(gtkconv->win->menu.send_to)) {
8618 if (sub && GTK_WIDGET_IS_SENSITIVE(gtkconv->win->menu.send_to)) {
8619 GtkWidget *item = gtk_menu_item_new_with_mnemonic(_("S_end To")); 9154 GtkWidget *item = gtk_menu_item_new_with_mnemonic(_("S_end To"));
8620 if (populated) 9155 if (populated)
8621 pidgin_separator(menu); 9156 pidgin_separator(menu);
8622 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 9157 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
8623 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), sub); 9158 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), sub);
9046 { 9581 {
9047 GtkWidget *entry = NULL; 9582 GtkWidget *entry = NULL;
9048 PurpleConversation *conv = gtkconv->active_conv; 9583 PurpleConversation *conv = gtkconv->active_conv;
9049 const char *text = NULL; 9584 const char *text = NULL;
9050 9585
9051 if (!GTK_WIDGET_VISIBLE(gtkconv->infopane)) { 9586 if (!gtk_widget_get_visible(gtkconv->infopane)) {
9052 /* There's already an entry for alias. Let's not create another one. */ 9587 /* There's already an entry for alias. Let's not create another one. */
9053 return FALSE; 9588 return FALSE;
9054 } 9589 }
9055 9590
9056 if (!purple_account_is_connected(gtkconv->active_conv->account)) { 9591 if (!purple_account_is_connected(purple_conversation_get_account(gtkconv->active_conv))) {
9057 /* Do not allow aliasing someone on a disconnected account. */ 9592 /* Do not allow aliasing someone on a disconnected account. */
9058 return FALSE; 9593 return FALSE;
9059 } 9594 }
9060 9595
9061 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 9596 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
9062 PurpleBuddy *buddy = purple_find_buddy(gtkconv->active_conv->account, gtkconv->active_conv->name); 9597 PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv));
9063 if (!buddy) 9598 if (!buddy)
9064 /* This buddy isn't in your buddy list, so we can't alias him */ 9599 /* This buddy isn't in your buddy list, so we can't alias him */
9065 return FALSE; 9600 return FALSE;
9066 9601
9067 text = purple_buddy_get_contact_alias(buddy); 9602 text = purple_buddy_get_contact_alias(buddy);
9068 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 9603 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
9069 PurpleConnection *gc; 9604 PurpleConnection *gc;
9070 PurplePluginProtocolInfo *prpl_info = NULL; 9605 PurplePluginProtocolInfo *prpl_info = NULL;
9071 9606
9072 gc = purple_conversation_get_gc(conv); 9607 gc = purple_conversation_get_connection(conv);
9073 if (gc != NULL) 9608 if (gc != NULL)
9074 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 9609 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
9075 if (prpl_info && prpl_info->set_chat_topic == NULL) 9610 if (prpl_info && prpl_info->set_chat_topic == NULL)
9076 /* This protocol doesn't support setting the chat room topic */ 9611 /* This protocol doesn't support setting the chat room topic */
9077 return FALSE; 9612 return FALSE;
9078 9613
9079 text = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv)); 9614 text = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv));
9130 gtkconv_set_unseen(gtkconv, PIDGIN_UNSEEN_NONE); 9665 gtkconv_set_unseen(gtkconv, PIDGIN_UNSEEN_NONE);
9131 } 9666 }
9132 9667
9133 /* Update the menubar */ 9668 /* Update the menubar */
9134 9669
9135 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging), 9670 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtkconv->win->menu.logging),
9136 purple_conversation_is_logging(conv)); 9671 purple_conversation_is_logging(conv));
9137 9672
9138 generate_send_to_items(win); 9673 generate_send_to_items(win);
9139 regenerate_options_items(win); 9674 regenerate_options_items(win);
9140 regenerate_plugins_items(win); 9675 regenerate_plugins_items(win);
9141 9676
9142 pidgin_conv_switch_active_conversation(conv); 9677 pidgin_conv_switch_active_conversation(conv);
9143 9678
9144 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); 9679 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method");
9145 if (strcmp(sound_method, "none") != 0) 9680 if (strcmp(sound_method, "none") != 0)
9146 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), 9681 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds),
9147 gtkconv->make_sound); 9682 gtkconv->make_sound);
9148 9683
9149 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_formatting_toolbar), 9684 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.show_formatting_toolbar),
9150 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar")); 9685 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar"));
9151
9152 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_timestamps),
9153 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps"));
9154 9686
9155 /* 9687 /*
9156 * We pause icons when they are not visible. If this icon should 9688 * We pause icons when they are not visible. If this icon should
9157 * be animated then start it back up again. 9689 * be animated then start it back up again.
9158 */ 9690 */
9206 } 9738 }
9207 9739
9208 static gboolean gtk_conv_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) { 9740 static gboolean gtk_conv_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) {
9209 int x, y; 9741 int x, y;
9210 9742
9211 if (GTK_WIDGET_VISIBLE(w)) 9743 if (gtk_widget_get_visible(w))
9212 gtk_window_get_position(GTK_WINDOW(w), &x, &y); 9744 gtk_window_get_position(GTK_WINDOW(w), &x, &y);
9213 else 9745 else
9214 return FALSE; /* carry on normally */ 9746 return FALSE; /* carry on normally */
9215 9747
9216 /* Workaround for GTK+ bug # 169811 - "configure_event" is fired 9748 /* Workaround for GTK+ bug # 169811 - "configure_event" is fired
9241 int conv_width, int conv_height) 9773 int conv_width, int conv_height)
9242 { 9774 {
9243 /* if the window exists, is hidden, we're saving positions, and the 9775 /* if the window exists, is hidden, we're saving positions, and the
9244 * position is sane... */ 9776 * position is sane... */
9245 if (win && win->window && 9777 if (win && win->window &&
9246 !GTK_WIDGET_VISIBLE(win->window) && conv_width != 0) { 9778 !gtk_widget_get_visible(win->window) && conv_width != 0) {
9247 9779
9248 #ifdef _WIN32 /* only override window manager placement on Windows */ 9780 #ifdef _WIN32 /* only override window manager placement on Windows */
9249 /* ...check position is on screen... */ 9781 /* ...check position is on screen... */
9250 if (conv_x >= gdk_screen_width()) 9782 if (conv_x >= gdk_screen_width())
9251 conv_x = gdk_screen_width() - 100; 9783 conv_x = gdk_screen_width() - 100;
9396 } 9928 }
9397 return; 9929 return;
9398 } 9930 }
9399 gtk_widget_destroy(win->window); 9931 gtk_widget_destroy(win->window);
9400 9932
9401 g_object_unref(G_OBJECT(win->menu.item_factory)); 9933 g_object_unref(G_OBJECT(win->menu.ui));
9402 9934
9403 purple_notify_close_with_handle(win); 9935 purple_notify_close_with_handle(win);
9404 purple_signals_disconnect_by_handle(win); 9936 purple_signals_disconnect_by_handle(win);
9405 9937
9406 g_free(win); 9938 g_free(win);
9474 pidgin_conv_tab_pack(win, ((PidginConversation*)win->gtkconvs->data)); 10006 pidgin_conv_tab_pack(win, ((PidginConversation*)win->gtkconvs->data));
9475 10007
9476 10008
9477 /* Close button. */ 10009 /* Close button. */
9478 gtkconv->close = pidgin_create_small_button(gtk_label_new("×")); 10010 gtkconv->close = pidgin_create_small_button(gtk_label_new("×"));
10011 #if GTK_CHECK_VERSION(2,12,0)
10012 gtk_widget_set_tooltip_text(gtkconv->close, _("Close conversation"));
10013 #else
9479 gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close, 10014 gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close,
9480 _("Close conversation"), NULL); 10015 _("Close conversation"), NULL);
10016 #endif
9481 10017
9482 g_signal_connect(gtkconv->close, "clicked", G_CALLBACK (close_conv_cb), gtkconv); 10018 g_signal_connect(gtkconv->close, "clicked", G_CALLBACK (close_conv_cb), gtkconv);
9483 10019
9484 /* Status icon. */ 10020 /* Status icon. */
9485 gtkconv->icon = gtk_image_new(); 10021 gtkconv->icon = gtk_image_new();
9611 10147
9612 /* Reset the tabs label to the new version */ 10148 /* Reset the tabs label to the new version */
9613 gtk_notebook_set_tab_label(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, ebox); 10149 gtk_notebook_set_tab_label(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, ebox);
9614 } 10150 }
9615 10151
9616 gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, 10152 gtk_container_child_set(GTK_CONTAINER(win->notebook), gtkconv->tab_cont,
9617 !tabs_side && !angle, 10153 "tab-expand", !tabs_side && !angle,
9618 TRUE, GTK_PACK_START); 10154 "tab-fill", TRUE, NULL);
9619 10155
9620 if (pidgin_conv_window_get_gtkconv_count(win) == 1) 10156 if (pidgin_conv_window_get_gtkconv_count(win) == 1)
9621 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), 10157 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook),
9622 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs") && 10158 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs") &&
9623 (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") || 10159 (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") ||
9637 { 10173 {
9638 unsigned int index; 10174 unsigned int index;
9639 10175
9640 index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont); 10176 index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont);
9641 10177
9642 g_object_ref(gtkconv->tab_cont); 10178 g_object_ref_sink(G_OBJECT(gtkconv->tab_cont));
9643 gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont));
9644 10179
9645 gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index); 10180 gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index);
9646 10181
9647 win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv); 10182 win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv);
9648 10183
9843 { 10378 {
9844 int x, y; 10379 int x, y;
9845 PurpleConversationType type = purple_conversation_get_type(conv->active_conv); 10380 PurpleConversationType type = purple_conversation_get_type(conv->active_conv);
9846 GList *all; 10381 GList *all;
9847 10382
9848 if (GTK_WIDGET_VISIBLE(w)) 10383 if (gtk_widget_get_visible(w))
9849 gtk_window_get_position(GTK_WINDOW(w), &x, &y); 10384 gtk_window_get_position(GTK_WINDOW(w), &x, &y);
9850 else 10385 else
9851 return FALSE; /* carry on normally */ 10386 return FALSE; /* carry on normally */
9852 10387
9853 /* Workaround for GTK+ bug # 169811 - "configure_event" is fired 10388 /* Workaround for GTK+ bug # 169811 - "configure_event" is fired