pidgin/gtkconv.c

changeset 18178
d461ccafa1fb
parent 17715
9536709ee696
parent 18130
e1fd81854863
child 18185
d4f1719d812b
child 18191
087e7ed44d3d
equal deleted inserted replaced
17755:ed70e92f7c28 18178:d461ccafa1fb
270 270
271 static void 271 static void
272 default_formatize(PidginConversation *c) 272 default_formatize(PidginConversation *c)
273 { 273 {
274 PurpleConversation *conv = c->active_conv; 274 PurpleConversation *conv = c->active_conv;
275 275 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features);
276 if (conv->features & PURPLE_CONNECTION_HTML)
277 {
278 char color[8];
279 GdkColor fg_color, bg_color;
280
281 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold") != GTK_IMHTML(c->entry)->edit.bold)
282 gtk_imhtml_toggle_bold(GTK_IMHTML(c->entry));
283
284 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic") != GTK_IMHTML(c->entry)->edit.italic)
285 gtk_imhtml_toggle_italic(GTK_IMHTML(c->entry));
286
287 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline") != GTK_IMHTML(c->entry)->edit.underline)
288 gtk_imhtml_toggle_underline(GTK_IMHTML(c->entry));
289
290 gtk_imhtml_toggle_fontface(GTK_IMHTML(c->entry),
291 purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face"));
292
293 if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE))
294 {
295 int size = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size");
296
297 /* 3 is the default. */
298 if (size != 3)
299 gtk_imhtml_font_set_size(GTK_IMHTML(c->entry), size);
300 }
301
302 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), "") != 0)
303 {
304 gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"),
305 &fg_color);
306 g_snprintf(color, sizeof(color), "#%02x%02x%02x",
307 fg_color.red / 256,
308 fg_color.green / 256,
309 fg_color.blue / 256);
310 } else
311 strcpy(color, "");
312
313 gtk_imhtml_toggle_forecolor(GTK_IMHTML(c->entry), color);
314
315 if(!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR) &&
316 strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), "") != 0)
317 {
318 gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"),
319 &bg_color);
320 g_snprintf(color, sizeof(color), "#%02x%02x%02x",
321 bg_color.red / 256,
322 bg_color.green / 256,
323 bg_color.blue / 256);
324 } else
325 strcpy(color, "");
326
327 gtk_imhtml_toggle_background(GTK_IMHTML(c->entry), color);
328
329 if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)
330 gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), TRUE);
331 else
332 gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), FALSE);
333 }
334 } 276 }
335 277
336 static void 278 static void
337 clear_formatting_cb(GtkIMHtml *imhtml, PidginConversation *gtkconv) 279 clear_formatting_cb(GtkIMHtml *imhtml, PidginConversation *gtkconv)
338 { 280 {
476 { 418 {
477 PidginConversation *gtkconv; 419 PidginConversation *gtkconv;
478 char *cmd; 420 char *cmd;
479 const char *prefix; 421 const char *prefix;
480 GtkTextIter start; 422 GtkTextIter start;
423 gboolean retval = FALSE;
481 424
482 gtkconv = PIDGIN_CONVERSATION(conv); 425 gtkconv = PIDGIN_CONVERSATION(conv);
483 prefix = pidgin_get_cmd_prefix(); 426 prefix = pidgin_get_cmd_prefix();
484 427
485 cmd = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL); 428 cmd = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL);
499 442
500 gtk_text_iter_forward_chars(&start, g_utf8_strlen(prefix, -1)); 443 gtk_text_iter_forward_chars(&start, g_utf8_strlen(prefix, -1));
501 gtk_text_buffer_get_end_iter(GTK_IMHTML(gtkconv->entry)->text_buffer, &end); 444 gtk_text_buffer_get_end_iter(GTK_IMHTML(gtkconv->entry)->text_buffer, &end);
502 markup = gtk_imhtml_get_markup_range(GTK_IMHTML(gtkconv->entry), &start, &end); 445 markup = gtk_imhtml_get_markup_range(GTK_IMHTML(gtkconv->entry), &start, &end);
503 status = purple_cmd_do_command(conv, cmdline, markup, &error); 446 status = purple_cmd_do_command(conv, cmdline, markup, &error);
504 g_free(cmd);
505 g_free(markup); 447 g_free(markup);
506 448
507 switch (status) { 449 switch (status) {
508 case PURPLE_CMD_STATUS_OK: 450 case PURPLE_CMD_STATUS_OK:
509 return TRUE; 451 retval = TRUE;
452 break;
510 case PURPLE_CMD_STATUS_NOT_FOUND: 453 case PURPLE_CMD_STATUS_NOT_FOUND:
511 return FALSE; 454 {
455 PurplePluginProtocolInfo *prpl_info = NULL;
456 PurpleConnection *gc;
457
458 if ((gc = purple_conversation_get_gc(conv)))
459 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
460
461 if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) {
462 char *firstspace;
463 char *slash;
464
465 firstspace = strchr(cmdline, ' ');
466 if (firstspace != NULL) {
467 slash = strrchr(firstspace, '/');
468 } else {
469 slash = strchr(cmdline, '/');
470 }
471
472 if (slash == NULL) {
473 purple_conversation_write(conv, "", _("Unknown command."), PURPLE_MESSAGE_NO_LOG, time(NULL));
474 retval = TRUE;
475 }
476 }
477 break;
478 }
512 case PURPLE_CMD_STATUS_WRONG_ARGS: 479 case PURPLE_CMD_STATUS_WRONG_ARGS:
513 purple_conversation_write(conv, "", _("Syntax Error: You typed the wrong number of arguments " 480 purple_conversation_write(conv, "", _("Syntax Error: You typed the wrong number of arguments "
514 "to that command."), 481 "to that command."),
515 PURPLE_MESSAGE_NO_LOG, time(NULL)); 482 PURPLE_MESSAGE_NO_LOG, time(NULL));
516 return TRUE; 483 retval = TRUE;
484 break;
517 case PURPLE_CMD_STATUS_FAILED: 485 case PURPLE_CMD_STATUS_FAILED:
518 purple_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."), 486 purple_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."),
519 PURPLE_MESSAGE_NO_LOG, time(NULL)); 487 PURPLE_MESSAGE_NO_LOG, time(NULL));
520 g_free(error); 488 g_free(error);
521 return TRUE; 489 retval = TRUE;
490 break;
522 case PURPLE_CMD_STATUS_WRONG_TYPE: 491 case PURPLE_CMD_STATUS_WRONG_TYPE:
523 if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) 492 if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
524 purple_conversation_write(conv, "", _("That command only works in chats, not IMs."), 493 purple_conversation_write(conv, "", _("That command only works in chats, not IMs."),
525 PURPLE_MESSAGE_NO_LOG, time(NULL)); 494 PURPLE_MESSAGE_NO_LOG, time(NULL));
526 else 495 else
527 purple_conversation_write(conv, "", _("That command only works in IMs, not chats."), 496 purple_conversation_write(conv, "", _("That command only works in IMs, not chats."),
528 PURPLE_MESSAGE_NO_LOG, time(NULL)); 497 PURPLE_MESSAGE_NO_LOG, time(NULL));
529 return TRUE; 498 retval = TRUE;
499 break;
530 case PURPLE_CMD_STATUS_WRONG_PRPL: 500 case PURPLE_CMD_STATUS_WRONG_PRPL:
531 purple_conversation_write(conv, "", _("That command doesn't work on this protocol."), 501 purple_conversation_write(conv, "", _("That command doesn't work on this protocol."),
532 PURPLE_MESSAGE_NO_LOG, time(NULL)); 502 PURPLE_MESSAGE_NO_LOG, time(NULL));
533 return TRUE; 503 retval = TRUE;
504 break;
534 } 505 }
535 } 506 }
536 507
537 g_free(cmd); 508 g_free(cmd);
538 return FALSE; 509 return retval;
539 } 510 }
540 511
541 static void 512 static void
542 send_cb(GtkWidget *widget, PidginConversation *gtkconv) 513 send_cb(GtkWidget *widget, PidginConversation *gtkconv)
543 { 514 {
665 { 636 {
666 prpl_info->get_cb_info(gc, 637 prpl_info->get_cb_info(gc,
667 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); 638 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
668 } 639 }
669 else 640 else
670 prpl_info->get_info(gc, who); 641 pidgin_retrieve_user_info(gc, who);
671 } 642 }
672 } 643 }
673 644
674 645
675 static void 646 static void
676 info_cb(GtkWidget *widget, PidginConversation *gtkconv) 647 info_cb(GtkWidget *widget, PidginConversation *gtkconv)
677 { 648 {
678 PurpleConversation *conv = gtkconv->active_conv; 649 PurpleConversation *conv = gtkconv->active_conv;
679 650
680 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 651 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
681 PurpleNotifyUserInfo *info = purple_notify_user_info_new(); 652 pidgin_retrieve_user_info(purple_conversation_get_gc(conv),
682 purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving..."));
683 purple_notify_userinfo(conv->account->gc, purple_conversation_get_name(conv), info, NULL, NULL);
684 purple_notify_user_info_destroy(info);
685
686 serv_get_info(purple_conversation_get_gc(conv),
687 purple_conversation_get_name(conv)); 653 purple_conversation_get_name(conv));
688
689 gtk_widget_grab_focus(gtkconv->entry); 654 gtk_widget_grab_focus(gtkconv->entry);
690 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 655 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
691 /* Get info of the person currently selected in the GtkTreeView */ 656 /* Get info of the person currently selected in the GtkTreeView */
692 PidginChatPane *gtkchat; 657 PidginChatPane *gtkchat;
693 GtkTreeIter iter; 658 GtkTreeIter iter;
2271 **************************************************************************/ 2236 **************************************************************************/
2272 2237
2273 static GList *get_prpl_icon_list(PurpleAccount *account) 2238 static GList *get_prpl_icon_list(PurpleAccount *account)
2274 { 2239 {
2275 GList *l = NULL; 2240 GList *l = NULL;
2276 GdkPixbuf *pixbuf; 2241 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
2277 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); 2242 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
2278 const char *prpl = prpl_info->list_icon(account, NULL); 2243 const char *prplname = prpl_info->list_icon(account, NULL);
2279 char *filename, *path; 2244 l = g_hash_table_lookup(prpl_lists, prplname);
2280 l = g_hash_table_lookup(prpl_lists, prpl);
2281 if (l) 2245 if (l)
2282 return l; 2246 return l;
2283 filename = g_strdup_printf("%s.png", prpl); 2247
2284 2248 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE));
2285 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", filename, NULL); 2249 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM));
2286 pixbuf = gdk_pixbuf_new_from_file(path, NULL); 2250 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL));
2287 if (pixbuf) 2251
2288 l = g_list_append(l, pixbuf); 2252 g_hash_table_insert(prpl_lists, g_strdup(prplname), l);
2289 g_free(path);
2290
2291 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "22", filename, NULL);
2292 pixbuf = gdk_pixbuf_new_from_file(path, NULL);
2293 if (pixbuf)
2294 l = g_list_append(l, pixbuf);
2295 g_free(path);
2296
2297 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "48", filename, NULL);
2298 pixbuf = gdk_pixbuf_new_from_file(path, NULL);
2299 if (pixbuf)
2300 l = g_list_append(l, pixbuf);
2301 g_free(path);
2302
2303 g_hash_table_insert(prpl_lists, g_strdup(prpl), l);
2304 return l; 2253 return l;
2305 } 2254 }
2306 2255
2307 static GList * 2256 static GList *
2308 pidgin_conv_get_tab_icons(PurpleConversation *conv) 2257 pidgin_conv_get_tab_icons(PurpleConversation *conv)
2739 pidgin_conversations_find_unseen_list(PurpleConversationType type, 2688 pidgin_conversations_find_unseen_list(PurpleConversationType type,
2740 PidginUnseenState min_state, 2689 PidginUnseenState min_state,
2741 gboolean hidden_only, 2690 gboolean hidden_only,
2742 guint max_count) 2691 guint max_count)
2743 { 2692 {
2744 GList *l; 2693 const GList *l;
2745 GList *r = NULL; 2694 GList *r = NULL;
2746 guint c = 0; 2695 guint c = 0;
2747 2696
2748 if (type == PURPLE_CONV_TYPE_IM) { 2697 if (type == PURPLE_CONV_TYPE_IM) {
2749 l = purple_get_ims(); 2698 l = purple_get_ims();
3027 } 2976 }
3028 2977
3029 gtk_widget_show_all(menu); 2978 gtk_widget_show_all(menu);
3030 } 2979 }
3031 2980
2981 static void
2982 remove_from_list(GtkWidget *widget, PidginWindow *win)
2983 {
2984 GList *list = g_object_get_data(G_OBJECT(win->window), "plugin-actions");
2985 list = g_list_remove(list, widget);
2986 g_object_set_data(G_OBJECT(win->window), "plugin-actions", list);
2987 }
2988
2989 static void
2990 regenerate_plugins_items(PidginWindow *win)
2991 {
2992 GList *action_items;
2993 GtkWidget *menu;
2994 GList *list;
2995 PidginConversation *gtkconv;
2996 PurpleConversation *conv;
2997 GtkWidget *item;
2998
2999 if (win->window == NULL || win == hidden_convwin)
3000 return;
3001
3002 gtkconv = pidgin_conv_window_get_active_gtkconv(win);
3003 if (gtkconv == NULL)
3004 return;
3005
3006 conv = gtkconv->active_conv;
3007 action_items = g_object_get_data(G_OBJECT(win->window), "plugin-actions");
3008
3009 /* Remove the old menuitems */
3010 while (action_items) {
3011 g_signal_handlers_disconnect_by_func(G_OBJECT(action_items->data),
3012 G_CALLBACK(remove_from_list), win);
3013 gtk_widget_destroy(action_items->data);
3014 action_items = g_list_delete_link(action_items, action_items);
3015 }
3016
3017 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options"));
3018
3019 list = purple_conversation_get_extended_menu(conv);
3020 if (list) {
3021 action_items = g_list_prepend(NULL, (item = pidgin_separator(menu)));
3022 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
3023 }
3024
3025 for(; list; list = g_list_delete_link(list, list)) {
3026 PurpleMenuAction *act = (PurpleMenuAction *) list->data;
3027 item = pidgin_append_menu_action(menu, act, conv);
3028 action_items = g_list_prepend(action_items, item);
3029 gtk_widget_show_all(item);
3030 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
3031 }
3032 g_object_set_data(G_OBJECT(win->window), "plugin-actions", action_items);
3033 }
3034
3032 static void menubar_activated(GtkWidget *item, gpointer data) 3035 static void menubar_activated(GtkWidget *item, gpointer data)
3033 { 3036 {
3034 PidginWindow *win = data; 3037 PidginWindow *win = data;
3035 regenerate_options_items(win); 3038 regenerate_options_items(win);
3039 regenerate_plugins_items(win);
3036 3040
3037 /* The following are to make sure the 'More' submenu is not regenerated every time 3041 /* The following are to make sure the 'More' submenu is not regenerated every time
3038 * the focus shifts from 'Conversations' to some other menu and back. */ 3042 * the focus shifts from 'Conversations' to some other menu and back. */
3039 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data); 3043 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data);
3040 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data); 3044 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data);
3844 &matches, TRUE, l->data); 3848 &matches, TRUE, l->data);
3845 } 3849 }
3846 g_list_free(list); 3850 g_list_free(list);
3847 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 3851 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
3848 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); 3852 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
3849 GList *l = purple_conv_chat_get_users(chat); 3853 const GList *l = purple_conv_chat_get_users(chat);
3850 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list)); 3854 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list));
3851 GtkTreeIter iter; 3855 GtkTreeIter iter;
3852 int f; 3856 int f;
3853 3857
3854 /* Users */ 3858 /* Users */
4242 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE); 4246 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE);
4243 g_idle_add(reset_auto_resize_cb, gtkconv); 4247 g_idle_add(reset_auto_resize_cb, gtkconv);
4244 } 4248 }
4245 } 4249 }
4246 4250
4247 static GtkWidget * 4251 static void
4248 setup_chat_pane(PidginConversation *gtkconv) 4252 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox)
4249 { 4253 {
4250 PurplePluginProtocolInfo *prpl_info;
4251 PurpleConversation *conv = gtkconv->active_conv; 4254 PurpleConversation *conv = gtkconv->active_conv;
4252 PidginChatPane *gtkchat; 4255 PurpleConnection *gc = purple_conversation_get_gc(conv);
4253 PurpleConnection *gc; 4256 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
4254 GtkWidget *vpaned, *hpaned;
4255 GtkWidget *vbox, *hbox, *frame;
4256 GtkWidget *imhtml_sw;
4257 GtkPolicyType imhtml_sw_hscroll;
4258 GtkWidget *lbox;
4259 GtkWidget *label;
4260 GtkWidget *list;
4261 GtkWidget *sw;
4262 GtkListStore *ls;
4263 GtkCellRenderer *rend;
4264 GtkTreeViewColumn *col;
4265 void *blist_handle = purple_blist_get_handle();
4266 GList *focus_chain = NULL;
4267 int ul_width;
4268
4269 gtkchat = gtkconv->u.chat;
4270 gc = purple_conversation_get_gc(conv);
4271 g_return_val_if_fail(gc != NULL, NULL);
4272 g_return_val_if_fail(gc->prpl != NULL, NULL);
4273 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
4274
4275 /* Setup the outer pane. */
4276 vpaned = gtk_vpaned_new();
4277 gtk_widget_show(vpaned);
4278
4279 /* Setup the top part of the pane. */
4280 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4281 gtk_paned_pack1(GTK_PANED(vpaned), vbox, TRUE, TRUE);
4282 gtk_widget_show(vbox);
4283
4284 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) 4257 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC)
4285 { 4258 {
4259 GtkWidget *hbox, *label;
4260 PidginChatPane *gtkchat = gtkconv->u.chat;
4261
4286 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4262 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4287 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); 4263 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
4288 gtk_widget_show(hbox); 4264 gtk_widget_show(hbox);
4289 4265
4290 label = gtk_label_new(_("Topic:")); 4266 label = gtk_label_new(_("Topic:"));
4303 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0); 4279 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0);
4304 gtk_widget_show(gtkchat->topic_text); 4280 gtk_widget_show(gtkchat->topic_text);
4305 g_signal_connect(G_OBJECT(gtkchat->topic_text), "key_press_event", 4281 g_signal_connect(G_OBJECT(gtkchat->topic_text), "key_press_event",
4306 G_CALLBACK(entry_key_press_cb), gtkconv); 4282 G_CALLBACK(entry_key_press_cb), gtkconv);
4307 } 4283 }
4308 4284 }
4309 /* Setup the horizontal pane. */ 4285
4310 hpaned = gtk_hpaned_new(); 4286 static void
4311 gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); 4287 setup_chat_userlist(PidginConversation *gtkconv, GtkWidget *hpaned)
4312 gtk_widget_show(hpaned); 4288 {
4313 4289 PidginChatPane *gtkchat = gtkconv->u.chat;
4314 /* Setup gtkihmtml. */ 4290 GtkWidget *lbox, *sw, *list;
4315 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw); 4291 GtkListStore *ls;
4316 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); 4292 GtkCellRenderer *rend;
4317 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), TRUE); 4293 GtkTreeViewColumn *col;
4318 gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE); 4294 int ul_width;
4319 gtk_widget_show(frame); 4295 void *blist_handle = purple_blist_get_handle();
4320 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw), 4296 PurpleConversation *conv = gtkconv->active_conv;
4321 &imhtml_sw_hscroll, NULL);
4322 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4323 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4324
4325 gtk_widget_set_size_request(gtkconv->imhtml,
4326 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width"),
4327 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height"));
4328 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4329 G_CALLBACK(size_allocate_cb), gtkconv);
4330
4331 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4332 G_CALLBACK(entry_stop_rclick_cb), NULL);
4333 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4334 G_CALLBACK(refocus_entry_cb), gtkconv);
4335 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4336 G_CALLBACK(refocus_entry_cb), gtkconv);
4337 4297
4338 /* Build the right pane. */ 4298 /* Build the right pane. */
4339 lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4299 lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4340 gtk_paned_pack2(GTK_PANED(hpaned), lbox, FALSE, TRUE); 4300 gtk_paned_pack2(GTK_PANED(hpaned), lbox, FALSE, TRUE);
4341 gtk_widget_show(lbox); 4301 gtk_widget_show(lbox);
4379 G_CALLBACK(right_click_chat_cb), gtkconv); 4339 G_CALLBACK(right_click_chat_cb), gtkconv);
4380 g_signal_connect(G_OBJECT(list), "popup-menu", 4340 g_signal_connect(G_OBJECT(list), "popup-menu",
4381 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv); 4341 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv);
4382 g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv); 4342 g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv);
4383 4343
4384
4385 rend = gtk_cell_renderer_text_new(); 4344 rend = gtk_cell_renderer_text_new();
4386
4387 g_object_set(rend, 4345 g_object_set(rend,
4388 "foreground-set", TRUE, 4346 "foreground-set", TRUE,
4389 "weight-set", TRUE, 4347 "weight-set", TRUE,
4390 NULL); 4348 NULL);
4391 col = gtk_tree_view_column_new_with_attributes(NULL, rend, 4349 col = gtk_tree_view_column_new_with_attributes(NULL, rend,
4412 gtk_widget_show(list); 4370 gtk_widget_show(list);
4413 4371
4414 gtkchat->list = list; 4372 gtkchat->list = list;
4415 4373
4416 gtk_container_add(GTK_CONTAINER(sw), list); 4374 gtk_container_add(GTK_CONTAINER(sw), list);
4375 }
4376
4377 static GtkWidget *
4378 setup_common_pane(PidginConversation *gtkconv)
4379 {
4380 GtkWidget *paned, *vbox, *frame, *imhtml_sw;
4381 PurpleConversation *conv = gtkconv->active_conv;
4382 gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT);
4383 GtkPolicyType imhtml_sw_hscroll;
4384
4385 paned = gtk_vpaned_new();
4386 gtk_widget_show(paned);
4387
4388 /* Setup the top part of the pane */
4389 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4390 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
4391 gtk_widget_show(vbox);
4392
4393 /* Setup the gtkimhtml widget */
4394 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
4395 if (chat) {
4396 GtkWidget *hpaned;
4397
4398 /* Add the topic */
4399 setup_chat_topic(gtkconv, vbox);
4400
4401 /* Add the gtkimhtml frame */
4402 hpaned = gtk_hpaned_new();
4403 gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0);
4404 gtk_widget_show(hpaned);
4405 gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE);
4406
4407 /* Now add the userlist */
4408 setup_chat_userlist(gtkconv, hpaned);
4409 } else {
4410 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4411 }
4412 gtk_widget_show(frame);
4413
4414 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
4415 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE);
4416
4417 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4418 &imhtml_sw_hscroll, NULL);
4419 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4420 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4421
4422 gtk_widget_set_size_request(gtkconv->imhtml,
4423 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width") :
4424 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"),
4425 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height") :
4426 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height"));
4427
4428 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4429 G_CALLBACK(size_allocate_cb), gtkconv);
4430
4431 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4432 G_CALLBACK(entry_stop_rclick_cb), NULL);
4433 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4434 G_CALLBACK(refocus_entry_cb), gtkconv);
4435 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4436 G_CALLBACK(refocus_entry_cb), gtkconv);
4417 4437
4418 /* Setup the bottom half of the conversation window */ 4438 /* Setup the bottom half of the conversation window */
4419 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4439 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4420 gtk_paned_pack2(GTK_PANED(vpaned), vbox, FALSE, TRUE); 4440 gtk_paned_pack2(GTK_PANED(paned), vbox, FALSE, TRUE);
4421 gtk_widget_show(vbox); 4441 gtk_widget_show(vbox);
4422 4442
4423 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 4443 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4424 gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0); 4444 gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0);
4425 gtk_widget_show(gtkconv->lower_hbox); 4445 gtk_widget_show(gtkconv->lower_hbox);
4431 /* Setup the toolbar, entry widget and all signals */ 4451 /* Setup the toolbar, entry widget and all signals */
4432 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL); 4452 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL);
4433 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); 4453 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4434 gtk_widget_show(frame); 4454 gtk_widget_show(frame);
4435 4455
4436 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4437 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4438
4439 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); 4456 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
4440 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), 4457 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
4441 purple_account_get_protocol_name(conv->account)); 4458 purple_account_get_protocol_name(conv->account));
4442 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, 4459 gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
4443 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height")); 4460 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height") :
4444 gtkconv->entry_buffer = 4461 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height"));
4445 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); 4462
4446 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); 4463 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4447 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", 4464 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4448 G_CALLBACK(resize_imhtml_cb), gtkconv);
4449
4450 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 4465 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event",
4451 G_CALLBACK(entry_key_press_cb), gtkconv); 4466 G_CALLBACK(entry_key_press_cb), gtkconv);
4452 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", 4467 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send",
4453 G_CALLBACK(send_cb), gtkconv); 4468 G_CALLBACK(send_cb), gtkconv);
4454 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", 4469 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event",
4455 G_CALLBACK(entry_stop_rclick_cb), NULL); 4470 G_CALLBACK(entry_stop_rclick_cb), NULL);
4456 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", 4471 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate",
4457 G_CALLBACK(size_allocate_cb), gtkconv); 4472 G_CALLBACK(size_allocate_cb), gtkconv);
4458 4473
4459 default_formatize(gtkconv);
4460
4461 /*
4462 * Focus for chat windows should be as follows:
4463 * Tab title -> chat topic -> conversation scrollback -> user list ->
4464 * user list buttons -> entry -> buttons at bottom
4465 */
4466 focus_chain = g_list_prepend(focus_chain, gtkconv->entry);
4467 gtk_container_set_focus_chain(GTK_CONTAINER(vbox), focus_chain);
4468
4469 return vpaned;
4470 }
4471
4472 static GtkWidget *
4473 setup_im_pane(PidginConversation *gtkconv)
4474 {
4475 PurpleConversation *conv = gtkconv->active_conv;
4476 GtkWidget *frame;
4477 GtkWidget *imhtml_sw;
4478 GtkPolicyType imhtml_sw_hscroll;
4479 GtkWidget *paned;
4480 GtkWidget *vbox;
4481 GtkWidget *vbox2;
4482 GList *focus_chain = NULL;
4483
4484 /* Setup the outer pane */
4485 paned = gtk_vpaned_new();
4486 gtk_widget_show(paned);
4487
4488 /* Setup the top part of the pane */
4489 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4490 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
4491 gtk_widget_show(vbox);
4492
4493 /* Setup the gtkimhtml widget */
4494 frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
4495 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
4496 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE);
4497 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
4498 gtk_widget_show(frame);
4499 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4500 &imhtml_sw_hscroll, NULL);
4501 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
4502 imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
4503
4504 gtk_widget_set_size_request(gtkconv->imhtml,
4505 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"),
4506 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height"));
4507 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
4508 G_CALLBACK(size_allocate_cb), gtkconv);
4509
4510 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
4511 G_CALLBACK(entry_stop_rclick_cb), NULL);
4512 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
4513 G_CALLBACK(refocus_entry_cb), gtkconv);
4514 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
4515 G_CALLBACK(refocus_entry_cb), gtkconv);
4516
4517 /* Setup the bottom half of the conversation window */
4518 vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4519 gtk_paned_pack2(GTK_PANED(paned), vbox2, FALSE, TRUE);
4520 gtk_widget_show(vbox2);
4521
4522 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4523 gtk_box_pack_start(GTK_BOX(vbox2), gtkconv->lower_hbox, TRUE, TRUE, 0);
4524 gtk_widget_show(gtkconv->lower_hbox);
4525
4526 vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
4527 gtk_box_pack_end(GTK_BOX(gtkconv->lower_hbox), vbox2, TRUE, TRUE, 0);
4528 gtk_widget_show(vbox2);
4529
4530 /* Setup the toolbar, entry widget and all signals */
4531 frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL);
4532 gtk_box_pack_start(GTK_BOX(vbox2), frame, TRUE, TRUE, 0);
4533 gtk_widget_show(frame);
4534
4535 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
4536 G_CALLBACK(entry_popup_menu_cb), gtkconv);
4537
4538 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
4539 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
4540 purple_account_get_protocol_name(conv->account));
4541 gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
4542 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height"));
4543 gtkconv->entry_buffer = 4474 gtkconv->entry_buffer =
4544 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); 4475 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry));
4545 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); 4476 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv);
4546 4477
4547 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", 4478 if (!chat) {
4548 G_CALLBACK(entry_key_press_cb), gtkconv); 4479 /* For sending typing notifications for IMs */
4549 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", 4480 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text",
4550 G_CALLBACK(send_cb), gtkconv); 4481 G_CALLBACK(insert_text_cb), gtkconv);
4551 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", 4482 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range",
4552 G_CALLBACK(entry_stop_rclick_cb), NULL); 4483 G_CALLBACK(delete_text_cb), gtkconv);
4553 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", 4484 gtkconv->u.im->typing_timer = 0;
4554 G_CALLBACK(size_allocate_cb), gtkconv); 4485 gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons");
4555 4486 gtkconv->u.im->show_icon = TRUE;
4556 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", 4487 }
4557 G_CALLBACK(insert_text_cb), gtkconv); 4488
4558 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range",
4559 G_CALLBACK(delete_text_cb), gtkconv);
4560 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", 4489 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed",
4561 G_CALLBACK(resize_imhtml_cb), gtkconv); 4490 G_CALLBACK(resize_imhtml_cb), gtkconv);
4562 4491
4563 /* had to move this after the imtoolbar is attached so that the
4564 * signals get fired to toggle the buttons on the toolbar as well.
4565 */
4566 default_formatize(gtkconv); 4492 default_formatize(gtkconv);
4567
4568 g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear", 4493 g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear",
4569 G_CALLBACK(clear_formatting_cb), gtkconv); 4494 G_CALLBACK(clear_formatting_cb), gtkconv);
4570 4495
4571 gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons");
4572 gtkconv->u.im->show_icon = TRUE;
4573
4574 /*
4575 * Focus for IM windows should be as follows:
4576 * Tab title -> conversation scrollback -> entry
4577 */
4578 focus_chain = g_list_prepend(focus_chain, gtkconv->entry);
4579 gtk_container_set_focus_chain(GTK_CONTAINER(vbox2), focus_chain);
4580
4581 gtkconv->u.im->typing_timer = 0;
4582 return paned; 4496 return paned;
4583 } 4497 }
4584 4498
4585 static void 4499 static void
4586 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, 4500 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y,
4772 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; 4686 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
4773 gtkconv->unseen_count = 0; 4687 gtkconv->unseen_count = 0;
4774 4688
4775 if (conv_type == PURPLE_CONV_TYPE_IM) { 4689 if (conv_type == PURPLE_CONV_TYPE_IM) {
4776 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); 4690 gtkconv->u.im = g_malloc0(sizeof(PidginImPane));
4777
4778 pane = setup_im_pane(gtkconv);
4779 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { 4691 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) {
4780 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); 4692 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane));
4781 pane = setup_chat_pane(gtkconv); 4693 }
4782 } 4694 pane = setup_common_pane(gtkconv);
4783 4695
4784 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml), 4696 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml),
4785 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE); 4697 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE);
4786 4698
4787 if (pane == NULL) { 4699 if (pane == NULL) {
5175 g_return_if_fail(account != NULL); 5087 g_return_if_fail(account != NULL);
5176 gc = purple_account_get_connection(account); 5088 gc = purple_account_get_connection(account);
5177 g_return_if_fail(gc != NULL); 5089 g_return_if_fail(gc != NULL);
5178 5090
5179 /* Make sure URLs are clickable */ 5091 /* Make sure URLs are clickable */
5180 displaying = purple_markup_linkify(message); 5092 if(flags & PURPLE_MESSAGE_NO_LINKIFY)
5093 displaying = g_strdup(message);
5094 else
5095 displaying = purple_markup_linkify(message);
5096
5181 plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( 5097 plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1(
5182 pidgin_conversations_get_handle(), (type == PURPLE_CONV_TYPE_IM ? 5098 pidgin_conversations_get_handle(), (type == PURPLE_CONV_TYPE_IM ?
5183 "displaying-im-msg" : "displaying-chat-msg"), 5099 "displaying-im-msg" : "displaying-chat-msg"),
5184 account, name, &displaying, conv, flags)); 5100 account, name, &displaying, conv, flags));
5185 if (plugin_return) 5101 if (plugin_return)
5528 5444
5529 chat = PURPLE_CONV_CHAT(conv); 5445 chat = PURPLE_CONV_CHAT(conv);
5530 gtkconv = PIDGIN_CONVERSATION(conv); 5446 gtkconv = PIDGIN_CONVERSATION(conv);
5531 gtkchat = gtkconv->u.chat; 5447 gtkchat = gtkconv->u.chat;
5532 5448
5533 num_users = g_list_length(purple_conv_chat_get_users(chat)); 5449 num_users = g_list_length((GList *)purple_conv_chat_get_users(chat));
5534 5450
5535 g_snprintf(tmp, sizeof(tmp), 5451 g_snprintf(tmp, sizeof(tmp),
5536 ngettext("%d person in room", "%d people in room", 5452 ngettext("%d person in room", "%d people in room",
5537 num_users), 5453 num_users),
5538 num_users); 5454 num_users);
5622 5538
5623 chat = PURPLE_CONV_CHAT(conv); 5539 chat = PURPLE_CONV_CHAT(conv);
5624 gtkconv = PIDGIN_CONVERSATION(conv); 5540 gtkconv = PIDGIN_CONVERSATION(conv);
5625 gtkchat = gtkconv->u.chat; 5541 gtkchat = gtkconv->u.chat;
5626 5542
5627 num_users = g_list_length(purple_conv_chat_get_users(chat)); 5543 num_users = g_list_length((GList *)purple_conv_chat_get_users(chat));
5628 5544
5629 for (l = users; l != NULL; l = l->next) { 5545 for (l = users; l != NULL; l = l->next) {
5630 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); 5546 model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
5631 5547
5632 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) 5548 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
6619 6535
6620 static void 6536 static void
6621 close_on_tabs_pref_cb(const char *name, PurplePrefType type, 6537 close_on_tabs_pref_cb(const char *name, PurplePrefType type,
6622 gconstpointer value, gpointer data) 6538 gconstpointer value, gpointer data)
6623 { 6539 {
6624 GList *l; 6540 const GList *l;
6625 PurpleConversation *conv; 6541 PurpleConversation *conv;
6626 PidginConversation *gtkconv; 6542 PidginConversation *gtkconv;
6627 6543
6628 for (l = purple_get_conversations(); l != NULL; l = l->next) { 6544 for (l = purple_get_conversations(); l != NULL; l = l->next) {
6629 conv = (PurpleConversation *)l->data; 6545 conv = (PurpleConversation *)l->data;
6643 static void 6559 static void
6644 spellcheck_pref_cb(const char *name, PurplePrefType type, 6560 spellcheck_pref_cb(const char *name, PurplePrefType type,
6645 gconstpointer value, gpointer data) 6561 gconstpointer value, gpointer data)
6646 { 6562 {
6647 #ifdef USE_GTKSPELL 6563 #ifdef USE_GTKSPELL
6648 GList *cl; 6564 const GList *cl;
6649 PurpleConversation *conv; 6565 PurpleConversation *conv;
6650 PidginConversation *gtkconv; 6566 PidginConversation *gtkconv;
6651 GtkSpell *spell; 6567 GtkSpell *spell;
6652 6568
6653 for (cl = purple_get_conversations(); cl != NULL; cl = cl->next) { 6569 for (cl = purple_get_conversations(); cl != NULL; cl = cl->next) {
6690 6606
6691 static void 6607 static void
6692 show_timestamps_pref_cb(const char *name, PurplePrefType type, 6608 show_timestamps_pref_cb(const char *name, PurplePrefType type,
6693 gconstpointer value, gpointer data) 6609 gconstpointer value, gpointer data)
6694 { 6610 {
6695 GList *l; 6611 const GList *l;
6696 PurpleConversation *conv; 6612 PurpleConversation *conv;
6697 PidginConversation *gtkconv; 6613 PidginConversation *gtkconv;
6698 PidginWindow *win; 6614 PidginWindow *win;
6699 6615
6700 for (l = purple_get_conversations(); l != NULL; l = l->next) 6616 for (l = purple_get_conversations(); l != NULL; l = l->next)
6718 6634
6719 static void 6635 static void
6720 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type, 6636 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type,
6721 gconstpointer value, gpointer data) 6637 gconstpointer value, gpointer data)
6722 { 6638 {
6723 GList *l; 6639 const GList *l;
6724 PurpleConversation *conv; 6640 PurpleConversation *conv;
6725 PidginConversation *gtkconv; 6641 PidginConversation *gtkconv;
6726 PidginWindow *win; 6642 PidginWindow *win;
6727 6643
6728 for (l = purple_get_conversations(); l != NULL; l = l->next) 6644 for (l = purple_get_conversations(); l != NULL; l = l->next)
6748 6664
6749 static void 6665 static void
6750 animate_buddy_icons_pref_cb(const char *name, PurplePrefType type, 6666 animate_buddy_icons_pref_cb(const char *name, PurplePrefType type,
6751 gconstpointer value, gpointer data) 6667 gconstpointer value, gpointer data)
6752 { 6668 {
6753 GList *l; 6669 const GList *l;
6754 PurpleConversation *conv; 6670 PurpleConversation *conv;
6755 PidginConversation *gtkconv; 6671 PidginConversation *gtkconv;
6756 PidginWindow *win; 6672 PidginWindow *win;
6757 6673
6758 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons")) 6674 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons"))
6775 6691
6776 static void 6692 static void
6777 show_buddy_icons_pref_cb(const char *name, PurplePrefType type, 6693 show_buddy_icons_pref_cb(const char *name, PurplePrefType type,
6778 gconstpointer value, gpointer data) 6694 gconstpointer value, gpointer data)
6779 { 6695 {
6780 GList *l; 6696 const GList *l;
6781 6697
6782 for (l = purple_get_conversations(); l != NULL; l = l->next) { 6698 for (l = purple_get_conversations(); l != NULL; l = l->next) {
6783 PurpleConversation *conv = l->data; 6699 PurpleConversation *conv = l->data;
6784 6700
6785 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) 6701 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
6901 } 6817 }
6902 6818
6903 static void 6819 static void
6904 account_signed_off_cb(PurpleConnection *gc, gpointer event) 6820 account_signed_off_cb(PurpleConnection *gc, gpointer event)
6905 { 6821 {
6906 GList *iter; 6822 const GList *iter;
6907 6823
6908 for (iter = purple_get_conversations(); iter; iter = iter->next) 6824 for (iter = purple_get_conversations(); iter; iter = iter->next)
6909 { 6825 {
6910 PurpleConversation *conv = iter->data; 6826 PurpleConversation *conv = iter->data;
6911 6827
8090 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging), 8006 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging),
8091 purple_conversation_is_logging(conv)); 8007 purple_conversation_is_logging(conv));
8092 8008
8093 generate_send_to_items(win); 8009 generate_send_to_items(win);
8094 regenerate_options_items(win); 8010 regenerate_options_items(win);
8011 regenerate_plugins_items(win);
8095 8012
8096 pidgin_conv_switch_active_conversation(conv); 8013 pidgin_conv_switch_active_conversation(conv);
8097 8014
8098 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); 8015 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method");
8099 if (strcmp(sound_method, "none") != 0) 8016 if (strcmp(sound_method, "none") != 0)
8160 offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w); 8077 offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w);
8161 away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w); 8078 away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w);
8162 prpl_lists = g_hash_table_new(g_str_hash, g_str_equal); 8079 prpl_lists = g_hash_table_new(g_str_hash, g_str_equal);
8163 } 8080 }
8164 8081
8082 static void
8083 plugin_changed_cb(PurplePlugin *p, gpointer data)
8084 {
8085 regenerate_plugins_items(data);
8086 }
8087
8165 PidginWindow * 8088 PidginWindow *
8166 pidgin_conv_window_new() 8089 pidgin_conv_window_new()
8167 { 8090 {
8168 PidginWindow *win; 8091 PidginWindow *win;
8169 GtkPositionType pos; 8092 GtkPositionType pos;
8173 win = g_malloc0(sizeof(PidginWindow)); 8096 win = g_malloc0(sizeof(PidginWindow));
8174 8097
8175 window_list = g_list_append(window_list, win); 8098 window_list = g_list_append(window_list, win);
8176 8099
8177 /* Create the window. */ 8100 /* Create the window. */
8178 win->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 8101 win->window = pidgin_create_window(NULL, 0, "conversation", TRUE);
8179 gtk_window_set_role(GTK_WINDOW(win->window), "conversation");
8180 gtk_window_set_resizable(GTK_WINDOW(win->window), TRUE);
8181 gtk_container_set_border_width(GTK_CONTAINER(win->window), 0);
8182 GTK_WINDOW(win->window)->allow_shrink = TRUE; 8102 GTK_WINDOW(win->window)->allow_shrink = TRUE;
8183 8103
8184 if (available_list == NULL) { 8104 if (available_list == NULL) {
8185 create_icon_lists(win->window); 8105 create_icon_lists(win->window);
8186 } 8106 }
8233 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0); 8153 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0);
8234 8154
8235 gtk_container_add(GTK_CONTAINER(win->window), testidea); 8155 gtk_container_add(GTK_CONTAINER(win->window), testidea);
8236 8156
8237 gtk_widget_show(testidea); 8157 gtk_widget_show(testidea);
8158
8159 /* Update the plugin actions when plugins are (un)loaded */
8160 purple_signal_connect(purple_plugins_get_handle(), "plugin-load",
8161 win, PURPLE_CALLBACK(plugin_changed_cb), win);
8162 purple_signal_connect(purple_plugins_get_handle(), "plugin-unload",
8163 win, PURPLE_CALLBACK(plugin_changed_cb), win);
8164
8238 8165
8239 #ifdef _WIN32 8166 #ifdef _WIN32
8240 g_signal_connect(G_OBJECT(win->window), "show", 8167 g_signal_connect(G_OBJECT(win->window), "show",
8241 G_CALLBACK(winpidgin_ensure_onscreen), win->window); 8168 G_CALLBACK(winpidgin_ensure_onscreen), win->window);
8242 #endif 8169 #endif
8273 gtk_widget_destroy(win->window); 8200 gtk_widget_destroy(win->window);
8274 8201
8275 g_object_unref(G_OBJECT(win->menu.item_factory)); 8202 g_object_unref(G_OBJECT(win->menu.item_factory));
8276 8203
8277 purple_notify_close_with_handle(win); 8204 purple_notify_close_with_handle(win);
8205 purple_signals_disconnect_by_handle(win);
8278 8206
8279 g_free(win); 8207 g_free(win);
8280 } 8208 }
8281 8209
8282 void 8210 void

mercurial