Mercurial > pidgin
changeset 18043:6b7b13adb9b1
propagate from branch 'im.pidgin.pidgin' (head ac83216c7b78e652b47f1fd0bcb91f1eaf2cdf36)
to branch 'im.pidgin.pidgin.2.1.0' (head 30a48520e9bc26b0d3914edad456b063cd6cf9fe)
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Mon, 04 Jun 2007 23:48:54 +0000 |
parents | ee9f7ee0be66 (current diff) 38a72d6dce7f (diff) |
children | 37469ac119b6 58e28ccf08e6 |
files | COPYRIGHT ChangeLog ChangeLog.API libpurple/blist.c libpurple/conversation.c libpurple/conversation.h libpurple/idle.c libpurple/protocols/silc/silc.c libpurple/purple-remote libpurple/util.c pidgin/gtkaccount.c pidgin/gtkblist.c pidgin/gtkconv.c pidgin/gtkimhtml.c pidgin/gtkimhtml.h pidgin/gtkpounce.c pidgin/gtkprefs.c pidgin/gtkutils.c pidgin/gtkutils.h |
diffstat | 56 files changed, 1246 insertions(+), 776 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Sun Jun 03 23:11:57 2007 +0000 +++ b/COPYRIGHT Mon Jun 04 23:48:54 2007 +0000 @@ -8,6 +8,7 @@ Dave Ahlswede Manuel Amador Matt Amato +Elliott Sales de Andrade Geoffrey Antos Daniel Atallah Paul Aurich
--- a/ChangeLog Sun Jun 03 23:11:57 2007 +0000 +++ b/ChangeLog Mon Jun 04 23:48:54 2007 +0000 @@ -19,12 +19,16 @@ version 2.0.2 (??/??/????): Pidgin: * Added a custom conversation font option to preferences + * Fixed smiley ordering in the insert smiley popup to be more intuitive libpurple: * Moving an ICQ buddy from one group to another no longer re-requests authorization from that person (Rene Hausleitner) * Added nullprpl, an example protocol plugin (Ryan Barrett) * Fixed SOCKS5 bug which caused Jabber file receiving to fail + * Remove MSN's random "Authorization Failed" dialogs + * Fix MSN to correctly detect incorrect passwords and disable the account + * Get User Info on MSN is now more reliable & accurate Finch: * Auto account reconnecting
--- a/ChangeLog.API Sun Jun 03 23:11:57 2007 +0000 +++ b/ChangeLog.API Mon Jun 04 23:48:54 2007 +0000 @@ -18,6 +18,23 @@ * purple_timeout_add_seconds() Callers should prefer this to purple_timeout_add() for timers longer than 1 second away. Be aware of the rounding, though. + * 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
--- a/doc/conversation-signals.dox Sun Jun 03 23:11:57 2007 +0000 +++ b/doc/conversation-signals.dox Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/gntaccount.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/gntblist.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/gntblist.h Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/gntconv.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/gntnotify.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/libgnt/gntbox.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/libgnt/gntkeys.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/libgnt/gntkeys.h Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/libgnt/gntmain.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/libgnt/gntwm.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/finch/libgnt/wms/Makefile.am Mon Jun 04 23:48:54 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 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/Makefile.am Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/blist.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/blist.h Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/conversation.c Mon Jun 04 23:48:54 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" @@ -1999,6 +2000,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) { @@ -2262,6 +2286,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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/conversation.h Mon Jun 04 23:48:54 2007 +0000 @@ -1192,6 +1192,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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/ft.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/ft.h Mon Jun 04 23:48:54 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/idle.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/idle.c Mon Jun 04 23:48:54 2007 +0000 @@ -121,7 +121,7 @@ gboolean report_idle; GList *l; gint away_seconds = 0; - gint idle_recheck_interval; + gint idle_recheck_interval = 0; purple_signal_emit(purple_blist_get_handle(), "update-idle");
--- a/libpurple/imgstore.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/imgstore.c Mon Jun 04 23:48:54 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/joinpart.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/plugins/joinpart.c Mon Jun 04 23:48:54 2007 +0000 @@ -210,7 +210,7 @@ * we don't have to worry one will be called after this. */ g_hash_table_destroy((GHashTable *)data[0]); - g_source_remove(GPOINTER_TO_UINT(data[1])); + purple_timeout_remove(GPOINTER_TO_UINT(data[1])); g_free(data); return TRUE;
--- a/libpurple/plugins/log_reader.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/plugins/log_reader.c Mon Jun 04 23:48:54 2007 +0000 @@ -1482,46 +1482,66 @@ * "> * Then, replace the next " " (or add this if the end-of-line is reached) with: * </a> + * + * As implemented, this isn't perfect, but it should cover common cases. */ link_temp_line = NULL; - while ((link = g_strstr_len(line, strlen(line), "(Link: "))) { - GString *temp; + while ((link = strstr(line, "(Link: "))) + { + char *tmp = link; - if (!*link) - continue; + link += 7; + if (*link) + { + char *end_paren; + char *space; + GString *temp; - *link = '\0'; - link++; + if (!(end_paren = strstr(link, ")"))) + { + /* Something is not as we expect. Bail out. */ + break; + } - temp = g_string_new(line); - g_string_append(temp, "<a href=\""); + *tmp = '\0'; + temp = g_string_new(line); + + /* Start an <a> tag. */ + g_string_append(temp, "<a href=\""); + + /* Append up to the ) */ + g_string_append_len(temp, link, end_paren - link); - if (strlen(link) >= 6) { - link += (sizeof("(Link: ") - 1); + /* Finish the <a> tag. */ + g_string_append(temp, "\">"); + + /* The \r is a bit of a hack to keep there from being a \r in + * the link text, which may not matter. */ + if ((space = strstr(end_paren, " ")) || (space = strstr(end_paren, "\r"))) + { + g_string_append_len(temp, end_paren + 1, space - end_paren - 1); - while (*link && *link != ')') { - g_string_append_c(temp, *link); - link++; + /* Close the <a> tag. */ + g_string_append(temp, "</a>"); + + space++; + if (*space) + { + g_string_append_c(temp, ' '); + /* Keep the rest of the line. */ + g_string_append(temp, space); + } } - if (link) { - link++; - - g_string_append(temp, "\">"); - while (*link && *link != ' ') { - g_string_append_c(temp, *link); - link++; - } + else + { + /* There is no space before the end of the line. */ + g_string_append(temp, end_paren + 1); + /* Close the <a> tag. */ g_string_append(temp, "</a>"); } - g_string_append(temp, link); - - /* Free the last round's line. */ - if (link_temp_line) - g_free(line); - - line = temp->str; - g_string_free(temp, FALSE); + g_free(link_temp_line); + line = g_string_free(temp, FALSE); /* Save this memory location so we can free it later. */ link_temp_line = line; @@ -1661,8 +1681,7 @@ g_string_append_c(formatted, '\n'); - if (link_temp_line) - g_free(link_temp_line); + g_free(link_temp_line); c++; line = c;
--- a/libpurple/plugins/perl/common/Account.xs Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/plugins/perl/common/Account.xs Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/plugins/perl/common/BuddyList.xs Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/plugins/perl/common/Conversation.xs Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/plugins/perl/common/Prefs.xs Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/plugins/perl/common/module.h Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/plugins/perl/common/typemap Mon Jun 04 23:48:54 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/libpurple/plugins/perl/perl-handlers.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/plugins/perl/perl-handlers.c Mon Jun 04 23:48:54 2007 +0000 @@ -184,7 +184,7 @@ timeout_handlers = g_list_remove(timeout_handlers, handler); if (handler->iotag > 0) - g_source_remove(handler->iotag); + purple_timeout_remove(handler->iotag); if (handler->callback != NULL) SvREFCNT_dec(handler->callback); @@ -405,7 +405,7 @@ timeout_handlers = g_list_append(timeout_handlers, handler); - handler->iotag = g_timeout_add(seconds * 1000, perl_timeout_cb, handler); + handler->iotag = purple_timeout_add(seconds * 1000, perl_timeout_cb, handler); } void
--- a/libpurple/protocols/oscar/flap_connection.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Mon Jun 04 23:48:54 2007 +0000 @@ -303,7 +303,7 @@ } } - if (conn->fd != -1) + if (conn->fd >= 0) { if (conn->type == SNAC_FAMILY_LOCATE) flap_connection_send_close(od, conn); @@ -792,7 +792,7 @@ } /* If there was an error then close the connection */ - if (read == -1) + if (read < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) /* No worries */ @@ -853,7 +853,7 @@ break; } - if (read == -1) + if (read < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) /* No worries */ @@ -902,7 +902,7 @@ ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); if (ret <= 0) { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + if (ret < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) /* No worries */ return; @@ -936,7 +936,7 @@ purple_circ_buffer_append(conn->buffer_outgoing, bs->data, count); /* If we haven't already started writing stuff, then start the cycle */ - if ((conn->watcher_outgoing == 0) && (conn->fd != -1)) + if ((conn->watcher_outgoing == 0) && (conn->fd >= 0)) { conn->watcher_outgoing = purple_input_add(conn->fd, PURPLE_INPUT_WRITE, send_cb, conn);
--- a/libpurple/protocols/oscar/odc.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/protocols/oscar/odc.c Mon Jun 04 23:48:54 2007 +0000 @@ -447,7 +447,7 @@ return; } - if (read == -1) + if (read < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) /* No worries */
--- a/libpurple/protocols/oscar/oscar.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Mon Jun 04 23:48:54 2007 +0000 @@ -1604,8 +1604,7 @@ straight_to_hell, pos) == NULL) { char buf[256]; - if (pos->modname) - g_free(pos->modname); + g_free(pos->modname); g_free(pos); g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. " "Check %s for updates."), PURPLE_WEBSITE);
--- a/libpurple/protocols/oscar/peer.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/protocols/oscar/peer.c Mon Jun 04 23:48:54 2007 +0000 @@ -173,12 +173,12 @@ purple_input_remove(conn->watcher_outgoing); conn->watcher_outgoing = 0; } - if (conn->listenerfd != -1) + if (conn->listenerfd >= 0) { close(conn->listenerfd); conn->listenerfd = -1; } - if (conn->fd != -1) + if (conn->fd >= 0) { close(conn->fd); conn->fd = -1; @@ -310,7 +310,7 @@ } /* If there was an error then close the connection */ - if (read == -1) + if (read < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) /* No worries */ @@ -360,7 +360,7 @@ return; } - if (read == -1) + if (read < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) /* No worries */ @@ -422,7 +422,7 @@ wrotelen = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); if (wrotelen <= 0) { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + if (wrotelen < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) /* No worries */ return; @@ -462,7 +462,7 @@ purple_circ_buffer_append(conn->buffer_outgoing, bs->data, bs->len); /* If we haven't already started writing stuff, then start the cycle */ - if ((conn->watcher_outgoing == 0) && (conn->fd != -1)) + if ((conn->watcher_outgoing == 0) && (conn->fd >= 0)) { conn->watcher_outgoing = purple_input_add(conn->fd, PURPLE_INPUT_WRITE, send_cb, conn); @@ -596,7 +596,7 @@ purple_debug_info("oscar", "Accepting connection on listener socket.\n"); conn->fd = accept(conn->listenerfd, &addr, &addrlen); - if (conn->fd == -1) + if (conn->fd < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) /* No connection yet--no worries */ @@ -640,7 +640,7 @@ conn = data; conn->listen_data = NULL; - if (listenerfd == -1) + if (listenerfd < 0) { /* Could not open listener socket */ peer_connection_trynext(conn);
--- a/libpurple/protocols/oscar/peer_proxy.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/protocols/oscar/peer_proxy.c Mon Jun 04 23:48:54 2007 +0000 @@ -224,7 +224,7 @@ } /* If there was an error then close the connection */ - if (read == -1) + if (read < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) /* No worries */ @@ -285,7 +285,8 @@ return; } - if (read == -1) + /* If there was an error then close the connection */ + if (read < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) /* No worries */
--- a/libpurple/protocols/silc/silc.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/protocols/silc/silc.c Mon Jun 04 23:48:54 2007 +0000 @@ -119,12 +119,12 @@ NULL, 0); } -static int +static gboolean silcpurple_scheduler(gpointer *context) { SilcPurple sg = (SilcPurple)context; silc_client_run_one(sg->client); - return 1; + return TRUE; } static void @@ -361,11 +361,7 @@ } /* Schedule SILC using Glib's event loop */ -#ifndef _WIN32 - sg->scheduler = g_timeout_add(5, (GSourceFunc)silcpurple_scheduler, sg); -#else - sg->scheduler = g_timeout_add(300, (GSourceFunc)silcpurple_scheduler, sg); -#endif + sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, sg); } static int @@ -396,8 +392,8 @@ if (sg->conn) silc_client_close_connection(sg->client, sg->conn); - g_source_remove(sg->scheduler); - g_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg); + purple_timeout_remove(sg->scheduler); + purple_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg); }
--- a/libpurple/protocols/yahoo/yahoo.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Mon Jun 04 23:48:54 2007 +0000 @@ -2310,7 +2310,7 @@ * are you trying to pull? */ guchar *start; - purple_debug_warning("yahoo", "Error in YMSG stream, got something not a YMSG packet!"); + purple_debug_warning("yahoo", "Error in YMSG stream, got something not a YMSG packet!\n"); start = memchr(yd->rxqueue + 1, 'Y', yd->rxlen - 1); if (start) { @@ -2377,7 +2377,11 @@ } if (source < 0) { - purple_connection_error(gc, _("Unable to connect.")); + gchar *tmp; + tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"), + error_message); + purple_connection_error(gc, tmp); + g_free(tmp); return; } @@ -2405,7 +2409,11 @@ } if (source < 0) { - purple_connection_error(gc, _("Unable to connect.")); + gchar *tmp; + tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"), + error_message); + purple_connection_error(gc, tmp); + g_free(tmp); return; } @@ -2507,12 +2515,16 @@ if (written < 0 && errno == EAGAIN) written = 0; else if (written <= 0) { + gchar *tmp; g_free(yd->auth); yd->auth = NULL; if (gc->inpa) purple_input_remove(gc->inpa); gc->inpa = 0; - purple_connection_error(gc, _("Unable to connect.")); + tmp = g_strdup_printf(_("Lost connection with %s:\n%s"), + "login.yahoo.com:80", strerror(errno)); + purple_connection_error(gc, tmp); + g_free(tmp); return; } @@ -2533,7 +2545,11 @@ PurpleConnection *gc = data; if (source < 0) { - purple_connection_error(gc, _("Unable to connect.")); + gchar *tmp; + tmp = g_strdup_printf(_("Could not establish a connection with %s:\n%s"), + "login.yahoo.com:80", error_message); + purple_connection_error(gc, tmp); + g_free(tmp); return; } @@ -2616,8 +2632,7 @@ if (error_message != NULL) { - /* TODO: Include error_message in the message below */ - purple_connection_error(gc, _("Unable to connect.")); + purple_connection_error(gc, error_message); return; }
--- a/libpurple/purple-remote Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/purple-remote Mon Jun 04 23:48:54 2007 +0000 @@ -31,7 +31,7 @@ return result def show_help(): - print """This program uses DBus to communicate with purple. + print """This program uses D-Bus to communicate with purple. Usage: @@ -96,8 +96,6 @@ protocol = match.group(2) if protocol == "xmpp": protocol = "jabber" - if protocol == "aim" or protocol == "icq": - protocol = "oscar" if protocol is not None: protocol = "prpl-" + protocol command = match.group(5)
--- a/libpurple/util.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/util.c Mon Jun 04 23:48:54 2007 +0000 @@ -46,6 +46,7 @@ } website; char *url; + int num_times_redirected; gboolean full; char *user_agent; gboolean http11; @@ -1284,14 +1285,17 @@ pt->dest_tag = y; \ tags = g_list_prepend(tags, pt); \ } \ - xhtml = g_string_append(xhtml, "<" y); \ - c += strlen("<" x ); \ - xhtml = g_string_append(xhtml, innards->str); \ - xhtml = g_string_append_c(xhtml, '>'); \ + if(xhtml) { \ + xhtml = g_string_append(xhtml, "<" y); \ + xhtml = g_string_append(xhtml, innards->str); \ + xhtml = g_string_append_c(xhtml, '>'); \ + } \ c = p + 1; \ } else { \ - xhtml = g_string_append(xhtml, "<"); \ - plain = g_string_append_c(plain, '<'); \ + if(xhtml) \ + xhtml = g_string_append(xhtml, "<"); \ + if(plain) \ + plain = g_string_append_c(plain, '<'); \ c++; \ } \ g_string_free(innards, TRUE); \ @@ -1300,16 +1304,19 @@ if(!g_ascii_strncasecmp(c, "<" x, strlen("<" x)) && \ (*(c+strlen("<" x)) == '>' || \ !g_ascii_strncasecmp(c+strlen("<" x), "/>", 2))) { \ - xhtml = g_string_append(xhtml, "<" y); \ + if(xhtml) \ + xhtml = g_string_append(xhtml, "<" y); \ c += strlen("<" x); \ if(*c != '/') { \ struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); \ pt->src_tag = x; \ pt->dest_tag = y; \ tags = g_list_prepend(tags, pt); \ - xhtml = g_string_append_c(xhtml, '>'); \ + if(xhtml) \ + xhtml = g_string_append_c(xhtml, '>'); \ } else { \ - xhtml = g_string_append(xhtml, "/>");\ + if(xhtml) \ + xhtml = g_string_append(xhtml, "/>");\ } \ c = strchr(c, '>') + 1; \ continue; \ @@ -1319,11 +1326,18 @@ purple_markup_html_to_xhtml(const char *html, char **xhtml_out, char **plain_out) { - GString *xhtml = g_string_new(""); - GString *plain = g_string_new(""); + GString *xhtml = NULL; + GString *plain = NULL; GList *tags = NULL, *tag; const char *c = html; + g_return_if_fail(xhtml_out != NULL || plain_out != NULL); + + if(xhtml_out) + xhtml = g_string_new(""); + if(plain_out) + plain = g_string_new(""); + while(c && *c) { if(*c == '<') { if(*(c+1) == '/') { /* closing tag */ @@ -1339,7 +1353,8 @@ if(tag) { while(tags) { struct purple_parse_tag *pt = tags->data; - g_string_append_printf(xhtml, "</%s>", pt->dest_tag); + if(xhtml) + g_string_append_printf(xhtml, "</%s>", pt->dest_tag); if(tags == tag) break; tags = g_list_remove(tags, pt); @@ -1357,8 +1372,10 @@ if(*end == '>') { c = end+1; } else { - xhtml = g_string_append(xhtml, "<"); - plain = g_string_append_c(plain, '<'); + if(xhtml) + xhtml = g_string_append(xhtml, "<"); + if(plain) + plain = g_string_append_c(plain, '<'); c++; } } @@ -1387,7 +1404,8 @@ ALLOW_TAG("span"); ALLOW_TAG("strong"); ALLOW_TAG("ul"); - + ALLOW_TAG("img"); + /* we skip <HR> because it's not legal in XHTML-IM. However, * we still want to send something sensible, so we put a * linebreak in its place. <BR> also needs special handling @@ -1398,8 +1416,9 @@ !g_ascii_strncasecmp(c+3, "/>", 2) || !g_ascii_strncasecmp(c+3, " />", 3))) { c = strchr(c, '>') + 1; - xhtml = g_string_append(xhtml, "<br/>"); - if(*c != '\n') + if(xhtml) + xhtml = g_string_append(xhtml, "<br/>"); + if(plain && *c != '\n') plain = g_string_append_c(plain, '\n'); continue; } @@ -1409,7 +1428,8 @@ pt->dest_tag = "span"; tags = g_list_prepend(tags, pt); c = strchr(c, '>') + 1; - xhtml = g_string_append(xhtml, "<span style='font-weight: bold;'>"); + if(xhtml) + xhtml = g_string_append(xhtml, "<span style='font-weight: bold;'>"); continue; } if(!g_ascii_strncasecmp(c, "<u>", 3) || !g_ascii_strncasecmp(c, "<underline>", strlen("<underline>"))) { @@ -1418,7 +1438,8 @@ pt->dest_tag = "span"; tags = g_list_prepend(tags, pt); c = strchr(c, '>') + 1; - xhtml = g_string_append(xhtml, "<span style='text-decoration: underline;'>"); + if (xhtml) + xhtml = g_string_append(xhtml, "<span style='text-decoration: underline;'>"); continue; } if(!g_ascii_strncasecmp(c, "<s>", 3) || !g_ascii_strncasecmp(c, "<strike>", strlen("<strike>"))) { @@ -1427,7 +1448,8 @@ pt->dest_tag = "span"; tags = g_list_prepend(tags, pt); c = strchr(c, '>') + 1; - xhtml = g_string_append(xhtml, "<span style='text-decoration: line-through;'>"); + if(xhtml) + xhtml = g_string_append(xhtml, "<span style='text-decoration: line-through;'>"); continue; } if(!g_ascii_strncasecmp(c, "<sub>", 5)) { @@ -1436,7 +1458,8 @@ pt->dest_tag = "span"; tags = g_list_prepend(tags, pt); c = strchr(c, '>') + 1; - xhtml = g_string_append(xhtml, "<span style='vertical-align:sub;'>"); + if(xhtml) + xhtml = g_string_append(xhtml, "<span style='vertical-align:sub;'>"); continue; } if(!g_ascii_strncasecmp(c, "<sup>", 5)) { @@ -1445,7 +1468,8 @@ pt->dest_tag = "span"; tags = g_list_prepend(tags, pt); c = strchr(c, '>') + 1; - xhtml = g_string_append(xhtml, "<span style='vertical-align:super;'>"); + if(xhtml) + xhtml = g_string_append(xhtml, "<span style='vertical-align:super;'>"); continue; } if(!g_ascii_strncasecmp(c, "<font", 5) && (*(c+5) == '>' || *(c+5) == ' ')) { @@ -1539,7 +1563,10 @@ pt->dest_tag = "span"; tags = g_list_prepend(tags, pt); if(style->len) - g_string_append_printf(xhtml, "<span style='%s'>", g_strstrip(style->str)); + { + if(xhtml) + g_string_append_printf(xhtml, "<span style='%s'>", g_strstrip(style->str)); + } else pt->ignore = TRUE; g_string_free(style, TRUE); @@ -1559,7 +1586,8 @@ color = g_string_append_c(color, *q); q++; } - g_string_append_printf(xhtml, "<span style='background: %s;'>", g_strstrip(color->str)); + if(xhtml) + g_string_append_printf(xhtml, "<span style='background: %s;'>", g_strstrip(color->str)); g_string_free(color, TRUE); if ((c = strchr(c, '>')) != NULL) c++; @@ -1580,14 +1608,17 @@ if(!g_ascii_strncasecmp(c, "<!--", strlen("<!--"))) { char *p = strstr(c + strlen("<!--"), "-->"); if(p) { - xhtml = g_string_append(xhtml, "<!--"); + if(xhtml) + xhtml = g_string_append(xhtml, "<!--"); c += strlen("<!--"); continue; } } - xhtml = g_string_append(xhtml, "<"); - plain = g_string_append_c(plain, '<'); + if(xhtml) + xhtml = g_string_append(xhtml, "<"); + if(plain) + plain = g_string_append_c(plain, '<'); c++; } } else if(*c == '&') { @@ -1600,29 +1631,31 @@ g_snprintf(buf, sizeof(buf), "%c", *c); pln = buf; } - xhtml = g_string_append_len(xhtml, c, len); - plain = g_string_append(plain, pln); + if(xhtml) + xhtml = g_string_append_len(xhtml, c, len); + if(plain) + plain = g_string_append(plain, pln); c += len; } else { - xhtml = g_string_append_c(xhtml, *c); - plain = g_string_append_c(plain, *c); + if(xhtml) + xhtml = g_string_append_c(xhtml, *c); + if(plain) + plain = g_string_append_c(plain, *c); c++; } } - tag = tags; - while(tag) { - struct purple_parse_tag *pt = tag->data; - if(!pt->ignore) - g_string_append_printf(xhtml, "</%s>", pt->dest_tag); - tag = tag->next; + if(xhtml) { + for (tag = tags; tag ; tag = tag->next) { + struct purple_parse_tag *pt = tag->data; + if(!pt->ignore) + g_string_append_printf(xhtml, "</%s>", pt->dest_tag); + } } g_list_free(tags); if(xhtml_out) - *xhtml_out = g_strdup(xhtml->str); + *xhtml_out = g_string_free(xhtml, FALSE); if(plain_out) - *plain_out = g_strdup(plain->str); - g_string_free(xhtml, TRUE); - g_string_free(plain, TRUE); + *plain_out = g_string_free(plain, FALSE); } /* The following are probably reasonable changes: @@ -3211,6 +3244,17 @@ g_hash_table_destroy(params); } +/* + * TODO: Should probably add a "gboolean *ret_ishttps" parameter that + * is set to TRUE if this URL is https, otherwise it is set to + * FALSE. But that change will break the API. + * + * This is important for Yahoo! web messenger login. They now + * force https login, and if you access the web messenger login + * page via http then it redirects you to the https version, but + * purple_util_fetch_url() ignores the "https" and attempts to + * fetch the URL via http again, which gets redirected again. + */ gboolean purple_url_parse(const char *url, char **ret_host, int *ret_port, char **ret_path, char **ret_user, char **ret_passwd) @@ -3231,12 +3275,16 @@ g_return_val_if_fail(url != NULL, FALSE); - if ((turl = strstr(url, "http://")) != NULL || - (turl = strstr(url, "HTTP://")) != NULL) + if ((turl = purple_strcasestr(url, "http://")) != NULL) { turl += 7; url = turl; } + else if ((turl = purple_strcasestr(url, "https://")) != NULL) + { + turl += 8; + url = turl; + } /* parse out authentication information if supplied */ /* Only care about @ char BEFORE the first / */ @@ -3316,85 +3364,92 @@ PurpleUtilFetchUrlData *gfud) { gchar *s; - - if ((s = g_strstr_len(data, data_len, "Location: ")) != NULL) + gchar *new_url, *temp_url, *end; + gboolean full; + int len; + + if ((s = g_strstr_len(data, data_len, "Location: ")) == NULL) + /* We're not being redirected */ + return FALSE; + + s += strlen("Location: "); + end = strchr(s, '\r'); + + /* Just in case :) */ + if (end == NULL) + end = strchr(s, '\n'); + + if (end == NULL) + return FALSE; + + len = end - s; + + new_url = g_malloc(len + 1); + strncpy(new_url, s, len); + new_url[len] = '\0'; + + full = gfud->full; + + if (*new_url == '/' || g_strstr_len(new_url, len, "://") == NULL) { - gchar *new_url, *temp_url, *end; - gboolean full; - int len; - - s += strlen("Location: "); - end = strchr(s, '\r'); - - /* Just in case :) */ - if (end == NULL) - end = strchr(s, '\n'); - - if (end == NULL) - return FALSE; - - len = end - s; - - new_url = g_malloc(len + 1); - strncpy(new_url, s, len); - new_url[len] = '\0'; - - full = gfud->full; - - if (*new_url == '/' || g_strstr_len(new_url, len, "://") == NULL) - { - temp_url = new_url; - - new_url = g_strdup_printf("%s:%d%s", gfud->website.address, - gfud->website.port, temp_url); - - g_free(temp_url); - - full = FALSE; - } - - purple_debug_info("util", "Redirecting to %s\n", new_url); - - /* - * Try again, with this new location. This code is somewhat - * ugly, but we need to reuse the gfud because whoever called - * us is holding a reference to it. - */ - g_free(gfud->url); - gfud->url = new_url; - gfud->full = full; - g_free(gfud->request); - gfud->request = NULL; - - purple_input_remove(gfud->inpa); - gfud->inpa = 0; - close(gfud->fd); - gfud->fd = -1; - gfud->request_written = 0; - gfud->len = 0; - gfud->data_len = 0; - - g_free(gfud->website.user); - g_free(gfud->website.passwd); - g_free(gfud->website.address); - g_free(gfud->website.page); - purple_url_parse(new_url, &gfud->website.address, &gfud->website.port, - &gfud->website.page, &gfud->website.user, &gfud->website.passwd); - - gfud->connect_data = purple_proxy_connect(NULL, NULL, - gfud->website.address, gfud->website.port, - url_fetch_connect_cb, gfud); - - if (gfud->connect_data == NULL) - { - purple_util_fetch_url_error(gfud, _("Unable to connect to %s"), - gfud->website.address); - } - + temp_url = new_url; + + new_url = g_strdup_printf("%s:%d%s", gfud->website.address, + gfud->website.port, temp_url); + + g_free(temp_url); + + full = FALSE; + } + + purple_debug_info("util", "Redirecting to %s\n", new_url); + + gfud->num_times_redirected++; + if (gfud->num_times_redirected >= 5) + { + purple_util_fetch_url_error(gfud, + _("Could not open %s: Redirected too many times"), + gfud->url); return TRUE; } - return FALSE; + /* + * Try again, with this new location. This code is somewhat + * ugly, but we need to reuse the gfud because whoever called + * us is holding a reference to it. + */ + g_free(gfud->url); + gfud->url = new_url; + gfud->full = full; + g_free(gfud->request); + gfud->request = NULL; + + purple_input_remove(gfud->inpa); + gfud->inpa = 0; + close(gfud->fd); + gfud->fd = -1; + gfud->request_written = 0; + gfud->len = 0; + gfud->data_len = 0; + + g_free(gfud->website.user); + g_free(gfud->website.passwd); + g_free(gfud->website.address); + g_free(gfud->website.page); + purple_url_parse(new_url, &gfud->website.address, &gfud->website.port, + &gfud->website.page, &gfud->website.user, &gfud->website.passwd); + + gfud->connect_data = purple_proxy_connect(NULL, NULL, + gfud->website.address, gfud->website.port, + url_fetch_connect_cb, gfud); + + if (gfud->connect_data == NULL) + { + purple_util_fetch_url_error(gfud, _("Unable to connect to %s"), + gfud->website.address); + } + + return TRUE; } static size_t
--- a/libpurple/xmlnode.c Sun Jun 03 23:11:57 2007 +0000 +++ b/libpurple/xmlnode.c Mon Jun 04 23:48:54 2007 +0000 @@ -519,38 +519,38 @@ } static xmlSAXHandler xmlnode_parser_libxml = { - .internalSubset = NULL, - .isStandalone = NULL, - .hasInternalSubset = NULL, - .hasExternalSubset = NULL, - .resolveEntity = NULL, - .getEntity = NULL, - .entityDecl = NULL, - .notationDecl = NULL, - .attributeDecl = NULL, - .elementDecl = NULL, - .unparsedEntityDecl = NULL, - .setDocumentLocator = NULL, - .startDocument = NULL, - .endDocument = NULL, - .startElement = NULL, - .endElement = NULL, - .reference = NULL, - .characters = xmlnode_parser_element_text_libxml, - .ignorableWhitespace = NULL, - .processingInstruction = NULL, - .comment = NULL, - .warning = NULL, - .error = xmlnode_parser_error_libxml, - .fatalError = NULL, - .getParameterEntity = NULL, - .cdataBlock = NULL, - .externalSubset = NULL, - .initialized = XML_SAX2_MAGIC, - ._private = NULL, - .startElementNs = xmlnode_parser_element_start_libxml, - .endElementNs = xmlnode_parser_element_end_libxml, - .serror = NULL + NULL, /* internalSubset */ + NULL, /* isStandalone */ + NULL, /* hasInternalSubset */ + NULL, /* hasExternalSubset */ + NULL, /* resolveEntity */ + NULL, /* getEntity */ + NULL, /* entityDecl */ + NULL, /* notationDecl */ + NULL, /* attributeDecl */ + NULL, /* elementDecl */ + NULL, /* unparsedEntityDecl */ + NULL, /* setDocumentLocator */ + NULL, /* startDocument */ + NULL, /* endDocument */ + NULL, /* startElement */ + NULL, /* endElement */ + NULL, /* reference */ + xmlnode_parser_element_text_libxml, /* characters */ + NULL, /* ignorableWhitespace */ + NULL, /* processingInstruction */ + NULL, /* comment */ + NULL, /* warning */ + xmlnode_parser_error_libxml, /* error */ + NULL, /* fatalError */ + NULL, /* getParameterEntity */ + NULL, /* cdataBlock */ + NULL, /* externalSubset */ + XML_SAX2_MAGIC, /* initialized */ + NULL, /* _private */ + xmlnode_parser_element_start_libxml, /* startElementNs */ + xmlnode_parser_element_end_libxml, /* endElementNs */ + NULL, /* serror */ }; xmlnode *
--- a/pidgin/gtkaccount.c Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/gtkaccount.c Mon Jun 04 23:48:54 2007 +0000 @@ -184,6 +184,7 @@ gtk_size_group_add_widget(dialog->sg, label); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, PIDGIN_HIG_BORDER); @@ -426,7 +427,7 @@ gtk_widget_ref(dialog->protocol_menu); } - hbox = add_pref_box(dialog, vbox, _("Protocol:"), dialog->protocol_menu); + hbox = add_pref_box(dialog, vbox, _("Pro_tocol:"), dialog->protocol_menu); g_object_set_data(G_OBJECT(dialog->protocol_menu), "container", hbox); gtk_widget_unref(dialog->protocol_menu); @@ -437,7 +438,7 @@ g_object_set(G_OBJECT(dialog->screenname_entry), "truncate-multiline", TRUE, NULL); #endif - add_pref_box(dialog, vbox, _("Screen name:"), dialog->screenname_entry); + add_pref_box(dialog, vbox, _("Screen _name:"), dialog->screenname_entry); g_signal_connect(G_OBJECT(dialog->screenname_entry), "changed", G_CALLBACK(screenname_changed_cb), dialog); @@ -479,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) { @@ -499,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) @@ -519,16 +519,16 @@ gtk_entry_set_visibility(GTK_ENTRY(dialog->password_entry), FALSE); if (gtk_entry_get_invisible_char(GTK_ENTRY(dialog->password_entry)) == '*') gtk_entry_set_invisible_char(GTK_ENTRY(dialog->password_entry), PIDGIN_INVISIBLE_CHAR); - dialog->password_box = add_pref_box(dialog, vbox, _("Password:"), + dialog->password_box = add_pref_box(dialog, vbox, _("_Password:"), dialog->password_entry); /* Alias */ dialog->alias_entry = gtk_entry_new(); - add_pref_box(dialog, vbox, _("Local alias:"), dialog->alias_entry); + add_pref_box(dialog, vbox, _("Local _alias:"), dialog->alias_entry); /* Remember Password */ dialog->remember_pass_check = - gtk_check_button_new_with_label(_("Remember password")); + gtk_check_button_new_with_mnemonic(_("Remember pass_word")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->remember_pass_check), FALSE); gtk_box_pack_start(GTK_BOX(vbox), dialog->remember_pass_check, @@ -599,12 +599,12 @@ /* New mail notifications */ dialog->new_mail_check = - gtk_check_button_new_with_label(_("New mail notifications")); + gtk_check_button_new_with_mnemonic(_("New _mail notifications")); gtk_box_pack_start(GTK_BOX(vbox), dialog->new_mail_check, FALSE, FALSE, 0); gtk_widget_show(dialog->new_mail_check); /* Buddy icon */ - dialog->icon_check = gtk_check_button_new_with_label(_("Use this buddy icon for this account:")); + dialog->icon_check = gtk_check_button_new_with_mnemonic(_("Use this buddy _icon for this account:")); g_signal_connect(G_OBJECT(dialog->icon_check), "toggled", G_CALLBACK(icon_check_cb), dialog); gtk_widget_show(dialog->icon_check); gtk_box_pack_start(GTK_BOX(vbox), dialog->icon_check, FALSE, FALSE, 0); @@ -702,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) { @@ -828,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); @@ -1023,7 +1022,7 @@ if (dialog->proxy_frame != NULL) gtk_widget_destroy(dialog->proxy_frame); - frame = pidgin_make_frame(parent, _("Proxy Options")); + frame = pidgin_make_frame(parent, _("Pro_xy Options")); dialog->proxy_frame = gtk_widget_get_parent(gtk_widget_get_parent(frame)); gtk_box_reorder_child(GTK_BOX(parent), dialog->proxy_frame, 1); @@ -1466,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 = pidgin_create_window((type == PIDGIN_ADD_ACCOUNT_DIALOG) ? _("Add Account") : _("Modify Account"), PIDGIN_HIG_BORDER, "account", FALSE);
--- a/pidgin/gtkblist.c Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/gtkblist.c Mon Jun 04 23:48:54 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) @@ -1124,10 +1119,10 @@ if (((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) { pidgin_separator(menu); pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy); - pidgin_new_item_from_stock(menu, _("Alias..."), PIDGIN_STOCK_ALIAS, + pidgin_new_item_from_stock(menu, _("_Alias..."), PIDGIN_STOCK_ALIAS, G_CALLBACK(gtk_blist_menu_alias_cb), contact, 0, 0, NULL); - pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE, + pidgin_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE, G_CALLBACK(pidgin_blist_remove_cb), contact, 0, 0, NULL); } else if (!sub || contact_expanded) { @@ -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; } @@ -4735,8 +4733,15 @@ NODE_COLUMN, &new_selection, -1); } - /* we set this up as a timeout, otherwise the blist flickers */ - g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection); + /* we set this up as a timeout, otherwise the blist flickers ... + * but we don't do it for groups, because it causes total bizarness - + * the previously selected buddy node might rendered at half height. + */ + if ((new_selection != NULL) && PURPLE_BLIST_NODE_IS_GROUP(new_selection)) { + do_selection_changed(new_selection); + } else { + g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection); + } } static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter) @@ -5397,12 +5402,25 @@ gtk_container_set_border_width(GTK_CONTAINER(table), 0); gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); - label = gtk_label_new(_("Screen name:")); + /* Set up stuff for the account box */ + label = gtk_label_new_with_mnemonic(_("_Account:")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); + data->account_box = pidgin_account_option_menu_new(account, FALSE, + G_CALLBACK(add_buddy_select_account_cb), NULL, data); + + gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 1, 2, 0, 1); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->account_box); + pidgin_set_accessible_label (data->account_box, label); + /* End of account box */ + + label = gtk_label_new_with_mnemonic(_("_Screen name:")); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); + data->entry = gtk_entry_new(); - gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 1, 2); gtk_widget_grab_focus(data->entry); if (username != NULL) @@ -5412,19 +5430,20 @@ GTK_RESPONSE_OK, FALSE); gtk_entry_set_activates_default (GTK_ENTRY(data->entry), TRUE); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->entry); pidgin_set_accessible_label (data->entry, label); g_signal_connect(G_OBJECT(data->entry), "changed", G_CALLBACK(pidgin_set_sensitive_if_input), data->window); - label = gtk_label_new(_("Alias:")); + label = gtk_label_new_with_mnemonic(_("A_lias:")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); + gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); data->entry_for_alias = gtk_entry_new(); gtk_table_attach_defaults(GTK_TABLE(table), - data->entry_for_alias, 1, 2, 1, 2); + data->entry_for_alias, 1, 2, 2, 3); if (alias != NULL) gtk_entry_set_text(GTK_ENTRY(data->entry_for_alias), alias); @@ -5433,29 +5452,19 @@ gtk_widget_grab_focus(GTK_WIDGET(data->entry_for_alias)); gtk_entry_set_activates_default (GTK_ENTRY(data->entry_for_alias), TRUE); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->entry_for_alias); pidgin_set_accessible_label (data->entry_for_alias, label); - label = gtk_label_new(_("Group:")); + label = gtk_label_new_with_mnemonic(_("_Group:")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); + gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); data->combo = gtk_combo_new(); gtk_combo_set_popdown_strings(GTK_COMBO(data->combo), groups_tree()); - gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 2, 3); + gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 3, 4); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_COMBO(data->combo)->entry); pidgin_set_accessible_label (data->combo, label); - /* Set up stuff for the account box */ - label = gtk_label_new(_("Account:")); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); - - data->account_box = pidgin_account_option_menu_new(account, FALSE, - G_CALLBACK(add_buddy_select_account_cb), NULL, data); - - gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 1, 2, 3, 4); - pidgin_set_accessible_label (data->account_box, label); - /* End of account box */ - g_signal_connect(G_OBJECT(data->window), "response", G_CALLBACK(add_buddy_cb), data); @@ -5761,7 +5770,7 @@ rowbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); - label = gtk_label_new(_("Account:")); + label = gtk_label_new_with_mnemonic(_("_Account:")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_size_group_add_widget(data->sg, label); gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); @@ -5770,6 +5779,7 @@ G_CALLBACK(addchat_select_account_cb), chat_account_filter_func, data); gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->account_menu); pidgin_set_accessible_label (data->account_menu, label); data->entries_box = gtk_vbox_new(FALSE, 5); @@ -5781,7 +5791,7 @@ rowbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); - label = gtk_label_new(_("Alias:")); + label = gtk_label_new_with_mnemonic(_("A_lias:")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_size_group_add_widget(data->sg, label); gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); @@ -5791,6 +5801,7 @@ gtk_entry_set_text(GTK_ENTRY(data->alias_entry), alias); gtk_box_pack_end(GTK_BOX(rowbox), data->alias_entry, TRUE, TRUE, 0); gtk_entry_set_activates_default(GTK_ENTRY(data->alias_entry), TRUE); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->alias_entry); pidgin_set_accessible_label (data->alias_entry, label); if (name != NULL) gtk_widget_grab_focus(data->alias_entry); @@ -5798,7 +5809,7 @@ rowbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); - label = gtk_label_new(_("Group:")); + label = gtk_label_new_with_mnemonic(_("_Group:")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_size_group_add_widget(data->sg, label); gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); @@ -5812,6 +5823,7 @@ gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(data->group_combo)->entry), group->name); } + gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_COMBO(data->group_combo)->entry); pidgin_set_accessible_label (data->group_combo, label); g_signal_connect(G_OBJECT(data->window), "response",
--- a/pidgin/gtkconv.c Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/gtkconv.c Mon Jun 04 23:48:54 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 @@ -695,7 +637,7 @@ purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); } else - prpl_info->get_info(gc, who); + pidgin_retrieve_user_info(gc, who); } } @@ -706,14 +648,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 */ @@ -2257,34 +2193,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; } @@ -2961,10 +2881,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. */ @@ -4164,45 +4139,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); @@ -4223,35 +4170,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); @@ -4299,9 +4230,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, @@ -4332,10 +4261,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); @@ -4351,20 +4342,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", @@ -4374,129 +4360,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; } @@ -4692,12 +4577,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); @@ -8006,6 +7889,7 @@ generate_send_to_items(win); regenerate_options_items(win); + regenerate_plugins_items(win); pidgin_conv_switch_active_conversation(conv); @@ -8076,6 +7960,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() { @@ -8147,6 +8037,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); @@ -8186,6 +8083,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 Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/gtkdialogs.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/gtkimhtml.c Mon Jun 04 23:48:54 2007 +0000 @@ -1344,9 +1344,9 @@ gtk_binding_entry_add_signal (binding_set, GDK_r, GDK_CONTROL_MASK, "format_function_clear", 0); gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "message_send", 0); gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "message_send", 0); - gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); - gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); - gtk_binding_entry_add_signal (binding_set, GDK_F14, 0, "undo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_F14, 0, "undo", 0); } @@ -4907,3 +4907,70 @@ 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/gtkimhtml.h Mon Jun 04 23:48:54 2007 +0000 @@ -29,6 +29,8 @@ #include <gtk/gtkimage.h> #include "gtksourceundomanager.h" +#include "connection.h" + #ifdef __cplusplus extern "C" { #endif @@ -790,6 +792,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 Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/gtkpounce.c Mon Jun 04 23:48:54 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) || @@ -647,7 +662,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...")); @@ -655,7 +671,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); @@ -667,8 +683,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); @@ -683,23 +697,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); @@ -708,7 +722,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); @@ -723,7 +737,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), @@ -759,7 +773,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); @@ -886,7 +905,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 Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/gtkprefs.c Mon Jun 04 23:48:54 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 Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/gtkutils.c Mon Jun 04 23:48:54 2007 +0000 @@ -261,13 +261,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) @@ -478,7 +479,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; @@ -511,6 +512,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); @@ -518,6 +520,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) { @@ -568,25 +603,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) { @@ -618,11 +634,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); @@ -631,10 +650,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); @@ -686,7 +705,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) @@ -704,18 +722,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)) { @@ -730,7 +742,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); @@ -899,6 +911,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, @@ -1599,40 +1620,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 @@ -1648,62 +1642,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 Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/gtkutils.h Mon Jun 04 23:48:54 2007 +0000 @@ -142,8 +142,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. @@ -319,6 +321,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. * @@ -416,8 +426,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 Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/plugins/cap/cap.c Mon Jun 04 23:48:54 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) {
--- a/pidgin/plugins/relnot.c Sun Jun 03 23:11:57 2007 +0000 +++ b/pidgin/plugins/relnot.c Mon Jun 04 23:48:54 2007 +0000 @@ -69,20 +69,17 @@ message = g_string_new(""); g_string_append_printf(message, _("You are using %s version %s. The " - "current version is %s.<hr>"), + "current version is %s. You can get it from " + "<a href=\"" PURPLE_WEBSITE "\">" PURPLE_WEBSITE "</a><hr>"), PIDGIN_NAME, purple_core_get_version(), cur_ver); if(*changelog) { formatted = purple_strdup_withhtml(changelog); - g_string_append_printf(message, _("<b>ChangeLog:</b>\n%s<br><br>"), + g_string_append_printf(message, _("<b>ChangeLog:</b><br>%s"), formatted); g_free(formatted); } - g_string_append_printf(message, _("You can get version %s from:<br>" - "<a href=\"http://pidgin.im/\">" - "http://pidgin.im</a>."), cur_ver); - purple_notify_formatted(NULL, _("New Version Available"), _("New Version Available"), NULL, message->str, NULL, NULL);