Mercurial > pidgin
changeset 18002:38a72d6dce7f
merge of '9e832cea16395c9007bc9e384ee379b293b99abd'
and 'bda8b30520ae63b1ce117a6799cb41a65c55018d'
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Mon, 04 Jun 2007 06:32:21 +0000 |
parents | 01021bb5c709 (current diff) 55a90b3fb1a1 (diff) |
children | 7935fe8ed901 6b7b13adb9b1 |
files | pidgin/gtkaccount.c pidgin/gtkblist.c pidgin/gtkimhtml.c |
diffstat | 39 files changed, 883 insertions(+), 510 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog.API Mon Jun 04 06:15:43 2007 +0000 +++ b/ChangeLog.API Mon Jun 04 06:32:21 2007 +0000 @@ -1,5 +1,25 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.1.0 (?/?/?): + Added: + * purple_conversation_get_extended_menu + * purple_conversation_do_command + * pidgin_retrieve_user_info, shows immediate feedback when getting + information about a user. + * gtk_imhtml_setup_entry + * purple_xfer_get_remote_user + * purple_blist_node_get_type + + Changed: + * pidgin_separator returns the separator added to the menu. + * pidgin_append_menu_action returns the menuitem added to the menu. + + Signals - Added: (See the Doxygen docs for details on all signals.) + * "conversation-extended-menu" + + Finch - Added: + * finch_retrieve_user_info + version 2.0.0 (5/3/2007): Please note all functions, defines, and data structures have been re-namespaced to match the new names of Pidgin, Finch, and libpurple.
--- a/doc/conversation-signals.dox Mon Jun 04 06:15:43 2007 +0000 +++ b/doc/conversation-signals.dox Mon Jun 04 06:32:21 2007 +0000 @@ -29,6 +29,7 @@ @signal chat-joined @signal chat-left @signal chat-topic-changed + @signal conversation-extended-menu @endsignals @signaldef writing-im-msg @@ -417,5 +418,15 @@ @param topic The new topic. @endsignaldef + @signaldef conversation-extended-menu + @signalproto +void (*conversation_extended_menu)(PurpleConversation *conv, GList **list); + @endsignalproto + @signaldesc + Emitted when the UI requests a list of plugin actions for a + conversation. + @param conv The conversation. + @param list A pointer to the list of actions. + @endsignaldef */ // vim: syntax=c tw=75 et
--- a/finch/gntaccount.c Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/gntaccount.c Mon Jun 04 06:32:21 2007 +0000 @@ -31,6 +31,7 @@ #include <gntlabel.h> #include <gntline.h> #include <gnttree.h> +#include <gntwindow.h> #include <account.h> #include <accountopt.h> @@ -40,6 +41,7 @@ #include <request.h> #include "gntaccount.h" +#include "gntblist.h" #include "finch.h" #include <string.h> @@ -743,12 +745,18 @@ finch_accounts_get_handle(), PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE)); - for (iter = purple_accounts_get_all(); iter; iter = iter->next) { - if (purple_account_get_enabled(iter->data, FINCH_UI)) - break; + iter = purple_accounts_get_all(); + if (iter) { + for (; iter; iter = iter->next) { + if (purple_account_get_enabled(iter->data, FINCH_UI)) + break; + } + if (!iter) + finch_accounts_show_all(); + } else { + edit_account(NULL); + finch_accounts_show_all(); } - if (!iter) - finch_accounts_show_all(); } void finch_accounts_uninit() @@ -865,25 +873,25 @@ } auth_and_add; static void -authorize_and_add_cb(auth_and_add *aa) +free_auth_and_add(auth_and_add *aa) { - aa->auth_cb(aa->data); - purple_blist_request_add_buddy(aa->account, aa->username, - NULL, aa->alias); - g_free(aa->username); g_free(aa->alias); g_free(aa); } static void +authorize_and_add_cb(auth_and_add *aa) +{ + aa->auth_cb(aa->data); + purple_blist_request_add_buddy(aa->account, aa->username, + NULL, aa->alias); +} + +static void deny_no_add_cb(auth_and_add *aa) { aa->deny_cb(aa->data); - - g_free(aa->username); - g_free(aa->alias); - g_free(aa); } static void * @@ -912,19 +920,47 @@ (message != NULL ? ": " : "."), (message != NULL ? message : "")); if (!on_list) { + GntWidget *widget; + GList *iter; auth_and_add *aa = g_new(auth_and_add, 1); + aa->auth_cb = (PurpleAccountRequestAuthorizationCb)auth_cb; aa->deny_cb = (PurpleAccountRequestAuthorizationCb)deny_cb; aa->data = user_data; aa->username = g_strdup(remote_user); aa->alias = g_strdup(alias); aa->account = account; - uihandle = purple_request_action(NULL, _("Authorize buddy?"), buffer, NULL, + + uihandle = gnt_vwindow_new(FALSE); + gnt_box_set_title(GNT_BOX(uihandle), _("Authorize buddy?")); + gnt_box_set_pad(GNT_BOX(uihandle), 0); + + widget = purple_request_action(NULL, _("Authorize buddy?"), buffer, NULL, PURPLE_DEFAULT_ACTION_NONE, account, remote_user, NULL, aa, 2, _("Authorize"), authorize_and_add_cb, _("Deny"), deny_no_add_cb); + gnt_screen_release(widget); + gnt_box_set_toplevel(GNT_BOX(widget), FALSE); + gnt_box_add_widget(GNT_BOX(uihandle), widget); + + gnt_box_add_widget(GNT_BOX(uihandle), gnt_hline_new()); + + widget = finch_retrieve_user_info(account->gc, remote_user); + for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) { + if (GNT_IS_BUTTON(iter->data)) { + gnt_widget_destroy(iter->data); + gnt_box_remove(GNT_BOX(widget), iter->data); + break; + } + } + gnt_box_set_toplevel(GNT_BOX(widget), FALSE); + gnt_screen_release(widget); + gnt_box_add_widget(GNT_BOX(uihandle), widget); + gnt_widget_show(uihandle); + + g_signal_connect_swapped(G_OBJECT(uihandle), "destroy", G_CALLBACK(free_auth_and_add), aa); } else { uihandle = purple_request_action(NULL, _("Authorize buddy?"), buffer, NULL, PURPLE_DEFAULT_ACTION_NONE,
--- a/finch/gntblist.c Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/gntblist.c Mon Jun 04 06:32:21 2007 +0000 @@ -104,6 +104,7 @@ static void add_group(PurpleGroup *group, FinchBlist *ggblist); static void add_chat(PurpleChat *chat, FinchBlist *ggblist); static void add_node(PurpleBlistNode *node, FinchBlist *ggblist); +static void node_update(PurpleBuddyList *list, PurpleBlistNode *node); static void draw_tooltip(FinchBlist *ggblist); static gboolean remove_typing_cb(gpointer null); static void remove_peripherals(FinchBlist *ggblist); @@ -189,6 +190,8 @@ if ((!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_contact_online(contact)) || contact->currentsize < 1) node_remove(list, (PurpleBlistNode*)contact); + else + node_update(list, (PurpleBlistNode*)contact); } else if (!PURPLE_BLIST_NODE_IS_GROUP(node)) { PurpleGroup *group = (PurpleGroup*)node->parent; if ((!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group)) || @@ -215,6 +218,9 @@ if (list->ui_data == NULL) return; /* XXX: this is probably the place to auto-join chats */ + if (ggblist->window == NULL) + return; + if (node->ui_data != NULL) { gnt_tree_change_text(GNT_TREE(ggblist->tree), node, 0, get_display_name(node)); @@ -824,17 +830,22 @@ PURPLE_CALLBACK(finch_add_group), group); } +gpointer finch_retrieve_user_info(PurpleConnection *conn, const char *name) +{ + PurpleNotifyUserInfo *info = purple_notify_user_info_new(); + gpointer uihandle; + purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); + uihandle = purple_notify_userinfo(conn, name, info, NULL, NULL); + purple_notify_user_info_destroy(info); + + serv_get_info(conn, name); + return uihandle; +} + static void finch_blist_get_buddy_info_cb(PurpleBuddy *buddy, PurpleBlistNode *selected) { - /* Add a userinfo with a "Retrieving information", which will later be updated - * when the server finally returns the information. */ - PurpleNotifyUserInfo *info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); - purple_notify_userinfo(buddy->account->gc, purple_buddy_get_name(buddy), info, NULL, NULL); - purple_notify_user_info_destroy(info); - - serv_get_info(buddy->account->gc, purple_buddy_get_name(buddy)); + finch_retrieve_user_info(buddy->account->gc, purple_buddy_get_name(buddy)); } static void
--- a/finch/gntblist.h Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/gntblist.h Mon Jun 04 06:32:21 2007 +0000 @@ -90,6 +90,16 @@ */ void finch_blist_set_size(int width, int height); +/** + * Get information about a user. Show immediate feedback. + * + * @param conn The connection to get information fro + * @param name The user to get information about. + * + * @return Returns the ui-handle for the userinfo notification. + */ +gpointer finch_retrieve_user_info(PurpleConnection *conn, const char *name); + /*@}*/ #endif
--- a/finch/gntconv.c Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/gntconv.c Mon Jun 04 06:32:21 2007 +0000 @@ -64,7 +64,7 @@ send_typing_notification(GntWidget *w, FinchConv *ggconv) { const char *text = gnt_entry_get_text(GNT_ENTRY(ggconv->entry)); - gboolean empty = (!text || !*text); + gboolean empty = (!text || !*text || (*text == '/')); if (purple_prefs_get_bool("/finch/conversations/notify_typing")) { PurpleConversation *conv = ggconv->active_conv; PurpleConvIm *im = PURPLE_CONV_IM(conv); @@ -313,12 +313,7 @@ get_info_cb(GntMenuItem *item, gpointer ggconv) { FinchConv *ggc = ggconv; - PurpleNotifyUserInfo *info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); - purple_notify_userinfo(ggc->active_conv->account->gc, purple_conversation_get_name(ggc->active_conv), info, NULL, NULL); - purple_notify_user_info_destroy(info); - - serv_get_info(purple_conversation_get_gc(ggc->active_conv), + finch_retrieve_user_info(purple_conversation_get_gc(ggc->active_conv), purple_conversation_get_name(ggc->active_conv)); }
--- a/finch/gntnotify.c Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/gntnotify.c Mon Jun 04 06:32:21 2007 +0000 @@ -69,6 +69,7 @@ gnt_box_set_title(GNT_BOX(window), title); gnt_box_set_fill(GNT_BOX(window), FALSE); gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); + gnt_box_set_pad(GNT_BOX(window), 0); if (primary) gnt_box_add_widget(GNT_BOX(window), @@ -168,7 +169,7 @@ gnt_label_new_with_format(_("You have mail!"), GNT_TEXT_FLAG_BOLD)); emaildialog.tree = tree = gnt_tree_new_with_columns(3); - gnt_tree_set_column_titles(GNT_TREE(tree), _("Account"), _("From"), _("Subject")); + gnt_tree_set_column_titles(GNT_TREE(tree), _("Account"), _("Sender"), _("Subject")); gnt_tree_set_show_title(GNT_TREE(tree), TRUE); gnt_tree_set_col_width(GNT_TREE(tree), 0, 15); gnt_tree_set_col_width(GNT_TREE(tree), 1, 25); @@ -268,11 +269,11 @@ char *strip = purple_markup_strip_html(info); int tvw, tvh, width, height, ntvw, ntvh; + while (GNT_WIDGET(ui_handle)->parent) + ui_handle = GNT_WIDGET(ui_handle)->parent; gnt_widget_get_size(GNT_WIDGET(ui_handle), &width, &height); gnt_widget_get_size(GNT_WIDGET(msg), &tvw, &tvh); - /* Ideally, I would replace the information in "info". But replacing tagged text is a - * bit nasty right now. So clear the view and add the new stuff instead. */ gnt_text_view_clear(msg); gnt_text_view_append_text_with_flags(msg, strip, GNT_TEXT_FLAG_NORMAL); gnt_text_view_scroll(msg, 0); @@ -280,7 +281,7 @@ ntvw += 3; ntvh++; - gnt_screen_resize_widget(GNT_WIDGET(ui_handle), width + (ntvw - tvw), height + (ntvh - tvh)); + gnt_screen_resize_widget(GNT_WIDGET(ui_handle), width + MAX(0, ntvw - tvw), height + MAX(0, ntvh - tvh)); g_free(strip); g_free(key); } else {
--- a/finch/libgnt/gntbox.c Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/libgnt/gntbox.c Mon Jun 04 06:32:21 2007 +0000 @@ -293,6 +293,10 @@ { find_next_focus(box); } + else if (strcmp(text, GNT_KEY_BACK_TAB) == 0) + { + find_prev_focus(box); + } } else if (text[0] == '\t') {
--- a/finch/libgnt/gntkeys.c Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/libgnt/gntkeys.c Mon Jun 04 06:32:21 2007 +0000 @@ -50,6 +50,7 @@ INSERT_KEY("pagedown", GNT_KEY_PGDOWN); INSERT_KEY("insert", GNT_KEY_INS); INSERT_KEY("delete", GNT_KEY_DEL); + INSERT_KEY("back_tab", GNT_KEY_BACK_TAB); INSERT_KEY("left", GNT_KEY_LEFT); INSERT_KEY("right", GNT_KEY_RIGHT);
--- a/finch/libgnt/gntkeys.h Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/libgnt/gntkeys.h Mon Jun 04 06:32:21 2007 +0000 @@ -39,6 +39,7 @@ #define GNT_KEY_BACKSPACE SAFE(key_backspace) #define GNT_KEY_DEL SAFE(key_dc) #define GNT_KEY_INS SAFE(key_ic) +#define GNT_KEY_BACK_TAB SAFE(back_tab) #define GNT_KEY_CTRL_A "\001" #define GNT_KEY_CTRL_B "\002"
--- a/finch/libgnt/gntmain.c Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/libgnt/gntmain.c Mon Jun 04 06:32:21 2007 +0000 @@ -1,5 +1,5 @@ #define _GNU_SOURCE -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__unix__) #define _XOPEN_SOURCE_EXTENDED #endif @@ -359,8 +359,7 @@ switch (sig) { #ifdef SIGWINCH case SIGWINCH: - werase(stdscr); - wrefresh(stdscr); + erase(); g_idle_add(refresh_screen, NULL); org_winch_handler(sig); signal(SIGWINCH, sighandler);
--- a/finch/libgnt/gntwm.c Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/libgnt/gntwm.c Mon Jun 04 06:32:21 2007 +0000 @@ -1,5 +1,5 @@ #define _GNU_SOURCE -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__unix__) #define _XOPEN_SOURCE_EXTENDED #endif @@ -980,12 +980,11 @@ GntWM *wm = GNT_WM(bindable); endwin(); - refresh(); - curs_set(0); /* endwin resets the cursor to normal */ g_hash_table_foreach(wm->nodes, (GHFunc)refresh_node, NULL); update_screen(wm); draw_taskbar(wm, TRUE); + curs_set(0); /* endwin resets the cursor to normal */ return FALSE; }
--- a/finch/libgnt/wms/Makefile.am Mon Jun 04 06:15:43 2007 +0000 +++ b/finch/libgnt/wms/Makefile.am Mon Jun 04 06:32:21 2007 +0000 @@ -1,9 +1,16 @@ s_la_LDFLAGS = -module -avoid-version +irssi_la_LDFLAGS = -module -avoid-version plugin_LTLIBRARIES = \ - s.la + s.la \ + irssi.la + +plugindir = $(libdir)/gnt -plugindir = $(libdir)/finch +irssi_la_SOURCES = irssi.c +irssi_la_LIBADD = \ + $(GLIB_LIBS) \ + $(top_builddir)/finch/libgnt/libgnt.la s_la_SOURCES = s.c s_la_LIBADD = \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/libgnt/wms/irssi.c Mon Jun 04 06:32:21 2007 +0000 @@ -0,0 +1,161 @@ +/** + * 1. Buddylist and conversation windows are borderless and full height of the screen. + * 2. Conversation windows will have (full-screen-width - buddylist-width) width + * - It's possible to auto-resize the conversation windows when the buddylist + * is closed/opened/resized to keep this always true. But resizing the textview + * in conversation window is rather costly, especially when there's a lot of text + * in the scrollback. So it's not done yet. + * 3. All the other windows are always centered. + */ +#include <string.h> +#include <sys/types.h> + +#include "gnt.h" +#include "gntbox.h" +#include "gntmenu.h" +#include "gntstyle.h" +#include "gntwm.h" +#include "gntwindow.h" +#include "gntlabel.h" + +#define TYPE_IRSSI (irssi_get_gtype()) + +typedef struct _Irssi +{ + GntWM inherit; +} Irssi; + +typedef struct _IrssiClass +{ + GntWMClass inherit; +} IrssiClass; + +GType irssi_get_gtype(void); +void gntwm_init(GntWM **wm); + +static void (*org_new_window)(GntWM *wm, GntWidget *win); + +/* This is changed whenever the buddylist is opened/closed or resized. */ +static int buddylistwidth; + +static gboolean +is_budddylist(GntWidget *win) +{ + const char *name = gnt_widget_get_name(win); + if (name && strcmp(name, "buddylist") == 0) + return TRUE; + return FALSE; +} + +static void +remove_border_set_position_size(GntWM *wm, GntWidget *win, int x, int y, int w, int h) +{ + gnt_box_set_toplevel(GNT_BOX(win), FALSE); + GNT_WIDGET_SET_FLAGS(win, GNT_WIDGET_CAN_TAKE_FOCUS); + + gnt_widget_set_position(win, x, y); + mvwin(win->window, y, x); + gnt_widget_set_size(win, (w < 0) ? -1 : w + 2, h + 2); +} + +static void +irssi_new_window(GntWM *wm, GntWidget *win) +{ + const char *name; + + name = gnt_widget_get_name(win); + if (!name || strcmp(name, "conversation-window")) { + if (!GNT_IS_MENU(win) && !GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_TRANSIENT)) { + if ((!name || strcmp(name, "buddylist"))) { + int w, h, x, y; + gnt_widget_get_size(win, &w, &h); + x = (getmaxx(stdscr) - w) / 2; + y = (getmaxy(stdscr) - h) / 2; + gnt_widget_set_position(win, x, y); + mvwin(win->window, y, x); + } else { + remove_border_set_position_size(wm, win, 0, 0, -1, getmaxy(stdscr) - 1); + gnt_widget_get_size(win, &buddylistwidth, NULL); + mvwvline(stdscr, 0, buddylistwidth, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), getmaxy(stdscr) - 1); + buddylistwidth++; + } + } + org_new_window(wm, win); + return; + } + + /* The window we have here is a conversation window. */ + remove_border_set_position_size(wm, win, buddylistwidth, 0, + getmaxx(stdscr) - buddylistwidth, getmaxy(stdscr) - 1); + org_new_window(wm, win); +} + +static void +irssi_window_resized(GntWM *wm, GntNode *node) +{ + if (!is_budddylist(node->me)) + return; + + if (buddylistwidth) + mvwvline(stdscr, 0, buddylistwidth - 1, + ' ' | COLOR_PAIR(GNT_COLOR_NORMAL), getmaxy(stdscr) - 1); + gnt_widget_get_size(node->me, &buddylistwidth, NULL); + mvwvline(stdscr, 0, buddylistwidth, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), getmaxy(stdscr) - 1); + buddylistwidth++; +} + +static gboolean +irssi_close_window(GntWM *wm, GntWidget *win) +{ + if (is_budddylist(win)) + buddylistwidth = 0; + return FALSE; +} + +static void +irssi_class_init(IrssiClass *klass) +{ + GntWMClass *pclass = GNT_WM_CLASS(klass); + + org_new_window = pclass->new_window; + + pclass->new_window = irssi_new_window; + pclass->window_resized = irssi_window_resized; + pclass->close_window = irssi_close_window; + + gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); + GNTDEBUG; +} + +void gntwm_init(GntWM **wm) +{ + buddylistwidth = 0; + *wm = g_object_new(TYPE_IRSSI, NULL); +} + +GType irssi_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(IrssiClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)irssi_class_init, + NULL, + NULL, /* class_data */ + sizeof(Irssi), + 0, /* n_preallocs */ + NULL, /* instance_init */ + NULL + }; + + type = g_type_register_static(GNT_TYPE_WM, + "GntIrssi", + &info, 0); + } + + return type; +} +
--- a/libpurple/Makefile.am Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/Makefile.am Mon Jun 04 06:32:21 2007 +0000 @@ -151,7 +151,7 @@ dbus_headers = dbus-bindings.h dbus-purple.h dbus-server.h dbus-useful.h dbus-define-api.h dbus_exported = dbus-useful.h dbus-define-api.h account.h blist.h buddyicon.h \ - connection.h conversation.h core.h log.h notify.h prefs.h roomlist.h \ + connection.h conversation.h core.h ft.h log.h notify.h prefs.h roomlist.h \ savedstatuses.h status.h server.h util.h xmlnode.h purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders))
--- a/libpurple/blist.c Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/blist.c Mon Jun 04 06:32:21 2007 +0000 @@ -2498,6 +2498,13 @@ return node->flags; } +PurpleBlistNodeType +purple_blist_node_get_type(PurpleBlistNode *node) +{ + g_return_val_if_fail(node != NULL, PURPLE_BLIST_OTHER_NODE); + return node->type; +} + void purple_blist_node_set_bool(PurpleBlistNode* node, const char *key, gboolean data) {
--- a/libpurple/blist.h Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/blist.h Mon Jun 04 06:32:21 2007 +0000 @@ -864,6 +864,15 @@ */ PurpleBlistNodeFlags purple_blist_node_get_flags(PurpleBlistNode *node); +/** + * Get the type of a given node. + * + * @param node The node. + * + * @return The type of the node. + */ +PurpleBlistNodeType purple_blist_node_get_type(PurpleBlistNode *node); + /*@}*/ /**
--- a/libpurple/conversation.c Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/conversation.c Mon Jun 04 06:32:21 2007 +0000 @@ -21,6 +21,7 @@ */ #include "internal.h" #include "blist.h" +#include "cmds.h" #include "conversation.h" #include "dbus-maybe.h" #include "debug.h" @@ -1989,6 +1990,29 @@ return cb->name; } +GList * +purple_conversation_get_extended_menu(PurpleConversation *conv) +{ + GList *menu = NULL; + + g_return_val_if_fail(conv != NULL, NULL); + + purple_signal_emit(purple_conversations_get_handle(), + "conversation-extended-menu", conv, &menu); + return menu; +} + +gboolean +purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline, + const gchar *markup, gchar **error) +{ + char *mark = (markup && *markup) ? NULL : g_markup_escape_text(cmdline, -1), *err = NULL; + PurpleCmdStatus status = purple_cmd_do_command(conv, cmdline, mark ? mark : markup, error ? error : &err); + g_free(mark); + g_free(err); + return (status == PURPLE_CMD_STATUS_OK); +} + void * purple_conversations_get_handle(void) { @@ -2252,6 +2276,12 @@ PURPLE_SUBTYPE_CONVERSATION), purple_value_new(PURPLE_TYPE_STRING), purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "conversation-extended-menu", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_BOXED, "GList **")); } void
--- a/libpurple/conversation.h Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/conversation.h Mon Jun 04 06:32:21 2007 +0000 @@ -1190,6 +1190,30 @@ */ void purple_conv_chat_cb_destroy(PurpleConvChatBuddy *cb); +/** + * Retrieves the extended menu items for the conversation. + * + * @param conv The conversation. + * + * @return A list of PurpleMenuAction items, harvested by the + * chat-extended-menu signal. The list and the menuaction + * items should be freed by the caller. + */ +GList * purple_conversation_get_extended_menu(PurpleConversation *conv); + +/** + * Perform a command in a conversation. Similar to @see purple_cmd_do_command + * + * @param conv The conversation. + * @param cmdline The entire command including the arguments. + * @param markup @c NULL, or the formatted command line. + * @param error If the command failed errormsg is filled in with the appropriate error + * message, if not @c NULL. It must be freed by the caller with g_free(). + * + * @return @c TRUE if the command was executed successfully, @c FALSE otherwise. + */ +gboolean purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline, const gchar *markup, gchar **error); + /*@}*/ /**************************************************************************/
--- a/libpurple/ft.c Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/ft.c Mon Jun 04 06:32:21 2007 +0000 @@ -23,6 +23,7 @@ * */ #include "internal.h" +#include "dbus-maybe.h" #include "ft.h" #include "network.h" #include "notify.h" @@ -56,6 +57,7 @@ g_return_val_if_fail(who != NULL, NULL); xfer = g_new0(PurpleXfer, 1); + PURPLE_DBUS_REGISTER_POINTER(xfer, PurpleXfer); xfer->ref = 1; xfer->type = type; @@ -97,6 +99,7 @@ g_free(xfer->remote_ip); g_free(xfer->local_filename); + PURPLE_DBUS_UNREGISTER_POINTER(xfer); g_free(xfer); xfers = g_list_remove(xfers, xfer); } @@ -551,6 +554,13 @@ return xfer->account; } +const char * +purple_xfer_get_remote_user(const PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, NULL); + return xfer->who; +} + PurpleXferStatusType purple_xfer_get_status(const PurpleXfer *xfer) {
--- a/libpurple/ft.h Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/ft.h Mon Jun 04 06:32:21 2007 +0000 @@ -237,6 +237,15 @@ PurpleAccount *purple_xfer_get_account(const PurpleXfer *xfer); /** + * Returns the name of the remote user. + * + * @param xfer The file transfer. + * + * @return The name of the remote user. + */ +const char *purple_xfer_get_remote_user(const PurpleXfer *xfer); + +/** * Returns the status of the xfer. * * @param xfer The file transfer.
--- a/libpurple/imgstore.c Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/imgstore.c Mon Jun 04 06:32:21 2007 +0000 @@ -25,6 +25,7 @@ */ #include <glib.h> +#include "dbus-maybe.h" #include "debug.h" #include "imgstore.h" #include "util.h" @@ -56,6 +57,7 @@ g_return_val_if_fail(size > 0, 0); img = g_new(PurpleStoredImage, 1); + PURPLE_DBUS_REGISTER_POINTER(img, PurpleStoredImage); img->data = data; img->size = size; img->filename = g_strdup(filename); @@ -159,6 +161,7 @@ g_free(img->data); g_free(img->filename); + PURPLE_DBUS_UNREGISTER_POINTER(img); g_free(img); img = NULL; }
--- a/libpurple/plugins/perl/common/Account.xs Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/plugins/perl/common/Account.xs Mon Jun 04 06:32:21 2007 +0000 @@ -215,6 +215,7 @@ t_GL = g_list_append(t_GL, SvPV(*av_fetch((AV *)SvRV(list), i, 0), t_sl)); } purple_account_add_buddies(account, t_GL); + g_list_free(t_GL); void purple_account_add_buddy(account, buddy) @@ -252,6 +253,8 @@ t_GL2 = g_list_append(t_GL2, SvPV(*av_fetch((AV *)SvRV(B), i, 0), t_sl)); } purple_account_remove_buddies(account, t_GL1, t_GL2); + g_list_free(t_GL1); + g_list_free(t_GL2); void purple_account_remove_buddy(account, buddy, group)
--- a/libpurple/plugins/perl/common/BuddyList.xs Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/plugins/perl/common/BuddyList.xs Mon Jun 04 06:32:21 2007 +0000 @@ -112,6 +112,10 @@ Purple::BuddyList::Group group Purple::Account account +const char * +purple_group_get_name(group) + Purple::BuddyList::Group group + MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList PREFIX = purple_blist_ PROTOTYPES: ENABLE @@ -248,6 +252,9 @@ Purple::Handle purple_blist_get_handle() +Purple::BuddyList::Node +purple_blist_get_root() + void purple_blist_init() @@ -263,7 +270,7 @@ PREINIT: GList *l; PPCODE: - for (l = purple_blist_node_get_extended_menu(node); l != NULL; l = l->next) { + for (l = purple_blist_node_get_extended_menu(node); l != NULL; l = g_list_delete_link(l, l)) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Menu::Action"))); } @@ -308,6 +315,15 @@ purple_blist_node_get_flags(node) Purple::BuddyList::Node node +Purple::BuddyList::NodeType +purple_blist_node_get_type(node) + Purple::BuddyList::Node node + +Purple::BuddyList::Node +purple_blist_node_next(node, offline) + Purple::BuddyList::Node node + gboolean offline + MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList::Chat PREFIX = purple_chat_ PROTOTYPES: ENABLE
--- a/libpurple/plugins/perl/common/Conversation.xs Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/plugins/perl/common/Conversation.xs Mon Jun 04 06:32:21 2007 +0000 @@ -218,6 +218,21 @@ Purple::Conversation conv Purple::Account account +void +purple_conversation_write(conv, who, message, flags, mtime) + Purple::Conversation conv + const char *who + const char *message + Purple::MessageFlags flags + time_t mtime + +gboolean +purple_conversation_do_command(conv, cmdline, markup, error) + Purple::Conversation conv + const char *cmdline + const char *markup + char **error + MODULE = Purple::Conversation PACKAGE = Purple::Conversation::IM PREFIX = purple_conv_im_ PROTOTYPES: ENABLE
--- a/libpurple/plugins/perl/common/Prefs.xs Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/plugins/perl/common/Prefs.xs Mon Jun 04 06:32:21 2007 +0000 @@ -94,8 +94,9 @@ PREINIT: GList *l; PPCODE: - for (l = purple_prefs_get_string_list(name); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::PrefValue"))); + for (l = purple_prefs_get_string_list(name); l != NULL; l = g_list_delete_link(l, l)) { + XPUSHs(sv_2mortal(newSVpv(l->data, 0))); + g_free(l->data); } Purple::PrefType
--- a/libpurple/plugins/perl/common/module.h Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/plugins/perl/common/module.h Mon Jun 04 06:32:21 2007 +0000 @@ -69,6 +69,7 @@ /* blist.h */ typedef PurpleBlistNode * Purple__BuddyList__Node; typedef PurpleBlistNodeFlags Purple__BuddyList__NodeFlags; +typedef PurpleBlistNodeType Purple__BuddyList__NodeType; typedef PurpleBlistUiOps * Purple__BuddyList__UiOps; typedef PurpleBuddyList * Purple__BuddyList; typedef PurpleBuddy * Purple__BuddyList__Buddy;
--- a/libpurple/plugins/perl/common/typemap Mon Jun 04 06:15:43 2007 +0000 +++ b/libpurple/plugins/perl/common/typemap Mon Jun 04 06:32:21 2007 +0000 @@ -52,6 +52,7 @@ Purple::BuddyList::Group T_PurpleObj Purple::BuddyList::Node T_PurpleObj Purple::BuddyList::NodeFlags T_IV +Purple::BuddyList::NodeType T_IV Purple::BuddyList::UiOps T_PurpleObj Purple::Cipher T_PurpleObj
--- a/pidgin/gtkaccount.c Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/gtkaccount.c Mon Jun 04 06:32:21 2007 +0000 @@ -480,7 +480,7 @@ GtkWidget *entry = l->data; PurpleAccountUserSplit *split = l2->data; - const char *value = NULL, *protocol = NULL; + const char *value = NULL; char *c; if (dialog->account != NULL) { @@ -500,9 +500,8 @@ /* Google Talk default domain hackery! */ menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu)); item = gtk_menu_get_active(GTK_MENU(menu)); - protocol = g_object_get_data(G_OBJECT(item), "protocol"); - if (value == NULL && protocol != NULL && !strcmp(protocol, "prpl-fake") && - !strcmp(purple_account_user_split_get_text(split), _("Domain"))) + if (value == NULL && g_object_get_data(G_OBJECT(item), "fake") && + !strcmp(purple_account_user_split_get_text(split), _("Domain"))) value = "gmail.com"; if (value != NULL) @@ -703,7 +702,7 @@ GList *l; char buf[1024]; char *title; - const char *str_value, *protocol; + const char *str_value; gboolean bool_value; if (dialog->protocol_frame != NULL) { @@ -829,10 +828,9 @@ /* Google Talk default domain hackery! */ menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu)); item = gtk_menu_get_active(GTK_MENU(menu)); - protocol = g_object_get_data(G_OBJECT(item), "protocol"); - if (str_value == NULL && protocol != NULL && !strcmp(protocol, "prpl-fake") && + if (str_value == NULL && g_object_get_data(G_OBJECT(item), "fake") && !strcmp(_("Connect server"), purple_account_option_get_text(option))) - str_value = "talk.google.com"; + str_value = "talk.google.com"; if (str_value != NULL) gtk_entry_set_text(GTK_ENTRY(entry), str_value); @@ -1467,7 +1465,6 @@ if ((dialog->plugin = purple_find_prpl(dialog->protocol_id)) != NULL) dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin); - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_role(GTK_WINDOW(win), "account");
--- a/pidgin/gtkblist.c Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/gtkblist.c Mon Jun 04 06:32:21 2007 +0000 @@ -274,12 +274,7 @@ static void gtk_blist_menu_info_cb(GtkWidget *w, PurpleBuddy *b) { - PurpleNotifyUserInfo *info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); - purple_notify_userinfo(b->account->gc, purple_buddy_get_name(b), info, NULL, NULL); - purple_notify_user_info_destroy(info); - - serv_get_info(b->account->gc, b->name); + pidgin_retrieve_user_info(b->account->gc, purple_buddy_get_name(b)); } static void gtk_blist_menu_im_cb(GtkWidget *w, PurpleBuddy *b) @@ -1142,7 +1137,8 @@ } static gboolean -gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data) { +gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data) +{ PurpleBlistNode *node; GValue val; GtkTreeIter iter; @@ -1169,7 +1165,7 @@ return FALSE; } if(buddy) - serv_get_info(buddy->account->gc, buddy->name); + pidgin_retrieve_user_info(buddy->account->gc, buddy->name); } else if (event->keyval == GDK_F2) { gtk_blist_menu_alias_cb(tv, node); } @@ -1423,7 +1419,7 @@ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); if (prpl && prpl_info->get_info) - serv_get_info(b->account->gc, b->name); + pidgin_retrieve_user_info(b->account->gc, b->name); handled = TRUE; } @@ -3837,15 +3833,17 @@ static gboolean gtk_blist_window_key_press_cb(GtkWidget *w, GdkEventKey *event, PidginBuddyList *gtkblist) { - GtkWidget *imhtml; + GtkWidget *widget; if (!gtkblist) return FALSE; - imhtml = gtk_window_get_focus(GTK_WINDOW(gtkblist->window)); - - if (GTK_IS_IMHTML(imhtml) && gtk_bindings_activate(GTK_OBJECT(imhtml), event->keyval, event->state)) - return TRUE; + widget = gtk_window_get_focus(GTK_WINDOW(gtkblist->window)); + + if (GTK_IS_IMHTML(widget) || GTK_IS_ENTRY(widget)) { + if (gtk_bindings_activate(GTK_OBJECT(widget), event->keyval, event->state)) + return TRUE; + } return FALSE; }
--- a/pidgin/gtkconv.c Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/gtkconv.c Mon Jun 04 06:32:21 2007 +0000 @@ -271,65 +271,7 @@ default_formatize(PidginConversation *c) { PurpleConversation *conv = c->active_conv; - - if (conv->features & PURPLE_CONNECTION_HTML) - { - char color[8]; - GdkColor fg_color, bg_color; - - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold") != GTK_IMHTML(c->entry)->edit.bold) - gtk_imhtml_toggle_bold(GTK_IMHTML(c->entry)); - - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic") != GTK_IMHTML(c->entry)->edit.italic) - gtk_imhtml_toggle_italic(GTK_IMHTML(c->entry)); - - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline") != GTK_IMHTML(c->entry)->edit.underline) - gtk_imhtml_toggle_underline(GTK_IMHTML(c->entry)); - - gtk_imhtml_toggle_fontface(GTK_IMHTML(c->entry), - purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face")); - - if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE)) - { - int size = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size"); - - /* 3 is the default. */ - if (size != 3) - gtk_imhtml_font_set_size(GTK_IMHTML(c->entry), size); - } - - if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), "") != 0) - { - gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), - &fg_color); - g_snprintf(color, sizeof(color), "#%02x%02x%02x", - fg_color.red / 256, - fg_color.green / 256, - fg_color.blue / 256); - } else - strcpy(color, ""); - - gtk_imhtml_toggle_forecolor(GTK_IMHTML(c->entry), color); - - if(!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR) && - strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), "") != 0) - { - gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), - &bg_color); - g_snprintf(color, sizeof(color), "#%02x%02x%02x", - bg_color.red / 256, - bg_color.green / 256, - bg_color.blue / 256); - } else - strcpy(color, ""); - - gtk_imhtml_toggle_background(GTK_IMHTML(c->entry), color); - - if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO) - gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), TRUE); - else - gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(c->entry), FALSE); - } + gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features); } static void @@ -666,7 +608,7 @@ purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); } else - prpl_info->get_info(gc, who); + pidgin_retrieve_user_info(gc, who); } } @@ -677,14 +619,8 @@ PurpleConversation *conv = gtkconv->active_conv; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleNotifyUserInfo *info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); - purple_notify_userinfo(conv->account->gc, purple_conversation_get_name(conv), info, NULL, NULL); - purple_notify_user_info_destroy(info); - - serv_get_info(purple_conversation_get_gc(conv), + pidgin_retrieve_user_info(purple_conversation_get_gc(conv), purple_conversation_get_name(conv)); - gtk_widget_grab_focus(gtkconv->entry); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { /* Get info of the person currently selected in the GtkTreeView */ @@ -2228,34 +2164,18 @@ static GList *get_prpl_icon_list(PurpleAccount *account) { GList *l = NULL; - GdkPixbuf *pixbuf; - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); - const char *prpl = prpl_info->list_icon(account, NULL); - char *filename, *path; - l = g_hash_table_lookup(prpl_lists, prpl); + PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + const char *prplname = prpl_info->list_icon(account, NULL); + l = g_hash_table_lookup(prpl_lists, prplname); if (l) return l; - filename = g_strdup_printf("%s.png", prpl); - - path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", filename, NULL); - pixbuf = gdk_pixbuf_new_from_file(path, NULL); - if (pixbuf) - l = g_list_append(l, pixbuf); - g_free(path); - - path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "22", filename, NULL); - pixbuf = gdk_pixbuf_new_from_file(path, NULL); - if (pixbuf) - l = g_list_append(l, pixbuf); - g_free(path); - - path = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "48", filename, NULL); - pixbuf = gdk_pixbuf_new_from_file(path, NULL); - if (pixbuf) - l = g_list_append(l, pixbuf); - g_free(path); - - g_hash_table_insert(prpl_lists, g_strdup(prpl), l); + + l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE)); + l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM)); + l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL)); + + g_hash_table_insert(prpl_lists, g_strdup(prplname), l); return l; } @@ -2932,10 +2852,65 @@ gtk_widget_show_all(menu); } +static void +remove_from_list(GtkWidget *widget, PidginWindow *win) +{ + GList *list = g_object_get_data(G_OBJECT(win->window), "plugin-actions"); + list = g_list_remove(list, widget); + g_object_set_data(G_OBJECT(win->window), "plugin-actions", list); +} + +static void +regenerate_plugins_items(PidginWindow *win) +{ + GList *action_items; + GtkWidget *menu; + GList *list; + PidginConversation *gtkconv; + PurpleConversation *conv; + GtkWidget *item; + + if (win->window == NULL || win == hidden_convwin) + return; + + gtkconv = pidgin_conv_window_get_active_gtkconv(win); + if (gtkconv == NULL) + return; + + conv = gtkconv->active_conv; + action_items = g_object_get_data(G_OBJECT(win->window), "plugin-actions"); + + /* Remove the old menuitems */ + while (action_items) { + g_signal_handlers_disconnect_by_func(G_OBJECT(action_items->data), + G_CALLBACK(remove_from_list), win); + gtk_widget_destroy(action_items->data); + action_items = g_list_delete_link(action_items, action_items); + } + + menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options")); + + list = purple_conversation_get_extended_menu(conv); + if (list) { + action_items = g_list_prepend(NULL, (item = pidgin_separator(menu))); + g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win); + } + + for(; list; list = g_list_delete_link(list, list)) { + PurpleMenuAction *act = (PurpleMenuAction *) list->data; + item = pidgin_append_menu_action(menu, act, conv); + action_items = g_list_prepend(action_items, item); + gtk_widget_show_all(item); + g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win); + } + g_object_set_data(G_OBJECT(win->window), "plugin-actions", action_items); +} + static void menubar_activated(GtkWidget *item, gpointer data) { PidginWindow *win = data; regenerate_options_items(win); + regenerate_plugins_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. */ @@ -4135,45 +4110,17 @@ } } -static GtkWidget * -setup_chat_pane(PidginConversation *gtkconv) -{ - PurplePluginProtocolInfo *prpl_info; +static void +setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox) +{ PurpleConversation *conv = gtkconv->active_conv; - PidginChatPane *gtkchat; - PurpleConnection *gc; - GtkWidget *vpaned, *hpaned; - GtkWidget *vbox, *hbox, *frame; - GtkWidget *imhtml_sw; - GtkPolicyType imhtml_sw_hscroll; - GtkWidget *lbox; - GtkWidget *label; - GtkWidget *list; - GtkWidget *sw; - GtkListStore *ls; - GtkCellRenderer *rend; - GtkTreeViewColumn *col; - void *blist_handle = purple_blist_get_handle(); - GList *focus_chain = NULL; - int ul_width; - - gtkchat = gtkconv->u.chat; - gc = purple_conversation_get_gc(conv); - g_return_val_if_fail(gc != NULL, NULL); - g_return_val_if_fail(gc->prpl != NULL, NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); - - /* Setup the outer pane. */ - vpaned = gtk_vpaned_new(); - gtk_widget_show(vpaned); - - /* Setup the top part of the pane. */ - vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_paned_pack1(GTK_PANED(vpaned), vbox, TRUE, TRUE); - gtk_widget_show(vbox); - + PurpleConnection *gc = purple_conversation_get_gc(conv); + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) { + GtkWidget *hbox, *label; + PidginChatPane *gtkchat = gtkconv->u.chat; + hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); @@ -4194,35 +4141,19 @@ gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0); gtk_widget_show(gtkchat->topic_text); } - - /* Setup the horizontal pane. */ - hpaned = gtk_hpaned_new(); - gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); - gtk_widget_show(hpaned); - - /* Setup gtkihmtml. */ - frame = pidgin_create_imhtml(FALSE, >kconv->imhtml, NULL, &imhtml_sw); - gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); - gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), TRUE); - gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE); - gtk_widget_show(frame); - gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw), - &imhtml_sw_hscroll, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw), - imhtml_sw_hscroll, GTK_POLICY_ALWAYS); - - gtk_widget_set_size_request(gtkconv->imhtml, - purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width"), - purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height")); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate", - G_CALLBACK(size_allocate_cb), gtkconv); - - g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event", - G_CALLBACK(entry_stop_rclick_cb), NULL); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", - G_CALLBACK(refocus_entry_cb), gtkconv); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", - G_CALLBACK(refocus_entry_cb), gtkconv); +} + +static void +setup_chat_userlist(PidginConversation *gtkconv, GtkWidget *hpaned) +{ + PidginChatPane *gtkchat = gtkconv->u.chat; + GtkWidget *lbox, *sw, *list; + GtkListStore *ls; + GtkCellRenderer *rend; + GtkTreeViewColumn *col; + int ul_width; + void *blist_handle = purple_blist_get_handle(); + PurpleConversation *conv = gtkconv->active_conv; /* Build the right pane. */ lbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); @@ -4270,9 +4201,7 @@ G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv); g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv); - rend = gtk_cell_renderer_text_new(); - g_object_set(rend, "foreground-set", TRUE, "weight-set", TRUE, @@ -4303,10 +4232,72 @@ gtkchat->list = list; gtk_container_add(GTK_CONTAINER(sw), list); +} + +static GtkWidget * +setup_common_pane(PidginConversation *gtkconv) +{ + GtkWidget *paned, *vbox, *frame, *imhtml_sw; + PurpleConversation *conv = gtkconv->active_conv; + gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT); + GtkPolicyType imhtml_sw_hscroll; + + paned = gtk_vpaned_new(); + gtk_widget_show(paned); + + /* Setup the top part of the pane */ + vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE); + gtk_widget_show(vbox); + + /* Setup the gtkimhtml widget */ + frame = pidgin_create_imhtml(FALSE, >kconv->imhtml, NULL, &imhtml_sw); + if (chat) { + GtkWidget *hpaned; + + /* Add the topic */ + setup_chat_topic(gtkconv, vbox); + + /* Add the gtkimhtml frame */ + hpaned = gtk_hpaned_new(); + gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); + gtk_widget_show(hpaned); + gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE); + + /* Now add the userlist */ + setup_chat_userlist(gtkconv, hpaned); + } 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); + + gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw), + &imhtml_sw_hscroll, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw), + imhtml_sw_hscroll, GTK_POLICY_ALWAYS); + + gtk_widget_set_size_request(gtkconv->imhtml, + chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width") : + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"), + chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height") : + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height")); + + g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate", + G_CALLBACK(size_allocate_cb), gtkconv); + + g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event", + G_CALLBACK(entry_stop_rclick_cb), NULL); + g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", + G_CALLBACK(refocus_entry_cb), gtkconv); + g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", + G_CALLBACK(refocus_entry_cb), gtkconv); /* Setup the bottom half of the conversation window */ vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_paned_pack2(GTK_PANED(vpaned), vbox, FALSE, TRUE); + gtk_paned_pack2(GTK_PANED(paned), vbox, FALSE, TRUE); gtk_widget_show(vbox); gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); @@ -4322,20 +4313,15 @@ gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); gtk_widget_show(frame); - g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", - G_CALLBACK(entry_popup_menu_cb), gtkconv); - 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(conv->account)); gtk_widget_set_size_request(gtkconv->lower_hbox, -1, - purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height")); - gtkconv->entry_buffer = - gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); - g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); - g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", - G_CALLBACK(resize_imhtml_cb), gtkconv); - + chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height") : + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height")); + + g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", + G_CALLBACK(entry_popup_menu_cb), gtkconv); g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", G_CALLBACK(entry_key_press_cb), gtkconv); g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", @@ -4345,129 +4331,28 @@ g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", G_CALLBACK(size_allocate_cb), gtkconv); - default_formatize(gtkconv); - - /* - * Focus for chat windows should be as follows: - * Tab title -> chat topic -> conversation scrollback -> user list -> - * user list buttons -> entry -> buttons at bottom - */ - focus_chain = g_list_prepend(focus_chain, gtkconv->entry); - gtk_container_set_focus_chain(GTK_CONTAINER(vbox), focus_chain); - - return vpaned; -} - -static GtkWidget * -setup_im_pane(PidginConversation *gtkconv) -{ - PurpleConversation *conv = gtkconv->active_conv; - GtkWidget *frame; - GtkWidget *imhtml_sw; - GtkPolicyType imhtml_sw_hscroll; - GtkWidget *paned; - GtkWidget *vbox; - GtkWidget *vbox2; - GList *focus_chain = NULL; - - /* Setup the outer pane */ - paned = gtk_vpaned_new(); - gtk_widget_show(paned); - - /* Setup the top part of the pane */ - vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE); - gtk_widget_show(vbox); - - /* Setup the gtkimhtml widget */ - frame = pidgin_create_imhtml(FALSE, >kconv->imhtml, NULL, &imhtml_sw); - gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); - gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE); - gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); - gtk_widget_show(frame); - gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw), - &imhtml_sw_hscroll, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw), - imhtml_sw_hscroll, GTK_POLICY_ALWAYS); - - gtk_widget_set_size_request(gtkconv->imhtml, - purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"), - purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height")); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate", - G_CALLBACK(size_allocate_cb), gtkconv); - - g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event", - G_CALLBACK(entry_stop_rclick_cb), NULL); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", - G_CALLBACK(refocus_entry_cb), gtkconv); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", - G_CALLBACK(refocus_entry_cb), gtkconv); - - /* Setup the bottom half of the conversation window */ - vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_paned_pack2(GTK_PANED(paned), vbox2, FALSE, TRUE); - gtk_widget_show(vbox2); - - gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_box_pack_start(GTK_BOX(vbox2), gtkconv->lower_hbox, TRUE, TRUE, 0); - gtk_widget_show(gtkconv->lower_hbox); - - vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_box_pack_end(GTK_BOX(gtkconv->lower_hbox), vbox2, TRUE, TRUE, 0); - gtk_widget_show(vbox2); - - /* Setup the toolbar, entry widget and all signals */ - frame = pidgin_create_imhtml(TRUE, >kconv->entry, >kconv->toolbar, NULL); - gtk_box_pack_start(GTK_BOX(vbox2), frame, TRUE, TRUE, 0); - gtk_widget_show(frame); - - g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", - G_CALLBACK(entry_popup_menu_cb), gtkconv); - - 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)); - gtk_widget_set_size_request(gtkconv->lower_hbox, -1, - purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height")); gtkconv->entry_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry)); g_object_set_data(G_OBJECT(gtkconv->entry_buffer), "user_data", gtkconv); - g_signal_connect(G_OBJECT(gtkconv->entry), "key_press_event", - G_CALLBACK(entry_key_press_cb), gtkconv); - g_signal_connect_after(G_OBJECT(gtkconv->entry), "message_send", - G_CALLBACK(send_cb), gtkconv); - g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event", - G_CALLBACK(entry_stop_rclick_cb), NULL); - g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate", - G_CALLBACK(size_allocate_cb), gtkconv); - - g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", - G_CALLBACK(insert_text_cb), gtkconv); - g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range", - G_CALLBACK(delete_text_cb), gtkconv); + if (!chat) { + /* For sending typing notifications for IMs */ + g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", + G_CALLBACK(insert_text_cb), gtkconv); + g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range", + G_CALLBACK(delete_text_cb), gtkconv); + gtkconv->u.im->typing_timer = 0; + gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons"); + gtkconv->u.im->show_icon = TRUE; + } + g_signal_connect_swapped(G_OBJECT(gtkconv->entry_buffer), "changed", G_CALLBACK(resize_imhtml_cb), gtkconv); - /* had to move this after the imtoolbar is attached so that the - * signals get fired to toggle the buttons on the toolbar as well. - */ default_formatize(gtkconv); - g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear", - G_CALLBACK(clear_formatting_cb), gtkconv); - - gtkconv->u.im->animate = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons"); - gtkconv->u.im->show_icon = TRUE; - - /* - * Focus for IM windows should be as follows: - * Tab title -> conversation scrollback -> entry - */ - focus_chain = g_list_prepend(focus_chain, gtkconv->entry); - gtk_container_set_focus_chain(GTK_CONTAINER(vbox2), focus_chain); - - gtkconv->u.im->typing_timer = 0; + G_CALLBACK(clear_formatting_cb), gtkconv); + return paned; } @@ -4663,12 +4548,10 @@ if (conv_type == PURPLE_CONV_TYPE_IM) { gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); - - pane = setup_im_pane(gtkconv); } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); - pane = setup_chat_pane(gtkconv); - } + } + 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); @@ -7973,6 +7856,7 @@ generate_send_to_items(win); regenerate_options_items(win); + regenerate_plugins_items(win); pidgin_conv_switch_active_conversation(conv); @@ -8043,6 +7927,12 @@ prpl_lists = g_hash_table_new(g_str_hash, g_str_equal); } +static void +plugin_changed_cb(PurplePlugin *p, gpointer data) +{ + regenerate_plugins_items(data); +} + PidginWindow * pidgin_conv_window_new() { @@ -8117,6 +8007,13 @@ gtk_widget_show(testidea); + /* Update the plugin actions when plugins are (un)loaded */ + purple_signal_connect(purple_plugins_get_handle(), "plugin-load", + win, PURPLE_CALLBACK(plugin_changed_cb), win); + purple_signal_connect(purple_plugins_get_handle(), "plugin-unload", + win, PURPLE_CALLBACK(plugin_changed_cb), win); + + #ifdef _WIN32 g_signal_connect(G_OBJECT(win->window), "show", G_CALLBACK(winpidgin_ensure_onscreen), win->window); @@ -8156,6 +8053,7 @@ g_object_unref(G_OBJECT(win->menu.item_factory)); purple_notify_close_with_handle(win); + purple_signals_disconnect_by_handle(win); g_free(win); }
--- a/pidgin/gtkdialogs.c Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/gtkdialogs.c Mon Jun 04 06:32:21 2007 +0000 @@ -823,7 +823,7 @@ found = pidgin_dialogs_ee(username); if (!found && username != NULL && *username != '\0' && account != NULL) - serv_get_info(purple_account_get_connection(account), username); + pidgin_retrieve_user_info(purple_account_get_connection(account), username); g_free(username); }
--- a/pidgin/gtkimhtml.c Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/gtkimhtml.c Mon Jun 04 06:32:21 2007 +0000 @@ -31,6 +31,7 @@ #include "util.h" #include "gtkimhtml.h" #include "gtksourceiter.h" +#include "pidgin.h" #include <gtk/gtk.h> #include <glib/gerror.h> #include <gdk/gdkkeysyms.h> @@ -4883,3 +4884,69 @@ g_return_if_fail(imhtml != NULL); imhtml->funcs = f; } + +void gtk_imhtml_setup_entry(GtkIMHtml *imhtml, PurpleConnectionFlags flags) +{ + if (flags & PURPLE_CONNECTION_HTML) { + char color[8]; + GdkColor fg_color, bg_color; + + gtk_imhtml_set_format_functions(imhtml, GTK_IMHTML_ALL); + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold") != imhtml->edit.bold) + gtk_imhtml_toggle_bold(imhtml); + + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic") != imhtml->edit.italic) + gtk_imhtml_toggle_italic(imhtml); + + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline") != imhtml->edit.underline) + gtk_imhtml_toggle_underline(imhtml); + + gtk_imhtml_toggle_fontface(imhtml, + purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face")); + + if (!(flags & PURPLE_CONNECTION_NO_FONTSIZE)) + { + int size = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size"); + + /* 3 is the default. */ + if (size != 3) + gtk_imhtml_font_set_size(imhtml, size); + } + + if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), "") != 0) + { + gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), + &fg_color); + g_snprintf(color, sizeof(color), "#%02x%02x%02x", + fg_color.red / 256, + fg_color.green / 256, + fg_color.blue / 256); + } else + strcpy(color, ""); + + gtk_imhtml_toggle_forecolor(imhtml, color); + + if(!(flags & PURPLE_CONNECTION_NO_BGCOLOR) && + strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), "") != 0) + { + gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), + &bg_color); + g_snprintf(color, sizeof(color), "#%02x%02x%02x", + bg_color.red / 256, + bg_color.green / 256, + bg_color.blue / 256); + } else + strcpy(color, ""); + + gtk_imhtml_toggle_background(imhtml, color); + + if (flags & PURPLE_CONNECTION_FORMATTING_WBFO) + gtk_imhtml_set_whole_buffer_formatting_only(imhtml, TRUE); + else + gtk_imhtml_set_whole_buffer_formatting_only(imhtml, FALSE); + } else { + imhtml_clear_formatting(imhtml); + gtk_imhtml_set_format_functions(imhtml, 0); + } +} +
--- a/pidgin/gtkimhtml.h Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/gtkimhtml.h Mon Jun 04 06:32:21 2007 +0000 @@ -28,6 +28,8 @@ #include <gtk/gtktooltips.h> #include <gtk/gtkimage.h> +#include "connection.h" + #ifdef __cplusplus extern "C" { #endif @@ -786,6 +788,14 @@ */ char *gtk_imhtml_get_text(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *stop); +/** + * Setup formatting for an imhtml depending on the flags specified. + * + * @param imhtml The GTK+ IM/HTML. + * @param flags The connection flag which describes the allowed types of formatting. + */ +void gtk_imhtml_setup_entry(GtkIMHtml *imhtml, PurpleConnectionFlags flags); + /*@}*/ #ifdef __cplusplus
--- a/pidgin/gtkpounce.c Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/gtkpounce.c Mon Jun 04 06:32:21 2007 +0000 @@ -38,6 +38,7 @@ #include "gtkblist.h" #include "gtkdialogs.h" +#include "gtkimhtml.h" #include "gtkpounce.h" #include "pidginstock.h" #include "gtkutils.h" @@ -241,7 +242,8 @@ save_pounce_cb(GtkWidget *w, PidginPounceDialog *dialog) { const char *name; - const char *message, *command, *sound, *reason; + const char *command, *sound, *reason; + char *message; PurplePounceEvent events = PURPLE_POUNCE_NONE; PurplePounceOption options = PURPLE_POUNCE_OPTION_NONE; @@ -290,13 +292,16 @@ events |= PURPLE_POUNCE_MESSAGE_RECEIVED; /* Data fields */ - message = gtk_entry_get_text(GTK_ENTRY(dialog->send_msg_entry)); + message = gtk_imhtml_get_markup(GTK_IMHTML(dialog->send_msg_entry)); command = gtk_entry_get_text(GTK_ENTRY(dialog->exec_cmd_entry)); sound = gtk_entry_get_text(GTK_ENTRY(dialog->play_sound_entry)); reason = gtk_entry_get_text(GTK_ENTRY(dialog->popup_entry)); if (*reason == '\0') reason = NULL; - if (*message == '\0') message = NULL; + if (*message == '\0') { + g_free(message); + message = NULL; + } if (*command == '\0') command = NULL; if (*sound == '\0') sound = NULL; @@ -349,6 +354,7 @@ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->save_pounce))); update_pounces(); + g_free(message); delete_win_cb(NULL, NULL, dialog); } @@ -446,6 +452,14 @@ {"application/x-im-contact", 0, 1} }; +static void +reset_send_msg_entry(PidginPounceDialog *dialog, GtkWidget *dontcare) +{ + PurpleAccount *account = pidgin_account_option_menu_get_selected(dialog->account_menu); + gtk_imhtml_setup_entry(GTK_IMHTML(dialog->send_msg_entry), + (account && account->gc) ? account->gc->flags : PURPLE_CONNECTION_HTML); +} + void pidgin_pounce_editor_show(PurpleAccount *account, const char *name, PurplePounce *cur_pounce) @@ -462,6 +476,7 @@ GtkSizeGroup *sg; GPtrArray *sound_widgets; GPtrArray *exec_widgets; + GtkWidget *send_msg_imhtml; g_return_if_fail((cur_pounce != NULL) || (account != NULL) || @@ -653,7 +668,8 @@ dialog->play_sound = gtk_check_button_new_with_mnemonic(_("P_lay a sound")); - dialog->send_msg_entry = gtk_entry_new(); + send_msg_imhtml = pidgin_create_imhtml(TRUE, &dialog->send_msg_entry, NULL, NULL); + reset_send_msg_entry(dialog, NULL); dialog->exec_cmd_entry = gtk_entry_new(); dialog->popup_entry = gtk_entry_new(); dialog->exec_cmd_browse = gtk_button_new_with_mnemonic(_("Brows_e...")); @@ -661,7 +677,7 @@ dialog->play_sound_browse = gtk_button_new_with_mnemonic(_("Br_owse...")); dialog->play_sound_test = gtk_button_new_with_mnemonic(_("Pre_view")); - gtk_widget_set_sensitive(dialog->send_msg_entry, FALSE); + gtk_widget_set_sensitive(send_msg_imhtml, FALSE); gtk_widget_set_sensitive(dialog->exec_cmd_entry, FALSE); gtk_widget_set_sensitive(dialog->popup_entry, FALSE); gtk_widget_set_sensitive(dialog->exec_cmd_browse, FALSE); @@ -673,8 +689,6 @@ gtk_size_group_add_widget(sg, dialog->open_win); gtk_size_group_add_widget(sg, dialog->popup); gtk_size_group_add_widget(sg, dialog->popup_entry); - gtk_size_group_add_widget(sg, dialog->send_msg); - gtk_size_group_add_widget(sg, dialog->send_msg_entry); gtk_size_group_add_widget(sg, dialog->exec_cmd); gtk_size_group_add_widget(sg, dialog->exec_cmd_entry); gtk_size_group_add_widget(sg, dialog->exec_cmd_browse); @@ -689,23 +703,23 @@ GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), dialog->popup_entry, 1, 4, 1, 2, GTK_FILL, 0, 0, 0); - gtk_table_attach(GTK_TABLE(table), dialog->send_msg, 0, 1, 2, 3, + gtk_table_attach(GTK_TABLE(table), dialog->send_msg, 0, 4, 2, 3, GTK_FILL, 0, 0, 0); - gtk_table_attach(GTK_TABLE(table), dialog->send_msg_entry, 1, 4, 2, 3, + gtk_table_attach(GTK_TABLE(table), send_msg_imhtml, 0, 4, 3, 4, GTK_FILL, 0, 0, 0); - gtk_table_attach(GTK_TABLE(table), dialog->exec_cmd, 0, 1, 3, 4, + gtk_table_attach(GTK_TABLE(table), dialog->exec_cmd, 0, 1, 4, 5, GTK_FILL, 0, 0, 0); - gtk_table_attach(GTK_TABLE(table), dialog->exec_cmd_entry, 1, 2, 3, 4, + gtk_table_attach(GTK_TABLE(table), dialog->exec_cmd_entry, 1, 2, 4, 5, GTK_FILL, 0, 0, 0); - gtk_table_attach(GTK_TABLE(table), dialog->exec_cmd_browse, 2, 3, 3, 4, + gtk_table_attach(GTK_TABLE(table), dialog->exec_cmd_browse, 2, 3, 4, 5, GTK_FILL | GTK_EXPAND, 0, 0, 0); - gtk_table_attach(GTK_TABLE(table), dialog->play_sound, 0, 1, 4, 5, + gtk_table_attach(GTK_TABLE(table), dialog->play_sound, 0, 1, 5, 6, GTK_FILL, 0, 0, 0); - gtk_table_attach(GTK_TABLE(table), dialog->play_sound_entry, 1, 2, 4, 5, + gtk_table_attach(GTK_TABLE(table), dialog->play_sound_entry, 1, 2, 5, 6, GTK_FILL, 0, 0, 0); - gtk_table_attach(GTK_TABLE(table), dialog->play_sound_browse, 2, 3, 4, 5, + gtk_table_attach(GTK_TABLE(table), dialog->play_sound_browse,2, 3, 5, 6, GTK_FILL | GTK_EXPAND, 0, 0, 0); - gtk_table_attach(GTK_TABLE(table), dialog->play_sound_test, 3, 4, 4, 5, + gtk_table_attach(GTK_TABLE(table), dialog->play_sound_test, 3, 4, 5, 6, GTK_FILL | GTK_EXPAND, 0, 0, 0); gtk_table_set_row_spacings(GTK_TABLE(table), PIDGIN_HIG_BOX_SPACE / 2); @@ -714,7 +728,7 @@ gtk_widget_show(dialog->popup); gtk_widget_show(dialog->popup_entry); gtk_widget_show(dialog->send_msg); - gtk_widget_show(dialog->send_msg_entry); + gtk_widget_show(send_msg_imhtml); gtk_widget_show(dialog->exec_cmd); gtk_widget_show(dialog->exec_cmd_entry); gtk_widget_show(dialog->exec_cmd_browse); @@ -729,7 +743,7 @@ g_signal_connect(G_OBJECT(dialog->send_msg), "clicked", G_CALLBACK(pidgin_toggle_sensitive), - dialog->send_msg_entry); + send_msg_imhtml); g_signal_connect(G_OBJECT(dialog->popup), "clicked", G_CALLBACK(pidgin_toggle_sensitive), @@ -765,7 +779,12 @@ g_object_set_data_full(G_OBJECT(dialog->window), "sound-widgets", sound_widgets, (GDestroyNotify)g_ptr_array_free); - g_signal_connect(G_OBJECT(dialog->send_msg_entry), "activate", + g_signal_connect_swapped(G_OBJECT(dialog->send_msg_entry), "format_function_clear", + G_CALLBACK(reset_send_msg_entry), dialog); + g_signal_connect_swapped(G_OBJECT(dialog->account_menu), "changed", + G_CALLBACK(reset_send_msg_entry), dialog); + + g_signal_connect(G_OBJECT(dialog->send_msg_entry), "message_send", G_CALLBACK(save_pounce_cb), dialog); g_signal_connect(G_OBJECT(dialog->popup_entry), "activate", G_CALLBACK(save_pounce_cb), dialog); @@ -892,7 +911,7 @@ "send-message", "message")) != NULL) { - gtk_entry_set_text(GTK_ENTRY(dialog->send_msg_entry), value); + gtk_imhtml_append_text(GTK_IMHTML(dialog->send_msg_entry), value, 0); } if ((value = purple_pounce_action_get_attribute(cur_pounce,
--- a/pidgin/gtkprefs.c Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/gtkprefs.c Mon Jun 04 06:32:21 2007 +0000 @@ -979,17 +979,7 @@ gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold")) - gtk_imhtml_toggle_bold(GTK_IMHTML(imhtml)); - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic")) - gtk_imhtml_toggle_italic(GTK_IMHTML(imhtml)); - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline")) - gtk_imhtml_toggle_underline(GTK_IMHTML(imhtml)); - - gtk_imhtml_font_set_size(GTK_IMHTML(imhtml), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size")); - gtk_imhtml_toggle_forecolor(GTK_IMHTML(imhtml), purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor")); - gtk_imhtml_toggle_background(GTK_IMHTML(imhtml), purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor")); - gtk_imhtml_toggle_fontface(GTK_IMHTML(imhtml), purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face")); + gtk_imhtml_setup_entry(GTK_IMHTML(imhtml), PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO); g_signal_connect_after(G_OBJECT(imhtml), "format_function_toggle", G_CALLBACK(formatting_toggle_cb), toolbar);
--- a/pidgin/gtkutils.c Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/gtkutils.c Mon Jun 04 06:32:21 2007 +0000 @@ -245,13 +245,14 @@ gtk_widget_show(to_toggle); } -void pidgin_separator(GtkWidget *menu) +GtkWidget *pidgin_separator(GtkWidget *menu) { GtkWidget *menuitem; menuitem = gtk_separator_menu_item_new(); gtk_widget_show(menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + return menuitem; } GtkWidget *pidgin_new_item(GtkWidget *menu, const char *str) @@ -462,7 +463,7 @@ } static GtkWidget * -aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data) +aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data, const char *data) { GtkWidget *item; GtkWidget *hbox; @@ -495,6 +496,7 @@ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); + g_object_set_data(G_OBJECT (item), data, per_item_data); g_object_set_data(G_OBJECT (item), "aop_per_item_data", per_item_data); pidgin_set_accessible_label(item, label); @@ -502,6 +504,39 @@ return item; } +static GdkPixbuf * +pidgin_create_prpl_icon_from_prpl(PurplePlugin *prpl, PidginPrplIconSize size, PurpleAccount *account) +{ + PurplePluginProtocolInfo *prpl_info; + const char *protoname = NULL; + char buf[MAXPATHLEN]; + char *filename = NULL; + GdkPixbuf *pixbuf; + + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + if (prpl_info->list_icon == NULL) + return NULL; + + protoname = prpl_info->list_icon(account, NULL); + if (protoname == NULL) + return NULL; + + /* + * Status icons will be themeable too, and then it will look up + * protoname from the theme + */ + g_snprintf(buf, sizeof(buf), "%s.png", protoname); + + filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", + size == PIDGIN_PRPL_ICON_SMALL ? "16" : + size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48", + buf, NULL); + pixbuf = gdk_pixbuf_new_from_file(filename, NULL); + g_free(filename); + + return pixbuf; +} + static GtkWidget * aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data) { @@ -552,25 +587,6 @@ } } -static GdkPixbuf * -get_prpl_pixbuf(PurplePluginProtocolInfo *prpl_info) -{ - const char *proto_name; - GdkPixbuf *pixbuf = NULL; - char *filename; - char buf[256]; - - proto_name = prpl_info->list_icon(NULL, NULL); - g_return_val_if_fail(proto_name != NULL, NULL); - - g_snprintf(buf, sizeof(buf), "%s.png", proto_name); - filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", buf, NULL); - pixbuf = gdk_pixbuf_new_from_file(filename, NULL); - g_free(filename); - - return pixbuf; -} - static AopMenu * create_protocols_menu(const char *default_proto_id) { @@ -602,11 +618,14 @@ if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) { char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", "google-talk.png", NULL); + GtkWidget *item; + pixbuf = gdk_pixbuf_new_from_file(filename, NULL); g_free(filename); gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), - aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber")); + item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol")); + g_object_set_data(G_OBJECT(item), "fake", GINT_TO_POINTER(1)); if (pixbuf) g_object_unref(pixbuf); @@ -615,10 +634,10 @@ i++; } - pixbuf = get_prpl_pixbuf(prpl_info); + pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), - aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id)); + aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id, "protocol")); if (pixbuf) g_object_unref(pixbuf); @@ -670,7 +689,6 @@ sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); for (p = list, i = 0; p != NULL; p = p->next, i++) { - PurplePluginProtocolInfo *prpl_info = NULL; PurplePlugin *plugin; if (show_all) @@ -688,18 +706,12 @@ plugin = purple_find_prpl(purple_account_get_protocol_id(account)); - if (plugin) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - - /* Load the image. */ - if (prpl_info) { - pixbuf = get_prpl_pixbuf(prpl_info); - - if (pixbuf) { - if (purple_account_is_disconnected(account) && show_all && - purple_connections_get_all()) - gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); - } + pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + + if (pixbuf) { + if (purple_account_is_disconnected(account) && show_all && + purple_connections_get_all()) + gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); } if (purple_account_get_alias(account)) { @@ -714,7 +726,7 @@ } gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), - aop_menu_item_new(sg, pixbuf, buf, account)); + aop_menu_item_new(sg, pixbuf, buf, account, "account")); if (pixbuf) g_object_unref(pixbuf); @@ -883,6 +895,15 @@ g_free(filename); } +void pidgin_retrieve_user_info(PurpleConnection *conn, const char *name) +{ + PurpleNotifyUserInfo *info = purple_notify_user_info_new(); + purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); + purple_notify_userinfo(conn, name, info, NULL, NULL); + purple_notify_user_info_destroy(info); + serv_get_info(conn, name); +} + gboolean pidgin_parse_x_im_contact(const char *msg, gboolean all_accounts, PurpleAccount **ret_account, char **ret_protocol, @@ -1583,40 +1604,13 @@ pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size) { PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; - const char *protoname = NULL; - char buf[256]; /* TODO: We should use a define for max file length */ - char *filename = NULL; - GdkPixbuf *pixbuf; g_return_val_if_fail(account != NULL, NULL); prpl = purple_find_prpl(purple_account_get_protocol_id(account)); if (prpl == NULL) return NULL; - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info->list_icon == NULL) - return NULL; - - protoname = prpl_info->list_icon(account, NULL); - if (protoname == NULL) - return NULL; - - /* - * Status icons will be themeable too, and then it will look up - * protoname from the theme - */ - g_snprintf(buf, sizeof(buf), "%s.png", protoname); - - filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", - size == PIDGIN_PRPL_ICON_SMALL ? "16" : - size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48", - buf, NULL); - pixbuf = gdk_pixbuf_new_from_file(filename, NULL); - g_free(filename); - - return pixbuf; + return pidgin_create_prpl_icon_from_prpl(prpl, size, account); } static void @@ -1632,62 +1626,63 @@ callback(object, data); } -void +GtkWidget * pidgin_append_menu_action(GtkWidget *menu, PurpleMenuAction *act, gpointer object) { + GtkWidget *menuitem; + if (act == NULL) { - pidgin_separator(menu); - } else { - GtkWidget *menuitem; - - if (act->children == NULL) { - menuitem = gtk_menu_item_new_with_mnemonic(act->label); - - if (act->callback != NULL) { - g_object_set_data(G_OBJECT(menuitem), - "purplecallback", - act->callback); - g_object_set_data(G_OBJECT(menuitem), - "purplecallbackdata", - act->data); - g_signal_connect(G_OBJECT(menuitem), "activate", - G_CALLBACK(menu_action_cb), - object); - } else { - gtk_widget_set_sensitive(menuitem, FALSE); - } - - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + return pidgin_separator(menu); + } + + if (act->children == NULL) { + menuitem = gtk_menu_item_new_with_mnemonic(act->label); + + if (act->callback != NULL) { + g_object_set_data(G_OBJECT(menuitem), + "purplecallback", + act->callback); + g_object_set_data(G_OBJECT(menuitem), + "purplecallbackdata", + act->data); + g_signal_connect(G_OBJECT(menuitem), "activate", + G_CALLBACK(menu_action_cb), + object); } else { - GList *l = NULL; - GtkWidget *submenu = NULL; - GtkAccelGroup *group; - - menuitem = gtk_menu_item_new_with_mnemonic(act->label); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - - submenu = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); - - group = gtk_menu_get_accel_group(GTK_MENU(menu)); - if (group) { - char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label); - gtk_menu_set_accel_path(GTK_MENU(submenu), path); - g_free(path); - gtk_menu_set_accel_group(GTK_MENU(submenu), group); - } - - for (l = act->children; l; l = l->next) { - PurpleMenuAction *act = (PurpleMenuAction *)l->data; - - pidgin_append_menu_action(submenu, act, object); - } - g_list_free(act->children); - act->children = NULL; + gtk_widget_set_sensitive(menuitem, FALSE); } - purple_menu_action_free(act); + + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } else { + GList *l = NULL; + GtkWidget *submenu = NULL; + GtkAccelGroup *group; + + menuitem = gtk_menu_item_new_with_mnemonic(act->label); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + + submenu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); + + group = gtk_menu_get_accel_group(GTK_MENU(menu)); + if (group) { + char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label); + gtk_menu_set_accel_path(GTK_MENU(submenu), path); + g_free(path); + gtk_menu_set_accel_group(GTK_MENU(submenu), group); + } + + for (l = act->children; l; l = l->next) { + PurpleMenuAction *act = (PurpleMenuAction *)l->data; + + pidgin_append_menu_action(submenu, act, object); + } + g_list_free(act->children); + act->children = NULL; } + purple_menu_action_free(act); + return menuitem; } #if GTK_CHECK_VERSION(2,3,0)
--- a/pidgin/gtkutils.h Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/gtkutils.h Mon Jun 04 06:32:21 2007 +0000 @@ -130,8 +130,10 @@ * Adds a separator to a menu. * * @param menu The menu to add a separator to. + * + * @return The separator. */ -void pidgin_separator(GtkWidget *menu); +GtkWidget *pidgin_separator(GtkWidget *menu); /** * Creates a menu item. @@ -307,6 +309,14 @@ void pidgin_load_accels(void); /** + * Get information about a user. Show immediate feedback. + * + * @param conn The connection to get information from. + * @param name The user to get information about. + */ +void pidgin_retrieve_user_info(PurpleConnection *conn, const char *name); + +/** * Parses an application/x-im-contact MIME message and returns the * data inside. * @@ -404,8 +414,10 @@ * @param menu The menu to append to. * @param act The PurpleMenuAction to append. * @param gobject The object to be passed to the action callback. + * + * @return The menuitem added. */ -void pidgin_append_menu_action(GtkWidget *menu, PurpleMenuAction *act, +GtkWidget *pidgin_append_menu_action(GtkWidget *menu, PurpleMenuAction *act, gpointer gobject); /**
--- a/pidgin/plugins/cap/cap.c Mon Jun 04 06:15:43 2007 +0000 +++ b/pidgin/plugins/cap/cap.c Mon Jun 04 06:32:21 2007 +0000 @@ -918,7 +918,8 @@ static PidginPluginUiInfo ui_info = { get_config_frame, - 0 /* page_num (reserved) */ + 0 /* page_num (reserved) */, + NULL,NULL,NULL,NULL }; static PurplePluginInfo info = { @@ -944,7 +945,8 @@ &ui_info, /**< ui_info */ NULL, /**< extra_info */ NULL, /**< prefs_info */ - NULL + NULL, + NULL,NULL,NULL,NULL }; static GtkWidget * get_config_frame(PurplePlugin *plugin) {