Mercurial > pidgin
diff pidgin/gtkconv.c @ 32819:2c6510167895 default tip
propagate from branch 'im.pidgin.pidgin.2.x.y' (head 3315c5dfbd0ad16511bdcf865e5b07c02d07df24)
to branch 'im.pidgin.pidgin' (head cbd1eda6bcbf0565ae7766396bb8f6f419cb6a9a)
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Sat, 02 Jun 2012 02:30:49 +0000 |
parents | 3d6528f36877 |
children |
line wrap: on
line diff
--- a/pidgin/gtkconv.c Sat Jun 02 02:30:13 2012 +0000 +++ b/pidgin/gtkconv.c Sat Jun 02 02:30:49 2012 +0000 @@ -52,6 +52,8 @@ #include "notify.h" #include "prpl.h" #include "request.h" +#include "theme-loader.h" +#include "theme-manager.h" #include "util.h" #include "version.h" @@ -59,6 +61,8 @@ #include "gtkblist.h" #include "gtkconv.h" #include "gtkconvwin.h" +#include "gtkconv-theme.h" +#include "gtkconv-theme-loader.h" #include "gtkdialogs.h" #include "gtkimhtml.h" #include "gtkimhtmltoolbar.h" @@ -69,11 +73,55 @@ #include "gtkprivacy.h" #include "gtkthemes.h" #include "gtkutils.h" +#include "gtkwebview.h" #include "pidginstock.h" #include "pidgintooltip.h" +#include "smileyparser.h" #include "gtknickcolors.h" +#if !GTK_CHECK_VERSION(2,20,0) +#define gtk_widget_get_realized(x) GTK_WIDGET_REALIZED(x) + +#if !GTK_CHECK_VERSION(2,18,0) +#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) +#define gtk_widget_is_drawable(x) GTK_WIDGET_DRAWABLE(x) +#endif +#endif + +/** + * A GTK+ Instant Message pane. + */ +struct _PidginImPane +{ + GtkWidget *block; + GtkWidget *send_file; + GtkWidget *sep1; + GtkWidget *sep2; + GtkWidget *check; + GtkWidget *progress; + guint32 typing_timer; + + /* Buddy icon stuff */ + GtkWidget *icon_container; + GtkWidget *icon; + gboolean show_icon; + gboolean animate; + GdkPixbufAnimation *anim; + GdkPixbufAnimationIter *iter; + guint32 icon_timer; +}; + +/** + * GTK+ Chat panes. + */ +struct _PidginChatPane +{ + GtkWidget *count; + GtkWidget *list; + GtkWidget *topic_text; +}; + #define CLOSE_CONV_TIMEOUT_SECS (10 * 60) #define AUTO_RESPONSE "<AUTO-REPLY> : " @@ -144,10 +192,13 @@ static GList *offline_list = NULL; static GHashTable *prpl_lists = NULL; +static PurpleTheme *default_conv_theme = NULL; + static gboolean update_send_to_selection(PidginWindow *win); static void generate_send_to_items(PidginWindow *win); /* Prototypes. <-- because Paco-Paco hates this comment. */ +static void load_conv_theme(PidginConversation *gtkconv); static gboolean infopane_entry_activate(PidginConversation *gtkconv); static void got_typing_keypress(PidginConversation *gtkconv, gboolean first); static void gray_stuff_out(PidginConversation *gtkconv); @@ -158,7 +209,6 @@ static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); static void update_typing_icon(PidginConversation *gtkconv); static void update_typing_message(PidginConversation *gtkconv, const char *message); -static const char *item_factory_translate_func (const char *path, gpointer func_data); gboolean pidgin_conv_has_focus(PurpleConversation *conv); static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); @@ -176,7 +226,7 @@ static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { static GdkColor col; - GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); + GtkStyle *style = gtk_widget_get_style(gtkconv->webview); float scale; col = nick_colors[g_str_hash(name) % nbr_nick_colors]; @@ -196,15 +246,16 @@ static PurpleBlistNode * get_conversation_blist_node(PurpleConversation *conv) { + PurpleAccount *account = purple_conversation_get_account(conv); PurpleBlistNode *node = NULL; switch (purple_conversation_get_type(conv)) { case PURPLE_CONV_TYPE_IM: - node = PURPLE_BLIST_NODE(purple_find_buddy(conv->account, conv->name)); + node = PURPLE_BLIST_NODE(purple_find_buddy(account, purple_conversation_get_name(conv))); node = node ? node->parent : NULL; break; case PURPLE_CONV_TYPE_CHAT: - node = PURPLE_BLIST_NODE(purple_blist_find_chat(conv->account, conv->name)); + node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, purple_conversation_get_name(conv))); break; default: break; @@ -276,7 +327,7 @@ default_formatize(PidginConversation *c) { PurpleConversation *conv = c->active_conv; - gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features); + gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), purple_conversation_get_features(conv)); } static void @@ -356,8 +407,32 @@ } tmp = g_string_free(str, FALSE); + } else if (!g_ascii_strcasecmp(args[0], "unsafe")) { + if (purple_debug_is_unsafe()) { + purple_debug_set_unsafe(FALSE); + purple_conversation_write(conv, NULL, _("Unsafe debugging is now disabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } else { + purple_debug_set_unsafe(TRUE); + purple_conversation_write(conv, NULL, _("Unsafe debugging is now enabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } + + return PURPLE_CMD_RET_OK; + } else if (!g_ascii_strcasecmp(args[0], "verbose")) { + if (purple_debug_is_verbose()) { + purple_debug_set_verbose(FALSE); + purple_conversation_write(conv, NULL, _("Verbose debugging is now disabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } else { + purple_debug_set_verbose(TRUE); + purple_conversation_write(conv, NULL, _("Verbose debugging is now enabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } + + return PURPLE_CMD_RET_OK; } else { - purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version"), + purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version unsafe verbose"), PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL)); return PURPLE_CMD_RET_OK; } @@ -376,11 +451,12 @@ static void clear_conversation_scrollback_cb(PurpleConversation *conv, void *data) { - PidginConversation *gtkconv = NULL; - - gtkconv = PIDGIN_CONVERSATION(conv); - if (gtkconv) - gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); + PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); + + if (PIDGIN_CONVERSATION(conv)) { + load_conv_theme(gtkconv); + gtkconv->last_flags = 0; + } } static PurpleCmdRet @@ -420,8 +496,8 @@ g_string_append(s, _("No such command (in this context).")); } } else { - s = g_string_new(_("Use \"/help <command>\" for help on a specific command.\n" - "The following commands are available in this context:\n")); + s = g_string_new(_("Use \"/help <command>\" for help on a specific command.<br/>" + "The following commands are available in this context:<br/>")); text = purple_cmd_list(conv); for (l = text; l; l = l->next) @@ -498,8 +574,8 @@ PurplePluginProtocolInfo *prpl_info = NULL; PurpleConnection *gc; - if ((gc = purple_conversation_get_gc(conv))) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + if ((gc = purple_conversation_get_connection(conv))) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) { char *spaceslash; @@ -578,7 +654,7 @@ gtk_widget_grab_focus(gtkconv->entry); - if (strlen(clean) == 0) { + if (!*clean) { g_free(buf); g_free(clean); return; @@ -591,7 +667,7 @@ flags |= PURPLE_MESSAGE_IMAGES; gc = purple_account_get_connection(account); - if (gc && (conv->features & PURPLE_CONNECTION_NO_NEWLINES)) { + if (gc && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_NO_NEWLINES)) { char **bufs; int i; @@ -657,7 +733,7 @@ PurpleConversation *conv = gtkconv->active_conv; PurpleConnection *gc; - if ((gc = purple_conversation_get_gc(conv))) { + if ((gc = purple_conversation_get_connection(conv))) { pidgin_retrieve_user_info_in_chat(gc, who, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); } } @@ -669,7 +745,7 @@ PurpleConversation *conv = gtkconv->active_conv; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - pidgin_retrieve_user_info(purple_conversation_get_gc(conv), + pidgin_retrieve_user_info(purple_conversation_get_connection(conv), purple_conversation_get_name(conv)); gtk_widget_grab_focus(gtkconv->entry); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { @@ -757,7 +833,7 @@ if (!g_ascii_strcasecmp(buddy, "")) return; - serv_chat_invite(purple_conversation_get_gc(conv), + serv_chat_invite(purple_conversation_get_connection(conv), purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), message, buddy); } @@ -792,7 +868,7 @@ else return; - if (strcmp(convprotocol, purple_account_get_protocol_id(buddy->account))) + if (strcmp(convprotocol, purple_account_get_protocol_id(purple_buddy_get_account(buddy)))) { purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL, _("That buddy is not on the same protocol as this " @@ -877,7 +953,9 @@ GTK_RESPONSE_OK); gtk_container_set_border_width(GTK_CONTAINER(invite_dialog), PIDGIN_HIG_BOX_SPACE); gtk_window_set_resizable(GTK_WINDOW(invite_dialog), FALSE); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(invite_dialog), FALSE); +#endif info->window = GTK_WIDGET(invite_dialog); @@ -974,13 +1052,13 @@ } static void -menu_new_conv_cb(gpointer data, guint action, GtkWidget *widget) +menu_new_conv_cb(GtkAction *action, gpointer data) { pidgin_dialogs_im(); } static void -menu_join_chat_cb(gpointer data, guint action, GtkWidget *widget) +menu_join_chat_cb(GtkAction *action, gpointer data) { pidgin_blist_joinchat_show(); } @@ -988,6 +1066,8 @@ static void savelog_writefile_cb(void *user_data, const char *filename) { + /* TODO WEBKIT: I don't know how to support this using webkit yet. */ +#if 0 PurpleConversation *conv = (PurpleConversation *)user_data; FILE *fp; const char *name; @@ -1014,6 +1094,7 @@ fprintf(fp, "\n</body>\n</html>\n"); fclose(fp); +#endif /* if 0 */ } /* @@ -1021,11 +1102,12 @@ * plaintext v. HTML file. */ static void -menu_save_as_cb(gpointer data, guint action, GtkWidget *widget) +menu_save_as_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); - PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); + PurpleAccount *account = purple_conversation_get_account(conv); + PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); const char *name; gchar *buf; gchar *c; @@ -1033,7 +1115,7 @@ if (buddy != NULL) name = purple_buddy_get_contact_alias(buddy); else - name = purple_normalize(conv->account, conv->name); + name = purple_normalize(account, purple_conversation_get_name(conv)); buf = g_strdup_printf("%s.html", name); for (c = buf ; *c ; c++) @@ -1051,7 +1133,7 @@ } static void -menu_view_log_cb(gpointer data, guint action, GtkWidget *widget) +menu_view_log_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1078,7 +1160,6 @@ gdk_window_set_cursor(gtkblist->window->window, cursor); gdk_window_set_cursor(win->window->window, cursor); gdk_cursor_unref(cursor); - gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window))); name = purple_conversation_get_name(conv); account = purple_conversation_get_account(conv); @@ -1105,7 +1186,7 @@ } static void -menu_clear_cb(gpointer data, guint action, GtkWidget *widget) +menu_clear_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1115,7 +1196,7 @@ } static void -menu_find_cb(gpointer data, guint action, GtkWidget *widget) +menu_find_cb(GtkAction *action, gpointer data) { PidginWindow *gtkwin = data; PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(gtkwin); @@ -1125,7 +1206,7 @@ #ifdef USE_VV static void -menu_initiate_media_call_cb(gpointer data, guint action, GtkWidget *widget) +menu_initiate_media_call_cb(GtkAction *action, gpointer data) { PidginWindow *win = (PidginWindow *)data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); @@ -1133,39 +1214,44 @@ purple_prpl_initiate_media(account, purple_conversation_get_name(conv), - action == 0 ? PURPLE_MEDIA_AUDIO : - action == 1 ? PURPLE_MEDIA_VIDEO : - action == 2 ? PURPLE_MEDIA_AUDIO | + action == win->audio_call ? PURPLE_MEDIA_AUDIO : + action == win->video_call ? PURPLE_MEDIA_VIDEO : + action == win->audio_video_call ? PURPLE_MEDIA_AUDIO | PURPLE_MEDIA_VIDEO : PURPLE_MEDIA_NONE); } #endif static void -menu_send_file_cb(gpointer data, guint action, GtkWidget *widget) +menu_send_file_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - serv_send_file(purple_conversation_get_gc(conv), purple_conversation_get_name(conv), NULL); - } - -} - -static void -menu_get_attention_cb(gpointer data, guint action, GtkWidget *widget) + serv_send_file(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), NULL); + } + +} + +static void +menu_get_attention_cb(GObject *obj, gpointer data) { PidginWindow *win = data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - purple_prpl_send_attention(purple_conversation_get_gc(conv), - purple_conversation_get_name(conv), 0); - } -} - -static void -menu_add_pounce_cb(gpointer data, guint action, GtkWidget *widget) + int index; + if ((GtkAction *)obj == win->menu.get_attention) + index = 0; + else + index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(obj), "index")); + purple_prpl_send_attention(purple_conversation_get_connection(conv), + purple_conversation_get_name(conv), index); + } +} + +static void +menu_add_pounce_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1177,7 +1263,7 @@ } static void -menu_insert_link_cb(gpointer data, guint action, GtkWidget *widget) +menu_insert_link_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PidginConversation *gtkconv; @@ -1191,7 +1277,7 @@ } static void -menu_insert_image_cb(gpointer data, guint action, GtkWidget *widget) +menu_insert_image_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PidginConversation *gtkconv; @@ -1206,7 +1292,7 @@ static void -menu_alias_cb(gpointer data, guint action, GtkWidget *widget) +menu_alias_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1233,7 +1319,7 @@ } static void -menu_get_info_cb(gpointer data, guint action, GtkWidget *widget) +menu_get_info_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1244,7 +1330,7 @@ } static void -menu_invite_cb(gpointer data, guint action, GtkWidget *widget) +menu_invite_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1255,7 +1341,7 @@ } static void -menu_block_cb(gpointer data, guint action, GtkWidget *widget) +menu_block_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1266,7 +1352,7 @@ } static void -menu_unblock_cb(gpointer data, guint action, GtkWidget *widget) +menu_unblock_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1277,7 +1363,7 @@ } static void -menu_add_remove_cb(gpointer data, guint action, GtkWidget *widget) +menu_add_remove_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1322,7 +1408,7 @@ } static void -menu_close_conv_cb(gpointer data, guint action, GtkWidget *widget) +menu_close_conv_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; @@ -1330,7 +1416,7 @@ } static void -menu_logging_cb(gpointer data, guint action, GtkWidget *widget) +menu_logging_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1342,7 +1428,7 @@ if (conv == NULL) return; - logging = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); + logging = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); if (logging == purple_conversation_is_logging(conv)) return; @@ -1356,16 +1442,14 @@ purple_conversation_write(conv, NULL, _("Logging started. Future messages in this conversation will be logged."), - conv->logs ? (PURPLE_MESSAGE_SYSTEM) : - (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG), + PURPLE_MESSAGE_SYSTEM, time(NULL)); } else { purple_conversation_write(conv, NULL, _("Logging stopped. Future messages in this conversation will not be logged."), - conv->logs ? (PURPLE_MESSAGE_SYSTEM) : - (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG), + PURPLE_MESSAGE_SYSTEM, time(NULL)); /* Disable the logging second, so that the above message can be logged. */ @@ -1373,7 +1457,7 @@ } /* Save the setting IFF it's different than the pref. */ - switch (conv->type) + switch (purple_conversation_get_type(conv)) { case PURPLE_CONV_TYPE_IM: if (logging == purple_prefs_get_bool("/purple/logging/log_ims")) @@ -1395,14 +1479,14 @@ } static void -menu_toolbar_cb(gpointer data, guint action, GtkWidget *widget) +menu_toolbar_cb(GtkAction *action, gpointer data) { purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar", - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); -} - -static void -menu_sounds_cb(gpointer data, guint action, GtkWidget *widget) + gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))); +} + +static void +menu_sounds_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1417,20 +1501,13 @@ gtkconv = PIDGIN_CONVERSATION(conv); gtkconv->make_sound = - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); + gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); node = get_conversation_blist_node(conv); if (node) purple_blist_node_set_bool(node, "gtk-mute-sound", !gtkconv->make_sound); } static void -menu_timestamps_cb(gpointer data, guint action, GtkWidget *widget) -{ - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps", - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); -} - -static void chat_do_im(PidginConversation *gtkconv, const char *who) { PurpleConversation *conv = gtkconv->active_conv; @@ -1445,7 +1522,7 @@ gc = purple_account_get_connection(account); g_return_if_fail(gc != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && prpl_info->get_cb_real_name) real_who = prpl_info->get_cb_real_name(gc, @@ -1496,12 +1573,12 @@ PurplePluginProtocolInfo *prpl_info; PurpleConversation *conv = gtkconv->active_conv; const char *who = g_object_get_data(G_OBJECT(w), "user_data"); - PurpleConnection *gc = purple_conversation_get_gc(conv); + PurpleConnection *gc = purple_conversation_get_connection(conv); gchar *real_who = NULL; g_return_if_fail(gc != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && prpl_info->get_cb_real_name) real_who = prpl_info->get_cb_real_name(gc, @@ -1522,32 +1599,6 @@ } static void -menu_chat_get_away_cb(GtkWidget *w, PidginConversation *gtkconv) -{ - PurpleConversation *conv = gtkconv->active_conv; - PurplePluginProtocolInfo *prpl_info = NULL; - PurpleConnection *gc; - char *who; - - gc = purple_conversation_get_gc(conv); - who = g_object_get_data(G_OBJECT(w), "user_data"); - - if (gc != NULL) { - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); - - /* - * May want to expand this to work similarly to menu_info_cb? - */ - - if (prpl_info->get_cb_away != NULL) - { - prpl_info->get_cb_away(gc, - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); - } - } -} - -static void menu_chat_add_remove_cb(GtkWidget *w, PidginConversation *gtkconv) { PurpleConversation *conv = gtkconv->active_conv; @@ -1570,7 +1621,7 @@ static GtkTextMark * get_mark_for_user(PidginConversation *gtkconv, const char *who) { - GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)); + GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->webview)); char *tmp = g_strconcat("user:", who, NULL); GtkTextMark *mark = gtk_text_buffer_get_mark(buf, tmp); @@ -1581,6 +1632,8 @@ static void menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv) { +/* TODO WEBKIT: This doesn't work yet, of course... */ +#if 0 GtkTextMark *mark; const char *who; @@ -1591,6 +1644,7 @@ gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0); else g_return_if_reached(); +#endif /* if 0 */ } static GtkWidget * @@ -1599,12 +1653,13 @@ static GtkWidget *menu = NULL; PurplePluginProtocolInfo *prpl_info = NULL; PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); + PurpleAccount *account = purple_conversation_get_account(conv); gboolean is_me = FALSE; GtkWidget *button; PurpleBuddy *buddy = NULL; if (gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); /* * If a menu already exists, destroy it before creating a new one, @@ -1613,7 +1668,7 @@ if (menu) gtk_widget_destroy(menu); - if (!strcmp(chat->nick, purple_normalize(conv->account, who))) + if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, who))) is_me = TRUE; menu = gtk_menu_new(); @@ -1678,18 +1733,8 @@ g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free); } - if (prpl_info && prpl_info->get_cb_away) { - button = pidgin_new_item_from_stock(menu, _("Get Away Message"), PIDGIN_STOCK_AWAY, - G_CALLBACK(menu_chat_get_away_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); - - if (gc == NULL) - gtk_widget_set_sensitive(button, FALSE); - else - g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free); - } - if (!is_me && prpl_info && !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - if ((buddy = purple_find_buddy(conv->account, who)) != NULL) + if ((buddy = purple_find_buddy(account, who)) != NULL) button = pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE, G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); else @@ -1710,8 +1755,8 @@ if (buddy != NULL) { - if (purple_account_is_connected(conv->account)) - pidgin_append_blist_node_proto_menu(menu, conv->account->gc, + if (purple_account_is_connected(account)) + pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account), (PurpleBlistNode *)buddy); pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy); gtk_widget_show_all(menu); @@ -1737,7 +1782,7 @@ gtkconv = PIDGIN_CONVERSATION(conv); gtkchat = gtkconv->u.chat; account = purple_conversation_get_account(conv); - gc = account->gc; + gc = purple_account_get_connection(account); model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -1773,7 +1818,7 @@ gtkchat = gtkconv->u.chat; account = purple_conversation_get_account(conv); - gc = account->gc; + gc = purple_account_get_connection(account); model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -1805,10 +1850,13 @@ chat_do_im(gtkconv, who); } else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) { /* Move to user's anchor */ +/* TODO WEBKIT: This isn't implemented yet. */ +#if 0 GtkTextMark *mark = get_mark_for_user(gtkconv, who); if(mark != NULL) gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0); +#endif /* if 0 */ } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { GtkWidget *menu = create_chat_menu (conv, who, gc); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, @@ -1885,8 +1933,8 @@ GtkWidget *from; GtkWidget *to; } transitions[] = { - {gtkconv->entry, gtkconv->imhtml}, - {gtkconv->imhtml, chat ? gtkconv->u.chat->list : gtkconv->entry}, + {gtkconv->entry, gtkconv->webview}, + {gtkconv->webview, chat ? gtkconv->u.chat->list : gtkconv->entry}, {chat ? gtkconv->u.chat->list : NULL, gtkconv->entry}, {NULL, NULL} }, *ptr; @@ -2142,14 +2190,14 @@ break; case GDK_Page_Up: - case GDK_KP_Page_Up: - gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml)); + case GDK_KP_Page_Up: + gtk_webview_page_up(GTK_WEBVIEW(gtkconv->webview)); return TRUE; break; case GDK_Page_Down: - case GDK_KP_Page_Down: - gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml)); + case GDK_KP_Page_Down: + gtk_webview_page_down(GTK_WEBVIEW(gtkconv->webview)); return TRUE; break; @@ -2236,6 +2284,7 @@ PurpleConversation *old_conv; GtkIMHtml *entry; const char *protocol_name; + PurpleConnectionFlags features; g_return_if_fail(conv != NULL); @@ -2254,17 +2303,18 @@ gtkconv->active_conv = conv; purple_conversation_set_logging(conv, - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging))); + gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(gtkconv->win->menu.logging))); entry = GTK_IMHTML(gtkconv->entry); - protocol_name = purple_account_get_protocol_name(conv->account); + protocol_name = purple_account_get_protocol_name(purple_conversation_get_account(conv)); gtk_imhtml_set_protocol_name(entry, protocol_name); - gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); - - if (!(conv->features & PURPLE_CONNECTION_HTML)) + /* TODO WEBKIT: gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); */ + + features = purple_conversation_get_features(conv); + if (!(features & PURPLE_CONNECTION_HTML)) gtk_imhtml_clear_formatting(GTK_IMHTML(gtkconv->entry)); - else if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO && - !(old_conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)) + else if (features & PURPLE_CONNECTION_FORMATTING_WBFO && + !(purple_conversation_get_features(old_conv) & PURPLE_CONNECTION_FORMATTING_WBFO)) { /* The old conversation allowed formatting on parts of the * buffer, but the new one only allows it on the whole @@ -2304,12 +2354,12 @@ gtk_imhtml_toggle_fontface(entry, fontface); - if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE)) + if (!(features & PURPLE_CONNECTION_NO_FONTSIZE)) gtk_imhtml_font_set_size(entry, fontsize); gtk_imhtml_toggle_forecolor(entry, forecolor); - if (!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR)) + if (!(features & PURPLE_CONNECTION_NO_BGCOLOR)) { gtk_imhtml_toggle_backcolor(entry, backcolor); gtk_imhtml_toggle_background(entry, background); @@ -2327,7 +2377,7 @@ * here, we didn't call gtk_imhtml_clear_formatting() (because we want to * preserve the formatting exactly as it is), so we have to do this now. */ gtk_imhtml_set_whole_buffer_formatting_only(entry, - (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)); + (features & PURPLE_CONNECTION_FORMATTING_WBFO)); } purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv); @@ -2392,7 +2442,7 @@ /* We deleted all the text, so turn off typing. */ purple_conv_im_stop_send_typed_timeout(im); - serv_send_typing(purple_conversation_get_gc(conv), + serv_send_typing(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), PURPLE_NOT_TYPING); } @@ -2557,7 +2607,7 @@ status = infopane_status = pidgin_conv_get_icon_stock(conv); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleBuddy *b = purple_find_buddy(conv->account, conv->name); + PurpleBuddy *b = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (b) emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b); } @@ -2578,7 +2628,7 @@ g_object_unref(emblem); if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) { - emblem = pidgin_create_prpl_icon(gtkconv->active_conv->account, PIDGIN_PRPL_ICON_SMALL); + emblem = pidgin_create_prpl_icon(purple_conversation_get_account(gtkconv->active_conv), PIDGIN_PRPL_ICON_SMALL); } else { emblem = NULL; } @@ -2634,7 +2684,7 @@ gtkconv = PIDGIN_CONVERSATION(conv); account = purple_conversation_get_account(conv); - if (!(account && account->gc)) { + if (!(account && purple_account_get_connection(account))) { gtkconv->u.im->icon_timer = 0; return FALSE; } @@ -2841,11 +2891,11 @@ ext = purple_buddy_icon_get_extension(purple_conv_im_get_icon(PURPLE_CONV_IM(conv))); - buf = g_strdup_printf("%s.%s", purple_normalize(conv->account, conv->name), ext); + buf = g_strdup_printf("%s.%s", purple_normalize(purple_conversation_get_account(conv), purple_conversation_get_name(conv)), ext); purple_request_file(gtkconv, _("Save Icon"), buf, TRUE, G_CALLBACK(saveicon_writefile_cb), NULL, - conv->account, NULL, conv, + purple_conversation_get_account(conv), NULL, conv, gtkconv); g_free(buf); @@ -3068,91 +3118,96 @@ return gtkconv->win; } -static GtkItemFactoryEntry menu_items[] = +static GtkActionEntry menu_entries[] = +/* TODO: fill out tooltips... */ { /* Conversation menu */ - { N_("/_Conversation"), NULL, NULL, 0, "<Branch>", NULL }, - - { N_("/Conversation/New Instant _Message..."), "<CTL>M", menu_new_conv_cb, - 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW }, - { N_("/Conversation/Join a _Chat..."), NULL, menu_join_chat_cb, - 0, "<StockItem>", PIDGIN_STOCK_CHAT }, - - { "/Conversation/sep0", NULL, NULL, 0, "<Separator>", NULL }, - - { N_("/Conversation/_Find..."), NULL, menu_find_cb, 0, - "<StockItem>", GTK_STOCK_FIND }, - { N_("/Conversation/View _Log"), NULL, menu_view_log_cb, 0, "<Item>", NULL }, - { N_("/Conversation/_Save As..."), NULL, menu_save_as_cb, 0, - "<StockItem>", GTK_STOCK_SAVE_AS }, - { N_("/Conversation/Clea_r Scrollback"), "<CTL>L", menu_clear_cb, 0, "<StockItem>", GTK_STOCK_CLEAR }, - - { "/Conversation/sep1", NULL, NULL, 0, "<Separator>", NULL }, + { "ConversationMenu", NULL, N_("_Conversation"), NULL, NULL, NULL }, + { "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "<control>M", NULL, G_CALLBACK(menu_new_conv_cb) }, + { "JoinAChat", PIDGIN_STOCK_CHAT, N_("Join a _Chat..."), NULL, NULL, G_CALLBACK(menu_join_chat_cb) }, + { "Find", GTK_STOCK_FIND, N_("_Find..."), NULL, NULL, G_CALLBACK(menu_find_cb) }, + { "ViewLog", NULL, N_("View _Log"), NULL, NULL, G_CALLBACK(menu_view_log_cb) }, + { "SaveAs", GTK_STOCK_SAVE_AS, N_("_Save As..."), NULL, NULL, G_CALLBACK(menu_save_as_cb) }, + { "ClearScrollback", GTK_STOCK_CLEAR, N_("Clea_r Scrollback"), "<control>L", NULL, G_CALLBACK(menu_clear_cb) }, #ifdef USE_VV - { N_("/Conversation/M_edia"), NULL, NULL, 0, "<Branch>", NULL }, - - { N_("/Conversation/Media/_Audio Call"), NULL, menu_initiate_media_call_cb, 0, - "<StockItem>", PIDGIN_STOCK_TOOLBAR_AUDIO_CALL }, - { N_("/Conversation/Media/_Video Call"), NULL, menu_initiate_media_call_cb, 1, - "<StockItem>", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL }, - { N_("/Conversation/Media/Audio\\/Video _Call"), NULL, menu_initiate_media_call_cb, 2, - "<StockItem>", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL }, + { "MediaMenu", NULL, N_("M_edia"), NULL, NULL, NULL }, + { "AudioCall", PIDGIN_STOCK_TOOLBAR_AUDIO_CALL, N_("_Audio Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) }, + { "VideoCall", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, N_("_Video Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) }, + { "AudioVideoCall", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, N_("Audio/Video _Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) }, #endif - { N_("/Conversation/Se_nd File..."), NULL, menu_send_file_cb, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SEND_FILE }, - { N_("/Conversation/Get _Attention"), NULL, menu_get_attention_cb, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION }, - { N_("/Conversation/Add Buddy _Pounce..."), NULL, menu_add_pounce_cb, - 0, "<Item>", NULL }, - { N_("/Conversation/_Get Info"), "<CTL>O", menu_get_info_cb, 0, - "<StockItem>", PIDGIN_STOCK_TOOLBAR_USER_INFO }, - { N_("/Conversation/In_vite..."), NULL, menu_invite_cb, 0, - "<Item>", NULL }, - { N_("/Conversation/M_ore"), NULL, NULL, 0, "<Branch>", NULL }, - - { "/Conversation/sep2", NULL, NULL, 0, "<Separator>", NULL }, - - { N_("/Conversation/Al_ias..."), NULL, menu_alias_cb, 0, - "<Item>", NULL }, - { N_("/Conversation/_Block..."), NULL, menu_block_cb, 0, - "<StockItem>", PIDGIN_STOCK_TOOLBAR_BLOCK }, - { N_("/Conversation/_Unblock..."), NULL, menu_unblock_cb, 0, - "<StockItem>", PIDGIN_STOCK_TOOLBAR_UNBLOCK }, - { N_("/Conversation/_Add..."), NULL, menu_add_remove_cb, 0, - "<StockItem>", GTK_STOCK_ADD }, - { N_("/Conversation/_Remove..."), NULL, menu_add_remove_cb, 0, - "<StockItem>", GTK_STOCK_REMOVE }, - - { "/Conversation/sep3", NULL, NULL, 0, "<Separator>", NULL }, - - { N_("/Conversation/Insert Lin_k..."), NULL, menu_insert_link_cb, 0, - "<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_LINK }, - { N_("/Conversation/Insert Imag_e..."), NULL, menu_insert_image_cb, 0, - "<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE }, - - { "/Conversation/sep4", NULL, NULL, 0, "<Separator>", NULL }, - - - { N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0, - "<StockItem>", GTK_STOCK_CLOSE }, + { "SendFile", PIDGIN_STOCK_TOOLBAR_SEND_FILE, N_("Se_nd File..."), NULL, NULL, G_CALLBACK(menu_send_file_cb) }, + { "GetAttention", PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION, N_("Get _Attention"), NULL, NULL, G_CALLBACK(menu_get_attention_cb) }, + { "AddBuddyPounce", NULL, N_("Add Buddy _Pounce..."), NULL, NULL, G_CALLBACK(menu_add_pounce_cb) }, + { "GetInfo", PIDGIN_STOCK_TOOLBAR_USER_INFO, N_("_Get Info"), "<control>O", NULL, G_CALLBACK(menu_get_info_cb) }, + { "Invite", NULL, N_("In_vite..."), NULL, NULL, G_CALLBACK(menu_invite_cb) }, + { "MoreMenu", NULL, N_("M_ore"), NULL, NULL, NULL }, + { "Alias", NULL, N_("Al_ias..."), NULL, NULL, G_CALLBACK(menu_alias_cb) }, + { "Block", PIDGIN_STOCK_TOOLBAR_BLOCK, N_("_Block..."), NULL, NULL, G_CALLBACK(menu_block_cb) }, + { "Unblock", PIDGIN_STOCK_TOOLBAR_UNBLOCK, N_("_Unblock..."), NULL, NULL, G_CALLBACK(menu_unblock_cb) }, + { "Add", GTK_STOCK_ADD, N_("_Add..."), NULL, NULL, G_CALLBACK(menu_add_remove_cb) }, + { "Remove", GTK_STOCK_REMOVE, N_("_Remove..."), NULL, NULL, G_CALLBACK(menu_add_remove_cb) }, + { "InsertLink", PIDGIN_STOCK_TOOLBAR_INSERT_LINK, N_("Insert Lin_k..."), NULL, NULL, G_CALLBACK(menu_insert_link_cb) }, + { "InsertImage", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, N_("Insert Imag_e..."), NULL, NULL, G_CALLBACK(menu_insert_image_cb) }, + { "Close", GTK_STOCK_CLOSE, N_("_Close"), NULL, NULL, G_CALLBACK(menu_close_conv_cb) }, /* Options */ - { N_("/_Options"), NULL, NULL, 0, "<Branch>", NULL }, - { N_("/Options/Enable _Logging"), NULL, menu_logging_cb, 0, "<CheckItem>", NULL }, - { N_("/Options/Enable _Sounds"), NULL, menu_sounds_cb, 0, "<CheckItem>", NULL }, - { "/Options/sep0", NULL, NULL, 0, "<Separator>", NULL }, - { N_("/Options/Show Formatting _Toolbars"), NULL, menu_toolbar_cb, 0, "<CheckItem>", NULL }, - { N_("/Options/Show Ti_mestamps"), NULL, menu_timestamps_cb, 0, "<CheckItem>", NULL }, + { "OptionsMenu", NULL, N_("_Options"), NULL, NULL, NULL }, +}; + +/* Toggle items */ +static const GtkToggleActionEntry menu_toggle_entries[] = { + { "EnableLogging", NULL, N_("Enable _Logging"), NULL, NULL, G_CALLBACK(menu_logging_cb), FALSE }, + { "EnableSounds", NULL, N_("Enable _Sounds"), NULL, NULL, G_CALLBACK(menu_sounds_cb), FALSE }, + { "ShowFormattingToolbars", NULL, N_("Show Formatting _Toolbars"), NULL, NULL, G_CALLBACK(menu_toolbar_cb), FALSE }, }; -static const int menu_item_count = -sizeof(menu_items) / sizeof(*menu_items); - -static const char * -item_factory_translate_func (const char *path, gpointer func_data) -{ - return _(path); -} +static const char *conversation_menu = +"<ui>" + "<menubar name='Conversation'>" + "<menu action='ConversationMenu'>" + "<menuitem action='NewInstantMessage'/>" + "<menuitem action='JoinAChat'/>" + "<separator/>" + "<menuitem action='Find'/>" + "<menuitem action='ViewLog'/>" + "<menuitem action='SaveAs'/>" + "<menuitem action='ClearScrollback'/>" + "<separator/>" +#ifdef USE_VV + "<menu action='MediaMenu'>" + "<menuitem action='AudioCall'/>" + "<menuitem action='VideoCall'/>" + "<menuitem action='AudioVideoCall'/>" + "</menu>" +#endif + "<menuitem action='SendFile'/>" + "<menuitem action='GetAttention'/>" + "<menuitem action='AddBuddyPounce'/>" + "<menuitem action='GetInfo'/>" + "<menuitem action='Invite'/>" + "<menu action='MoreMenu'/>" + "<separator/>" + "<menuitem action='Alias'/>" + "<menuitem action='Block'/>" + "<menuitem action='Unblock'/>" + "<menuitem action='Add'/>" + "<menuitem action='Remove'/>" + "<separator/>" + "<menuitem action='InsertLink'/>" + "<menuitem action='InsertImage'/>" + "<separator/>" + "<menuitem action='Close'/>" + "</menu>" + "<menu action='OptionsMenu'>" + "<menuitem action='EnableLogging'/>" + "<menuitem action='EnableSounds'/>" + "<separator/>" + "<menuitem action='ShowFormattingToolbars'/>" + "</menu>" + "</menubar>" +"</ui>"; static void sound_method_pref_changed_cb(const char *name, PurplePrefType type, @@ -3163,19 +3218,18 @@ if (!strcmp(method, "none")) { - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), - FALSE); - gtk_widget_set_sensitive(win->menu.sounds, FALSE); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds), + FALSE); + gtk_action_set_sensitive(win->menu.sounds, FALSE); } else { PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win); if (gtkconv != NULL) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), - gtkconv->make_sound); - gtk_widget_set_sensitive(win->menu.sounds, TRUE); - + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds), + gtkconv->make_sound); + gtk_action_set_sensitive(win->menu.sounds, TRUE); } } @@ -3185,21 +3239,23 @@ { GList *list; PurpleConversation *conv; + PurpleAccount *account; PurpleBlistNode *node = NULL; PurpleChat *chat = NULL; PurpleBuddy *buddy = NULL; gboolean ret; conv = gtkconv->active_conv; + account = purple_conversation_get_account(conv); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { - chat = purple_blist_find_chat(conv->account, conv->name); - - if ((chat == NULL) && (gtkconv->imhtml != NULL)) { - chat = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); - } - - if ((chat == NULL) && (gtkconv->imhtml != NULL)) { + chat = purple_blist_find_chat(account, purple_conversation_get_name(conv)); + + if ((chat == NULL) && (gtkconv->webview != NULL)) { + chat = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat"); + } + + if ((chat == NULL) && (gtkconv->webview != NULL)) { GHashTable *components; PurpleAccount *account = purple_conversation_get_account(conv); PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); @@ -3214,30 +3270,30 @@ g_hash_table_replace(components, g_strdup("channel"), g_strdup(purple_conversation_get_name(conv))); } - chat = purple_chat_new(conv->account, NULL, components); + chat = purple_chat_new(account, NULL, components); purple_blist_node_set_flags((PurpleBlistNode *)chat, PURPLE_BLIST_NODE_FLAG_NO_SAVE); - g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_chat", + g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_chat", chat, (GDestroyNotify)purple_blist_remove_chat); } } else { - if (!purple_account_is_connected(conv->account)) + if (!purple_account_is_connected(account)) return FALSE; - buddy = purple_find_buddy(conv->account, conv->name); + buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); /* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle * removing "isolated" buddy nodes well */ if (purple_version_check(2, 0, 2) == NULL) { - if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { - buddy = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); + if ((buddy == NULL) && (gtkconv->webview != NULL)) { + buddy = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy"); } - if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { - buddy = purple_buddy_new(conv->account, conv->name, NULL); + if ((buddy == NULL) && (gtkconv->webview != NULL)) { + buddy = purple_buddy_new(account, purple_conversation_get_name(conv), NULL); purple_blist_node_set_flags((PurpleBlistNode *)buddy, PURPLE_BLIST_NODE_FLAG_NO_SAVE); - g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_buddy", + g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_buddy", buddy, (GDestroyNotify)purple_buddy_destroy); } } @@ -3256,8 +3312,8 @@ /* XXX: */ } } else if (node) { - if (purple_account_is_connected(conv->account)) - pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node); + if (purple_account_is_connected(account)) + pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account), node); pidgin_append_blist_node_extended_menu(menu, node); } @@ -3303,38 +3359,100 @@ purple_prpl_get_media_caps(account, purple_conversation_get_name(conv)); - gtk_widget_set_sensitive(win->audio_call, + gtk_action_set_sensitive(win->audio_call, caps & PURPLE_MEDIA_CAPS_AUDIO ? TRUE : FALSE); - gtk_widget_set_sensitive(win->video_call, + gtk_action_set_sensitive(win->video_call, caps & PURPLE_MEDIA_CAPS_VIDEO ? TRUE : FALSE); - gtk_widget_set_sensitive(win->audio_video_call, + gtk_action_set_sensitive(win->audio_video_call, caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO ? TRUE : FALSE); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { /* for now, don't care about chats... */ - gtk_widget_set_sensitive(win->audio_call, FALSE); - gtk_widget_set_sensitive(win->video_call, FALSE); - gtk_widget_set_sensitive(win->audio_video_call, FALSE); + gtk_action_set_sensitive(win->audio_call, FALSE); + gtk_action_set_sensitive(win->video_call, FALSE); + gtk_action_set_sensitive(win->audio_video_call, FALSE); } else { - gtk_widget_set_sensitive(win->audio_call, FALSE); - gtk_widget_set_sensitive(win->video_call, FALSE); - gtk_widget_set_sensitive(win->audio_video_call, FALSE); + gtk_action_set_sensitive(win->audio_call, FALSE); + gtk_action_set_sensitive(win->video_call, FALSE); + gtk_action_set_sensitive(win->audio_video_call, FALSE); } #endif } static void +regenerate_attention_items(PidginWindow *win) +{ + GtkWidget *attention; + GtkWidget *menu; + PurpleConversation *conv; + PurpleConnection *pc; + PurplePlugin *prpl = NULL; + PurplePluginProtocolInfo *prpl_info = NULL; + GList *list; + + conv = pidgin_conv_window_get_active_conversation(win); + if (!conv) + return; + + attention = gtk_ui_manager_get_widget(win->menu.ui, + "/Conversation/ConversationMenu/GetAttention"); + + /* Remove the previous entries */ + gtk_menu_item_set_submenu(GTK_MENU_ITEM(attention), NULL); + + pc = purple_conversation_get_connection(conv); + if (pc != NULL) + prpl = purple_connection_get_prpl(pc); + if (prpl != NULL) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + + if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_attention_types)) { + list = prpl_info->get_attention_types(purple_connection_get_account(pc)); + + /* Multiple attention types */ + if (list && list->next) { + int index = 0; + + menu = gtk_menu_new(); + while (list) { + PurpleAttentionType *type; + GtkWidget *menuitem; + + type = list->data; + + menuitem = gtk_menu_item_new_with_label(purple_attention_type_get_name(type)); + g_object_set_data(G_OBJECT(menuitem), "index", GINT_TO_POINTER(index)); + g_signal_connect(G_OBJECT(menuitem), "activate", + G_CALLBACK(menu_get_attention_cb), + win); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + + index++; + list = g_list_delete_link(list, list); + } + + gtk_menu_item_set_submenu(GTK_MENU_ITEM(attention), menu); + gtk_widget_show_all(menu); + } + } +} + +static void regenerate_options_items(PidginWindow *win) { GtkWidget *menu; PidginConversation *gtkconv; GList *list; + GtkWidget *more_menu; gtkconv = pidgin_conv_window_get_active_gtkconv(win); - menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More")); + more_menu = gtk_ui_manager_get_widget(win->menu.ui, + "/Conversation/ConversationMenu/MoreMenu"); + gtk_widget_show(more_menu); + menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(more_menu)); /* Remove the previous entries */ for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; ) @@ -3390,7 +3508,8 @@ action_items = g_list_delete_link(action_items, action_items); } - menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options")); + item = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/OptionsMenu"); + menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item)); list = purple_conversation_get_extended_menu(conv); if (list) { @@ -3414,6 +3533,7 @@ regenerate_media_items(win); regenerate_options_items(win); regenerate_plugins_items(win); + regenerate_attention_items(win); /* The following are to make sure the 'More' submenu is not regenerated every time * the focus shifts from 'Conversations' to some other menu and back. */ @@ -3426,7 +3546,7 @@ { /* The menubar has been deactivated. Make sure the 'More' submenu is regenerated next time * the 'Conversation' menu pops up. */ - GtkWidget *menuitem = gtk_item_factory_get_item(win->menu.item_factory, N_("/Conversation")); + GtkWidget *menuitem = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/ConversationMenu"); g_signal_handlers_unblock_by_func(G_OBJECT(menuitem), G_CALLBACK(menubar_activated), win); g_signal_handlers_disconnect_by_func(G_OBJECT(win->menu.menubar), G_CALLBACK(focus_out_from_menubar), win); @@ -3437,129 +3557,142 @@ { GtkAccelGroup *accel_group; const char *method; + GtkActionGroup *action_group; + GError *error; GtkWidget *menuitem; - accel_group = gtk_accel_group_new (); + action_group = gtk_action_group_new("ConversationActions"); + gtk_action_group_add_actions(action_group, + menu_entries, + G_N_ELEMENTS(menu_entries), + win); + gtk_action_group_add_toggle_actions(action_group, + menu_toggle_entries, + G_N_ELEMENTS(menu_toggle_entries), + win); +#ifdef ENABLE_NLS + gtk_action_group_set_translation_domain(action_group, + PACKAGE); +#endif + + win->menu.ui = gtk_ui_manager_new(); + gtk_ui_manager_insert_action_group(win->menu.ui, action_group, 0); + + accel_group = gtk_ui_manager_get_accel_group(win->menu.ui); gtk_window_add_accel_group(GTK_WINDOW(win->window), accel_group); - g_object_unref(accel_group); - - win->menu.item_factory = - gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group); - - gtk_item_factory_set_translate_func(win->menu.item_factory, - (GtkTranslateFunc)item_factory_translate_func, - NULL, NULL); - - gtk_item_factory_create_items(win->menu.item_factory, menu_item_count, - menu_items, win); g_signal_connect(G_OBJECT(accel_group), "accel-changed", G_CALLBACK(pidgin_save_accels_cb), NULL); + error = NULL; + if (!gtk_ui_manager_add_ui_from_string(win->menu.ui, conversation_menu, -1, &error)) + { + g_message("building menus failed: %s", error->message); + g_error_free(error); + exit(EXIT_FAILURE); + } + + win->menu.menubar = + gtk_ui_manager_get_widget(win->menu.ui, "/Conversation"); + /* Make sure the 'Conversation -> More' menuitems are regenerated whenever * the 'Conversation' menu pops up because the entries can change after the * conversation is created. */ - menuitem = gtk_item_factory_get_item(win->menu.item_factory, N_("/Conversation")); + menuitem = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/ConversationMenu"); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menubar_activated), win); - win->menu.menubar = - gtk_item_factory_get_widget(win->menu.item_factory, "<main>"); - win->menu.view_log = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/View Log")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/ViewLog"); #ifdef USE_VV win->audio_call = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Media/Audio Call")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/MediaMenu/AudioCall"); win->video_call = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Media/Video Call")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/MediaMenu/VideoCall"); win->audio_video_call = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Media/Audio\\/Video Call")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/MediaMenu/AudioVideoCall"); #endif /* --- */ win->menu.send_file = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Send File...")); - - g_object_set_data(G_OBJECT(win->window), "get_attention", - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Get Attention"))); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/SendFile"); + + win->menu.get_attention = + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/GetAttention"); + win->menu.add_pounce = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Add Buddy Pounce...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/AddBuddyPounce"); /* --- */ win->menu.get_info = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Get Info")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/GetInfo"); win->menu.invite = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Invite...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Invite"); /* --- */ win->menu.alias = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Alias...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Alias"); win->menu.block = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Block...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Block"); win->menu.unblock = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Unblock...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Unblock"); win->menu.add = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Add...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Add"); win->menu.remove = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Remove...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Remove"); /* --- */ win->menu.insert_link = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Insert Link...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/InsertLink"); win->menu.insert_image = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Insert Image...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/InsertImage"); /* --- */ win->menu.logging = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Options/Enable Logging")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/OptionsMenu/EnableLogging"); win->menu.sounds = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Options/Enable Sounds")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/OptionsMenu/EnableSounds"); method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); if (method != NULL && !strcmp(method, "none")) { - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds), FALSE); - gtk_widget_set_sensitive(win->menu.sounds, FALSE); + gtk_action_set_sensitive(win->menu.sounds, FALSE); } purple_prefs_connect_callback(win, PIDGIN_PREFS_ROOT "/sound/method", sound_method_pref_changed_cb, win); win->menu.show_formatting_toolbar = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Options/Show Formatting Toolbars")); - win->menu.show_timestamps = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Options/Show Timestamps")); - win->menu.show_icon = NULL; + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/OptionsMenu/ShowFormattingToolbars"); win->menu.tray = pidgin_menu_tray_new(); gtk_menu_shell_append(GTK_MENU_SHELL(win->menu.menubar), @@ -3597,7 +3730,7 @@ time(NULL) > purple_conv_im_get_type_again(im))) { unsigned int timeout; - timeout = serv_send_typing(purple_conversation_get_gc(conv), + timeout = serv_send_typing(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), PURPLE_TYPING); purple_conv_im_set_type_again(im, timeout); @@ -3648,6 +3781,8 @@ static void update_typing_message(PidginConversation *gtkconv, const char *message) { + /* TODO WEBKIT: this is not handled at all */ +#if 0 GtkTextBuffer *buffer; GtkTextMark *stmark, *enmark; @@ -3680,6 +3815,7 @@ gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_create_mark(buffer, "typing-notification-end", &iter, TRUE); } +#endif /* if 0 */ } static void @@ -3736,10 +3872,9 @@ if (win->menu.send_to == NULL) return FALSE; - if (!(b = purple_find_buddy(account, conv->name))) + if (!(b = purple_find_buddy(account, purple_conversation_get_name(conv)))) return FALSE; - gtk_widget_show(win->menu.send_to); menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(win->menu.send_to)); @@ -3896,8 +4031,8 @@ gtk_widget_show(menu); - if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM) { - buds = purple_find_buddies(gtkconv->active_conv->account, gtkconv->active_conv->name); + if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM) { + buds = purple_find_buddies(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv)); if (buds == NULL) { @@ -3921,7 +4056,8 @@ continue; account = purple_buddy_get_account(buddy); - if (purple_account_is_connected(account) || account == gtkconv->active_conv->account) + /* TODO WEBKIT: (I'm not actually sure if this is webkit-related --Mark Doliner) */ + if (purple_account_is_connected(account) /*|| account == purple_conversation_get_account(gtkconv->active_conv)*/) { /* Use the PurplePresence to get unique buddies. */ PurplePresence *presence = purple_buddy_get_presence(buddy); @@ -3980,10 +4116,11 @@ static void deleting_chat_buddy_cb(PurpleConvChatBuddy *cb) { - if (cb->ui_data) { - GtkTreeRowReference *ref = cb->ui_data; + GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb); + + if (ref) { gtk_tree_row_reference_free(ref); - cb->ui_data = NULL; + purple_conv_chat_cb_set_ui_data(cb, NULL); } } @@ -4002,20 +4139,21 @@ GtkTreeIter iter; gboolean is_me = FALSE; gboolean is_buddy; - gchar *tmp, *alias_key, *name, *alias; + const gchar *name, *alias; + gchar *tmp, *alias_key; PurpleConvChatBuddyFlags flags; GdkColor *color = NULL; - alias = cb->alias; - name = cb->name; - flags = cb->flags; + alias = purple_conv_chat_cb_get_alias(cb); + name = purple_conv_chat_cb_get_name(cb); + flags = purple_conv_chat_cb_get_flags(cb); chat = PURPLE_CONV_CHAT(conv); gtkconv = PIDGIN_CONVERSATION(conv); gtkchat = gtkconv->u.chat; - gc = purple_conversation_get_gc(conv); - - if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl))) + gc = purple_conversation_get_connection(conv); + + if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)))) return; tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -4023,20 +4161,23 @@ stock = get_chat_buddy_status_icon(chat, name, flags); - if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name))) + if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(purple_conversation_get_account(conv), old_name != NULL ? old_name : name))) is_me = TRUE; - is_buddy = cb->buddy; + is_buddy = purple_conv_chat_cb_is_buddy(cb); tmp = g_utf8_casefold(alias, -1); alias_key = g_utf8_collate_key(tmp, -1); g_free(tmp); if (is_me) { +#if 0 + /* TODO WEBKIT: No tags in webkit stuff, yet. */ GtkTextTag *tag = gtk_text_tag_table_lookup( - gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->imhtml)->text_buffer), + gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->webview)->text_buffer), "send-name"); g_object_get(tag, "foreground-gdk", &color, NULL); +#endif /* if 0 */ } else { GtkTextTag *tag; if ((tag = get_buddy_tag(conv, name, 0, FALSE))) @@ -4064,13 +4205,13 @@ CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1); - if (cb->ui_data) { - GtkTreeRowReference *ref = cb->ui_data; + if (purple_conv_chat_cb_get_ui_data(cb)) { + GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb); gtk_tree_row_reference_free(ref); } newpath = gtk_tree_model_get_path(tm, &iter); - cb->ui_data = gtk_tree_row_reference_new(tm, newpath); + purple_conv_chat_cb_set_ui_data(cb, gtk_tree_row_reference_new(tm, newpath)); gtk_tree_path_free(newpath); if (is_me && color) @@ -4100,7 +4241,7 @@ */ static void tab_complete_process_item(int *most_matched, const char *entered, gsize entered_bytes, char **partial, char *nick_partial, - GList **matches, char *name) + GList **matches, const char *name) { memcpy(nick_partial, name, entered_bytes); if (purple_utf8_strcasecmp(nick_partial, entered)) @@ -4222,7 +4363,7 @@ /* Users */ for (; l != NULL; l = l->next) { tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, - &matches, ((PurpleConvChatBuddy *)l->data)->name); + &matches, purple_conv_chat_cb_get_name((PurpleConvChatBuddy *)l->data)); } @@ -4320,9 +4461,9 @@ char *new_topic; const char *current_topic; - gc = purple_conversation_get_gc(conv); - - if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl))) + gc = purple_conversation_get_connection(conv); + + if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)))) return; if(prpl_info->set_chat_topic == NULL) @@ -4397,6 +4538,7 @@ { PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); + PurpleAccount *account = purple_conversation_get_account(conv); GtkTreeModel *model; char *normalized_name; GtkTreeIter iter; @@ -4411,23 +4553,23 @@ if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) return; - normalized_name = g_strdup(purple_normalize(conv->account, buddy->name)); + normalized_name = g_strdup(purple_normalize(account, purple_buddy_get_name(buddy))); do { char *name; gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1); - if (!strcmp(normalized_name, purple_normalize(conv->account, name))) { + if (!strcmp(normalized_name, purple_normalize(account, name))) { const char *alias = name; char *tmp; char *alias_key = NULL; PurpleBuddy *buddy2; - if (strcmp(chat->nick, purple_normalize(conv->account, name))) { + if (strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, name))) { /* This user is not me, so look into updating the alias. */ - if ((buddy2 = purple_find_buddy(conv->account, name)) != NULL) { + if ((buddy2 = purple_find_buddy(account, name)) != NULL) { alias = purple_buddy_get_contact_alias(buddy2); } @@ -4462,10 +4604,10 @@ g_return_if_fail(node != NULL); g_return_if_fail(conv != NULL); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); g_return_if_fail(gc != NULL); - g_return_if_fail(gc->prpl != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + g_return_if_fail(purple_connection_get_prpl(gc) != NULL); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME) return; @@ -4485,7 +4627,7 @@ else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) update_chat_alias((PurpleBuddy *)node, conv, gc, prpl_info); else if (PURPLE_BLIST_NODE_IS_CHAT(node) && - purple_conversation_get_account(conv) == ((PurpleChat*)node)->account) + purple_conversation_get_account(conv) == purple_chat_get_account((PurpleChat*)node)) { if (old_alias == NULL || g_utf8_collate(old_alias, purple_conversation_get_title(conv)) == 0) pidgin_conv_update_fields(conv, PIDGIN_CONV_SET_TITLE); @@ -4514,14 +4656,14 @@ if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) return; - normalized_name = g_strdup(purple_normalize(conv->account, buddy->name)); + normalized_name = g_strdup(purple_normalize(purple_conversation_get_account(conv), purple_buddy_get_name(buddy))); do { char *name; gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1); - if (!strcmp(normalized_name, purple_normalize(conv->account, name))) { + if (!strcmp(normalized_name, purple_normalize(purple_conversation_get_account(conv), name))) { gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1); g_free(name); @@ -4600,7 +4742,7 @@ GdkRectangle oneline; int height, diff; int pad_top, pad_inside, pad_bottom; - int total_height = (gtkconv->imhtml->allocation.height + gtkconv->entry->allocation.height); + int total_height = (gtkconv->webview->allocation.height + gtkconv->entry->allocation.height); int max_height = total_height / 2; int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines"); int min_height; @@ -4672,8 +4814,8 @@ setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox) { PurpleConversation *conv = gtkconv->active_conv; - PurpleConnection *gc = purple_conversation_get_gc(conv); - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + PurpleConnection *gc = purple_conversation_get_connection(conv); + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) { GtkWidget *hbox, *label; @@ -4714,7 +4856,7 @@ PurpleAccount *account = purple_conversation_get_account(conv); char *who = NULL; - if (account->gc == NULL) + if (purple_account_get_connection(account) == NULL) return FALSE; if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path)) @@ -4722,8 +4864,8 @@ gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl); - node = (PurpleBlistNode*)(purple_find_buddy(conv->account, who)); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account))); + node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), who)); if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) pidgin_blist_draw_tooltip(node, gtkconv->infopane); @@ -4824,7 +4966,7 @@ gtkchat->list = list; - gtk_box_pack_start(GTK_BOX(lbox), + gtk_box_pack_start(GTK_BOX(lbox), pidgin_make_scrollable(list, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1), TRUE, TRUE, 0); } @@ -4838,15 +4980,15 @@ conv = gtkconv->active_conv; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { - node = (PurpleBlistNode*)(purple_blist_find_chat(conv->account, conv->name)); + node = (PurpleBlistNode*)(purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv))); if (!node) - node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); + node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat"); } else { - node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name)); + node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv))); #if 0 /* Using the transient blist nodes to show the tooltip doesn't quite work yet. */ if (!node) - node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); + node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy"); #endif } @@ -4861,7 +5003,7 @@ { gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); - gtk_imhtml_search_clear(GTK_IMHTML(gtkconv->imhtml)); + webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(gtkconv->webview)); gtk_widget_hide_all(gtkconv->quickfind.container); gtk_widget_grab_focus(gtkconv->entry); @@ -4874,7 +5016,7 @@ switch (event->keyval) { case GDK_Return: case GDK_KP_Enter: - if (gtk_imhtml_search_find(GTK_IMHTML(gtkconv->imhtml), gtk_entry_get_text(GTK_ENTRY(entry)))) { + if (webkit_web_view_search_text(WEBKIT_WEB_VIEW(gtkconv->webview), gtk_entry_get_text(GTK_ENTRY(entry)), FALSE, TRUE, TRUE)) { gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); } else { GdkColor col; @@ -4903,8 +5045,12 @@ close = pidgin_create_small_button(gtk_label_new("×")); gtk_box_pack_start(GTK_BOX(widget), close, FALSE, FALSE, 0); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(close, _("Close Find bar")); +#else gtk_tooltips_set_tip(gtkconv->tooltips, close, _("Close Find bar"), NULL); +#endif label = gtk_label_new(_("Find:")); gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 10); @@ -4924,15 +5070,233 @@ /* }}} */ +static char * +replace_header_tokens(PurpleConversation *conv, const char *text) +{ + PurpleAccount *account = purple_conversation_get_account(conv); + GString *str; + const char *cur = text; + const char *prev = cur; + time_t mtime; + struct tm *tm = NULL; + + if (text == NULL || *text == '\0') + return NULL; + + str = g_string_new(NULL); + while ((cur = strchr(cur, '%'))) { + const char *replace = NULL; + const char *fin = NULL; + + if (g_str_has_prefix(cur, "%chatName%")) { + replace = purple_conversation_get_name(conv); + + } else if (g_str_has_prefix(cur, "%sourceName%")) { + replace = purple_account_get_alias(account); + if (replace == NULL) + replace = purple_account_get_username(account); + + } else if (g_str_has_prefix(cur, "%destinationName%")) { + PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); + if (buddy) { + replace = purple_buddy_get_alias(buddy); + } else { + replace = purple_conversation_get_name(conv); + } + + } else if (g_str_has_prefix(cur, "%incomingIconPath%")) { + PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); + if (icon) + replace = purple_buddy_icon_get_full_path(icon); + + } else if (g_str_has_prefix(cur, "%outgoingIconPath%")) { + replace = purple_account_get_buddy_icon_path(account); + + } else if (g_str_has_prefix(cur, "%timeOpened")) { + const char *tmp = cur + strlen("%timeOpened"); + char *format = NULL; + + if (*tmp == '{') { + const char *end; + tmp++; + end = strstr(tmp, "}%"); + if (!end) /* Invalid string */ + continue; + format = g_strndup(tmp, end - tmp); + fin = end + 1; + } + + if (!tm) { + mtime = time(NULL); + tm = localtime(&mtime); + } + + replace = purple_utf8_strftime(format ? format : "%X", tm); + g_free(format); + + } else if (g_str_has_prefix(cur, "%dateOpened%")) { + if (!tm) { + mtime = time(NULL); + tm = localtime(&mtime); + } + + replace = purple_date_format_short(tm); + + } else { + cur++; + continue; + } + + /* Here we have a replacement to make */ + g_string_append_len(str, prev, cur - prev); + if (replace) + g_string_append(str, replace); + + /* And update the pointers */ + if (fin) { + prev = cur = fin + 1; + } else { + prev = cur = strchr(cur + 1, '%') + 1; + } + } + + /* And wrap it up */ + g_string_append(str, prev); + return g_string_free(str, FALSE); +} + +static char * +replace_template_tokens(PidginConvTheme *theme, const char *header, const char *footer) +{ + GString *str; + const char *text; + char **ms; + char *path; + + text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN); + if (text == NULL) + return NULL; + + ms = g_strsplit(text, "%@", 6); + if (ms[0] == NULL || ms[1] == NULL || ms[2] == NULL || ms[3] == NULL || ms[4] == NULL || ms[5] == NULL) { + g_strfreev(ms); + return NULL; + } + + str = g_string_new(NULL); + + g_string_append(str, ms[0]); + g_string_append(str, "file://"); + path = pidgin_conversation_theme_get_template_path(theme); + g_string_append(str, path); + g_free(path); + + g_string_append(str, ms[1]); + + text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS); + g_string_append(str, text); + + g_string_append(str, ms[2]); + + g_string_append(str, "file://"); + path = pidgin_conversation_theme_get_css_path(theme); + g_string_append(str, path); + g_free(path); + + g_string_append(str, ms[3]); + if (header) + g_string_append(str, header); + g_string_append(str, ms[4]); + if (footer) + g_string_append(str, footer); + g_string_append(str, ms[5]); + + g_strfreev(ms); + + return g_string_free(str, FALSE); +} + +static void +set_theme_webkit_settings(WebKitWebView *webview, PidginConvTheme *theme) +{ + WebKitWebSettings *settings; + const GValue *val; + + g_object_get(G_OBJECT(webview), "settings", &settings, NULL); + + val = pidgin_conversation_theme_lookup(theme, "DefaultFontFamily", TRUE); + if (val && G_VALUE_HOLDS_STRING(val)) + g_object_set(G_OBJECT(settings), "default-font-family", g_value_get_string(val), NULL); + + val = pidgin_conversation_theme_lookup(theme, "DefaultFontSize", TRUE); + if (val && G_VALUE_HOLDS_INT(val)) + g_object_set(G_OBJECT(settings), "default-font-size", GINT_TO_POINTER(g_value_get_int(val)), NULL); + + val = pidgin_conversation_theme_lookup(theme, "DefaultBackgroundIsTransparent", TRUE); + if (val && G_VALUE_HOLDS_BOOLEAN(val)) + /* this does not work :( */ + webkit_web_view_set_transparent(webview, g_value_get_boolean(val)); +} + +static void +conv_variant_changed_cb(GObject *gobject, GParamSpec *pspec, gpointer user_data) +{ + PidginConversation *gtkconv = user_data; + char *path, *js; + + path = pidgin_conversation_theme_get_css_path(PIDGIN_CONV_THEME(gobject)); + js = g_strdup_printf("setStylesheet(\"mainStyle\", \"file://%s\");", path); + g_free(path); + gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), js); + g_free(js); +} + +static void +load_conv_theme(PidginConversation *gtkconv) +{ + char *header, *footer; + char *template; + char *basedir, *baseuri; + + header = replace_header_tokens(gtkconv->active_conv, + pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER)); + footer = replace_header_tokens(gtkconv->active_conv, + pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER)); + template = replace_template_tokens(gtkconv->theme, header, footer); + g_free(header); + g_free(footer); + + if (template == NULL) + return; + + set_theme_webkit_settings(WEBKIT_WEB_VIEW(gtkconv->webview), gtkconv->theme); + + basedir = pidgin_conversation_theme_get_template_path(gtkconv->theme); + baseuri = g_strdup_printf("file://%s", basedir); + webkit_web_view_load_string(WEBKIT_WEB_VIEW(gtkconv->webview), template, + "text/html", "UTF-8", baseuri); + + if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT) + gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), + "document.getElementById('Chat').className = 'groupchat'"); + + g_signal_connect(G_OBJECT(gtkconv->theme), "notify::variant", + G_CALLBACK(conv_variant_changed_cb), gtkconv); + + g_free(basedir); + g_free(baseuri); + g_free(template); +} + static GtkWidget * setup_common_pane(PidginConversation *gtkconv) { - GtkWidget *vbox, *frame, *imhtml_sw, *event_box; + GtkWidget *vbox, *frame, *webview_sw, *event_box; GtkCellRenderer *rend; GtkTreePath *path; PurpleConversation *conv = gtkconv->active_conv; PurpleBuddy *buddy; - gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT); + gboolean chat = (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT); int buddyicon_size = 0; /* Setup the top part of the pane */ @@ -5023,9 +5387,12 @@ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_EMBLEM_COLUMN, NULL); g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL); - /* Setup the gtkimhtml widget */ - frame = pidgin_create_imhtml(FALSE, >kconv->imhtml, NULL, &imhtml_sw); - gtk_widget_set_size_request(gtkconv->imhtml, -1, 0); + /* Setup the webkit widget */ + frame = pidgin_create_webview(FALSE, >kconv->webview, NULL, &webview_sw); + gtk_widget_set_size_request(gtkconv->webview, -1, 0); + + load_conv_theme(gtkconv); + if (chat) { GtkWidget *hpaned; @@ -5043,19 +5410,16 @@ } else { gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); } - gtk_widget_show(frame); - - gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); - gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE); - g_object_set_data(G_OBJECT(gtkconv->imhtml), "gtkconv", gtkconv); - - g_object_set(G_OBJECT(imhtml_sw), "vscrollbar-policy", GTK_POLICY_ALWAYS, NULL); - - g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event", + gtk_widget_show_all(frame); + + gtk_widget_set_name(gtkconv->webview, "pidgin_conv_webview"); + g_object_set_data(G_OBJECT(gtkconv->webview), "gtkconv", gtkconv); + + g_signal_connect_after(G_OBJECT(gtkconv->webview), "button_press_event", G_CALLBACK(entry_stop_rclick_cb), NULL); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", + g_signal_connect(G_OBJECT(gtkconv->webview), "key_press_event", G_CALLBACK(refocus_entry_cb), gtkconv); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", + g_signal_connect(G_OBJECT(gtkconv->webview), "key_release_event", G_CALLBACK(refocus_entry_cb), gtkconv); pidgin_conv_setup_quickfind(gtkconv, vbox); @@ -5071,7 +5435,7 @@ gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), - purple_account_get_protocol_name(conv->account)); + purple_account_get_protocol_name(purple_conversation_get_account(conv))); g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", G_CALLBACK(entry_popup_menu_cb), gtkconv); @@ -5118,7 +5482,7 @@ PurpleConversation *c; PurpleAccount *convaccount = purple_conversation_get_account(conv); PurpleConnection *gc = purple_account_get_connection(convaccount); - PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL; + PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL; if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) { @@ -5238,7 +5602,7 @@ static PidginConversation * pidgin_conv_find_gtkconv(PurpleConversation * conv) { - PurpleBuddy *bud = purple_find_buddy(conv->account, conv->name); + PurpleBuddy *bud = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); PurpleContact *c; PurpleBlistNode *cn, *bn; @@ -5252,9 +5616,9 @@ for (bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) { PurpleBuddy *b = PURPLE_BUDDY(bn); PurpleConversation *conv; - if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, b->account))) { - if (conv->ui_data) - return conv->ui_data; + if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(b), purple_buddy_get_account(b)))) { + if (PIDGIN_CONVERSATION(conv)) + return PIDGIN_CONVERSATION(conv); } } @@ -5296,6 +5660,8 @@ static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv) { +/* TODO WEBKIT */ +#if 0 static PangoFontDescription *font_desc = NULL; static GdkColor *color = NULL; static gboolean enable = TRUE; @@ -5326,6 +5692,7 @@ } g_signal_handlers_disconnect_by_func(G_OBJECT(widget), set_typing_font, gtkconv); +#endif /* if 0 */ } /************************************************************************** @@ -5335,14 +5702,15 @@ private_gtkconv_new(PurpleConversation *conv, gboolean hidden) { PidginConversation *gtkconv; + const char *theme_name; + PurpleTheme *theme = NULL; PurpleConversationType conv_type = purple_conversation_get_type(conv); GtkWidget *pane = NULL; GtkWidget *tab_cont; PurpleBlistNode *convnode; - PurpleValue *value; if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) { - conv->ui_data = gtkconv; + purple_conversation_set_ui_data(conv, gtkconv); if (!g_list_find(gtkconv->convs, conv)) gtkconv->convs = g_list_prepend(gtkconv->convs, conv); pidgin_conv_switch_active_conversation(conv); @@ -5350,15 +5718,24 @@ } gtkconv = g_new0(PidginConversation, 1); - conv->ui_data = gtkconv; + purple_conversation_set_ui_data(conv, gtkconv); gtkconv->active_conv = conv; gtkconv->convs = g_list_prepend(gtkconv->convs, conv); gtkconv->send_history = g_list_append(NULL, NULL); /* Setup some initial variables. */ +#if !GTK_CHECK_VERSION(2,12,0) gtkconv->tooltips = gtk_tooltips_new(); +#endif gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; gtkconv->unseen_count = 0; + theme_name = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/theme"); + if (theme_name && *theme_name) + theme = purple_theme_manager_find_theme(theme_name, "conversation"); + if (!theme) + theme = default_conv_theme; + gtkconv->theme = PIDGIN_CONV_THEME(g_object_ref(theme)); + gtkconv->last_flags = 0; if (conv_type == PURPLE_CONV_TYPE_IM) { gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); @@ -5367,9 +5744,6 @@ } pane = setup_common_pane(gtkconv); - gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml), - gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE); - if (pane == NULL) { if (conv_type == PURPLE_CONV_TYPE_CHAT) g_free(gtkconv->u.chat); @@ -5377,7 +5751,7 @@ g_free(gtkconv->u.im); g_free(gtkconv); - conv->ui_data = NULL; + purple_conversation_set_ui_data(conv, NULL); return; } @@ -5392,7 +5766,7 @@ GTK_DEST_DEFAULT_DROP, te, sizeof(te) / sizeof(GtkTargetEntry), GDK_ACTION_COPY); - gtk_drag_dest_set(gtkconv->imhtml, 0, + gtk_drag_dest_set(gtkconv->webview, 0, te, sizeof(te) / sizeof(GtkTargetEntry), GDK_ACTION_COPY); @@ -5404,12 +5778,12 @@ G_CALLBACK(ignore_middle_click), NULL); g_signal_connect(G_OBJECT(pane), "drag_data_received", G_CALLBACK(conv_dnd_recv), gtkconv); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "drag_data_received", + g_signal_connect(G_OBJECT(gtkconv->webview), "drag_data_received", G_CALLBACK(conv_dnd_recv), gtkconv); g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received", G_CALLBACK(conv_dnd_recv), gtkconv); - g_signal_connect(gtkconv->imhtml, "style-set", G_CALLBACK(set_typing_font), gtkconv); + g_signal_connect(gtkconv->webview, "style-set", G_CALLBACK(set_typing_font), gtkconv); /* Setup the container for the tab. */ gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); @@ -5422,11 +5796,9 @@ if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound")) gtkconv->make_sound = TRUE; - if (convnode != NULL && - (value = g_hash_table_lookup(convnode->settings, "enable-logging")) && - purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN) - { - purple_conversation_set_logging(conv, purple_value_get_boolean(value)); + if (convnode != NULL && purple_blist_node_has_setting(convnode, "enable-logging")) { + gboolean logging = purple_blist_node_get_bool(convnode, "enable-logging"); + purple_conversation_set_logging(conv, logging); } if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar")) @@ -5439,10 +5811,6 @@ else gtk_widget_hide(gtkconv->infopane_hbox); - gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), - purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps")); - gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), - purple_account_get_protocol_name(conv->account)); g_signal_connect_swapped(G_OBJECT(pane), "focus", G_CALLBACK(gtk_widget_grab_focus), @@ -5455,10 +5823,10 @@ if (nick_colors == NULL) { nbr_nick_colors = NUM_NICK_COLORS; - nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->imhtml)->base[GTK_STATE_NORMAL]); - } - - if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) + nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]); + } + + if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) pidgin_themes_smiley_themeize_custom(gtkconv->entry); } @@ -5559,7 +5927,9 @@ g_free(gtkconv->u.chat); } +#if !GTK_CHECK_VERSION(2,12,0) gtk_object_sink(GTK_OBJECT(gtkconv->tooltips)); +#endif gtkconv->send_history = g_list_first(gtkconv->send_history); g_list_foreach(gtkconv->send_history, (GFunc)g_free, NULL); @@ -5569,6 +5939,10 @@ g_source_remove(gtkconv->attach.timer); } + g_object_disconnect(G_OBJECT(gtkconv->theme), "any_signal::notify", + conv_variant_changed_cb, gtkconv, NULL); + g_object_unref(gtkconv->theme); + g_free(gtkconv); } @@ -5596,6 +5970,7 @@ purple_conversation_write(conv, who, message, flags, mtime); } +#if 0 static const char * get_text_tag_color(GtkTextTag *tag) { @@ -5659,7 +6034,7 @@ &start, &end)) { GtkWidget *menu = NULL; PurpleConnection *gc = - purple_conversation_get_gc(conv); + purple_conversation_get_connection(conv); menu = create_chat_menu(conv, buddyname, gc); @@ -5676,10 +6051,13 @@ return FALSE; } +#endif static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, gboolean create) { +/* TODO WEBKIT */ +#if 0 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); GtkTextTag *buddytag; gchar *str; @@ -5713,8 +6091,11 @@ g_free(str); return buddytag; -} - +#endif /* if 0 */ + return NULL; +} + +#if 0 static void pidgin_conv_calculate_newday(PidginConversation *gtkconv, time_t mtime) { struct tm *tm = localtime(&mtime); @@ -5760,6 +6141,142 @@ *str = ret; #endif } +#endif + +static char * +replace_message_tokens( + const char *text, + PurpleConversation *conv, + const char *name, + const char *alias, + const char *message, + PurpleMessageFlags flags, + time_t mtime) +{ + GString *str; + const char *cur = text; + const char *prev = cur; + struct tm *tm = NULL; + + if (text == NULL || *text == '\0') + return NULL; + + str = g_string_new(NULL); + while ((cur = strchr(cur, '%'))) { + const char *replace = NULL; + const char *fin = NULL; + gpointer freeval = NULL; + + if (g_str_has_prefix(cur, "%message%")) { + replace = message; + + } else if (g_str_has_prefix(cur, "%messageClasses%")) { + GString *classes = g_string_new(NULL); +#define ADD_CLASS(f, class) \ + if (flags & f) \ + g_string_append(classes, class); + ADD_CLASS(PURPLE_MESSAGE_SEND, "outgoing "); + ADD_CLASS(PURPLE_MESSAGE_RECV, "incoming "); + ADD_CLASS(PURPLE_MESSAGE_SYSTEM, "event "); + ADD_CLASS(PURPLE_MESSAGE_AUTO_RESP, "autoreply "); + ADD_CLASS(PURPLE_MESSAGE_DELAYED, "history "); + ADD_CLASS(PURPLE_MESSAGE_NICK, "mention "); +#undef ADD_CLASS + + replace = freeval = g_string_free(classes, FALSE); + + } else if (g_str_has_prefix(cur, "%time")) { + const char *tmp = cur + strlen("%time"); + char *format = NULL; + + if (*tmp == '{') { + char *end; + tmp++; + end = strstr(tmp, "}%"); + if (!end) /* Invalid string */ + continue; + format = g_strndup(tmp, end - tmp); + fin = end + 1; + } + + if (!tm) + tm = localtime(&mtime); + + replace = purple_utf8_strftime(format ? format : "%X", tm); + g_free(format); + + } else if (g_str_has_prefix(cur, "%shortTime%")) { + if (!tm) + tm = localtime(&mtime); + + replace = purple_utf8_strftime("%H:%M", tm); + + } else if (g_str_has_prefix(cur, "%userIconPath%")) { + if (flags & PURPLE_MESSAGE_SEND) { + if (purple_account_get_bool(purple_conversation_get_account(conv), "use-global-buddyicon", TRUE)) { + replace = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon"); + } else { + PurpleStoredImage *img = purple_buddy_icons_find_account_icon(purple_conversation_get_account(conv)); + replace = purple_imgstore_get_filename(img); + } + if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) { + replace = freeval = g_build_filename("Outgoing", "buddy_icon.png", NULL); + } + } else if (flags & PURPLE_MESSAGE_RECV) { + PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); + if (icon) + replace = purple_buddy_icon_get_full_path(icon); + if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) { + replace = freeval = g_build_filename("Incoming", "buddy_icon.png", NULL); + } + } + + } else if (g_str_has_prefix(cur, "%senderScreenName%")) { + replace = name; + + } else if (g_str_has_prefix(cur, "%sender%")) { + replace = alias; + + } else if (g_str_has_prefix(cur, "%service%")) { + replace = purple_account_get_protocol_name(purple_conversation_get_account(conv)); + + } else if (g_str_has_prefix(cur, "%messageDirection%")) { + replace = purple_markup_is_rtl(message) ? "rtl" : "ltr"; + + } else if (g_str_has_prefix(cur, "%status%")) { + GString *classes = g_string_new(NULL); + + if (flags & PURPLE_MESSAGE_ERROR) + g_string_append(classes, "error "); + + replace = freeval = g_string_free(classes, FALSE); + + } else { + cur++; + continue; + } + + /* Here we have a replacement to make */ + g_string_append_len(str, prev, cur - prev); + if (replace) + g_string_append(str, replace); + g_free(freeval); + replace = freeval = NULL; + + /* And update the pointers */ + if (fin) { + prev = cur = fin + 1; + } else { + prev = cur = strchr(cur + 1, '%') + 1; + } + + } + + /* And wrap it up */ + g_string_append(str, prev); + + return g_string_free(str, FALSE); +} static void pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias, @@ -5769,23 +6286,31 @@ PidginConversation *gtkconv; PurpleConnection *gc; PurpleAccount *account; +#if 0 int gtk_font_options = 0; int gtk_font_options_all = 0; - int max_scrollback_lines; - int line_count; char buf2[BUF_LONG]; gboolean show_date; char *mdate; char *str; char *with_font_tag; char *sml_attrib = NULL; +#endif size_t length; PurpleConversationType type; char *displaying; gboolean plugin_return; - char *bracket; - int tag_count = 0; +#if 0 gboolean is_rtl_message = FALSE; +#endif + + const char *message_html; + char *msg; + char *escape; + char *script; + char *smileyed; + PurpleMessageFlags old_flags; + const char *func = "appendMessage"; g_return_if_fail(conv != NULL); gtkconv = PIDGIN_CONVERSATION(conv); @@ -5842,56 +6367,56 @@ } length = strlen(displaying) + 1; - /* Awful hack to work around GtkIMHtml's inefficient rendering of messages with lots of formatting changes. - * If a message has over 100 '<' characters, strip formatting before appending it. Hopefully nobody actually - * needs that much formatting, anyway. - */ - for (bracket = strchr(displaying, '<'); bracket && *(bracket + 1); bracket = strchr(bracket + 1, '<')) - tag_count++; - - if (tag_count > 100) { - char *tmp = displaying; - displaying = purple_markup_strip_html(tmp); - g_free(tmp); - } - - line_count = gtk_text_buffer_get_line_count( - gtk_text_view_get_buffer(GTK_TEXT_VIEW( - gtkconv->imhtml))); - - max_scrollback_lines = purple_prefs_get_int( - PIDGIN_PREFS_ROOT "/conversations/scrollback_lines"); - /* If we're sitting at more than 100 lines more than the - max scrollback, trim down to max scrollback */ - if (max_scrollback_lines > 0 - && line_count > (max_scrollback_lines + 100)) { - GtkTextBuffer *text_buffer = gtk_text_view_get_buffer( - GTK_TEXT_VIEW(gtkconv->imhtml)); - GtkTextIter start, end; - - gtk_text_buffer_get_start_iter(text_buffer, &start); - gtk_text_buffer_get_iter_at_line(text_buffer, &end, - (line_count - max_scrollback_lines)); - gtk_imhtml_delete(GTK_IMHTML(gtkconv->imhtml), &start, &end); - } - - if (type == PURPLE_CONV_TYPE_CHAT) - { - /* Create anchor for user */ - GtkTextIter iter; - char *tmp = g_strconcat("user:", name, NULL); - - gtk_text_buffer_get_end_iter(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)), &iter); - gtk_text_buffer_create_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)), - tmp, &iter, TRUE); - g_free(tmp); - } - - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling")) - gtk_font_options_all |= GTK_IMHTML_USE_SMOOTHSCROLLING; - - if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)))) - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", gtk_font_options_all | GTK_IMHTML_NO_SCROLL); + old_flags = gtkconv->last_flags; + if ((flags & PURPLE_MESSAGE_SEND) && (old_flags & PURPLE_MESSAGE_SEND)) { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT); + func = "appendNextMessage"; + + } else if (flags & PURPLE_MESSAGE_SEND) { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT); + + } else if ((flags & PURPLE_MESSAGE_RECV) && (old_flags & PURPLE_MESSAGE_RECV)) { + GList *history = purple_conversation_get_message_history(conv); + PurpleConvMessage *last_msg = (PurpleConvMessage *)history->data; + + /* If the senders are the same, use appendNextMessage */ + if (purple_strequal(purple_conversation_message_get_sender(last_msg), name)) { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT); + func = "appendNextMessage"; + } else { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT); + } + } else if (flags & PURPLE_MESSAGE_RECV) { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT); + + } else { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS); + } + gtkconv->last_flags = flags; + + smileyed = smiley_parse_markup(displaying, purple_account_get_protocol_id(account)); + msg = replace_message_tokens(message_html, conv, name, alias, smileyed, flags, mtime); + escape = gtk_webview_quote_js_string(msg ? msg : ""); + script = g_strdup_printf("%s(%s)", func, escape); + + purple_debug_info("webkit", "JS: %s\n", script); + gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), script); + + g_free(script); + g_free(smileyed); + g_free(msg); + g_free(escape); + +#if 0 + /* if the buffer is not empty add a <br> */ + if (!gtk_webview_is_empty(GTK_WEBVIEW(gtkconv->webview))) + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<br />"); /* First message in a conversation. */ if (gtkconv->newday == 0) @@ -5934,40 +6459,40 @@ gtk_font_options |= GTK_IMHTML_NO_COLOURS | GTK_IMHTML_NO_FONTS | GTK_IMHTML_NO_SIZES | GTK_IMHTML_NO_FORMATTING; /* this is gonna crash one day, I can feel it. */ - if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(conv->account)))->options & + if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(purple_conversation_get_account(conv))))->options & OPT_PROTO_USE_POINTSIZE) { gtk_font_options |= GTK_IMHTML_USE_POINTSIZE; } - if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) + if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) { /* We want to see our own smileys. Need to revert it after send*/ - pidgin_themes_smiley_themeize_custom(gtkconv->imhtml); + pidgin_themes_smiley_themeize_custom(gtkconv->webview); } /* TODO: These colors should not be hardcoded so log.c can use them */ if (flags & PURPLE_MESSAGE_RAW) { - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, gtk_font_options_all); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), message); } else if (flags & PURPLE_MESSAGE_SYSTEM) { g_snprintf(buf2, sizeof(buf2), - "<FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT>", + "<font %s><font size=\"2\"><span class='timestamp'>%s</span></font><b>%s</b></font>", sml_attrib ? sml_attrib : "", mdate, displaying); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2); } else if (flags & PURPLE_MESSAGE_ERROR) { g_snprintf(buf2, sizeof(buf2), - "<FONT COLOR=\"#ff0000\"><FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT></FONT>", + "<font color=\"#ff0000\"><font %s><font size=\"2\"><span class='timestamp'>%s</span> </font><b>%s</b></font></font>", sml_attrib ? sml_attrib : "", mdate, displaying); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2); } else if (flags & PURPLE_MESSAGE_NO_LOG) { g_snprintf(buf2, BUF_LONG, - "<B><FONT %s COLOR=\"#777777\">%s</FONT></B>", + "<b><font %s color=\"#777777\">%s</font></b>", sml_attrib ? sml_attrib : "", displaying); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2); } else { char *new_message = g_memdup(displaying, length); char *alias_escaped = (alias ? g_markup_escape_text(alias, strlen(alias)) : g_strdup("")); @@ -5977,11 +6502,6 @@ int tag_end_offset = 0; const char *tagname = NULL; - GtkTextIter start, end; - GtkTextMark *mark; - GtkTextTag *tag; - GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer; - /* Enforce direction on alias */ if (is_rtl_message) str_embed_direction_chars(&alias_escaped); @@ -6042,55 +6562,41 @@ g_free(alias_escaped); + /* TODO WEBKIT */ +#if 0 if (tagname) tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname); else tag = get_buddy_tag(conv, name, flags, TRUE); if (GTK_IMHTML(gtkconv->imhtml)->show_comments) { + { /* The color for the timestamp has to be set in the font-tags, unfortunately. * Applying the nick-tag to timestamps would work, but that can make it * bold. I thought applying the "comment" tag again, which has "weight" set * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So * this will have to do. I don't terribly like it. -- sadrul */ - const char *color = get_text_tag_color(tag); + /* const char *color = get_text_tag_color(tag); */ g_snprintf(buf2, BUF_LONG, "<FONT %s%s%s SIZE=\"2\"><!--%s --></FONT>", color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); - } - - gtk_text_buffer_get_end_iter(buffer, &end); - mark = gtk_text_buffer_create_mark(buffer, NULL, &end, TRUE); - - g_snprintf(buf2, BUF_LONG, "<FONT %s>%s</FONT> ", sml_attrib ? sml_attrib : "", str); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); - - gtk_text_buffer_get_end_iter(buffer, &end); - gtk_text_buffer_get_iter_at_mark(buffer, &start, mark); - gtk_text_buffer_apply_tag(buffer, tag, &start, &end); - gtk_text_buffer_delete_mark(buffer, mark); + gtk_webview_append_html (GTK_WEBVIEW(gtkconv->webview), buf2); + } +#endif /* if 0 */ + g_snprintf(buf2, BUF_LONG, "<font %s>%s</font> ", sml_attrib ? sml_attrib : "", str); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2); g_free(str); - if(gc){ + if (gc) { char *pre = g_strdup_printf("<font %s>", sml_attrib ? sml_attrib : ""); char *post = "</font>"; - int pre_len = strlen(pre); - int post_len = strlen(post); - - with_font_tag = g_malloc(length + pre_len + post_len + 1); - - strcpy(with_font_tag, pre); - memcpy(with_font_tag + pre_len, new_message, length); - strcpy(with_font_tag + pre_len + length, post); - - length += pre_len + post_len; + with_font_tag = g_strdup_printf("%s%s%s", pre, new_message, post); g_free(pre); } else with_font_tag = g_memdup(new_message, length); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), - with_font_tag, gtk_font_options | gtk_font_options_all); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), + with_font_tag); g_free(with_font_tag); g_free(new_message); @@ -6099,6 +6605,8 @@ g_free(mdate); g_free(sml_attrib); +#endif + /* Tab highlighting stuff */ if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv)) { @@ -6117,11 +6625,13 @@ gtkconv_set_unseen(gtkconv, unseen); } - if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) +#if 0 + if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) { /* Restore the smiley-data */ - pidgin_themes_smiley_themeize(gtkconv->imhtml); - } + pidgin_themes_smiley_themeize(gtkconv->webview); + } +#endif purple_signal_emit(pidgin_conversations_get_handle(), (type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"), @@ -6138,7 +6648,7 @@ g_return_val_if_fail(cb != NULL, FALSE); - ref = cb->ui_data; + ref = purple_conv_chat_cb_get_ui_data(cb); if (!ref) return FALSE; @@ -6229,11 +6739,11 @@ return; if (get_iter_from_chatbuddy(old_cbuddy, &iter)) { - GtkTreeRowReference *ref = old_cbuddy->ui_data; + GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(old_cbuddy); gtk_list_store_remove(GTK_LIST_STORE(model), &iter); gtk_tree_row_reference_free(ref); - old_cbuddy->ui_data = NULL; + purple_conv_chat_cb_set_ui_data(old_cbuddy, NULL); } g_return_if_fail(new_alias != NULL); @@ -6322,10 +6832,10 @@ return; if (get_iter_from_chatbuddy(cbuddy, &iter)) { - GtkTreeRowReference *ref = cbuddy->ui_data; + GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cbuddy); gtk_list_store_remove(GTK_LIST_STORE(model), &iter); gtk_tree_row_reference_free(ref); - cbuddy->ui_data = NULL; + purple_conv_chat_cb_set_ui_data(cbuddy, NULL); } if (cbuddy) @@ -6372,6 +6882,13 @@ } static gboolean +add_custom_smiley_for_webview(GtkWebView *webview, const char *sml, const char *smile) +{ + /* TODO WEBKIT: Smileys need to be added to webkit stuff */ + return TRUE; +} + +static gboolean pidgin_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, gboolean remote) { PidginConversation *gtkconv; @@ -6388,7 +6905,7 @@ /* If possible add this smiley to the current theme. * The addition is only temporary: custom smilies aren't saved to disk. */ - conv_sml = purple_account_get_protocol_name(conv->account); + conv_sml = purple_account_get_protocol_name(purple_conversation_get_account(conv)); gtkconv = PIDGIN_CONVERSATION(conv); for (list = (struct smiley_list *)current_smiley_theme->list; list; list = list->next) { @@ -6398,7 +6915,7 @@ } } - if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->imhtml), sml, smile)) + if (!add_custom_smiley_for_webview(GTK_WEBVIEW(gtkconv->webview), sml, smile)) return FALSE; if (!remote) /* If it's a local custom smiley, then add it for the entry */ @@ -6412,12 +6929,14 @@ pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile, const guchar *data, gsize size) { +/* TODO WEBKIT */ +#if 0 PidginConversation *gtkconv; GtkIMHtmlSmiley *smiley; const char *sml; GError *error = NULL; - sml = purple_account_get_protocol_name(conv->account); + sml = purple_account_get_protocol_name(purple_conversation_get_account(conv)); gtkconv = PIDGIN_CONVERSATION(conv); smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); @@ -6433,7 +6952,7 @@ if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) { purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() " - "failed with size=%zu: %s\n", size, + "failed with size=%" G_GSIZE_FORMAT ": %s\n", size, error ? error->message : "(no error message)"); if (error) g_error_free(error); @@ -6446,11 +6965,14 @@ g_object_unref(G_OBJECT(smiley->loader)); smiley->loader = gdk_pixbuf_loader_new(); } +#endif /* if 0 */ } static void pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile) { +/* TODO WEBKIT */ +#if 0 PidginConversation *gtkconv; GtkIMHtmlSmiley *smiley; const char *sml; @@ -6459,7 +6981,7 @@ g_return_if_fail(conv != NULL); g_return_if_fail(smile != NULL); - sml = purple_account_get_protocol_name(conv->account); + sml = purple_account_get_protocol_name(purple_conversation_get_account(conv)); gtkconv = PIDGIN_CONVERSATION(conv); smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); @@ -6487,6 +7009,7 @@ g_object_unref(G_OBJECT(smiley->loader)); smiley->loader = gdk_pixbuf_loader_new(); } +#endif /* if 0 */ } static void @@ -6514,11 +7037,11 @@ PurpleAccount *account; win = pidgin_conv_get_window(gtkconv); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); account = purple_conversation_get_account(conv); if (gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (win->menu.send_to != NULL) update_send_to_selection(win); @@ -6535,57 +7058,57 @@ /* Show stuff that applies to IMs, hide stuff that applies to chats */ /* Deal with menu items */ - gtk_widget_show(win->menu.view_log); - gtk_widget_show(win->menu.send_file); - gtk_widget_show(g_object_get_data(G_OBJECT(win->window), "get_attention")); - gtk_widget_show(win->menu.add_pounce); - gtk_widget_show(win->menu.get_info); - gtk_widget_hide(win->menu.invite); - gtk_widget_show(win->menu.alias); + gtk_action_set_visible(win->menu.view_log, TRUE); + gtk_action_set_visible(win->menu.send_file, TRUE); + gtk_action_set_visible(win->menu.get_attention, TRUE); + gtk_action_set_visible(win->menu.add_pounce, TRUE); + gtk_action_set_visible(win->menu.get_info, TRUE); + gtk_action_set_visible(win->menu.invite, FALSE); + gtk_action_set_visible(win->menu.alias, TRUE); if (purple_privacy_check(account, purple_conversation_get_name(conv))) { - gtk_widget_hide(win->menu.unblock); - gtk_widget_show(win->menu.block); + gtk_action_set_visible(win->menu.unblock, FALSE); + gtk_action_set_visible(win->menu.block, TRUE); } else { - gtk_widget_hide(win->menu.block); - gtk_widget_show(win->menu.unblock); + gtk_action_set_visible(win->menu.block, FALSE); + gtk_action_set_visible(win->menu.unblock, TRUE); } if ((account == NULL) || purple_find_buddy(account, purple_conversation_get_name(conv)) == NULL) { - gtk_widget_show(win->menu.add); - gtk_widget_hide(win->menu.remove); + gtk_action_set_visible(win->menu.add, TRUE); + gtk_action_set_visible(win->menu.remove, FALSE); } else { - gtk_widget_show(win->menu.remove); - gtk_widget_hide(win->menu.add); - } - - gtk_widget_show(win->menu.insert_link); - gtk_widget_show(win->menu.insert_image); + gtk_action_set_visible(win->menu.remove, TRUE); + gtk_action_set_visible(win->menu.add, FALSE); + } + + gtk_action_set_visible(win->menu.insert_link, TRUE); + gtk_action_set_visible(win->menu.insert_image, TRUE); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { /* Show stuff that applies to Chats, hide stuff that applies to IMs */ /* Deal with menu items */ - gtk_widget_show(win->menu.view_log); - gtk_widget_hide(win->menu.send_file); - gtk_widget_hide(g_object_get_data(G_OBJECT(win->window), "get_attention")); - gtk_widget_hide(win->menu.add_pounce); - gtk_widget_hide(win->menu.get_info); - gtk_widget_show(win->menu.invite); - gtk_widget_show(win->menu.alias); - gtk_widget_hide(win->menu.block); - gtk_widget_hide(win->menu.unblock); + gtk_action_set_visible(win->menu.view_log, TRUE); + gtk_action_set_visible(win->menu.send_file, FALSE); + gtk_action_set_visible(win->menu.get_attention, FALSE); + gtk_action_set_visible(win->menu.add_pounce, FALSE); + gtk_action_set_visible(win->menu.get_info, FALSE); + gtk_action_set_visible(win->menu.invite, TRUE); + gtk_action_set_visible(win->menu.alias, TRUE); + gtk_action_set_visible(win->menu.block, FALSE); + gtk_action_set_visible(win->menu.unblock, FALSE); if ((account == NULL) || purple_blist_find_chat(account, purple_conversation_get_name(conv)) == NULL) { /* If the chat is NOT in the buddy list */ - gtk_widget_show(win->menu.add); - gtk_widget_hide(win->menu.remove); + gtk_action_set_visible(win->menu.add, TRUE); + gtk_action_set_visible(win->menu.remove, FALSE); } else { /* If the chat IS in the buddy list */ - gtk_widget_hide(win->menu.add); - gtk_widget_show(win->menu.remove); - } - - gtk_widget_show(win->menu.insert_link); - gtk_widget_show(win->menu.insert_image); + gtk_action_set_visible(win->menu.add, FALSE); + gtk_action_set_visible(win->menu.remove, TRUE); + } + + gtk_action_set_visible(win->menu.insert_link, TRUE); + gtk_action_set_visible(win->menu.insert_image, TRUE); } /* @@ -6596,31 +7119,35 @@ ((purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) || !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) )) { + PurpleConnectionFlags features = purple_conversation_get_features(conv); /* Account is online */ /* Deal with the toolbar */ - if (conv->features & PURPLE_CONNECTION_HTML) + if (features & PURPLE_CONNECTION_HTML) { buttons = GTK_IMHTML_ALL; /* Everything on */ - if (conv->features & PURPLE_CONNECTION_NO_BGCOLOR) + if (features & PURPLE_CONNECTION_NO_BGCOLOR) buttons &= ~GTK_IMHTML_BACKCOLOR; - if (conv->features & PURPLE_CONNECTION_NO_FONTSIZE) + if (features & PURPLE_CONNECTION_NO_FONTSIZE) { buttons &= ~GTK_IMHTML_GROW; buttons &= ~GTK_IMHTML_SHRINK; } - if (conv->features & PURPLE_CONNECTION_NO_URLDESC) + if (features & PURPLE_CONNECTION_NO_URLDESC) buttons &= ~GTK_IMHTML_LINKDESC; } else { buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE; } - if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)) - conv->features |= PURPLE_CONNECTION_NO_IMAGES; - - if(conv->features & PURPLE_CONNECTION_NO_IMAGES) + if (!(prpl_info->options & OPT_PROTO_IM_IMAGE) + && !(features & PURPLE_CONNECTION_NO_IMAGES)) { + features |= PURPLE_CONNECTION_NO_IMAGES; + purple_conversation_set_features(conv, features); + } + + if (features & PURPLE_CONNECTION_NO_IMAGES) buttons &= ~GTK_IMHTML_IMAGE; - if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) + if (features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) buttons |= GTK_IMHTML_CUSTOM_SMILEY; else buttons &= ~GTK_IMHTML_CUSTOM_SMILEY; @@ -6630,30 +7157,30 @@ gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(gtkconv->toolbar), purple_account_get_protocol_id(account)); /* Deal with menu items */ - gtk_widget_set_sensitive(win->menu.view_log, TRUE); - gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); - gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); - gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); - gtk_widget_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML)); - gtk_widget_set_sensitive(win->menu.insert_image, !(conv->features & PURPLE_CONNECTION_NO_IMAGES)); + gtk_action_set_sensitive(win->menu.view_log, TRUE); + gtk_action_set_sensitive(win->menu.add_pounce, TRUE); + gtk_action_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); + gtk_action_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); + gtk_action_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_HTML)); + gtk_action_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_NO_IMAGES)); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - gtk_widget_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL) || (prpl_info->add_buddy_with_invite != NULL)); - gtk_widget_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); - gtk_widget_set_sensitive(win->menu.send_file, + gtk_action_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL)); + gtk_action_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); + gtk_action_set_sensitive(win->menu.send_file, (prpl_info->send_file != NULL && (!prpl_info->can_receive_file || prpl_info->can_receive_file(gc, purple_conversation_get_name(conv))))); - gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(win->window), "get_attention"), (prpl_info->send_attention != NULL)); - gtk_widget_set_sensitive(win->menu.alias, + gtk_action_set_sensitive(win->menu.get_attention, (prpl_info->send_attention != NULL)); + gtk_action_set_sensitive(win->menu.alias, (account != NULL) && (purple_find_buddy(account, purple_conversation_get_name(conv)) != NULL)); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { - gtk_widget_set_sensitive(win->menu.add, (prpl_info->join_chat != NULL)); - gtk_widget_set_sensitive(win->menu.remove, (prpl_info->join_chat != NULL)); - gtk_widget_set_sensitive(win->menu.alias, + gtk_action_set_sensitive(win->menu.add, (prpl_info->join_chat != NULL)); + gtk_action_set_sensitive(win->menu.remove, (prpl_info->join_chat != NULL)); + gtk_action_set_sensitive(win->menu.alias, (account != NULL) && (purple_blist_find_chat(account, purple_conversation_get_name(conv)) != NULL)); } @@ -6663,18 +7190,17 @@ /* Or it's a chat that we've left. */ /* Then deal with menu items */ - gtk_widget_set_sensitive(win->menu.view_log, TRUE); - gtk_widget_set_sensitive(win->menu.send_file, FALSE); - gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(win->window), - "get_attention"), FALSE); - gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); - gtk_widget_set_sensitive(win->menu.get_info, FALSE); - gtk_widget_set_sensitive(win->menu.invite, FALSE); - gtk_widget_set_sensitive(win->menu.alias, FALSE); - gtk_widget_set_sensitive(win->menu.add, FALSE); - gtk_widget_set_sensitive(win->menu.remove, FALSE); - gtk_widget_set_sensitive(win->menu.insert_link, TRUE); - gtk_widget_set_sensitive(win->menu.insert_image, FALSE); + gtk_action_set_sensitive(win->menu.view_log, TRUE); + gtk_action_set_sensitive(win->menu.send_file, FALSE); + gtk_action_set_sensitive(win->menu.get_attention, FALSE); + gtk_action_set_sensitive(win->menu.add_pounce, TRUE); + gtk_action_set_sensitive(win->menu.get_info, FALSE); + gtk_action_set_sensitive(win->menu.invite, FALSE); + gtk_action_set_sensitive(win->menu.alias, FALSE); + gtk_action_set_sensitive(win->menu.add, FALSE); + gtk_action_set_sensitive(win->menu.remove, FALSE); + gtk_action_set_sensitive(win->menu.insert_link, TRUE); + gtk_action_set_sensitive(win->menu.insert_image, FALSE); } /* @@ -6686,7 +7212,7 @@ if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && (gtkconv->u.im->anim)) { - PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); + PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); window_icon = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); @@ -6734,6 +7260,7 @@ { gray_stuff_out(PIDGIN_CONVERSATION(conv)); generate_send_to_items(win); + regenerate_plugins_items(win); } if (fields & PIDGIN_CONV_TAB_ICON) @@ -6754,13 +7281,20 @@ topic = purple_conv_chat_get_topic(chat); gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), topic ? topic : ""); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(gtkchat->topic_text, + topic ? topic : ""); +#else gtk_tooltips_set_tip(gtkconv->tooltips, gtkchat->topic_text, topic ? topic : "", NULL); - } - } - +#endif + } + } + +#if 0 if (fields & PIDGIN_CONV_SMILEY_THEME) - pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->imhtml); + pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->webview); +#endif if ((fields & PIDGIN_CONV_COLORIZE_TITLE) || (fields & PIDGIN_CONV_SET_TITLE) || @@ -6787,7 +7321,7 @@ title = g_strdup(purple_conversation_get_title(conv)); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - buddy = purple_find_buddy(account, conv->name); + buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); if (buddy) { markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE); } else { @@ -6815,7 +7349,7 @@ if (title != markup) g_free(markup); - if (!GTK_WIDGET_REALIZED(gtkconv->tab_label)) + if (!gtk_widget_get_realized(gtkconv->tab_label)) gtk_widget_realize(gtkconv->tab_label); accessibility_obj = gtk_widget_get_accessible(gtkconv->tab_cont); @@ -6832,7 +7366,7 @@ style = "tab-label-attention"; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) { atk_object_set_description(accessibility_obj, _("Unread Messages")); - if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_CHAT) + if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT) style = "tab-label-unreadchat"; else style = "tab-label-attention"; @@ -7044,7 +7578,7 @@ if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons")) return; - if (purple_conversation_get_gc(conv) == NULL) + if (purple_conversation_get_connection(conv) == NULL) return; buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); @@ -7209,7 +7743,7 @@ tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page); /* Make sure the tab is not hidden beyond an arrow */ - if (!GTK_WIDGET_DRAWABLE(tab) && gtk_notebook_get_show_tabs(notebook)) + if (!gtk_widget_is_drawable(tab) && gtk_notebook_get_show_tabs(notebook)) continue; if (horiz) { @@ -7316,34 +7850,6 @@ } static void -show_timestamps_pref_cb(const char *name, PurplePrefType type, - gconstpointer value, gpointer data) -{ - GList *l; - PurpleConversation *conv; - PidginConversation *gtkconv; - PidginWindow *win; - - for (l = purple_get_conversations(); l != NULL; l = l->next) - { - conv = (PurpleConversation *)l->data; - - if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv)) - continue; - - gtkconv = PIDGIN_CONVERSATION(conv); - win = gtkconv->win; - - gtk_check_menu_item_set_active( - GTK_CHECK_MENU_ITEM(win->menu.show_timestamps), - (gboolean)GPOINTER_TO_INT(value)); - - gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), - (gboolean)GPOINTER_TO_INT(value)); - } -} - -static void show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) { @@ -7362,8 +7868,8 @@ gtkconv = PIDGIN_CONVERSATION(conv); win = gtkconv->win; - gtk_check_menu_item_set_active( - GTK_CHECK_MENU_ITEM(win->menu.show_formatting_toolbar), + gtk_toggle_action_set_active( + GTK_TOGGLE_ACTION(win->menu.show_formatting_toolbar), (gboolean)GPOINTER_TO_INT(value)); if ((gboolean)GPOINTER_TO_INT(value)) @@ -7507,7 +8013,7 @@ conv = gtkconv->active_conv; - if (conv->type == PURPLE_CONV_TYPE_CHAT || + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT || gtkconv->unseen_count == 0 || (when_away && !purple_status_is_available( purple_account_get_active_status( @@ -7547,7 +8053,7 @@ { PurpleBuddy *buddy = (PurpleBuddy*)node; PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); if (conv) return PIDGIN_CONVERSATION(conv); } @@ -7572,16 +8078,18 @@ PIDGIN_CONV_MENU | PIDGIN_CONV_COLORIZE_TITLE); if (PURPLE_CONNECTION_IS_CONNECTED(gc) && - conv->type == PURPLE_CONV_TYPE_CHAT && - conv->account == gc->account && + purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && + purple_conversation_get_account(conv) == purple_connection_get_account(gc) && purple_conversation_get_data(conv, "want-to-rejoin")) { GHashTable *comps = NULL; - PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); + PurpleChat *chat = purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (chat == NULL) { - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) - comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, conv->name); + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + + if (prpl_info->chat_info_defaults != NULL) + comps = prpl_info->chat_info_defaults(gc, purple_conversation_get_name(conv)); } else { - comps = chat->components; + comps = purple_chat_get_components(chat); } serv_join_chat(gc, comps); if (chat == NULL && comps != NULL) @@ -7648,7 +8156,7 @@ { PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); if (conv) pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON); } @@ -7658,7 +8166,7 @@ { PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); if (conv) pidgin_conv_update_fields(conv, PIDGIN_CONV_BUDDY_ICON); } @@ -7723,7 +8231,7 @@ message_compare(gconstpointer p1, gconstpointer p2) { const PurpleConvMessage *m1 = p1, *m2 = p2; - return (m1->when > m2->when); + return (purple_conversation_message_get_timestamp(m1) > purple_conversation_message_get_timestamp(m2)); } /* Adds some message history to the gtkconv. This happens in a idle-callback. */ @@ -7731,19 +8239,27 @@ add_message_history_to_gtkconv(gpointer data) { PidginConversation *gtkconv = data; + GtkWebView *webview = GTK_WEBVIEW(gtkconv->webview); int count = 0; int timer = gtkconv->attach.timer; time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time")); - gboolean im = (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM); + gboolean im = (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM); gtkconv->attach.timer = 0; while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */ PurpleConvMessage *msg = gtkconv->attach.current->data; - if (!im && when && when < msg->when) { - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0); + if (!im && when && when < purple_conversation_message_get_timestamp(msg)) { + gtk_webview_append_html(webview, "<BR><HR>"); + gtk_webview_scroll_to_end(webview, TRUE); g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); } - pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when); + pidgin_conv_write_conv( + purple_conversation_message_get_conv(msg), + purple_conversation_message_get_sender(msg), + purple_conversation_message_get_alias(msg), + purple_conversation_message_get_message(msg), + purple_conversation_message_get_flags(msg), + purple_conversation_message_get_timestamp(msg)); if (im) { gtkconv->attach.current = g_list_delete_link(gtkconv->attach.current, gtkconv->attach.current); } else { @@ -7766,16 +8282,23 @@ GList *history = purple_conversation_get_message_history(conv); for (; history; history = history->next) { PurpleConvMessage *msg = history->data; - if (msg->when > when) + if (purple_conversation_message_get_timestamp(msg) > when) msgs = g_list_prepend(msgs, msg); } } msgs = g_list_sort(msgs, message_compare); for (; msgs; msgs = g_list_delete_link(msgs, msgs)) { PurpleConvMessage *msg = msgs->data; - pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when); - } - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0); + pidgin_conv_write_conv( + purple_conversation_message_get_conv(msg), + purple_conversation_message_get_sender(msg), + purple_conversation_message_get_alias(msg), + purple_conversation_message_get_message(msg), + purple_conversation_message_get_flags(msg), + purple_conversation_message_get_timestamp(msg)); + } + gtk_webview_append_html(webview, "<BR><HR>"); + gtk_webview_scroll_to_end(webview, TRUE); g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); } @@ -7851,21 +8374,27 @@ g_return_val_if_reached(TRUE); } g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", - GINT_TO_POINTER(((PurpleConvMessage*)(list->data))->when)); + GINT_TO_POINTER(purple_conversation_message_get_timestamp((PurpleConvMessage*)(list->data)))); gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv); } else { purple_signal_emit(pidgin_conversations_get_handle(), "conversation-displayed", gtkconv); } - if (conv->type == PURPLE_CONV_TYPE_CHAT) { + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); - pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE); + pidgin_conv_chat_add_users(conv, purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)), TRUE); } return TRUE; } +PurpleTheme * +pidgin_conversations_get_default_theme(void) +{ + return default_conv_theme; +} + void * pidgin_conversations_get_handle(void) { @@ -7879,21 +8408,23 @@ { void *handle = pidgin_conversations_get_handle(); void *blist_handle = purple_blist_get_handle(); + char *theme_dir; /* Conversations */ purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations"); + purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/themes"); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", TRUE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", TRUE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", FALSE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE); + purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_strike", FALSE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/spellcheck", TRUE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting", TRUE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/resize_custom_smileys", TRUE); purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/custom_smileys_size", 96); purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines", 2); - purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps", TRUE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar", TRUE); purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/placement", "last"); @@ -7942,8 +8473,6 @@ /* Connect callbacks. */ purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", close_on_tabs_pref_cb, NULL); - purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/show_timestamps", - show_timestamps_pref_cb, NULL); purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar", show_formatting_toolbar_pref_cb, NULL); purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/spellcheck", @@ -8165,6 +8694,11 @@ purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle, PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); + purple_theme_manager_register_type(g_object_new(PIDGIN_TYPE_CONV_THEME_LOADER, "type", "conversation", NULL)); + theme_dir = g_build_filename(DATADIR, "pidgin", "theme", NULL); + default_conv_theme = purple_theme_manager_load_theme(theme_dir, "conversation"); + g_free(theme_dir); + { /* Set default tab colors */ GString *str = g_string_new(NULL); @@ -8310,8 +8844,9 @@ gtk_container_set_border_width(GTK_CONTAINER(warn_close_dialog), 6); gtk_window_set_resizable(GTK_WINDOW(warn_close_dialog), FALSE); - gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), - FALSE); +#if !GTK_CHECK_VERSION(2,22,0) + gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), FALSE); +#endif /* Setup the outside spacing. */ vbox = GTK_DIALOG(warn_close_dialog)->vbox; @@ -8613,9 +9148,9 @@ /* Right click was pressed. Popup the context menu. */ GtkWidget *menu = gtk_menu_new(), *sub; gboolean populated = populate_menu_with_options(menu, gtkconv, TRUE); + sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to)); - - if (sub && GTK_WIDGET_IS_SENSITIVE(gtkconv->win->menu.send_to)) { + if (sub && gtk_widget_is_sensitive(gtkconv->win->menu.send_to)) { GtkWidget *item = gtk_menu_item_new_with_mnemonic(_("S_end To")); if (populated) pidgin_separator(menu); @@ -9048,18 +9583,18 @@ PurpleConversation *conv = gtkconv->active_conv; const char *text = NULL; - if (!GTK_WIDGET_VISIBLE(gtkconv->infopane)) { + if (!gtk_widget_get_visible(gtkconv->infopane)) { /* There's already an entry for alias. Let's not create another one. */ return FALSE; } - if (!purple_account_is_connected(gtkconv->active_conv->account)) { + if (!purple_account_is_connected(purple_conversation_get_account(gtkconv->active_conv))) { /* Do not allow aliasing someone on a disconnected account. */ return FALSE; } if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleBuddy *buddy = purple_find_buddy(gtkconv->active_conv->account, gtkconv->active_conv->name); + PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv)); if (!buddy) /* This buddy isn't in your buddy list, so we can't alias him */ return FALSE; @@ -9069,9 +9604,9 @@ PurpleConnection *gc; PurplePluginProtocolInfo *prpl_info = NULL; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && prpl_info->set_chat_topic == NULL) /* This protocol doesn't support setting the chat room topic */ return FALSE; @@ -9132,8 +9667,8 @@ /* Update the menubar */ - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging), - purple_conversation_is_logging(conv)); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtkconv->win->menu.logging), + purple_conversation_is_logging(conv)); generate_send_to_items(win); regenerate_options_items(win); @@ -9143,14 +9678,11 @@ sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); if (strcmp(sound_method, "none") != 0) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), - gtkconv->make_sound); - - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_formatting_toolbar), - purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar")); - - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_timestamps), - purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps")); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds), + gtkconv->make_sound); + + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.show_formatting_toolbar), + purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar")); /* * We pause icons when they are not visible. If this icon should @@ -9208,7 +9740,7 @@ static gboolean gtk_conv_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) { int x, y; - if (GTK_WIDGET_VISIBLE(w)) + if (gtk_widget_get_visible(w)) gtk_window_get_position(GTK_WINDOW(w), &x, &y); else return FALSE; /* carry on normally */ @@ -9243,7 +9775,7 @@ /* if the window exists, is hidden, we're saving positions, and the * position is sane... */ if (win && win->window && - !GTK_WIDGET_VISIBLE(win->window) && conv_width != 0) { + !gtk_widget_get_visible(win->window) && conv_width != 0) { #ifdef _WIN32 /* only override window manager placement on Windows */ /* ...check position is on screen... */ @@ -9398,7 +9930,7 @@ } gtk_widget_destroy(win->window); - g_object_unref(G_OBJECT(win->menu.item_factory)); + g_object_unref(G_OBJECT(win->menu.ui)); purple_notify_close_with_handle(win); purple_signals_disconnect_by_handle(win); @@ -9476,8 +10008,12 @@ /* Close button. */ gtkconv->close = pidgin_create_small_button(gtk_label_new("×")); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(gtkconv->close, _("Close conversation")); +#else gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close, _("Close conversation"), NULL); +#endif g_signal_connect(gtkconv->close, "clicked", G_CALLBACK (close_conv_cb), gtkconv); @@ -9613,9 +10149,9 @@ gtk_notebook_set_tab_label(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, ebox); } - gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, - !tabs_side && !angle, - TRUE, GTK_PACK_START); + gtk_container_child_set(GTK_CONTAINER(win->notebook), gtkconv->tab_cont, + "tab-expand", !tabs_side && !angle, + "tab-fill", TRUE, NULL); if (pidgin_conv_window_get_gtkconv_count(win) == 1) gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), @@ -9639,8 +10175,7 @@ index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont); - g_object_ref(gtkconv->tab_cont); - gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont)); + g_object_ref_sink(G_OBJECT(gtkconv->tab_cont)); gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index); @@ -9845,7 +10380,7 @@ PurpleConversationType type = purple_conversation_get_type(conv->active_conv); GList *all; - if (GTK_WIDGET_VISIBLE(w)) + if (gtk_widget_get_visible(w)) gtk_window_get_position(GTK_WINDOW(w), &x, &y); else return FALSE; /* carry on normally */