| 17398:1edf059a4a26 | 18545:5af898e91ec2 |
|---|---|
| 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" |
| 78 PIDGIN_CONV_TAB_ICON = 1 << 3, | 79 PIDGIN_CONV_TAB_ICON = 1 << 3, |
| 79 PIDGIN_CONV_TOPIC = 1 << 4, | 80 PIDGIN_CONV_TOPIC = 1 << 4, |
| 80 PIDGIN_CONV_SMILEY_THEME = 1 << 5, | 81 PIDGIN_CONV_SMILEY_THEME = 1 << 5, |
| 81 PIDGIN_CONV_COLORIZE_TITLE = 1 << 6 | 82 PIDGIN_CONV_COLORIZE_TITLE = 1 << 6 |
| 82 }PidginConvFields; | 83 }PidginConvFields; |
| 84 | |
| 85 enum { | |
| 86 ICON_COLUMN, | |
| 87 TEXT_COLUMN, | |
| 88 NUM_COLUMNS | |
| 89 } PidginInfopaneColumns; | |
| 83 | 90 |
| 84 #define PIDGIN_CONV_ALL ((1 << 7) - 1) | 91 #define PIDGIN_CONV_ALL ((1 << 7) - 1) |
| 85 | 92 |
| 86 #define SEND_COLOR "#204a87" | 93 #define SEND_COLOR "#204a87" |
| 87 #define RECV_COLOR "#cc0000" | 94 #define RECV_COLOR "#cc0000" |
| 175 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); | 182 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); |
| 176 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); | 183 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); |
| 177 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); | 184 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); |
| 178 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); | 185 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); |
| 179 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); | 186 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); |
| 187 static gboolean infopane_release_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); | |
| 188 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); | |
| 180 | 189 |
| 181 static GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { | 190 static GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { |
| 182 static GdkColor col; | 191 static GdkColor col; |
| 183 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); | 192 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); |
| 184 float scale; | 193 float scale; |
| 230 | 239 |
| 231 if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv)) | 240 if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv)) |
| 232 return FALSE; | 241 return FALSE; |
| 233 | 242 |
| 234 if (gtkconv->auto_resize) { | 243 if (gtkconv->auto_resize) { |
| 244 return FALSE; | |
| 245 } | |
| 246 | |
| 247 if (gdk_window_get_state(gtkconv->win->window->window) & GDK_WINDOW_STATE_MAXIMIZED) { | |
| 235 return FALSE; | 248 return FALSE; |
| 236 } | 249 } |
| 237 | 250 |
| 238 /* I find that I resize the window when it has a bunch of conversations in it, mostly so that the | 251 /* I find that I resize the window when it has a bunch of conversations in it, mostly so that the |
| 239 * tab bar will fit, but then I don't want new windows taking up the entire screen. I check to see | 252 * tab bar will fit, but then I don't want new windows taking up the entire screen. I check to see |
| 241 * size of the last resized new window. */ | 254 * size of the last resized new window. */ |
| 242 /* I think that the above justification is not the majority, and that the new tab resizing should | 255 /* I think that the above justification is not the majority, and that the new tab resizing should |
| 243 * negate it anyway. --luke */ | 256 * negate it anyway. --luke */ |
| 244 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) | 257 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) |
| 245 { | 258 { |
| 246 if (w == gtkconv->imhtml) { | |
| 247 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width", allocation->width); | |
| 248 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height", allocation->height); | |
| 249 } | |
| 250 if (w == gtkconv->lower_hbox) | 259 if (w == gtkconv->lower_hbox) |
| 251 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height", allocation->height); | 260 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height", allocation->height); |
| 252 } | 261 } |
| 253 else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) | 262 else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) |
| 254 { | 263 { |
| 255 if (w == gtkconv->imhtml) { | |
| 256 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width", allocation->width); | |
| 257 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height", allocation->height); | |
| 258 } | |
| 259 if (w == gtkconv->lower_hbox) | 264 if (w == gtkconv->lower_hbox) |
| 260 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height", allocation->height); | 265 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height", allocation->height); |
| 261 } | 266 } |
| 262 | 267 |
| 263 return FALSE; | 268 return FALSE; |
| 265 | 270 |
| 266 static void | 271 static void |
| 267 default_formatize(PidginConversation *c) | 272 default_formatize(PidginConversation *c) |
| 268 { | 273 { |
| 269 PurpleConversation *conv = c->active_conv; | 274 PurpleConversation *conv = c->active_conv; |
| 270 | 275 gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features); |
| 271 if (conv->features & PURPLE_CONNECTION_HTML) | |
| 272 { | |
| 273 char color[8]; | |
| 274 GdkColor fg_color, bg_color; | |
| 275 | |
| 276 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold") != GTK_IMHTML(c->entry)->edit.bold) | |
| 277 gtk_imhtml_toggle_bold(GTK_IMHTML(c->entry)); | |
| 278 | |
| 279 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic") != GTK_IMHTML(c->entry)->edit.italic) | |
| 280 gtk_imhtml_toggle_italic(GTK_IMHTML(c->entry)); | |
| 281 | |
| 282 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline") != GTK_IMHTML(c->entry)->edit.underline) | |
| 283 gtk_imhtml_toggle_underline(GTK_IMHTML(c->entry)); | |
| 284 | |
| 285 gtk_imhtml_toggle_fontface(GTK_IMHTML(c->entry), | |
| 286 purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face")); | |
| 287 | |
| 288 if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE)) | |
| 289 { | |
| 290 int size = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size"); | |
| 291 | |
| 292 /* 3 is the default. */ | |
| 293 if (size != 3) | |
| 294 gtk_imhtml_font_set_size(GTK_IMHTML(c->entry), size); | |
| 295 } | |
| 296 | |
| 297 if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), "") != 0) | |
| 298 { | |
| 299 gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), | |
| 300 &fg_color); | |
| 301 g_snprintf(color, sizeof(color), "#%02x%02x%02x", | |
| 302 fg_color.red / 256, | |
| 303 fg_color.green / 256, | |
| 304 fg_color.blue / 256); | |
| 305 } else | |
| 306 strcpy(color, ""); | |
| 307 | |
| 308 gtk_imhtml_toggle_forecolor(GTK_IMHTML(c->entry), color); | |
| 309 | |
| 310 if(!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR) && | |
| 311 strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), "") != 0) | |
| 312 { | |
| 313 gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), | |
| 314 &bg_color); | |
| 315 g_snprintf(color, sizeof(color), "#%02x%02x%02x", | |
| 316 bg_color.red / 256, | |
| 317 bg_color.green / 256, | |
| 318 bg_color.blue / 256); | |
| 319 } else | |
| 320 strcpy(color, ""); | |
| 321 | |
| 322 gtk_imhtml_toggle_background(GTK_IMHTML(c->entry), color); | |
| 323 | |
| 324 if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO) | |
| 325 gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), TRUE); | |
| 326 else | |
| 327 gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), FALSE); | |
| 328 } | |
| 329 } | 276 } |
| 330 | 277 |
| 331 static void | 278 static void |
| 332 clear_formatting_cb(GtkIMHtml *imhtml, PidginConversation *gtkconv) | 279 clear_formatting_cb(GtkIMHtml *imhtml, PidginConversation *gtkconv) |
| 333 { | 280 { |
| 390 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL)); | 337 PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL)); |
| 391 return PURPLE_CMD_STATUS_OK; | 338 return PURPLE_CMD_STATUS_OK; |
| 392 } | 339 } |
| 393 } | 340 } |
| 394 | 341 |
| 342 static void clear_conversation_scrollback(PurpleConversation *conv) | |
| 343 { | |
| 344 PidginConversation *gtkconv = NULL; | |
| 345 | |
| 346 gtkconv = PIDGIN_CONVERSATION(conv); | |
| 347 | |
| 348 gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); | |
| 349 } | |
| 350 | |
| 395 static PurpleCmdRet | 351 static PurpleCmdRet |
| 396 clear_command_cb(PurpleConversation *conv, | 352 clear_command_cb(PurpleConversation *conv, |
| 397 const char *cmd, char **args, char **error, void *data) | 353 const char *cmd, char **args, char **error, void *data) |
| 398 { | 354 { |
| 399 PidginConversation *gtkconv = NULL; | 355 clear_conversation_scrollback(conv); |
| 400 | 356 return PURPLE_CMD_STATUS_OK; |
| 401 gtkconv = PIDGIN_CONVERSATION(conv); | 357 } |
| 402 | 358 |
| 403 gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); | 359 static PurpleCmdRet |
| 360 clearall_command_cb(PurpleConversation *conv, | |
| 361 const char *cmd, char **args, char **error, void *data) | |
| 362 { | |
| 363 purple_conversation_foreach(clear_conversation_scrollback); | |
| 404 return PURPLE_CMD_STATUS_OK; | 364 return PURPLE_CMD_STATUS_OK; |
| 405 } | 365 } |
| 406 | 366 |
| 407 static PurpleCmdRet | 367 static PurpleCmdRet |
| 408 help_command_cb(PurpleConversation *conv, | 368 help_command_cb(PurpleConversation *conv, |
| 471 { | 431 { |
| 472 PidginConversation *gtkconv; | 432 PidginConversation *gtkconv; |
| 473 char *cmd; | 433 char *cmd; |
| 474 const char *prefix; | 434 const char *prefix; |
| 475 GtkTextIter start; | 435 GtkTextIter start; |
| 436 gboolean retval = FALSE; | |
| 476 | 437 |
| 477 gtkconv = PIDGIN_CONVERSATION(conv); | 438 gtkconv = PIDGIN_CONVERSATION(conv); |
| 478 prefix = pidgin_get_cmd_prefix(); | 439 prefix = pidgin_get_cmd_prefix(); |
| 479 | 440 |
| 480 cmd = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL); | 441 cmd = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL); |
| 494 | 455 |
| 495 gtk_text_iter_forward_chars(&start, g_utf8_strlen(prefix, -1)); | 456 gtk_text_iter_forward_chars(&start, g_utf8_strlen(prefix, -1)); |
| 496 gtk_text_buffer_get_end_iter(GTK_IMHTML(gtkconv->entry)->text_buffer, &end); | 457 gtk_text_buffer_get_end_iter(GTK_IMHTML(gtkconv->entry)->text_buffer, &end); |
| 497 markup = gtk_imhtml_get_markup_range(GTK_IMHTML(gtkconv->entry), &start, &end); | 458 markup = gtk_imhtml_get_markup_range(GTK_IMHTML(gtkconv->entry), &start, &end); |
| 498 status = purple_cmd_do_command(conv, cmdline, markup, &error); | 459 status = purple_cmd_do_command(conv, cmdline, markup, &error); |
| 499 g_free(cmd); | |
| 500 g_free(markup); | 460 g_free(markup); |
| 501 | 461 |
| 502 switch (status) { | 462 switch (status) { |
| 503 case PURPLE_CMD_STATUS_OK: | 463 case PURPLE_CMD_STATUS_OK: |
| 504 return TRUE; | 464 retval = TRUE; |
| 465 break; | |
| 505 case PURPLE_CMD_STATUS_NOT_FOUND: | 466 case PURPLE_CMD_STATUS_NOT_FOUND: |
| 506 return FALSE; | 467 { |
| 468 PurplePluginProtocolInfo *prpl_info = NULL; | |
| 469 PurpleConnection *gc; | |
| 470 | |
| 471 if ((gc = purple_conversation_get_gc(conv))) | |
| 472 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
| 473 | |
| 474 if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) { | |
| 475 char *firstspace; | |
| 476 char *slash; | |
| 477 | |
| 478 firstspace = strchr(cmdline, ' '); | |
| 479 if (firstspace != NULL) { | |
| 480 slash = strrchr(firstspace, '/'); | |
| 481 } else { | |
| 482 slash = strchr(cmdline, '/'); | |
| 483 } | |
| 484 | |
| 485 if (slash == NULL) { | |
| 486 purple_conversation_write(conv, "", _("Unknown command."), PURPLE_MESSAGE_NO_LOG, time(NULL)); | |
| 487 retval = TRUE; | |
| 488 } | |
| 489 } | |
| 490 break; | |
| 491 } | |
| 507 case PURPLE_CMD_STATUS_WRONG_ARGS: | 492 case PURPLE_CMD_STATUS_WRONG_ARGS: |
| 508 purple_conversation_write(conv, "", _("Syntax Error: You typed the wrong number of arguments " | 493 purple_conversation_write(conv, "", _("Syntax Error: You typed the wrong number of arguments " |
| 509 "to that command."), | 494 "to that command."), |
| 510 PURPLE_MESSAGE_NO_LOG, time(NULL)); | 495 PURPLE_MESSAGE_NO_LOG, time(NULL)); |
| 511 return TRUE; | 496 retval = TRUE; |
| 497 break; | |
| 512 case PURPLE_CMD_STATUS_FAILED: | 498 case PURPLE_CMD_STATUS_FAILED: |
| 513 purple_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."), | 499 purple_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."), |
| 514 PURPLE_MESSAGE_NO_LOG, time(NULL)); | 500 PURPLE_MESSAGE_NO_LOG, time(NULL)); |
| 515 g_free(error); | 501 g_free(error); |
| 516 return TRUE; | 502 retval = TRUE; |
| 503 break; | |
| 517 case PURPLE_CMD_STATUS_WRONG_TYPE: | 504 case PURPLE_CMD_STATUS_WRONG_TYPE: |
| 518 if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) | 505 if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) |
| 519 purple_conversation_write(conv, "", _("That command only works in chats, not IMs."), | 506 purple_conversation_write(conv, "", _("That command only works in chats, not IMs."), |
| 520 PURPLE_MESSAGE_NO_LOG, time(NULL)); | 507 PURPLE_MESSAGE_NO_LOG, time(NULL)); |
| 521 else | 508 else |
| 522 purple_conversation_write(conv, "", _("That command only works in IMs, not chats."), | 509 purple_conversation_write(conv, "", _("That command only works in IMs, not chats."), |
| 523 PURPLE_MESSAGE_NO_LOG, time(NULL)); | 510 PURPLE_MESSAGE_NO_LOG, time(NULL)); |
| 524 return TRUE; | 511 retval = TRUE; |
| 512 break; | |
| 525 case PURPLE_CMD_STATUS_WRONG_PRPL: | 513 case PURPLE_CMD_STATUS_WRONG_PRPL: |
| 526 purple_conversation_write(conv, "", _("That command doesn't work on this protocol."), | 514 purple_conversation_write(conv, "", _("That command doesn't work on this protocol."), |
| 527 PURPLE_MESSAGE_NO_LOG, time(NULL)); | 515 PURPLE_MESSAGE_NO_LOG, time(NULL)); |
| 528 return TRUE; | 516 retval = TRUE; |
| 517 break; | |
| 529 } | 518 } |
| 530 } | 519 } |
| 531 | 520 |
| 532 g_free(cmd); | 521 g_free(cmd); |
| 533 return FALSE; | 522 return retval; |
| 534 } | 523 } |
| 535 | 524 |
| 536 static void | 525 static void |
| 537 send_cb(GtkWidget *widget, PidginConversation *gtkconv) | 526 send_cb(GtkWidget *widget, PidginConversation *gtkconv) |
| 538 { | 527 { |
| 541 PurpleConnection *gc; | 530 PurpleConnection *gc; |
| 542 PurpleMessageFlags flags = 0; | 531 PurpleMessageFlags flags = 0; |
| 543 char *buf, *clean; | 532 char *buf, *clean; |
| 544 | 533 |
| 545 account = purple_conversation_get_account(conv); | 534 account = purple_conversation_get_account(conv); |
| 546 | |
| 547 if (!purple_account_is_connected(account)) | |
| 548 return; | |
| 549 | |
| 550 if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) && | |
| 551 purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) | |
| 552 return; | |
| 553 | 535 |
| 554 if (check_for_and_do_command(conv)) { | 536 if (check_for_and_do_command(conv)) { |
| 555 if (gtkconv->entry_growing) { | 537 if (gtkconv->entry_growing) { |
| 556 reset_default_size(gtkconv); | 538 reset_default_size(gtkconv); |
| 557 gtkconv->entry_growing = FALSE; | 539 gtkconv->entry_growing = FALSE; |
| 558 } | 540 } |
| 559 gtk_imhtml_clear(GTK_IMHTML(gtkconv->entry)); | 541 gtk_imhtml_clear(GTK_IMHTML(gtkconv->entry)); |
| 560 return; | 542 return; |
| 561 } | 543 } |
| 544 | |
| 545 if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) && | |
| 546 purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) | |
| 547 return; | |
| 548 | |
| 549 if (!purple_account_is_connected(account)) | |
| 550 return; | |
| 562 | 551 |
| 563 buf = gtk_imhtml_get_markup(GTK_IMHTML(gtkconv->entry)); | 552 buf = gtk_imhtml_get_markup(GTK_IMHTML(gtkconv->entry)); |
| 564 clean = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL); | 553 clean = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL); |
| 565 | 554 |
| 566 gtk_widget_grab_focus(gtkconv->entry); | 555 gtk_widget_grab_focus(gtkconv->entry); |
| 644 } | 633 } |
| 645 | 634 |
| 646 static void chat_do_info(PidginConversation *gtkconv, const char *who) | 635 static void chat_do_info(PidginConversation *gtkconv, const char *who) |
| 647 { | 636 { |
| 648 PurpleConversation *conv = gtkconv->active_conv; | 637 PurpleConversation *conv = gtkconv->active_conv; |
| 649 PurplePluginProtocolInfo *prpl_info = NULL; | |
| 650 PurpleConnection *gc; | 638 PurpleConnection *gc; |
| 651 | 639 |
| 652 if ((gc = purple_conversation_get_gc(conv))) { | 640 if ((gc = purple_conversation_get_gc(conv))) { |
| 653 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); | 641 pidgin_retrieve_user_info_in_chat(gc, who, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); |
| 654 | |
| 655 /* | |
| 656 * If there are special needs for getting info on users in | |
| 657 * buddy chat "rooms"... | |
| 658 */ | |
| 659 if (prpl_info->get_cb_info != NULL) | |
| 660 { | |
| 661 prpl_info->get_cb_info(gc, | |
| 662 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); | |
| 663 } | |
| 664 else | |
| 665 prpl_info->get_info(gc, who); | |
| 666 } | 642 } |
| 667 } | 643 } |
| 668 | 644 |
| 669 | 645 |
| 670 static void | 646 static void |
| 671 info_cb(GtkWidget *widget, PidginConversation *gtkconv) | 647 info_cb(GtkWidget *widget, PidginConversation *gtkconv) |
| 672 { | 648 { |
| 673 PurpleConversation *conv = gtkconv->active_conv; | 649 PurpleConversation *conv = gtkconv->active_conv; |
| 674 | 650 |
| 675 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { | 651 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { |
| 676 PurpleNotifyUserInfo *info = purple_notify_user_info_new(); | 652 pidgin_retrieve_user_info(purple_conversation_get_gc(conv), |
| 677 purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); | |
| 678 purple_notify_userinfo(conv->account->gc, purple_conversation_get_name(conv), info, NULL, NULL); | |
| 679 purple_notify_user_info_destroy(info); | |
| 680 | |
| 681 serv_get_info(purple_conversation_get_gc(conv), | |
| 682 purple_conversation_get_name(conv)); | 653 purple_conversation_get_name(conv)); |
| 683 | |
| 684 gtk_widget_grab_focus(gtkconv->entry); | 654 gtk_widget_grab_focus(gtkconv->entry); |
| 685 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { | 655 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { |
| 686 /* Get info of the person currently selected in the GtkTreeView */ | 656 /* Get info of the person currently selected in the GtkTreeView */ |
| 687 PidginChatPane *gtkchat; | 657 PidginChatPane *gtkchat; |
| 688 GtkTreeIter iter; | 658 GtkTreeIter iter; |
| 1241 pidgin_pounce_editor_show(purple_conversation_get_account(conv), | 1211 pidgin_pounce_editor_show(purple_conversation_get_account(conv), |
| 1242 purple_conversation_get_name(conv), NULL); | 1212 purple_conversation_get_name(conv), NULL); |
| 1243 } | 1213 } |
| 1244 | 1214 |
| 1245 static void | 1215 static void |
| 1216 menu_insert_link_cb(gpointer data, guint action, GtkWidget *widget) | |
| 1217 { | |
| 1218 PidginWindow *win = data; | |
| 1219 PidginConversation *gtkconv; | |
| 1220 GtkIMHtmlToolbar *toolbar; | |
| 1221 | |
| 1222 gtkconv = pidgin_conv_window_get_active_gtkconv(win); | |
| 1223 toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar); | |
| 1224 | |
| 1225 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->link), | |
| 1226 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->link))); | |
| 1227 } | |
| 1228 | |
| 1229 static void | |
| 1230 menu_insert_image_cb(gpointer data, guint action, GtkWidget *widget) | |
| 1231 { | |
| 1232 PidginWindow *win = data; | |
| 1233 PurpleConversation *conv; | |
| 1234 PidginConversation *gtkconv; | |
| 1235 GtkIMHtmlToolbar *toolbar; | |
| 1236 | |
| 1237 gtkconv = pidgin_conv_window_get_active_gtkconv(win); | |
| 1238 conv = gtkconv->active_conv; | |
| 1239 toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar); | |
| 1240 | |
| 1241 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->image), | |
| 1242 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->image))); | |
| 1243 } | |
| 1244 | |
| 1245 | |
| 1246 static void | |
| 1246 menu_alias_cb(gpointer data, guint action, GtkWidget *widget) | 1247 menu_alias_cb(gpointer data, guint action, GtkWidget *widget) |
| 1247 { | 1248 { |
| 1248 PidginWindow *win = data; | 1249 PidginWindow *win = data; |
| 1249 PurpleConversation *conv; | 1250 PurpleConversation *conv; |
| 1250 PurpleAccount *account; | 1251 PurpleAccount *account; |
| 1738 if (path == NULL) | 1739 if (path == NULL) |
| 1739 return FALSE; | 1740 return FALSE; |
| 1740 | 1741 |
| 1741 gtk_tree_selection_select_path(GTK_TREE_SELECTION( | 1742 gtk_tree_selection_select_path(GTK_TREE_SELECTION( |
| 1742 gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkchat->list))), path); | 1743 gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkchat->list))), path); |
| 1744 gtk_tree_view_set_cursor(GTK_TREE_VIEW(gtkchat->list), | |
| 1745 path, NULL, FALSE); | |
| 1746 gtk_widget_grab_focus(GTK_WIDGET(gtkchat->list)); | |
| 1743 | 1747 |
| 1744 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path); | 1748 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path); |
| 1745 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1); | 1749 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1); |
| 1746 | 1750 |
| 1747 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { | 1751 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { |
| 1817 /* If CTRL was held down... */ | 1821 /* If CTRL was held down... */ |
| 1818 if (event->state & GDK_CONTROL_MASK) { | 1822 if (event->state & GDK_CONTROL_MASK) { |
| 1819 switch (event->keyval) { | 1823 switch (event->keyval) { |
| 1820 case GDK_Up: | 1824 case GDK_Up: |
| 1821 if (!gtkconv->send_history) | 1825 if (!gtkconv->send_history) |
| 1826 break; | |
| 1827 | |
| 1828 if (gtkconv->entry != entry) | |
| 1822 break; | 1829 break; |
| 1823 | 1830 |
| 1824 if (!gtkconv->send_history->prev) { | 1831 if (!gtkconv->send_history->prev) { |
| 1825 GtkTextIter start, end; | 1832 GtkTextIter start, end; |
| 1826 | 1833 |
| 1865 return TRUE; | 1872 return TRUE; |
| 1866 break; | 1873 break; |
| 1867 | 1874 |
| 1868 case GDK_Down: | 1875 case GDK_Down: |
| 1869 if (!gtkconv->send_history) | 1876 if (!gtkconv->send_history) |
| 1877 break; | |
| 1878 | |
| 1879 if (gtkconv->entry != entry) | |
| 1870 break; | 1880 break; |
| 1871 | 1881 |
| 1872 if (gtkconv->send_history->prev && gtkconv->send_history->prev->data) { | 1882 if (gtkconv->send_history->prev && gtkconv->send_history->prev->data) { |
| 1873 GObject *object; | 1883 GObject *object; |
| 1874 GtkTextIter iter; | 1884 GtkTextIter iter; |
| 1970 else | 1980 else |
| 1971 { | 1981 { |
| 1972 switch (event->keyval) | 1982 switch (event->keyval) |
| 1973 { | 1983 { |
| 1974 case GDK_Tab: | 1984 case GDK_Tab: |
| 1985 if (gtkconv->entry != entry) | |
| 1986 break; | |
| 1975 return tab_complete(conv); | 1987 return tab_complete(conv); |
| 1976 break; | 1988 break; |
| 1977 | 1989 |
| 1978 case GDK_Page_Up: | 1990 case GDK_Page_Up: |
| 1979 gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml)); | 1991 gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml)); |
| 2046 gtk_widget_event(gtkconv->entry, (GdkEvent *)event); | 2058 gtk_widget_event(gtkconv->entry, (GdkEvent *)event); |
| 2047 | 2059 |
| 2048 return TRUE; | 2060 return TRUE; |
| 2049 } | 2061 } |
| 2050 | 2062 |
| 2063 static void | |
| 2064 regenerate_options_items(PidginWindow *win); | |
| 2065 | |
| 2051 void | 2066 void |
| 2052 pidgin_conv_switch_active_conversation(PurpleConversation *conv) | 2067 pidgin_conv_switch_active_conversation(PurpleConversation *conv) |
| 2053 { | 2068 { |
| 2054 PidginConversation *gtkconv; | 2069 PidginConversation *gtkconv; |
| 2055 PurpleConversation *old_conv; | 2070 PurpleConversation *old_conv; |
| 2146 | 2161 |
| 2147 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv); | 2162 purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv); |
| 2148 | 2163 |
| 2149 gray_stuff_out(gtkconv); | 2164 gray_stuff_out(gtkconv); |
| 2150 update_typing_icon(gtkconv); | 2165 update_typing_icon(gtkconv); |
| 2166 g_object_set_data(G_OBJECT(entry), "transient_buddy", NULL); | |
| 2167 regenerate_options_items(gtkconv->win); | |
| 2151 | 2168 |
| 2152 gtk_window_set_title(GTK_WINDOW(gtkconv->win->window), | 2169 gtk_window_set_title(GTK_WINDOW(gtkconv->win->window), |
| 2153 gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); | 2170 gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); |
| 2154 } | 2171 } |
| 2155 | 2172 |
| 2222 **************************************************************************/ | 2239 **************************************************************************/ |
| 2223 | 2240 |
| 2224 static GList *get_prpl_icon_list(PurpleAccount *account) | 2241 static GList *get_prpl_icon_list(PurpleAccount *account) |
| 2225 { | 2242 { |
| 2226 GList *l = NULL; | 2243 GList *l = NULL; |
| 2227 GdkPixbuf *pixbuf; | 2244 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); |
| 2228 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); | 2245 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); |
| 2229 const char *prpl = prpl_info->list_icon(account, NULL); | 2246 const char *prplname = prpl_info->list_icon(account, NULL); |
| 2230 char *filename, *path; | 2247 l = g_hash_table_lookup(prpl_lists, prplname); |
| 2231 l = g_hash_table_lookup(prpl_lists, prpl); | |
| 2232 if (l) | 2248 if (l) |
| 2233 return l; | 2249 return l; |
| 2234 filename = g_strdup_printf("%s.png", prpl); | 2250 |
| 2235 | 2251 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE)); |
| 2236 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", filename, NULL); | 2252 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM)); |
| 2237 pixbuf = gdk_pixbuf_new_from_file(path, NULL); | 2253 l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL)); |
| 2238 if (pixbuf) | 2254 |
| 2239 l = g_list_append(l, pixbuf); | 2255 g_hash_table_insert(prpl_lists, g_strdup(prplname), l); |
| 2240 g_free(path); | |
| 2241 | |
| 2242 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "22", filename, NULL); | |
| 2243 pixbuf = gdk_pixbuf_new_from_file(path, NULL); | |
| 2244 if (pixbuf) | |
| 2245 l = g_list_append(l, pixbuf); | |
| 2246 g_free(path); | |
| 2247 | |
| 2248 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "48", filename, NULL); | |
| 2249 pixbuf = gdk_pixbuf_new_from_file(path, NULL); | |
| 2250 if (pixbuf) | |
| 2251 l = g_list_append(l, pixbuf); | |
| 2252 g_free(path); | |
| 2253 | |
| 2254 g_hash_table_insert(prpl_lists, g_strdup(prpl), l); | |
| 2255 return l; | 2256 return l; |
| 2256 } | 2257 } |
| 2257 | 2258 |
| 2258 static GList * | 2259 static GList * |
| 2259 pidgin_conv_get_tab_icons(PurpleConversation *conv) | 2260 pidgin_conv_get_tab_icons(PurpleConversation *conv) |
| 2350 g_return_if_fail(status != NULL); | 2351 g_return_if_fail(status != NULL); |
| 2351 | 2352 |
| 2352 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->icon), status); | 2353 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->icon), status); |
| 2353 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->menu_icon), status); | 2354 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->menu_icon), status); |
| 2354 | 2355 |
| 2356 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model), | |
| 2357 &(gtkconv->infopane_iter), | |
| 2358 ICON_COLUMN, status, -1); | |
| 2359 | |
| 2355 if (status != NULL) | 2360 if (status != NULL) |
| 2356 g_object_unref(status); | 2361 g_object_unref(status); |
| 2357 | 2362 |
| 2358 if (pidgin_conv_window_is_active_conversation(conv) && | 2363 if (pidgin_conv_window_is_active_conversation(conv) && |
| 2359 (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM || | 2364 (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM || |
| 2399 } else { | 2404 } else { |
| 2400 gtkconv->u.im->icon_timer = 0; | 2405 gtkconv->u.im->icon_timer = 0; |
| 2401 return FALSE; | 2406 return FALSE; |
| 2402 } | 2407 } |
| 2403 | 2408 |
| 2404 gtkconv->auto_resize = TRUE; | |
| 2405 g_idle_add(reset_auto_resize_cb, gtkconv); | |
| 2406 | |
| 2407 gdk_pixbuf_animation_iter_advance(gtkconv->u.im->iter, NULL); | 2409 gdk_pixbuf_animation_iter_advance(gtkconv->u.im->iter, NULL); |
| 2408 buf = gdk_pixbuf_animation_iter_get_pixbuf(gtkconv->u.im->iter); | 2410 buf = gdk_pixbuf_animation_iter_get_pixbuf(gtkconv->u.im->iter); |
| 2409 | 2411 |
| 2410 pidgin_buddy_icon_get_scale_size(buf, &prpl_info->icon_spec, | 2412 scale_width = gdk_pixbuf_get_width(buf); |
| 2411 PURPLE_ICON_SCALE_DISPLAY, &scale_width, &scale_height); | 2413 scale_height = gdk_pixbuf_get_height(buf); |
| 2412 | 2414 if (scale_width == scale_height) { |
| 2413 /* this code is ugly, and scares me */ | 2415 scale_width = scale_height = 32; |
| 2414 scale = gdk_pixbuf_scale_simple(buf, | 2416 } else if (scale_height > scale_width) { |
| 2415 MAX(gdk_pixbuf_get_width(buf) * scale_width / | 2417 scale_width = 32 * scale_width / scale_height; |
| 2416 gdk_pixbuf_animation_get_width(gtkconv->u.im->anim), 1), | 2418 scale_height = 32; |
| 2417 MAX(gdk_pixbuf_get_height(buf) * scale_height / | 2419 } else { |
| 2418 gdk_pixbuf_animation_get_height(gtkconv->u.im->anim), 1), | 2420 scale_height = 32 * scale_height / scale_width; |
| 2421 scale_width = 32; | |
| 2422 } | |
| 2423 | |
| 2424 scale = gdk_pixbuf_scale_simple(buf, scale_width, scale_height, | |
| 2419 GDK_INTERP_BILINEAR); | 2425 GDK_INTERP_BILINEAR); |
| 2426 if (pidgin_gdk_pixbuf_is_opaque(scale)) | |
| 2427 pidgin_gdk_pixbuf_make_round(scale); | |
| 2420 | 2428 |
| 2421 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->u.im->icon), scale); | 2429 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->u.im->icon), scale); |
| 2422 g_object_unref(G_OBJECT(scale)); | 2430 g_object_unref(G_OBJECT(scale)); |
| 2423 gtk_widget_queue_draw(gtkconv->u.im->icon); | 2431 gtk_widget_queue_draw(gtkconv->u.im->icon); |
| 2424 | 2432 |
| 2812 { N_("/Conversation/_Remove..."), NULL, menu_add_remove_cb, 0, | 2820 { N_("/Conversation/_Remove..."), NULL, menu_add_remove_cb, 0, |
| 2813 "<StockItem>", GTK_STOCK_REMOVE }, | 2821 "<StockItem>", GTK_STOCK_REMOVE }, |
| 2814 | 2822 |
| 2815 { "/Conversation/sep3", NULL, NULL, 0, "<Separator>", NULL }, | 2823 { "/Conversation/sep3", NULL, NULL, 0, "<Separator>", NULL }, |
| 2816 | 2824 |
| 2825 { N_("/Conversation/Insert Lin_k..."), NULL, menu_insert_link_cb, 0, | |
| 2826 "<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_LINK }, | |
| 2827 { N_("/Conversation/Insert Imag_e..."), NULL, menu_insert_image_cb, 0, | |
| 2828 "<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE }, | |
| 2829 | |
| 2830 { "/Conversation/sep4", NULL, NULL, 0, "<Separator>", NULL }, | |
| 2831 | |
| 2832 | |
| 2817 { N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0, | 2833 { N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0, |
| 2818 "<StockItem>", GTK_STOCK_CLOSE }, | 2834 "<StockItem>", GTK_STOCK_CLOSE }, |
| 2819 | 2835 |
| 2820 /* Options */ | 2836 /* Options */ |
| 2821 { N_("/_Options"), NULL, NULL, 0, "<Branch>", NULL }, | 2837 { N_("/_Options"), NULL, NULL, 0, "<Branch>", NULL }, |
| 2891 { | 2907 { |
| 2892 GtkWidget *menu; | 2908 GtkWidget *menu; |
| 2893 GList *list; | 2909 GList *list; |
| 2894 PidginConversation *gtkconv; | 2910 PidginConversation *gtkconv; |
| 2895 PurpleConversation *conv; | 2911 PurpleConversation *conv; |
| 2896 PurpleBuddy *buddy; | 2912 PurpleBlistNode *node = NULL; |
| 2913 PurpleChat *chat = NULL; | |
| 2914 PurpleBuddy *buddy = NULL; | |
| 2897 | 2915 |
| 2898 gtkconv = pidgin_conv_window_get_active_gtkconv(win); | 2916 gtkconv = pidgin_conv_window_get_active_gtkconv(win); |
| 2899 conv = gtkconv->active_conv; | 2917 conv = gtkconv->active_conv; |
| 2900 buddy = purple_find_buddy(conv->account, conv->name); | |
| 2901 | 2918 |
| 2902 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More")); | 2919 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More")); |
| 2920 | |
| 2921 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { | |
| 2922 chat = purple_blist_find_chat(conv->account, conv->name); | |
| 2923 | |
| 2924 if ((chat == NULL) && (gtkconv->imhtml != NULL)) { | |
| 2925 chat = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); | |
| 2926 } | |
| 2927 | |
| 2928 if ((chat == NULL) && (gtkconv->imhtml != NULL)) { | |
| 2929 GHashTable *components; | |
| 2930 components = g_hash_table_new_full(g_str_hash, g_str_equal, | |
| 2931 g_free, g_free); | |
| 2932 g_hash_table_replace(components, g_strdup("channel"), | |
| 2933 g_strdup(conv->name)); | |
| 2934 chat = purple_chat_new(conv->account, NULL, components); | |
| 2935 purple_blist_node_set_flags((PurpleBlistNode *)chat, | |
| 2936 PURPLE_BLIST_NODE_FLAG_NO_SAVE); | |
| 2937 g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_chat", | |
| 2938 chat, (GDestroyNotify)purple_blist_remove_chat); | |
| 2939 } | |
| 2940 } else { | |
| 2941 buddy = purple_find_buddy(conv->account, conv->name); | |
| 2942 | |
| 2943 /* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle | |
| 2944 * removing "isolated" buddy nodes well */ | |
| 2945 if (purple_version_check(2, 0, 2) == NULL) { | |
| 2946 if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { | |
| 2947 buddy = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); | |
| 2948 } | |
| 2949 | |
| 2950 if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { | |
| 2951 buddy = purple_buddy_new(conv->account, conv->name, NULL); | |
| 2952 purple_blist_node_set_flags((PurpleBlistNode *)buddy, | |
| 2953 PURPLE_BLIST_NODE_FLAG_NO_SAVE); | |
| 2954 g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_buddy", | |
| 2955 buddy, (GDestroyNotify)purple_blist_remove_buddy); | |
| 2956 } | |
| 2957 } | |
| 2958 } | |
| 2959 | |
| 2960 if (chat) | |
| 2961 node = (PurpleBlistNode *)chat; | |
| 2962 else if (buddy) | |
| 2963 node = (PurpleBlistNode *)buddy; | |
| 2903 | 2964 |
| 2904 /* Remove the previous entries */ | 2965 /* Remove the previous entries */ |
| 2905 for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; ) | 2966 for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; ) |
| 2906 { | 2967 { |
| 2907 GtkWidget *w = list->data; | 2968 GtkWidget *w = list->data; |
| 2908 list = list->next; | 2969 list = list->next; |
| 2909 gtk_widget_destroy(w); | 2970 gtk_widget_destroy(w); |
| 2910 } | 2971 } |
| 2911 | 2972 |
| 2912 /* Now add the stuff */ | 2973 /* Now add the stuff */ |
| 2913 if (buddy) | 2974 if (node) |
| 2914 { | 2975 { |
| 2915 if (purple_account_is_connected(conv->account)) | 2976 if (purple_account_is_connected(conv->account)) |
| 2916 pidgin_append_blist_node_proto_menu(menu, conv->account->gc, | 2977 pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node); |
| 2917 (PurpleBlistNode *)buddy); | 2978 pidgin_append_blist_node_extended_menu(menu, node); |
| 2918 pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy); | |
| 2919 } | 2979 } |
| 2920 | 2980 |
| 2921 if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL) | 2981 if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL) |
| 2922 { | 2982 { |
| 2923 GtkWidget *item = gtk_menu_item_new_with_label(_("No actions available")); | 2983 GtkWidget *item = gtk_menu_item_new_with_label(_("No actions available")); |
| 2926 } | 2986 } |
| 2927 | 2987 |
| 2928 gtk_widget_show_all(menu); | 2988 gtk_widget_show_all(menu); |
| 2929 } | 2989 } |
| 2930 | 2990 |
| 2991 static void | |
| 2992 remove_from_list(GtkWidget *widget, PidginWindow *win) | |
| 2993 { | |
| 2994 GList *list = g_object_get_data(G_OBJECT(win->window), "plugin-actions"); | |
| 2995 list = g_list_remove(list, widget); | |
| 2996 g_object_set_data(G_OBJECT(win->window), "plugin-actions", list); | |
| 2997 } | |
| 2998 | |
| 2999 static void | |
| 3000 regenerate_plugins_items(PidginWindow *win) | |
| 3001 { | |
| 3002 GList *action_items; | |
| 3003 GtkWidget *menu; | |
| 3004 GList *list; | |
| 3005 PidginConversation *gtkconv; | |
| 3006 PurpleConversation *conv; | |
| 3007 GtkWidget *item; | |
| 3008 | |
| 3009 if (win->window == NULL || win == hidden_convwin) | |
| 3010 return; | |
| 3011 | |
| 3012 gtkconv = pidgin_conv_window_get_active_gtkconv(win); | |
| 3013 if (gtkconv == NULL) | |
| 3014 return; | |
| 3015 | |
| 3016 conv = gtkconv->active_conv; | |
| 3017 action_items = g_object_get_data(G_OBJECT(win->window), "plugin-actions"); | |
| 3018 | |
| 3019 /* Remove the old menuitems */ | |
| 3020 while (action_items) { | |
| 3021 g_signal_handlers_disconnect_by_func(G_OBJECT(action_items->data), | |
| 3022 G_CALLBACK(remove_from_list), win); | |
| 3023 gtk_widget_destroy(action_items->data); | |
| 3024 action_items = g_list_delete_link(action_items, action_items); | |
| 3025 } | |
| 3026 | |
| 3027 menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options")); | |
| 3028 | |
| 3029 list = purple_conversation_get_extended_menu(conv); | |
| 3030 if (list) { | |
| 3031 action_items = g_list_prepend(NULL, (item = pidgin_separator(menu))); | |
| 3032 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win); | |
| 3033 } | |
| 3034 | |
| 3035 for(; list; list = g_list_delete_link(list, list)) { | |
| 3036 PurpleMenuAction *act = (PurpleMenuAction *) list->data; | |
| 3037 item = pidgin_append_menu_action(menu, act, conv); | |
| 3038 action_items = g_list_prepend(action_items, item); | |
| 3039 gtk_widget_show_all(item); | |
| 3040 g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win); | |
| 3041 } | |
| 3042 g_object_set_data(G_OBJECT(win->window), "plugin-actions", action_items); | |
| 3043 } | |
| 3044 | |
| 2931 static void menubar_activated(GtkWidget *item, gpointer data) | 3045 static void menubar_activated(GtkWidget *item, gpointer data) |
| 2932 { | 3046 { |
| 2933 PidginWindow *win = data; | 3047 PidginWindow *win = data; |
| 2934 regenerate_options_items(win); | 3048 regenerate_options_items(win); |
| 3049 regenerate_plugins_items(win); | |
| 2935 | 3050 |
| 2936 /* The following are to make sure the 'More' submenu is not regenerated every time | 3051 /* The following are to make sure the 'More' submenu is not regenerated every time |
| 2937 * the focus shifts from 'Conversations' to some other menu and back. */ | 3052 * the focus shifts from 'Conversations' to some other menu and back. */ |
| 2938 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data); | 3053 g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(menubar_activated), data); |
| 2939 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data); | 3054 g_signal_connect(G_OBJECT(win->menu.menubar), "deactivate", G_CALLBACK(focus_out_from_menubar), data); |
| 3025 N_("/Conversation/Add...")); | 3140 N_("/Conversation/Add...")); |
| 3026 | 3141 |
| 3027 win->menu.remove = | 3142 win->menu.remove = |
| 3028 gtk_item_factory_get_widget(win->menu.item_factory, | 3143 gtk_item_factory_get_widget(win->menu.item_factory, |
| 3029 N_("/Conversation/Remove...")); | 3144 N_("/Conversation/Remove...")); |
| 3145 | |
| 3146 /* --- */ | |
| 3147 | |
| 3148 win->menu.insert_link = | |
| 3149 gtk_item_factory_get_widget(win->menu.item_factory, | |
| 3150 N_("/Conversation/Insert Link...")); | |
| 3151 | |
| 3152 win->menu.insert_image = | |
| 3153 gtk_item_factory_get_widget(win->menu.item_factory, | |
| 3154 N_("/Conversation/Insert Image...")); | |
| 3155 | |
| 3156 /* --- */ | |
| 3030 | 3157 |
| 3031 win->menu.logging = | 3158 win->menu.logging = |
| 3032 gtk_item_factory_get_widget(win->menu.item_factory, | 3159 gtk_item_factory_get_widget(win->menu.item_factory, |
| 3033 N_("/Options/Enable Logging")); | 3160 N_("/Options/Enable Logging")); |
| 3034 win->menu.sounds = | 3161 win->menu.sounds = |
| 3547 pixbuf = get_chat_buddy_status_icon(chat, name, flags); | 3674 pixbuf = get_chat_buddy_status_icon(chat, name, flags); |
| 3548 | 3675 |
| 3549 if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name))) | 3676 if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name))) |
| 3550 is_me = TRUE; | 3677 is_me = TRUE; |
| 3551 | 3678 |
| 3552 is_buddy = (purple_find_buddy(conv->account, name) != NULL); | 3679 is_buddy = cb->buddy; |
| 3553 | 3680 |
| 3554 tmp = g_utf8_casefold(alias, -1); | 3681 tmp = g_utf8_casefold(alias, -1); |
| 3555 alias_key = g_utf8_collate_key(tmp, -1); | 3682 alias_key = g_utf8_collate_key(tmp, -1); |
| 3556 g_free(tmp); | 3683 g_free(tmp); |
| 3557 | 3684 |
| 3755 gtk_tree_model_get(model, &iter, | 3882 gtk_tree_model_get(model, &iter, |
| 3756 CHAT_USERS_NAME_COLUMN, &name, | 3883 CHAT_USERS_NAME_COLUMN, &name, |
| 3757 CHAT_USERS_ALIAS_COLUMN, &alias, | 3884 CHAT_USERS_ALIAS_COLUMN, &alias, |
| 3758 -1); | 3885 -1); |
| 3759 | 3886 |
| 3760 if (strcmp(name, alias)) | 3887 if (name && alias && strcmp(name, alias)) |
| 3761 tab_complete_process_item(&most_matched, entered, &partial, nick_partial, | 3888 tab_complete_process_item(&most_matched, entered, &partial, nick_partial, |
| 3762 &matches, FALSE, alias); | 3889 &matches, FALSE, alias); |
| 3763 g_free(name); | 3890 g_free(name); |
| 3764 g_free(alias); | 3891 g_free(alias); |
| 3765 | 3892 |
| 4124 | 4251 |
| 4125 gtk_widget_size_request(gtkconv->lower_hbox, &sr); | 4252 gtk_widget_size_request(gtkconv->lower_hbox, &sr); |
| 4126 if (sr.height < height + PIDGIN_HIG_BOX_SPACE) { | 4253 if (sr.height < height + PIDGIN_HIG_BOX_SPACE) { |
| 4127 gtkconv->auto_resize = TRUE; | 4254 gtkconv->auto_resize = TRUE; |
| 4128 gtkconv->entry_growing = TRUE; | 4255 gtkconv->entry_growing = TRUE; |
| 4129 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE); | 4256 gtk_widget_set_size_request(gtkconv->entry, -1, height); |
| 4130 g_idle_add(reset_auto_resize_cb, gtkconv); | 4257 g_idle_add(reset_auto_resize_cb, gtkconv); |
| 4131 } | 4258 } |
| 4132 } | 4259 } |
| 4133 | 4260 |
| 4134 static GtkWidget * | 4261 static void |
| 4135 setup_chat_pane(PidginConversation *gtkconv) | 4262 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox) |
| 4136 { | 4263 { |
| 4137 PurplePluginProtocolInfo *prpl_info; | |
| 4138 PurpleConversation *conv = gtkconv->active_conv; | 4264 PurpleConversation *conv = gtkconv->active_conv; |
| 4139 PidginChatPane *gtkchat; | 4265 PurpleConnection *gc = purple_conversation_get_gc(conv); |
| 4140 PurpleConnection *gc; | 4266 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); |
| 4141 GtkWidget *vpaned, *hpaned; | |
| 4142 GtkWidget *vbox, *hbox, *frame; | |
| 4143 GtkWidget *imhtml_sw; | |
| 4144 GtkPolicyType imhtml_sw_hscroll; | |
| 4145 GtkWidget *lbox; | |
| 4146 GtkWidget *label; | |
| 4147 GtkWidget *list; | |
| 4148 GtkWidget *sw; | |
| 4149 GtkListStore *ls; | |
| 4150 GtkCellRenderer *rend; | |
| 4151 GtkTreeViewColumn *col; | |
| 4152 void *blist_handle = purple_blist_get_handle(); | |
| 4153 GList *focus_chain = NULL; | |
| 4154 int ul_width; | |
| 4155 | |
| 4156 gtkchat = gtkconv->u.chat; | |
| 4157 gc = purple_conversation_get_gc(conv); | |
| 4158 g_return_val_if_fail(gc != NULL, NULL); | |
| 4159 g_return_val_if_fail(gc->prpl != NULL, NULL); | |
| 4160 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
| 4161 | |
| 4162 /* Setup the outer pane. */ | |
| 4163 vpaned = gtk_vpaned_new(); | |
| 4164 gtk_widget_show(vpaned); | |
| 4165 | |
| 4166 /* Setup the top part of the pane. */ | |
| 4167 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); | |
| 4168 gtk_paned_pack1(GTK_PANED(vpaned), vbox, TRUE, TRUE); | |
| 4169 gtk_widget_show(vbox); | |
| 4170 | |
| 4171 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) | 4267 if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) |
| 4172 { | 4268 { |
| 4269 GtkWidget *hbox, *label; | |
| 4270 PidginChatPane *gtkchat = gtkconv->u.chat; | |
| 4271 | |
| 4173 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); | 4272 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); |
| 4174 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | 4273 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
| 4175 gtk_widget_show(hbox); | |
| 4176 | 4274 |
| 4177 label = gtk_label_new(_("Topic:")); | 4275 label = gtk_label_new(_("Topic:")); |
| 4178 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | 4276 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); |
| 4179 gtk_widget_show(label); | |
| 4180 | 4277 |
| 4181 gtkchat->topic_text = gtk_entry_new(); | 4278 gtkchat->topic_text = gtk_entry_new(); |
| 4182 | 4279 |
| 4183 if(prpl_info->set_chat_topic == NULL) { | 4280 if(prpl_info->set_chat_topic == NULL) { |
| 4184 gtk_editable_set_editable(GTK_EDITABLE(gtkchat->topic_text), FALSE); | 4281 gtk_editable_set_editable(GTK_EDITABLE(gtkchat->topic_text), FALSE); |
| 4186 g_signal_connect(GTK_OBJECT(gtkchat->topic_text), "activate", | 4283 g_signal_connect(GTK_OBJECT(gtkchat->topic_text), "activate", |
| 4187 G_CALLBACK(topic_callback), gtkconv); | 4284 G_CALLBACK(topic_callback), gtkconv); |
| 4188 } | 4285 } |
| 4189 | 4286 |
| 4190 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0); | 4287 gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0); |
| 4191 gtk_widget_show(gtkchat->topic_text); | 4288 g_signal_connect(G_OBJECT(gtkchat->topic_text), "key_press_event", |
| 4192 } | 4289 G_CALLBACK(entry_key_press_cb), gtkconv); |
| 4193 | 4290 } |
| 4194 /* Setup the horizontal pane. */ | 4291 } |
| 4195 hpaned = gtk_hpaned_new(); | 4292 |
| 4196 gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); | 4293 static void |
| 4197 gtk_widget_show(hpaned); | 4294 setup_chat_userlist(PidginConversation *gtkconv, GtkWidget *hpaned) |
| 4198 | 4295 { |
| 4199 /* Setup gtkihmtml. */ | 4296 PidginChatPane *gtkchat = gtkconv->u.chat; |
| 4200 frame = pidgin_create_imhtml(FALSE, >kconv->imhtml, NULL, &imhtml_sw); | 4297 GtkWidget *lbox, *sw, *list; |
| 4201 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); | 4298 GtkListStore *ls; |
| 4202 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), TRUE); | 4299 GtkCellRenderer *rend; |
| 4203 gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE); | 4300 GtkTreeViewColumn *col; |
| 4204 gtk_widget_show(frame); | 4301 int ul_width; |
| 4205 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw), | 4302 void *blist_handle = purple_blist_get_handle(); |
| 4206 &imhtml_sw_hscroll, NULL); | 4303 PurpleConversation *conv = gtkconv->active_conv; |
| 4207 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw), | |
| 4208 imhtml_sw_hscroll, GTK_POLICY_ALWAYS); | |
| 4209 | |
| 4210 gtk_widget_set_size_request(gtkconv->imhtml, | |
| 4211 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width"), | |
| 4212 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height")); | |
| 4213 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate", | |
| 4214 G_CALLBACK(size_allocate_cb), gtkconv); | |
| 4215 | |
| 4216 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event", | |
| 4217 G_CALLBACK(entry_stop_rclick_cb), NULL); | |
| 4218 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", | |
| 4219 G_CALLBACK(refocus_entry_cb), gtkconv); | |
| 4220 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", | |
| 4221 G_CALLBACK(refocus_entry_cb), gtkconv); | |
| 4222 | 4304 |
| 4223 /* Build the right pane. */ | 4305 /* Build the right pane. */ |
| 4224 lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); | 4306 lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); |
| 4225 gtk_paned_pack2(GTK_PANED(hpaned), lbox, FALSE, TRUE); | 4307 gtk_paned_pack2(GTK_PANED(hpaned), lbox, FALSE, TRUE); |
| 4226 gtk_widget_show(lbox); | 4308 gtk_widget_show(lbox); |
| 4264 G_CALLBACK(right_click_chat_cb), gtkconv); | 4346 G_CALLBACK(right_click_chat_cb), gtkconv); |
| 4265 g_signal_connect(G_OBJECT(list), "popup-menu", | 4347 g_signal_connect(G_OBJECT(list), "popup-menu", |
| 4266 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv); | 4348 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv); |
| 4267 g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv); | 4349 g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv); |
| 4268 | 4350 |
| 4269 | |
| 4270 rend = gtk_cell_renderer_text_new(); | 4351 rend = gtk_cell_renderer_text_new(); |
| 4271 | |
| 4272 g_object_set(rend, | 4352 g_object_set(rend, |
| 4273 "foreground-set", TRUE, | 4353 "foreground-set", TRUE, |
| 4274 "weight-set", TRUE, | 4354 "weight-set", TRUE, |
| 4275 NULL); | 4355 NULL); |
| 4276 col = gtk_tree_view_column_new_with_attributes(NULL, rend, | 4356 col = gtk_tree_view_column_new_with_attributes(NULL, rend, |
| 4297 gtk_widget_show(list); | 4377 gtk_widget_show(list); |
| 4298 | 4378 |
| 4299 gtkchat->list = list; | 4379 gtkchat->list = list; |
| 4300 | 4380 |
| 4301 gtk_container_add(GTK_CONTAINER(sw), list); | 4381 gtk_container_add(GTK_CONTAINER(sw), list); |
| 4382 } | |
| 4383 | |
| 4384 static GtkWidget * | |
| 4385 setup_common_pane(PidginConversation *gtkconv) | |
| 4386 { | |
| 4387 GtkWidget *paned, *vbox, *frame, *imhtml_sw, *event_box; | |
| 4388 GtkCellRenderer *rend; | |
| 4389 GtkTreePath *path; | |
| 4390 PurpleConversation *conv = gtkconv->active_conv; | |
| 4391 gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT); | |
| 4392 GtkPolicyType imhtml_sw_hscroll; | |
| 4393 | |
| 4394 paned = gtk_vpaned_new(); | |
| 4395 gtk_widget_show(paned); | |
| 4396 | |
| 4397 /* Setup the top part of the pane */ | |
| 4398 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); | |
| 4399 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE); | |
| 4400 gtk_widget_show(vbox); | |
| 4401 | |
| 4402 /* Setup the info pane */ | |
| 4403 event_box = gtk_event_box_new(); | |
| 4404 gtk_widget_show(event_box); | |
| 4405 gtkconv->infopane_hbox = gtk_hbox_new(FALSE, 0); | |
| 4406 gtk_box_pack_start(GTK_BOX(vbox), event_box, FALSE, FALSE, 0); | |
| 4407 gtk_container_add(GTK_CONTAINER(event_box), gtkconv->infopane_hbox); | |
| 4408 gtk_widget_show(gtkconv->infopane_hbox); | |
| 4409 gtk_widget_add_events(event_box, | |
| 4410 GDK_BUTTON1_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); | |
| 4411 g_signal_connect(G_OBJECT(event_box), "button_press_event", | |
| 4412 G_CALLBACK(infopane_press_cb), gtkconv); | |
| 4413 g_signal_connect(G_OBJECT(event_box), "button_release_event", | |
| 4414 G_CALLBACK(infopane_release_cb), gtkconv); | |
| 4415 | |
| 4416 | |
| 4417 gtkconv->infopane = gtk_cell_view_new(); | |
| 4418 gtkconv->infopane_model = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING); | |
| 4419 gtk_cell_view_set_model(GTK_CELL_VIEW(gtkconv->infopane), | |
| 4420 GTK_TREE_MODEL(gtkconv->infopane_model)); | |
| 4421 gtk_list_store_append(gtkconv->infopane_model, &(gtkconv->infopane_iter)); | |
| 4422 gtk_box_pack_start(GTK_BOX(gtkconv->infopane_hbox), gtkconv->infopane, TRUE, TRUE, 0); | |
| 4423 path = gtk_tree_path_new_from_string("0"); | |
| 4424 gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(gtkconv->infopane), path); | |
| 4425 gtk_tree_path_free(path); | |
| 4426 gtk_widget_set_size_request(gtkconv->infopane, -1, 32); | |
| 4427 gtk_widget_show(gtkconv->infopane); | |
| 4428 | |
| 4429 rend = gtk_cell_renderer_pixbuf_new(); | |
| 4430 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE); | |
| 4431 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", ICON_COLUMN, NULL); | |
| 4432 g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL); | |
| 4433 | |
| 4434 rend = gtk_cell_renderer_text_new(); | |
| 4435 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, TRUE); | |
| 4436 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "markup", TEXT_COLUMN, NULL); | |
| 4437 g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL); | |
| 4438 | |
| 4439 #if GTK_CHECK_VERSION(2, 6, 0) | |
| 4440 g_object_set(rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); | |
| 4441 #endif | |
| 4442 | |
| 4443 /* Setup the gtkimhtml widget */ | |
| 4444 frame = pidgin_create_imhtml(FALSE, >kconv->imhtml, NULL, &imhtml_sw); | |
| 4445 if (chat) { | |
| 4446 GtkWidget *hpaned; | |
| 4447 | |
| 4448 /* Add the topic */ | |
| 4449 setup_chat_topic(gtkconv, vbox); | |
| 4450 | |
| 4451 /* Add the gtkimhtml frame */ | |
| 4452 hpaned = gtk_hpaned_new(); | |
| 4453 gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); | |
| 4454 gtk_widget_show(hpaned); | |
| 4455 gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE); | |
| 4456 | |
| 4457 /* Now add the userlist */ | |
| 4458 setup_chat_userlist(gtkconv, hpaned); | |
| 4459 } else { | |
| 4460 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); | |
| 4461 } | |
| 4462 gtk_widget_show(frame); | |
| 4463 | |
| 4464 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); | |
| 4465 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE); | |
| 4466 | |
| 4467 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw), | |
| 4468 &imhtml_sw_hscroll, NULL); | |
| 4469 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw), | |
| 4470 imhtml_sw_hscroll, GTK_POLICY_ALWAYS); | |
| 4471 | |
| 4472 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event", | |
| 4473 G_CALLBACK(entry_stop_rclick_cb), NULL); | |
| 4474 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", | |
| 4475 G_CALLBACK(refocus_entry_cb), gtkconv); | |
| 4476 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", | |
| 4477 G_CALLBACK(refocus_entry_cb), gtkconv); | |
| 4302 | 4478 |
| 4303 /* Setup the bottom half of the conversation window */ | 4479 /* Setup the bottom half of the conversation window */ |
| 4304 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); | 4480 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); |
| 4305 gtk_paned_pack2(GTK_PANED(vpaned), vbox, FALSE, TRUE); | 4481 gtk_paned_pack2(GTK_PANED(paned), vbox, FALSE, TRUE); |
| 4306 gtk_widget_show(vbox); | 4482 gtk_widget_show(vbox); |
| 4307 | 4483 |
| 4308 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); | 4484 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); |
| 4309 gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0); | 4485 gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0); |
| 4310 gtk_widget_show(gtkconv->lower_hbox); | 4486 gtk_widget_show(gtkconv->lower_hbox); |
| 4316 /* Setup the toolbar, entry widget and all signals */ | 4492 /* Setup the toolbar, entry widget and all signals */ |
| 4317 frame = pidgin_create_imhtml(TRUE, >kconv->entry, >kconv->toolbar, NULL); | 4493 frame = pidgin_create_imhtml(TRUE, >kconv->entry, >kconv->toolbar, NULL); |
| 4318 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); | 4494 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); |
| 4319 gtk_widget_show(frame); | 4495 gtk_widget_show(frame); |
| 4320 | 4496 |
| 4321 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", | |
| 4322 G_CALLBACK(entry_popup_menu_cb), gtkconv); | |
| 4323 | |
| 4324 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); | 4497 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); |
| 4325 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), | 4498 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), |
| 4326 purple_account_get_protocol_name(conv->account)); | 4499 purple_account_get_protocol_name(conv->account)); |
| 4327 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, | 4500 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, |
| 4328 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height")); | 4501 chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height") : |
| 4329 gtkconv->entry_buffer = | 4502 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height")); |
| 4330 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); | 4503 |
| 4331 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); | 4504 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", |
| 4332 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", | 4505 G_CALLBACK(entry_popup_menu_cb), gtkconv); |
| 4333 G_CALLBACK(resize_imhtml_cb), gtkconv); | |
| 4334 | |
| 4335 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", | 4506 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", |
| 4336 G_CALLBACK(entry_key_press_cb), gtkconv); | 4507 G_CALLBACK(entry_key_press_cb), gtkconv); |
| 4337 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", | 4508 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", |
| 4338 G_CALLBACK(send_cb), gtkconv); | 4509 G_CALLBACK(send_cb), gtkconv); |
| 4339 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", | 4510 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", |
| 4340 G_CALLBACK(entry_stop_rclick_cb), NULL); | 4511 G_CALLBACK(entry_stop_rclick_cb), NULL); |
| 4341 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", | 4512 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", |
| 4342 G_CALLBACK(size_allocate_cb), gtkconv); | 4513 G_CALLBACK(size_allocate_cb), gtkconv); |
| 4343 | 4514 |
| 4344 default_formatize(gtkconv); | |
| 4345 | |
| 4346 /* | |
| 4347 * Focus for chat windows should be as follows: | |
| 4348 * Tab title -> chat topic -> conversation scrollback -> user list -> | |
| 4349 * user list buttons -> entry -> buttons at bottom | |
| 4350 */ | |
| 4351 focus_chain = g_list_prepend(focus_chain, gtkconv->entry); | |
| 4352 gtk_container_set_focus_chain(GTK_CONTAINER(vbox), focus_chain); | |
| 4353 | |
| 4354 return vpaned; | |
| 4355 } | |
| 4356 | |
| 4357 static GtkWidget * | |
| 4358 setup_im_pane(PidginConversation *gtkconv) | |
| 4359 { | |
| 4360 PurpleConversation *conv = gtkconv->active_conv; | |
| 4361 GtkWidget *frame; | |
| 4362 GtkWidget *imhtml_sw; | |
| 4363 GtkPolicyType imhtml_sw_hscroll; | |
| 4364 GtkWidget *paned; | |
| 4365 GtkWidget *vbox; | |
| 4366 GtkWidget *vbox2; | |
| 4367 GList *focus_chain = NULL; | |
| 4368 | |
| 4369 /* Setup the outer pane */ | |
| 4370 paned = gtk_vpaned_new(); | |
| 4371 gtk_widget_show(paned); | |
| 4372 | |
| 4373 /* Setup the top part of the pane */ | |
| 4374 vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); | |
| 4375 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE); | |
| 4376 gtk_widget_show(vbox); | |
| 4377 | |
| 4378 /* Setup the gtkimhtml widget */ | |
| 4379 frame = pidgin_create_imhtml(FALSE, >kconv->imhtml, NULL, &imhtml_sw); | |
| 4380 gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); | |
| 4381 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE); | |
| 4382 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); | |
| 4383 gtk_widget_show(frame); | |
| 4384 gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw), | |
| 4385 &imhtml_sw_hscroll, NULL); | |
| 4386 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw), | |
| 4387 imhtml_sw_hscroll, GTK_POLICY_ALWAYS); | |
| 4388 | |
| 4389 gtk_widget_set_size_request(gtkconv->imhtml, | |
| 4390 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"), | |
| 4391 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height")); | |
| 4392 g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate", | |
| 4393 G_CALLBACK(size_allocate_cb), gtkconv); | |
| 4394 | |
| 4395 g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event", | |
| 4396 G_CALLBACK(entry_stop_rclick_cb), NULL); | |
| 4397 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", | |
| 4398 G_CALLBACK(refocus_entry_cb), gtkconv); | |
| 4399 g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", | |
| 4400 G_CALLBACK(refocus_entry_cb), gtkconv); | |
| 4401 | |
| 4402 /* Setup the bottom half of the conversation window */ | |
| 4403 vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); | |
| 4404 gtk_paned_pack2(GTK_PANED(paned), vbox2, FALSE, TRUE); | |
| 4405 gtk_widget_show(vbox2); | |
| 4406 | |
| 4407 gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); | |
| 4408 gtk_box_pack_start(GTK_BOX(vbox2), gtkconv->lower_hbox, TRUE, TRUE, 0); | |
| 4409 gtk_widget_show(gtkconv->lower_hbox); | |
| 4410 | |
| 4411 vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); | |
| 4412 gtk_box_pack_end(GTK_BOX(gtkconv->lower_hbox), vbox2, TRUE, TRUE, 0); | |
| 4413 gtk_widget_show(vbox2); | |
| 4414 | |
| 4415 /* Setup the toolbar, entry widget and all signals */ | |
| 4416 frame = pidgin_create_imhtml(TRUE, >kconv->entry, >kconv->toolbar, NULL); | |
| 4417 gtk_box_pack_start(GTK_BOX(vbox2), frame, TRUE, TRUE, 0); | |
| 4418 gtk_widget_show(frame); | |
| 4419 | |
| 4420 g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", | |
| 4421 G_CALLBACK(entry_popup_menu_cb), gtkconv); | |
| 4422 | |
| 4423 gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); | |
| 4424 gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), | |
| 4425 purple_account_get_protocol_name(conv->account)); | |
| 4426 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, | |
| 4427 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height")); | |
| 4428 gtkconv->entry_buffer = | 4515 gtkconv->entry_buffer = |
| 4429 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); | 4516 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); |
| 4430 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); | 4517 g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); |
| 4431 | 4518 |
| 4432 g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", | 4519 if (!chat) { |
| 4433 G_CALLBACK(entry_key_press_cb), gtkconv); | 4520 /* For sending typing notifications for IMs */ |
| 4434 g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", | 4521 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", |
| 4435 G_CALLBACK(send_cb), gtkconv); | 4522 G_CALLBACK(insert_text_cb), gtkconv); |
| 4436 g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", | 4523 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range", |
| 4437 G_CALLBACK(entry_stop_rclick_cb), NULL); | 4524 G_CALLBACK(delete_text_cb), gtkconv); |
| 4438 g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", | 4525 gtkconv->u.im->typing_timer = 0; |
| 4439 G_CALLBACK(size_allocate_cb), gtkconv); | 4526 gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons"); |
| 4440 | 4527 gtkconv->u.im->show_icon = TRUE; |
| 4441 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", | 4528 } |
| 4442 G_CALLBACK(insert_text_cb), gtkconv); | 4529 |
| 4443 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range", | |
| 4444 G_CALLBACK(delete_text_cb), gtkconv); | |
| 4445 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", | 4530 g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", |
| 4446 G_CALLBACK(resize_imhtml_cb), gtkconv); | 4531 G_CALLBACK(resize_imhtml_cb), gtkconv); |
| 4447 | 4532 |
| 4448 /* had to move this after the imtoolbar is attached so that the | |
| 4449 * signals get fired to toggle the buttons on the toolbar as well. | |
| 4450 */ | |
| 4451 default_formatize(gtkconv); | 4533 default_formatize(gtkconv); |
| 4452 | |
| 4453 g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear", | 4534 g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear", |
| 4454 G_CALLBACK(clear_formatting_cb), gtkconv); | 4535 G_CALLBACK(clear_formatting_cb), gtkconv); |
| 4455 | 4536 |
| 4456 gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons"); | |
| 4457 gtkconv->u.im->show_icon = TRUE; | |
| 4458 | |
| 4459 /* | |
| 4460 * Focus for IM windows should be as follows: | |
| 4461 * Tab title -> conversation scrollback -> entry | |
| 4462 */ | |
| 4463 focus_chain = g_list_prepend(focus_chain, gtkconv->entry); | |
| 4464 gtk_container_set_focus_chain(GTK_CONTAINER(vbox2), focus_chain); | |
| 4465 | |
| 4466 gtkconv->u.im->typing_timer = 0; | |
| 4467 return paned; | 4537 return paned; |
| 4468 } | 4538 } |
| 4469 | 4539 |
| 4470 static void | 4540 static void |
| 4471 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | 4541 conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, |
| 4657 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; | 4727 gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; |
| 4658 gtkconv->unseen_count = 0; | 4728 gtkconv->unseen_count = 0; |
| 4659 | 4729 |
| 4660 if (conv_type == PURPLE_CONV_TYPE_IM) { | 4730 if (conv_type == PURPLE_CONV_TYPE_IM) { |
| 4661 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); | 4731 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); |
| 4662 | |
| 4663 pane = setup_im_pane(gtkconv); | |
| 4664 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { | 4732 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { |
| 4665 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); | 4733 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); |
| 4666 pane = setup_chat_pane(gtkconv); | 4734 } |
| 4667 } | 4735 pane = setup_common_pane(gtkconv); |
| 4668 | 4736 |
| 4669 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml), | 4737 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml), |
| 4670 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE); | 4738 gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE); |
| 4671 | 4739 |
| 4672 if (pane == NULL) { | 4740 if (pane == NULL) { |
| 5060 g_return_if_fail(account != NULL); | 5128 g_return_if_fail(account != NULL); |
| 5061 gc = purple_account_get_connection(account); | 5129 gc = purple_account_get_connection(account); |
| 5062 g_return_if_fail(gc != NULL); | 5130 g_return_if_fail(gc != NULL); |
| 5063 | 5131 |
| 5064 /* Make sure URLs are clickable */ | 5132 /* Make sure URLs are clickable */ |
| 5065 displaying = purple_markup_linkify(message); | 5133 if(flags & PURPLE_MESSAGE_NO_LINKIFY) |
| 5134 displaying = g_strdup(message); | |
| 5135 else | |
| 5136 displaying = purple_markup_linkify(message); | |
| 5137 | |
| 5066 plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( | 5138 plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( |
| 5067 pidgin_conversations_get_handle(), (type == PURPLE_CONV_TYPE_IM ? | 5139 pidgin_conversations_get_handle(), (type == PURPLE_CONV_TYPE_IM ? |
| 5068 "displaying-im-msg" : "displaying-chat-msg"), | 5140 "displaying-im-msg" : "displaying-chat-msg"), |
| 5069 account, name, &displaying, conv, flags)); | 5141 account, name, &displaying, conv, flags)); |
| 5070 if (plugin_return) | 5142 if (plugin_return) |
| 5485 if (!purple_conv_chat_find_user(chat, old_name)) | 5557 if (!purple_conv_chat_find_user(chat, old_name)) |
| 5486 return; | 5558 return; |
| 5487 | 5559 |
| 5488 g_return_if_fail(new_alias != NULL); | 5560 g_return_if_fail(new_alias != NULL); |
| 5489 | 5561 |
| 5490 cbuddy = purple_conv_chat_cb_new(new_name, new_alias, flags); | 5562 cbuddy = purple_conv_chat_cb_find(chat, new_name); |
| 5491 | 5563 |
| 5492 add_chat_buddy_common(conv, cbuddy, old_name); | 5564 add_chat_buddy_common(conv, cbuddy, old_name); |
| 5493 } | 5565 } |
| 5494 | 5566 |
| 5495 static void | 5567 static void |
| 5891 } else { | 5963 } else { |
| 5892 gtk_widget_show(win->menu.remove); | 5964 gtk_widget_show(win->menu.remove); |
| 5893 gtk_widget_hide(win->menu.add); | 5965 gtk_widget_hide(win->menu.add); |
| 5894 } | 5966 } |
| 5895 | 5967 |
| 5968 gtk_widget_show(win->menu.insert_link); | |
| 5969 gtk_widget_show(win->menu.insert_image); | |
| 5896 gtk_widget_show(win->menu.show_icon); | 5970 gtk_widget_show(win->menu.show_icon); |
| 5897 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { | 5971 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { |
| 5898 /* Show stuff that applies to Chats, hide stuff that applies to IMs */ | 5972 /* Show stuff that applies to Chats, hide stuff that applies to IMs */ |
| 5899 | 5973 |
| 5900 /* Deal with menu items */ | 5974 /* Deal with menu items */ |
| 5916 /* If the chat IS in the buddy list */ | 5990 /* If the chat IS in the buddy list */ |
| 5917 gtk_widget_hide(win->menu.add); | 5991 gtk_widget_hide(win->menu.add); |
| 5918 gtk_widget_show(win->menu.remove); | 5992 gtk_widget_show(win->menu.remove); |
| 5919 } | 5993 } |
| 5920 | 5994 |
| 5995 gtk_widget_show(win->menu.insert_link); | |
| 5996 gtk_widget_show(win->menu.insert_image); | |
| 5921 } | 5997 } |
| 5922 | 5998 |
| 5923 /* | 5999 /* |
| 5924 * Handle graying stuff out based on whether an account is connected | 6000 * Handle graying stuff out based on whether an account is connected |
| 5925 * and what features that account supports. | 6001 * and what features that account supports. |
| 5944 buttons &= ~GTK_IMHTML_LINKDESC; | 6020 buttons &= ~GTK_IMHTML_LINKDESC; |
| 5945 } else { | 6021 } else { |
| 5946 buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE; | 6022 buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE; |
| 5947 } | 6023 } |
| 5948 | 6024 |
| 5949 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE) || | 6025 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)) |
| 5950 conv->features & PURPLE_CONNECTION_NO_IMAGES) | 6026 conv->features |= PURPLE_CONNECTION_NO_IMAGES; |
| 6027 | |
| 6028 if(conv->features & PURPLE_CONNECTION_NO_IMAGES) | |
| 5951 buttons &= ~GTK_IMHTML_IMAGE; | 6029 buttons &= ~GTK_IMHTML_IMAGE; |
| 5952 | 6030 |
| 5953 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons); | 6031 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons); |
| 5954 if (account != NULL) | 6032 if (account != NULL) |
| 5955 gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(gtkconv->toolbar), purple_account_get_protocol_id(account)); | 6033 gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(gtkconv->toolbar), purple_account_get_protocol_id(account)); |
| 5957 /* Deal with menu items */ | 6035 /* Deal with menu items */ |
| 5958 gtk_widget_set_sensitive(win->menu.view_log, TRUE); | 6036 gtk_widget_set_sensitive(win->menu.view_log, TRUE); |
| 5959 gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); | 6037 gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); |
| 5960 gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); | 6038 gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); |
| 5961 gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); | 6039 gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); |
| 6040 gtk_widget_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML)); | |
| 6041 gtk_widget_set_sensitive(win->menu.insert_image, !(conv->features & PURPLE_CONNECTION_NO_IMAGES)); | |
| 5962 | 6042 |
| 5963 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) | 6043 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) |
| 5964 { | 6044 { |
| 5965 gtk_widget_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL)); | 6045 gtk_widget_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL)); |
| 5966 gtk_widget_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); | 6046 gtk_widget_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); |
| 5991 gtk_widget_set_sensitive(win->menu.get_info, FALSE); | 6071 gtk_widget_set_sensitive(win->menu.get_info, FALSE); |
| 5992 gtk_widget_set_sensitive(win->menu.invite, FALSE); | 6072 gtk_widget_set_sensitive(win->menu.invite, FALSE); |
| 5993 gtk_widget_set_sensitive(win->menu.alias, FALSE); | 6073 gtk_widget_set_sensitive(win->menu.alias, FALSE); |
| 5994 gtk_widget_set_sensitive(win->menu.add, FALSE); | 6074 gtk_widget_set_sensitive(win->menu.add, FALSE); |
| 5995 gtk_widget_set_sensitive(win->menu.remove, FALSE); | 6075 gtk_widget_set_sensitive(win->menu.remove, FALSE); |
| 6076 gtk_widget_set_sensitive(win->menu.insert_link, TRUE); | |
| 6077 gtk_widget_set_sensitive(win->menu.insert_image, FALSE); | |
| 5996 } | 6078 } |
| 5997 | 6079 |
| 5998 /* | 6080 /* |
| 5999 * Update the window's icon | 6081 * Update the window's icon |
| 6000 */ | 6082 */ |
| 6074 | 6156 |
| 6075 if (fields & PIDGIN_CONV_SMILEY_THEME) | 6157 if (fields & PIDGIN_CONV_SMILEY_THEME) |
| 6076 pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->imhtml); | 6158 pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->imhtml); |
| 6077 | 6159 |
| 6078 if ((fields & PIDGIN_CONV_COLORIZE_TITLE) || | 6160 if ((fields & PIDGIN_CONV_COLORIZE_TITLE) || |
| 6079 (fields & PIDGIN_CONV_SET_TITLE)) | 6161 (fields & PIDGIN_CONV_SET_TITLE) || |
| 6162 (fields & PIDGIN_CONV_TOPIC)) | |
| 6080 { | 6163 { |
| 6081 char *title; | 6164 char *title; |
| 6082 PurpleConvIm *im = NULL; | 6165 PurpleConvIm *im = NULL; |
| 6083 PurpleAccount *account = purple_conversation_get_account(conv); | 6166 PurpleAccount *account = purple_conversation_get_account(conv); |
| 6167 char *markup = NULL; | |
| 6084 AtkObject *accessibility_obj; | 6168 AtkObject *accessibility_obj; |
| 6085 /* I think this is a little longer than it needs to be but I'm lazy. */ | 6169 /* I think this is a little longer than it needs to be but I'm lazy. */ |
| 6086 char style[51]; | 6170 char style[51]; |
| 6087 | 6171 |
| 6088 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) | 6172 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) |
| 6093 ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) | 6177 ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) |
| 6094 && purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)))) | 6178 && purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)))) |
| 6095 title = g_strdup_printf("(%s)", purple_conversation_get_title(conv)); | 6179 title = g_strdup_printf("(%s)", purple_conversation_get_title(conv)); |
| 6096 else | 6180 else |
| 6097 title = g_strdup(purple_conversation_get_title(conv)); | 6181 title = g_strdup(purple_conversation_get_title(conv)); |
| 6182 | |
| 6183 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { | |
| 6184 PurpleBuddy *buddy = purple_find_buddy(account, conv->name); | |
| 6185 if (buddy) | |
| 6186 markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE); | |
| 6187 else | |
| 6188 markup = title; | |
| 6189 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { | |
| 6190 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); | |
| 6191 const char *topic = purple_conv_chat_get_topic(chat); | |
| 6192 markup = g_strdup_printf("%s%s<span color='%s' size='smaller'>%s</span>", | |
| 6193 purple_conversation_get_title(conv), | |
| 6194 topic ? "\n" : "", | |
| 6195 pidgin_get_dim_grey_string(gtkconv->infopane), | |
| 6196 topic ? topic : ""); | |
| 6197 } | |
| 6198 gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter), | |
| 6199 TEXT_COLUMN, markup, -1); | |
| 6200 | |
| 6201 if (title != markup) | |
| 6202 g_free(markup); | |
| 6098 | 6203 |
| 6099 *style = '\0'; | 6204 *style = '\0'; |
| 6100 | 6205 |
| 6101 if (!GTK_WIDGET_REALIZED(gtkconv->tab_label)) | 6206 if (!GTK_WIDGET_REALIZED(gtkconv->tab_label)) |
| 6102 gtk_widget_realize(gtkconv->tab_label); | 6207 gtk_widget_realize(gtkconv->tab_label); |
| 6253 size_t len; | 6358 size_t len; |
| 6254 | 6359 |
| 6255 GdkPixbuf *buf; | 6360 GdkPixbuf *buf; |
| 6256 | 6361 |
| 6257 GtkWidget *event; | 6362 GtkWidget *event; |
| 6258 GtkWidget *frame; | |
| 6259 GdkPixbuf *scale; | 6363 GdkPixbuf *scale; |
| 6260 int scale_width, scale_height; | 6364 int scale_width, scale_height; |
| 6261 | 6365 |
| 6262 PurpleAccount *account; | 6366 PurpleAccount *account; |
| 6263 PurplePluginProtocolInfo *prpl_info = NULL; | 6367 PurplePluginProtocolInfo *prpl_info = NULL; |
| 6352 "Buddy icon error: %s\n", err->message); | 6456 "Buddy icon error: %s\n", err->message); |
| 6353 g_error_free(err); | 6457 g_error_free(err); |
| 6354 } | 6458 } |
| 6355 | 6459 |
| 6356 if (gdk_pixbuf_animation_is_static_image(gtkconv->u.im->anim)) { | 6460 if (gdk_pixbuf_animation_is_static_image(gtkconv->u.im->anim)) { |
| 6461 GdkPixbuf *stat; | |
| 6357 gtkconv->u.im->iter = NULL; | 6462 gtkconv->u.im->iter = NULL; |
| 6358 buf = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); | 6463 stat = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); |
| 6464 buf = gdk_pixbuf_add_alpha(stat, FALSE, 0, 0, 0); | |
| 6359 } else { | 6465 } else { |
| 6466 GdkPixbuf *stat; | |
| 6360 gtkconv->u.im->iter = | 6467 gtkconv->u.im->iter = |
| 6361 gdk_pixbuf_animation_get_iter(gtkconv->u.im->anim, NULL); /* LEAK */ | 6468 gdk_pixbuf_animation_get_iter(gtkconv->u.im->anim, NULL); /* LEAK */ |
| 6362 buf = gdk_pixbuf_animation_iter_get_pixbuf(gtkconv->u.im->iter); | 6469 stat = gdk_pixbuf_animation_iter_get_pixbuf(gtkconv->u.im->iter); |
| 6470 buf = gdk_pixbuf_add_alpha(stat, FALSE, 0, 0, 0); | |
| 6363 if (gtkconv->u.im->animate) | 6471 if (gtkconv->u.im->animate) |
| 6364 start_anim(NULL, gtkconv); | 6472 start_anim(NULL, gtkconv); |
| 6365 } | 6473 } |
| 6366 | 6474 |
| 6367 pidgin_buddy_icon_get_scale_size(buf, &prpl_info->icon_spec, | 6475 scale_width = gdk_pixbuf_get_width(buf); |
| 6368 PURPLE_ICON_SCALE_DISPLAY, &scale_width, &scale_height); | 6476 scale_height = gdk_pixbuf_get_height(buf); |
| 6369 scale = gdk_pixbuf_scale_simple(buf, | 6477 if (scale_width == scale_height) { |
| 6370 MAX(gdk_pixbuf_get_width(buf) * scale_width / | 6478 scale_width = scale_height = 32; |
| 6371 gdk_pixbuf_animation_get_width(gtkconv->u.im->anim), 1), | 6479 } else if (scale_height > scale_width) { |
| 6372 MAX(gdk_pixbuf_get_height(buf) * scale_height / | 6480 scale_width = 32 * scale_width / scale_height; |
| 6373 gdk_pixbuf_animation_get_height(gtkconv->u.im->anim), 1), | 6481 scale_height = 32; |
| 6482 } else { | |
| 6483 scale_height = 32 * scale_height / scale_width; | |
| 6484 scale_width = 32; | |
| 6485 } | |
| 6486 scale = gdk_pixbuf_scale_simple(buf, scale_width, scale_height, | |
| 6374 GDK_INTERP_BILINEAR); | 6487 GDK_INTERP_BILINEAR); |
| 6375 | 6488 g_object_unref(buf); |
| 6489 if (pidgin_gdk_pixbuf_is_opaque(scale)) | |
| 6490 pidgin_gdk_pixbuf_make_round(scale); | |
| 6376 gtkconv->u.im->icon_container = gtk_vbox_new(FALSE, 0); | 6491 gtkconv->u.im->icon_container = gtk_vbox_new(FALSE, 0); |
| 6377 | 6492 |
| 6378 frame = gtk_frame_new(NULL); | |
| 6379 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE); | |
| 6380 gtk_box_pack_start(GTK_BOX(gtkconv->u.im->icon_container), frame, | |
| 6381 FALSE, FALSE, 0); | |
| 6382 | |
| 6383 event = gtk_event_box_new(); | 6493 event = gtk_event_box_new(); |
| 6384 gtk_container_add(GTK_CONTAINER(frame), event); | 6494 gtk_container_add(GTK_CONTAINER(gtkconv->u.im->icon_container), event); |
| 6385 g_signal_connect(G_OBJECT(event), "button-press-event", | 6495 g_signal_connect(G_OBJECT(event), "button-press-event", |
| 6386 G_CALLBACK(icon_menu), gtkconv); | 6496 G_CALLBACK(icon_menu), gtkconv); |
| 6387 gtk_widget_show(event); | 6497 gtk_widget_show(event); |
| 6388 | 6498 |
| 6389 gtkconv->u.im->icon = gtk_image_new_from_pixbuf(scale); | 6499 gtkconv->u.im->icon = gtk_image_new_from_pixbuf(scale); |
| 6390 gtkconv->auto_resize = TRUE; | 6500 gtkconv->auto_resize = TRUE; |
| 6391 /* Reset the size request to allow the buddy icon to resize */ | |
| 6392 gtk_widget_set_size_request(gtkconv->lower_hbox, -1, -1); | |
| 6393 g_idle_add(reset_auto_resize_cb, gtkconv); | |
| 6394 gtk_widget_set_size_request(gtkconv->u.im->icon, scale_width, scale_height); | |
| 6395 gtk_container_add(GTK_CONTAINER(event), gtkconv->u.im->icon); | 6501 gtk_container_add(GTK_CONTAINER(event), gtkconv->u.im->icon); |
| 6396 gtk_widget_show(gtkconv->u.im->icon); | 6502 gtk_widget_show(gtkconv->u.im->icon); |
| 6397 | 6503 |
| 6398 g_object_unref(G_OBJECT(scale)); | 6504 g_object_unref(G_OBJECT(scale)); |
| 6399 | 6505 |
| 6400 gtk_box_pack_start(GTK_BOX(gtkconv->lower_hbox), | 6506 gtk_box_pack_start(GTK_BOX(gtkconv->infopane_hbox), |
| 6401 gtkconv->u.im->icon_container, FALSE, FALSE, 0); | 6507 gtkconv->u.im->icon_container, FALSE, FALSE, 0); |
| 6402 | 6508 |
| 6403 gtk_widget_show(gtkconv->u.im->icon_container); | 6509 gtk_widget_show(gtkconv->u.im->icon_container); |
| 6404 gtk_widget_show(frame); | |
| 6405 | 6510 |
| 6406 /* The buddy icon code needs badly to be fixed. */ | 6511 /* The buddy icon code needs badly to be fixed. */ |
| 6407 if(pidgin_conv_window_is_active_conversation(conv)) | 6512 if(pidgin_conv_window_is_active_conversation(conv)) |
| 6408 { | 6513 { |
| 6409 buf = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); | 6514 buf = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); |
| 6948 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/font_face", ""); | 7053 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/font_face", ""); |
| 6949 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/font_size", 3); | 7054 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/font_size", 3); |
| 6950 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/tabs", TRUE); | 7055 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/tabs", TRUE); |
| 6951 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/tab_side", GTK_POS_TOP); | 7056 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/tab_side", GTK_POS_TOP); |
| 6952 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/scrollback_lines", 4000); | 7057 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/scrollback_lines", 4000); |
| 7058 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/x", 0); | |
| 7059 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/y", 0); | |
| 7060 | |
| 7061 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font", TRUE); | |
| 7062 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/custom_font", ""); | |
| 6953 | 7063 |
| 6954 /* Conversations -> Chat */ | 7064 /* Conversations -> Chat */ |
| 6955 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/chat"); | 7065 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/chat"); |
| 6956 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width", 410); | 7066 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width", 410); |
| 6957 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height", 160); | 7067 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height", 160); |
| 7090 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL, | 7200 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL, |
| 7091 debug_command_cb, _("debug <option>: Send various debug information to the current conversation."), NULL); | 7201 debug_command_cb, _("debug <option>: Send various debug information to the current conversation."), NULL); |
| 7092 purple_cmd_register("clear", "", PURPLE_CMD_P_DEFAULT, | 7202 purple_cmd_register("clear", "", PURPLE_CMD_P_DEFAULT, |
| 7093 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL, | 7203 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL, |
| 7094 clear_command_cb, _("clear: Clears the conversation scrollback."), NULL); | 7204 clear_command_cb, _("clear: Clears the conversation scrollback."), NULL); |
| 7205 purple_cmd_register("clearall", "", PURPLE_CMD_P_DEFAULT, | |
| 7206 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL, | |
| 7207 clearall_command_cb, _("clear: Clears all conversation scrollbacks."), NULL); | |
| 7095 purple_cmd_register("help", "w", PURPLE_CMD_P_DEFAULT, | 7208 purple_cmd_register("help", "w", PURPLE_CMD_P_DEFAULT, |
| 7096 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, NULL, | 7209 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, NULL, |
| 7097 help_command_cb, _("help <command>: Help on a specific command."), NULL); | 7210 help_command_cb, _("help <command>: Help on a specific command."), NULL); |
| 7098 | 7211 |
| 7099 /********************************************************************** | 7212 /********************************************************************** |
| 7494 } | 7607 } |
| 7495 | 7608 |
| 7496 /* | 7609 /* |
| 7497 * THANK YOU GALEON! | 7610 * THANK YOU GALEON! |
| 7498 */ | 7611 */ |
| 7612 | |
| 7613 static gboolean | |
| 7614 infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv) | |
| 7615 { | |
| 7616 int nb_x, nb_y; | |
| 7617 | |
| 7618 if (e->button != 1 || e->type != GDK_BUTTON_PRESS) | |
| 7619 return FALSE; | |
| 7620 | |
| 7621 if (gtkconv->win->in_drag) { | |
| 7622 purple_debug(PURPLE_DEBUG_WARNING, "gtkconv", | |
| 7623 "Already in the middle of a window drag at tab_press_cb\n"); | |
| 7624 return TRUE; | |
| 7625 } | |
| 7626 | |
| 7627 gtkconv->win->in_predrag = TRUE; | |
| 7628 gtkconv->win->drag_tab = gtk_notebook_page_num(GTK_NOTEBOOK(gtkconv->win->notebook), gtkconv->tab_cont); | |
| 7629 | |
| 7630 gdk_window_get_origin(gtkconv->infopane_hbox->window, &nb_x, &nb_y); | |
| 7631 | |
| 7632 gtkconv->win->drag_min_x = gtkconv->infopane_hbox->allocation.x + nb_x; | |
| 7633 gtkconv->win->drag_min_y = gtkconv->infopane_hbox->allocation.y + nb_y; | |
| 7634 gtkconv->win->drag_max_x = gtkconv->infopane_hbox->allocation.width + gtkconv->win->drag_min_x; | |
| 7635 gtkconv->win->drag_max_y = gtkconv->infopane_hbox->allocation.height + gtkconv->win->drag_min_y; | |
| 7636 | |
| 7637 | |
| 7638 /* Connect the new motion signals. */ | |
| 7639 gtkconv->win->drag_motion_signal = | |
| 7640 g_signal_connect(G_OBJECT(gtkconv->win->notebook), "motion_notify_event", | |
| 7641 G_CALLBACK(notebook_motion_cb), gtkconv->win); | |
| 7642 | |
| 7643 gtkconv->win->drag_leave_signal = | |
| 7644 g_signal_connect(G_OBJECT(gtkconv->win->notebook), "leave_notify_event", | |
| 7645 G_CALLBACK(notebook_leave_cb), gtkconv->win); | |
| 7646 | |
| 7647 return FALSE; | |
| 7648 | |
| 7649 } | |
| 7650 | |
| 7499 static gboolean | 7651 static gboolean |
| 7500 notebook_press_cb(GtkWidget *widget, GdkEventButton *e, PidginWindow *win) | 7652 notebook_press_cb(GtkWidget *widget, GdkEventButton *e, PidginWindow *win) |
| 7501 { | 7653 { |
| 7502 gint nb_x, nb_y, x_rel, y_rel; | 7654 gint nb_x, nb_y, x_rel, y_rel; |
| 7503 int tab_clicked; | 7655 int tab_clicked; |
| 7579 | 7731 |
| 7580 win->drag_leave_signal = | 7732 win->drag_leave_signal = |
| 7581 g_signal_connect(G_OBJECT(widget), "leave_notify_event", | 7733 g_signal_connect(G_OBJECT(widget), "leave_notify_event", |
| 7582 G_CALLBACK(notebook_leave_cb), win); | 7734 G_CALLBACK(notebook_leave_cb), win); |
| 7583 | 7735 |
| 7736 return FALSE; | |
| 7737 } | |
| 7738 | |
| 7739 static gboolean | |
| 7740 infopane_release_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv) | |
| 7741 { | |
| 7584 return FALSE; | 7742 return FALSE; |
| 7585 } | 7743 } |
| 7586 | 7744 |
| 7587 static gboolean | 7745 static gboolean |
| 7588 notebook_release_cb(GtkWidget *widget, GdkEventButton *e, PidginWindow *win) | 7746 notebook_release_cb(GtkWidget *widget, GdkEventButton *e, PidginWindow *win) |
| 7913 if (!GTK_WIDGET_VISIBLE(gtkconv->tab_label)) { | 8071 if (!GTK_WIDGET_VISIBLE(gtkconv->tab_label)) { |
| 7914 /* There's already an entry for alias. Let's not create another one. */ | 8072 /* There's already an entry for alias. Let's not create another one. */ |
| 7915 return FALSE; | 8073 return FALSE; |
| 7916 } | 8074 } |
| 7917 | 8075 |
| 8076 if (!purple_account_is_connected(gtkconv->active_conv->account)) { | |
| 8077 /* Do not allow aliasing someone on a disconnected account. */ | |
| 8078 return FALSE; | |
| 8079 } | |
| 8080 | |
| 7918 /* alias label */ | 8081 /* alias label */ |
| 7919 entry = gtk_entry_new(); | 8082 entry = gtk_entry_new(); |
| 7920 gtk_entry_set_has_frame(GTK_ENTRY(entry), FALSE); | 8083 gtk_entry_set_has_frame(GTK_ENTRY(entry), FALSE); |
| 7921 gtk_entry_set_width_chars(GTK_ENTRY(entry), 10); | 8084 gtk_entry_set_width_chars(GTK_ENTRY(entry), 10); |
| 8085 #if GTK_CHECK_VERSION(2,4,0) | |
| 7922 gtk_entry_set_alignment(GTK_ENTRY(entry), 0.5); | 8086 gtk_entry_set_alignment(GTK_ENTRY(entry), 0.5); |
| 8087 #endif | |
| 7923 | 8088 |
| 7924 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), entry, TRUE, TRUE, 0); | 8089 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), entry, TRUE, TRUE, 0); |
| 7925 /* after the tab label */ | 8090 /* after the tab label */ |
| 7926 gtk_box_reorder_child(GTK_BOX(gtkconv->tabby), entry, 2); | 8091 gtk_box_reorder_child(GTK_BOX(gtkconv->tabby), entry, 2); |
| 7927 | 8092 |
| 7962 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging), | 8127 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging), |
| 7963 purple_conversation_is_logging(conv)); | 8128 purple_conversation_is_logging(conv)); |
| 7964 | 8129 |
| 7965 generate_send_to_items(win); | 8130 generate_send_to_items(win); |
| 7966 regenerate_options_items(win); | 8131 regenerate_options_items(win); |
| 8132 regenerate_plugins_items(win); | |
| 7967 | 8133 |
| 7968 pidgin_conv_switch_active_conversation(conv); | 8134 pidgin_conv_switch_active_conversation(conv); |
| 7969 | 8135 |
| 7970 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); | 8136 sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); |
| 7971 if (strcmp(sound_method, "none") != 0) | 8137 if (strcmp(sound_method, "none") != 0) |
| 8032 offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w); | 8198 offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w); |
| 8033 away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w); | 8199 away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w); |
| 8034 prpl_lists = g_hash_table_new(g_str_hash, g_str_equal); | 8200 prpl_lists = g_hash_table_new(g_str_hash, g_str_equal); |
| 8035 } | 8201 } |
| 8036 | 8202 |
| 8203 static void | |
| 8204 plugin_changed_cb(PurplePlugin *p, gpointer data) | |
| 8205 { | |
| 8206 regenerate_plugins_items(data); | |
| 8207 } | |
| 8208 | |
| 8209 static gboolean gtk_conv_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) { | |
| 8210 int x, y; | |
| 8211 | |
| 8212 if (GTK_WIDGET_VISIBLE(w)) | |
| 8213 gtk_window_get_position(GTK_WINDOW(w), &x, &y); | |
| 8214 else | |
| 8215 return FALSE; /* carry on normally */ | |
| 8216 | |
| 8217 /* Workaround for GTK+ bug # 169811 - "configure_event" is fired | |
| 8218 * when the window is being maximized */ | |
| 8219 if (gdk_window_get_state(w->window) & GDK_WINDOW_STATE_MAXIMIZED) | |
| 8220 return FALSE; | |
| 8221 | |
| 8222 /* don't save if nothing changed */ | |
| 8223 if (x == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/x") && | |
| 8224 y == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/y") && | |
| 8225 event->width == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width") && | |
| 8226 event->height == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height")) | |
| 8227 return FALSE; /* carry on normally */ | |
| 8228 | |
| 8229 /* don't save off-screen positioning */ | |
| 8230 if (x + event->width < 0 || | |
| 8231 y + event->height < 0 || | |
| 8232 x > gdk_screen_width() || | |
| 8233 y > gdk_screen_height()) | |
| 8234 return FALSE; /* carry on normally */ | |
| 8235 | |
| 8236 /* store the position */ | |
| 8237 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/x", x); | |
| 8238 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/y", y); | |
| 8239 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/width", event->width); | |
| 8240 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/height", event->height); | |
| 8241 | |
| 8242 /* continue to handle event normally */ | |
| 8243 return FALSE; | |
| 8244 | |
| 8245 } | |
| 8246 | |
| 8037 PidginWindow * | 8247 PidginWindow * |
| 8038 pidgin_conv_window_new() | 8248 pidgin_conv_window_new() |
| 8039 { | 8249 { |
| 8040 PidginWindow *win; | 8250 PidginWindow *win; |
| 8041 GtkPositionType pos; | 8251 GtkPositionType pos; |
| 8045 win = g_malloc0(sizeof(PidginWindow)); | 8255 win = g_malloc0(sizeof(PidginWindow)); |
| 8046 | 8256 |
| 8047 window_list = g_list_append(window_list, win); | 8257 window_list = g_list_append(window_list, win); |
| 8048 | 8258 |
| 8049 /* Create the window. */ | 8259 /* Create the window. */ |
| 8050 win->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | 8260 win->window = pidgin_create_window(NULL, 0, "conversation", TRUE); |
| 8051 gtk_window_set_role(GTK_WINDOW(win->window), "conversation"); | 8261 gtk_window_set_default_size(GTK_WINDOW(win->window), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/width"), |
| 8052 gtk_window_set_resizable(GTK_WINDOW(win->window), TRUE); | 8262 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/height")); |
| 8053 gtk_container_set_border_width(GTK_CONTAINER(win->window), 0); | |
| 8054 GTK_WINDOW(win->window)->allow_shrink = TRUE; | |
| 8055 | 8263 |
| 8056 if (available_list == NULL) { | 8264 if (available_list == NULL) { |
| 8057 create_icon_lists(win->window); | 8265 create_icon_lists(win->window); |
| 8058 } | 8266 } |
| 8059 | 8267 |
| 8060 g_signal_connect(G_OBJECT(win->window), "delete_event", | 8268 g_signal_connect(G_OBJECT(win->window), "delete_event", |
| 8061 G_CALLBACK(close_win_cb), win); | 8269 G_CALLBACK(close_win_cb), win); |
| 8062 | 8270 g_signal_connect(G_OBJECT(win->window), "configure_event", |
| 8271 G_CALLBACK(gtk_conv_configure_cb), NULL); | |
| 8063 g_signal_connect(G_OBJECT(win->window), "focus_in_event", | 8272 g_signal_connect(G_OBJECT(win->window), "focus_in_event", |
| 8064 G_CALLBACK(focus_win_cb), win); | 8273 G_CALLBACK(focus_win_cb), win); |
| 8065 | 8274 |
| 8066 /* Create the notebook. */ | 8275 /* Create the notebook. */ |
| 8067 win->notebook = gtk_notebook_new(); | 8276 win->notebook = gtk_notebook_new(); |
| 8105 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0); | 8314 gtk_box_pack_start(GTK_BOX(testidea), win->notebook, TRUE, TRUE, 0); |
| 8106 | 8315 |
| 8107 gtk_container_add(GTK_CONTAINER(win->window), testidea); | 8316 gtk_container_add(GTK_CONTAINER(win->window), testidea); |
| 8108 | 8317 |
| 8109 gtk_widget_show(testidea); | 8318 gtk_widget_show(testidea); |
| 8319 | |
| 8320 /* Update the plugin actions when plugins are (un)loaded */ | |
| 8321 purple_signal_connect(purple_plugins_get_handle(), "plugin-load", | |
| 8322 win, PURPLE_CALLBACK(plugin_changed_cb), win); | |
| 8323 purple_signal_connect(purple_plugins_get_handle(), "plugin-unload", | |
| 8324 win, PURPLE_CALLBACK(plugin_changed_cb), win); | |
| 8325 | |
| 8110 | 8326 |
| 8111 #ifdef _WIN32 | 8327 #ifdef _WIN32 |
| 8112 g_signal_connect(G_OBJECT(win->window), "show", | 8328 g_signal_connect(G_OBJECT(win->window), "show", |
| 8113 G_CALLBACK(winpidgin_ensure_onscreen), win->window); | 8329 G_CALLBACK(winpidgin_ensure_onscreen), win->window); |
| 8114 #endif | 8330 #endif |
| 8145 gtk_widget_destroy(win->window); | 8361 gtk_widget_destroy(win->window); |
| 8146 | 8362 |
| 8147 g_object_unref(G_OBJECT(win->menu.item_factory)); | 8363 g_object_unref(G_OBJECT(win->menu.item_factory)); |
| 8148 | 8364 |
| 8149 purple_notify_close_with_handle(win); | 8365 purple_notify_close_with_handle(win); |
| 8366 purple_signals_disconnect_by_handle(win); | |
| 8150 | 8367 |
| 8151 g_free(win); | 8368 g_free(win); |
| 8152 } | 8369 } |
| 8153 | 8370 |
| 8154 void | 8371 void |
| 8260 | 8477 |
| 8261 if (pidgin_conv_window_get_gtkconv_count(win) == 1) { | 8478 if (pidgin_conv_window_get_gtkconv_count(win) == 1) { |
| 8262 /* Er, bug in notebooks? Switch to the page manually. */ | 8479 /* Er, bug in notebooks? Switch to the page manually. */ |
| 8263 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0); | 8480 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0); |
| 8264 | 8481 |
| 8265 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), | 8482 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); |
| 8266 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs")); | |
| 8267 } else | 8483 } else |
| 8268 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), TRUE); | 8484 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), TRUE); |
| 8269 | 8485 |
| 8270 focus_gtkconv = g_list_nth_data(pidgin_conv_window_get_gtkconvs(win), | 8486 focus_gtkconv = g_list_nth_data(pidgin_conv_window_get_gtkconvs(win), |
| 8271 gtk_notebook_get_current_page(GTK_NOTEBOOK(win->notebook))); | 8487 gtk_notebook_get_current_page(GTK_NOTEBOOK(win->notebook))); |
| 8324 first = gtkconv->icon; | 8540 first = gtkconv->icon; |
| 8325 third = gtkconv->close; | 8541 third = gtkconv->close; |
| 8326 } | 8542 } |
| 8327 | 8543 |
| 8328 ebox = gtk_event_box_new(); | 8544 ebox = gtk_event_box_new(); |
| 8545 #if GTK_CHECK_VERSION(2,4,0) | |
| 8329 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE); | 8546 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE); |
| 8547 #endif | |
| 8330 gtk_container_add(GTK_CONTAINER(ebox), gtkconv->tabby); | 8548 gtk_container_add(GTK_CONTAINER(ebox), gtkconv->tabby); |
| 8331 g_signal_connect(G_OBJECT(ebox), "button-press-event", | 8549 g_signal_connect(G_OBJECT(ebox), "button-press-event", |
| 8332 G_CALLBACK(alias_double_click_cb), gtkconv); | 8550 G_CALLBACK(alias_double_click_cb), gtkconv); |
| 8333 | 8551 |
| 8334 if (gtkconv->tab_label->parent == NULL) { | 8552 if (gtkconv->tab_label->parent == NULL) { |
| 8353 } | 8571 } |
| 8354 | 8572 |
| 8355 gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, !tabs_side && !angle, TRUE, GTK_PACK_START); | 8573 gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, !tabs_side && !angle, TRUE, GTK_PACK_START); |
| 8356 | 8574 |
| 8357 /* show the widgets */ | 8575 /* show the widgets */ |
| 8358 gtk_widget_show(gtkconv->icon); | 8576 /* XXX gtk_widget_show(gtkconv->icon); */ |
| 8359 gtk_widget_show(gtkconv->tab_label); | 8577 gtk_widget_show(gtkconv->tab_label); |
| 8360 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs")) | 8578 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs")) |
| 8361 gtk_widget_show(gtkconv->close); | 8579 gtk_widget_show(gtkconv->close); |
| 8362 gtk_widget_show(gtkconv->tabby); | 8580 gtk_widget_show(gtkconv->tabby); |
| 8363 gtk_widget_show(ebox); | 8581 gtk_widget_show(ebox); |
| 8375 g_object_ref(gtkconv->tab_cont); | 8593 g_object_ref(gtkconv->tab_cont); |
| 8376 gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont)); | 8594 gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont)); |
| 8377 | 8595 |
| 8378 gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index); | 8596 gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index); |
| 8379 | 8597 |
| 8380 /* go back to tabless if need be */ | 8598 /* go back to tabless */ |
| 8381 if (pidgin_conv_window_get_gtkconv_count(win) <= 2) { | 8599 if (pidgin_conv_window_get_gtkconv_count(win) <= 2) { |
| 8382 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), | 8600 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); |
| 8383 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs")); | |
| 8384 } | 8601 } |
| 8385 | 8602 |
| 8386 win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv); | 8603 win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv); |
| 8604 | |
| 8605 if (!win->gtkconvs || !win->gtkconvs->next) | |
| 8606 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); | |
| 8387 | 8607 |
| 8388 if (!win->gtkconvs && win != hidden_convwin) | 8608 if (!win->gtkconvs && win != hidden_convwin) |
| 8389 pidgin_conv_window_destroy(win); | 8609 pidgin_conv_window_destroy(win); |
| 8390 } | 8610 } |
| 8391 | 8611 |