comparison pidgin/gtkconv.c @ 32672:3828a61c44da

A boring and large patch so I can merge heads.
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Fri, 23 Dec 2011 08:21:58 +0000
parents e2a1510da13d
children
comparison
equal deleted inserted replaced
32671:0e69949b3e61 32672:3828a61c44da
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
173 static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y); 221 static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y);
174 222
175 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) 223 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name)
176 { 224 {
177 static GdkColor col; 225 static GdkColor col;
178 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); 226 GtkStyle *style = gtk_widget_get_style(gtkconv->webview);
179 float scale; 227 float scale;
180 228
181 col = nick_colors[g_str_hash(name) % nbr_nick_colors]; 229 col = nick_colors[g_str_hash(name) % nbr_nick_colors];
182 scale = ((1-(LUMINANCE(style->base[GTK_STATE_NORMAL]) / LUMINANCE(style->white))) * 230 scale = ((1-(LUMINANCE(style->base[GTK_STATE_NORMAL]) / LUMINANCE(style->white))) *
183 (LUMINANCE(style->white)/MAX(MAX(col.red, col.blue), col.green))); 231 (LUMINANCE(style->white)/MAX(MAX(col.red, col.blue), col.green)));
193 } 241 }
194 242
195 static PurpleBlistNode * 243 static PurpleBlistNode *
196 get_conversation_blist_node(PurpleConversation *conv) 244 get_conversation_blist_node(PurpleConversation *conv)
197 { 245 {
246 PurpleAccount *account = purple_conversation_get_account(conv);
198 PurpleBlistNode *node = NULL; 247 PurpleBlistNode *node = NULL;
199 248
200 switch (purple_conversation_get_type(conv)) { 249 switch (purple_conversation_get_type(conv)) {
201 case PURPLE_CONV_TYPE_IM: 250 case PURPLE_CONV_TYPE_IM:
202 node = PURPLE_BLIST_NODE(purple_find_buddy(conv->account, conv->name)); 251 node = PURPLE_BLIST_NODE(purple_find_buddy(account, purple_conversation_get_name(conv)));
203 node = node ? node->parent : NULL; 252 node = node ? node->parent : NULL;
204 break; 253 break;
205 case PURPLE_CONV_TYPE_CHAT: 254 case PURPLE_CONV_TYPE_CHAT:
206 node = PURPLE_BLIST_NODE(purple_blist_find_chat(conv->account, conv->name)); 255 node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, purple_conversation_get_name(conv)));
207 break; 256 break;
208 default: 257 default:
209 break; 258 break;
210 } 259 }
211 return node; 260 return node;
273 322
274 static void 323 static void
275 default_formatize(PidginConversation *c) 324 default_formatize(PidginConversation *c)
276 { 325 {
277 PurpleConversation *conv = c->active_conv; 326 PurpleConversation *conv = c->active_conv;
278 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features); 327 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), purple_conversation_get_features(conv));
279 } 328 }
280 329
281 static void 330 static void
282 conversation_entry_clear(PidginConversation *gtkconv) 331 conversation_entry_clear(PidginConversation *gtkconv)
283 { 332 {
353 } else { 402 } else {
354 str = g_string_append(str, "(none)"); 403 str = g_string_append(str, "(none)");
355 } 404 }
356 405
357 tmp = g_string_free(str, FALSE); 406 tmp = g_string_free(str, FALSE);
407 } else if (!g_ascii_strcasecmp(args[0], "unsafe")) {
408 if (purple_debug_is_unsafe()) {
409 purple_debug_set_unsafe(FALSE);
410 purple_conversation_write(conv, NULL, _("Unsafe debugging is now disabled."),
411 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
412 } else {
413 purple_debug_set_unsafe(TRUE);
414 purple_conversation_write(conv, NULL, _("Unsafe debugging is now enabled."),
415 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
416 }
417
418 return PURPLE_CMD_RET_OK;
419 } else if (!g_ascii_strcasecmp(args[0], "verbose")) {
420 if (purple_debug_is_verbose()) {
421 purple_debug_set_verbose(FALSE);
422 purple_conversation_write(conv, NULL, _("Verbose debugging is now disabled."),
423 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
424 } else {
425 purple_debug_set_verbose(TRUE);
426 purple_conversation_write(conv, NULL, _("Verbose debugging is now enabled."),
427 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
428 }
429
430 return PURPLE_CMD_RET_OK;
358 } else { 431 } else {
359 purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version"), 432 purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version unsafe verbose"),
360 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL)); 433 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL));
361 return PURPLE_CMD_RET_OK; 434 return PURPLE_CMD_RET_OK;
362 } 435 }
363 436
364 markup = g_markup_escape_text(tmp, -1); 437 markup = g_markup_escape_text(tmp, -1);
376 void *data) 449 void *data)
377 { 450 {
378 PidginConversation *gtkconv = NULL; 451 PidginConversation *gtkconv = NULL;
379 452
380 gtkconv = PIDGIN_CONVERSATION(conv); 453 gtkconv = PIDGIN_CONVERSATION(conv);
381 if (gtkconv) 454
382 gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); 455 if (PIDGIN_CONVERSATION(conv))
456 webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(gtkconv->webview), "", "");
383 } 457 }
384 458
385 static PurpleCmdRet 459 static PurpleCmdRet
386 clear_command_cb(PurpleConversation *conv, 460 clear_command_cb(PurpleConversation *conv,
387 const char *cmd, char **args, char **error, void *data) 461 const char *cmd, char **args, char **error, void *data)
495 case PURPLE_CMD_STATUS_NOT_FOUND: 569 case PURPLE_CMD_STATUS_NOT_FOUND:
496 { 570 {
497 PurplePluginProtocolInfo *prpl_info = NULL; 571 PurplePluginProtocolInfo *prpl_info = NULL;
498 PurpleConnection *gc; 572 PurpleConnection *gc;
499 573
500 if ((gc = purple_conversation_get_gc(conv))) 574 if ((gc = purple_conversation_get_connection(conv)))
501 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 575 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
502 576
503 if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) { 577 if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) {
504 char *spaceslash; 578 char *spaceslash;
505 579
506 /* If the first word in the entered text has a '/' in it, then the user 580 /* If the first word in the entered text has a '/' in it, then the user
588 /* XXX: is there a better way to tell if the message has images? */ 662 /* XXX: is there a better way to tell if the message has images? */
589 if (GTK_IMHTML(gtkconv->entry)->im_images != NULL) 663 if (GTK_IMHTML(gtkconv->entry)->im_images != NULL)
590 flags |= PURPLE_MESSAGE_IMAGES; 664 flags |= PURPLE_MESSAGE_IMAGES;
591 665
592 gc = purple_account_get_connection(account); 666 gc = purple_account_get_connection(account);
593 if (gc && (conv->features & PURPLE_CONNECTION_NO_NEWLINES)) { 667 if (gc && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_NO_NEWLINES)) {
594 char **bufs; 668 char **bufs;
595 int i; 669 int i;
596 670
597 bufs = gtk_imhtml_get_markup_lines(GTK_IMHTML(gtkconv->entry)); 671 bufs = gtk_imhtml_get_markup_lines(GTK_IMHTML(gtkconv->entry));
598 for (i = 0; bufs[i]; i++) { 672 for (i = 0; bufs[i]; i++) {
654 static void chat_do_info(PidginConversation *gtkconv, const char *who) 728 static void chat_do_info(PidginConversation *gtkconv, const char *who)
655 { 729 {
656 PurpleConversation *conv = gtkconv->active_conv; 730 PurpleConversation *conv = gtkconv->active_conv;
657 PurpleConnection *gc; 731 PurpleConnection *gc;
658 732
659 if ((gc = purple_conversation_get_gc(conv))) { 733 if ((gc = purple_conversation_get_connection(conv))) {
660 pidgin_retrieve_user_info_in_chat(gc, who, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); 734 pidgin_retrieve_user_info_in_chat(gc, who, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)));
661 } 735 }
662 } 736 }
663 737
664 738
666 info_cb(GtkWidget *widget, PidginConversation *gtkconv) 740 info_cb(GtkWidget *widget, PidginConversation *gtkconv)
667 { 741 {
668 PurpleConversation *conv = gtkconv->active_conv; 742 PurpleConversation *conv = gtkconv->active_conv;
669 743
670 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 744 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
671 pidgin_retrieve_user_info(purple_conversation_get_gc(conv), 745 pidgin_retrieve_user_info(purple_conversation_get_connection(conv),
672 purple_conversation_get_name(conv)); 746 purple_conversation_get_name(conv));
673 gtk_widget_grab_focus(gtkconv->entry); 747 gtk_widget_grab_focus(gtkconv->entry);
674 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 748 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
675 /* Get info of the person currently selected in the GtkTreeView */ 749 /* Get info of the person currently selected in the GtkTreeView */
676 PidginChatPane *gtkchat; 750 PidginChatPane *gtkchat;
754 message = gtk_entry_get_text(GTK_ENTRY(info->message)); 828 message = gtk_entry_get_text(GTK_ENTRY(info->message));
755 829
756 if (!g_ascii_strcasecmp(buddy, "")) 830 if (!g_ascii_strcasecmp(buddy, ""))
757 return; 831 return;
758 832
759 serv_chat_invite(purple_conversation_get_gc(conv), 833 serv_chat_invite(purple_conversation_get_connection(conv),
760 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), 834 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)),
761 message, buddy); 835 message, buddy);
762 } 836 }
763 837
764 gtk_widget_destroy(invite_dialog); 838 gtk_widget_destroy(invite_dialog);
772 GtkSelectionData *sd, guint inf, guint t, gpointer data) 846 GtkSelectionData *sd, guint inf, guint t, gpointer data)
773 { 847 {
774 InviteBuddyInfo *info = (InviteBuddyInfo *)data; 848 InviteBuddyInfo *info = (InviteBuddyInfo *)data;
775 const char *convprotocol; 849 const char *convprotocol;
776 gboolean success = TRUE; 850 gboolean success = TRUE;
777 GdkAtom target = gtk_selection_data_get_target(sd);
778 851
779 convprotocol = purple_account_get_protocol_id(purple_conversation_get_account(info->conv)); 852 convprotocol = purple_account_get_protocol_id(purple_conversation_get_account(info->conv));
780 853
781 if (target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) 854 if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
782 { 855 {
783 PurpleBlistNode *node = NULL; 856 PurpleBlistNode *node = NULL;
784 PurpleBuddy *buddy; 857 PurpleBuddy *buddy;
785 const guchar *data = gtk_selection_data_get_data(sd); 858
786 859 memcpy(&node, sd->data, sizeof(node));
787 memcpy(&node, data, sizeof(node));
788 860
789 if (PURPLE_BLIST_NODE_IS_CONTACT(node)) 861 if (PURPLE_BLIST_NODE_IS_CONTACT(node))
790 buddy = purple_contact_get_priority_buddy((PurpleContact *)node); 862 buddy = purple_contact_get_priority_buddy((PurpleContact *)node);
791 else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) 863 else if (PURPLE_BLIST_NODE_IS_BUDDY(node))
792 buddy = (PurpleBuddy *)node; 864 buddy = (PurpleBuddy *)node;
793 else 865 else
794 return; 866 return;
795 867
796 if (strcmp(convprotocol, purple_account_get_protocol_id(buddy->account))) 868 if (strcmp(convprotocol, purple_account_get_protocol_id(purple_buddy_get_account(buddy))))
797 { 869 {
798 purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL, 870 purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL,
799 _("That buddy is not on the same protocol as this " 871 _("That buddy is not on the same protocol as this "
800 "chat."), NULL); 872 "chat."), NULL);
801 success = FALSE; 873 success = FALSE;
802 } 874 }
803 else 875 else
804 gtk_entry_set_text(GTK_ENTRY(info->entry), purple_buddy_get_name(buddy)); 876 gtk_entry_set_text(GTK_ENTRY(info->entry), purple_buddy_get_name(buddy));
805 877
806 gtk_drag_finish(dc, success, 878 gtk_drag_finish(dc, success, (dc->action == GDK_ACTION_MOVE), t);
807 gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); 879 }
808 } 880 else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE))
809 else if (target == gdk_atom_intern("application/x-im-contact", FALSE))
810 { 881 {
811 char *protocol = NULL; 882 char *protocol = NULL;
812 char *username = NULL; 883 char *username = NULL;
813 PurpleAccount *account; 884 PurpleAccount *account;
814 885
815 if (pidgin_parse_x_im_contact((const char *) data, FALSE, &account, 886 if (pidgin_parse_x_im_contact((const char *)sd->data, FALSE, &account,
816 &protocol, &username, NULL)) 887 &protocol, &username, NULL))
817 { 888 {
818 if (account == NULL) 889 if (account == NULL)
819 { 890 {
820 purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL, 891 purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL,
835 } 906 }
836 907
837 g_free(username); 908 g_free(username);
838 g_free(protocol); 909 g_free(protocol);
839 910
840 gtk_drag_finish(dc, success, 911 gtk_drag_finish(dc, success, (dc->action == GDK_ACTION_MOVE), t);
841 gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
842 } 912 }
843 } 913 }
844 914
845 static const GtkTargetEntry dnd_targets[] = 915 static const GtkTargetEntry dnd_targets[] =
846 { 916 {
878 948
879 gtk_dialog_set_default_response(GTK_DIALOG(invite_dialog), 949 gtk_dialog_set_default_response(GTK_DIALOG(invite_dialog),
880 GTK_RESPONSE_OK); 950 GTK_RESPONSE_OK);
881 gtk_container_set_border_width(GTK_CONTAINER(invite_dialog), PIDGIN_HIG_BOX_SPACE); 951 gtk_container_set_border_width(GTK_CONTAINER(invite_dialog), PIDGIN_HIG_BOX_SPACE);
882 gtk_window_set_resizable(GTK_WINDOW(invite_dialog), FALSE); 952 gtk_window_set_resizable(GTK_WINDOW(invite_dialog), FALSE);
883 /* TODO: set no separator using GTK+ 3.0 */ 953 #if !GTK_CHECK_VERSION(2,22,0)
884 #if 0
885 gtk_dialog_set_has_separator(GTK_DIALOG(invite_dialog), FALSE); 954 gtk_dialog_set_has_separator(GTK_DIALOG(invite_dialog), FALSE);
886 #endif 955 #endif
887 956
888 info->window = GTK_WIDGET(invite_dialog); 957 info->window = GTK_WIDGET(invite_dialog);
889 958
890 /* Setup the outside spacing. */ 959 /* Setup the outside spacing. */
891 vbox = gtk_dialog_get_content_area(GTK_DIALOG(invite_dialog)); 960 vbox = GTK_DIALOG(invite_dialog)->vbox;
892 961
893 gtk_box_set_spacing(GTK_BOX(vbox), PIDGIN_HIG_BORDER); 962 gtk_box_set_spacing(GTK_BOX(vbox), PIDGIN_HIG_BORDER);
894 gtk_container_set_border_width(GTK_CONTAINER(vbox), PIDGIN_HIG_BOX_SPACE); 963 gtk_container_set_border_width(GTK_CONTAINER(vbox), PIDGIN_HIG_BOX_SPACE);
895 964
896 /* Setup the inner hbox and put the dialog's icon in it. */ 965 /* Setup the inner hbox and put the dialog's icon in it. */
984 { 1053 {
985 pidgin_dialogs_im(); 1054 pidgin_dialogs_im();
986 } 1055 }
987 1056
988 static void 1057 static void
989 menu_join_chat_cb(gpointer data, guint action, GtkWidget *widget) 1058 menu_join_chat_cb(GtkAction *action, gpointer data)
990 { 1059 {
991 pidgin_blist_joinchat_show(); 1060 pidgin_blist_joinchat_show();
992 } 1061 }
993 1062
994 static void 1063 static void
995 savelog_writefile_cb(void *user_data, const char *filename) 1064 savelog_writefile_cb(void *user_data, const char *filename)
996 { 1065 {
1066 /* TODO WEBKIT: I don't know how to support this using webkit yet. */
1067 #if 0
997 PurpleConversation *conv = (PurpleConversation *)user_data; 1068 PurpleConversation *conv = (PurpleConversation *)user_data;
998 FILE *fp; 1069 FILE *fp;
999 const char *name; 1070 const char *name;
1000 char **lines; 1071 char **lines;
1001 gchar *text; 1072 gchar *text;
1018 g_free(text); 1089 g_free(text);
1019 g_strfreev(lines); 1090 g_strfreev(lines);
1020 1091
1021 fprintf(fp, "\n</body>\n</html>\n"); 1092 fprintf(fp, "\n</body>\n</html>\n");
1022 fclose(fp); 1093 fclose(fp);
1094 #endif /* if 0 */
1023 } 1095 }
1024 1096
1025 /* 1097 /*
1026 * It would be kinda cool if this gave the option of saving a 1098 * It would be kinda cool if this gave the option of saving a
1027 * plaintext v. HTML file. 1099 * plaintext v. HTML file.
1029 static void 1101 static void
1030 menu_save_as_cb(GtkAction *action, gpointer data) 1102 menu_save_as_cb(GtkAction *action, gpointer data)
1031 { 1103 {
1032 PidginWindow *win = data; 1104 PidginWindow *win = data;
1033 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); 1105 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
1034 PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); 1106 PurpleAccount *account = purple_conversation_get_account(conv);
1107 PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
1035 const char *name; 1108 const char *name;
1036 gchar *buf; 1109 gchar *buf;
1037 gchar *c; 1110 gchar *c;
1038 1111
1039 if (buddy != NULL) 1112 if (buddy != NULL)
1040 name = purple_buddy_get_contact_alias(buddy); 1113 name = purple_buddy_get_contact_alias(buddy);
1041 else 1114 else
1042 name = purple_normalize(conv->account, conv->name); 1115 name = purple_normalize(account, purple_conversation_get_name(conv));
1043 1116
1044 buf = g_strdup_printf("%s.html", name); 1117 buf = g_strdup_printf("%s.html", name);
1045 for (c = buf ; *c ; c++) 1118 for (c = buf ; *c ; c++)
1046 { 1119 {
1047 if (*c == '/' || *c == '\\') 1120 if (*c == '/' || *c == '\\')
1079 return; 1152 return;
1080 1153
1081 gtkblist = pidgin_blist_get_default_gtk_blist(); 1154 gtkblist = pidgin_blist_get_default_gtk_blist();
1082 1155
1083 cursor = gdk_cursor_new(GDK_WATCH); 1156 cursor = gdk_cursor_new(GDK_WATCH);
1084 gdk_window_set_cursor(gtk_widget_get_window(gtkblist->window), cursor); 1157 gdk_window_set_cursor(gtkblist->window->window, cursor);
1085 gdk_window_set_cursor(gtk_widget_get_window(win->window), cursor); 1158 gdk_window_set_cursor(win->window->window, cursor);
1086 gdk_cursor_unref(cursor); 1159 gdk_cursor_unref(cursor);
1087 #if GTK_CHECK_VERSION(2,4,0) && !GTK_CHECK_VERSION(2,6,0) //FIXME: What?
1088 gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window)));
1089 #endif
1090 1160
1091 name = purple_conversation_get_name(conv); 1161 name = purple_conversation_get_name(conv);
1092 account = purple_conversation_get_account(conv); 1162 account = purple_conversation_get_account(conv);
1093 1163
1094 buddies = purple_find_buddies(account, name); 1164 buddies = purple_find_buddies(account, name);
1097 PurpleBlistNode *node = cur->data; 1167 PurpleBlistNode *node = cur->data;
1098 if ((node != NULL) && ((node->prev != NULL) || (node->next != NULL))) 1168 if ((node != NULL) && ((node->prev != NULL) || (node->next != NULL)))
1099 { 1169 {
1100 pidgin_log_show_contact((PurpleContact *)node->parent); 1170 pidgin_log_show_contact((PurpleContact *)node->parent);
1101 g_slist_free(buddies); 1171 g_slist_free(buddies);
1102 gdk_window_set_cursor(gtk_widget_get_window(gtkblist->window), NULL); 1172 gdk_window_set_cursor(gtkblist->window->window, NULL);
1103 gdk_window_set_cursor(gtk_widget_get_window(win->window), NULL); 1173 gdk_window_set_cursor(win->window->window, NULL);
1104 return; 1174 return;
1105 } 1175 }
1106 } 1176 }
1107 g_slist_free(buddies); 1177 g_slist_free(buddies);
1108 1178
1109 pidgin_log_show(type, name, account); 1179 pidgin_log_show(type, name, account);
1110 1180
1111 gdk_window_set_cursor(gtk_widget_get_window(gtkblist->window), NULL); 1181 gdk_window_set_cursor(gtkblist->window->window, NULL);
1112 gdk_window_set_cursor(gtk_widget_get_window(win->window), NULL); 1182 gdk_window_set_cursor(win->window->window, NULL);
1113 } 1183 }
1114 1184
1115 static void 1185 static void
1116 menu_clear_cb(GtkAction *action, gpointer data) 1186 menu_clear_cb(GtkAction *action, gpointer data)
1117 { 1187 {
1153 { 1223 {
1154 PidginWindow *win = data; 1224 PidginWindow *win = data;
1155 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); 1225 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
1156 1226
1157 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 1227 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
1158 serv_send_file(purple_conversation_get_gc(conv), purple_conversation_get_name(conv), NULL); 1228 serv_send_file(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), NULL);
1159 } 1229 }
1160 1230
1161 } 1231 }
1162 1232
1163 static void 1233 static void
1164 menu_get_attention_cb(GtkAction *ation, gpointer data) 1234 menu_get_attention_cb(GObject *obj, gpointer data)
1165 { 1235 {
1166 PidginWindow *win = data; 1236 PidginWindow *win = data;
1167 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); 1237 PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
1168 1238
1169 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 1239 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
1170 purple_prpl_send_attention(purple_conversation_get_gc(conv), 1240 int index;
1171 purple_conversation_get_name(conv), 0); 1241 if ((GtkAction *)obj == win->menu.get_attention)
1242 index = 0;
1243 else
1244 index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(obj), "index"));
1245 purple_prpl_send_attention(purple_conversation_get_connection(conv),
1246 purple_conversation_get_name(conv), index);
1172 } 1247 }
1173 } 1248 }
1174 1249
1175 static void 1250 static void
1176 menu_add_pounce_cb(GtkAction *action, gpointer data) 1251 menu_add_pounce_cb(GtkAction *action, gpointer data)
1362 /* Enable logging first so the message below can be logged. */ 1437 /* Enable logging first so the message below can be logged. */
1363 purple_conversation_set_logging(conv, TRUE); 1438 purple_conversation_set_logging(conv, TRUE);
1364 1439
1365 purple_conversation_write(conv, NULL, 1440 purple_conversation_write(conv, NULL,
1366 _("Logging started. Future messages in this conversation will be logged."), 1441 _("Logging started. Future messages in this conversation will be logged."),
1367 conv->logs ? (PURPLE_MESSAGE_SYSTEM) : 1442 PURPLE_MESSAGE_SYSTEM,
1368 (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG),
1369 time(NULL)); 1443 time(NULL));
1370 } 1444 }
1371 else 1445 else
1372 { 1446 {
1373 purple_conversation_write(conv, NULL, 1447 purple_conversation_write(conv, NULL,
1374 _("Logging stopped. Future messages in this conversation will not be logged."), 1448 _("Logging stopped. Future messages in this conversation will not be logged."),
1375 conv->logs ? (PURPLE_MESSAGE_SYSTEM) : 1449 PURPLE_MESSAGE_SYSTEM,
1376 (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG),
1377 time(NULL)); 1450 time(NULL));
1378 1451
1379 /* Disable the logging second, so that the above message can be logged. */ 1452 /* Disable the logging second, so that the above message can be logged. */
1380 purple_conversation_set_logging(conv, FALSE); 1453 purple_conversation_set_logging(conv, FALSE);
1381 } 1454 }
1382 1455
1383 /* Save the setting IFF it's different than the pref. */ 1456 /* Save the setting IFF it's different than the pref. */
1384 switch (conv->type) 1457 switch (purple_conversation_get_type(conv))
1385 { 1458 {
1386 case PURPLE_CONV_TYPE_IM: 1459 case PURPLE_CONV_TYPE_IM:
1387 if (logging == purple_prefs_get_bool("/purple/logging/log_ims")) 1460 if (logging == purple_prefs_get_bool("/purple/logging/log_ims"))
1388 purple_blist_node_remove_setting(node, "enable-logging"); 1461 purple_blist_node_remove_setting(node, "enable-logging");
1389 else 1462 else
1451 g_return_if_fail(account != NULL); 1524 g_return_if_fail(account != NULL);
1452 1525
1453 gc = purple_account_get_connection(account); 1526 gc = purple_account_get_connection(account);
1454 g_return_if_fail(gc != NULL); 1527 g_return_if_fail(gc != NULL);
1455 1528
1456 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 1529 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1457 1530
1458 if (prpl_info && prpl_info->get_cb_real_name) 1531 if (prpl_info && prpl_info->get_cb_real_name)
1459 real_who = prpl_info->get_cb_real_name(gc, 1532 real_who = prpl_info->get_cb_real_name(gc,
1460 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); 1533 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
1461 1534
1502 menu_chat_send_file_cb(GtkWidget *w, PidginConversation *gtkconv) 1575 menu_chat_send_file_cb(GtkWidget *w, PidginConversation *gtkconv)
1503 { 1576 {
1504 PurplePluginProtocolInfo *prpl_info; 1577 PurplePluginProtocolInfo *prpl_info;
1505 PurpleConversation *conv = gtkconv->active_conv; 1578 PurpleConversation *conv = gtkconv->active_conv;
1506 const char *who = g_object_get_data(G_OBJECT(w), "user_data"); 1579 const char *who = g_object_get_data(G_OBJECT(w), "user_data");
1507 PurpleConnection *gc = purple_conversation_get_gc(conv); 1580 PurpleConnection *gc = purple_conversation_get_connection(conv);
1508 gchar *real_who = NULL; 1581 gchar *real_who = NULL;
1509 1582
1510 g_return_if_fail(gc != NULL); 1583 g_return_if_fail(gc != NULL);
1511 1584
1512 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 1585 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1513 1586
1514 if (prpl_info && prpl_info->get_cb_real_name) 1587 if (prpl_info && prpl_info->get_cb_real_name)
1515 real_who = prpl_info->get_cb_real_name(gc, 1588 real_who = prpl_info->get_cb_real_name(gc,
1516 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); 1589 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
1517 1590
1525 char *who; 1598 char *who;
1526 1599
1527 who = g_object_get_data(G_OBJECT(w), "user_data"); 1600 who = g_object_get_data(G_OBJECT(w), "user_data");
1528 1601
1529 chat_do_info(gtkconv, who); 1602 chat_do_info(gtkconv, who);
1530 }
1531
1532 static void
1533 menu_chat_get_away_cb(GtkWidget *w, PidginConversation *gtkconv)
1534 {
1535 PurpleConversation *conv = gtkconv->active_conv;
1536 PurplePluginProtocolInfo *prpl_info = NULL;
1537 PurpleConnection *gc;
1538 char *who;
1539
1540 gc = purple_conversation_get_gc(conv);
1541 who = g_object_get_data(G_OBJECT(w), "user_data");
1542
1543 if (gc != NULL) {
1544 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
1545
1546 /*
1547 * May want to expand this to work similarly to menu_info_cb?
1548 */
1549
1550 if (prpl_info->get_cb_away != NULL)
1551 {
1552 prpl_info->get_cb_away(gc,
1553 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
1554 }
1555 }
1556 } 1603 }
1557 1604
1558 static void 1605 static void
1559 menu_chat_add_remove_cb(GtkWidget *w, PidginConversation *gtkconv) 1606 menu_chat_add_remove_cb(GtkWidget *w, PidginConversation *gtkconv)
1560 { 1607 {
1576 } 1623 }
1577 1624
1578 static GtkTextMark * 1625 static GtkTextMark *
1579 get_mark_for_user(PidginConversation *gtkconv, const char *who) 1626 get_mark_for_user(PidginConversation *gtkconv, const char *who)
1580 { 1627 {
1581 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)); 1628 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->webview));
1582 char *tmp = g_strconcat("user:", who, NULL); 1629 char *tmp = g_strconcat("user:", who, NULL);
1583 GtkTextMark *mark = gtk_text_buffer_get_mark(buf, tmp); 1630 GtkTextMark *mark = gtk_text_buffer_get_mark(buf, tmp);
1584 1631
1585 g_free(tmp); 1632 g_free(tmp);
1586 return mark; 1633 return mark;
1587 } 1634 }
1588 1635
1589 static void 1636 static void
1590 menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv) 1637 menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv)
1591 { 1638 {
1639 /* TODO WEBKIT: This doesn't work yet, of course... */
1640 #if 0
1592 GtkTextMark *mark; 1641 GtkTextMark *mark;
1593 const char *who; 1642 const char *who;
1594 1643
1595 who = g_object_get_data(G_OBJECT(w), "user_data"); 1644 who = g_object_get_data(G_OBJECT(w), "user_data");
1596 mark = get_mark_for_user(gtkconv, who); 1645 mark = get_mark_for_user(gtkconv, who);
1597 1646
1598 if (mark != NULL) 1647 if (mark != NULL)
1599 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0); 1648 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0);
1600 else 1649 else
1601 g_return_if_reached(); 1650 g_return_if_reached();
1651 #endif /* if 0 */
1602 } 1652 }
1603 1653
1604 static GtkWidget * 1654 static GtkWidget *
1605 create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc) 1655 create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc)
1606 { 1656 {
1607 static GtkWidget *menu = NULL; 1657 static GtkWidget *menu = NULL;
1608 PurplePluginProtocolInfo *prpl_info = NULL; 1658 PurplePluginProtocolInfo *prpl_info = NULL;
1609 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); 1659 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
1660 PurpleAccount *account = purple_conversation_get_account(conv);
1610 gboolean is_me = FALSE; 1661 gboolean is_me = FALSE;
1611 GtkWidget *button; 1662 GtkWidget *button;
1612 PurpleBuddy *buddy = NULL; 1663 PurpleBuddy *buddy = NULL;
1613 1664
1614 if (gc != NULL) 1665 if (gc != NULL)
1615 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 1666 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1616 1667
1617 /* 1668 /*
1618 * If a menu already exists, destroy it before creating a new one, 1669 * If a menu already exists, destroy it before creating a new one,
1619 * thus freeing-up the memory it occupied. 1670 * thus freeing-up the memory it occupied.
1620 */ 1671 */
1621 if (menu) 1672 if (menu)
1622 gtk_widget_destroy(menu); 1673 gtk_widget_destroy(menu);
1623 1674
1624 if (!strcmp(chat->nick, purple_normalize(conv->account, who))) 1675 if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, who)))
1625 is_me = TRUE; 1676 is_me = TRUE;
1626 1677
1627 menu = gtk_menu_new(); 1678 menu = gtk_menu_new();
1628 1679
1629 if (!is_me) { 1680 if (!is_me) {
1684 gtk_widget_set_sensitive(button, FALSE); 1735 gtk_widget_set_sensitive(button, FALSE);
1685 else 1736 else
1686 g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free); 1737 g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
1687 } 1738 }
1688 1739
1689 if (prpl_info && prpl_info->get_cb_away) {
1690 button = pidgin_new_item_from_stock(menu, _("Get Away Message"), PIDGIN_STOCK_AWAY,
1691 G_CALLBACK(menu_chat_get_away_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
1692
1693 if (gc == NULL)
1694 gtk_widget_set_sensitive(button, FALSE);
1695 else
1696 g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
1697 }
1698
1699 if (!is_me && prpl_info && !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { 1740 if (!is_me && prpl_info && !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
1700 if ((buddy = purple_find_buddy(conv->account, who)) != NULL) 1741 if ((buddy = purple_find_buddy(account, who)) != NULL)
1701 button = pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE, 1742 button = pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE,
1702 G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); 1743 G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
1703 else 1744 else
1704 button = pidgin_new_item_from_stock(menu, _("Add"), GTK_STOCK_ADD, 1745 button = pidgin_new_item_from_stock(menu, _("Add"), GTK_STOCK_ADD,
1705 G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); 1746 G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
1716 if (!get_mark_for_user(PIDGIN_CONVERSATION(conv), who)) 1757 if (!get_mark_for_user(PIDGIN_CONVERSATION(conv), who))
1717 gtk_widget_set_sensitive(button, FALSE); 1758 gtk_widget_set_sensitive(button, FALSE);
1718 1759
1719 if (buddy != NULL) 1760 if (buddy != NULL)
1720 { 1761 {
1721 if (purple_account_is_connected(conv->account)) 1762 if (purple_account_is_connected(account))
1722 pidgin_append_blist_node_proto_menu(menu, conv->account->gc, 1763 pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account),
1723 (PurpleBlistNode *)buddy); 1764 (PurpleBlistNode *)buddy);
1724 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy); 1765 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy);
1725 gtk_widget_show_all(menu); 1766 gtk_widget_show_all(menu);
1726 } 1767 }
1727 1768
1743 gchar *who; 1784 gchar *who;
1744 1785
1745 gtkconv = PIDGIN_CONVERSATION(conv); 1786 gtkconv = PIDGIN_CONVERSATION(conv);
1746 gtkchat = gtkconv->u.chat; 1787 gtkchat = gtkconv->u.chat;
1747 account = purple_conversation_get_account(conv); 1788 account = purple_conversation_get_account(conv);
1748 gc = account->gc; 1789 gc = purple_account_get_connection(account);
1749 1790
1750 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 1791 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
1751 1792
1752 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkchat->list)); 1793 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkchat->list));
1753 if(!gtk_tree_selection_get_selected(sel, NULL, &iter)) 1794 if(!gtk_tree_selection_get_selected(sel, NULL, &iter))
1779 gchar *who; 1820 gchar *who;
1780 int x, y; 1821 int x, y;
1781 1822
1782 gtkchat = gtkconv->u.chat; 1823 gtkchat = gtkconv->u.chat;
1783 account = purple_conversation_get_account(conv); 1824 account = purple_conversation_get_account(conv);
1784 gc = account->gc; 1825 gc = purple_account_get_connection(account);
1785 1826
1786 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 1827 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
1787 1828
1788 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list), 1829 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list),
1789 event->x, event->y, &path, &column, &x, &y); 1830 event->x, event->y, &path, &column, &x, &y);
1811 1852
1812 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { 1853 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) {
1813 chat_do_im(gtkconv, who); 1854 chat_do_im(gtkconv, who);
1814 } else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) { 1855 } else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) {
1815 /* Move to user's anchor */ 1856 /* Move to user's anchor */
1857 /* TODO WEBKIT: This isn't implemented yet. */
1858 #if 0
1816 GtkTextMark *mark = get_mark_for_user(gtkconv, who); 1859 GtkTextMark *mark = get_mark_for_user(gtkconv, who);
1817 1860
1818 if(mark != NULL) 1861 if(mark != NULL)
1819 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0); 1862 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0);
1863 #endif /* if 0 */
1820 } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { 1864 } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
1821 GtkWidget *menu = create_chat_menu (conv, who, gc); 1865 GtkWidget *menu = create_chat_menu (conv, who, gc);
1822 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 1866 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1823 event->button, event->time); 1867 event->button, event->time);
1824 } 1868 }
1891 GtkWidget *next = NULL; 1935 GtkWidget *next = NULL;
1892 struct { 1936 struct {
1893 GtkWidget *from; 1937 GtkWidget *from;
1894 GtkWidget *to; 1938 GtkWidget *to;
1895 } transitions[] = { 1939 } transitions[] = {
1896 {gtkconv->entry, gtkconv->imhtml}, 1940 {gtkconv->entry, gtkconv->webview},
1897 {gtkconv->imhtml, chat ? gtkconv->u.chat->list : gtkconv->entry}, 1941 {gtkconv->webview, chat ? gtkconv->u.chat->list : gtkconv->entry},
1898 {chat ? gtkconv->u.chat->list : NULL, gtkconv->entry}, 1942 {chat ? gtkconv->u.chat->list : NULL, gtkconv->entry},
1899 {NULL, NULL} 1943 {NULL, NULL}
1900 }, *ptr; 1944 }, *ptr;
1901 1945
1902 for (ptr = transitions; !next && ptr->from; ptr++) { 1946 for (ptr = transitions; !next && ptr->from; ptr++) {
1930 pidgin_tooltip_destroy(); 1974 pidgin_tooltip_destroy();
1931 1975
1932 /* If CTRL was held down... */ 1976 /* If CTRL was held down... */
1933 if (event->state & GDK_CONTROL_MASK) { 1977 if (event->state & GDK_CONTROL_MASK) {
1934 switch (event->keyval) { 1978 switch (event->keyval) {
1935 case GDK_KEY_Page_Down: 1979 case GDK_Page_Down:
1936 case GDK_KEY_KP_Page_Down: 1980 case GDK_KP_Page_Down:
1937 case ']': 1981 case ']':
1938 if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv + 1)) 1982 if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv + 1))
1939 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0); 1983 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0);
1940 else 1984 else
1941 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), curconv + 1); 1985 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), curconv + 1);
1942 return TRUE; 1986 return TRUE;
1943 break; 1987 break;
1944 1988
1945 case GDK_KEY_Page_Up: 1989 case GDK_Page_Up:
1946 case GDK_KEY_KP_Page_Up: 1990 case GDK_KP_Page_Up:
1947 case '[': 1991 case '[':
1948 if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv - 1)) 1992 if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv - 1))
1949 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), -1); 1993 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), -1);
1950 else 1994 else
1951 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), curconv - 1); 1995 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), curconv - 1);
1952 return TRUE; 1996 return TRUE;
1953 break; 1997 break;
1954 1998
1955 case GDK_KEY_Tab: 1999 case GDK_Tab:
1956 case GDK_KEY_KP_Tab: 2000 case GDK_KP_Tab:
1957 case GDK_KEY_ISO_Left_Tab: 2001 case GDK_ISO_Left_Tab:
1958 if (event->state & GDK_SHIFT_MASK) { 2002 if (event->state & GDK_SHIFT_MASK) {
1959 move_to_next_unread_tab(gtkconv, FALSE); 2003 move_to_next_unread_tab(gtkconv, FALSE);
1960 } else { 2004 } else {
1961 move_to_next_unread_tab(gtkconv, TRUE); 2005 move_to_next_unread_tab(gtkconv, TRUE);
1962 } 2006 }
1963 2007
1964 return TRUE; 2008 return TRUE;
1965 break; 2009 break;
1966 2010
1967 case GDK_KEY_comma: 2011 case GDK_comma:
1968 gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook), 2012 gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook),
1969 gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv), 2013 gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv),
1970 curconv - 1); 2014 curconv - 1);
1971 return TRUE; 2015 return TRUE;
1972 break; 2016 break;
1973 2017
1974 case GDK_KEY_period: 2018 case GDK_period:
1975 gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook), 2019 gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook),
1976 gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv), 2020 gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv),
1977 (curconv + 1) % gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->notebook))); 2021 (curconv + 1) % gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->notebook)));
1978 return TRUE; 2022 return TRUE;
1979 break; 2023 break;
1980 case GDK_KEY_F6: 2024 case GDK_F6:
1981 if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD)) 2025 if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD))
1982 return TRUE; 2026 return TRUE;
1983 break; 2027 break;
1984 } /* End of switch */ 2028 } /* End of switch */
1985 } 2029 }
1999 2043
2000 /* If neither CTRL nor ALT were held down... */ 2044 /* If neither CTRL nor ALT were held down... */
2001 else 2045 else
2002 { 2046 {
2003 switch (event->keyval) { 2047 switch (event->keyval) {
2004 case GDK_KEY_F2: 2048 case GDK_F2:
2005 if (gtk_widget_is_focus(GTK_WIDGET(win->notebook))) { 2049 if (gtk_widget_is_focus(GTK_WIDGET(win->notebook))) {
2006 infopane_entry_activate(gtkconv); 2050 infopane_entry_activate(gtkconv);
2007 return TRUE; 2051 return TRUE;
2008 } 2052 }
2009 break; 2053 break;
2010 case GDK_KEY_F6: 2054 case GDK_F6:
2011 if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD)) 2055 if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD))
2012 return TRUE; 2056 return TRUE;
2013 break; 2057 break;
2014 } 2058 }
2015 } 2059 }
2029 return TRUE; 2073 return TRUE;
2030 2074
2031 /* If CTRL was held down... */ 2075 /* If CTRL was held down... */
2032 if (event->state & GDK_CONTROL_MASK) { 2076 if (event->state & GDK_CONTROL_MASK) {
2033 switch (event->keyval) { 2077 switch (event->keyval) {
2034 case GDK_KEY_Up: 2078 case GDK_Up:
2035 if (!gtkconv->send_history) 2079 if (!gtkconv->send_history)
2036 break; 2080 break;
2037 2081
2038 if (gtkconv->entry != entry) 2082 if (gtkconv->entry != entry)
2039 break; 2083 break;
2080 } 2124 }
2081 2125
2082 return TRUE; 2126 return TRUE;
2083 break; 2127 break;
2084 2128
2085 case GDK_KEY_Down: 2129 case GDK_Down:
2086 if (!gtkconv->send_history) 2130 if (!gtkconv->send_history)
2087 break; 2131 break;
2088 2132
2089 if (gtkconv->entry != entry) 2133 if (gtkconv->entry != entry)
2090 break; 2134 break;
2133 } 2177 }
2134 2178
2135 /* If neither CTRL nor ALT were held down... */ 2179 /* If neither CTRL nor ALT were held down... */
2136 else { 2180 else {
2137 switch (event->keyval) { 2181 switch (event->keyval) {
2138 case GDK_KEY_Tab: 2182 case GDK_Tab:
2139 case GDK_KEY_KP_Tab: 2183 case GDK_KP_Tab:
2140 case GDK_KEY_ISO_Left_Tab: 2184 case GDK_ISO_Left_Tab:
2141 if (gtkconv->entry != entry) 2185 if (gtkconv->entry != entry)
2142 break; 2186 break;
2143 { 2187 {
2144 gint plugin_return; 2188 gint plugin_return;
2145 plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( 2189 plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1(
2147 conv, event->state & GDK_SHIFT_MASK)); 2191 conv, event->state & GDK_SHIFT_MASK));
2148 return plugin_return ? TRUE : tab_complete(conv); 2192 return plugin_return ? TRUE : tab_complete(conv);
2149 } 2193 }
2150 break; 2194 break;
2151 2195
2152 case GDK_KEY_Page_Up: 2196 case GDK_Page_Up:
2153 case GDK_KEY_KP_Page_Up: 2197 case GDK_KP_Page_Up:
2198 /* TODO WEBKIT: Write this. */
2199 #if 0
2154 gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml)); 2200 gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml));
2201 #endif /* if 0 */
2155 return TRUE; 2202 return TRUE;
2156 break; 2203 break;
2157 2204
2158 case GDK_KEY_Page_Down: 2205 case GDK_Page_Down:
2159 case GDK_KEY_KP_Page_Down: 2206 case GDK_KP_Page_Down:
2207 /* TODO WEBKIT: Write this. */
2208 #if 0
2160 gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml)); 2209 gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml));
2210 #endif /* if 0 */
2161 return TRUE; 2211 return TRUE;
2162 break; 2212 break;
2163 2213
2164 } 2214 }
2165 } 2215 }
2198 { 2248 {
2199 PidginConversation *gtkconv = data; 2249 PidginConversation *gtkconv = data;
2200 2250
2201 /* If we have a valid key for the conversation display, then exit */ 2251 /* If we have a valid key for the conversation display, then exit */
2202 if ((event->state & GDK_CONTROL_MASK) || 2252 if ((event->state & GDK_CONTROL_MASK) ||
2203 (event->keyval == GDK_KEY_F6) || 2253 (event->keyval == GDK_F6) ||
2204 (event->keyval == GDK_KEY_F10) || 2254 (event->keyval == GDK_F10) ||
2205 (event->keyval == GDK_KEY_Shift_L) || 2255 (event->keyval == GDK_Shift_L) ||
2206 (event->keyval == GDK_KEY_Shift_R) || 2256 (event->keyval == GDK_Shift_R) ||
2207 (event->keyval == GDK_KEY_Control_L) || 2257 (event->keyval == GDK_Control_L) ||
2208 (event->keyval == GDK_KEY_Control_R) || 2258 (event->keyval == GDK_Control_R) ||
2209 (event->keyval == GDK_KEY_Escape) || 2259 (event->keyval == GDK_Escape) ||
2210 (event->keyval == GDK_KEY_Up) || 2260 (event->keyval == GDK_Up) ||
2211 (event->keyval == GDK_KEY_Down) || 2261 (event->keyval == GDK_Down) ||
2212 (event->keyval == GDK_KEY_Left) || 2262 (event->keyval == GDK_Left) ||
2213 (event->keyval == GDK_KEY_Right) || 2263 (event->keyval == GDK_Right) ||
2214 (event->keyval == GDK_KEY_Page_Up) || 2264 (event->keyval == GDK_Page_Up) ||
2215 (event->keyval == GDK_KEY_KP_Page_Up) || 2265 (event->keyval == GDK_KP_Page_Up) ||
2216 (event->keyval == GDK_KEY_Page_Down) || 2266 (event->keyval == GDK_Page_Down) ||
2217 (event->keyval == GDK_KEY_KP_Page_Down) || 2267 (event->keyval == GDK_KP_Page_Down) ||
2218 (event->keyval == GDK_KEY_Home) || 2268 (event->keyval == GDK_Home) ||
2219 (event->keyval == GDK_KEY_End) || 2269 (event->keyval == GDK_End) ||
2220 (event->keyval == GDK_KEY_Tab) || 2270 (event->keyval == GDK_Tab) ||
2221 (event->keyval == GDK_KEY_KP_Tab) || 2271 (event->keyval == GDK_KP_Tab) ||
2222 (event->keyval == GDK_KEY_ISO_Left_Tab)) 2272 (event->keyval == GDK_ISO_Left_Tab))
2223 { 2273 {
2224 if (event->type == GDK_KEY_PRESS) 2274 if (event->type == GDK_KEY_PRESS)
2225 return conv_keypress_common(gtkconv, event); 2275 return conv_keypress_common(gtkconv, event);
2226 return FALSE; 2276 return FALSE;
2227 } 2277 }
2242 { 2292 {
2243 PidginConversation *gtkconv; 2293 PidginConversation *gtkconv;
2244 PurpleConversation *old_conv; 2294 PurpleConversation *old_conv;
2245 GtkIMHtml *entry; 2295 GtkIMHtml *entry;
2246 const char *protocol_name; 2296 const char *protocol_name;
2297 PurpleConnectionFlags features;
2247 2298
2248 g_return_if_fail(conv != NULL); 2299 g_return_if_fail(conv != NULL);
2249 2300
2250 gtkconv = PIDGIN_CONVERSATION(conv); 2301 gtkconv = PIDGIN_CONVERSATION(conv);
2251 old_conv = gtkconv->active_conv; 2302 old_conv = gtkconv->active_conv;
2263 2314
2264 purple_conversation_set_logging(conv, 2315 purple_conversation_set_logging(conv,
2265 gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(gtkconv->win->menu.logging))); 2316 gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(gtkconv->win->menu.logging)));
2266 2317
2267 entry = GTK_IMHTML(gtkconv->entry); 2318 entry = GTK_IMHTML(gtkconv->entry);
2268 protocol_name = purple_account_get_protocol_name(conv->account); 2319 protocol_name = purple_account_get_protocol_name(purple_conversation_get_account(conv));
2269 gtk_imhtml_set_protocol_name(entry, protocol_name); 2320 gtk_imhtml_set_protocol_name(entry, protocol_name);
2270 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); 2321 /* TODO WEBKIT: gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); */
2271 2322
2272 if (!(conv->features & PURPLE_CONNECTION_HTML)) 2323 features = purple_conversation_get_features(conv);
2324 if (!(features & PURPLE_CONNECTION_HTML))
2273 gtk_imhtml_clear_formatting(GTK_IMHTML(gtkconv->entry)); 2325 gtk_imhtml_clear_formatting(GTK_IMHTML(gtkconv->entry));
2274 else if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO && 2326 else if (features & PURPLE_CONNECTION_FORMATTING_WBFO &&
2275 !(old_conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)) 2327 !(purple_conversation_get_features(old_conv) & PURPLE_CONNECTION_FORMATTING_WBFO))
2276 { 2328 {
2277 /* The old conversation allowed formatting on parts of the 2329 /* The old conversation allowed formatting on parts of the
2278 * buffer, but the new one only allows it on the whole 2330 * buffer, but the new one only allows it on the whole
2279 * buffer. This code saves the formatting from the current 2331 * buffer. This code saves the formatting from the current
2280 * position of the cursor, clears the formatting, then 2332 * position of the cursor, clears the formatting, then
2310 if (underline != underline2) 2362 if (underline != underline2)
2311 gtk_imhtml_toggle_underline(entry); 2363 gtk_imhtml_toggle_underline(entry);
2312 2364
2313 gtk_imhtml_toggle_fontface(entry, fontface); 2365 gtk_imhtml_toggle_fontface(entry, fontface);
2314 2366
2315 if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE)) 2367 if (!(features & PURPLE_CONNECTION_NO_FONTSIZE))
2316 gtk_imhtml_font_set_size(entry, fontsize); 2368 gtk_imhtml_font_set_size(entry, fontsize);
2317 2369
2318 gtk_imhtml_toggle_forecolor(entry, forecolor); 2370 gtk_imhtml_toggle_forecolor(entry, forecolor);
2319 2371
2320 if (!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR)) 2372 if (!(features & PURPLE_CONNECTION_NO_BGCOLOR))
2321 { 2373 {
2322 gtk_imhtml_toggle_backcolor(entry, backcolor); 2374 gtk_imhtml_toggle_backcolor(entry, backcolor);
2323 gtk_imhtml_toggle_background(entry, background); 2375 gtk_imhtml_toggle_background(entry, background);
2324 } 2376 }
2325 2377
2333 /* This is done in default_formatize, which is called from clear_formatting_cb, 2385 /* This is done in default_formatize, which is called from clear_formatting_cb,
2334 * which is (obviously) a clear_formatting signal handler. However, if we're 2386 * which is (obviously) a clear_formatting signal handler. However, if we're
2335 * here, we didn't call gtk_imhtml_clear_formatting() (because we want to 2387 * here, we didn't call gtk_imhtml_clear_formatting() (because we want to
2336 * preserve the formatting exactly as it is), so we have to do this now. */ 2388 * preserve the formatting exactly as it is), so we have to do this now. */
2337 gtk_imhtml_set_whole_buffer_formatting_only(entry, 2389 gtk_imhtml_set_whole_buffer_formatting_only(entry,
2338 (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)); 2390 (features & PURPLE_CONNECTION_FORMATTING_WBFO));
2339 } 2391 }
2340 2392
2341 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv); 2393 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv);
2342 2394
2343 gray_stuff_out(gtkconv); 2395 gray_stuff_out(gtkconv);
2398 if (gtk_text_iter_is_start(start_pos) && gtk_text_iter_is_end(end_pos)) { 2450 if (gtk_text_iter_is_start(start_pos) && gtk_text_iter_is_end(end_pos)) {
2399 2451
2400 /* We deleted all the text, so turn off typing. */ 2452 /* We deleted all the text, so turn off typing. */
2401 purple_conv_im_stop_send_typed_timeout(im); 2453 purple_conv_im_stop_send_typed_timeout(im);
2402 2454
2403 serv_send_typing(purple_conversation_get_gc(conv), 2455 serv_send_typing(purple_conversation_get_connection(conv),
2404 purple_conversation_get_name(conv), 2456 purple_conversation_get_name(conv),
2405 PURPLE_NOT_TYPING); 2457 PURPLE_NOT_TYPING);
2406 } 2458 }
2407 else { 2459 else {
2408 /* We're deleting, but not all of it, so it counts as typing. */ 2460 /* We're deleting, but not all of it, so it counts as typing. */
2448 2500
2449 /* Use the buddy icon, if possible */ 2501 /* Use the buddy icon, if possible */
2450 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 2502 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
2451 PurpleBuddy *b = purple_find_buddy(account, name); 2503 PurpleBuddy *b = purple_find_buddy(account, name);
2452 if (b != NULL) { 2504 if (b != NULL) {
2453 PurplePresence *p = purple_buddy_get_presence(b); 2505 PurplePresence *p;
2506 p = purple_buddy_get_presence(b);
2454 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY)) 2507 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY))
2455 return away_list; 2508 return away_list;
2456 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE)) 2509 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE))
2457 return busy_list; 2510 return busy_list;
2458 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY)) 2511 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY))
2562 return; 2615 return;
2563 2616
2564 status = infopane_status = pidgin_conv_get_icon_stock(conv); 2617 status = infopane_status = pidgin_conv_get_icon_stock(conv);
2565 2618
2566 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 2619 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
2567 PurpleBuddy *b = purple_find_buddy(conv->account, conv->name); 2620 PurpleBuddy *b = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
2568 if (b) 2621 if (b)
2569 emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b); 2622 emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b);
2570 } 2623 }
2571 2624
2572 g_return_if_fail(status != NULL); 2625 g_return_if_fail(status != NULL);
2583 CONV_EMBLEM_COLUMN, emblem, -1); 2636 CONV_EMBLEM_COLUMN, emblem, -1);
2584 if (emblem) 2637 if (emblem)
2585 g_object_unref(emblem); 2638 g_object_unref(emblem);
2586 2639
2587 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) { 2640 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) {
2588 emblem = pidgin_create_prpl_icon(gtkconv->active_conv->account, PIDGIN_PRPL_ICON_SMALL); 2641 emblem = pidgin_create_prpl_icon(purple_conversation_get_account(gtkconv->active_conv), PIDGIN_PRPL_ICON_SMALL);
2589 } else { 2642 } else {
2590 emblem = NULL; 2643 emblem = NULL;
2591 } 2644 }
2592 2645
2593 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model), 2646 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model),
2639 int size; 2692 int size;
2640 2693
2641 gtkconv = PIDGIN_CONVERSATION(conv); 2694 gtkconv = PIDGIN_CONVERSATION(conv);
2642 account = purple_conversation_get_account(conv); 2695 account = purple_conversation_get_account(conv);
2643 2696
2644 if (!(account && account->gc)) { 2697 if (!(account && purple_account_get_connection(account))) {
2645 gtkconv->u.im->icon_timer = 0; 2698 gtkconv->u.im->icon_timer = 0;
2646 return FALSE; 2699 return FALSE;
2647 } 2700 }
2648 2701
2649 gdk_pixbuf_animation_iter_advance(gtkconv->u.im->iter, NULL); 2702 gdk_pixbuf_animation_iter_advance(gtkconv->u.im->iter, NULL);
2684 2737
2685 return FALSE; 2738 return FALSE;
2686 } 2739 }
2687 2740
2688 static void 2741 static void
2689 start_anim(GtkWidget *widget, PidginConversation *gtkconv) 2742 start_anim(GtkObject *obj, PidginConversation *gtkconv)
2690 { 2743 {
2691 int delay; 2744 int delay;
2692 2745
2693 if (gtkconv->u.im->anim == NULL) 2746 if (gtkconv->u.im->anim == NULL)
2694 return; 2747 return;
2846 2899
2847 g_return_if_fail(conv != NULL); 2900 g_return_if_fail(conv != NULL);
2848 2901
2849 ext = purple_buddy_icon_get_extension(purple_conv_im_get_icon(PURPLE_CONV_IM(conv))); 2902 ext = purple_buddy_icon_get_extension(purple_conv_im_get_icon(PURPLE_CONV_IM(conv)));
2850 2903
2851 buf = g_strdup_printf("%s.%s", purple_normalize(conv->account, conv->name), ext); 2904 buf = g_strdup_printf("%s.%s", purple_normalize(purple_conversation_get_account(conv), purple_conversation_get_name(conv)), ext);
2852 2905
2853 purple_request_file(gtkconv, _("Save Icon"), buf, TRUE, 2906 purple_request_file(gtkconv, _("Save Icon"), buf, TRUE,
2854 G_CALLBACK(saveicon_writefile_cb), NULL, 2907 G_CALLBACK(saveicon_writefile_cb), NULL,
2855 conv->account, NULL, conv, 2908 purple_conversation_get_account(conv), NULL, conv,
2856 gtkconv); 2909 gtkconv);
2857 2910
2858 g_free(buf); 2911 g_free(buf);
2859 } 2912 }
2860 2913
2861 static void 2914 static void
2862 stop_anim(GtkWidget *widget, PidginConversation *gtkconv) 2915 stop_anim(GtkObject *obj, PidginConversation *gtkconv)
2863 { 2916 {
2864 if (gtkconv->u.im->icon_timer != 0) 2917 if (gtkconv->u.im->icon_timer != 0)
2865 g_source_remove(gtkconv->u.im->icon_timer); 2918 g_source_remove(gtkconv->u.im->icon_timer);
2866 2919
2867 gtkconv->u.im->icon_timer = 0; 2920 gtkconv->u.im->icon_timer = 0;
2879 else 2932 else
2880 stop_anim(NULL, gtkconv); 2933 stop_anim(NULL, gtkconv);
2881 } 2934 }
2882 2935
2883 static gboolean 2936 static gboolean
2884 icon_menu(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv) 2937 icon_menu(GtkObject *obj, GdkEventButton *e, PidginConversation *gtkconv)
2885 { 2938 {
2886 static GtkWidget *menu = NULL; 2939 static GtkWidget *menu = NULL;
2887 PurpleConversation *conv; 2940 PurpleConversation *conv;
2888 PurpleBuddy *buddy; 2941 PurpleBuddy *buddy;
2889 2942
3073 { 3126 {
3074 g_return_val_if_fail(gtkconv != NULL, NULL); 3127 g_return_val_if_fail(gtkconv != NULL, NULL);
3075 return gtkconv->win; 3128 return gtkconv->win;
3076 } 3129 }
3077 3130
3078 #if 1
3079
3080 static GtkActionEntry menu_entries[] = 3131 static GtkActionEntry menu_entries[] =
3081 /* TODO: fill out tooltips... */ 3132 /* TODO: fill out tooltips... */
3082 { 3133 {
3083 /* Conversation menu */ 3134 /* Conversation menu */
3084 { "ConversationMenu", NULL, N_("_Conversation"), NULL, NULL, NULL }, 3135 { "ConversationMenu", NULL, N_("_Conversation"), NULL, NULL, NULL },
3085 { "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "<control>M", NULL, G_CALLBACK(menu_new_conv_cb) }, 3136 { "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "<control>M", NULL, G_CALLBACK(menu_new_conv_cb) },
3137 { "JoinAChat", PIDGIN_STOCK_CHAT, N_("Join a _Chat..."), NULL, NULL, G_CALLBACK(menu_join_chat_cb) },
3086 { "Find", GTK_STOCK_FIND, N_("_Find..."), NULL, NULL, G_CALLBACK(menu_find_cb) }, 3138 { "Find", GTK_STOCK_FIND, N_("_Find..."), NULL, NULL, G_CALLBACK(menu_find_cb) },
3087 { "ViewLog", NULL, N_("View _Log"), NULL, NULL, G_CALLBACK(menu_view_log_cb) }, 3139 { "ViewLog", NULL, N_("View _Log"), NULL, NULL, G_CALLBACK(menu_view_log_cb) },
3088 { "SaveAs", GTK_STOCK_SAVE_AS, N_("_Save As..."), NULL, NULL, G_CALLBACK(menu_save_as_cb) }, 3140 { "SaveAs", GTK_STOCK_SAVE_AS, N_("_Save As..."), NULL, NULL, G_CALLBACK(menu_save_as_cb) },
3089 { "ClearScrollback", GTK_STOCK_CLEAR, N_("Clea_r Scrollback"), "<control>L", NULL, G_CALLBACK(menu_clear_cb) }, 3141 { "ClearScrollback", GTK_STOCK_CLEAR, N_("Clea_r Scrollback"), "<control>L", NULL, G_CALLBACK(menu_clear_cb) },
3090 3142
3125 static const char *conversation_menu = 3177 static const char *conversation_menu =
3126 "<ui>" 3178 "<ui>"
3127 "<menubar name='Conversation'>" 3179 "<menubar name='Conversation'>"
3128 "<menu action='ConversationMenu'>" 3180 "<menu action='ConversationMenu'>"
3129 "<menuitem action='NewInstantMessage'/>" 3181 "<menuitem action='NewInstantMessage'/>"
3182 "<menuitem action='JoinAChat'/>"
3130 "<separator/>" 3183 "<separator/>"
3131 "<menuitem action='Find'/>" 3184 "<menuitem action='Find'/>"
3132 "<menuitem action='ViewLog'/>" 3185 "<menuitem action='ViewLog'/>"
3133 "<menuitem action='SaveAs'/>" 3186 "<menuitem action='SaveAs'/>"
3134 "<menuitem action='ClearScrollback'/>" 3187 "<menuitem action='ClearScrollback'/>"
3166 "<menuitem action='ShowTimestamps'/>" 3219 "<menuitem action='ShowTimestamps'/>"
3167 "</menu>" 3220 "</menu>"
3168 "</menubar>" 3221 "</menubar>"
3169 "</ui>"; 3222 "</ui>";
3170 3223
3171 #else
3172
3173 static GtkItemFactoryEntry menu_items[] =
3174 {
3175 /* Conversation menu */
3176 { N_("/_Conversation"), NULL, NULL, 0, "<Branch>", NULL },
3177
3178 { N_("/Conversation/New Instant _Message..."), "<CTL>M", menu_new_conv_cb,
3179 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW },
3180 { N_("/Conversation/Join a _Chat..."), NULL, menu_join_chat_cb,
3181 0, "<StockItem>", PIDGIN_STOCK_CHAT },
3182
3183 { "/Conversation/sep0", NULL, NULL, 0, "<Separator>", NULL },
3184
3185 { N_("/Conversation/_Find..."), NULL, menu_find_cb, 0,
3186 "<StockItem>", GTK_STOCK_FIND },
3187 { N_("/Conversation/View _Log"), NULL, menu_view_log_cb, 0, "<Item>", NULL },
3188 { N_("/Conversation/_Save As..."), NULL, menu_save_as_cb, 0,
3189 "<StockItem>", GTK_STOCK_SAVE_AS },
3190 { N_("/Conversation/Clea_r Scrollback"), "<CTL>L", menu_clear_cb, 0, "<StockItem>", GTK_STOCK_CLEAR },
3191
3192 { "/Conversation/sep1", NULL, NULL, 0, "<Separator>", NULL },
3193
3194 #ifdef USE_VV
3195 { N_("/Conversation/M_edia"), NULL, NULL, 0, "<Branch>", NULL },
3196
3197 { N_("/Conversation/Media/_Audio Call"), NULL, menu_initiate_media_call_cb, 0,
3198 "<StockItem>", PIDGIN_STOCK_TOOLBAR_AUDIO_CALL },
3199 { N_("/Conversation/Media/_Video Call"), NULL, menu_initiate_media_call_cb, 1,
3200 "<StockItem>", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL },
3201 { N_("/Conversation/Media/Audio\\/Video _Call"), NULL, menu_initiate_media_call_cb, 2,
3202 "<StockItem>", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL },
3203 #endif
3204
3205 { N_("/Conversation/Se_nd File..."), NULL, menu_send_file_cb, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SEND_FILE },
3206 { N_("/Conversation/Get _Attention"), NULL, menu_get_attention_cb, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION },
3207 { N_("/Conversation/Add Buddy _Pounce..."), NULL, menu_add_pounce_cb,
3208 0, "<Item>", NULL },
3209 { N_("/Conversation/_Get Info"), "<CTL>O", menu_get_info_cb, 0,
3210 "<StockItem>", PIDGIN_STOCK_TOOLBAR_USER_INFO },
3211 { N_("/Conversation/In_vite..."), NULL, menu_invite_cb, 0,
3212 "<Item>", NULL },
3213 { N_("/Conversation/M_ore"), NULL, NULL, 0, "<Branch>", NULL },
3214
3215 { "/Conversation/sep2", NULL, NULL, 0, "<Separator>", NULL },
3216
3217 { N_("/Conversation/Al_ias..."), NULL, menu_alias_cb, 0,
3218 "<Item>", NULL },
3219 { N_("/Conversation/_Block..."), NULL, menu_block_cb, 0,
3220 "<StockItem>", PIDGIN_STOCK_TOOLBAR_BLOCK },
3221 { N_("/Conversation/_Unblock..."), NULL, menu_unblock_cb, 0,
3222 "<StockItem>", PIDGIN_STOCK_TOOLBAR_UNBLOCK },
3223 { N_("/Conversation/_Add..."), NULL, menu_add_remove_cb, 0,
3224 "<StockItem>", GTK_STOCK_ADD },
3225 { N_("/Conversation/_Remove..."), NULL, menu_add_remove_cb, 0,
3226 "<StockItem>", GTK_STOCK_REMOVE },
3227
3228 { "/Conversation/sep3", NULL, NULL, 0, "<Separator>", NULL },
3229
3230 { N_("/Conversation/Insert Lin_k..."), NULL, menu_insert_link_cb, 0,
3231 "<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_LINK },
3232 { N_("/Conversation/Insert Imag_e..."), NULL, menu_insert_image_cb, 0,
3233 "<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE },
3234
3235 { "/Conversation/sep4", NULL, NULL, 0, "<Separator>", NULL },
3236
3237
3238 { N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0,
3239 "<StockItem>", GTK_STOCK_CLOSE },
3240
3241 /* Options */
3242 { N_("/_Options"), NULL, NULL, 0, "<Branch>", NULL },
3243 { N_("/Options/Enable _Logging"), NULL, menu_logging_cb, 0, "<CheckItem>", NULL },
3244 { N_("/Options/Enable _Sounds"), NULL, menu_sounds_cb, 0, "<CheckItem>", NULL },
3245 { "/Options/sep0", NULL, NULL, 0, "<Separator>", NULL },
3246 { N_("/Options/Show Formatting _Toolbars"), NULL, menu_toolbar_cb, 0, "<CheckItem>", NULL },
3247 { N_("/Options/Show Ti_mestamps"), NULL, menu_timestamps_cb, 0, "<CheckItem>", NULL },
3248 };
3249 #endif
3250
3251 static void 3224 static void
3252 sound_method_pref_changed_cb(const char *name, PurplePrefType type, 3225 sound_method_pref_changed_cb(const char *name, PurplePrefType type,
3253 gconstpointer value, gpointer data) 3226 gconstpointer value, gpointer data)
3254 { 3227 {
3255 PidginWindow *win = data; 3228 PidginWindow *win = data;
3276 static gboolean 3249 static gboolean
3277 populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolean all) 3250 populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolean all)
3278 { 3251 {
3279 GList *list; 3252 GList *list;
3280 PurpleConversation *conv; 3253 PurpleConversation *conv;
3254 PurpleAccount *account;
3281 PurpleBlistNode *node = NULL; 3255 PurpleBlistNode *node = NULL;
3282 PurpleChat *chat = NULL; 3256 PurpleChat *chat = NULL;
3283 PurpleBuddy *buddy = NULL; 3257 PurpleBuddy *buddy = NULL;
3284 gboolean ret; 3258 gboolean ret;
3285 3259
3286 conv = gtkconv->active_conv; 3260 conv = gtkconv->active_conv;
3261 account = purple_conversation_get_account(conv);
3287 3262
3288 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 3263 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
3289 chat = purple_blist_find_chat(conv->account, conv->name); 3264 chat = purple_blist_find_chat(account, purple_conversation_get_name(conv));
3290 3265
3291 if ((chat == NULL) && (gtkconv->imhtml != NULL)) { 3266 if ((chat == NULL) && (gtkconv->webview != NULL)) {
3292 chat = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); 3267 chat = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat");
3293 } 3268 }
3294 3269
3295 if ((chat == NULL) && (gtkconv->imhtml != NULL)) { 3270 if ((chat == NULL) && (gtkconv->webview != NULL)) {
3296 GHashTable *components; 3271 GHashTable *components;
3297 PurpleAccount *account = purple_conversation_get_account(conv); 3272 PurpleAccount *account = purple_conversation_get_account(conv);
3298 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); 3273 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
3299 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 3274 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
3300 if (purple_account_get_connection(account) != NULL && 3275 if (purple_account_get_connection(account) != NULL &&
3305 components = g_hash_table_new_full(g_str_hash, g_str_equal, 3280 components = g_hash_table_new_full(g_str_hash, g_str_equal,
3306 g_free, g_free); 3281 g_free, g_free);
3307 g_hash_table_replace(components, g_strdup("channel"), 3282 g_hash_table_replace(components, g_strdup("channel"),
3308 g_strdup(purple_conversation_get_name(conv))); 3283 g_strdup(purple_conversation_get_name(conv)));
3309 } 3284 }
3310 chat = purple_chat_new(conv->account, NULL, components); 3285 chat = purple_chat_new(account, NULL, components);
3311 purple_blist_node_set_flags((PurpleBlistNode *)chat, 3286 purple_blist_node_set_flags((PurpleBlistNode *)chat,
3312 PURPLE_BLIST_NODE_FLAG_NO_SAVE); 3287 PURPLE_BLIST_NODE_FLAG_NO_SAVE);
3313 g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_chat", 3288 g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_chat",
3314 chat, (GDestroyNotify)purple_blist_remove_chat); 3289 chat, (GDestroyNotify)purple_blist_remove_chat);
3315 } 3290 }
3316 } else { 3291 } else {
3317 if (!purple_account_is_connected(conv->account)) 3292 if (!purple_account_is_connected(account))
3318 return FALSE; 3293 return FALSE;
3319 3294
3320 buddy = purple_find_buddy(conv->account, conv->name); 3295 buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
3321 3296
3322 /* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle 3297 /* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle
3323 * removing "isolated" buddy nodes well */ 3298 * removing "isolated" buddy nodes well */
3324 if (purple_version_check(2, 0, 2) == NULL) { 3299 if (purple_version_check(2, 0, 2) == NULL) {
3325 if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { 3300 if ((buddy == NULL) && (gtkconv->webview != NULL)) {
3326 buddy = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); 3301 buddy = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy");
3327 } 3302 }
3328 3303
3329 if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { 3304 if ((buddy == NULL) && (gtkconv->webview != NULL)) {
3330 buddy = purple_buddy_new(conv->account, conv->name, NULL); 3305 buddy = purple_buddy_new(account, purple_conversation_get_name(conv), NULL);
3331 purple_blist_node_set_flags((PurpleBlistNode *)buddy, 3306 purple_blist_node_set_flags((PurpleBlistNode *)buddy,
3332 PURPLE_BLIST_NODE_FLAG_NO_SAVE); 3307 PURPLE_BLIST_NODE_FLAG_NO_SAVE);
3333 g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_buddy", 3308 g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_buddy",
3334 buddy, (GDestroyNotify)purple_buddy_destroy); 3309 buddy, (GDestroyNotify)purple_buddy_destroy);
3335 } 3310 }
3336 } 3311 }
3337 } 3312 }
3338 3313
3347 pidgin_blist_make_buddy_menu(menu, buddy, TRUE); 3322 pidgin_blist_make_buddy_menu(menu, buddy, TRUE);
3348 else if (chat) { 3323 else if (chat) {
3349 /* XXX: */ 3324 /* XXX: */
3350 } 3325 }
3351 } else if (node) { 3326 } else if (node) {
3352 if (purple_account_is_connected(conv->account)) 3327 if (purple_account_is_connected(account))
3353 pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node); 3328 pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account), node);
3354 pidgin_append_blist_node_extended_menu(menu, node); 3329 pidgin_append_blist_node_extended_menu(menu, node);
3355 } 3330 }
3356 3331
3357 if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL) { 3332 if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL) {
3358 ret = FALSE; 3333 ret = FALSE;
3400 caps & PURPLE_MEDIA_CAPS_AUDIO 3375 caps & PURPLE_MEDIA_CAPS_AUDIO
3401 ? TRUE : FALSE); 3376 ? TRUE : FALSE);
3402 gtk_action_set_sensitive(win->video_call, 3377 gtk_action_set_sensitive(win->video_call,
3403 caps & PURPLE_MEDIA_CAPS_VIDEO 3378 caps & PURPLE_MEDIA_CAPS_VIDEO
3404 ? TRUE : FALSE); 3379 ? TRUE : FALSE);
3405 gtk_action_set_sensitive(win->audio_video_call, 3380 gtk_action_set_sensitive(win->audio_video_call,
3406 caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO 3381 caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO
3407 ? TRUE : FALSE); 3382 ? TRUE : FALSE);
3408 } else if (purple_conversation_get_type(conv) 3383 } else if (purple_conversation_get_type(conv)
3409 == PURPLE_CONV_TYPE_CHAT) { 3384 == PURPLE_CONV_TYPE_CHAT) {
3410 /* for now, don't care about chats... */ 3385 /* for now, don't care about chats... */
3418 } 3393 }
3419 #endif 3394 #endif
3420 } 3395 }
3421 3396
3422 static void 3397 static void
3398 regenerate_attention_items(PidginWindow *win)
3399 {
3400 GtkWidget *menu;
3401 PurpleConversation *conv;
3402 PurpleConnection *pc;
3403 PurplePlugin *prpl = NULL;
3404 PurplePluginProtocolInfo *prpl_info = NULL;
3405 GList *list;
3406
3407 conv = pidgin_conv_window_get_active_conversation(win);
3408 if (!conv)
3409 return;
3410
3411 /* Remove the previous entries */
3412 gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.get_attention), NULL);
3413
3414 pc = purple_conversation_get_connection(conv);
3415 if (pc != NULL)
3416 prpl = purple_connection_get_prpl(pc);
3417 if (prpl != NULL)
3418 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
3419
3420 if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_attention_types)) {
3421 list = prpl_info->get_attention_types(purple_connection_get_account(pc));
3422
3423 /* Multiple attention types */
3424 if (list && list->next) {
3425 int index = 0;
3426
3427 menu = gtk_menu_new();
3428 while (list) {
3429 PurpleAttentionType *type;
3430 GtkWidget *menuitem;
3431
3432 type = list->data;
3433
3434 menuitem = gtk_menu_item_new_with_label(purple_attention_type_get_name(type));
3435 g_object_set_data(G_OBJECT(menuitem), "index", GINT_TO_POINTER(index));
3436 g_signal_connect(G_OBJECT(menuitem), "activate",
3437 G_CALLBACK(menu_get_attention_cb),
3438 win);
3439 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
3440
3441 index++;
3442 list = g_list_delete_link(list, list);
3443 }
3444
3445 gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.get_attention), menu);
3446 gtk_widget_show_all(menu);
3447 }
3448 }
3449 }
3450
3451 static void
3423 regenerate_options_items(PidginWindow *win) 3452 regenerate_options_items(PidginWindow *win)
3424 { 3453 {
3425 GtkWidget *menu; 3454 GtkWidget *menu;
3426 PidginConversation *gtkconv; 3455 PidginConversation *gtkconv;
3427 GList *list; 3456 GList *list;
3428 #if GTK_CHECK_VERSION(2,6,0)
3429 GtkWidget *more_menu; 3457 GtkWidget *more_menu;
3430 3458
3431 gtkconv = pidgin_conv_window_get_active_gtkconv(win); 3459 gtkconv = pidgin_conv_window_get_active_gtkconv(win);
3432 more_menu = gtk_ui_manager_get_widget(win->menu.ui, 3460 more_menu = gtk_ui_manager_get_widget(win->menu.ui,
3433 "/Conversation/ConversationMenu/MoreMenu"); 3461 "/Conversation/ConversationMenu/MoreMenu");
3434 gtk_widget_show(more_menu); 3462 gtk_widget_show(more_menu);
3435 menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(more_menu)); 3463 menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(more_menu));
3436 #else
3437 gtkconv = pidgin_conv_window_get_active_gtkconv(win);
3438 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More"));
3439 #endif
3440 3464
3441 /* Remove the previous entries */ 3465 /* Remove the previous entries */
3442 for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; ) 3466 for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; )
3443 { 3467 {
3444 GtkWidget *w = list->data; 3468 GtkWidget *w = list->data;
3490 G_CALLBACK(remove_from_list), win); 3514 G_CALLBACK(remove_from_list), win);
3491 gtk_widget_destroy(action_items->data); 3515 gtk_widget_destroy(action_items->data);
3492 action_items = g_list_delete_link(action_items, action_items); 3516 action_items = g_list_delete_link(action_items, action_items);
3493 } 3517 }
3494 3518
3495 #if GTK_CHECK_VERSION(2,6,0)
3496 item = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/OptionsMenu"); 3519 item = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/OptionsMenu");
3497 menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item)); 3520 menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item));
3498 #else
3499 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options"));
3500 #endif
3501 3521
3502 list = purple_conversation_get_extended_menu(conv); 3522 list = purple_conversation_get_extended_menu(conv);
3503 if (list) { 3523 if (list) {
3504 action_items = g_list_prepend(NULL, (item = pidgin_separator(menu))); 3524 action_items = g_list_prepend(NULL, (item = pidgin_separator(menu)));
3505 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win); 3525 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
3519 { 3539 {
3520 PidginWindow *win = data; 3540 PidginWindow *win = data;
3521 regenerate_media_items(win); 3541 regenerate_media_items(win);
3522 regenerate_options_items(win); 3542 regenerate_options_items(win);
3523 regenerate_plugins_items(win); 3543 regenerate_plugins_items(win);
3544 regenerate_attention_items(win);
3524 3545
3525 /* The following are to make sure the 'More' submenu is not regenerated every time 3546 /* The following are to make sure the 'More' submenu is not regenerated every time
3526 * the focus shifts from 'Conversations' to some other menu and back. */ 3547 * the focus shifts from 'Conversations' to some other menu and back. */
3527 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data); 3548 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data);
3528 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data); 3549 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data);
3604 3625
3605 win->menu.send_file = 3626 win->menu.send_file =
3606 gtk_ui_manager_get_action(win->menu.ui, 3627 gtk_ui_manager_get_action(win->menu.ui,
3607 "/Conversation/ConversationMenu/SendFile"); 3628 "/Conversation/ConversationMenu/SendFile");
3608 3629
3609 g_object_set_data(G_OBJECT(win->window), "get_attention", 3630 win->menu.get_attention =
3610 gtk_ui_manager_get_action(win->menu.ui, 3631 gtk_ui_manager_get_action(win->menu.ui,
3611 "/Conversation/ConversationMenu/GetAttention")); 3632 "/Conversation/ConversationMenu/GetAttention");
3612 3633
3613 win->menu.add_pounce = 3634 win->menu.add_pounce =
3614 gtk_ui_manager_get_action(win->menu.ui, 3635 gtk_ui_manager_get_action(win->menu.ui,
3615 "/Conversation/ConversationMenu/AddBuddyPounce"); 3636 "/Conversation/ConversationMenu/AddBuddyPounce");
3616 3637
3716 /* Check if we need to send another PURPLE_TYPING message */ 3737 /* Check if we need to send another PURPLE_TYPING message */
3717 if (first || (purple_conv_im_get_type_again(im) != 0 && 3738 if (first || (purple_conv_im_get_type_again(im) != 0 &&
3718 time(NULL) > purple_conv_im_get_type_again(im))) 3739 time(NULL) > purple_conv_im_get_type_again(im)))
3719 { 3740 {
3720 unsigned int timeout; 3741 unsigned int timeout;
3721 timeout = serv_send_typing(purple_conversation_get_gc(conv), 3742 timeout = serv_send_typing(purple_conversation_get_connection(conv),
3722 purple_conversation_get_name(conv), 3743 purple_conversation_get_name(conv),
3723 PURPLE_TYPING); 3744 PURPLE_TYPING);
3724 purple_conv_im_set_type_again(im, timeout); 3745 purple_conv_im_set_type_again(im, timeout);
3725 } 3746 }
3726 } 3747 }
3752 case 4: 3773 case 4:
3753 stock_id = PIDGIN_STOCK_ANIMATION_TYPING4; 3774 stock_id = PIDGIN_STOCK_ANIMATION_TYPING4;
3754 break; 3775 break;
3755 } 3776 }
3756 if (gtkwin->menu.typing_icon == NULL) { 3777 if (gtkwin->menu.typing_icon == NULL) {
3757 gtkwin->menu.typing_icon = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU); 3778 gtkwin->menu.typing_icon = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU);
3758 pidgin_menu_tray_append(PIDGIN_MENU_TRAY(gtkwin->menu.tray), 3779 pidgin_menu_tray_append(PIDGIN_MENU_TRAY(gtkwin->menu.tray),
3759 gtkwin->menu.typing_icon, 3780 gtkwin->menu.typing_icon,
3760 _("User is typing...")); 3781 _("User is typing..."));
3761 } else { 3782 } else {
3762 gtk_image_set_from_stock(GTK_IMAGE(gtkwin->menu.typing_icon), stock_id, GTK_ICON_SIZE_MENU); 3783 gtk_image_set_from_stock(GTK_IMAGE(gtkwin->menu.typing_icon), stock_id, GTK_ICON_SIZE_MENU);
3763 } 3784 }
3764 gtk_widget_show(gtkwin->menu.typing_icon); 3785 gtk_widget_show(gtkwin->menu.typing_icon);
3765 return TRUE; 3786 return TRUE;
3767 #endif 3788 #endif
3768 3789
3769 static void 3790 static void
3770 update_typing_message(PidginConversation *gtkconv, const char *message) 3791 update_typing_message(PidginConversation *gtkconv, const char *message)
3771 { 3792 {
3793 /* TODO WEBKIT: this is not handled at all */
3794 #if 0
3772 GtkTextBuffer *buffer; 3795 GtkTextBuffer *buffer;
3773 GtkTextMark *stmark, *enmark; 3796 GtkTextMark *stmark, *enmark;
3774 3797
3775 if (g_object_get_data(G_OBJECT(gtkconv->imhtml), "disable-typing-notification")) 3798 if (g_object_get_data(G_OBJECT(gtkconv->imhtml), "disable-typing-notification"))
3776 return; 3799 return;
3799 gtk_text_buffer_create_mark(buffer, "typing-notification-start", &iter, TRUE); 3822 gtk_text_buffer_create_mark(buffer, "typing-notification-start", &iter, TRUE);
3800 gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, message, -1, "TYPING-NOTIFICATION", NULL); 3823 gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, message, -1, "TYPING-NOTIFICATION", NULL);
3801 gtk_text_buffer_get_end_iter(buffer, &iter); 3824 gtk_text_buffer_get_end_iter(buffer, &iter);
3802 gtk_text_buffer_create_mark(buffer, "typing-notification-end", &iter, TRUE); 3825 gtk_text_buffer_create_mark(buffer, "typing-notification-end", &iter, TRUE);
3803 } 3826 }
3827 #endif /* if 0 */
3804 } 3828 }
3805 3829
3806 static void 3830 static void
3807 update_typing_icon(PidginConversation *gtkconv) 3831 update_typing_icon(PidginConversation *gtkconv)
3808 { 3832 {
3855 return FALSE; 3879 return FALSE;
3856 3880
3857 if (win->menu.send_to == NULL) 3881 if (win->menu.send_to == NULL)
3858 return FALSE; 3882 return FALSE;
3859 3883
3860 if (!(b = purple_find_buddy(account, conv->name))) 3884 if (!(b = purple_find_buddy(account, purple_conversation_get_name(conv))))
3861 return FALSE; 3885 return FALSE;
3862 3886
3863 #if 0 /* TODO */
3864 gtk_widget_show(win->menu.send_to); 3887 gtk_widget_show(win->menu.send_to);
3865 3888
3866 menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(win->menu.send_to)); 3889 menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(win->menu.send_to));
3867 3890
3868 for (child = gtk_container_get_children(GTK_CONTAINER(menu)); 3891 for (child = gtk_container_get_children(GTK_CONTAINER(menu));
3880 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); 3903 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
3881 g_list_free(child); 3904 g_list_free(child);
3882 break; 3905 break;
3883 } 3906 }
3884 } 3907 }
3885 #endif
3886 3908
3887 return FALSE; 3909 return FALSE;
3888 } 3910 }
3889 3911
3890 static gboolean 3912 static gboolean
3990 } 4012 }
3991 4013
3992 static void 4014 static void
3993 generate_send_to_items(PidginWindow *win) 4015 generate_send_to_items(PidginWindow *win)
3994 { 4016 {
3995 #if 0 /* TODO */
3996 GtkWidget *menu; 4017 GtkWidget *menu;
3997 GSList *group = NULL; 4018 GSList *group = NULL;
3998 GtkSizeGroup *sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); 4019 GtkSizeGroup *sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3999 PidginConversation *gtkconv; 4020 PidginConversation *gtkconv;
4000 GSList *l, *buds; 4021 GSList *l, *buds;
4017 win->menu.send_to, 2); 4038 win->menu.send_to, 2);
4018 gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.send_to), menu); 4039 gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.send_to), menu);
4019 4040
4020 gtk_widget_show(menu); 4041 gtk_widget_show(menu);
4021 4042
4022 if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM) { 4043 if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM) {
4023 buds = purple_find_buddies(gtkconv->active_conv->account, gtkconv->active_conv->name); 4044 buds = purple_find_buddies(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv));
4024 4045
4025 if (buds == NULL) 4046 if (buds == NULL)
4026 { 4047 {
4027 /* The user isn't on the buddy list. So we don't create any sendto menu. */ 4048 /* The user isn't on the buddy list. So we don't create any sendto menu. */
4028 } 4049 }
4042 4063
4043 if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) 4064 if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
4044 continue; 4065 continue;
4045 4066
4046 account = purple_buddy_get_account(buddy); 4067 account = purple_buddy_get_account(buddy);
4047 if (purple_account_is_connected(account) || account == gtkconv->active_conv->account) 4068 /* TODO WEBKIT: (I'm not actually sure if this is webkit-related --Mark Doliner) */
4069 if (purple_account_is_connected(account) /*|| account == purple_conversation_get_account(gtkconv->active_conv)*/)
4048 { 4070 {
4049 /* Use the PurplePresence to get unique buddies. */ 4071 /* Use the PurplePresence to get unique buddies. */
4050 PurplePresence *presence = purple_buddy_get_presence(buddy); 4072 PurplePresence *presence = purple_buddy_get_presence(buddy);
4051 if (!g_list_find_custom(list, presence, (GCompareFunc)compare_buddy_presence)) 4073 if (!g_list_find_custom(list, presence, (GCompareFunc)compare_buddy_presence))
4052 list = g_list_prepend(list, presence); 4074 list = g_list_prepend(list, presence);
4075 gtk_widget_show(win->menu.send_to); 4097 gtk_widget_show(win->menu.send_to);
4076 /* TODO: This should never be insensitive. Possibly hidden or not. */ 4098 /* TODO: This should never be insensitive. Possibly hidden or not. */
4077 if (!group) 4099 if (!group)
4078 gtk_widget_set_sensitive(win->menu.send_to, FALSE); 4100 gtk_widget_set_sensitive(win->menu.send_to, FALSE);
4079 update_send_to_selection(win); 4101 update_send_to_selection(win);
4080 #endif
4081 } 4102 }
4082 4103
4083 static const char * 4104 static const char *
4084 get_chat_buddy_status_icon(PurpleConvChat *chat, const char *name, PurpleConvChatBuddyFlags flags) 4105 get_chat_buddy_status_icon(PurpleConvChat *chat, const char *name, PurpleConvChatBuddyFlags flags)
4085 { 4106 {
4102 } 4123 }
4103 4124
4104 static void 4125 static void
4105 deleting_chat_buddy_cb(PurpleConvChatBuddy *cb) 4126 deleting_chat_buddy_cb(PurpleConvChatBuddy *cb)
4106 { 4127 {
4107 if (cb->ui_data) { 4128 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
4108 GtkTreeRowReference *ref = cb->ui_data; 4129
4130 if (ref) {
4109 gtk_tree_row_reference_free(ref); 4131 gtk_tree_row_reference_free(ref);
4110 cb->ui_data = NULL; 4132 purple_conv_chat_cb_set_ui_data(cb, NULL);
4111 } 4133 }
4112 } 4134 }
4113 4135
4114 static void 4136 static void
4115 add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const char *old_name) 4137 add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const char *old_name)
4124 GtkTreePath *newpath; 4146 GtkTreePath *newpath;
4125 const char *stock; 4147 const char *stock;
4126 GtkTreeIter iter; 4148 GtkTreeIter iter;
4127 gboolean is_me = FALSE; 4149 gboolean is_me = FALSE;
4128 gboolean is_buddy; 4150 gboolean is_buddy;
4129 gchar *tmp, *alias_key, *name, *alias; 4151 const gchar *name, *alias;
4152 gchar *tmp, *alias_key;
4130 PurpleConvChatBuddyFlags flags; 4153 PurpleConvChatBuddyFlags flags;
4131 GdkColor *color = NULL; 4154 GdkColor *color = NULL;
4132 4155
4133 alias = cb->alias; 4156 alias = purple_conv_chat_cb_get_alias(cb);
4134 name = cb->name; 4157 name = purple_conv_chat_cb_get_name(cb);
4135 flags = cb->flags; 4158 flags = purple_conv_chat_cb_get_flags(cb);
4136 4159
4137 chat = PURPLE_CONV_CHAT(conv); 4160 chat = PURPLE_CONV_CHAT(conv);
4138 gtkconv = PIDGIN_CONVERSATION(conv); 4161 gtkconv = PIDGIN_CONVERSATION(conv);
4139 gtkchat = gtkconv->u.chat; 4162 gtkchat = gtkconv->u.chat;
4140 gc = purple_conversation_get_gc(conv); 4163 gc = purple_conversation_get_connection(conv);
4141 4164
4142 if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl))) 4165 if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
4143 return; 4166 return;
4144 4167
4145 tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 4168 tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
4146 ls = GTK_LIST_STORE(tm); 4169 ls = GTK_LIST_STORE(tm);
4147 4170
4148 stock = get_chat_buddy_status_icon(chat, name, flags); 4171 stock = get_chat_buddy_status_icon(chat, name, flags);
4149 4172
4150 if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name))) 4173 if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(purple_conversation_get_account(conv), old_name != NULL ? old_name : name)))
4151 is_me = TRUE; 4174 is_me = TRUE;
4152 4175
4153 is_buddy = cb->buddy; 4176 is_buddy = purple_conv_chat_cb_is_buddy(cb);
4154 4177
4155 tmp = g_utf8_casefold(alias, -1); 4178 tmp = g_utf8_casefold(alias, -1);
4156 alias_key = g_utf8_collate_key(tmp, -1); 4179 alias_key = g_utf8_collate_key(tmp, -1);
4157 g_free(tmp); 4180 g_free(tmp);
4158 4181
4159 if (is_me) { 4182 if (is_me) {
4183 #if 0
4184 /* TODO WEBKIT: No tags in webkit stuff, yet. */
4160 GtkTextTag *tag = gtk_text_tag_table_lookup( 4185 GtkTextTag *tag = gtk_text_tag_table_lookup(
4161 gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->imhtml)->text_buffer), 4186 gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->webview)->text_buffer),
4162 "send-name"); 4187 "send-name");
4163 g_object_get(tag, "foreground-gdk", &color, NULL); 4188 g_object_get(tag, "foreground-gdk", &color, NULL);
4189 #endif /* if 0 */
4164 } else { 4190 } else {
4165 GtkTextTag *tag; 4191 GtkTextTag *tag;
4166 if ((tag = get_buddy_tag(conv, name, 0, FALSE))) 4192 if ((tag = get_buddy_tag(conv, name, 0, FALSE)))
4167 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); 4193 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL);
4168 if ((tag = get_buddy_tag(conv, name, PURPLE_MESSAGE_NICK, FALSE))) 4194 if ((tag = get_buddy_tag(conv, name, PURPLE_MESSAGE_NICK, FALSE)))
4186 CHAT_USERS_FLAGS_COLUMN, flags, 4212 CHAT_USERS_FLAGS_COLUMN, flags,
4187 CHAT_USERS_COLOR_COLUMN, color, 4213 CHAT_USERS_COLOR_COLUMN, color,
4188 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, 4214 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
4189 -1); 4215 -1);
4190 4216
4191 if (cb->ui_data) { 4217 if (purple_conv_chat_cb_get_ui_data(cb)) {
4192 GtkTreeRowReference *ref = cb->ui_data; 4218 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
4193 gtk_tree_row_reference_free(ref); 4219 gtk_tree_row_reference_free(ref);
4194 } 4220 }
4195 4221
4196 newpath = gtk_tree_model_get_path(tm, &iter); 4222 newpath = gtk_tree_model_get_path(tm, &iter);
4197 cb->ui_data = gtk_tree_row_reference_new(tm, newpath); 4223 purple_conv_chat_cb_set_ui_data(cb, gtk_tree_row_reference_new(tm, newpath));
4198 gtk_tree_path_free(newpath); 4224 gtk_tree_path_free(newpath);
4199 4225
4200 if (is_me && color) 4226 if (is_me && color)
4201 gdk_color_free(color); 4227 gdk_color_free(color);
4202 g_free(alias_key); 4228 g_free(alias_key);
4222 * @param name The buddy name or alias or slash command name that we're 4248 * @param name The buddy name or alias or slash command name that we're
4223 * checking for a match. 4249 * checking for a match.
4224 */ 4250 */
4225 static void 4251 static void
4226 tab_complete_process_item(int *most_matched, const char *entered, gsize entered_bytes, char **partial, char *nick_partial, 4252 tab_complete_process_item(int *most_matched, const char *entered, gsize entered_bytes, char **partial, char *nick_partial,
4227 GList **matches, char *name) 4253 GList **matches, const char *name)
4228 { 4254 {
4229 memcpy(nick_partial, name, entered_bytes); 4255 memcpy(nick_partial, name, entered_bytes);
4230 if (purple_utf8_strcasecmp(nick_partial, entered)) 4256 if (purple_utf8_strcasecmp(nick_partial, entered))
4231 return; 4257 return;
4232 4258
4344 int f; 4370 int f;
4345 4371
4346 /* Users */ 4372 /* Users */
4347 for (; l != NULL; l = l->next) { 4373 for (; l != NULL; l = l->next) {
4348 tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, 4374 tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial,
4349 &matches, ((PurpleConvChatBuddy *)l->data)->name); 4375 &matches, purple_conv_chat_cb_get_name((PurpleConvChatBuddy *)l->data));
4350 } 4376 }
4351 4377
4352 4378
4353 /* Aliases */ 4379 /* Aliases */
4354 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 4380 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
4442 PurpleConversation *conv = gtkconv->active_conv; 4468 PurpleConversation *conv = gtkconv->active_conv;
4443 PidginChatPane *gtkchat; 4469 PidginChatPane *gtkchat;
4444 char *new_topic; 4470 char *new_topic;
4445 const char *current_topic; 4471 const char *current_topic;
4446 4472
4447 gc = purple_conversation_get_gc(conv); 4473 gc = purple_conversation_get_connection(conv);
4448 4474
4449 if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl))) 4475 if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
4450 return; 4476 return;
4451 4477
4452 if(prpl_info->set_chat_topic == NULL) 4478 if(prpl_info->set_chat_topic == NULL)
4453 return; 4479 return;
4454 4480
4519 static void 4545 static void
4520 update_chat_alias(PurpleBuddy *buddy, PurpleConversation *conv, PurpleConnection *gc, PurplePluginProtocolInfo *prpl_info) 4546 update_chat_alias(PurpleBuddy *buddy, PurpleConversation *conv, PurpleConnection *gc, PurplePluginProtocolInfo *prpl_info)
4521 { 4547 {
4522 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); 4548 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
4523 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); 4549 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
4550 PurpleAccount *account = purple_conversation_get_account(conv);
4524 GtkTreeModel *model; 4551 GtkTreeModel *model;
4525 char *normalized_name; 4552 char *normalized_name;
4526 GtkTreeIter iter; 4553 GtkTreeIter iter;
4527 int f; 4554 int f;
4528 4555
4533 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkconv->u.chat->list)); 4560 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkconv->u.chat->list));
4534 4561
4535 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 4562 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
4536 return; 4563 return;
4537 4564
4538 normalized_name = g_strdup(purple_normalize(conv->account, buddy->name)); 4565 normalized_name = g_strdup(purple_normalize(account, purple_buddy_get_name(buddy)));
4539 4566
4540 do { 4567 do {
4541 char *name; 4568 char *name;
4542 4569
4543 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1); 4570 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1);
4544 4571
4545 if (!strcmp(normalized_name, purple_normalize(conv->account, name))) { 4572 if (!strcmp(normalized_name, purple_normalize(account, name))) {
4546 const char *alias = name; 4573 const char *alias = name;
4547 char *tmp; 4574 char *tmp;
4548 char *alias_key = NULL; 4575 char *alias_key = NULL;
4549 PurpleBuddy *buddy2; 4576 PurpleBuddy *buddy2;
4550 4577
4551 if (strcmp(chat->nick, purple_normalize(conv->account, name))) { 4578 if (strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, name))) {
4552 /* This user is not me, so look into updating the alias. */ 4579 /* This user is not me, so look into updating the alias. */
4553 4580
4554 if ((buddy2 = purple_find_buddy(conv->account, name)) != NULL) { 4581 if ((buddy2 = purple_find_buddy(account, name)) != NULL) {
4555 alias = purple_buddy_get_contact_alias(buddy2); 4582 alias = purple_buddy_get_contact_alias(buddy2);
4556 } 4583 }
4557 4584
4558 tmp = g_utf8_casefold(alias, -1); 4585 tmp = g_utf8_casefold(alias, -1);
4559 alias_key = g_utf8_collate_key(tmp, -1); 4586 alias_key = g_utf8_collate_key(tmp, -1);
4584 PurplePluginProtocolInfo *prpl_info; 4611 PurplePluginProtocolInfo *prpl_info;
4585 4612
4586 g_return_if_fail(node != NULL); 4613 g_return_if_fail(node != NULL);
4587 g_return_if_fail(conv != NULL); 4614 g_return_if_fail(conv != NULL);
4588 4615
4589 gc = purple_conversation_get_gc(conv); 4616 gc = purple_conversation_get_connection(conv);
4590 g_return_if_fail(gc != NULL); 4617 g_return_if_fail(gc != NULL);
4591 g_return_if_fail(gc->prpl != NULL); 4618 g_return_if_fail(purple_connection_get_prpl(gc) != NULL);
4592 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 4619 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
4593 4620
4594 if (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME) 4621 if (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)
4595 return; 4622 return;
4596 4623
4597 if (PURPLE_BLIST_NODE_IS_CONTACT(node)) 4624 if (PURPLE_BLIST_NODE_IS_CONTACT(node))
4607 } 4634 }
4608 } 4635 }
4609 else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) 4636 else if (PURPLE_BLIST_NODE_IS_BUDDY(node))
4610 update_chat_alias((PurpleBuddy *)node, conv, gc, prpl_info); 4637 update_chat_alias((PurpleBuddy *)node, conv, gc, prpl_info);
4611 else if (PURPLE_BLIST_NODE_IS_CHAT(node) && 4638 else if (PURPLE_BLIST_NODE_IS_CHAT(node) &&
4612 purple_conversation_get_account(conv) == ((PurpleChat*)node)->account) 4639 purple_conversation_get_account(conv) == purple_chat_get_account((PurpleChat*)node))
4613 { 4640 {
4614 if (old_alias == NULL || g_utf8_collate(old_alias, purple_conversation_get_title(conv)) == 0) 4641 if (old_alias == NULL || g_utf8_collate(old_alias, purple_conversation_get_title(conv)) == 0)
4615 pidgin_conv_update_fields(conv, PIDGIN_CONV_SET_TITLE); 4642 pidgin_conv_update_fields(conv, PIDGIN_CONV_SET_TITLE);
4616 } 4643 }
4617 } 4644 }
4636 model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list)); 4663 model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list));
4637 4664
4638 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 4665 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
4639 return; 4666 return;
4640 4667
4641 normalized_name = g_strdup(purple_normalize(conv->account, buddy->name)); 4668 normalized_name = g_strdup(purple_normalize(purple_conversation_get_account(conv), purple_buddy_get_name(buddy)));
4642 4669
4643 do { 4670 do {
4644 char *name; 4671 char *name;
4645 4672
4646 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1); 4673 gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1);
4647 4674
4648 if (!strcmp(normalized_name, purple_normalize(conv->account, name))) { 4675 if (!strcmp(normalized_name, purple_normalize(purple_conversation_get_account(conv), name))) {
4649 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 4676 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
4650 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1); 4677 CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1);
4651 g_free(name); 4678 g_free(name);
4652 break; 4679 break;
4653 } 4680 }
4722 GtkTextIter iter; 4749 GtkTextIter iter;
4723 int lines; 4750 int lines;
4724 GdkRectangle oneline; 4751 GdkRectangle oneline;
4725 int height, diff; 4752 int height, diff;
4726 int pad_top, pad_inside, pad_bottom; 4753 int pad_top, pad_inside, pad_bottom;
4727 int total_height; 4754 int total_height = (gtkconv->webview->allocation.height + gtkconv->entry->allocation.height);
4728 int max_height; 4755 int max_height = total_height / 2;
4729 int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines"); 4756 int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines");
4730 int min_height; 4757 int min_height;
4731 gboolean interior_focus; 4758 gboolean interior_focus;
4732 int focus_width; 4759 int focus_width;
4733 GtkAllocation imhtml_allocation;
4734 GtkAllocation entry_allocation;
4735 GtkAllocation lower_hbox_allocation;
4736
4737 gtk_widget_get_allocation(gtkconv->imhtml, &imhtml_allocation);
4738 gtk_widget_get_allocation(gtkconv->entry, &entry_allocation);
4739 gtk_widget_get_allocation(gtkconv->lower_hbox, &lower_hbox_allocation);
4740 total_height = imhtml_allocation.height + entry_allocation.height;
4741 max_height = total_height / 2;
4742 4760
4743 pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry)); 4761 pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry));
4744 pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry)); 4762 pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry));
4745 pad_inside = gtk_text_view_get_pixels_inside_wrap(GTK_TEXT_VIEW(gtkconv->entry)); 4763 pad_inside = gtk_text_view_get_pixels_inside_wrap(GTK_TEXT_VIEW(gtkconv->entry));
4746 4764
4770 "focus-line-width", &focus_width, 4788 "focus-line-width", &focus_width,
4771 NULL); 4789 NULL);
4772 if (!interior_focus) 4790 if (!interior_focus)
4773 height += 2 * focus_width; 4791 height += 2 * focus_width;
4774 4792
4775 diff = height - entry_allocation.height; 4793 diff = height - gtkconv->entry->allocation.height;
4776 if (ABS(diff) < oneline.height / 2) 4794 if (ABS(diff) < oneline.height / 2)
4777 return FALSE; 4795 return FALSE;
4778 4796
4779 purple_debug_info("pidgin", "resizing to %d, %d lines, diff %d\n",
4780 diff + lower_hbox_allocation.height, min_lines, diff);
4781
4782 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, 4797 gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
4783 diff + lower_hbox_allocation.height); 4798 diff + gtkconv->lower_hbox->allocation.height);
4784 4799
4785 return FALSE; 4800 return FALSE;
4786 } 4801 }
4787 4802
4788 static void 4803 static void
4806 4821
4807 static void 4822 static void
4808 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox) 4823 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox)
4809 { 4824 {
4810 PurpleConversation *conv = gtkconv->active_conv; 4825 PurpleConversation *conv = gtkconv->active_conv;
4811 PurpleConnection *gc = purple_conversation_get_gc(conv); 4826 PurpleConnection *gc = purple_conversation_get_connection(conv);
4812 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 4827 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
4813 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) 4828 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC)
4814 { 4829 {
4815 GtkWidget *hbox, *label; 4830 GtkWidget *hbox, *label;
4816 PidginChatPane *gtkchat = gtkconv->u.chat; 4831 PidginChatPane *gtkchat = gtkconv->u.chat;
4817 4832
4825 gtk_widget_set_size_request(gtkchat->topic_text, -1, BUDDYICON_SIZE_MIN); 4840 gtk_widget_set_size_request(gtkchat->topic_text, -1, BUDDYICON_SIZE_MIN);
4826 4841
4827 if(prpl_info->set_chat_topic == NULL) { 4842 if(prpl_info->set_chat_topic == NULL) {
4828 gtk_editable_set_editable(GTK_EDITABLE(gtkchat->topic_text), FALSE); 4843 gtk_editable_set_editable(GTK_EDITABLE(gtkchat->topic_text), FALSE);
4829 } else { 4844 } else {
4830 g_signal_connect(GTK_WIDGET(gtkchat->topic_text), "activate", 4845 g_signal_connect(GTK_OBJECT(gtkchat->topic_text), "activate",
4831 G_CALLBACK(topic_callback), gtkconv); 4846 G_CALLBACK(topic_callback), gtkconv);
4832 } 4847 }
4833 4848
4834 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0); 4849 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0);
4835 g_signal_connect(G_OBJECT(gtkchat->topic_text), "key_press_event", 4850 g_signal_connect(G_OBJECT(gtkchat->topic_text), "key_press_event",
4848 PurpleBlistNode *node; 4863 PurpleBlistNode *node;
4849 PurplePluginProtocolInfo *prpl_info; 4864 PurplePluginProtocolInfo *prpl_info;
4850 PurpleAccount *account = purple_conversation_get_account(conv); 4865 PurpleAccount *account = purple_conversation_get_account(conv);
4851 char *who = NULL; 4866 char *who = NULL;
4852 4867
4853 if (account->gc == NULL) 4868 if (purple_account_get_connection(account) == NULL)
4854 return FALSE; 4869 return FALSE;
4855 4870
4856 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path)) 4871 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path))
4857 return FALSE; 4872 return FALSE;
4858 4873
4859 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1); 4874 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1);
4860 4875
4861 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl); 4876 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account)));
4862 node = (PurpleBlistNode*)(purple_find_buddy(conv->account, who)); 4877 node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), who));
4863 if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) 4878 if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME))
4864 pidgin_blist_draw_tooltip(node, gtkconv->infopane); 4879 pidgin_blist_draw_tooltip(node, gtkconv->infopane);
4865 4880
4866 g_free(who); 4881 g_free(who);
4867 return FALSE; 4882 return FALSE;
4958 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE); 4973 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE);
4959 gtk_widget_show(list); 4974 gtk_widget_show(list);
4960 4975
4961 gtkchat->list = list; 4976 gtkchat->list = list;
4962 4977
4963 gtk_box_pack_start(GTK_BOX(lbox), 4978 gtk_box_pack_start(GTK_BOX(lbox),
4964 pidgin_make_scrollable(list, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1), 4979 pidgin_make_scrollable(list, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1),
4965 TRUE, TRUE, 0); 4980 TRUE, TRUE, 0);
4966 } 4981 }
4967 4982
4968 static gboolean 4983 static gboolean
4972 PurpleConversation *conv; 4987 PurpleConversation *conv;
4973 PidginConversation *gtkconv = userdata; 4988 PidginConversation *gtkconv = userdata;
4974 4989
4975 conv = gtkconv->active_conv; 4990 conv = gtkconv->active_conv;
4976 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 4991 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
4977 node = (PurpleBlistNode*)(purple_blist_find_chat(conv->account, conv->name)); 4992 node = (PurpleBlistNode*)(purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv)));
4978 if (!node) 4993 if (!node)
4979 node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); 4994 node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat");
4980 } else { 4995 } else {
4981 node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name)); 4996 node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)));
4982 #if 0 4997 #if 0
4983 /* Using the transient blist nodes to show the tooltip doesn't quite work yet. */ 4998 /* Using the transient blist nodes to show the tooltip doesn't quite work yet. */
4984 if (!node) 4999 if (!node)
4985 node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); 5000 node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy");
4986 #endif 5001 #endif
4987 } 5002 }
4988 5003
4989 if (node) 5004 if (node)
4990 pidgin_blist_draw_tooltip(node, gtkconv->infopane); 5005 pidgin_blist_draw_tooltip(node, gtkconv->infopane);
4995 static gboolean 5010 static gboolean
4996 pidgin_conv_end_quickfind(PidginConversation *gtkconv) 5011 pidgin_conv_end_quickfind(PidginConversation *gtkconv)
4997 { 5012 {
4998 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); 5013 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL);
4999 5014
5000 gtk_imhtml_search_clear(GTK_IMHTML(gtkconv->imhtml)); 5015 webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(gtkconv->webview));
5001 gtk_widget_hide(gtkconv->quickfind.container); 5016 gtk_widget_hide_all(gtkconv->quickfind.container);
5002 5017
5003 gtk_widget_grab_focus(gtkconv->entry); 5018 gtk_widget_grab_focus(gtkconv->entry);
5004 return TRUE; 5019 return TRUE;
5005 } 5020 }
5006 5021
5007 static gboolean 5022 static gboolean
5008 quickfind_process_input(GtkWidget *entry, GdkEventKey *event, PidginConversation *gtkconv) 5023 quickfind_process_input(GtkWidget *entry, GdkEventKey *event, PidginConversation *gtkconv)
5009 { 5024 {
5010 switch (event->keyval) { 5025 switch (event->keyval) {
5011 case GDK_KEY_Return: 5026 case GDK_Return:
5012 case GDK_KEY_KP_Enter: 5027 case GDK_KP_Enter:
5013 if (gtk_imhtml_search_find(GTK_IMHTML(gtkconv->imhtml), gtk_entry_get_text(GTK_ENTRY(entry)))) { 5028 if (webkit_web_view_search_text(WEBKIT_WEB_VIEW(gtkconv->webview), gtk_entry_get_text(GTK_ENTRY(entry)), FALSE, TRUE, TRUE)) {
5014 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); 5029 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL);
5015 } else { 5030 } else {
5016 GdkColor col; 5031 GdkColor col;
5017 col.red = 0xffff; 5032 col.red = 0xffff;
5018 col.green = 0xafff; 5033 col.green = 0xafff;
5019 col.blue = 0xafff; 5034 col.blue = 0xafff;
5020 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, &col); 5035 gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, &col);
5021 } 5036 }
5022 break; 5037 break;
5023 case GDK_KEY_Escape: 5038 case GDK_Escape:
5024 pidgin_conv_end_quickfind(gtkconv); 5039 pidgin_conv_end_quickfind(gtkconv);
5025 break; 5040 break;
5026 default: 5041 default:
5027 return FALSE; 5042 return FALSE;
5028 } 5043 }
5062 G_CALLBACK(pidgin_conv_end_quickfind), gtkconv); 5077 G_CALLBACK(pidgin_conv_end_quickfind), gtkconv);
5063 } 5078 }
5064 5079
5065 /* }}} */ 5080 /* }}} */
5066 5081
5082 static char *
5083 replace_header_tokens(PurpleConversation *conv, const char *text)
5084 {
5085 PurpleAccount *account = purple_conversation_get_account(conv);
5086 GString *str;
5087 const char *cur = text;
5088 const char *prev = cur;
5089
5090 if (text == NULL || *text == '\0')
5091 return NULL;
5092
5093 str = g_string_new(NULL);
5094 while ((cur = strchr(cur, '%'))) {
5095 const char *replace = NULL;
5096 const char *fin = NULL;
5097
5098 if (g_str_has_prefix(cur, "%chatName%")) {
5099 replace = purple_conversation_get_name(conv);
5100
5101 } else if (g_str_has_prefix(cur, "%sourceName%")) {
5102 replace = purple_account_get_alias(account);
5103 if (replace == NULL)
5104 replace = purple_account_get_username(account);
5105
5106 } else if (g_str_has_prefix(cur, "%destinationName%")) {
5107 PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
5108 if (buddy) {
5109 replace = purple_buddy_get_alias(buddy);
5110 } else {
5111 replace = purple_conversation_get_name(conv);
5112 }
5113
5114 } else if (g_str_has_prefix(cur, "%incomingIconPath%")) {
5115 PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
5116 if (icon)
5117 replace = purple_buddy_icon_get_full_path(icon);
5118
5119 } else if (g_str_has_prefix(cur, "%outgoingIconPath%")) {
5120 replace = purple_account_get_buddy_icon_path(account);
5121
5122 } else if (g_str_has_prefix(cur, "%timeOpened")) {
5123 const char *tmp = cur + strlen("%timeOpened");
5124 char *format = NULL;
5125 if (*tmp == '{') {
5126 const char *end;
5127 tmp++;
5128 end = strstr(tmp, "}%");
5129 if (!end) /* Invalid string */
5130 continue;
5131 format = g_strndup(tmp, end - tmp);
5132 fin = end + 1;
5133 }
5134 replace = purple_utf8_strftime(format ? format : "%X", NULL);
5135 g_free(format);
5136
5137 } else if (g_str_has_prefix(cur, "%dateOpened%")) {
5138 replace = purple_date_format_short(NULL);
5139
5140 } else {
5141 cur++;
5142 continue;
5143 }
5144
5145 /* Here we have a replacement to make */
5146 g_string_append_len(str, prev, cur - prev);
5147 if (replace)
5148 g_string_append(str, replace);
5149
5150 /* And update the pointers */
5151 if (fin) {
5152 prev = cur = fin + 1;
5153 } else {
5154 prev = cur = strchr(cur + 1, '%') + 1;
5155 }
5156 }
5157
5158 /* And wrap it up */
5159 g_string_append(str, prev);
5160 return g_string_free(str, FALSE);
5161 }
5162
5163 static char *
5164 replace_template_tokens(PidginConvTheme *theme, const char *header, const char *footer)
5165 {
5166 GString *str;
5167 const char *text;
5168 char **ms;
5169 char *path;
5170
5171 text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN);
5172 if (text == NULL)
5173 return NULL;
5174
5175 ms = g_strsplit(text, "%@", 6);
5176 if (ms[0] == NULL || ms[1] == NULL || ms[2] == NULL || ms[3] == NULL || ms[4] == NULL || ms[5] == NULL) {
5177 g_strfreev(ms);
5178 return NULL;
5179 }
5180
5181 str = g_string_new(NULL);
5182
5183 g_string_append(str, ms[0]);
5184 g_string_append(str, "file://");
5185 path = pidgin_conversation_theme_get_template_path(theme);
5186 g_string_append(str, path);
5187 g_free(path);
5188
5189 g_string_append(str, ms[1]);
5190
5191 text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS);
5192 g_string_append(str, text);
5193
5194 g_string_append(str, ms[2]);
5195
5196 g_string_append(str, "file://");
5197 path = pidgin_conversation_theme_get_css_path(theme);
5198 g_string_append(str, path);
5199 g_free(path);
5200
5201 g_string_append(str, ms[3]);
5202 if (header)
5203 g_string_append(str, header);
5204 g_string_append(str, ms[4]);
5205 if (footer)
5206 g_string_append(str, footer);
5207 g_string_append(str, ms[5]);
5208
5209 g_strfreev(ms);
5210
5211 return g_string_free(str, FALSE);
5212 }
5213
5214 static void
5215 set_theme_webkit_settings(WebKitWebView *webview, PidginConvTheme *theme)
5216 {
5217 WebKitWebSettings *settings;
5218 const GValue *val;
5219
5220 g_object_get(G_OBJECT(webview), "settings", &settings, NULL);
5221
5222 val = pidgin_conversation_theme_lookup(theme, "DefaultFontFamily", TRUE);
5223 if (val && G_VALUE_HOLDS_STRING(val))
5224 g_object_set(G_OBJECT(settings), "default-font-family", g_value_get_string(val), NULL);
5225
5226 val = pidgin_conversation_theme_lookup(theme, "DefaultFontSize", TRUE);
5227 if (val && G_VALUE_HOLDS_INT(val))
5228 g_object_set(G_OBJECT(settings), "default-font-size", GINT_TO_POINTER(g_value_get_int(val)), NULL);
5229
5230 val = pidgin_conversation_theme_lookup(theme, "DefaultBackgroundIsTransparent", TRUE);
5231 if (val && G_VALUE_HOLDS_BOOLEAN(val))
5232 /* this does not work :( */
5233 webkit_web_view_set_transparent(webview, g_value_get_boolean(val));
5234 }
5235
5236 static void
5237 conv_variant_changed_cb(GObject *gobject, GParamSpec *pspec, gpointer user_data)
5238 {
5239 PidginConversation *gtkconv = user_data;
5240 const char *path;
5241 char *js;
5242
5243 path = pidgin_conversation_theme_get_css_path(PIDGIN_CONV_THEME(gobject));
5244 js = g_strdup_printf("setStylesheet(\"mainStyle\", \"file://%s\");", path);
5245 gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), js);
5246 g_free(js);
5247 }
5248
5067 static GtkWidget * 5249 static GtkWidget *
5068 setup_common_pane(PidginConversation *gtkconv) 5250 setup_common_pane(PidginConversation *gtkconv)
5069 { 5251 {
5070 GtkWidget *vbox, *frame, *imhtml_sw, *event_box; 5252 GtkWidget *vbox, *frame, *webview_sw, *event_box;
5071 GtkCellRenderer *rend; 5253 GtkCellRenderer *rend;
5072 GtkTreePath *path; 5254 GtkTreePath *path;
5073 PurpleConversation *conv = gtkconv->active_conv; 5255 PurpleConversation *conv = gtkconv->active_conv;
5074 PurpleBuddy *buddy; 5256 PurpleBuddy *buddy;
5075 gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT); 5257 gboolean chat = (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT);
5076 int buddyicon_size = 0; 5258 int buddyicon_size = 0;
5259 char *header, *footer;
5260 char *template;
5077 5261
5078 /* Setup the top part of the pane */ 5262 /* Setup the top part of the pane */
5079 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 5263 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
5080 gtk_widget_show(vbox); 5264 gtk_widget_show(vbox);
5081 5265
5161 rend = gtk_cell_renderer_pixbuf_new(); 5345 rend = gtk_cell_renderer_pixbuf_new();
5162 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE); 5346 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE);
5163 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_EMBLEM_COLUMN, NULL); 5347 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_EMBLEM_COLUMN, NULL);
5164 g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL); 5348 g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL);
5165 5349
5166 /* Setup the gtkimhtml widget */ 5350 /* Setup the webkit widget */
5167 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw); 5351 frame = pidgin_create_webview(FALSE, &gtkconv->webview, NULL, &webview_sw);
5168 gtk_widget_set_size_request(gtkconv->imhtml, -1, 0); 5352 gtk_widget_set_size_request(gtkconv->webview, -1, 0);
5353
5354 header = replace_header_tokens(conv,
5355 pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER));
5356 footer = replace_header_tokens(conv,
5357 pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER));
5358 template = replace_template_tokens(gtkconv->theme, header, footer);
5359 g_free(header);
5360 g_free(footer);
5361
5362 if (template != NULL) {
5363 char *basedir;
5364 char *baseuri;
5365
5366 purple_debug_info("webkit", "template: %s\n", template);
5367
5368 set_theme_webkit_settings(WEBKIT_WEB_VIEW(gtkconv->webview), gtkconv->theme);
5369
5370 basedir = pidgin_conversation_theme_get_template_path(gtkconv->theme);
5371 baseuri = g_strdup_printf("file://%s", basedir);
5372 webkit_web_view_load_string(WEBKIT_WEB_VIEW(gtkconv->webview), template, "text/html", "UTF-8", baseuri);
5373
5374 if (chat)
5375 gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), "document.getElementById('Chat').className = 'groupchat'");
5376
5377 g_signal_connect(G_OBJECT(gtkconv->theme), "notify::variant",
5378 G_CALLBACK(conv_variant_changed_cb), gtkconv);
5379
5380 g_free(basedir);
5381 g_free(baseuri);
5382 g_free(template);
5383 }
5384
5169 if (chat) { 5385 if (chat) {
5170 GtkWidget *hpaned; 5386 GtkWidget *hpaned;
5171 5387
5172 /* Add the topic */ 5388 /* Add the topic */
5173 setup_chat_topic(gtkconv, vbox); 5389 setup_chat_topic(gtkconv, vbox);
5181 /* Now add the userlist */ 5397 /* Now add the userlist */
5182 setup_chat_userlist(gtkconv, hpaned); 5398 setup_chat_userlist(gtkconv, hpaned);
5183 } else { 5399 } else {
5184 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); 5400 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
5185 } 5401 }
5186 gtk_widget_show(frame); 5402 gtk_widget_show_all(frame);
5187 5403
5188 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); 5404 gtk_widget_set_name(gtkconv->webview, "pidgin_conv_webview");
5189 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE); 5405 g_object_set_data(G_OBJECT(gtkconv->webview), "gtkconv", gtkconv);
5190 g_object_set_data(G_OBJECT(gtkconv->imhtml), "gtkconv", gtkconv); 5406
5191 5407 g_signal_connect_after(G_OBJECT(gtkconv->webview), "button_press_event",
5192 g_object_set(G_OBJECT(imhtml_sw), "vscrollbar-policy", GTK_POLICY_ALWAYS, NULL);
5193
5194 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
5195 G_CALLBACK(entry_stop_rclick_cb), NULL); 5408 G_CALLBACK(entry_stop_rclick_cb), NULL);
5196 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", 5409 g_signal_connect(G_OBJECT(gtkconv->webview), "key_press_event",
5197 G_CALLBACK(refocus_entry_cb), gtkconv); 5410 G_CALLBACK(refocus_entry_cb), gtkconv);
5198 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", 5411 g_signal_connect(G_OBJECT(gtkconv->webview), "key_release_event",
5199 G_CALLBACK(refocus_entry_cb), gtkconv); 5412 G_CALLBACK(refocus_entry_cb), gtkconv);
5200 5413
5201 pidgin_conv_setup_quickfind(gtkconv, vbox); 5414 pidgin_conv_setup_quickfind(gtkconv, vbox);
5202 5415
5203 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 5416 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
5209 gtk_box_pack_start(GTK_BOX(gtkconv->lower_hbox), frame, TRUE, TRUE, 0); 5422 gtk_box_pack_start(GTK_BOX(gtkconv->lower_hbox), frame, TRUE, TRUE, 0);
5210 gtk_widget_show(frame); 5423 gtk_widget_show(frame);
5211 5424
5212 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); 5425 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
5213 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), 5426 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
5214 purple_account_get_protocol_name(conv->account)); 5427 purple_account_get_protocol_name(purple_conversation_get_account(conv)));
5215 5428
5216 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", 5429 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
5217 G_CALLBACK(entry_popup_menu_cb), gtkconv); 5430 G_CALLBACK(entry_popup_menu_cb), gtkconv);
5218 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 5431 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event",
5219 G_CALLBACK(entry_key_press_cb), gtkconv); 5432 G_CALLBACK(entry_key_press_cb), gtkconv);
5256 PurpleConversation *conv = gtkconv->active_conv; 5469 PurpleConversation *conv = gtkconv->active_conv;
5257 PidginWindow *win = gtkconv->win; 5470 PidginWindow *win = gtkconv->win;
5258 PurpleConversation *c; 5471 PurpleConversation *c;
5259 PurpleAccount *convaccount = purple_conversation_get_account(conv); 5472 PurpleAccount *convaccount = purple_conversation_get_account(conv);
5260 PurpleConnection *gc = purple_account_get_connection(convaccount); 5473 PurpleConnection *gc = purple_account_get_connection(convaccount);
5261 PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL; 5474 PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL;
5262 GdkAtom target = gtk_selection_data_get_target(sd); 5475
5263 const guchar *data = gtk_selection_data_get_data(sd); 5476 if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
5264
5265 if (target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
5266 { 5477 {
5267 PurpleBlistNode *n = NULL; 5478 PurpleBlistNode *n = NULL;
5268 PurpleBuddy *b; 5479 PurpleBuddy *b;
5269 PidginConversation *gtkconv = NULL; 5480 PidginConversation *gtkconv = NULL;
5270 PurpleAccount *buddyaccount; 5481 PurpleAccount *buddyaccount;
5271 const char *buddyname; 5482 const char *buddyname;
5272 5483
5273 n = *(PurpleBlistNode **) data; 5484 n = *(PurpleBlistNode **)sd->data;
5274 5485
5275 if (PURPLE_BLIST_NODE_IS_CONTACT(n)) 5486 if (PURPLE_BLIST_NODE_IS_CONTACT(n))
5276 b = purple_contact_get_priority_buddy((PurpleContact*)n); 5487 b = purple_contact_get_priority_buddy((PurpleContact*)n);
5277 else if (PURPLE_BLIST_NODE_IS_BUDDY(n)) 5488 else if (PURPLE_BLIST_NODE_IS_BUDDY(n))
5278 b = (PurpleBuddy*)n; 5489 b = (PurpleBuddy*)n;
5316 5527
5317 /* Make this conversation the active conversation */ 5528 /* Make this conversation the active conversation */
5318 pidgin_conv_window_switch_gtkconv(win, gtkconv); 5529 pidgin_conv_window_switch_gtkconv(win, gtkconv);
5319 } 5530 }
5320 5531
5321 gtk_drag_finish(dc, TRUE, 5532 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
5322 gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); 5533 }
5323 } 5534 else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE))
5324 else if (target == gdk_atom_intern("application/x-im-contact", FALSE))
5325 { 5535 {
5326 char *protocol = NULL; 5536 char *protocol = NULL;
5327 char *username = NULL; 5537 char *username = NULL;
5328 PurpleAccount *account; 5538 PurpleAccount *account;
5329 PidginConversation *gtkconv; 5539 PidginConversation *gtkconv;
5330 5540
5331 if (pidgin_parse_x_im_contact((const char *) data, FALSE, &account, 5541 if (pidgin_parse_x_im_contact((const char *)sd->data, FALSE, &account,
5332 &protocol, &username, NULL)) 5542 &protocol, &username, NULL))
5333 { 5543 {
5334 if (account == NULL) 5544 if (account == NULL)
5335 { 5545 {
5336 purple_notify_error(win, NULL, 5546 purple_notify_error(win, NULL,
5357 } 5567 }
5358 5568
5359 g_free(username); 5569 g_free(username);
5360 g_free(protocol); 5570 g_free(protocol);
5361 5571
5362 gtk_drag_finish(dc, TRUE, 5572 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
5363 gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); 5573 }
5364 } 5574 else if (sd->target == gdk_atom_intern("text/uri-list", FALSE)) {
5365 else if (target == gdk_atom_intern("text/uri-list", FALSE)) {
5366 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) 5575 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
5367 pidgin_dnd_file_manage(sd, convaccount, purple_conversation_get_name(conv)); 5576 pidgin_dnd_file_manage(sd, convaccount, purple_conversation_get_name(conv));
5368 gtk_drag_finish(dc, TRUE, 5577 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
5369 gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
5370 } 5578 }
5371 else 5579 else
5372 gtk_drag_finish(dc, FALSE, FALSE, t); 5580 gtk_drag_finish(dc, FALSE, FALSE, t);
5373 } 5581 }
5374 5582
5381 }; 5589 };
5382 5590
5383 static PidginConversation * 5591 static PidginConversation *
5384 pidgin_conv_find_gtkconv(PurpleConversation * conv) 5592 pidgin_conv_find_gtkconv(PurpleConversation * conv)
5385 { 5593 {
5386 PurpleBuddy *bud = purple_find_buddy(conv->account, conv->name); 5594 PurpleBuddy *bud = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
5387 PurpleContact *c; 5595 PurpleContact *c;
5388 PurpleBlistNode *cn, *bn; 5596 PurpleBlistNode *cn, *bn;
5389 5597
5390 if (!bud) 5598 if (!bud)
5391 return NULL; 5599 return NULL;
5395 5603
5396 cn = PURPLE_BLIST_NODE(c); 5604 cn = PURPLE_BLIST_NODE(c);
5397 for (bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) { 5605 for (bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) {
5398 PurpleBuddy *b = PURPLE_BUDDY(bn); 5606 PurpleBuddy *b = PURPLE_BUDDY(bn);
5399 PurpleConversation *conv; 5607 PurpleConversation *conv;
5400 if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, b->account))) { 5608 if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(b), purple_buddy_get_account(b)))) {
5401 if (conv->ui_data) 5609 if (PIDGIN_CONVERSATION(conv))
5402 return conv->ui_data; 5610 return PIDGIN_CONVERSATION(conv);
5403 } 5611 }
5404 } 5612 }
5405 5613
5406 return NULL; 5614 return NULL;
5407 } 5615 }
5439 return FALSE; 5647 return FALSE;
5440 } 5648 }
5441 5649
5442 static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv) 5650 static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv)
5443 { 5651 {
5652 /* TODO WEBKIT */
5653 #if 0
5444 static PangoFontDescription *font_desc = NULL; 5654 static PangoFontDescription *font_desc = NULL;
5445 static GdkColor *color = NULL; 5655 static GdkColor *color = NULL;
5446 static gboolean enable = TRUE; 5656 static gboolean enable = TRUE;
5447 5657
5448 if (font_desc == NULL) { 5658 if (font_desc == NULL) {
5469 g_object_set_data(G_OBJECT(widget), "disable-typing-notification", GINT_TO_POINTER(TRUE)); 5679 g_object_set_data(G_OBJECT(widget), "disable-typing-notification", GINT_TO_POINTER(TRUE));
5470 /* or may be 'gtkconv->disable_typing = TRUE;' instead? */ 5680 /* or may be 'gtkconv->disable_typing = TRUE;' instead? */
5471 } 5681 }
5472 5682
5473 g_signal_handlers_disconnect_by_func(G_OBJECT(widget), set_typing_font, gtkconv); 5683 g_signal_handlers_disconnect_by_func(G_OBJECT(widget), set_typing_font, gtkconv);
5684 #endif /* if 0 */
5474 } 5685 }
5475 5686
5476 /************************************************************************** 5687 /**************************************************************************
5477 * Conversation UI operations 5688 * Conversation UI operations
5478 **************************************************************************/ 5689 **************************************************************************/
5479 static void 5690 static void
5480 private_gtkconv_new(PurpleConversation *conv, gboolean hidden) 5691 private_gtkconv_new(PurpleConversation *conv, gboolean hidden)
5481 { 5692 {
5482 PidginConversation *gtkconv; 5693 PidginConversation *gtkconv;
5694 PurpleTheme *theme;
5483 PurpleConversationType conv_type = purple_conversation_get_type(conv); 5695 PurpleConversationType conv_type = purple_conversation_get_type(conv);
5484 GtkWidget *pane = NULL; 5696 GtkWidget *pane = NULL;
5485 GtkWidget *tab_cont; 5697 GtkWidget *tab_cont;
5486 PurpleBlistNode *convnode; 5698 PurpleBlistNode *convnode;
5487 PurpleValue *value;
5488 5699
5489 if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) { 5700 if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) {
5490 conv->ui_data = gtkconv; 5701 purple_conversation_set_ui_data(conv, gtkconv);
5491 if (!g_list_find(gtkconv->convs, conv)) 5702 if (!g_list_find(gtkconv->convs, conv))
5492 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); 5703 gtkconv->convs = g_list_prepend(gtkconv->convs, conv);
5493 pidgin_conv_switch_active_conversation(conv); 5704 pidgin_conv_switch_active_conversation(conv);
5494 return; 5705 return;
5495 } 5706 }
5496 5707
5497 gtkconv = g_new0(PidginConversation, 1); 5708 gtkconv = g_new0(PidginConversation, 1);
5498 conv->ui_data = gtkconv; 5709 purple_conversation_set_ui_data(conv, gtkconv);
5499 gtkconv->active_conv = conv; 5710 gtkconv->active_conv = conv;
5500 gtkconv->convs = g_list_prepend(gtkconv->convs, conv); 5711 gtkconv->convs = g_list_prepend(gtkconv->convs, conv);
5501 gtkconv->send_history = g_list_append(NULL, NULL); 5712 gtkconv->send_history = g_list_append(NULL, NULL);
5502 5713
5503 /* Setup some initial variables. */ 5714 /* Setup some initial variables. */
5504 #if !GTK_CHECK_VERSION(2,12,0) 5715 #if !GTK_CHECK_VERSION(2,12,0)
5505 gtkconv->tooltips = gtk_tooltips_new(); 5716 gtkconv->tooltips = gtk_tooltips_new();
5506 #endif 5717 #endif
5507 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; 5718 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
5508 gtkconv->unseen_count = 0; 5719 gtkconv->unseen_count = 0;
5720 theme = purple_theme_manager_find_theme(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/theme"), "conversation");
5721 if (!theme)
5722 theme = purple_theme_manager_find_theme("Default", "conversation");
5723 gtkconv->theme = PIDGIN_CONV_THEME(g_object_ref(theme));
5724 gtkconv->last_flags = 0;
5509 5725
5510 if (conv_type == PURPLE_CONV_TYPE_IM) { 5726 if (conv_type == PURPLE_CONV_TYPE_IM) {
5511 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); 5727 gtkconv->u.im = g_malloc0(sizeof(PidginImPane));
5512 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { 5728 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) {
5513 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); 5729 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane));
5514 } 5730 }
5515 pane = setup_common_pane(gtkconv); 5731 pane = setup_common_pane(gtkconv);
5516
5517 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml),
5518 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE);
5519 5732
5520 if (pane == NULL) { 5733 if (pane == NULL) {
5521 if (conv_type == PURPLE_CONV_TYPE_CHAT) 5734 if (conv_type == PURPLE_CONV_TYPE_CHAT)
5522 g_free(gtkconv->u.chat); 5735 g_free(gtkconv->u.chat);
5523 else if (conv_type == PURPLE_CONV_TYPE_IM) 5736 else if (conv_type == PURPLE_CONV_TYPE_IM)
5524 g_free(gtkconv->u.im); 5737 g_free(gtkconv->u.im);
5525 5738
5526 g_free(gtkconv); 5739 g_free(gtkconv);
5527 conv->ui_data = NULL; 5740 purple_conversation_set_ui_data(conv, NULL);
5528 return; 5741 return;
5529 } 5742 }
5530 5743
5531 /* Setup drag-and-drop */ 5744 /* Setup drag-and-drop */
5532 gtk_drag_dest_set(pane, 5745 gtk_drag_dest_set(pane,
5537 gtk_drag_dest_set(pane, 5750 gtk_drag_dest_set(pane,
5538 GTK_DEST_DEFAULT_MOTION | 5751 GTK_DEST_DEFAULT_MOTION |
5539 GTK_DEST_DEFAULT_DROP, 5752 GTK_DEST_DEFAULT_DROP,
5540 te, sizeof(te) / sizeof(GtkTargetEntry), 5753 te, sizeof(te) / sizeof(GtkTargetEntry),
5541 GDK_ACTION_COPY); 5754 GDK_ACTION_COPY);
5542 gtk_drag_dest_set(gtkconv->imhtml, 0, 5755 gtk_drag_dest_set(gtkconv->webview, 0,
5543 te, sizeof(te) / sizeof(GtkTargetEntry), 5756 te, sizeof(te) / sizeof(GtkTargetEntry),
5544 GDK_ACTION_COPY); 5757 GDK_ACTION_COPY);
5545 5758
5546 gtk_drag_dest_set(gtkconv->entry, 0, 5759 gtk_drag_dest_set(gtkconv->entry, 0,
5547 te, sizeof(te) / sizeof(GtkTargetEntry), 5760 te, sizeof(te) / sizeof(GtkTargetEntry),
5549 5762
5550 g_signal_connect(G_OBJECT(pane), "button_press_event", 5763 g_signal_connect(G_OBJECT(pane), "button_press_event",
5551 G_CALLBACK(ignore_middle_click), NULL); 5764 G_CALLBACK(ignore_middle_click), NULL);
5552 g_signal_connect(G_OBJECT(pane), "drag_data_received", 5765 g_signal_connect(G_OBJECT(pane), "drag_data_received",
5553 G_CALLBACK(conv_dnd_recv), gtkconv); 5766 G_CALLBACK(conv_dnd_recv), gtkconv);
5554 g_signal_connect(G_OBJECT(gtkconv->imhtml), "drag_data_received", 5767 g_signal_connect(G_OBJECT(gtkconv->webview), "drag_data_received",
5555 G_CALLBACK(conv_dnd_recv), gtkconv); 5768 G_CALLBACK(conv_dnd_recv), gtkconv);
5556 g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received", 5769 g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received",
5557 G_CALLBACK(conv_dnd_recv), gtkconv); 5770 G_CALLBACK(conv_dnd_recv), gtkconv);
5558 5771
5559 g_signal_connect(gtkconv->imhtml, "style-set", G_CALLBACK(set_typing_font), gtkconv); 5772 g_signal_connect(gtkconv->webview, "style-set", G_CALLBACK(set_typing_font), gtkconv);
5560 5773
5561 /* Setup the container for the tab. */ 5774 /* Setup the container for the tab. */
5562 gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 5775 gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
5563 g_object_set_data(G_OBJECT(tab_cont), "PidginConversation", gtkconv); 5776 g_object_set_data(G_OBJECT(tab_cont), "PidginConversation", gtkconv);
5564 gtk_container_set_border_width(GTK_CONTAINER(tab_cont), PIDGIN_HIG_BOX_SPACE); 5777 gtk_container_set_border_width(GTK_CONTAINER(tab_cont), PIDGIN_HIG_BOX_SPACE);
5567 5780
5568 convnode = get_conversation_blist_node(conv); 5781 convnode = get_conversation_blist_node(conv);
5569 if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound")) 5782 if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound"))
5570 gtkconv->make_sound = TRUE; 5783 gtkconv->make_sound = TRUE;
5571 5784
5572 if (convnode != NULL && 5785 if (convnode != NULL) {
5573 (value = g_hash_table_lookup(convnode->settings, "enable-logging")) && 5786 gboolean logging = purple_blist_node_get_bool(convnode, "enable-logging");
5574 purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN) 5787 purple_conversation_set_logging(conv, logging);
5575 {
5576 purple_conversation_set_logging(conv, purple_value_get_boolean(value));
5577 } 5788 }
5578 5789
5579 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar")) 5790 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar"))
5580 gtk_widget_show(gtkconv->toolbar); 5791 gtk_widget_show(gtkconv->toolbar);
5581 else 5792 else
5584 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons")) 5795 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons"))
5585 gtk_widget_show(gtkconv->infopane_hbox); 5796 gtk_widget_show(gtkconv->infopane_hbox);
5586 else 5797 else
5587 gtk_widget_hide(gtkconv->infopane_hbox); 5798 gtk_widget_hide(gtkconv->infopane_hbox);
5588 5799
5589 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),
5590 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps"));
5591 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml),
5592 purple_account_get_protocol_name(conv->account));
5593 5800
5594 g_signal_connect_swapped(G_OBJECT(pane), "focus", 5801 g_signal_connect_swapped(G_OBJECT(pane), "focus",
5595 G_CALLBACK(gtk_widget_grab_focus), 5802 G_CALLBACK(gtk_widget_grab_focus),
5596 gtkconv->entry); 5803 gtkconv->entry);
5597 5804
5600 else 5807 else
5601 pidgin_conv_placement_place(gtkconv); 5808 pidgin_conv_placement_place(gtkconv);
5602 5809
5603 if (nick_colors == NULL) { 5810 if (nick_colors == NULL) {
5604 nbr_nick_colors = NUM_NICK_COLORS; 5811 nbr_nick_colors = NUM_NICK_COLORS;
5605 nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->imhtml)->base[GTK_STATE_NORMAL]); 5812 nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]);
5606 } 5813 }
5607 5814
5608 if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) 5815 if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
5609 pidgin_themes_smiley_themeize_custom(gtkconv->entry); 5816 pidgin_themes_smiley_themeize_custom(gtkconv->entry);
5610 } 5817 }
5611 5818
5612 static void 5819 static void
5613 pidgin_conv_new_hidden(PurpleConversation *conv) 5820 pidgin_conv_new_hidden(PurpleConversation *conv)
5715 g_list_free(gtkconv->send_history); 5922 g_list_free(gtkconv->send_history);
5716 5923
5717 if (gtkconv->attach.timer) { 5924 if (gtkconv->attach.timer) {
5718 g_source_remove(gtkconv->attach.timer); 5925 g_source_remove(gtkconv->attach.timer);
5719 } 5926 }
5927
5928 g_object_disconnect(G_OBJECT(gtkconv->theme), "any_signal::notify",
5929 conv_variant_changed_cb, gtkconv, NULL);
5930 g_object_unref(gtkconv->theme);
5720 5931
5721 g_free(gtkconv); 5932 g_free(gtkconv);
5722 } 5933 }
5723 5934
5724 5935
5743 } 5954 }
5744 5955
5745 purple_conversation_write(conv, who, message, flags, mtime); 5956 purple_conversation_write(conv, who, message, flags, mtime);
5746 } 5957 }
5747 5958
5959 #if 0
5748 static const char * 5960 static const char *
5749 get_text_tag_color(GtkTextTag *tag) 5961 get_text_tag_color(GtkTextTag *tag)
5750 { 5962 {
5751 GdkColor *color = NULL; 5963 GdkColor *color = NULL;
5752 gboolean set = FALSE; 5964 gboolean set = FALSE;
5770 if (event->type == GDK_BUTTON_PRESS 5982 if (event->type == GDK_BUTTON_PRESS
5771 || event->type == GDK_2BUTTON_PRESS) { 5983 || event->type == GDK_2BUTTON_PRESS) {
5772 GdkEventButton *btn_event = (GdkEventButton*) event; 5984 GdkEventButton *btn_event = (GdkEventButton*) event;
5773 PurpleConversation *conv = data; 5985 PurpleConversation *conv = data;
5774 char *buddyname; 5986 char *buddyname;
5775 gchar *name;
5776
5777 g_object_get(G_OBJECT(tag), "name", &name, NULL);
5778 5987
5779 /* strlen("BUDDY " or "HILIT ") == 6 */ 5988 /* strlen("BUDDY " or "HILIT ") == 6 */
5780 g_return_val_if_fail((name != NULL) && (strlen(name) > 6), FALSE); 5989 g_return_val_if_fail((tag->name != NULL)
5781 5990 && (strlen(tag->name) > 6), FALSE);
5782 buddyname = name + 6; 5991
5992 buddyname = (tag->name) + 6;
5783 5993
5784 /* emit chat-nick-clicked signal */ 5994 /* emit chat-nick-clicked signal */
5785 if (event->type == GDK_BUTTON_PRESS) { 5995 if (event->type == GDK_BUTTON_PRESS) {
5786 gint plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( 5996 gint plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1(
5787 pidgin_conversations_get_handle(), "chat-nick-clicked", 5997 pidgin_conversations_get_handle(), "chat-nick-clicked",
5788 data, buddyname, btn_event->button)); 5998 data, buddyname, btn_event->button));
5789 if (plugin_return) { 5999 if (plugin_return)
5790 g_free(name);
5791 return TRUE; 6000 return TRUE;
5792 } 6001 }
5793 } 6002
5794 6003 if (btn_event->button == 1 &&
5795 if (btn_event->button == 1 && event->type == GDK_2BUTTON_PRESS) { 6004 event->type == GDK_2BUTTON_PRESS) {
5796 chat_do_im(PIDGIN_CONVERSATION(conv), buddyname); 6005 chat_do_im(PIDGIN_CONVERSATION(conv), buddyname);
5797 g_free(name);
5798
5799 return TRUE; 6006 return TRUE;
5800 } else if (btn_event->button == 2 && event->type == GDK_2BUTTON_PRESS) { 6007 } else if (btn_event->button == 2
6008 && event->type == GDK_2BUTTON_PRESS) {
5801 chat_do_info(PIDGIN_CONVERSATION(conv), buddyname); 6009 chat_do_info(PIDGIN_CONVERSATION(conv), buddyname);
5802 g_free(name);
5803 6010
5804 return TRUE; 6011 return TRUE;
5805 } else if (btn_event->button == 3 && event->type == GDK_BUTTON_PRESS) { 6012 } else if (btn_event->button == 3
6013 && event->type == GDK_BUTTON_PRESS) {
5806 GtkTextIter start, end; 6014 GtkTextIter start, end;
5807 6015
5808 /* we shouldn't display the popup 6016 /* we shouldn't display the popup
5809 * if the user has selected something: */ 6017 * if the user has selected something: */
5810 if (!gtk_text_buffer_get_selection_bounds( 6018 if (!gtk_text_buffer_get_selection_bounds(
5811 gtk_text_iter_get_buffer(arg2), 6019 gtk_text_iter_get_buffer(arg2),
5812 &start, &end)) { 6020 &start, &end)) {
5813 GtkWidget *menu = NULL; 6021 GtkWidget *menu = NULL;
5814 PurpleConnection *gc = 6022 PurpleConnection *gc =
5815 purple_conversation_get_gc(conv); 6023 purple_conversation_get_connection(conv);
5816 6024
5817 6025
5818 menu = create_chat_menu(conv, buddyname, gc); 6026 menu = create_chat_menu(conv, buddyname, gc);
5819 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, 6027 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
5820 NULL, GTK_WIDGET(imhtml), 6028 NULL, GTK_WIDGET(imhtml),
5821 btn_event->button, 6029 btn_event->button,
5822 btn_event->time); 6030 btn_event->time);
5823 6031
5824 g_free(name);
5825
5826 /* Don't propagate the event any further */ 6032 /* Don't propagate the event any further */
5827 return TRUE; 6033 return TRUE;
5828 } 6034 }
5829 } 6035 }
5830
5831 g_free(name);
5832 } 6036 }
5833 6037
5834 return FALSE; 6038 return FALSE;
5835 } 6039 }
6040 #endif
5836 6041
5837 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, 6042 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag,
5838 gboolean create) 6043 gboolean create)
5839 { 6044 {
6045 /* TODO WEBKIT */
6046 #if 0
5840 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); 6047 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
5841 GtkTextTag *buddytag; 6048 GtkTextTag *buddytag;
5842 gchar *str; 6049 gchar *str;
5843 gboolean highlight = (flag & PURPLE_MESSAGE_NICK); 6050 gboolean highlight = (flag & PURPLE_MESSAGE_NICK);
5844 GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer; 6051 GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer;
5868 } 6075 }
5869 6076
5870 g_free(str); 6077 g_free(str);
5871 6078
5872 return buddytag; 6079 return buddytag;
5873 } 6080 #endif /* if 0 */
5874 6081 return NULL;
6082 }
6083
6084 #if 0
5875 static void pidgin_conv_calculate_newday(PidginConversation *gtkconv, time_t mtime) 6085 static void pidgin_conv_calculate_newday(PidginConversation *gtkconv, time_t mtime)
5876 { 6086 {
5877 struct tm *tm = localtime(&mtime); 6087 struct tm *tm = localtime(&mtime);
5878 6088
5879 tm->tm_hour = tm->tm_min = tm->tm_sec = 0; 6089 tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
5915 6125
5916 g_free(*str); 6126 g_free(*str);
5917 *str = ret; 6127 *str = ret;
5918 #endif 6128 #endif
5919 } 6129 }
6130 #endif
6131
6132 static char *
6133 replace_message_tokens(
6134 const char *text,
6135 PurpleConversation *conv,
6136 const char *name,
6137 const char *alias,
6138 const char *message,
6139 PurpleMessageFlags flags,
6140 time_t mtime)
6141 {
6142 GString *str;
6143 const char *cur = text;
6144 const char *prev = cur;
6145
6146 if (text == NULL)
6147 return g_strdup("");
6148
6149 str = g_string_new(NULL);
6150 while ((cur = strchr(cur, '%'))) {
6151 const char *replace = NULL;
6152 const char *fin = NULL;
6153
6154 if (g_str_has_prefix(cur, "%message%")) {
6155 replace = message;
6156
6157 } else if (g_str_has_prefix(cur, "%messageClasses%")) {
6158 replace = flags & PURPLE_MESSAGE_SEND ? "outgoing" :
6159 flags & PURPLE_MESSAGE_RECV ? "incoming" : "event";
6160
6161 } else if (g_str_has_prefix(cur, "%time")) {
6162 const char *tmp = cur + strlen("%time");
6163 char *format = NULL;
6164 if (*tmp == '{') {
6165 char *end;
6166 tmp++;
6167 end = strstr(tmp, "}%");
6168 if (!end) /* Invalid string */
6169 continue;
6170 format = g_strndup(tmp, end - tmp);
6171 fin = end + 1;
6172 }
6173 replace = purple_utf8_strftime(format ? format : "%X", NULL);
6174 g_free(format);
6175
6176 } else if (g_str_has_prefix(cur, "%shortTime%")) {
6177 replace = purple_utf8_strftime("%H:%M", NULL);
6178
6179 } else if (g_str_has_prefix(cur, "%userIconPath%")) {
6180 if (flags & PURPLE_MESSAGE_SEND) {
6181 if (purple_account_get_bool(purple_conversation_get_account(conv), "use-global-buddyicon", TRUE)) {
6182 replace = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon");
6183 } else {
6184 PurpleStoredImage *img = purple_buddy_icons_find_account_icon(purple_conversation_get_account(conv));
6185 replace = purple_imgstore_get_filename(img);
6186 }
6187 if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) {
6188 replace = g_build_filename("Outgoing", "buddy_icon.png", NULL);
6189 }
6190 } else if (flags & PURPLE_MESSAGE_RECV) {
6191 PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
6192 if (icon)
6193 replace = purple_buddy_icon_get_full_path(icon);
6194 if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) {
6195 replace = g_build_filename("Incoming", "buddy_icon.png", NULL);
6196 }
6197 }
6198
6199 } else if (g_str_has_prefix(cur, "%senderScreenName%")) {
6200 replace = name;
6201
6202 } else if (g_str_has_prefix(cur, "%sender%")) {
6203 replace = alias;
6204
6205 } else if (g_str_has_prefix(cur, "%service%")) {
6206 replace = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6207
6208 } else if (g_str_has_prefix(cur, "%messageDirection%")) {
6209 replace = purple_markup_is_rtl(message) ? "rtl" : "ltr";
6210
6211 } else {
6212 cur++;
6213 continue;
6214 }
6215
6216 /* Here we have a replacement to make */
6217 g_string_append_len(str, prev, cur - prev);
6218 if (replace)
6219 g_string_append(str, replace);
6220
6221 /* And update the pointers */
6222 if (fin) {
6223 prev = cur = fin + 1;
6224 } else {
6225 prev = cur = strchr(cur + 1, '%') + 1;
6226 }
6227
6228 }
6229
6230 /* And wrap it up */
6231 g_string_append(str, prev);
6232
6233 return g_string_free(str, FALSE);
6234 }
5920 6235
5921 static void 6236 static void
5922 pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias, 6237 pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias,
5923 const char *message, PurpleMessageFlags flags, 6238 const char *message, PurpleMessageFlags flags,
5924 time_t mtime) 6239 time_t mtime)
5925 { 6240 {
5926 PidginConversation *gtkconv; 6241 PidginConversation *gtkconv;
5927 PurpleConnection *gc; 6242 PurpleConnection *gc;
5928 PurpleAccount *account; 6243 PurpleAccount *account;
6244 #if 0
5929 int gtk_font_options = 0; 6245 int gtk_font_options = 0;
5930 int gtk_font_options_all = 0; 6246 int gtk_font_options_all = 0;
5931 int max_scrollback_lines;
5932 int line_count;
5933 char buf2[BUF_LONG]; 6247 char buf2[BUF_LONG];
5934 gboolean show_date; 6248 gboolean show_date;
5935 char *mdate; 6249 char *mdate;
5936 char *str; 6250 char *str;
5937 char *with_font_tag; 6251 char *with_font_tag;
5938 char *sml_attrib = NULL; 6252 char *sml_attrib = NULL;
6253 #endif
5939 size_t length; 6254 size_t length;
5940 PurpleConversationType type; 6255 PurpleConversationType type;
5941 char *displaying; 6256 char *displaying;
5942 gboolean plugin_return; 6257 gboolean plugin_return;
5943 char *bracket; 6258 #if 0
5944 int tag_count = 0;
5945 gboolean is_rtl_message = FALSE; 6259 gboolean is_rtl_message = FALSE;
6260 #endif
6261
6262 const char *message_html;
6263 char *msg;
6264 char *escape;
6265 char *script;
6266 char *smileyed;
6267 PurpleMessageFlags old_flags;
6268 const char *func = "appendMessage";
5946 6269
5947 g_return_if_fail(conv != NULL); 6270 g_return_if_fail(conv != NULL);
5948 gtkconv = PIDGIN_CONVERSATION(conv); 6271 gtkconv = PIDGIN_CONVERSATION(conv);
5949 g_return_if_fail(gtkconv != NULL); 6272 g_return_if_fail(gtkconv != NULL);
5950 6273
5997 g_free(displaying); 6320 g_free(displaying);
5998 return; 6321 return;
5999 } 6322 }
6000 length = strlen(displaying) + 1; 6323 length = strlen(displaying) + 1;
6001 6324
6002 /* Awful hack to work around GtkIMHtml's inefficient rendering of messages with lots of formatting changes. 6325 old_flags = gtkconv->last_flags;
6003 * If a message has over 100 '<' characters, strip formatting before appending it. Hopefully nobody actually 6326 if ((flags & PURPLE_MESSAGE_SEND) && (old_flags & PURPLE_MESSAGE_SEND)) {
6004 * needs that much formatting, anyway. 6327 message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT);
6005 */ 6328 func = "appendNextMessage";
6006 for (bracket = strchr(displaying, '<'); bracket && *(bracket + 1); bracket = strchr(bracket + 1, '<')) 6329 } else if (flags & PURPLE_MESSAGE_SEND) {
6007 tag_count++; 6330 message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT);
6008 6331 } else if ((flags & PURPLE_MESSAGE_RECV) && (old_flags & PURPLE_MESSAGE_RECV)) {
6009 if (tag_count > 100) { 6332 message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT);
6010 char *tmp = displaying; 6333 func = "appendNextMessage";
6011 displaying = purple_markup_strip_html(tmp); 6334 } else if (flags & PURPLE_MESSAGE_RECV) {
6012 g_free(tmp); 6335 message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT);
6013 } 6336 } else {
6014 6337 message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS);
6015 line_count = gtk_text_buffer_get_line_count( 6338 }
6016 gtk_text_view_get_buffer(GTK_TEXT_VIEW( 6339 gtkconv->last_flags = flags;
6017 gtkconv->imhtml))); 6340
6018 6341 smileyed = smiley_parse_markup(message, purple_account_get_protocol_id(account));
6019 max_scrollback_lines = purple_prefs_get_int( 6342 msg = replace_message_tokens(message_html, conv, name, alias, smileyed, flags, mtime);
6020 PIDGIN_PREFS_ROOT "/conversations/scrollback_lines"); 6343 escape = gtk_webview_quote_js_string(msg);
6021 /* If we're sitting at more than 100 lines more than the 6344 script = g_strdup_printf("%s(%s)", func, escape);
6022 max scrollback, trim down to max scrollback */ 6345
6023 if (max_scrollback_lines > 0 6346 purple_debug_info("webkit", "JS: %s\n", script);
6024 && line_count > (max_scrollback_lines + 100)) { 6347 gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), script);
6025 GtkTextBuffer *text_buffer = gtk_text_view_get_buffer( 6348
6026 GTK_TEXT_VIEW(gtkconv->imhtml)); 6349 g_free(script);
6027 GtkTextIter start, end; 6350 g_free(smileyed);
6028 6351 g_free(msg);
6029 gtk_text_buffer_get_start_iter(text_buffer, &start); 6352 g_free(escape);
6030 gtk_text_buffer_get_iter_at_line(text_buffer, &end, 6353
6031 (line_count - max_scrollback_lines)); 6354 #if 0
6032 gtk_imhtml_delete(GTK_IMHTML(gtkconv->imhtml), &start, &end); 6355 /* if the buffer is not empty add a <br> */
6033 } 6356 if (!gtk_webview_is_empty(GTK_WEBVIEW(gtkconv->webview)))
6034 6357 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<br />");
6035 if (type == PURPLE_CONV_TYPE_CHAT)
6036 {
6037 /* Create anchor for user */
6038 GtkTextIter iter;
6039 char *tmp = g_strconcat("user:", name, NULL);
6040
6041 gtk_text_buffer_get_end_iter(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)), &iter);
6042 gtk_text_buffer_create_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)),
6043 tmp, &iter, TRUE);
6044 g_free(tmp);
6045 }
6046
6047 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling"))
6048 gtk_font_options_all |= GTK_IMHTML_USE_SMOOTHSCROLLING;
6049
6050 if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml))))
6051 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", gtk_font_options_all | GTK_IMHTML_NO_SCROLL);
6052 6358
6053 /* First message in a conversation. */ 6359 /* First message in a conversation. */
6054 if (gtkconv->newday == 0) 6360 if (gtkconv->newday == 0)
6055 pidgin_conv_calculate_newday(gtkconv, mtime); 6361 pidgin_conv_calculate_newday(gtkconv, mtime);
6056 6362
6089 if ((flags & PURPLE_MESSAGE_RECV) && 6395 if ((flags & PURPLE_MESSAGE_RECV) &&
6090 !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting")) 6396 !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting"))
6091 gtk_font_options |= GTK_IMHTML_NO_COLOURS | GTK_IMHTML_NO_FONTS | GTK_IMHTML_NO_SIZES | GTK_IMHTML_NO_FORMATTING; 6397 gtk_font_options |= GTK_IMHTML_NO_COLOURS | GTK_IMHTML_NO_FONTS | GTK_IMHTML_NO_SIZES | GTK_IMHTML_NO_FORMATTING;
6092 6398
6093 /* this is gonna crash one day, I can feel it. */ 6399 /* this is gonna crash one day, I can feel it. */
6094 if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(conv->account)))->options & 6400 if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(purple_conversation_get_account(conv))))->options &
6095 OPT_PROTO_USE_POINTSIZE) { 6401 OPT_PROTO_USE_POINTSIZE) {
6096 gtk_font_options |= GTK_IMHTML_USE_POINTSIZE; 6402 gtk_font_options |= GTK_IMHTML_USE_POINTSIZE;
6097 } 6403 }
6098 6404
6099 if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) 6405 if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY))
6100 { 6406 {
6101 /* We want to see our own smileys. Need to revert it after send*/ 6407 /* We want to see our own smileys. Need to revert it after send*/
6102 pidgin_themes_smiley_themeize_custom(gtkconv->imhtml); 6408 pidgin_themes_smiley_themeize_custom(gtkconv->webview);
6103 } 6409 }
6104 6410
6105 /* TODO: These colors should not be hardcoded so log.c can use them */ 6411 /* TODO: These colors should not be hardcoded so log.c can use them */
6106 if (flags & PURPLE_MESSAGE_RAW) { 6412 if (flags & PURPLE_MESSAGE_RAW) {
6107 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, gtk_font_options_all); 6413 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), message);
6108 } else if (flags & PURPLE_MESSAGE_SYSTEM) { 6414 } else if (flags & PURPLE_MESSAGE_SYSTEM) {
6109 g_snprintf(buf2, sizeof(buf2), 6415 g_snprintf(buf2, sizeof(buf2),
6110 "<FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT>", 6416 "<font %s><font size=\"2\"><span class='timestamp'>%s</span></font><b>%s</b></font>",
6111 sml_attrib ? sml_attrib : "", mdate, displaying); 6417 sml_attrib ? sml_attrib : "", mdate, displaying);
6112 6418
6113 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); 6419 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
6114 6420
6115 } else if (flags & PURPLE_MESSAGE_ERROR) { 6421 } else if (flags & PURPLE_MESSAGE_ERROR) {
6116 g_snprintf(buf2, sizeof(buf2), 6422 g_snprintf(buf2, sizeof(buf2),
6117 "<FONT COLOR=\"#ff0000\"><FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT></FONT>", 6423 "<font color=\"#ff0000\"><font %s><font size=\"2\"><span class='timestamp'>%s</span> </font><b>%s</b></font></font>",
6118 sml_attrib ? sml_attrib : "", mdate, displaying); 6424 sml_attrib ? sml_attrib : "", mdate, displaying);
6119 6425
6120 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); 6426 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
6121 6427
6122 } else if (flags & PURPLE_MESSAGE_NO_LOG) { 6428 } else if (flags & PURPLE_MESSAGE_NO_LOG) {
6123 g_snprintf(buf2, BUF_LONG, 6429 g_snprintf(buf2, BUF_LONG,
6124 "<B><FONT %s COLOR=\"#777777\">%s</FONT></B>", 6430 "<b><font %s color=\"#777777\">%s</font></b>",
6125 sml_attrib ? sml_attrib : "", displaying); 6431 sml_attrib ? sml_attrib : "", displaying);
6126 6432
6127 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); 6433 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
6128 } else { 6434 } else {
6129 char *new_message = g_memdup(displaying, length); 6435 char *new_message = g_memdup(displaying, length);
6130 char *alias_escaped = (alias ? g_markup_escape_text(alias, strlen(alias)) : g_strdup("")); 6436 char *alias_escaped = (alias ? g_markup_escape_text(alias, strlen(alias)) : g_strdup(""));
6131 /* The initial offset is to deal with 6437 /* The initial offset is to deal with
6132 * escaped entities making the string longer */ 6438 * escaped entities making the string longer */
6133 int tag_start_offset = 0; 6439 int tag_start_offset = 0;
6134 int tag_end_offset = 0; 6440 int tag_end_offset = 0;
6135 const char *tagname = NULL; 6441 const char *tagname = NULL;
6136
6137 GtkTextIter start, end;
6138 GtkTextMark *mark;
6139 GtkTextTag *tag;
6140 GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer;
6141 6442
6142 /* Enforce direction on alias */ 6443 /* Enforce direction on alias */
6143 if (is_rtl_message) 6444 if (is_rtl_message)
6144 str_embed_direction_chars(&alias_escaped); 6445 str_embed_direction_chars(&alias_escaped);
6145 6446
6197 } 6498 }
6198 } 6499 }
6199 6500
6200 g_free(alias_escaped); 6501 g_free(alias_escaped);
6201 6502
6503 /* TODO WEBKIT */
6504 #if 0
6202 if (tagname) 6505 if (tagname)
6203 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname); 6506 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname);
6204 else 6507 else
6205 tag = get_buddy_tag(conv, name, flags, TRUE); 6508 tag = get_buddy_tag(conv, name, flags, TRUE);
6206 6509
6207 if (GTK_IMHTML(gtkconv->imhtml)->show_comments) { 6510 if (GTK_IMHTML(gtkconv->imhtml)->show_comments) {
6511 {
6208 /* The color for the timestamp has to be set in the font-tags, unfortunately. 6512 /* The color for the timestamp has to be set in the font-tags, unfortunately.
6209 * Applying the nick-tag to timestamps would work, but that can make it 6513 * Applying the nick-tag to timestamps would work, but that can make it
6210 * bold. I thought applying the "comment" tag again, which has "weight" set 6514 * bold. I thought applying the "comment" tag again, which has "weight" set
6211 * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So 6515 * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So
6212 * this will have to do. I don't terribly like it. -- sadrul */ 6516 * this will have to do. I don't terribly like it. -- sadrul */
6213 const char *color = get_text_tag_color(tag); 6517 /* const char *color = get_text_tag_color(tag); */
6214 g_snprintf(buf2, BUF_LONG, "<FONT %s%s%s SIZE=\"2\"><!--%s --></FONT>", 6518 g_snprintf(buf2, BUF_LONG, "<FONT %s%s%s SIZE=\"2\"><!--%s --></FONT>",
6215 color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate); 6519 color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate);
6216 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); 6520 gtk_webview_append_html (GTK_WEBVIEW(gtkconv->webview), buf2);
6217 } 6521 }
6218 6522 #endif /* if 0 */
6219 gtk_text_buffer_get_end_iter(buffer, &end); 6523 g_snprintf(buf2, BUF_LONG, "<font %s>%s</font> ", sml_attrib ? sml_attrib : "", str);
6220 mark = gtk_text_buffer_create_mark(buffer, NULL, &end, TRUE); 6524 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
6221
6222 g_snprintf(buf2, BUF_LONG, "<FONT %s>%s</FONT> ", sml_attrib ? sml_attrib : "", str);
6223 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL);
6224
6225 gtk_text_buffer_get_end_iter(buffer, &end);
6226 gtk_text_buffer_get_iter_at_mark(buffer, &start, mark);
6227 gtk_text_buffer_apply_tag(buffer, tag, &start, &end);
6228 gtk_text_buffer_delete_mark(buffer, mark);
6229 6525
6230 g_free(str); 6526 g_free(str);
6231 6527
6232 if(gc){ 6528 if (gc) {
6233 char *pre = g_strdup_printf("<font %s>", sml_attrib ? sml_attrib : ""); 6529 char *pre = g_strdup_printf("<font %s>", sml_attrib ? sml_attrib : "");
6234 char *post = "</font>"; 6530 char *post = "</font>";
6235 int pre_len = strlen(pre); 6531 with_font_tag = g_strdup_printf("%s%s%s", pre, new_message, post);
6236 int post_len = strlen(post);
6237
6238 with_font_tag = g_malloc(length + pre_len + post_len + 1);
6239
6240 strcpy(with_font_tag, pre);
6241 memcpy(with_font_tag + pre_len, new_message, length);
6242 strcpy(with_font_tag + pre_len + length, post);
6243
6244 length += pre_len + post_len;
6245 g_free(pre); 6532 g_free(pre);
6246 } else 6533 } else
6247 with_font_tag = g_memdup(new_message, length); 6534 with_font_tag = g_memdup(new_message, length);
6248 6535
6249 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), 6536 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview),
6250 with_font_tag, gtk_font_options | gtk_font_options_all); 6537 with_font_tag);
6251 6538
6252 g_free(with_font_tag); 6539 g_free(with_font_tag);
6253 g_free(new_message); 6540 g_free(new_message);
6254 } 6541 }
6255 6542
6256 g_free(mdate); 6543 g_free(mdate);
6257 g_free(sml_attrib); 6544 g_free(sml_attrib);
6545
6546 #endif
6258 6547
6259 /* Tab highlighting stuff */ 6548 /* Tab highlighting stuff */
6260 if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv)) 6549 if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv))
6261 { 6550 {
6262 PidginUnseenState unseen = PIDGIN_UNSEEN_NONE; 6551 PidginUnseenState unseen = PIDGIN_UNSEEN_NONE;
6272 unseen = PIDGIN_UNSEEN_TEXT; 6561 unseen = PIDGIN_UNSEEN_TEXT;
6273 6562
6274 gtkconv_set_unseen(gtkconv, unseen); 6563 gtkconv_set_unseen(gtkconv, unseen);
6275 } 6564 }
6276 6565
6277 if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) 6566 #if 0
6567 if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY))
6278 { 6568 {
6279 /* Restore the smiley-data */ 6569 /* Restore the smiley-data */
6280 pidgin_themes_smiley_themeize(gtkconv->imhtml); 6570 pidgin_themes_smiley_themeize(gtkconv->webview);
6281 } 6571 }
6572 #endif
6282 6573
6283 purple_signal_emit(pidgin_conversations_get_handle(), 6574 purple_signal_emit(pidgin_conversations_get_handle(),
6284 (type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"), 6575 (type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"),
6285 account, name, displaying, conv, flags); 6576 account, name, displaying, conv, flags);
6286 g_free(displaying); 6577 g_free(displaying);
6287 update_typing_message(gtkconv, NULL); 6578 update_typing_message(gtkconv, NULL);
6288 } 6579 }
6289 6580
6290 static gboolean get_iter_from_chatbuddy(PurpleConvChatBuddy *cb, GtkTreeIter *iter) 6581 static gboolean get_iter_from_chatbuddy(PurpleConvChatBuddy *cb, GtkTreeIter *iter)
6291 { 6582 {
6292 GtkTreeRowReference *ref = cb->ui_data; 6583 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
6293 GtkTreePath *path; 6584 GtkTreePath *path;
6294 GtkTreeModel *model; 6585 GtkTreeModel *model;
6295 6586
6296 if (!ref) 6587 if (!ref)
6297 return FALSE; 6588 return FALSE;
6371 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 6662 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
6372 6663
6373 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 6664 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
6374 return; 6665 return;
6375 6666
6376 old_cbuddy = purple_conv_chat_cb_find(chat, old_name);
6377 if (get_iter_from_chatbuddy(old_cbuddy, &iter)) {
6378 GtkTreeRowReference *ref = old_cbuddy->ui_data;
6379
6380 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
6381 gtk_tree_row_reference_free(ref);
6382 old_cbuddy->ui_data = NULL;
6383 }
6384
6385 if ((tag = get_buddy_tag(conv, old_name, 0, FALSE))) 6667 if ((tag = get_buddy_tag(conv, old_name, 0, FALSE)))
6386 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL); 6668 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
6387 if ((tag = get_buddy_tag(conv, old_name, PURPLE_MESSAGE_NICK, FALSE))) 6669 if ((tag = get_buddy_tag(conv, old_name, PURPLE_MESSAGE_NICK, FALSE)))
6388 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL); 6670 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
6389 6671
6672 old_cbuddy = purple_conv_chat_cb_find(chat, old_name);
6390 if (!old_cbuddy) 6673 if (!old_cbuddy)
6391 return; 6674 return;
6675
6676 if (get_iter_from_chatbuddy(old_cbuddy, &iter)) {
6677 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(old_cbuddy);
6678
6679 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
6680 gtk_tree_row_reference_free(ref);
6681 purple_conv_chat_cb_set_ui_data(old_cbuddy, NULL);
6682 }
6392 6683
6393 g_return_if_fail(new_alias != NULL); 6684 g_return_if_fail(new_alias != NULL);
6394 6685
6395 new_cbuddy = purple_conv_chat_cb_find(chat, new_name); 6686 new_cbuddy = purple_conv_chat_cb_find(chat, new_name);
6396 6687
6471 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 6762 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
6472 return; 6763 return;
6473 6764
6474 cbuddy = purple_conv_chat_cb_find(chat, user); 6765 cbuddy = purple_conv_chat_cb_find(chat, user);
6475 if (get_iter_from_chatbuddy(cbuddy, &iter)) { 6766 if (get_iter_from_chatbuddy(cbuddy, &iter)) {
6476 GtkTreeRowReference *ref = cbuddy->ui_data; 6767 GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cbuddy);
6477 gtk_list_store_remove(GTK_LIST_STORE(model), &iter); 6768 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
6478 gtk_tree_row_reference_free(ref); 6769 gtk_tree_row_reference_free(ref);
6479 cbuddy->ui_data = NULL; 6770 purple_conv_chat_cb_set_ui_data(cbuddy, NULL);
6480 } 6771 }
6481 6772
6482 if (cbuddy) 6773 if (cbuddy)
6483 add_chat_buddy_common(conv, cbuddy, NULL); 6774 add_chat_buddy_common(conv, cbuddy, NULL);
6484 } 6775 }
6521 6812
6522 return TRUE; 6813 return TRUE;
6523 } 6814 }
6524 6815
6525 static gboolean 6816 static gboolean
6817 add_custom_smiley_for_webview(GtkWebView *webview, const char *sml, const char *smile)
6818 {
6819 /* TODO WEBKIT: Smileys need to be added to webkit stuff */
6820 return TRUE;
6821 }
6822
6823 static gboolean
6526 pidgin_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, gboolean remote) 6824 pidgin_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, gboolean remote)
6527 { 6825 {
6528 PidginConversation *gtkconv; 6826 PidginConversation *gtkconv;
6529 struct smiley_list *list; 6827 struct smiley_list *list;
6530 const char *sml = NULL, *conv_sml; 6828 const char *sml = NULL, *conv_sml;
6537 if (pidgin_themes_smileys_disabled()) 6835 if (pidgin_themes_smileys_disabled())
6538 return FALSE; 6836 return FALSE;
6539 6837
6540 /* If possible add this smiley to the current theme. 6838 /* If possible add this smiley to the current theme.
6541 * The addition is only temporary: custom smilies aren't saved to disk. */ 6839 * The addition is only temporary: custom smilies aren't saved to disk. */
6542 conv_sml = purple_account_get_protocol_name(conv->account); 6840 conv_sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6543 gtkconv = PIDGIN_CONVERSATION(conv); 6841 gtkconv = PIDGIN_CONVERSATION(conv);
6544 6842
6545 for (list = (struct smiley_list *)current_smiley_theme->list; list; list = list->next) { 6843 for (list = (struct smiley_list *)current_smiley_theme->list; list; list = list->next) {
6546 if (!strcmp(list->sml, conv_sml)) { 6844 if (!strcmp(list->sml, conv_sml)) {
6547 sml = list->sml; 6845 sml = list->sml;
6548 break; 6846 break;
6549 } 6847 }
6550 } 6848 }
6551 6849
6552 if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->imhtml), sml, smile)) 6850 if (!add_custom_smiley_for_webview(GTK_WEBVIEW(gtkconv->webview), sml, smile))
6553 return FALSE; 6851 return FALSE;
6554 6852
6555 if (!remote) /* If it's a local custom smiley, then add it for the entry */ 6853 if (!remote) /* If it's a local custom smiley, then add it for the entry */
6556 if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->entry), sml, smile)) 6854 if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->entry), sml, smile))
6557 return FALSE; 6855 return FALSE;
6561 6859
6562 static void 6860 static void
6563 pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile, 6861 pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile,
6564 const guchar *data, gsize size) 6862 const guchar *data, gsize size)
6565 { 6863 {
6864 /* TODO WEBKIT */
6865 #if 0
6566 PidginConversation *gtkconv; 6866 PidginConversation *gtkconv;
6567 GtkIMHtmlSmiley *smiley; 6867 GtkIMHtmlSmiley *smiley;
6568 const char *sml; 6868 const char *sml;
6569 GError *error = NULL; 6869 GError *error = NULL;
6570 6870
6571 sml = purple_account_get_protocol_name(conv->account); 6871 sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6572 gtkconv = PIDGIN_CONVERSATION(conv); 6872 gtkconv = PIDGIN_CONVERSATION(conv);
6573 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); 6873 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile);
6574 6874
6575 if (!smiley) 6875 if (!smiley)
6576 return; 6876 return;
6582 if (!smiley->loader) 6882 if (!smiley->loader)
6583 return; 6883 return;
6584 6884
6585 if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) { 6885 if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) {
6586 purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() " 6886 purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() "
6587 "failed with size=%zu: %s\n", size, 6887 "failed with size=%" G_GSIZE_FORMAT ": %s\n", size,
6588 error ? error->message : "(no error message)"); 6888 error ? error->message : "(no error message)");
6589 if (error) 6889 if (error)
6590 g_error_free(error); 6890 g_error_free(error);
6591 /* We must stop using the GdkPixbufLoader because trying to load 6891 /* We must stop using the GdkPixbufLoader because trying to load
6592 certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return 6892 certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return
6595 But we also don't want to set smiley->loader to NULL because our 6895 But we also don't want to set smiley->loader to NULL because our
6596 code might expect it to be set. So create a new loader. */ 6896 code might expect it to be set. So create a new loader. */
6597 g_object_unref(G_OBJECT(smiley->loader)); 6897 g_object_unref(G_OBJECT(smiley->loader));
6598 smiley->loader = gdk_pixbuf_loader_new(); 6898 smiley->loader = gdk_pixbuf_loader_new();
6599 } 6899 }
6900 #endif /* if 0 */
6600 } 6901 }
6601 6902
6602 static void 6903 static void
6603 pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile) 6904 pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile)
6604 { 6905 {
6906 /* TODO WEBKIT */
6907 #if 0
6605 PidginConversation *gtkconv; 6908 PidginConversation *gtkconv;
6606 GtkIMHtmlSmiley *smiley; 6909 GtkIMHtmlSmiley *smiley;
6607 const char *sml; 6910 const char *sml;
6608 GError *error = NULL; 6911 GError *error = NULL;
6609 6912
6610 g_return_if_fail(conv != NULL); 6913 g_return_if_fail(conv != NULL);
6611 g_return_if_fail(smile != NULL); 6914 g_return_if_fail(smile != NULL);
6612 6915
6613 sml = purple_account_get_protocol_name(conv->account); 6916 sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6614 gtkconv = PIDGIN_CONVERSATION(conv); 6917 gtkconv = PIDGIN_CONVERSATION(conv);
6615 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); 6918 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile);
6616 6919
6617 if (!smiley) 6920 if (!smiley)
6618 return; 6921 return;
6636 to set smiley->loader to NULL because our code might expect it 6939 to set smiley->loader to NULL because our code might expect it
6637 to be set. So create a new loader. */ 6940 to be set. So create a new loader. */
6638 g_object_unref(G_OBJECT(smiley->loader)); 6941 g_object_unref(G_OBJECT(smiley->loader));
6639 smiley->loader = gdk_pixbuf_loader_new(); 6942 smiley->loader = gdk_pixbuf_loader_new();
6640 } 6943 }
6944 #endif /* if 0 */
6641 } 6945 }
6642 6946
6643 static void 6947 static void
6644 pidgin_conv_send_confirm(PurpleConversation *conv, const char *message) 6948 pidgin_conv_send_confirm(PurpleConversation *conv, const char *message)
6645 { 6949 {
6663 GdkPixbuf *window_icon = NULL; 6967 GdkPixbuf *window_icon = NULL;
6664 GtkIMHtmlButtons buttons; 6968 GtkIMHtmlButtons buttons;
6665 PurpleAccount *account; 6969 PurpleAccount *account;
6666 6970
6667 win = pidgin_conv_get_window(gtkconv); 6971 win = pidgin_conv_get_window(gtkconv);
6668 gc = purple_conversation_get_gc(conv); 6972 gc = purple_conversation_get_connection(conv);
6669 account = purple_conversation_get_account(conv); 6973 account = purple_conversation_get_account(conv);
6670 6974
6671 if (gc != NULL) 6975 if (gc != NULL)
6672 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 6976 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
6673 6977
6674 if (win->menu.send_to != NULL) 6978 if (win->menu.send_to != NULL)
6675 update_send_to_selection(win); 6979 update_send_to_selection(win);
6676 6980
6677 /* 6981 /*
6686 /* Show stuff that applies to IMs, hide stuff that applies to chats */ 6990 /* Show stuff that applies to IMs, hide stuff that applies to chats */
6687 6991
6688 /* Deal with menu items */ 6992 /* Deal with menu items */
6689 gtk_action_set_visible(win->menu.view_log, TRUE); 6993 gtk_action_set_visible(win->menu.view_log, TRUE);
6690 gtk_action_set_visible(win->menu.send_file, TRUE); 6994 gtk_action_set_visible(win->menu.send_file, TRUE);
6691 gtk_action_set_visible(GTK_ACTION(g_object_get_data(G_OBJECT(win->window), "get_attention")), TRUE); 6995 gtk_action_set_visible(win->menu.get_attention, TRUE);
6692 gtk_action_set_visible(win->menu.add_pounce, TRUE); 6996 gtk_action_set_visible(win->menu.add_pounce, TRUE);
6693 gtk_action_set_visible(win->menu.get_info, TRUE); 6997 gtk_action_set_visible(win->menu.get_info, TRUE);
6694 gtk_action_set_visible(win->menu.invite, FALSE); 6998 gtk_action_set_visible(win->menu.invite, FALSE);
6695 gtk_action_set_visible(win->menu.alias, TRUE); 6999 gtk_action_set_visible(win->menu.alias, TRUE);
6696 if (purple_privacy_check(account, purple_conversation_get_name(conv))) { 7000 if (purple_privacy_check(account, purple_conversation_get_name(conv))) {
6715 /* Show stuff that applies to Chats, hide stuff that applies to IMs */ 7019 /* Show stuff that applies to Chats, hide stuff that applies to IMs */
6716 7020
6717 /* Deal with menu items */ 7021 /* Deal with menu items */
6718 gtk_action_set_visible(win->menu.view_log, TRUE); 7022 gtk_action_set_visible(win->menu.view_log, TRUE);
6719 gtk_action_set_visible(win->menu.send_file, FALSE); 7023 gtk_action_set_visible(win->menu.send_file, FALSE);
6720 gtk_action_set_visible(g_object_get_data(G_OBJECT(win->window), "get_attention"), FALSE); 7024 gtk_action_set_visible(win->menu.get_attention, FALSE);
6721 gtk_action_set_visible(win->menu.add_pounce, FALSE); 7025 gtk_action_set_visible(win->menu.add_pounce, FALSE);
6722 gtk_action_set_visible(win->menu.get_info, FALSE); 7026 gtk_action_set_visible(win->menu.get_info, FALSE);
6723 gtk_action_set_visible(win->menu.invite, TRUE); 7027 gtk_action_set_visible(win->menu.invite, TRUE);
6724 gtk_action_set_visible(win->menu.alias, TRUE); 7028 gtk_action_set_visible(win->menu.alias, TRUE);
6725 gtk_action_set_visible(win->menu.block, FALSE); 7029 gtk_action_set_visible(win->menu.block, FALSE);
6745 */ 7049 */
6746 if ((gc != NULL) && 7050 if ((gc != NULL) &&
6747 ((purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) || 7051 ((purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) ||
6748 !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) )) 7052 !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) ))
6749 { 7053 {
7054 PurpleConnectionFlags features = purple_conversation_get_features(conv);
6750 /* Account is online */ 7055 /* Account is online */
6751 /* Deal with the toolbar */ 7056 /* Deal with the toolbar */
6752 if (conv->features & PURPLE_CONNECTION_HTML) 7057 if (features & PURPLE_CONNECTION_HTML)
6753 { 7058 {
6754 buttons = GTK_IMHTML_ALL; /* Everything on */ 7059 buttons = GTK_IMHTML_ALL; /* Everything on */
6755 if (conv->features & PURPLE_CONNECTION_NO_BGCOLOR) 7060 if (features & PURPLE_CONNECTION_NO_BGCOLOR)
6756 buttons &= ~GTK_IMHTML_BACKCOLOR; 7061 buttons &= ~GTK_IMHTML_BACKCOLOR;
6757 if (conv->features & PURPLE_CONNECTION_NO_FONTSIZE) 7062 if (features & PURPLE_CONNECTION_NO_FONTSIZE)
6758 { 7063 {
6759 buttons &= ~GTK_IMHTML_GROW; 7064 buttons &= ~GTK_IMHTML_GROW;
6760 buttons &= ~GTK_IMHTML_SHRINK; 7065 buttons &= ~GTK_IMHTML_SHRINK;
6761 } 7066 }
6762 if (conv->features & PURPLE_CONNECTION_NO_URLDESC) 7067 if (features & PURPLE_CONNECTION_NO_URLDESC)
6763 buttons &= ~GTK_IMHTML_LINKDESC; 7068 buttons &= ~GTK_IMHTML_LINKDESC;
6764 } else { 7069 } else {
6765 buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE; 7070 buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE;
6766 } 7071 }
6767 7072
6768 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)) 7073 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)
6769 conv->features |= PURPLE_CONNECTION_NO_IMAGES; 7074 && !(features & PURPLE_CONNECTION_NO_IMAGES)) {
6770 7075 features |= PURPLE_CONNECTION_NO_IMAGES;
6771 if(conv->features & PURPLE_CONNECTION_NO_IMAGES) 7076 purple_conversation_set_features(conv, features);
7077 }
7078
7079 if (features & PURPLE_CONNECTION_NO_IMAGES)
6772 buttons &= ~GTK_IMHTML_IMAGE; 7080 buttons &= ~GTK_IMHTML_IMAGE;
6773 7081
6774 if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) 7082 if (features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
6775 buttons |= GTK_IMHTML_CUSTOM_SMILEY; 7083 buttons |= GTK_IMHTML_CUSTOM_SMILEY;
6776 else 7084 else
6777 buttons &= ~GTK_IMHTML_CUSTOM_SMILEY; 7085 buttons &= ~GTK_IMHTML_CUSTOM_SMILEY;
6778 7086
6779 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons); 7087 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons);
6783 /* Deal with menu items */ 7091 /* Deal with menu items */
6784 gtk_action_set_sensitive(win->menu.view_log, TRUE); 7092 gtk_action_set_sensitive(win->menu.view_log, TRUE);
6785 gtk_action_set_sensitive(win->menu.add_pounce, TRUE); 7093 gtk_action_set_sensitive(win->menu.add_pounce, TRUE);
6786 gtk_action_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); 7094 gtk_action_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL));
6787 gtk_action_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); 7095 gtk_action_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL));
6788 gtk_action_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML)); 7096 gtk_action_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_HTML));
6789 gtk_action_set_sensitive(win->menu.insert_image, !(conv->features & PURPLE_CONNECTION_NO_IMAGES)); 7097 gtk_action_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_NO_IMAGES));
6790 7098
6791 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) 7099 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
6792 { 7100 {
6793 gtk_action_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL) || (prpl_info->add_buddy_with_invite != NULL)); 7101 gtk_action_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL));
6794 gtk_action_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); 7102 gtk_action_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL));
6795 gtk_action_set_sensitive(win->menu.send_file, 7103 gtk_action_set_sensitive(win->menu.send_file,
6796 (prpl_info->send_file != NULL && (!prpl_info->can_receive_file || 7104 (prpl_info->send_file != NULL && (!prpl_info->can_receive_file ||
6797 prpl_info->can_receive_file(gc, purple_conversation_get_name(conv))))); 7105 prpl_info->can_receive_file(gc, purple_conversation_get_name(conv)))));
6798 gtk_action_set_sensitive(g_object_get_data(G_OBJECT(win->window), "get_attention"), (prpl_info->send_attention != NULL)); 7106 gtk_action_set_sensitive(win->menu.get_attention, (prpl_info->send_attention != NULL));
6799 gtk_action_set_sensitive(win->menu.alias, 7107 gtk_action_set_sensitive(win->menu.alias,
6800 (account != NULL) && 7108 (account != NULL) &&
6801 (purple_find_buddy(account, purple_conversation_get_name(conv)) != NULL)); 7109 (purple_find_buddy(account, purple_conversation_get_name(conv)) != NULL));
6802 } 7110 }
6803 else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) 7111 else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)
6814 /* Or it's a chat that we've left. */ 7122 /* Or it's a chat that we've left. */
6815 7123
6816 /* Then deal with menu items */ 7124 /* Then deal with menu items */
6817 gtk_action_set_sensitive(win->menu.view_log, TRUE); 7125 gtk_action_set_sensitive(win->menu.view_log, TRUE);
6818 gtk_action_set_sensitive(win->menu.send_file, FALSE); 7126 gtk_action_set_sensitive(win->menu.send_file, FALSE);
6819 gtk_action_set_sensitive(g_object_get_data(G_OBJECT(win->window), 7127 gtk_action_set_sensitive(win->menu.get_attention, FALSE);
6820 "get_attention"), FALSE);
6821 gtk_action_set_sensitive(win->menu.add_pounce, TRUE); 7128 gtk_action_set_sensitive(win->menu.add_pounce, TRUE);
6822 gtk_action_set_sensitive(win->menu.get_info, FALSE); 7129 gtk_action_set_sensitive(win->menu.get_info, FALSE);
6823 gtk_action_set_sensitive(win->menu.invite, FALSE); 7130 gtk_action_set_sensitive(win->menu.invite, FALSE);
6824 gtk_action_set_sensitive(win->menu.alias, FALSE); 7131 gtk_action_set_sensitive(win->menu.alias, FALSE);
6825 gtk_action_set_sensitive(win->menu.add, FALSE); 7132 gtk_action_set_sensitive(win->menu.add, FALSE);
6835 { 7142 {
6836 GList *l = NULL; 7143 GList *l = NULL;
6837 if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && 7144 if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) &&
6838 (gtkconv->u.im->anim)) 7145 (gtkconv->u.im->anim))
6839 { 7146 {
6840 PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); 7147 PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
6841 window_icon = 7148 window_icon =
6842 gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); 7149 gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim);
6843 7150
6844 if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy)) 7151 if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy))
6845 gdk_pixbuf_saturate_and_pixelate(window_icon, window_icon, 0.0, FALSE); 7152 gdk_pixbuf_saturate_and_pixelate(window_icon, window_icon, 0.0, FALSE);
6883 7190
6884 if (fields & PIDGIN_CONV_MENU) 7191 if (fields & PIDGIN_CONV_MENU)
6885 { 7192 {
6886 gray_stuff_out(PIDGIN_CONVERSATION(conv)); 7193 gray_stuff_out(PIDGIN_CONVERSATION(conv));
6887 generate_send_to_items(win); 7194 generate_send_to_items(win);
7195 regenerate_plugins_items(win);
6888 } 7196 }
6889 7197
6890 if (fields & PIDGIN_CONV_TAB_ICON) 7198 if (fields & PIDGIN_CONV_TAB_ICON)
6891 { 7199 {
6892 update_tab_icon(conv); 7200 update_tab_icon(conv);
6913 topic ? topic : "", NULL); 7221 topic ? topic : "", NULL);
6914 #endif 7222 #endif
6915 } 7223 }
6916 } 7224 }
6917 7225
7226 #if 0
6918 if (fields & PIDGIN_CONV_SMILEY_THEME) 7227 if (fields & PIDGIN_CONV_SMILEY_THEME)
6919 pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->imhtml); 7228 pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->webview);
7229 #endif
6920 7230
6921 if ((fields & PIDGIN_CONV_COLORIZE_TITLE) || 7231 if ((fields & PIDGIN_CONV_COLORIZE_TITLE) ||
6922 (fields & PIDGIN_CONV_SET_TITLE) || 7232 (fields & PIDGIN_CONV_SET_TITLE) ||
6923 (fields & PIDGIN_CONV_TOPIC)) 7233 (fields & PIDGIN_CONV_TOPIC))
6924 { 7234 {
6925 char *title; 7235 char *title;
6926 PurpleConvIm *im = NULL; 7236 PurpleConvIm *im = NULL;
6927 PurpleAccount *account = purple_conversation_get_account(conv); 7237 PurpleAccount *account = purple_conversation_get_account(conv);
6928 PurpleBuddy *buddy = NULL; 7238 PurpleBuddy *buddy = NULL;
6941 title = g_strdup_printf("(%s)", purple_conversation_get_title(conv)); 7251 title = g_strdup_printf("(%s)", purple_conversation_get_title(conv));
6942 else 7252 else
6943 title = g_strdup(purple_conversation_get_title(conv)); 7253 title = g_strdup(purple_conversation_get_title(conv));
6944 7254
6945 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 7255 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
6946 buddy = purple_find_buddy(account, conv->name); 7256 buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
6947 if (buddy) { 7257 if (buddy) {
6948 markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE); 7258 markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE);
6949 } else { 7259 } else {
6950 markup = title; 7260 markup = title;
6951 } 7261 }
6986 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) { 7296 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) {
6987 atk_object_set_description(accessibility_obj, _("Nick Said")); 7297 atk_object_set_description(accessibility_obj, _("Nick Said"));
6988 style = "tab-label-attention"; 7298 style = "tab-label-attention";
6989 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) { 7299 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) {
6990 atk_object_set_description(accessibility_obj, _("Unread Messages")); 7300 atk_object_set_description(accessibility_obj, _("Unread Messages"));
6991 if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_CHAT) 7301 if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT)
6992 style = "tab-label-unreadchat"; 7302 style = "tab-label-unreadchat";
6993 else 7303 else
6994 style = "tab-label-attention"; 7304 style = "tab-label-attention";
6995 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) { 7305 } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) {
6996 atk_object_set_description(accessibility_obj, _("New Event")); 7306 atk_object_set_description(accessibility_obj, _("New Event"));
7198 gtkconv->u.im->iter = NULL; 7508 gtkconv->u.im->iter = NULL;
7199 7509
7200 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons")) 7510 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons"))
7201 return; 7511 return;
7202 7512
7203 if (purple_conversation_get_gc(conv) == NULL) 7513 if (purple_conversation_get_connection(conv) == NULL)
7204 return; 7514 return;
7205 7515
7206 buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); 7516 buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
7207 if (buddy) 7517 if (buddy)
7208 { 7518 {
7284 7594
7285 event = gtk_event_box_new(); 7595 event = gtk_event_box_new();
7286 gtk_container_add(GTK_CONTAINER(gtkconv->u.im->icon_container), event); 7596 gtk_container_add(GTK_CONTAINER(gtkconv->u.im->icon_container), event);
7287 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event), FALSE); 7597 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event), FALSE);
7288 gtk_widget_add_events(event, 7598 gtk_widget_add_events(event,
7289 GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); 7599 GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
7290 g_signal_connect(G_OBJECT(event), "button-press-event", 7600 g_signal_connect(G_OBJECT(event), "button-press-event",
7291 G_CALLBACK(icon_menu), gtkconv); 7601 G_CALLBACK(icon_menu), gtkconv);
7292 7602
7293 pidgin_tooltip_setup_for_widget(event, gtkconv, pidgin_conv_create_tooltip, NULL); 7603 pidgin_tooltip_setup_for_widget(event, gtkconv, pidgin_conv_create_tooltip, NULL);
7294 gtk_widget_show(event); 7604 gtk_widget_show(event);
7326 static gboolean 7636 static gboolean
7327 pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y) 7637 pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y)
7328 { 7638 {
7329 gint pane_x, pane_y, x_rel; 7639 gint pane_x, pane_y, x_rel;
7330 PidginConversation *gtkconv; 7640 PidginConversation *gtkconv;
7331 GtkAllocation allocation; 7641
7332 7642 gdk_window_get_origin(win->notebook->window, &pane_x, &pane_y);
7333 gdk_window_get_origin(gtk_widget_get_window(win->notebook),
7334 &pane_x, &pane_y);
7335 x_rel = x - pane_x; 7643 x_rel = x - pane_x;
7336 gtkconv = pidgin_conv_window_get_active_gtkconv(win); 7644 gtkconv = pidgin_conv_window_get_active_gtkconv(win);
7337 gtk_widget_get_allocation(gtkconv->infopane, &allocation); 7645 return (x_rel > gtkconv->infopane->allocation.x + gtkconv->infopane->allocation.width / 2);
7338 return (x_rel > allocation.x + allocation.width / 2);
7339 } 7646 }
7340 7647
7341 int 7648 int
7342 pidgin_conv_get_tab_at_xy(PidginWindow *win, int x, int y, gboolean *to_right) 7649 pidgin_conv_get_tab_at_xy(PidginWindow *win, int x, int y, gboolean *to_right)
7343 { 7650 {
7351 if (to_right) 7658 if (to_right)
7352 *to_right = FALSE; 7659 *to_right = FALSE;
7353 7660
7354 notebook = GTK_NOTEBOOK(win->notebook); 7661 notebook = GTK_NOTEBOOK(win->notebook);
7355 7662
7356 gdk_window_get_origin(gtk_widget_get_window(win->notebook), &nb_x, &nb_y); 7663 gdk_window_get_origin(win->notebook->window, &nb_x, &nb_y);
7357 x_rel = x - nb_x; 7664 x_rel = x - nb_x;
7358 y_rel = y - nb_y; 7665 y_rel = y - nb_y;
7359 7666
7360 horiz = (gtk_notebook_get_tab_pos(notebook) == GTK_POS_TOP || 7667 horiz = (gtk_notebook_get_tab_pos(notebook) == GTK_POS_TOP ||
7361 gtk_notebook_get_tab_pos(notebook) == GTK_POS_BOTTOM); 7668 gtk_notebook_get_tab_pos(notebook) == GTK_POS_BOTTOM);
7362 7669
7363 count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook)); 7670 count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook));
7364 7671
7365 for (i = 0; i < count; i++) { 7672 for (i = 0; i < count; i++) {
7366 GtkAllocation allocation;
7367 7673
7368 page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i); 7674 page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i);
7369 tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page); 7675 tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);
7370 gtk_widget_get_allocation(tab, &allocation);
7371 7676
7372 /* Make sure the tab is not hidden beyond an arrow */ 7677 /* Make sure the tab is not hidden beyond an arrow */
7373 if (!gtk_widget_is_drawable(tab) && gtk_notebook_get_show_tabs(notebook)) 7678 if (!gtk_widget_is_drawable(tab) && gtk_notebook_get_show_tabs(notebook))
7374 continue; 7679 continue;
7375 7680
7376 if (horiz) { 7681 if (horiz) {
7377 if (x_rel >= allocation.x - PIDGIN_HIG_BOX_SPACE && 7682 if (x_rel >= tab->allocation.x - PIDGIN_HIG_BOX_SPACE &&
7378 x_rel <= allocation.x + allocation.width + PIDGIN_HIG_BOX_SPACE) { 7683 x_rel <= tab->allocation.x + tab->allocation.width + PIDGIN_HIG_BOX_SPACE) {
7379 page_num = i; 7684 page_num = i;
7380 7685
7381 if (to_right && x_rel >= allocation.x + allocation.width/2) 7686 if (to_right && x_rel >= tab->allocation.x + tab->allocation.width/2)
7382 *to_right = TRUE; 7687 *to_right = TRUE;
7383 7688
7384 break; 7689 break;
7385 } 7690 }
7386 } else { 7691 } else {
7387 if (y_rel >= allocation.y - PIDGIN_HIG_BOX_SPACE && 7692 if (y_rel >= tab->allocation.y - PIDGIN_HIG_BOX_SPACE &&
7388 y_rel <= allocation.y + allocation.height + PIDGIN_HIG_BOX_SPACE) { 7693 y_rel <= tab->allocation.y + tab->allocation.height + PIDGIN_HIG_BOX_SPACE) {
7389 page_num = i; 7694 page_num = i;
7390 7695
7391 if (to_right && y_rel >= allocation.y + allocation.height/2) 7696 if (to_right && y_rel >= tab->allocation.y + tab->allocation.height/2)
7392 *to_right = TRUE; 7697 *to_right = TRUE;
7393 7698
7394 break; 7699 break;
7395 } 7700 }
7396 } 7701 }
7497 7802
7498 gtk_toggle_action_set_active( 7803 gtk_toggle_action_set_active(
7499 GTK_TOGGLE_ACTION(win->menu.show_timestamps), 7804 GTK_TOGGLE_ACTION(win->menu.show_timestamps),
7500 (gboolean)GPOINTER_TO_INT(value)); 7805 (gboolean)GPOINTER_TO_INT(value));
7501 7806
7807 /* TODO WEBKIT: Use WebKit version of this. */
7808 #if 0
7502 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), 7809 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),
7503 (gboolean)GPOINTER_TO_INT(value)); 7810 (gboolean)GPOINTER_TO_INT(value));
7811 #endif /* if 0 */
7504 } 7812 }
7505 } 7813 }
7506 7814
7507 static void 7815 static void
7508 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type, 7816 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type,
7666 gtkconv = l->data; 7974 gtkconv = l->data;
7667 l = l->next; 7975 l = l->next;
7668 7976
7669 conv = gtkconv->active_conv; 7977 conv = gtkconv->active_conv;
7670 7978
7671 if (conv->type == PURPLE_CONV_TYPE_CHAT || 7979 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT ||
7672 gtkconv->unseen_count == 0 || 7980 gtkconv->unseen_count == 0 ||
7673 (when_away && !purple_status_is_available( 7981 (when_away && !purple_status_is_available(
7674 purple_account_get_active_status( 7982 purple_account_get_active_status(
7675 purple_conversation_get_account(conv))))) 7983 purple_conversation_get_account(conv)))))
7676 continue; 7984 continue;
7706 8014
7707 for (; node; node = node->next) 8015 for (; node; node = node->next)
7708 { 8016 {
7709 PurpleBuddy *buddy = (PurpleBuddy*)node; 8017 PurpleBuddy *buddy = (PurpleBuddy*)node;
7710 PurpleConversation *conv; 8018 PurpleConversation *conv;
7711 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); 8019 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
7712 if (conv) 8020 if (conv)
7713 return PIDGIN_CONVERSATION(conv); 8021 return PIDGIN_CONVERSATION(conv);
7714 } 8022 }
7715 return NULL; 8023 return NULL;
7716 } 8024 }
7731 /* if (purple_conversation_get_account(conv) == account) */ 8039 /* if (purple_conversation_get_account(conv) == account) */
7732 pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON | 8040 pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON |
7733 PIDGIN_CONV_MENU | PIDGIN_CONV_COLORIZE_TITLE); 8041 PIDGIN_CONV_MENU | PIDGIN_CONV_COLORIZE_TITLE);
7734 8042
7735 if (PURPLE_CONNECTION_IS_CONNECTED(gc) && 8043 if (PURPLE_CONNECTION_IS_CONNECTED(gc) &&
7736 conv->type == PURPLE_CONV_TYPE_CHAT && 8044 purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT &&
7737 conv->account == gc->account && 8045 purple_conversation_get_account(conv) == purple_connection_get_account(gc) &&
7738 purple_conversation_get_data(conv, "want-to-rejoin")) { 8046 purple_conversation_get_data(conv, "want-to-rejoin")) {
7739 GHashTable *comps = NULL; 8047 GHashTable *comps = NULL;
7740 PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); 8048 PurpleChat *chat = purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
7741 if (chat == NULL) { 8049 if (chat == NULL) {
7742 if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) 8050 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
7743 comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, conv->name); 8051
8052 if (prpl_info->chat_info_defaults != NULL)
8053 comps = prpl_info->chat_info_defaults(gc, purple_conversation_get_name(conv));
7744 } else { 8054 } else {
7745 comps = chat->components; 8055 comps = purple_chat_get_components(chat);
7746 } 8056 }
7747 serv_join_chat(gc, comps); 8057 serv_join_chat(gc, comps);
7748 if (chat == NULL && comps != NULL) 8058 if (chat == NULL && comps != NULL)
7749 g_hash_table_destroy(comps); 8059 g_hash_table_destroy(comps);
7750 } 8060 }
7807 static void 8117 static void
7808 update_buddy_idle_changed(PurpleBuddy *buddy, gboolean old, gboolean newidle) 8118 update_buddy_idle_changed(PurpleBuddy *buddy, gboolean old, gboolean newidle)
7809 { 8119 {
7810 PurpleConversation *conv; 8120 PurpleConversation *conv;
7811 8121
7812 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); 8122 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
7813 if (conv) 8123 if (conv)
7814 pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON); 8124 pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON);
7815 } 8125 }
7816 8126
7817 static void 8127 static void
7818 update_buddy_icon(PurpleBuddy *buddy) 8128 update_buddy_icon(PurpleBuddy *buddy)
7819 { 8129 {
7820 PurpleConversation *conv; 8130 PurpleConversation *conv;
7821 8131
7822 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); 8132 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
7823 if (conv) 8133 if (conv)
7824 pidgin_conv_update_fields(conv, PIDGIN_CONV_BUDDY_ICON); 8134 pidgin_conv_update_fields(conv, PIDGIN_CONV_BUDDY_ICON);
7825 } 8135 }
7826 8136
7827 static void 8137 static void
7882 /* Compare two PurpleConvMessage's, according to time in ascending order. */ 8192 /* Compare two PurpleConvMessage's, according to time in ascending order. */
7883 static int 8193 static int
7884 message_compare(gconstpointer p1, gconstpointer p2) 8194 message_compare(gconstpointer p1, gconstpointer p2)
7885 { 8195 {
7886 const PurpleConvMessage *m1 = p1, *m2 = p2; 8196 const PurpleConvMessage *m1 = p1, *m2 = p2;
7887 return (m1->when > m2->when); 8197 return (purple_conversation_message_get_timestamp(m1) > purple_conversation_message_get_timestamp(m2));
7888 } 8198 }
7889 8199
7890 /* Adds some message history to the gtkconv. This happens in a idle-callback. */ 8200 /* Adds some message history to the gtkconv. This happens in a idle-callback. */
7891 static gboolean 8201 static gboolean
7892 add_message_history_to_gtkconv(gpointer data) 8202 add_message_history_to_gtkconv(gpointer data)
7893 { 8203 {
7894 PidginConversation *gtkconv = data; 8204 PidginConversation *gtkconv = data;
7895 int count = 0; 8205 int count = 0;
7896 int timer = gtkconv->attach.timer; 8206 int timer = gtkconv->attach.timer;
7897 time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time")); 8207 time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time"));
7898 gboolean im = (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM); 8208 gboolean im = (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM);
7899 8209
7900 gtkconv->attach.timer = 0; 8210 gtkconv->attach.timer = 0;
7901 while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */ 8211 while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */
7902 PurpleConvMessage *msg = gtkconv->attach.current->data; 8212 PurpleConvMessage *msg = gtkconv->attach.current->data;
7903 if (!im && when && when < msg->when) { 8213 if (!im && when && when < purple_conversation_message_get_timestamp(msg)) {
7904 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0); 8214 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<BR><HR>");
7905 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); 8215 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
7906 } 8216 }
7907 pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when); 8217 pidgin_conv_write_conv(
8218 purple_conversation_message_get_conv(msg),
8219 purple_conversation_message_get_sender(msg),
8220 purple_conversation_message_get_alias(msg),
8221 purple_conversation_message_get_message(msg),
8222 purple_conversation_message_get_flags(msg),
8223 purple_conversation_message_get_timestamp(msg));
7908 if (im) { 8224 if (im) {
7909 gtkconv->attach.current = g_list_delete_link(gtkconv->attach.current, gtkconv->attach.current); 8225 gtkconv->attach.current = g_list_delete_link(gtkconv->attach.current, gtkconv->attach.current);
7910 } else { 8226 } else {
7911 gtkconv->attach.current = gtkconv->attach.current->prev; 8227 gtkconv->attach.current = gtkconv->attach.current->prev;
7912 } 8228 }
7925 for (; iter; iter = iter->next) { 8241 for (; iter; iter = iter->next) {
7926 PurpleConversation *conv = iter->data; 8242 PurpleConversation *conv = iter->data;
7927 GList *history = purple_conversation_get_message_history(conv); 8243 GList *history = purple_conversation_get_message_history(conv);
7928 for (; history; history = history->next) { 8244 for (; history; history = history->next) {
7929 PurpleConvMessage *msg = history->data; 8245 PurpleConvMessage *msg = history->data;
7930 if (msg->when > when) 8246 if (purple_conversation_message_get_timestamp(msg) > when)
7931 msgs = g_list_prepend(msgs, msg); 8247 msgs = g_list_prepend(msgs, msg);
7932 } 8248 }
7933 } 8249 }
7934 msgs = g_list_sort(msgs, message_compare); 8250 msgs = g_list_sort(msgs, message_compare);
7935 for (; msgs; msgs = g_list_delete_link(msgs, msgs)) { 8251 for (; msgs; msgs = g_list_delete_link(msgs, msgs)) {
7936 PurpleConvMessage *msg = msgs->data; 8252 PurpleConvMessage *msg = msgs->data;
7937 pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when); 8253 pidgin_conv_write_conv(
7938 } 8254 purple_conversation_message_get_conv(msg),
7939 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0); 8255 purple_conversation_message_get_sender(msg),
8256 purple_conversation_message_get_alias(msg),
8257 purple_conversation_message_get_message(msg),
8258 purple_conversation_message_get_flags(msg),
8259 purple_conversation_message_get_timestamp(msg));
8260 }
8261 gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<BR><HR>");
7940 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); 8262 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
7941 } 8263 }
7942 8264
7943 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); 8265 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
7944 purple_signal_emit(pidgin_conversations_get_handle(), 8266 purple_signal_emit(pidgin_conversations_get_handle(),
8010 break; 8332 break;
8011 default: 8333 default:
8012 g_return_val_if_reached(TRUE); 8334 g_return_val_if_reached(TRUE);
8013 } 8335 }
8014 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", 8336 g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time",
8015 GINT_TO_POINTER(((PurpleConvMessage*)(list->data))->when)); 8337 GINT_TO_POINTER(purple_conversation_message_get_timestamp((PurpleConvMessage*)(list->data))));
8016 gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv); 8338 gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv);
8017 } else { 8339 } else {
8018 purple_signal_emit(pidgin_conversations_get_handle(), 8340 purple_signal_emit(pidgin_conversations_get_handle(),
8019 "conversation-displayed", gtkconv); 8341 "conversation-displayed", gtkconv);
8020 } 8342 }
8021 8343
8022 if (conv->type == PURPLE_CONV_TYPE_CHAT) { 8344 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
8023 pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); 8345 pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC);
8024 pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE); 8346 pidgin_conv_chat_add_users(conv, purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)), TRUE);
8025 } 8347 }
8026 8348
8027 return TRUE; 8349 return TRUE;
8028 } 8350 }
8029 8351
8041 void *handle = pidgin_conversations_get_handle(); 8363 void *handle = pidgin_conversations_get_handle();
8042 void *blist_handle = purple_blist_get_handle(); 8364 void *blist_handle = purple_blist_get_handle();
8043 8365
8044 /* Conversations */ 8366 /* Conversations */
8045 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations"); 8367 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations");
8368 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/themes");
8046 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", TRUE); 8369 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", TRUE);
8047 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", TRUE); 8370 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", TRUE);
8048 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE); 8371 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE);
8049 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", FALSE); 8372 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", FALSE);
8050 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE); 8373 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE);
8128 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons", 8451 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons",
8129 show_buddy_icons_pref_cb, NULL); 8452 show_buddy_icons_pref_cb, NULL);
8130 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/blist/show_protocol_icons", 8453 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/blist/show_protocol_icons",
8131 show_protocol_icons_pref_cb, NULL); 8454 show_protocol_icons_pref_cb, NULL);
8132 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/im/hide_new", 8455 purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/im/hide_new",
8133 hide_new_pref_cb, NULL); 8456 hide_new_pref_cb, NULL);
8134 8457
8135 8458
8136 8459
8137 /********************************************************************** 8460 /**********************************************************************
8138 * Register signals 8461 * Register signals
8285 8608
8286 hidden_convwin = pidgin_conv_window_new(); 8609 hidden_convwin = pidgin_conv_window_new();
8287 window_list = g_list_remove(window_list, hidden_convwin); 8610 window_list = g_list_remove(window_list, hidden_convwin);
8288 8611
8289 purple_signal_connect(purple_accounts_get_handle(), "account-status-changed", 8612 purple_signal_connect(purple_accounts_get_handle(), "account-status-changed",
8290 handle, PURPLE_CALLBACK(account_status_changed_cb), NULL); 8613 handle, PURPLE_CALLBACK(account_status_changed_cb), NULL);
8291 8614
8292 /* Callbacks to update a conversation */ 8615 /* Callbacks to update a conversation */
8293 purple_signal_connect(blist_handle, "blist-node-added", handle, 8616 purple_signal_connect(blist_handle, "blist-node-added", handle,
8294 G_CALLBACK(buddy_update_cb), NULL); 8617 G_CALLBACK(buddy_update_cb), NULL);
8295 purple_signal_connect(blist_handle, "blist-node-removed", handle, 8618 purple_signal_connect(blist_handle, "blist-node-removed", handle,
8324 purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", handle, 8647 purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", handle,
8325 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); 8648 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL);
8326 purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle, 8649 purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle,
8327 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); 8650 PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL);
8328 8651
8652 purple_theme_manager_register_type(g_object_new(PIDGIN_TYPE_CONV_THEME_LOADER, "type", "conversation", NULL));
8653
8329 { 8654 {
8330 /* Set default tab colors */ 8655 /* Set default tab colors */
8331 GString *str = g_string_new(NULL); 8656 GString *str = g_string_new(NULL);
8332 GtkSettings *settings = gtk_settings_get_default(); 8657 GtkSettings *settings = gtk_settings_get_default();
8333 GtkStyle *parent = gtk_rc_get_style_by_paths(settings, "tab-container.tab-label*", NULL, G_TYPE_NONE), *now; 8658 GtkStyle *parent = gtk_rc_get_style_by_paths(settings, "tab-container.tab-label*", NULL, G_TYPE_NONE), *now;
8469 GTK_RESPONSE_OK); 8794 GTK_RESPONSE_OK);
8470 8795
8471 gtk_container_set_border_width(GTK_CONTAINER(warn_close_dialog), 8796 gtk_container_set_border_width(GTK_CONTAINER(warn_close_dialog),
8472 6); 8797 6);
8473 gtk_window_set_resizable(GTK_WINDOW(warn_close_dialog), FALSE); 8798 gtk_window_set_resizable(GTK_WINDOW(warn_close_dialog), FALSE);
8474 8799 #if !GTK_CHECK_VERSION(2,22,0)
8475 /* TODO: figure out how to set no separator in GTK+ 3.0 */ 8800 gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), FALSE);
8476 #if 0
8477 gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog),
8478 FALSE);
8479 #endif 8801 #endif
8480 8802
8481 /* Setup the outside spacing. */ 8803 /* Setup the outside spacing. */
8482 vbox = gtk_dialog_get_content_area(GTK_DIALOG(warn_close_dialog)); 8804 vbox = GTK_DIALOG(warn_close_dialog)->vbox;
8483 8805
8484 gtk_box_set_spacing(GTK_BOX(vbox), 12); 8806 gtk_box_set_spacing(GTK_BOX(vbox), 12);
8485 gtk_container_set_border_width(GTK_CONTAINER(vbox), 6); 8807 gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
8486 8808
8487 img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_WARNING, 8809 img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_WARNING,
8631 #ifndef _WIN32 8953 #ifndef _WIN32
8632 /* Currently for win32 GTK+ (as of 2.2.1), gdk_pointer_is_grabbed will 8954 /* Currently for win32 GTK+ (as of 2.2.1), gdk_pointer_is_grabbed will
8633 always be true after a button press. */ 8955 always be true after a button press. */
8634 if (!gdk_pointer_is_grabbed()) 8956 if (!gdk_pointer_is_grabbed())
8635 #endif 8957 #endif
8636 gdk_pointer_grab(gtk_widget_get_window(gtkwin->notebook), FALSE, 8958 gdk_pointer_grab(gtkwin->notebook->window, FALSE,
8637 GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, 8959 GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
8638 NULL, cursor, GDK_CURRENT_TIME); 8960 NULL, cursor, GDK_CURRENT_TIME);
8639 } 8961 }
8640 8962
8641 static gboolean 8963 static gboolean
8751 if (e->type != GDK_BUTTON_PRESS) 9073 if (e->type != GDK_BUTTON_PRESS)
8752 return FALSE; 9074 return FALSE;
8753 9075
8754 if (e->button == 1) { 9076 if (e->button == 1) {
8755 int nb_x, nb_y; 9077 int nb_x, nb_y;
8756 GtkAllocation allocation;
8757
8758 gtk_widget_get_allocation(gtkconv->infopane_hbox, &allocation);
8759 9078
8760 if (gtkconv->win->in_drag) 9079 if (gtkconv->win->in_drag)
8761 return TRUE; 9080 return TRUE;
8762 9081
8763 gtkconv->win->in_predrag = TRUE; 9082 gtkconv->win->in_predrag = TRUE;
8764 gtkconv->win->drag_tab = gtk_notebook_page_num(GTK_NOTEBOOK(gtkconv->win->notebook), gtkconv->tab_cont); 9083 gtkconv->win->drag_tab = gtk_notebook_page_num(GTK_NOTEBOOK(gtkconv->win->notebook), gtkconv->tab_cont);
8765 9084
8766 gdk_window_get_origin(gtk_widget_get_window(gtkconv->infopane_hbox), &nb_x, &nb_y); 9085 gdk_window_get_origin(gtkconv->infopane_hbox->window, &nb_x, &nb_y);
8767 9086
8768 gtkconv->win->drag_min_x = allocation.x + nb_x; 9087 gtkconv->win->drag_min_x = gtkconv->infopane_hbox->allocation.x + nb_x;
8769 gtkconv->win->drag_min_y = allocation.y + nb_y; 9088 gtkconv->win->drag_min_y = gtkconv->infopane_hbox->allocation.y + nb_y;
8770 gtkconv->win->drag_max_x = allocation.width + gtkconv->win->drag_min_x; 9089 gtkconv->win->drag_max_x = gtkconv->infopane_hbox->allocation.width + gtkconv->win->drag_min_x;
8771 gtkconv->win->drag_max_y = allocation.height + gtkconv->win->drag_min_y; 9090 gtkconv->win->drag_max_y = gtkconv->infopane_hbox->allocation.height + gtkconv->win->drag_min_y;
8772 9091
8773 gtkconv->win->drag_motion_signal = g_signal_connect(G_OBJECT(gtkconv->win->notebook), "motion_notify_event", 9092 gtkconv->win->drag_motion_signal = g_signal_connect(G_OBJECT(gtkconv->win->notebook), "motion_notify_event",
8774 G_CALLBACK(notebook_motion_cb), gtkconv->win); 9093 G_CALLBACK(notebook_motion_cb), gtkconv->win);
8775 gtkconv->win->drag_leave_signal = g_signal_connect(G_OBJECT(gtkconv->win->notebook), "leave_notify_event", 9094 gtkconv->win->drag_leave_signal = g_signal_connect(G_OBJECT(gtkconv->win->notebook), "leave_notify_event",
8776 G_CALLBACK(notebook_leave_cb), gtkconv->win); 9095 G_CALLBACK(notebook_leave_cb), gtkconv->win);
8779 9098
8780 if (e->button == 3) { 9099 if (e->button == 3) {
8781 /* Right click was pressed. Popup the context menu. */ 9100 /* Right click was pressed. Popup the context menu. */
8782 GtkWidget *menu = gtk_menu_new(), *sub; 9101 GtkWidget *menu = gtk_menu_new(), *sub;
8783 gboolean populated = populate_menu_with_options(menu, gtkconv, TRUE); 9102 gboolean populated = populate_menu_with_options(menu, gtkconv, TRUE);
8784 #if 0 /* TODO */ 9103
8785 sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to)); 9104 sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to));
8786 9105 if (sub && gtk_widget_is_sensitive(gtkconv->win->menu.send_to)) {
8787 if (sub && GTK_WIDGET_IS_SENSITIVE(gtkconv->win->menu.send_to)) {
8788 GtkWidget *item = gtk_menu_item_new_with_mnemonic(_("S_end To")); 9106 GtkWidget *item = gtk_menu_item_new_with_mnemonic(_("S_end To"));
8789 if (populated) 9107 if (populated)
8790 pidgin_separator(menu); 9108 pidgin_separator(menu);
8791 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 9109 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
8792 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), sub); 9110 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), sub);
8794 gtk_widget_show_all(sub); 9112 gtk_widget_show_all(sub);
8795 } else if (!populated) { 9113 } else if (!populated) {
8796 gtk_widget_destroy(menu); 9114 gtk_widget_destroy(menu);
8797 return FALSE; 9115 return FALSE;
8798 } 9116 }
8799 #endif 9117
8800 gtk_widget_show_all(menu); 9118 gtk_widget_show_all(menu);
8801 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, e->button, e->time); 9119 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, e->button, e->time);
8802 return TRUE; 9120 return TRUE;
8803 } 9121 }
8804 return FALSE; 9122 return FALSE;
8809 { 9127 {
8810 gint nb_x, nb_y; 9128 gint nb_x, nb_y;
8811 int tab_clicked; 9129 int tab_clicked;
8812 GtkWidget *page; 9130 GtkWidget *page;
8813 GtkWidget *tab; 9131 GtkWidget *tab;
8814 GtkAllocation allocation;
8815 9132
8816 if (e->button == 2 && e->type == GDK_BUTTON_PRESS) { 9133 if (e->button == 2 && e->type == GDK_BUTTON_PRESS) {
8817 PidginConversation *gtkconv; 9134 PidginConversation *gtkconv;
8818 tab_clicked = pidgin_conv_get_tab_at_xy(win, e->x_root, e->y_root, NULL); 9135 tab_clicked = pidgin_conv_get_tab_at_xy(win, e->x_root, e->y_root, NULL);
8819 9136
8847 9164
8848 /* 9165 /*
8849 * Get the relative position of the press event, with regards to 9166 * Get the relative position of the press event, with regards to
8850 * the position of the notebook. 9167 * the position of the notebook.
8851 */ 9168 */
8852 gdk_window_get_origin(gtk_widget_get_window(win->notebook), &nb_x, &nb_y); 9169 gdk_window_get_origin(win->notebook->window, &nb_x, &nb_y);
8853 9170
8854 /* Reset the min/max x/y */ 9171 /* Reset the min/max x/y */
8855 win->drag_min_x = 0; 9172 win->drag_min_x = 0;
8856 win->drag_min_y = 0; 9173 win->drag_min_y = 0;
8857 win->drag_max_x = 0; 9174 win->drag_max_x = 0;
8859 9176
8860 /* Find out which tab was dragged. */ 9177 /* Find out which tab was dragged. */
8861 page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), tab_clicked); 9178 page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), tab_clicked);
8862 tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(win->notebook), page); 9179 tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(win->notebook), page);
8863 9180
8864 gtk_widget_get_allocation(tab, &allocation); 9181 win->drag_min_x = tab->allocation.x + nb_x;
8865 9182 win->drag_min_y = tab->allocation.y + nb_y;
8866 win->drag_min_x = allocation.x + nb_x; 9183 win->drag_max_x = tab->allocation.width + win->drag_min_x;
8867 win->drag_min_y = allocation.y + nb_y; 9184 win->drag_max_y = tab->allocation.height + win->drag_min_y;
8868 win->drag_max_x = allocation.width + win->drag_min_x;
8869 win->drag_max_y = allocation.height + win->drag_min_y;
8870 9185
8871 /* Make sure the click occurred in the tab. */ 9186 /* Make sure the click occurred in the tab. */
8872 if (e->x_root < win->drag_min_x || 9187 if (e->x_root < win->drag_min_x ||
8873 e->x_root >= win->drag_max_x || 9188 e->x_root >= win->drag_max_x ||
8874 e->y_root < win->drag_min_y || 9189 e->y_root < win->drag_min_y ||
8875 e->y_root >= win->drag_max_y) { 9190 e->y_root >= win->drag_max_y) {
8876 9191
8877 return FALSE; 9192 return FALSE;
8878 } 9193 }
8879 9194
8880 win->in_predrag = TRUE; 9195 win->in_predrag = TRUE;
8881 win->drag_tab = tab_clicked; 9196 win->drag_tab = tab_clicked;
8882 9197
8883 /* Connect the new motion signals. */ 9198 /* Connect the new motion signals. */
9101 9416
9102 if (gtkconv) 9417 if (gtkconv)
9103 close_conv_cb(NULL, gtkconv); 9418 close_conv_cb(NULL, gtkconv);
9104 } 9419 }
9105 9420
9106 /* TODO: I don't know if this doable in GTK+ 3.0 */
9107 #if 0
9108 static gboolean 9421 static gboolean
9109 right_click_menu_cb(GtkNotebook *notebook, GdkEventButton *event, PidginWindow *win) 9422 right_click_menu_cb(GtkNotebook *notebook, GdkEventButton *event, PidginWindow *win)
9110 { 9423 {
9111 GtkWidget *item; 9424 GtkWidget *item, *menu;
9112 PidginConversation *gtkconv; 9425 PidginConversation *gtkconv;
9113 GtkWidget *menu = gtk_notebook_get_menu
9114 9426
9115 if (event->type != GDK_BUTTON_PRESS || event->button != 3) 9427 if (event->type != GDK_BUTTON_PRESS || event->button != 3)
9116 return FALSE; 9428 return FALSE;
9117 9429
9118 gtkconv = pidgin_conv_window_get_gtkconv_at_index(win, 9430 gtkconv = pidgin_conv_window_get_gtkconv_at_index(win,
9155 g_signal_connect(G_OBJECT(item), "activate", 9467 g_signal_connect(G_OBJECT(item), "activate",
9156 G_CALLBACK(close_tab_cb), menu); 9468 G_CALLBACK(close_tab_cb), menu);
9157 9469
9158 return FALSE; 9470 return FALSE;
9159 } 9471 }
9160 #endif
9161 9472
9162 static void 9473 static void
9163 remove_edit_entry(PidginConversation *gtkconv, GtkWidget *entry) 9474 remove_edit_entry(PidginConversation *gtkconv, GtkWidget *entry)
9164 { 9475 {
9165 g_signal_handlers_disconnect_matched(G_OBJECT(entry), G_SIGNAL_MATCH_DATA, 9476 g_signal_handlers_disconnect_matched(G_OBJECT(entry), G_SIGNAL_MATCH_DATA,
9177 } 9488 }
9178 9489
9179 static gboolean 9490 static gboolean
9180 alias_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data) 9491 alias_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
9181 { 9492 {
9182 if (event->keyval == GDK_KEY_Escape) { 9493 if (event->keyval == GDK_Escape) {
9183 remove_edit_entry(user_data, widget); 9494 remove_edit_entry(user_data, widget);
9184 return TRUE; 9495 return TRUE;
9185 } 9496 }
9186 return FALSE; 9497 return FALSE;
9187 } 9498 }
9204 9515
9205 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 9516 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
9206 PurpleBuddy *buddy; 9517 PurpleBuddy *buddy;
9207 buddy = purple_find_buddy(account, name); 9518 buddy = purple_find_buddy(account, name);
9208 if (buddy != NULL) { 9519 if (buddy != NULL) {
9209 purple_blist_alias_buddy(buddy, gtk_entry_get_text(entry)); 9520 purple_blist_alias_buddy(buddy,
9521 gtk_entry_get_text(entry));
9210 } 9522 }
9211 serv_alias_buddy(buddy); 9523 serv_alias_buddy(buddy);
9212 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 9524 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
9213 gtk_entry_set_text(GTK_ENTRY(gtkconv->u.chat->topic_text), gtk_entry_get_text(entry)); 9525 gtk_entry_set_text(GTK_ENTRY(gtkconv->u.chat->topic_text), gtk_entry_get_text(entry));
9214 topic_callback(NULL, gtkconv); 9526 topic_callback(NULL, gtkconv);
9226 if (!gtk_widget_get_visible(gtkconv->infopane)) { 9538 if (!gtk_widget_get_visible(gtkconv->infopane)) {
9227 /* There's already an entry for alias. Let's not create another one. */ 9539 /* There's already an entry for alias. Let's not create another one. */
9228 return FALSE; 9540 return FALSE;
9229 } 9541 }
9230 9542
9231 if (!purple_account_is_connected(gtkconv->active_conv->account)) { 9543 if (!purple_account_is_connected(purple_conversation_get_account(gtkconv->active_conv))) {
9232 /* Do not allow aliasing someone on a disconnected account. */ 9544 /* Do not allow aliasing someone on a disconnected account. */
9233 return FALSE; 9545 return FALSE;
9234 } 9546 }
9235 9547
9236 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 9548 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
9237 PurpleBuddy *buddy = purple_find_buddy(gtkconv->active_conv->account, gtkconv->active_conv->name); 9549 PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv));
9238 if (!buddy) 9550 if (!buddy)
9239 /* This buddy isn't in your buddy list, so we can't alias him */ 9551 /* This buddy isn't in your buddy list, so we can't alias him */
9240 return FALSE; 9552 return FALSE;
9241 9553
9242 text = purple_buddy_get_contact_alias(buddy); 9554 text = purple_buddy_get_contact_alias(buddy);
9243 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 9555 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
9244 PurpleConnection *gc; 9556 PurpleConnection *gc;
9245 PurplePluginProtocolInfo *prpl_info = NULL; 9557 PurplePluginProtocolInfo *prpl_info = NULL;
9246 9558
9247 gc = purple_conversation_get_gc(conv); 9559 gc = purple_conversation_get_connection(conv);
9248 if (gc != NULL) 9560 if (gc != NULL)
9249 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 9561 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
9250 if (prpl_info && prpl_info->set_chat_topic == NULL) 9562 if (prpl_info && prpl_info->set_chat_topic == NULL)
9251 /* This protocol doesn't support setting the chat room topic */ 9563 /* This protocol doesn't support setting the chat room topic */
9252 return FALSE; 9564 return FALSE;
9253 9565
9254 text = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv)); 9566 text = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv));
9350 9662
9351 static GList* 9663 static GList*
9352 make_status_icon_list(const char *stock, GtkWidget *w) 9664 make_status_icon_list(const char *stock, GtkWidget *w)
9353 { 9665 {
9354 GList *l = NULL; 9666 GList *l = NULL;
9355 l = g_list_append(l, 9667 l = g_list_append(l, gtk_widget_render_icon (w, stock,
9356 gtk_widget_render_icon(w, stock, 9668 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), "GtkWindow"));
9357 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), "GtkWindow")); 9669 l = g_list_append(l, gtk_widget_render_icon (w, stock,
9358 l = g_list_append(l, 9670 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL), "GtkWindow"));
9359 gtk_widget_render_icon(w, stock, 9671 l = g_list_append(l, gtk_widget_render_icon (w, stock,
9360 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL), "GtkWindow")); 9672 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM), "GtkWindow"));
9361 l = g_list_append(l, 9673 l = g_list_append(l, gtk_widget_render_icon (w, stock,
9362 gtk_widget_render_icon(w, stock, 9674 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_LARGE), "GtkWindow"));
9363 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM), "GtkWindow"));
9364 l = g_list_append(l,
9365 gtk_widget_render_icon(w, stock,
9366 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_LARGE), "GtkWindow"));
9367 return l; 9675 return l;
9368 } 9676 }
9369 9677
9370 static void 9678 static void
9371 create_icon_lists(GtkWidget *w) 9679 create_icon_lists(GtkWidget *w)
9392 else 9700 else
9393 return FALSE; /* carry on normally */ 9701 return FALSE; /* carry on normally */
9394 9702
9395 /* Workaround for GTK+ bug # 169811 - "configure_event" is fired 9703 /* Workaround for GTK+ bug # 169811 - "configure_event" is fired
9396 * when the window is being maximized */ 9704 * when the window is being maximized */
9397 if (gdk_window_get_state(gtk_widget_get_window(w)) & GDK_WINDOW_STATE_MAXIMIZED) 9705 if (gdk_window_get_state(w->window) & GDK_WINDOW_STATE_MAXIMIZED)
9398 return FALSE; 9706 return FALSE;
9399 9707
9400 /* don't save off-screen positioning */ 9708 /* don't save off-screen positioning */
9401 if (x + event->width < 0 || 9709 if (x + event->width < 0 ||
9402 y + event->height < 0 || 9710 y + event->height < 0 ||
9417 9725
9418 static void 9726 static void
9419 pidgin_conv_set_position_size(PidginWindow *win, int conv_x, int conv_y, 9727 pidgin_conv_set_position_size(PidginWindow *win, int conv_x, int conv_y,
9420 int conv_width, int conv_height) 9728 int conv_width, int conv_height)
9421 { 9729 {
9422 /* if the window exists, is hidden, we're saving positions, and the 9730 /* if the window exists, is hidden, we're saving positions, and the
9423 * position is sane... */ 9731 * position is sane... */
9424 if (win && win->window && 9732 if (win && win->window &&
9425 !gtk_widget_get_visible(win->window) && conv_width != 0) { 9733 !gtk_widget_get_visible(win->window) && conv_width != 0) {
9426 9734
9427 #ifdef _WIN32 /* only override window manager placement on Windows */ 9735 #ifdef _WIN32 /* only override window manager placement on Windows */
9428 /* ...check position is on screen... */ 9736 /* ...check position is on screen... */
9505 gtk_notebook_set_scrollable(GTK_NOTEBOOK(win->notebook), TRUE); 9813 gtk_notebook_set_scrollable(GTK_NOTEBOOK(win->notebook), TRUE);
9506 gtk_notebook_popup_enable(GTK_NOTEBOOK(win->notebook)); 9814 gtk_notebook_popup_enable(GTK_NOTEBOOK(win->notebook));
9507 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); 9815 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE);
9508 gtk_notebook_set_show_border(GTK_NOTEBOOK(win->notebook), TRUE); 9816 gtk_notebook_set_show_border(GTK_NOTEBOOK(win->notebook), TRUE);
9509 9817
9510 /* TODO: figure out how to add custom stuff to the right-click menu in
9511 GtkNotebook in GTK+ 3.0 */
9512 #if 0
9513 g_signal_connect(G_OBJECT(win->notebook), "button-press-event", 9818 g_signal_connect(G_OBJECT(win->notebook), "button-press-event",
9514 G_CALLBACK(right_click_menu_cb), win); 9819 G_CALLBACK(right_click_menu_cb), win);
9515 #endif
9516 9820
9517 gtk_widget_show(win->notebook); 9821 gtk_widget_show(win->notebook);
9518 9822
9519 g_signal_connect(G_OBJECT(win->notebook), "switch_page", 9823 g_signal_connect(G_OBJECT(win->notebook), "switch_page",
9520 G_CALLBACK(before_switch_conv_cb), win); 9824 G_CALLBACK(before_switch_conv_cb), win);
9602 } 9906 }
9603 9907
9604 void 9908 void
9605 pidgin_conv_window_raise(PidginWindow *win) 9909 pidgin_conv_window_raise(PidginWindow *win)
9606 { 9910 {
9607 gdk_window_raise(GDK_WINDOW(gtk_widget_get_window(win->window))); 9911 gdk_window_raise(GDK_WINDOW(win->window->window));
9608 } 9912 }
9609 9913
9610 void 9914 void
9611 pidgin_conv_window_switch_gtkconv(PidginWindow *win, PidginConversation *gtkconv) 9915 pidgin_conv_window_switch_gtkconv(PidginWindow *win, PidginConversation *gtkconv)
9612 { 9916 {
9777 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE); 10081 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
9778 gtk_container_add(GTK_CONTAINER(ebox), gtkconv->tabby); 10082 gtk_container_add(GTK_CONTAINER(ebox), gtkconv->tabby);
9779 g_signal_connect(G_OBJECT(ebox), "enter-notify-event", 10083 g_signal_connect(G_OBJECT(ebox), "enter-notify-event",
9780 G_CALLBACK(gtkconv_tab_set_tip), gtkconv); 10084 G_CALLBACK(gtkconv_tab_set_tip), gtkconv);
9781 10085
9782 if (gtk_widget_get_parent(gtkconv->tab_label) == NULL) { 10086 if (gtkconv->tab_label->parent == NULL) {
9783 /* Pack if it's a new widget */ 10087 /* Pack if it's a new widget */
9784 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), first, FALSE, FALSE, 0); 10088 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), first, FALSE, FALSE, 0);
9785 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), gtkconv->tab_label, TRUE, TRUE, 0); 10089 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), gtkconv->tab_label, TRUE, TRUE, 0);
9786 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), third, FALSE, FALSE, 0); 10090 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), third, FALSE, FALSE, 0);
9787 10091
9798 10102
9799 /* Reset the tabs label to the new version */ 10103 /* Reset the tabs label to the new version */
9800 gtk_notebook_set_tab_label(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, ebox); 10104 gtk_notebook_set_tab_label(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, ebox);
9801 } 10105 }
9802 10106
9803 g_object_set(G_OBJECT(win->notebook), "expand", !tabs_side && !angle, NULL); 10107 gtk_container_child_set(GTK_CONTAINER(win->notebook), gtkconv->tab_cont,
10108 "tab-expand", !tabs_side && !angle,
10109 "tab-fill", TRUE, NULL);
9804 10110
9805 if (pidgin_conv_window_get_gtkconv_count(win) == 1) 10111 if (pidgin_conv_window_get_gtkconv_count(win) == 1)
9806 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), 10112 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook),
9807 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs") && 10113 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs") &&
9808 (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") || 10114 (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") ||
9822 { 10128 {
9823 unsigned int index; 10129 unsigned int index;
9824 10130
9825 index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont); 10131 index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont);
9826 10132
9827 #if GTK_CHECK_VERSION(2,10,0)
9828 g_object_ref_sink(G_OBJECT(gtkconv->tab_cont)); 10133 g_object_ref_sink(G_OBJECT(gtkconv->tab_cont));
9829 #else
9830 g_object_ref(gtkconv->tab_cont);
9831 gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont));
9832 #endif
9833 10134
9834 gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index); 10135 gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index);
9835 10136
9836 win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv); 10137 win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv);
9837 10138
9910 gdkwin = gdk_window_get_toplevel(gdkwin); 10211 gdkwin = gdk_window_get_toplevel(gdkwin);
9911 10212
9912 for (l = pidgin_conv_windows_get_list(); l != NULL; l = l->next) { 10213 for (l = pidgin_conv_windows_get_list(); l != NULL; l = l->next) {
9913 win = l->data; 10214 win = l->data;
9914 10215
9915 if (gdkwin == gtk_widget_get_window(win->window)) 10216 if (gdkwin == win->window->window)
9916 return win; 10217 return win;
9917 } 10218 }
9918 10219
9919 return NULL; 10220 return NULL;
9920 } 10221 }
10039 else 10340 else
10040 return FALSE; /* carry on normally */ 10341 return FALSE; /* carry on normally */
10041 10342
10042 /* Workaround for GTK+ bug # 169811 - "configure_event" is fired 10343 /* Workaround for GTK+ bug # 169811 - "configure_event" is fired
10043 * when the window is being maximized */ 10344 * when the window is being maximized */
10044 if (gdk_window_get_state(gtk_widget_get_window(w)) & GDK_WINDOW_STATE_MAXIMIZED) 10345 if (gdk_window_get_state(w->window) & GDK_WINDOW_STATE_MAXIMIZED)
10045 return FALSE; 10346 return FALSE;
10046 10347
10047 /* don't save off-screen positioning */ 10348 /* don't save off-screen positioning */
10048 if (x + event->width < 0 || 10349 if (x + event->width < 0 ||
10049 y + event->height < 0 || 10350 y + event->height < 0 ||