comparison pidgin/gtkconv.c @ 25512:ff69c2a9ccf2

propagate from branch 'im.pidgin.pidgin' (head 725fc6cb64d550dcc3a71741a974e5255f83a366) to branch 'im.pidgin.pidgin.yaz' (head 51241dcb972c543304c03eb0b9edc39a64ba3c6f)
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Sun, 17 Jun 2007 05:28:54 +0000
parents cf708cbcbc04 9b9e202eb449
children 90d558470507
comparison
equal deleted inserted replaced
25511:7a3c3c360624 25512:ff69c2a9ccf2
47 #include "log.h" 47 #include "log.h"
48 #include "notify.h" 48 #include "notify.h"
49 #include "prpl.h" 49 #include "prpl.h"
50 #include "request.h" 50 #include "request.h"
51 #include "util.h" 51 #include "util.h"
52 #include "version.h"
52 53
53 #include "gtkdnd-hints.h" 54 #include "gtkdnd-hints.h"
54 #include "gtkblist.h" 55 #include "gtkblist.h"
55 #include "gtkconv.h" 56 #include "gtkconv.h"
56 #include "gtkconvwin.h" 57 #include "gtkconvwin.h"
273 274
274 static void 275 static void
275 default_formatize(PidginConversation *c) 276 default_formatize(PidginConversation *c)
276 { 277 {
277 PurpleConversation *conv = c->active_conv; 278 PurpleConversation *conv = c->active_conv;
278 279 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features);
279 if (conv->features & PURPLE_CONNECTION_HTML)
280 {
281 char color[8];
282 GdkColor fg_color, bg_color;
283
284 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold") != GTK_IMHTML(c->entry)->edit.bold)
285 gtk_imhtml_toggle_bold(GTK_IMHTML(c->entry));
286
287 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic") != GTK_IMHTML(c->entry)->edit.italic)
288 gtk_imhtml_toggle_italic(GTK_IMHTML(c->entry));
289
290 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline") != GTK_IMHTML(c->entry)->edit.underline)
291 gtk_imhtml_toggle_underline(GTK_IMHTML(c->entry));
292
293 gtk_imhtml_toggle_fontface(GTK_IMHTML(c->entry),
294 purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face"));
295
296 if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE))
297 {
298 int size = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size");
299
300 /* 3 is the default. */
301 if (size != 3)
302 gtk_imhtml_font_set_size(GTK_IMHTML(c->entry), size);
303 }
304
305 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), "") != 0)
306 {
307 gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"),
308 &fg_color);
309 g_snprintf(color, sizeof(color), "#%02x%02x%02x",
310 fg_color.red / 256,
311 fg_color.green / 256,
312 fg_color.blue / 256);
313 } else
314 strcpy(color, "");
315
316 gtk_imhtml_toggle_forecolor(GTK_IMHTML(c->entry), color);
317
318 if(!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR) &&
319 strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), "") != 0)
320 {
321 gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"),
322 &bg_color);
323 g_snprintf(color, sizeof(color), "#%02x%02x%02x",
324 bg_color.red / 256,
325 bg_color.green / 256,
326 bg_color.blue / 256);
327 } else
328 strcpy(color, "");
329
330 gtk_imhtml_toggle_background(GTK_IMHTML(c->entry), color);
331
332 if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)
333 gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), TRUE);
334 else
335 gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), FALSE);
336 }
337 } 280 }
338 281
339 static void 282 static void
340 clear_formatting_cb(GtkIMHtml *imhtml, PidginConversation *gtkconv) 283 clear_formatting_cb(GtkIMHtml *imhtml, PidginConversation *gtkconv)
341 { 284 {
479 { 422 {
480 PidginConversation *gtkconv; 423 PidginConversation *gtkconv;
481 char *cmd; 424 char *cmd;
482 const char *prefix; 425 const char *prefix;
483 GtkTextIter start; 426 GtkTextIter start;
427 gboolean retval = FALSE;
484 428
485 gtkconv = PIDGIN_CONVERSATION(conv); 429 gtkconv = PIDGIN_CONVERSATION(conv);
486 prefix = pidgin_get_cmd_prefix(); 430 prefix = pidgin_get_cmd_prefix();
487 431
488 cmd = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL); 432 cmd = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL);
502 446
503 gtk_text_iter_forward_chars(&start, g_utf8_strlen(prefix, -1)); 447 gtk_text_iter_forward_chars(&start, g_utf8_strlen(prefix, -1));
504 gtk_text_buffer_get_end_iter(GTK_IMHTML(gtkconv->entry)->text_buffer, &end); 448 gtk_text_buffer_get_end_iter(GTK_IMHTML(gtkconv->entry)->text_buffer, &end);
505 markup = gtk_imhtml_get_markup_range(GTK_IMHTML(gtkconv->entry), &start, &end); 449 markup = gtk_imhtml_get_markup_range(GTK_IMHTML(gtkconv->entry), &start, &end);
506 status = purple_cmd_do_command(conv, cmdline, markup, &error); 450 status = purple_cmd_do_command(conv, cmdline, markup, &error);
507 g_free(cmd);
508 g_free(markup); 451 g_free(markup);
509 452
510 switch (status) { 453 switch (status) {
511 case PURPLE_CMD_STATUS_OK: 454 case PURPLE_CMD_STATUS_OK:
512 return TRUE; 455 retval = TRUE;
456 break;
513 case PURPLE_CMD_STATUS_NOT_FOUND: 457 case PURPLE_CMD_STATUS_NOT_FOUND:
514 return FALSE; 458 {
459 PurplePluginProtocolInfo *prpl_info = NULL;
460 PurpleConnection *gc;
461
462 if ((gc = purple_conversation_get_gc(conv)))
463 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
464
465 if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) {
466 char *firstspace;
467 char *slash;
468
469 firstspace = strchr(cmdline, ' ');
470 if (firstspace != NULL) {
471 slash = strrchr(firstspace, '/');
472 } else {
473 slash = strchr(cmdline, '/');
474 }
475
476 if (slash == NULL) {
477 purple_conversation_write(conv, "", _("Unknown command."), PURPLE_MESSAGE_NO_LOG, time(NULL));
478 retval = TRUE;
479 }
480 }
481 break;
482 }
515 case PURPLE_CMD_STATUS_WRONG_ARGS: 483 case PURPLE_CMD_STATUS_WRONG_ARGS:
516 purple_conversation_write(conv, "", _("Syntax Error: You typed the wrong number of arguments " 484 purple_conversation_write(conv, "", _("Syntax Error: You typed the wrong number of arguments "
517 "to that command."), 485 "to that command."),
518 PURPLE_MESSAGE_NO_LOG, time(NULL)); 486 PURPLE_MESSAGE_NO_LOG, time(NULL));
519 return TRUE; 487 retval = TRUE;
488 break;
520 case PURPLE_CMD_STATUS_FAILED: 489 case PURPLE_CMD_STATUS_FAILED:
521 purple_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."), 490 purple_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."),
522 PURPLE_MESSAGE_NO_LOG, time(NULL)); 491 PURPLE_MESSAGE_NO_LOG, time(NULL));
523 g_free(error); 492 g_free(error);
524 return TRUE; 493 retval = TRUE;
494 break;
525 case PURPLE_CMD_STATUS_WRONG_TYPE: 495 case PURPLE_CMD_STATUS_WRONG_TYPE:
526 if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) 496 if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
527 purple_conversation_write(conv, "", _("That command only works in chats, not IMs."), 497 purple_conversation_write(conv, "", _("That command only works in chats, not IMs."),
528 PURPLE_MESSAGE_NO_LOG, time(NULL)); 498 PURPLE_MESSAGE_NO_LOG, time(NULL));
529 else 499 else
530 purple_conversation_write(conv, "", _("That command only works in IMs, not chats."), 500 purple_conversation_write(conv, "", _("That command only works in IMs, not chats."),
531 PURPLE_MESSAGE_NO_LOG, time(NULL)); 501 PURPLE_MESSAGE_NO_LOG, time(NULL));
532 return TRUE; 502 retval = TRUE;
503 break;
533 case PURPLE_CMD_STATUS_WRONG_PRPL: 504 case PURPLE_CMD_STATUS_WRONG_PRPL:
534 purple_conversation_write(conv, "", _("That command doesn't work on this protocol."), 505 purple_conversation_write(conv, "", _("That command doesn't work on this protocol."),
535 PURPLE_MESSAGE_NO_LOG, time(NULL)); 506 PURPLE_MESSAGE_NO_LOG, time(NULL));
536 return TRUE; 507 retval = TRUE;
508 break;
537 } 509 }
538 } 510 }
539 511
540 g_free(cmd); 512 g_free(cmd);
541 return FALSE; 513 return retval;
542 } 514 }
543 515
544 static void 516 static void
545 send_cb(GtkWidget *widget, PidginConversation *gtkconv) 517 send_cb(GtkWidget *widget, PidginConversation *gtkconv)
546 { 518 {
668 { 640 {
669 prpl_info->get_cb_info(gc, 641 prpl_info->get_cb_info(gc,
670 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); 642 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
671 } 643 }
672 else 644 else
673 prpl_info->get_info(gc, who); 645 pidgin_retrieve_user_info(gc, who);
674 } 646 }
675 } 647 }
676 648
677 649
678 static void 650 static void
679 info_cb(GtkWidget *widget, PidginConversation *gtkconv) 651 info_cb(GtkWidget *widget, PidginConversation *gtkconv)
680 { 652 {
681 PurpleConversation *conv = gtkconv->active_conv; 653 PurpleConversation *conv = gtkconv->active_conv;
682 654
683 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 655 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
684 PurpleNotifyUserInfo *info = purple_notify_user_info_new(); 656 pidgin_retrieve_user_info(purple_conversation_get_gc(conv),
685 purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving..."));
686 purple_notify_userinfo(conv->account->gc, purple_conversation_get_name(conv), info, NULL, NULL);
687 purple_notify_user_info_destroy(info);
688
689 serv_get_info(purple_conversation_get_gc(conv),
690 purple_conversation_get_name(conv)); 657 purple_conversation_get_name(conv));
691
692 gtk_widget_grab_focus(gtkconv->entry); 658 gtk_widget_grab_focus(gtkconv->entry);
693 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 659 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
694 /* Get info of the person currently selected in the GtkTreeView */ 660 /* Get info of the person currently selected in the GtkTreeView */
695 PidginChatPane *gtkchat; 661 PidginChatPane *gtkchat;
696 GtkTreeIter iter; 662 GtkTreeIter iter;
2093 gtk_widget_event(gtkconv->entry, (GdkEvent *)event); 2059 gtk_widget_event(gtkconv->entry, (GdkEvent *)event);
2094 2060
2095 return TRUE; 2061 return TRUE;
2096 } 2062 }
2097 2063
2064 static void
2065 regenerate_options_items(PidginWindow *win);
2066
2098 void 2067 void
2099 pidgin_conv_switch_active_conversation(PurpleConversation *conv) 2068 pidgin_conv_switch_active_conversation(PurpleConversation *conv)
2100 { 2069 {
2101 PidginConversation *gtkconv; 2070 PidginConversation *gtkconv;
2102 PurpleConversation *old_conv; 2071 PurpleConversation *old_conv;
2193 2162
2194 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv); 2163 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv);
2195 2164
2196 gray_stuff_out(gtkconv); 2165 gray_stuff_out(gtkconv);
2197 update_typing_icon(gtkconv); 2166 update_typing_icon(gtkconv);
2167 g_object_set_data(G_OBJECT(entry), "transient_buddy", NULL);
2168 regenerate_options_items(gtkconv->win);
2198 2169
2199 gtk_window_set_title(GTK_WINDOW(gtkconv->win->window), 2170 gtk_window_set_title(GTK_WINDOW(gtkconv->win->window),
2200 gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); 2171 gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)));
2201 } 2172 }
2202 2173
2269 **************************************************************************/ 2240 **************************************************************************/
2270 2241
2271 static GList *get_prpl_icon_list(PurpleAccount *account) 2242 static GList *get_prpl_icon_list(PurpleAccount *account)
2272 { 2243 {
2273 GList *l = NULL; 2244 GList *l = NULL;
2274 GdkPixbuf *pixbuf; 2245 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
2275 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); 2246 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
2276 const char *prpl = prpl_info->list_icon(account, NULL); 2247 const char *prplname = prpl_info->list_icon(account, NULL);
2277 char *filename, *path; 2248 l = g_hash_table_lookup(prpl_lists, prplname);
2278 l = g_hash_table_lookup(prpl_lists, prpl);
2279 if (l) 2249 if (l)
2280 return l; 2250 return l;
2281 filename = g_strdup_printf("%s.png", prpl); 2251
2282 2252 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE));
2283 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", filename, NULL); 2253 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM));
2284 pixbuf = gdk_pixbuf_new_from_file(path, NULL); 2254 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL));
2285 if (pixbuf) 2255
2286 l = g_list_append(l, pixbuf); 2256 g_hash_table_insert(prpl_lists, g_strdup(prplname), l);
2287 g_free(path);
2288
2289 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "22", filename, NULL);
2290 pixbuf = gdk_pixbuf_new_from_file(path, NULL);
2291 if (pixbuf)
2292 l = g_list_append(l, pixbuf);
2293 g_free(path);
2294
2295 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "48", filename, NULL);
2296 pixbuf = gdk_pixbuf_new_from_file(path, NULL);
2297 if (pixbuf)
2298 l = g_list_append(l, pixbuf);
2299 g_free(path);
2300
2301 g_hash_table_insert(prpl_lists, g_strdup(prpl), l);
2302 return l; 2257 return l;
2303 } 2258 }
2304 2259
2305 static GList * 2260 static GList *
2306 pidgin_conv_get_tab_icons(PurpleConversation *conv) 2261 pidgin_conv_get_tab_icons(PurpleConversation *conv)
2968 gtkconv = pidgin_conv_window_get_active_gtkconv(win); 2923 gtkconv = pidgin_conv_window_get_active_gtkconv(win);
2969 conv = gtkconv->active_conv; 2924 conv = gtkconv->active_conv;
2970 2925
2971 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More")); 2926 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More"));
2972 2927
2973 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) 2928 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
2974 chat = purple_blist_find_chat(conv->account, conv->name); 2929 chat = purple_blist_find_chat(conv->account, conv->name);
2975 else 2930
2931 if ((chat == NULL) && (gtkconv->imhtml != NULL)) {
2932 chat = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat");
2933 }
2934
2935 if ((chat == NULL) && (gtkconv->imhtml != NULL)) {
2936 GHashTable *components;
2937 components = g_hash_table_new_full(g_str_hash, g_str_equal,
2938 g_free, g_free);
2939 g_hash_table_replace(components, g_strdup("channel"),
2940 g_strdup(conv->name));
2941 chat = purple_chat_new(conv->account, NULL, components);
2942 purple_blist_node_set_flags((PurpleBlistNode *)chat,
2943 PURPLE_BLIST_NODE_FLAG_NO_SAVE);
2944 g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_chat",
2945 chat, (GDestroyNotify)purple_blist_remove_chat);
2946 }
2947 } else {
2976 buddy = purple_find_buddy(conv->account, conv->name); 2948 buddy = purple_find_buddy(conv->account, conv->name);
2949
2950 /* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle
2951 * removing "isolated" buddy nodes well */
2952 if (purple_version_check(2, 0, 2) == NULL) {
2953 if ((buddy == NULL) && (gtkconv->imhtml != NULL)) {
2954 buddy = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy");
2955 }
2956
2957 if ((buddy == NULL) && (gtkconv->imhtml != NULL)) {
2958 buddy = purple_buddy_new(conv->account, conv->name, NULL);
2959 purple_blist_node_set_flags((PurpleBlistNode *)buddy,
2960 PURPLE_BLIST_NODE_FLAG_NO_SAVE);
2961 g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_buddy",
2962 buddy, (GDestroyNotify)purple_blist_remove_buddy);
2963 }
2964 }
2965 }
2977 2966
2978 if (chat) 2967 if (chat)
2979 node = (PurpleBlistNode *)chat; 2968 node = (PurpleBlistNode *)chat;
2980 else if (buddy) 2969 else if (buddy)
2981 node = (PurpleBlistNode *)buddy; 2970 node = (PurpleBlistNode *)buddy;
3004 } 2993 }
3005 2994
3006 gtk_widget_show_all(menu); 2995 gtk_widget_show_all(menu);
3007 } 2996 }
3008 2997
2998 static void
2999 remove_from_list(GtkWidget *widget, PidginWindow *win)
3000 {
3001 GList *list = g_object_get_data(G_OBJECT(win->window), "plugin-actions");
3002 list = g_list_remove(list, widget);
3003 g_object_set_data(G_OBJECT(win->window), "plugin-actions", list);
3004 }
3005
3006 static void
3007 regenerate_plugins_items(PidginWindow *win)
3008 {
3009 GList *action_items;
3010 GtkWidget *menu;
3011 GList *list;
3012 PidginConversation *gtkconv;
3013 PurpleConversation *conv;
3014 GtkWidget *item;
3015
3016 if (win->window == NULL || win == hidden_convwin)
3017 return;
3018
3019 gtkconv = pidgin_conv_window_get_active_gtkconv(win);
3020 if (gtkconv == NULL)
3021 return;
3022
3023 conv = gtkconv->active_conv;
3024 action_items = g_object_get_data(G_OBJECT(win->window), "plugin-actions");
3025
3026 /* Remove the old menuitems */
3027 while (action_items) {
3028 g_signal_handlers_disconnect_by_func(G_OBJECT(action_items->data),
3029 G_CALLBACK(remove_from_list), win);
3030 gtk_widget_destroy(action_items->data);
3031 action_items = g_list_delete_link(action_items, action_items);
3032 }
3033
3034 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options"));
3035
3036 list = purple_conversation_get_extended_menu(conv);
3037 if (list) {
3038 action_items = g_list_prepend(NULL, (item = pidgin_separator(menu)));
3039 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
3040 }
3041
3042 for(; list; list = g_list_delete_link(list, list)) {
3043 PurpleMenuAction *act = (PurpleMenuAction *) list->data;
3044 item = pidgin_append_menu_action(menu, act, conv);
3045 action_items = g_list_prepend(action_items, item);
3046 gtk_widget_show_all(item);
3047 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
3048 }
3049 g_object_set_data(G_OBJECT(win->window), "plugin-actions", action_items);
3050 }
3051
3009 static void menubar_activated(GtkWidget *item, gpointer data) 3052 static void menubar_activated(GtkWidget *item, gpointer data)
3010 { 3053 {
3011 PidginWindow *win = data; 3054 PidginWindow *win = data;
3012 regenerate_options_items(win); 3055 regenerate_options_items(win);
3056 regenerate_plugins_items(win);
3013 3057
3014 /* The following are to make sure the 'More' submenu is not regenerated every time 3058 /* The following are to make sure the 'More' submenu is not regenerated every time
3015 * the focus shifts from 'Conversations' to some other menu and back. */ 3059 * the focus shifts from 'Conversations' to some other menu and back. */
3016 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data); 3060 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data);
3017 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data); 3061 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data);
4231 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE); 4275 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE);
4232 g_idle_add(reset_auto_resize_cb, gtkconv); 4276 g_idle_add(reset_auto_resize_cb, gtkconv);
4233 } 4277 }
4234 } 4278 }
4235 4279
4236 static GtkWidget * 4280 static void
4237 setup_chat_pane(PidginConversation *gtkconv) 4281 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox)
4238 { 4282 {
4239 PurplePluginProtocolInfo *prpl_info;
4240 PurpleConversation *conv = gtkconv->active_conv; 4283 PurpleConversation *conv = gtkconv->active_conv;
4241 PidginChatPane *gtkchat; 4284 PurpleConnection *gc = purple_conversation_get_gc(conv);
4242 PurpleConnection *gc; 4285 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
4243 GtkWidget *vpaned, *hpaned;
4244 GtkWidget *vbox, *hbox, *frame;
4245 GtkWidget *imhtml_sw;
4246 GtkPolicyType imhtml_sw_hscroll;
4247 GtkWidget *lbox;
4248 GtkWidget *label;
4249 GtkWidget *list;
4250 GtkWidget *sw;
4251 GtkListStore *ls;
4252 GtkCellRenderer *rend;
4253 GtkTreeViewColumn *col;
4254 void *blist_handle = purple_blist_get_handle();
4255 GList *focus_chain = NULL;
4256 int ul_width;
4257
4258 gtkchat = gtkconv->u.chat;
4259 gc = purple_conversation_get_gc(conv);
4260 g_return_val_if_fail(gc != NULL, NULL);
4261 g_return_val_if_fail(gc->prpl != NULL, NULL);
4262 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
4263
4264 /* Setup the outer pane. */
4265 vpaned = gtk_vpaned_new();
4266 gtk_widget_show(vpaned);
4267
4268 /* Setup the top part of the pane. */
4269 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4270 gtk_paned_pack1(GTK_PANED(vpaned), vbox, TRUE, TRUE);
4271 gtk_widget_show(vbox);
4272
4273 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) 4286 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC)
4274 { 4287 {
4288 GtkWidget *hbox, *label;
4289 PidginChatPane *gtkchat = gtkconv->u.chat;
4290
4275 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4291 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4276 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); 4292 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
4277 gtk_widget_show(hbox); 4293 gtk_widget_show(hbox);
4278 4294
4279 label = gtk_label_new(_("Topic:")); 4295 label = gtk_label_new(_("Topic:"));
4292 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0); 4308 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0);
4293 gtk_widget_show(gtkchat->topic_text); 4309 gtk_widget_show(gtkchat->topic_text);
4294 g_signal_connect(G_OBJECT(gtkchat->topic_text), "key_press_event", 4310 g_signal_connect(G_OBJECT(gtkchat->topic_text), "key_press_event",
4295 G_CALLBACK(entry_key_press_cb), gtkconv); 4311 G_CALLBACK(entry_key_press_cb), gtkconv);
4296 } 4312 }
4297 4313 }
4298 /* Setup the horizontal pane. */ 4314
4299 hpaned = gtk_hpaned_new(); 4315 static void
4300 gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); 4316 setup_chat_userlist(PidginConversation *gtkconv, GtkWidget *hpaned)
4301 gtk_widget_show(hpaned); 4317 {
4302 4318 PidginChatPane *gtkchat = gtkconv->u.chat;
4303 /* Setup gtkihmtml. */ 4319 GtkWidget *lbox, *sw, *list;
4304 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw); 4320 GtkListStore *ls;
4305 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); 4321 GtkCellRenderer *rend;
4306 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), TRUE); 4322 GtkTreeViewColumn *col;
4307 gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE); 4323 int ul_width;
4308 gtk_widget_show(frame); 4324 void *blist_handle = purple_blist_get_handle();
4309 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw), 4325 PurpleConversation *conv = gtkconv->active_conv;
4310 &imhtml_sw_hscroll, NULL);
4311 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4312 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4313
4314 gtk_widget_set_size_request(gtkconv->imhtml,
4315 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width"),
4316 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height"));
4317 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4318 G_CALLBACK(size_allocate_cb), gtkconv);
4319
4320 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4321 G_CALLBACK(entry_stop_rclick_cb), NULL);
4322 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4323 G_CALLBACK(refocus_entry_cb), gtkconv);
4324 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4325 G_CALLBACK(refocus_entry_cb), gtkconv);
4326 4326
4327 /* Build the right pane. */ 4327 /* Build the right pane. */
4328 lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4328 lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4329 gtk_paned_pack2(GTK_PANED(hpaned), lbox, FALSE, TRUE); 4329 gtk_paned_pack2(GTK_PANED(hpaned), lbox, FALSE, TRUE);
4330 gtk_widget_show(lbox); 4330 gtk_widget_show(lbox);
4368 G_CALLBACK(right_click_chat_cb), gtkconv); 4368 G_CALLBACK(right_click_chat_cb), gtkconv);
4369 g_signal_connect(G_OBJECT(list), "popup-menu", 4369 g_signal_connect(G_OBJECT(list), "popup-menu",
4370 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv); 4370 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv);
4371 g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv); 4371 g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv);
4372 4372
4373
4374 rend = gtk_cell_renderer_text_new(); 4373 rend = gtk_cell_renderer_text_new();
4375
4376 g_object_set(rend, 4374 g_object_set(rend,
4377 "foreground-set", TRUE, 4375 "foreground-set", TRUE,
4378 "weight-set", TRUE, 4376 "weight-set", TRUE,
4379 NULL); 4377 NULL);
4380 col = gtk_tree_view_column_new_with_attributes(NULL, rend, 4378 col = gtk_tree_view_column_new_with_attributes(NULL, rend,
4401 gtk_widget_show(list); 4399 gtk_widget_show(list);
4402 4400
4403 gtkchat->list = list; 4401 gtkchat->list = list;
4404 4402
4405 gtk_container_add(GTK_CONTAINER(sw), list); 4403 gtk_container_add(GTK_CONTAINER(sw), list);
4404 }
4405
4406 static GtkWidget *
4407 setup_common_pane(PidginConversation *gtkconv)
4408 {
4409 GtkWidget *paned, *vbox, *frame, *imhtml_sw;
4410 PurpleConversation *conv = gtkconv->active_conv;
4411 gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT);
4412 GtkPolicyType imhtml_sw_hscroll;
4413
4414 paned = gtk_vpaned_new();
4415 gtk_widget_show(paned);
4416
4417 /* Setup the top part of the pane */
4418 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4419 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
4420 gtk_widget_show(vbox);
4421
4422 /* Setup the gtkimhtml widget */
4423 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
4424 if (chat) {
4425 GtkWidget *hpaned;
4426
4427 /* Add the topic */
4428 setup_chat_topic(gtkconv, vbox);
4429
4430 /* Add the gtkimhtml frame */
4431 hpaned = gtk_hpaned_new();
4432 gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0);
4433 gtk_widget_show(hpaned);
4434 gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE);
4435
4436 /* Now add the userlist */
4437 setup_chat_userlist(gtkconv, hpaned);
4438 } else {
4439 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4440 }
4441 gtk_widget_show(frame);
4442
4443 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
4444 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE);
4445
4446 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4447 &imhtml_sw_hscroll, NULL);
4448 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4449 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4450
4451 gtk_widget_set_size_request(gtkconv->imhtml,
4452 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width") :
4453 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"),
4454 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height") :
4455 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height"));
4456
4457 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4458 G_CALLBACK(size_allocate_cb), gtkconv);
4459
4460 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4461 G_CALLBACK(entry_stop_rclick_cb), NULL);
4462 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4463 G_CALLBACK(refocus_entry_cb), gtkconv);
4464 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4465 G_CALLBACK(refocus_entry_cb), gtkconv);
4406 4466
4407 /* Setup the bottom half of the conversation window */ 4467 /* Setup the bottom half of the conversation window */
4408 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4468 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4409 gtk_paned_pack2(GTK_PANED(vpaned), vbox, FALSE, TRUE); 4469 gtk_paned_pack2(GTK_PANED(paned), vbox, FALSE, TRUE);
4410 gtk_widget_show(vbox); 4470 gtk_widget_show(vbox);
4411 4471
4412 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4472 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4413 gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0); 4473 gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0);
4414 gtk_widget_show(gtkconv->lower_hbox); 4474 gtk_widget_show(gtkconv->lower_hbox);
4420 /* Setup the toolbar, entry widget and all signals */ 4480 /* Setup the toolbar, entry widget and all signals */
4421 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL); 4481 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL);
4422 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); 4482 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4423 gtk_widget_show(frame); 4483 gtk_widget_show(frame);
4424 4484
4425 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4426 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4427
4428 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); 4485 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
4429 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), 4486 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
4430 purple_account_get_protocol_name(conv->account)); 4487 purple_account_get_protocol_name(conv->account));
4431 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, 4488 gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
4432 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height")); 4489 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height") :
4433 gtkconv->entry_buffer = 4490 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height"));
4434 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); 4491
4435 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); 4492 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4436 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", 4493 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4437 G_CALLBACK(resize_imhtml_cb), gtkconv);
4438
4439 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 4494 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event",
4440 G_CALLBACK(entry_key_press_cb), gtkconv); 4495 G_CALLBACK(entry_key_press_cb), gtkconv);
4441 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", 4496 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send",
4442 G_CALLBACK(send_cb), gtkconv); 4497 G_CALLBACK(send_cb), gtkconv);
4443 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", 4498 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event",
4444 G_CALLBACK(entry_stop_rclick_cb), NULL); 4499 G_CALLBACK(entry_stop_rclick_cb), NULL);
4445 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", 4500 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate",
4446 G_CALLBACK(size_allocate_cb), gtkconv); 4501 G_CALLBACK(size_allocate_cb), gtkconv);
4447 4502
4448 default_formatize(gtkconv);
4449
4450 /*
4451 * Focus for chat windows should be as follows:
4452 * Tab title -> chat topic -> conversation scrollback -> user list ->
4453 * user list buttons -> entry -> buttons at bottom
4454 */
4455 focus_chain = g_list_prepend(focus_chain, gtkconv->entry);
4456 gtk_container_set_focus_chain(GTK_CONTAINER(vbox), focus_chain);
4457
4458 return vpaned;
4459 }
4460
4461 static GtkWidget *
4462 setup_im_pane(PidginConversation *gtkconv)
4463 {
4464 PurpleConversation *conv = gtkconv->active_conv;
4465 GtkWidget *frame;
4466 GtkWidget *imhtml_sw;
4467 GtkPolicyType imhtml_sw_hscroll;
4468 GtkWidget *paned;
4469 GtkWidget *vbox;
4470 GtkWidget *vbox2;
4471 GList *focus_chain = NULL;
4472
4473 /* Setup the outer pane */
4474 paned = gtk_vpaned_new();
4475 gtk_widget_show(paned);
4476
4477 /* Setup the top part of the pane */
4478 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4479 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
4480 gtk_widget_show(vbox);
4481
4482 /* Setup the gtkimhtml widget */
4483 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
4484 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
4485 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE);
4486 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4487 gtk_widget_show(frame);
4488 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4489 &imhtml_sw_hscroll, NULL);
4490 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4491 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4492
4493 gtk_widget_set_size_request(gtkconv->imhtml,
4494 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"),
4495 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height"));
4496 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4497 G_CALLBACK(size_allocate_cb), gtkconv);
4498
4499 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4500 G_CALLBACK(entry_stop_rclick_cb), NULL);
4501 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4502 G_CALLBACK(refocus_entry_cb), gtkconv);
4503 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4504 G_CALLBACK(refocus_entry_cb), gtkconv);
4505
4506 /* Setup the bottom half of the conversation window */
4507 vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4508 gtk_paned_pack2(GTK_PANED(paned), vbox2, FALSE, TRUE);
4509 gtk_widget_show(vbox2);
4510
4511 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4512 gtk_box_pack_start(GTK_BOX(vbox2), gtkconv->lower_hbox, TRUE, TRUE, 0);
4513 gtk_widget_show(gtkconv->lower_hbox);
4514
4515 vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4516 gtk_box_pack_end(GTK_BOX(gtkconv->lower_hbox), vbox2, TRUE, TRUE, 0);
4517 gtk_widget_show(vbox2);
4518
4519 /* Setup the toolbar, entry widget and all signals */
4520 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL);
4521 gtk_box_pack_start(GTK_BOX(vbox2), frame, TRUE, TRUE, 0);
4522 gtk_widget_show(frame);
4523
4524 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4525 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4526
4527 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
4528 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
4529 purple_account_get_protocol_name(conv->account));
4530 gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
4531 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height"));
4532 gtkconv->entry_buffer = 4503 gtkconv->entry_buffer =
4533 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); 4504 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry));
4534 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); 4505 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv);
4535 4506
4536 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 4507 if (!chat) {
4537 G_CALLBACK(entry_key_press_cb), gtkconv); 4508 /* For sending typing notifications for IMs */
4538 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", 4509 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text",
4539 G_CALLBACK(send_cb), gtkconv); 4510 G_CALLBACK(insert_text_cb), gtkconv);
4540 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", 4511 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range",
4541 G_CALLBACK(entry_stop_rclick_cb), NULL); 4512 G_CALLBACK(delete_text_cb), gtkconv);
4542 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", 4513 gtkconv->u.im->typing_timer = 0;
4543 G_CALLBACK(size_allocate_cb), gtkconv); 4514 gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons");
4544 4515 gtkconv->u.im->show_icon = TRUE;
4545 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", 4516 }
4546 G_CALLBACK(insert_text_cb), gtkconv); 4517
4547 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range",
4548 G_CALLBACK(delete_text_cb), gtkconv);
4549 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", 4518 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed",
4550 G_CALLBACK(resize_imhtml_cb), gtkconv); 4519 G_CALLBACK(resize_imhtml_cb), gtkconv);
4551 4520
4552 /* had to move this after the imtoolbar is attached so that the
4553 * signals get fired to toggle the buttons on the toolbar as well.
4554 */
4555 default_formatize(gtkconv); 4521 default_formatize(gtkconv);
4556
4557 g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear", 4522 g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear",
4558 G_CALLBACK(clear_formatting_cb), gtkconv); 4523 G_CALLBACK(clear_formatting_cb), gtkconv);
4559 4524
4560 gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons");
4561 gtkconv->u.im->show_icon = TRUE;
4562
4563 /*
4564 * Focus for IM windows should be as follows:
4565 * Tab title -> conversation scrollback -> entry
4566 */
4567 focus_chain = g_list_prepend(focus_chain, gtkconv->entry);
4568 gtk_container_set_focus_chain(GTK_CONTAINER(vbox2), focus_chain);
4569
4570 gtkconv->u.im->typing_timer = 0;
4571 return paned; 4525 return paned;
4572 } 4526 }
4573 4527
4574 static void 4528 static void
4575 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, 4529 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y,
4761 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; 4715 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
4762 gtkconv->unseen_count = 0; 4716 gtkconv->unseen_count = 0;
4763 4717
4764 if (conv_type == PURPLE_CONV_TYPE_IM) { 4718 if (conv_type == PURPLE_CONV_TYPE_IM) {
4765 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); 4719 gtkconv->u.im = g_malloc0(sizeof(PidginImPane));
4766
4767 pane = setup_im_pane(gtkconv);
4768 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { 4720 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) {
4769 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); 4721 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane));
4770 pane = setup_chat_pane(gtkconv); 4722 }
4771 } 4723 pane = setup_common_pane(gtkconv);
4772 4724
4773 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml), 4725 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml),
4774 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE); 4726 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE);
4775 4727
4776 if (pane == NULL) { 4728 if (pane == NULL) {
5164 g_return_if_fail(account != NULL); 5116 g_return_if_fail(account != NULL);
5165 gc = purple_account_get_connection(account); 5117 gc = purple_account_get_connection(account);
5166 g_return_if_fail(gc != NULL); 5118 g_return_if_fail(gc != NULL);
5167 5119
5168 /* Make sure URLs are clickable */ 5120 /* Make sure URLs are clickable */
5169 displaying = purple_markup_linkify(message); 5121 if(flags & PURPLE_MESSAGE_NO_LINKIFY)
5122 displaying = g_strdup(message);
5123 else
5124 displaying = purple_markup_linkify(message);
5125
5170 plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( 5126 plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1(
5171 pidgin_conversations_get_handle(), (type == PURPLE_CONV_TYPE_IM ? 5127 pidgin_conversations_get_handle(), (type == PURPLE_CONV_TYPE_IM ?
5172 "displaying-im-msg" : "displaying-chat-msg"), 5128 "displaying-im-msg" : "displaying-chat-msg"),
5173 account, name, &displaying, conv, flags)); 5129 account, name, &displaying, conv, flags));
5174 if (plugin_return) 5130 if (plugin_return)
8114 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging), 8070 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging),
8115 purple_conversation_is_logging(conv)); 8071 purple_conversation_is_logging(conv));
8116 8072
8117 generate_send_to_items(win); 8073 generate_send_to_items(win);
8118 regenerate_options_items(win); 8074 regenerate_options_items(win);
8075 regenerate_plugins_items(win);
8119 8076
8120 pidgin_conv_switch_active_conversation(conv); 8077 pidgin_conv_switch_active_conversation(conv);
8121 8078
8122 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); 8079 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method");
8123 if (strcmp(sound_method, "none") != 0) 8080 if (strcmp(sound_method, "none") != 0)
8184 offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w); 8141 offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w);
8185 away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w); 8142 away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w);
8186 prpl_lists = g_hash_table_new(g_str_hash, g_str_equal); 8143 prpl_lists = g_hash_table_new(g_str_hash, g_str_equal);
8187 } 8144 }
8188 8145
8146 static void
8147 plugin_changed_cb(PurplePlugin *p, gpointer data)
8148 {
8149 regenerate_plugins_items(data);
8150 }
8151
8189 PidginWindow * 8152 PidginWindow *
8190 pidgin_conv_window_new() 8153 pidgin_conv_window_new()
8191 { 8154 {
8192 PidginWindow *win; 8155 PidginWindow *win;
8193 GtkPositionType pos; 8156 GtkPositionType pos;
8197 win = g_malloc0(sizeof(PidginWindow)); 8160 win = g_malloc0(sizeof(PidginWindow));
8198 8161
8199 window_list = g_list_append(window_list, win); 8162 window_list = g_list_append(window_list, win);
8200 8163
8201 /* Create the window. */ 8164 /* Create the window. */
8202 win->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 8165 win->window = pidgin_create_window(NULL, 0, "conversation", TRUE);
8203 gtk_window_set_role(GTK_WINDOW(win->window), "conversation");
8204 gtk_window_set_resizable(GTK_WINDOW(win->window), TRUE);
8205 gtk_container_set_border_width(GTK_CONTAINER(win->window), 0);
8206 GTK_WINDOW(win->window)->allow_shrink = TRUE; 8166 GTK_WINDOW(win->window)->allow_shrink = TRUE;
8207 8167
8208 if (available_list == NULL) { 8168 if (available_list == NULL) {
8209 create_icon_lists(win->window); 8169 create_icon_lists(win->window);
8210 } 8170 }
8257 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0); 8217 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0);
8258 8218
8259 gtk_container_add(GTK_CONTAINER(win->window), testidea); 8219 gtk_container_add(GTK_CONTAINER(win->window), testidea);
8260 8220
8261 gtk_widget_show(testidea); 8221 gtk_widget_show(testidea);
8222
8223 /* Update the plugin actions when plugins are (un)loaded */
8224 purple_signal_connect(purple_plugins_get_handle(), "plugin-load",
8225 win, PURPLE_CALLBACK(plugin_changed_cb), win);
8226 purple_signal_connect(purple_plugins_get_handle(), "plugin-unload",
8227 win, PURPLE_CALLBACK(plugin_changed_cb), win);
8228
8262 8229
8263 #ifdef _WIN32 8230 #ifdef _WIN32
8264 g_signal_connect(G_OBJECT(win->window), "show", 8231 g_signal_connect(G_OBJECT(win->window), "show",
8265 G_CALLBACK(winpidgin_ensure_onscreen), win->window); 8232 G_CALLBACK(winpidgin_ensure_onscreen), win->window);
8266 #endif 8233 #endif
8297 gtk_widget_destroy(win->window); 8264 gtk_widget_destroy(win->window);
8298 8265
8299 g_object_unref(G_OBJECT(win->menu.item_factory)); 8266 g_object_unref(G_OBJECT(win->menu.item_factory));
8300 8267
8301 purple_notify_close_with_handle(win); 8268 purple_notify_close_with_handle(win);
8269 purple_signals_disconnect_by_handle(win);
8302 8270
8303 g_free(win); 8271 g_free(win);
8304 } 8272 }
8305 8273
8306 void 8274 void