# HG changeset patch # User Eric Polino # Date 1183082085 0 # Node ID bd44f661f4c81aed87d151860725610474f207bf # Parent b25cb0775be34f8088157ab0f3e5c378577a21fb# Parent 086cfcb71b01d3b7092159753da4e01bff2a3673 merge of '7229e4b74f5d355cabe59ecbbe84f35f1d9cdca9' and 'd415e1047f1286523321e03ed1bca413f396edac' diff -r 086cfcb71b01 -r bd44f661f4c8 COPYRIGHT --- a/COPYRIGHT Fri Jun 29 01:51:13 2007 +0000 +++ b/COPYRIGHT Fri Jun 29 01:54:45 2007 +0000 @@ -277,6 +277,7 @@ Eric Polino Ari Pollak Robey Pointer +Eric Polino Stephen Pope Nathan Poznick Jory A. Pratt @@ -356,6 +357,7 @@ Cestonaro Thilo Will Thompson Douglas Thrift (douglaswth) +Mark Tiefenbruck Andrew Tinney Jeffery To Warren Togami diff -r 086cfcb71b01 -r bd44f661f4c8 Doxyfile.in --- a/Doxyfile.in Fri Jun 29 01:51:13 2007 +0000 +++ b/Doxyfile.in Fri Jun 29 01:54:45 2007 +0000 @@ -432,8 +432,9 @@ # with spaces. INPUT = libpurple \ - finch \ - pidgin \ + finch \ + finch/libgnt \ + pidgin \ doc # If the value of the INPUT tag contains directories, you can use the diff -r 086cfcb71b01 -r bd44f661f4c8 finch/gntconv.c --- a/finch/gntconv.c Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/gntconv.c Fri Jun 29 01:54:45 2007 +0000 @@ -571,7 +571,8 @@ if (ggc->list == NULL) { g_free(ggc->u.chat); - gnt_widget_destroy(ggc->window); + if (ggc->window) + gnt_widget_destroy(ggc->window); g_free(ggc); } } diff -r 086cfcb71b01 -r bd44f661f4c8 finch/gntplugin.c --- a/finch/gntplugin.c Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/gntplugin.c Fri Jun 29 01:54:45 2007 +0000 @@ -47,7 +47,7 @@ static GHashTable *confwins; -static void process_pref_frame(PurplePluginPrefFrame *frame); +static GntWidget *process_pref_frame(PurplePluginPrefFrame *frame); static void decide_conf_button(PurplePlugin *plugin) @@ -84,7 +84,7 @@ gnt_tree_set_choice(GNT_TREE(tree), plugin, TRUE); } - if ((win = g_hash_table_lookup(confwins, plugin)) != NULL) + if (confwins && (win = g_hash_table_lookup(confwins, plugin)) != NULL) { gnt_widget_destroy(win); } @@ -221,7 +221,11 @@ else if (plugin->info->prefs_info && plugin->info->prefs_info->get_plugin_pref_frame) { - process_pref_frame(plugin->info->prefs_info->get_plugin_pref_frame(plugin)); + GntWidget *win = process_pref_frame(plugin->info->prefs_info->get_plugin_pref_frame(plugin)); + if (confwins == NULL) + confwin_init(); + g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(remove_confwin), plugin); + g_hash_table_insert(confwins, plugin, win); return; } else @@ -273,6 +277,14 @@ { PurplePlugin *plug = iter->data; + if (plug->info->type == PURPLE_PLUGIN_LOADER) { + GList *cur; + for (cur = PURPLE_PLUGIN_LOADER_INFO(plug)->exts; cur != NULL; + cur = cur->next) + purple_plugins_probe(cur->data); + continue; + } + if (plug->info->type != PURPLE_PLUGIN_STANDARD || (plug->info->flags & PURPLE_PLUGIN_FLAG_INVISIBLE) || plug->error) @@ -308,7 +320,7 @@ decide_conf_button(gnt_tree_get_selection_data(GNT_TREE(tree))); } -static void +static GntWidget* process_pref_frame(PurplePluginPrefFrame *frame) { PurpleRequestField *field; @@ -360,7 +372,7 @@ } } - purple_request_fields(NULL, _("Preferences"), NULL, NULL, fields, + return purple_request_fields(NULL, _("Preferences"), NULL, NULL, fields, _("Save"), G_CALLBACK(finch_request_save_in_prefs), _("Cancel"), NULL, NULL, NULL, NULL, NULL); diff -r 086cfcb71b01 -r bd44f661f4c8 finch/gntprefs.c diff -r 086cfcb71b01 -r bd44f661f4c8 finch/gntrequest.c --- a/finch/gntrequest.c Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/gntrequest.c Fri Jun 29 01:54:45 2007 +0000 @@ -399,7 +399,7 @@ purple_request_field_string_get_default_value(field)); gnt_entry_set_masked(GNT_ENTRY(entry), purple_request_field_string_is_masked(field)); - if (purple_str_has_prefix(hint, "screenname")) { + if (hint && purple_str_has_prefix(hint, "screenname")) { PurpleBlistNode *node = purple_blist_get_root(); gboolean offline = purple_str_has_suffix(hint, "all"); for (; node; node = purple_blist_node_next(node, offline)) { diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gnt-skel.h --- a/finch/libgnt/gnt-skel.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gnt-skel.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gnt-skel.h -skel API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gnt.h --- a/finch/libgnt/gnt.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gnt.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,14 @@ /** + * @defgroup gnt GNT (GLib Ncurses Toolkit) + * + * GNT is an ncurses toolkit for creating text-mode graphical user interfaces + * in a fast and easy way. + */ +/** + * @file gnt.h GNT API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntbindable.h --- a/finch/libgnt/gntbindable.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntbindable.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntbindable.h Bindable API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntbox.h --- a/finch/libgnt/gntbox.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntbox.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntbox.h Box API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous @@ -84,9 +88,8 @@ G_BEGIN_DECLS /** - * - * - * @return + * The GType for GntBox. + * @return The GType. */ GType gnt_box_get_gtype(void); @@ -94,98 +97,110 @@ #define gnt_hbox_new(homo) gnt_box_new(homo, FALSE) /** - * - * @param homo - * @param vert + * Create a new GntBox. * - * @return + * @param homo If @c TRUE, all the widgets in it will have the same width (or height) + * @param vert Whether the widgets in it should be stacked vertically (if @c TRUE) + * or horizontally (if @c FALSE). + * + * @return The new GntBox. */ GntWidget * gnt_box_new(gboolean homo, gboolean vert); /** - * - * @param box - * @param widget + * Add a widget in the box. + * + * @param box The box + * @param widget The widget to add */ void gnt_box_add_widget(GntBox *box, GntWidget *widget); /** - * - * @param box - * @param title + * Set a title for the box. + * + * @param box The box + * @param title The title to set */ void gnt_box_set_title(GntBox *box, const char *title); /** - * - * @param box - * @param pad + * Set the padding to use between the widgets in the box. + * + * @param box The box + * @param pad The padding to use */ void gnt_box_set_pad(GntBox *box, int pad); /** - * - * @param box - * @param set + * Set whether it's a toplevel box (ie, a window) or not. If a box is toplevel, + * then it will show borders, the title (if set) and shadow (if enabled in + * @e .gntrc) + * + * @param box The box + * @param set @c TRUE if it's a toplevel box, @c FALSE otherwise. */ void gnt_box_set_toplevel(GntBox *box, gboolean set); /** - * - * @param box + * Reposition and refresh the widgets in the box. + * + * @param box The box */ void gnt_box_sync_children(GntBox *box); /** - * - * @param box - * @param alignment + * Set the alignment for the widgets in the box. + * + * @param box The box + * @param alignment The alignment to use */ void gnt_box_set_alignment(GntBox *box, GntAlignment alignment); /** - * - * @param box - * @param widget + * Remove a widget from the box. Calling this does NOT destroy the removed widget. + * + * @param box The box + * @param widget The widget to remove */ void gnt_box_remove(GntBox *box, GntWidget *widget); - /* XXX: does NOT destroy widget */ - /** - * - * @param box + * Remove all widgets from the box. This DOES destroy all widgets in the box. + * + * @param box The box */ void gnt_box_remove_all(GntBox *box); - /* Removes AND destroys all the widgets in it */ - /** - * - * @param box + * Readjust the size of each child widget, reposition the child widgets and + * recalculate the size of the box. + * + * @param box The box */ void gnt_box_readjust(GntBox *box); /** - * - * @param box - * @param fill + * Set whether the widgets in the box should fill the empty spaces. + * + * @param box The box + * @param fill Whether the child widgets should fill the empty space */ void gnt_box_set_fill(GntBox *box, gboolean fill); /** - * - * @param box - * @param dir + * Move the focus from one widget to the other. + * + * @param box The box + * @param dir The direction. If it's 1, then the focus is moved forwards, if it's + * -1, the focus is moved backwards. */ void gnt_box_move_focus(GntBox *box, int dir); - /* +1 to move forward, -1 for backward */ - /** - * - * @param box - * @param widget + * Give focus to a specific child widget. + * + * @param box The box + * @param widget The child widget to give focus */ void gnt_box_give_focus_to_child(GntBox *box, GntWidget *widget); diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntbutton.h --- a/finch/libgnt/gntbutton.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntbutton.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntbutton.h Button API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntcheckbox.h --- a/finch/libgnt/gntcheckbox.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntcheckbox.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntcheckbox.h Checkbox API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntclipboard.h --- a/finch/libgnt/gntclipboard.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntclipboard.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntclipboard.h Clipboard API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntcolors.h --- a/finch/libgnt/gntcolors.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntcolors.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntcolors.h Colors API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntcombobox.h --- a/finch/libgnt/gntcombobox.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntcombobox.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntcombobox.h Combobox API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntentry.h --- a/finch/libgnt/gntentry.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntentry.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntentry.h Entry API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntfilesel.h --- a/finch/libgnt/gntfilesel.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntfilesel.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntfilesel.h File selector API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntkeys.h --- a/finch/libgnt/gntkeys.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntkeys.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntkeys.h Keys API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntlabel.h --- a/finch/libgnt/gntlabel.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntlabel.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntlabel.h Label API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntline.h --- a/finch/libgnt/gntline.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntline.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntline.h Line API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntmenu.h --- a/finch/libgnt/gntmenu.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntmenu.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntmenu.h Menu API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntmenuitem.h --- a/finch/libgnt/gntmenuitem.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntmenuitem.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntmenuitem.h Menuitem API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntmenuitemcheck.h --- a/finch/libgnt/gntmenuitemcheck.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntmenuitemcheck.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntmenuitemcheck.h Check Menuitem API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntstyle.c --- a/finch/libgnt/gntstyle.c Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntstyle.c Fri Jun 29 01:54:45 2007 +0000 @@ -37,7 +37,6 @@ static GKeyFile *gkfile; #endif -static GHashTable *unknowns; static char * str_styles[GNT_STYLES]; static int int_styles[GNT_STYLES]; static int bool_styles[GNT_STYLES]; @@ -47,9 +46,11 @@ return str_styles[style]; } -const char *gnt_style_get_from_name(const char *name) +const char *gnt_style_get_from_name(const char *group, const char *key) { - return g_hash_table_lookup(unknowns, name); +#if GLIB_CHECK_VERSION(2,6,0) + return g_key_file_get_value(gkfile, group, key, NULL); +#endif } gboolean gnt_style_get_bool(GntStyle style, gboolean def) @@ -294,9 +295,6 @@ str_styles[styles[i].en] = g_key_file_get_string(kfile, "general", styles[i].style, NULL); } - for (i = 0; i < nkeys; i++) - g_hash_table_replace(unknowns, g_strdup(keys[i]), - g_strdup(g_key_file_get_string(kfile, "general", keys[i], NULL))); } g_strfreev(keys); } @@ -307,9 +305,9 @@ #if GLIB_CHECK_VERSION(2,6,0) GError *error = NULL; gkfile = g_key_file_new(); - unknowns = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - if (!g_key_file_load_from_file(gkfile, filename, G_KEY_FILE_NONE, &error)) + if (!g_key_file_load_from_file(gkfile, filename, + G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error)) { g_printerr("GntStyle: %s\n", error->message); g_error_free(error); diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntstyle.h --- a/finch/libgnt/gntstyle.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntstyle.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntstyle.h Style API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous @@ -41,7 +45,7 @@ const char *gnt_style_get(GntStyle style); -const char *gnt_style_get_from_name(const char *key); +const char *gnt_style_get_from_name(const char *group, const char *key); /** * diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gnttextview.h --- a/finch/libgnt/gnttextview.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gnttextview.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gnttextview.h Textview API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gnttree.c diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gnttree.h --- a/finch/libgnt/gnttree.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gnttree.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gnttree.h Tree API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntutils.c diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntutils.h --- a/finch/libgnt/gntutils.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntutils.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntutils.h Some utility functions + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous @@ -28,89 +32,102 @@ typedef gpointer (*GDupFunc)(gconstpointer data); /** - * - * @param text - * @param width - * @param height + * Compute the width and height required to view the text on the screen. + * + * @param text The text to be displayed. + * @param width The width required is set here, if not @c NULL. + * @param height The height required is set here, if not @c NULL. */ void gnt_util_get_text_bound(const char *text, int *width, int *height); /* excluding *end */ /** - * - * @param start - * @param end + * Get the onscreen width of a string, or a substring. * - * @return + * @param start The beginning of the string. + * @param end The end of the string. The width returned is the width + * upto (but not including) end. If end is NULL, then start + * is considered as a @c NULL-terminated string. + * + * @return The on-screen width of the string. */ int gnt_util_onscreen_width(const char *start, const char *end); +/** + * Computes and returns the string after a specific number of onscreen characters. + * + * @param str The string. + * @param len The length to consider. If non-positive, the entire screenlength is used. + * @param w The actual width of the string upto the returned offset, if not @c NULL. + * + * @return The string after len offset. + */ const char *gnt_util_onscreen_width_to_pointer(const char *str, int len, int *w); -/* Inserts newlines in 'string' where necessary so that its onscreen width is +/** + * Inserts newlines in 'string' where necessary so that its onscreen width is * no more than 'maxw'. - * 'maxw' can be <= 0, in which case the maximum screen width is considered. * - * Returns a newly allocated string. - */ -/** - * - * @param string - * @param maxw + * @param string The string. + * @param maxw The width that the string should fit into. If maxw is <= 0, + * then the available maximum width is used. * - * @return + * @return A newly allocated string that needs to be freed by the caller. */ char * gnt_util_onscreen_fit_string(const char *string, int maxw); /** - * - * @param src - * @param hash - * @param equal - * @param key_d - * @param value_d - * @param key_dup - * @param value_dup + * Duplicate the contents of a hastable. * - * @return + * @param src The source hashtable. + * @param hash The hash-function to use. + * @param equal The hash-equal function to use. + * @param key_d The key-destroy function to use. + * @param value_d The value-destroy function to use. + * @param key_dup The function to use to duplicate the key. + * @param value_dup The function to use to duplicate the value. + * + * @return The new hashtable. */ GHashTable * g_hash_table_duplicate(GHashTable *src, GHashFunc hash, GEqualFunc equal, GDestroyNotify key_d, GDestroyNotify value_d, GDupFunc key_dup, GDupFunc value_dup); /** * To be used with g_signal_new. Look in the key_pressed signal-definition in * gntwidget.c for usage. - */ -/** - * - * @param ihint - * @param return_accu - * @param handler_return - * @param dummy * - * @return + * @param ihint NA + * @param return_accu NA + * @param handler_return NA + * @param dummy NA + * + * @return NA */ gboolean gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, gpointer dummy); /** - * Returns a GntTree populated with "key" -> "binding" for the widget. - */ -/** + * Get a helpful display about the bindings of a widget. * - * @param widget + * @param widget The widget to get bindings for. * - * @return - * - * @deprecated Consider using gnt_bindable_bindings_view instead. + * @return Returns a GntTree populated with "key" -> "binding" for the widget. */ GntWidget * gnt_widget_bindings_view(GntWidget *widget); /** - * Parse widgets from 'string'. - */ -/** + * Parse widgets from an XML description. For example, + * + * @code + * GntWidget *win, *button; + * gnt_util_parse_widgets("\ + * \ + * \ + * \ + * ", + * 2, &win, &button); + * @endcode * - * @param string - * @param num + * @param string The XML string. + * @param num The number of widgets to return, followed by 'num' GntWidget ** */ void gnt_util_parse_widgets(const char *string, int num, ...); diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntwidget.c --- a/finch/libgnt/gntwidget.c Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntwidget.c Fri Jun 29 01:54:45 2007 +0000 @@ -576,7 +576,7 @@ GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_HAS_FOCUS); g_signal_emit(widget, signals[SIG_GIVE_FOCUS], 0); } - else if (!set) + else if (!set && GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_HAS_FOCUS)) { GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_HAS_FOCUS); g_signal_emit(widget, signals[SIG_LOST_FOCUS], 0); diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntwidget.h --- a/finch/libgnt/gntwidget.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntwidget.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntwidget.h Widget API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntwindow.h --- a/finch/libgnt/gntwindow.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntwindow.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntwindow.h Window API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntwm.c --- a/finch/libgnt/gntwm.c Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntwm.c Fri Jun 29 01:54:45 2007 +0000 @@ -497,6 +497,35 @@ return TRUE; } +static gboolean +help_for_widget(GntBindable *bindable, GList *null) +{ + GntWM *wm = GNT_WM(bindable); + GntWidget *widget, *tree, *win, *active; + char *title; + + if (!wm->cws->ordered) + return TRUE; + + widget = wm->cws->ordered->data; + if (!GNT_IS_BOX(widget)) + return TRUE; + active = GNT_BOX(widget)->active; + + tree = gnt_widget_bindings_view(active); + win = gnt_window_new(); + title = g_strdup_printf("Bindings for %s", g_type_name(G_OBJECT_TYPE(active))); + gnt_box_set_title(GNT_BOX(win), title); + if (tree) + gnt_box_add_widget(GNT_BOX(win), tree); + else + gnt_box_add_widget(GNT_BOX(win), gnt_label_new("This widget has no customizable bindings.")); + + gnt_widget_show(win); + + return TRUE; +} + static void destroy__list(GntWidget *widget, GntWM *wm) { @@ -603,7 +632,6 @@ list_of_windows(GntWM *wm, gboolean workspace) { GntWidget *tree, *win; - setup__list(wm); wm->windows = &wm->_list; @@ -1321,7 +1349,7 @@ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "place-tagged", place_tagged, "\033" "T", NULL); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "workspace-list", workspace_list, - "\033" "s", NULL); + "\033" "s", NULL); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-clipboard", toggle_clipboard, "\033" "C", NULL); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "help-for-wm", help_for_wm, @@ -1539,7 +1567,6 @@ } #endif - static GntWS * new_widget_find_workspace(GntWM *wm, GntWidget *widget) { @@ -1735,7 +1762,6 @@ keys = gnt_bindable_remap_keys(GNT_BINDABLE(wm), keys); idle_update = TRUE; - if(ignore_keys){ if(keys && !strcmp(keys, "\033" GNT_KEY_CTRL_G)){ if(gnt_bindable_perform_action_key(GNT_BINDABLE(wm), keys)){ diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntwm.h --- a/finch/libgnt/gntwm.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntwm.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,4 +1,8 @@ /** + * @file gntwm.h Window-manager API + * @ingroup gnt + */ +/* * GNT - The GLib Ncurses Toolkit * * GNT is the legal property of its developers, whose names are too numerous diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntws.c --- a/finch/libgnt/gntws.c Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntws.c Fri Jun 29 01:54:45 2007 +0000 @@ -87,8 +87,12 @@ void gnt_ws_add_widget(GntWS *ws, GntWidget* wid) { + GntWidget *oldfocus; + oldfocus = ws->ordered ? ws->ordered->data : NULL; ws->list = g_list_append(ws->list, wid); ws->ordered = g_list_prepend(ws->ordered, wid); + if (oldfocus) + gnt_widget_set_focus(oldfocus, FALSE); } void gnt_ws_remove_widget(GntWS *ws, GntWidget* wid) diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/gntws.h --- a/finch/libgnt/gntws.h Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/gntws.h Fri Jun 29 01:54:45 2007 +0000 @@ -1,3 +1,29 @@ +/** + * @file gntws.h Workspace API + * @ingroup gnt + */ +/* + * GNT - The GLib Ncurses Toolkit + * + * GNT is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #ifndef GNTWS_H #define GNTWS_H diff -r 086cfcb71b01 -r bd44f661f4c8 finch/libgnt/wms/irssi.c --- a/finch/libgnt/wms/irssi.c Fri Jun 29 01:51:13 2007 +0000 +++ b/finch/libgnt/wms/irssi.c Fri Jun 29 01:54:45 2007 +0000 @@ -280,10 +280,10 @@ irssi = g_object_new(TYPE_IRSSI, NULL); *wm = GNT_WM(irssi); - style = gnt_style_get_from_name("irssi-split-v"); + style = gnt_style_get_from_name("irssi", "split-v"); irssi->vert = style ? atoi(style) : 1; - style = gnt_style_get_from_name("irssi-split-h"); + style = gnt_style_get_from_name("irssi", "split-h"); irssi->horiz = style ? atoi(style) : 1; irssi->vert = MAX(irssi->vert, 1); diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/Makefile.am --- a/libpurple/Makefile.am Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/Makefile.am Fri Jun 29 01:54:45 2007 +0000 @@ -157,10 +157,10 @@ purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) dbus_build_exported = $(addprefix $(srcdir)/, $(dbus_exported)) -dbus-types.c: dbus-analyze-types.py $(purple_coreheaders) +dbus-types.c: dbus-analyze-types.py $(purple_build_coreheaders) cat $(purple_build_coreheaders) | $(PYTHON) $(srcdir)/dbus-analyze-types.py --pattern=PURPLE_DBUS_DEFINE_TYPE\(%s\) > $@ -dbus-types.h: dbus-analyze-types.py $(dbus_coreheaders) +dbus-types.h: dbus-analyze-types.py $(purple_build_coreheaders) cat $(purple_build_coreheaders) | $(PYTHON) $(srcdir)/dbus-analyze-types.py --pattern=PURPLE_DBUS_DECLARE_TYPE\(%s\) > $@ dbus-bindings.c: dbus-analyze-functions.py $(dbus_exported) diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/conversation.c --- a/libpurple/conversation.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/conversation.c Fri Jun 29 01:54:45 2007 +0000 @@ -1563,6 +1563,7 @@ purple_conv_chat_is_user_ignored(chat, user); cbuddy = purple_conv_chat_cb_new(user, alias, flag); + cbuddy->buddy = purple_find_buddy(conv->account, user) != NULL; /* This seems dumb. Why should we set users thousands of times? */ purple_conv_chat_set_users(chat, g_list_prepend(chat->in_room, cbuddy)); @@ -1631,11 +1632,6 @@ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); g_return_if_fail(prpl_info != NULL); - flags = purple_conv_chat_user_get_flags(chat, old_user); - cb = purple_conv_chat_cb_new(new_user, NULL, flags); - purple_conv_chat_set_users(chat, - g_list_prepend(chat->in_room, cb)); - if (!strcmp(chat->nick, purple_normalize(conv->account, old_user))) { const char *alias; @@ -1659,6 +1655,12 @@ new_alias = purple_buddy_get_contact_alias(buddy); } + flags = purple_conv_chat_user_get_flags(chat, old_user); + cb = purple_conv_chat_cb_new(new_user, new_alias, flags); + cb->buddy = purple_find_buddy(conv->account, new_user) != NULL; + purple_conv_chat_set_users(chat, + g_list_prepend(chat->in_room, cb)); + if (ops != NULL && ops->chat_rename_user != NULL) ops->chat_rename_user(conv, old_user, new_user, new_alias); @@ -1949,6 +1951,7 @@ return chat->left; } + PurpleConvChatBuddy * purple_conv_chat_cb_new(const char *name, const char *alias, PurpleConvChatBuddyFlags flags) { diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/core.c --- a/libpurple/core.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/core.c Fri Jun 29 01:54:45 2007 +0000 @@ -222,11 +222,10 @@ purple_sound_uninit(); purple_plugins_uninit(); - purple_signals_uninit(); - #ifdef HAVE_DBUS purple_dbus_uninit(); #endif + purple_signals_uninit(); g_free(core->ui); g_free(core); diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/debug.c diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/plugins/perl/scripts/signals-test.pl --- a/libpurple/plugins/perl/scripts/signals-test.pl Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/plugins/perl/scripts/signals-test.pl Fri Jun 29 01:54:45 2007 +0000 @@ -7,7 +7,7 @@ name => "Perl: $MODULE_NAME", version => "0.1", summary => "Signals Test plugin for the Perl interpreter.", - description => "Demonstrate the user of purple signals from " . + description => "Demonstrate the use of purple signals from " . "a perl plugin.", author => "Sadrul Habib Chowdhury ", url => "http://developer.pidgin.im/wiki/sadrul/", diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/bonjour/buddy.c --- a/libpurple/protocols/bonjour/buddy.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.c Fri Jun 29 01:54:45 2007 +0000 @@ -17,6 +17,7 @@ #include #include +#include "internal.h" #include "buddy.h" #include "account.h" #include "blist.h" diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Fri Jun 29 01:54:45 2007 +0000 @@ -31,6 +31,7 @@ #include #include +#include "internal.h" #include "network.h" #include "eventloop.h" #include "connection.h" diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/bonjour/mdns_common.c --- a/libpurple/protocols/bonjour/mdns_common.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_common.c Fri Jun 29 01:54:45 2007 +0000 @@ -16,6 +16,7 @@ #include +#include "internal.h" #include "config.h" #include "mdns_common.h" #include "bonjour.h" diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/bonjour/mdns_win32.c --- a/libpurple/protocols/bonjour/mdns_win32.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_win32.c Fri Jun 29 01:54:45 2007 +0000 @@ -14,6 +14,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "internal.h" #include "mdns_win32.h" #include "debug.h" diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/jabber/.todo --- a/libpurple/protocols/jabber/.todo Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/jabber/.todo Fri Jun 29 01:54:45 2007 +0000 @@ -1,13 +1,4 @@ - - *sigh* file transfer (do we really need/want this?) - - faceprint did this - - - - problem seeing buddies with long blist? - Browsing @@ -17,12 +8,6 @@ Add option for user info to be published or not in JUD. - - Show self on buddylist - - is this done? - - Delete server account. @@ -37,9 +22,6 @@ formatted. enhancement-request so that the birthday field in the setinfo form would split up into relevant fields allowing for a strict syntax (like year--month--day or so, perhaps even dropdown menus) - - have set info pre-fill values from the server when no local vcard exists. this will help people migrating to libpurple-based clients - Jabber Transports (having them show up on the buddy list should be fairly easy; having an appropriate right-click menu for them should also be somewhat easy. Providing a UI for adding transports should be rather difficult.) diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/jabber/buddy.c Fri Jun 29 01:54:45 2007 +0000 @@ -419,6 +419,10 @@ avatar_data = purple_imgstore_get_data(img); avatar_len = purple_imgstore_get_size(img); + /* have to get rid of the old PHOTO if it exists */ + if((photo = xmlnode_get_child(vc_node, "PHOTO"))) { + xmlnode_free(photo); + } photo = xmlnode_new_child(vc_node, "PHOTO"); binval = xmlnode_new_child(photo, "BINVAL"); enc = purple_base64_encode(avatar_data, avatar_len); diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/jabber/disco.c Fri Jun 29 01:54:45 2007 +0000 @@ -83,6 +83,7 @@ SUPPORT_FEATURE("jabber:iq:last") SUPPORT_FEATURE("jabber:iq:oob") SUPPORT_FEATURE("jabber:iq:time") + SUPPORT_FEATURE("xmpp:urn:time") SUPPORT_FEATURE("jabber:iq:version") SUPPORT_FEATURE("jabber:x:conference") SUPPORT_FEATURE("http://jabber.org/protocol/bytestreams") diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/jabber/iq.c --- a/libpurple/protocols/jabber/iq.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/jabber/iq.c Fri Jun 29 01:54:45 2007 +0000 @@ -169,7 +169,7 @@ static void jabber_iq_time_parse(JabberStream *js, xmlnode *packet) { - const char *type, *from, *id; + const char *type, *from, *id, *xmlns; JabberIq *iq; xmlnode *query; time_t now_t; @@ -182,27 +182,40 @@ from = xmlnode_get_attrib(packet, "from"); id = xmlnode_get_attrib(packet, "id"); + /* we're gonna throw this away in a moment, but we need it + * to get the xmlns, so we can figure out if this is + * jabber:iq:time or urn:xmpp:time */ + query = xmlnode_get_child(packet, "query"); + xmlns = xmlnode_get_namespace(query); + if(type && !strcmp(type, "get")) { + xmlnode *utc; const char *date; - iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:time"); + iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, xmlns); jabber_iq_set_id(iq, id); xmlnode_set_attrib(iq->node, "to", from); query = xmlnode_get_child(iq->node, "query"); date = purple_utf8_strftime("%Y%m%dT%T", now); - xmlnode_insert_data(xmlnode_new_child(query, "utc"), date, -1); + utc = xmlnode_new_child(query, "utc"); + xmlnode_insert_data(utc, date, -1); + + if(!strcmp("urn:xmpp:time", xmlns)) { + xmlnode_insert_data(utc, "Z", 1); /* of COURSE the thing that is the same is different */ - date = purple_utf8_strftime("%Z", now); - xmlnode_insert_data(xmlnode_new_child(query, "tz"), date, -1); + date = purple_get_tzoff_str(now, TRUE); + xmlnode_insert_data(xmlnode_new_child(query, "tzo"), date, -1); + } else { /* jabber:iq:time */ + date = purple_utf8_strftime("%Z", now); + xmlnode_insert_data(xmlnode_new_child(query, "tz"), date, -1); - date = purple_utf8_strftime("%d %b %Y %T", now); - xmlnode_insert_data(xmlnode_new_child(query, "display"), date, -1); + date = purple_utf8_strftime("%d %b %Y %T", now); + xmlnode_insert_data(xmlnode_new_child(query, "display"), date, -1); + } jabber_iq_send(iq); - } else { - /* XXX: error */ } } @@ -347,6 +360,7 @@ jabber_iq_register_handler("http://jabber.org/protocol/bytestreams", jabber_bytestreams_parse); jabber_iq_register_handler("jabber:iq:last", jabber_iq_last_parse); jabber_iq_register_handler("jabber:iq:time", jabber_iq_time_parse); + jabber_iq_register_handler("urn:xmpp:time", jabber_iq_time_parse); jabber_iq_register_handler("jabber:iq:version", jabber_iq_version_parse); jabber_iq_register_handler("http://jabber.org/protocol/disco#info", jabber_disco_info_parse); jabber_iq_register_handler("http://jabber.org/protocol/disco#items", jabber_disco_items_parse); diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Fri Jun 29 01:54:45 2007 +0000 @@ -1116,9 +1116,11 @@ char *jabber_status_text(PurpleBuddy *b) { - JabberBuddy *jb = jabber_buddy_find(b->account->gc->proto_data, b->name, - FALSE); char *ret = NULL; + JabberBuddy *jb = NULL; + + if (b->account->gc && b->account->gc->proto_data) + jb = jabber_buddy_find(b->account->gc->proto_data, b->name, FALSE); if(jb && !PURPLE_BUDDY_IS_ONLINE(b) && (jb->subscription & JABBER_SUB_PENDING || !(jb->subscription & JABBER_SUB_TO))) { ret = g_strdup(_("Not Authorized")); diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/jabber/presence.c Fri Jun 29 01:54:45 2007 +0000 @@ -515,7 +515,7 @@ buddy_name = g_strdup_printf("%s%s%s", jid->node ? jid->node : "", jid->node ? "@" : "", jid->domain); if((b = purple_find_buddy(js->gc->account, buddy_name)) == NULL) { - purple_debug_warning("jabber", "Got presence for unknown buddy %s on account %s (%x)", + purple_debug_warning("jabber", "Got presence for unknown buddy %s on account %s (%x)\n", buddy_name, purple_account_get_username(js->gc->account), js->gc->account); jabber_id_free(jid); g_free(avatar_hash); @@ -558,6 +558,7 @@ jabber_buddy_remove_resource(jb, jid->resource); if((conv = jabber_find_unnormalized_conv(from, js->gc->account))) purple_conversation_set_name(conv, buddy_name); + printf("Removed resource\n"); } else { jbr = jabber_buddy_track_resource(jb, jid->resource, priority, @@ -565,9 +566,7 @@ } if((found_jbr = jabber_buddy_find_resource(jb, NULL))) { - if(!jbr || jbr == found_jbr) { - purple_prpl_got_user_status(js->gc->account, buddy_name, jabber_buddy_state_get_status_id(state), "priority", found_jbr->priority, found_jbr->status ? "message" : NULL, found_jbr->status, NULL); - } + purple_prpl_got_user_status(js->gc->account, buddy_name, jabber_buddy_state_get_status_id(found_jbr->state), "priority", found_jbr->priority, found_jbr->status ? "message" : NULL, found_jbr->status, NULL); } else { purple_prpl_got_user_status(js->gc->account, buddy_name, "offline", status ? "message" : NULL, status, NULL); } diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/oscar/family_auth.c --- a/libpurple/protocols/oscar/family_auth.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/oscar/family_auth.c Fri Jun 29 01:54:45 2007 +0000 @@ -211,7 +211,7 @@ #ifdef USE_XOR_FOR_ICQ /* If we're signing on an ICQ account then use the older, XOR login method */ - if (isdigit(sn[0])) + if (aim_sn_is_icq(sn)) return goddamnicq2(od, conn, sn, password, ci); #endif @@ -224,7 +224,7 @@ /* Truncate ICQ and AOL passwords, if necessary */ password_len = strlen(password); - if (isdigit(sn[0]) && (password_len > MAXICQPASSLEN)) + if (aim_sn_is_icq(sn) && (password_len > MAXICQPASSLEN)) password_len = MAXICQPASSLEN; else if (truncate_pass && password_len > 8) password_len = 8; @@ -477,7 +477,7 @@ return -EINVAL; #ifdef USE_XOR_FOR_ICQ - if (isdigit(sn[0])) + if (aim_sn_is_icq(sn)) return goddamnicq(od, conn, sn); #endif diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/oscar/libicq.c --- a/libpurple/protocols/oscar/libicq.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/oscar/libicq.c Fri Jun 29 01:54:45 2007 +0000 @@ -32,7 +32,7 @@ OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE, NULL, /* user_splits */ NULL, /* protocol_options */ - {"gif,jpeg,bmp,ico", 48, 48, 50, 50, 7168, + {"gif,jpeg,bmp,ico", 48, 48, 52, 64, 7168, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ oscar_list_icon_icq, /* list_icon */ oscar_list_emblem, /* list_emblems */ diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Fri Jun 29 01:54:45 2007 +0000 @@ -425,7 +425,7 @@ charsetstr1 = "UCS-2BE"; charsetstr2 = "UTF-8"; } else if (charset == AIM_CHARSET_CUSTOM) { - if ((sourcesn != NULL) && isdigit(sourcesn[0])) + if ((sourcesn != NULL) && aim_sn_is_icq(sourcesn)) charsetstr1 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); else charsetstr1 = "ISO-8859-1"; @@ -1258,7 +1258,7 @@ if (!aim_snvalid(purple_account_get_username(account))) { gchar *buf; - buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the screen name is invalid. Screen names must either start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account)); + buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the screen name is invalid. Screen names must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account)); gc->wants_to_die = TRUE; purple_connection_error(gc, buf); g_free(buf); @@ -4623,7 +4623,7 @@ if (!aim_snvalid(buddy->name)) { gchar *buf; - buf = g_strdup_printf(_("Could not add the buddy %s because the screen name is invalid. Screen names must either start with a letter and contain only letters, numbers and spaces, or contain only numbers."), buddy->name); + buf = g_strdup_printf(_("Could not add the buddy %s because the screen name is invalid. Screen names must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), buddy->name); if (!purple_conv_present_error(buddy->name, purple_connection_get_account(gc), buf)) purple_notify_error(gc, NULL, _("Unable To Add"), buf); g_free(buf); @@ -5060,7 +5060,8 @@ default: { /* La la la */ gchar *buf; purple_debug_error("oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack); - buf = g_strdup_printf(_("Could not add the buddy %s for an unknown reason. The most common reason for this is that you have the maximum number of allowed buddies in your buddy list."), (retval->name ? retval->name : _("(no name)"))); + buf = g_strdup_printf(_("Could not add the buddy %s for an unknown reason."), + (retval->name ? retval->name : _("(no name)"))); if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf)) purple_notify_error(gc, NULL, _("Unable To Add"), buf); g_free(buf); diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/oscar/peer.c --- a/libpurple/protocols/oscar/peer.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/oscar/peer.c Fri Jun 29 01:54:45 2007 +0000 @@ -1019,7 +1019,7 @@ PURPLE_DEFAULT_ACTION_NONE, account, sn, NULL, conn, 2, - _("_Connect"), G_CALLBACK(peer_connection_got_proposition_yes_cb), + _("C_onnect"), G_CALLBACK(peer_connection_got_proposition_yes_cb), _("Cancel"), G_CALLBACK(peer_connection_got_proposition_no_cb)); } else if (args->type == OSCAR_CAPABILITY_SENDFILE) diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/oscar/util.c --- a/libpurple/protocols/oscar/util.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/oscar/util.c Fri Jun 29 01:54:45 2007 +0000 @@ -37,6 +37,7 @@ * -- DMP. * */ +/* TODO: Get rid of this and use glib functions */ int aimutil_tokslen(char *toSearch, int theindex, char dl) { @@ -138,6 +139,7 @@ * Check if the given screen name is a valid AIM screen name. * Example: BobDole * Example: Henry_Ford@mac.com + * Example: 1KrazyKat@example.com * * @return TRUE if the screen name is valid, FALSE if not. */ @@ -146,9 +148,16 @@ { int i; + if (purple_email_is_valid(sn)) + return TRUE; + + /* Normal AIM screen names can't start with a number */ + if (isdigit(sn[0])) + return FALSE; + for (i = 0; sn[i] != '\0'; i++) { if (!isalnum(sn[i]) && (sn[i] != ' ') && - (sn[i] != '@') && (sn[i] != '.') && + (sn[i] != '.') && (sn[i] != '_') && (sn[i] != '-')) return FALSE; } @@ -169,10 +178,10 @@ for (i = 0; sn[i] != '\0'; i++) { if (!isdigit(sn[i])) - return 0; + return FALSE; } - return 1; + return TRUE; } /** @@ -187,14 +196,14 @@ int i; if (sn[0] != '+') - return 0; + return FALSE; for (i = 1; sn[i] != '\0'; i++) { if (!isdigit(sn[i])) - return 0; + return FALSE; } - return 1; + return TRUE; } /** @@ -206,70 +215,37 @@ aim_snvalid(const char *sn) { if ((sn == NULL) || (*sn == '\0')) - return 0; + return FALSE; - if (isalpha(sn[0])) - return aim_snvalid_aim(sn); - else if (isdigit(sn[0])) - return aim_snvalid_icq(sn); - else if (sn[0] == '+') - return aim_snvalid_sms(sn); - - return 0; + return aim_snvalid_icq(sn) || aim_snvalid_sms(sn) || aim_snvalid_aim(sn); } /** * Determine if a given screen name is an ICQ screen name - * (i.e. it begins with a number). + * (i.e. it is composed of only numbers). * - * @sn A valid AIM or ICQ screen name. + * @param sn A valid AIM or ICQ screen name. * @return TRUE if the screen name is an ICQ screen name. Otherwise * FALSE is returned. */ gboolean aim_sn_is_icq(const char *sn) { - if (isalpha(sn[0])) - return FALSE; - return TRUE; + return aim_snvalid_icq(sn); } /** * Determine if a given screen name is an SMS number * (i.e. it begins with a +). * - * @sn A valid AIM or ICQ screen name. + * @param sn A valid AIM or ICQ screen name. * @return TRUE if the screen name is an SMS number. Otherwise * FALSE is returned. */ gboolean aim_sn_is_sms(const char *sn) { - if (sn[0] != '+') - return FALSE; - return TRUE; -} - -/** - * This takes a screen name and returns its length without - * spaces. If there are no spaces in the SN, then the - * return is equal to that of strlen(). - */ -int -aim_snlen(const char *sn) -{ - int i = 0; - - if (!sn) - return 0; - - while (*sn != '\0') { - if (*sn != ' ') - i++; - sn++; - } - - return i; + return (sn[0] == '+'); } /** @@ -279,9 +255,9 @@ * ignored, with the exception that screen names can not start with * a space). * - * Return: 0 if equal - * non-0 if different + * @return 0 if equal, non-0 if different */ +/* TODO: Do something different for email addresses. */ int aim_sncmp(const char *sn1, const char *sn2) { diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/protocols/qq/Makefile.mingw --- a/libpurple/protocols/qq/Makefile.mingw Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/protocols/qq/Makefile.mingw Fri Jun 29 01:54:45 2007 +0000 @@ -54,7 +54,6 @@ group_im.c \ group_info.c \ group_join.c \ - group_misc.c \ group_network.c \ group_opt.c \ group_search.c \ diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/server.c --- a/libpurple/server.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/server.c Fri Jun 29 01:54:45 2007 +0000 @@ -198,7 +198,7 @@ { PurplePluginProtocolInfo *prpl_info = NULL; - if (b != NULL && b->account->gc->prpl != NULL) + if (b != NULL && b->account->gc && b->account->gc->prpl != NULL) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(b->account->gc->prpl); if (b && prpl_info && prpl_info->alias_buddy) { diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/status.c --- a/libpurple/status.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/status.c Fri Jun 29 01:54:45 2007 +0000 @@ -152,10 +152,10 @@ { PURPLE_STATUS_UNSET, "unset", N_("Unset") }, { PURPLE_STATUS_OFFLINE, "offline", N_("Offline") }, { PURPLE_STATUS_AVAILABLE, "available", N_("Available") }, - { PURPLE_STATUS_UNAVAILABLE, "unavailable", N_("Unavailable") }, + { PURPLE_STATUS_UNAVAILABLE, "unavailable", N_("Do not disturb") }, { PURPLE_STATUS_INVISIBLE, "invisible", N_("Invisible") }, { PURPLE_STATUS_AWAY, "away", N_("Away") }, - { PURPLE_STATUS_EXTENDED_AWAY, "extended_away", N_("Extended Away") }, + { PURPLE_STATUS_EXTENDED_AWAY, "extended_away", N_("Extended away") }, { PURPLE_STATUS_MOBILE, "mobile", N_("Mobile") } }; diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/util.c --- a/libpurple/util.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/util.c Fri Jun 29 01:54:45 2007 +0000 @@ -531,10 +531,9 @@ } #endif -#ifndef HAVE_STRFTIME_Z_FORMAT -static const char *get_tmoff(const struct tm *tm) +const char *purple_get_tzoff_str(const struct tm *tm, gboolean iso) { - static char buf[6]; + static char buf[7]; long off; gint8 min; gint8 hrs; @@ -554,7 +553,7 @@ # else # ifdef HAVE_TIMEZONE tzset(); - off = -timezone; + off = -1 * timezone; # endif /* HAVE_TIMEZONE */ # endif /* !HAVE_TM_GMTOFF */ #endif /* _WIN32 */ @@ -562,12 +561,22 @@ min = (off / 60) % 60; hrs = ((off / 60) - min) / 60; - if (g_snprintf(buf, sizeof(buf), "%+03d%02d", hrs, ABS(min)) > 5) - g_return_val_if_reached(""); + if(iso) { + if (0 == off) { + strcpy(buf, "Z"); + } else { + /* please leave the colons...they're optional for iso, but jabber + * wants them */ + if(g_snprintf(buf, sizeof(buf), "%+03d:%02d", hrs, ABS(min)) > 6) + g_return_val_if_reached(""); + } + } else { + if (g_snprintf(buf, sizeof(buf), "%+03d%02d", hrs, ABS(min)) > 5) + g_return_val_if_reached(""); + } return buf; } -#endif /* Windows doesn't HAVE_STRFTIME_Z_FORMAT, but this seems clearer. -- rlaager */ #if !defined(HAVE_STRFTIME_Z_FORMAT) || defined(_WIN32) @@ -600,7 +609,7 @@ fmt ? fmt : "", c - start - 1, start, - get_tmoff(tm)); + purple_get_tzoff_str(tm, FALSE)); g_free(fmt); fmt = tmp; start = c + 1; diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/util.h --- a/libpurple/util.h Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/util.h Fri Jun 29 01:54:45 2007 +0000 @@ -257,6 +257,16 @@ const char *purple_utf8_strftime(const char *format, const struct tm *tm); /** + * Gets a string representation of the local timezone offset + * + * @param tm The time to get the timezone for + * @param iso TRUE to format the offset according to ISO-8601, FALSE to + * not substitute 'Z' for 0 offset, and to not separate + * hours and minutes with a colon. + */ +const char *purple_get_tzoff_str(const struct tm *tm, gboolean iso); + +/** * Formats a time into the user's preferred short date format. * * The returned string is stored in a static buffer, so the result diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/win32/win32dep.c --- a/libpurple/win32/win32dep.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/win32/win32dep.c Fri Jun 29 01:54:45 2007 +0000 @@ -32,6 +32,7 @@ #include #include +#include "internal.h" #include "debug.h" #include "notify.h" diff -r 086cfcb71b01 -r bd44f661f4c8 libpurple/xmlnode.c --- a/libpurple/xmlnode.c Fri Jun 29 01:51:13 2007 +0000 +++ b/libpurple/xmlnode.c Fri Jun 29 01:54:45 2007 +0000 @@ -268,6 +268,22 @@ g_return_if_fail(node != NULL); + /* if we're part of a tree, remove ourselves from the tree first */ + if(NULL != node->parent) { + if(node->parent->child == node) { + node->parent->child = node->next; + } else { + xmlnode *prev = node->parent->child; + while(prev && prev->next != node) { + prev = prev->next; + } + if(prev) { + prev->next = node->next; + } + } + } + + /* now free our children */ x = node->child; while(x) { y = x->next; @@ -275,6 +291,7 @@ x = y; } + /* now dispose of ourselves */ g_free(node->name); g_free(node->data); g_free(node->xmlns); diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/eggtrayicon.c --- a/pidgin/eggtrayicon.c Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/eggtrayicon.c Fri Jun 29 01:54:45 2007 +0000 @@ -152,6 +152,26 @@ } } +static Display * +egg_tray_icon_get_x_display(EggTrayIcon *icon) +{ + Display *xdisplay = NULL; + +#if GTK_CHECK_VERSION(2,1,0) + { + GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (icon)); + if (!GDK_IS_DISPLAY (display)) + display = gdk_display_get_default (); + + xdisplay = GDK_DISPLAY_XDISPLAY (display); + } +#else + xdisplay = gdk_display; +#endif + + return xdisplay; +} + static void egg_tray_icon_get_orientation_property (EggTrayIcon *icon) { @@ -168,11 +188,10 @@ g_return_if_fail(icon->manager_window != None); -#if GTK_CHECK_VERSION(2,1,0) - xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); -#else - xdisplay = gdk_display; -#endif + xdisplay = egg_tray_icon_get_x_display(icon); + + if (xdisplay == NULL) + return; gdk_error_trap_push (); type = None; @@ -321,11 +340,10 @@ if (icon->manager_window != None) return; -#if GTK_CHECK_VERSION(2,1,0) - xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); -#else - xdisplay = gdk_display; -#endif + xdisplay = egg_tray_icon_get_x_display(icon); + + if (xdisplay == NULL) + return; XGrabServer (xdisplay); @@ -424,12 +442,15 @@ make_transparent (widget, NULL); + xdisplay = egg_tray_icon_get_x_display(icon); + + if (xdisplay == NULL) + return; + #if GTK_CHECK_VERSION(2,1,0) screen = gdk_screen_get_number (gtk_widget_get_screen (widget)); - xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)); #else screen = XScreenNumberOfScreen (DefaultScreenOfDisplay (gdk_display)); - xdisplay = gdk_display; #endif /* Now see if there's a manager window around */ @@ -519,11 +540,10 @@ XClientMessageEvent ev; Display *xdisplay; -#if GTK_CHECK_VERSION(2,1,0) - xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); -#else - xdisplay = gdk_display; -#endif + xdisplay = egg_tray_icon_get_x_display(icon); + + if (xdisplay == NULL) + return; ev.type = ClientMessage; ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon)); diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/gtkblist.c --- a/pidgin/gtkblist.c Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/gtkblist.c Fri Jun 29 01:54:45 2007 +0000 @@ -174,6 +174,7 @@ static gboolean gtk_blist_window_state_cb(GtkWidget *w, GdkEventWindowState *event, gpointer data) { +#if GTK_CHECK_VERSION(2,2,0) if(event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) { if(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", FALSE); @@ -195,6 +196,28 @@ if (!(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)) pidgin_blist_refresh_timer(purple_get_blist()); } +#else + /* At least gtk+ 2.0.6 does not properly set the change_mask when unsetting a + * GdkWindowState flag. To work around, the window state will be explicitly + * queried on these older versions of gtk+. See pidgin ticket #739. + */ + GdkWindowState new_window_state = gdk_window_get_state(G_OBJECT(gtkblist->window->window)); + + if(new_window_state & GDK_WINDOW_STATE_WITHDRAWN) { + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", FALSE); + } else { + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", TRUE); + pidgin_blist_refresh_timer(purple_get_blist()); + } + + if(new_window_state & GDK_WINDOW_STATE_MAXIMIZED) + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_maximized", TRUE); + else + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_maximized", FALSE); + + if (!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) + pidgin_blist_refresh_timer(purple_get_blist()); +#endif return FALSE; } @@ -2976,10 +2999,11 @@ signon = purple_presence_get_login_time(presence); if (full && PURPLE_BUDDY_IS_ONLINE(b) && signon > 0) { - if (time(NULL) - signon > 63072000 /* 2 years */) { + if (signon > time(NULL)) { /* - * Our local clock must be wrong, show the actual - * date instead of "4 days", etc. + * They signed on in the future?! Our local clock + * must be wrong, show the actual date instead of + * "4 days", etc. */ tmp = g_strdup(purple_date_format_long(localtime(&signon))); } else diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/gtkconv.c Fri Jun 29 01:54:45 2007 +0000 @@ -184,6 +184,8 @@ static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); +static gboolean infopane_release_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); +static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); static GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { static GdkColor col; @@ -345,15 +347,28 @@ } } -static PurpleCmdRet -clear_command_cb(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) +static void clear_conversation_scrollback(PurpleConversation *conv) { PidginConversation *gtkconv = NULL; gtkconv = PIDGIN_CONVERSATION(conv); gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); +} + +static PurpleCmdRet +clear_command_cb(PurpleConversation *conv, + const char *cmd, char **args, char **error, void *data) +{ + clear_conversation_scrollback(conv); + return PURPLE_CMD_STATUS_OK; +} + +static PurpleCmdRet +clearall_command_cb(PurpleConversation *conv, + const char *cmd, char **args, char **error, void *data) +{ + purple_conversation_foreach(clear_conversation_scrollback); return PURPLE_CMD_STATUS_OK; } @@ -526,13 +541,6 @@ account = purple_conversation_get_account(conv); - if (!purple_account_is_connected(account)) - return; - - if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) && - purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) - return; - if (check_for_and_do_command(conv)) { if (gtkconv->entry_growing) { reset_default_size(gtkconv); @@ -542,6 +550,13 @@ return; } + if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) && + purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) + return; + + if (!purple_account_is_connected(account)) + return; + buf = gtk_imhtml_get_markup(GTK_IMHTML(gtkconv->entry)); clean = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL); @@ -3669,7 +3684,7 @@ if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name))) is_me = TRUE; - is_buddy = (purple_find_buddy(conv->account, name) != NULL); + is_buddy = cb->buddy; tmp = g_utf8_casefold(alias, -1); alias_key = g_utf8_collate_key(tmp, -1); @@ -3877,7 +3892,7 @@ CHAT_USERS_ALIAS_COLUMN, &alias, -1); - if (strcmp(name, alias)) + if (name && alias && strcmp(name, alias)) tab_complete_process_item(&most_matched, entered, &partial, nick_partial, &matches, FALSE, alias); g_free(name); @@ -4377,7 +4392,7 @@ static GtkWidget * setup_common_pane(PidginConversation *gtkconv) { - GtkWidget *paned, *vbox, *frame, *imhtml_sw; + GtkWidget *paned, *vbox, *frame, *imhtml_sw, *event_box; GtkCellRenderer *rend; GtkTreePath *path; PurpleConversation *conv = gtkconv->active_conv; @@ -4393,9 +4408,19 @@ gtk_widget_show(vbox); /* Setup the info pane */ + event_box = gtk_event_box_new(); + gtk_widget_show(event_box); gtkconv->infopane_hbox = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), gtkconv->infopane_hbox, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), event_box, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(event_box), gtkconv->infopane_hbox); gtk_widget_show(gtkconv->infopane_hbox); + gtk_widget_add_events(event_box, + GDK_BUTTON1_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); + g_signal_connect(G_OBJECT(event_box), "button_press_event", + G_CALLBACK(infopane_press_cb), gtkconv); + g_signal_connect(G_OBJECT(event_box), "button_release_event", + G_CALLBACK(infopane_release_cb), gtkconv); + gtkconv->infopane = gtk_cell_view_new(); gtkconv->infopane_model = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING); @@ -5551,7 +5576,7 @@ g_return_if_fail(new_alias != NULL); - cbuddy = purple_conv_chat_cb_new(new_name, new_alias, flags); + cbuddy = purple_conv_chat_cb_find(chat, new_name); add_chat_buddy_common(conv, cbuddy, old_name); } @@ -6180,10 +6205,11 @@ markup = title; } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); - markup = g_strdup_printf("%s\n%s", + const char *topic = purple_conv_chat_get_topic(chat); + markup = g_strdup_printf("%s%s%s", purple_conversation_get_title(conv), pidgin_get_dim_grey_string(gtkconv->infopane), - purple_conv_chat_get_topic(chat)); + topic ? "\n" : "", topic ? topic : ""); } gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter), TEXT_COLUMN, markup, -1); @@ -7190,6 +7216,9 @@ purple_cmd_register("clear", "", PURPLE_CMD_P_DEFAULT, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL, clear_command_cb, _("clear: Clears the conversation scrollback."), NULL); + purple_cmd_register("clearall", "", PURPLE_CMD_P_DEFAULT, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL, + clearall_command_cb, _("clear: Clears all conversation scrollbacks."), NULL); purple_cmd_register("help", "w", PURPLE_CMD_P_DEFAULT, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, NULL, help_command_cb, _("help <command>: Help on a specific command."), NULL); @@ -7594,6 +7623,45 @@ /* * THANK YOU GALEON! */ + +static gboolean +infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv) +{ + int nb_x, nb_y; + + if (e->button != 1 || e->type != GDK_BUTTON_PRESS) + return FALSE; + + if (gtkconv->win->in_drag) { + purple_debug(PURPLE_DEBUG_WARNING, "gtkconv", + "Already in the middle of a window drag at tab_press_cb\n"); + return TRUE; + } + + gtkconv->win->in_predrag = TRUE; + gtkconv->win->drag_tab = gtk_notebook_page_num(GTK_NOTEBOOK(gtkconv->win->notebook), gtkconv->tab_cont); + + gdk_window_get_origin(gtkconv->infopane_hbox->window, &nb_x, &nb_y); + + gtkconv->win->drag_min_x = gtkconv->infopane_hbox->allocation.x + nb_x; + gtkconv->win->drag_min_y = gtkconv->infopane_hbox->allocation.y + nb_y; + gtkconv->win->drag_max_x = gtkconv->infopane_hbox->allocation.width + gtkconv->win->drag_min_x; + gtkconv->win->drag_max_y = gtkconv->infopane_hbox->allocation.height + gtkconv->win->drag_min_y; + + + /* Connect the new motion signals. */ + gtkconv->win->drag_motion_signal = + g_signal_connect(G_OBJECT(gtkconv->win->notebook), "motion_notify_event", + G_CALLBACK(notebook_motion_cb), gtkconv->win); + + gtkconv->win->drag_leave_signal = + g_signal_connect(G_OBJECT(gtkconv->win->notebook), "leave_notify_event", + G_CALLBACK(notebook_leave_cb), gtkconv->win); + + return FALSE; + +} + static gboolean notebook_press_cb(GtkWidget *widget, GdkEventButton *e, PidginWindow *win) { @@ -7683,6 +7751,12 @@ } static gboolean +infopane_release_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv) +{ + return FALSE; +} + +static gboolean notebook_release_cb(GtkWidget *widget, GdkEventButton *e, PidginWindow *win) { PidginWindow *dest_win; @@ -8013,6 +8087,11 @@ return FALSE; } + if (!purple_account_is_connected(gtkconv->active_conv->account)) { + /* Do not allow aliasing someone on a disconnected account. */ + return FALSE; + } + /* alias label */ entry = gtk_entry_new(); gtk_entry_set_has_frame(GTK_ENTRY(entry), FALSE); @@ -8374,8 +8453,7 @@ /* Er, bug in notebooks? Switch to the page manually. */ gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0); - gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), - purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs")); + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); } else gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), TRUE); @@ -8491,14 +8569,16 @@ gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index); - /* go back to tabless if need be */ + /* go back to tabless */ if (pidgin_conv_window_get_gtkconv_count(win) <= 2) { - gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), - purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs")); + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); } win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv); + if (!win->gtkconvs || !win->gtkconvs->next) + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); + if (!win->gtkconvs && win != hidden_convwin) pidgin_conv_window_destroy(win); } diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/gtkdialogs.c diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/gtkimhtml.c Fri Jun 29 01:54:45 2007 +0000 @@ -1002,11 +1002,12 @@ gtk_imhtml_close_tags(imhtml, &iter); gtk_imhtml_insert_html_at_iter(imhtml, text, flags, &iter); - if (!imhtml->wbfo && !plaintext) - gtk_imhtml_close_tags(imhtml, &iter); gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "insert", &iter); gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(imhtml), gtk_text_buffer_get_insert(imhtml->text_buffer), 0, FALSE, 0.0, 0.0); + if (!imhtml->wbfo && !plaintext) + gtk_imhtml_close_tags(imhtml, &iter); + } static void paste_plaintext_received_cb (GtkClipboard *clipboard, const gchar *text, gpointer data) @@ -4938,9 +4939,6 @@ if (imhtml->edit.link) gtk_imhtml_toggle_link(imhtml, NULL); - - gtk_text_buffer_remove_all_tags(imhtml->text_buffer, iter, iter); - } char *gtk_imhtml_get_markup(GtkIMHtml *imhtml) diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/gtkprivacy.c --- a/pidgin/gtkprivacy.c Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/gtkprivacy.c Fri Jun 29 01:54:45 2007 +0000 @@ -366,7 +366,7 @@ dialog = g_new0(PidginPrivacyDialog, 1); - dialog->win = pidgin_create_window(_("Privacy"), PIDGIN_HIG_BORDER, "privacy", FALSE); + dialog->win = pidgin_create_window(_("Privacy"), PIDGIN_HIG_BORDER, "privacy", TRUE); g_signal_connect(G_OBJECT(dialog->win), "delete_event", G_CALLBACK(destroy_cb), dialog); diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/gtksavedstatuses.c --- a/pidgin/gtksavedstatuses.c Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/gtksavedstatuses.c Fri Jun 29 01:54:45 2007 +0000 @@ -658,17 +658,16 @@ G_CALLBACK(status_window_close_cb), dialog); purple_signal_connect(purple_savedstatuses_get_handle(), - "savedstatus-changed", dialog, + "savedstatus-changed", status_window, PURPLE_CALLBACK(current_status_changed), dialog); - purple_signal_connect(purple_savedstatuses_get_handle(), - "savedstatus-added", dialog, + "savedstatus-added", status_window, PURPLE_CALLBACK(saved_status_updated_cb), dialog); purple_signal_connect(purple_savedstatuses_get_handle(), - "savedstatus-deleted", dialog, + "savedstatus-deleted", status_window, PURPLE_CALLBACK(saved_status_updated_cb), dialog); purple_signal_connect(purple_savedstatuses_get_handle(), - "savedstatus-modified", dialog, + "savedstatus-modified", status_window, PURPLE_CALLBACK(saved_status_updated_cb), dialog); gtk_widget_show_all(win); @@ -685,6 +684,7 @@ purple_request_close_with_handle(status_window); purple_notify_close_with_handle(status_window); + purple_signals_disconnect_by_handle(status_window); g_free(status_window); status_window = NULL; } @@ -1140,7 +1140,7 @@ if (edit) dialog->original_title = g_strdup(purple_savedstatus_get_title(saved_status)); - dialog->window = win = pidgin_create_window (_("Status"), PIDGIN_HIG_BORDER, "status", FALSE) ; + dialog->window = win = pidgin_create_window(_("Status"), PIDGIN_HIG_BORDER, "status", TRUE); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(status_editor_destroy_cb), dialog); @@ -1475,7 +1475,7 @@ dialog->account = account; tmp = g_strdup_printf(_("Status for %s"), purple_account_get_username(account)); - dialog->window = win = pidgin_create_window(tmp, PIDGIN_HIG_BORDER, "substatus", FALSE) ; + dialog->window = win = pidgin_create_window(tmp, PIDGIN_HIG_BORDER, "substatus", TRUE); g_free(tmp); g_signal_connect(G_OBJECT(win), "delete_event", @@ -1520,7 +1520,7 @@ /* Status mesage */ hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); label = gtk_label_new_with_mnemonic(_("_Message:")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/gtkstatusbox.c --- a/pidgin/gtkstatusbox.c Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/gtkstatusbox.c Fri Jun 29 01:54:45 2007 +0000 @@ -1016,10 +1016,10 @@ } } -static void -pidgin_status_box_regenerate(PidginStatusBox *status_box) +static gboolean +pidgin_status_box_regenerate_real(PidginStatusBox *status_box) { - GdkPixbuf *pixbuf, *pixbuf2, *pixbuf3, *pixbuf4; + GdkPixbuf *pixbuf, *pixbuf2, *pixbuf3, *pixbuf4, *pixbuf5; GtkIconSize icon_size; icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL); @@ -1049,15 +1049,19 @@ icon_size, "PidginStatusBox"); pixbuf4 = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), PIDGIN_STOCK_STATUS_INVISIBLE, icon_size, "PidginStatusBox"); + pixbuf5 = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), PIDGIN_STOCK_STATUS_BUSY, + icon_size, "PidginStatusBox"); pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf, _("Available"), NULL, GINT_TO_POINTER(PURPLE_STATUS_AVAILABLE)); pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf2, _("Away"), NULL, GINT_TO_POINTER(PURPLE_STATUS_AWAY)); + pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf5, _("Do not disturb"), NULL, GINT_TO_POINTER(PURPLE_STATUS_UNAVAILABLE)); pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf4, _("Invisible"), NULL, GINT_TO_POINTER(PURPLE_STATUS_INVISIBLE)); pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf3, _("Offline"), NULL, GINT_TO_POINTER(PURPLE_STATUS_OFFLINE)); if (pixbuf2) g_object_unref(G_OBJECT(pixbuf2)); if (pixbuf3) g_object_unref(G_OBJECT(pixbuf3)); if (pixbuf4) g_object_unref(G_OBJECT(pixbuf4)); + if (pixbuf5) g_object_unref(G_OBJECT(pixbuf5)); } add_popular_statuses(status_box); @@ -1077,11 +1081,21 @@ } gtk_tree_view_set_model(GTK_TREE_VIEW(status_box->tree_view), GTK_TREE_MODEL(status_box->dropdown_store)); gtk_tree_view_set_search_column(GTK_TREE_VIEW(status_box->tree_view), TEXT_COLUMN); + + return FALSE; +} + +static void +pidgin_status_box_regenerate(PidginStatusBox *status_box) +{ + /* we have to do this in a timeout, so we avoid recursing + * to infinity (and beyond) */ + purple_timeout_add(0, (GSourceFunc)pidgin_status_box_regenerate_real, status_box); } static gboolean combo_box_scroll_event_cb(GtkWidget *w, GdkEventScroll *event, GtkIMHtml *imhtml) { - pidgin_status_box_popup(PIDGIN_STATUS_BOX(w)); + pidgin_status_box_popup(PIDGIN_STATUS_BOX(w)); return TRUE; } diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/gtkutils.c Fri Jun 29 01:54:45 2007 +0000 @@ -1147,6 +1147,9 @@ acc = gtk_widget_get_accessible (w); label = gtk_widget_get_accessible (l); + /* Make sure mnemonics work */ + gtk_label_set_mnemonic_widget(GTK_LABEL(l), w); + /* If this object has no name, set it's name with the label text */ existing_name = atk_object_get_name (acc); if (!existing_name) { diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/pidginstock.c --- a/pidgin/pidginstock.c Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/pidginstock.c Fri Jun 29 01:54:45 2007 +0000 @@ -169,10 +169,8 @@ { PIDGIN_STOCK_TRAY_XA, "tray", "tray-extended-away.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, { PIDGIN_STOCK_TRAY_OFFLINE, "tray", "tray-offline.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, { PIDGIN_STOCK_TRAY_CONNECT, "tray", "tray-connecting.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-new-im.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL } -/* Uncomment me after 2.0.2! - * { PIDGIN_STOCK_TRAY_EMAIL, "tray", "tray-message.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL } - */ + { PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-new-im.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TRAY_EMAIL, "tray", "tray-message.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL } }; static gchar * diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/pidginstock.h --- a/pidgin/pidginstock.h Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/pidginstock.h Fri Jun 29 01:54:45 2007 +0000 @@ -137,9 +137,7 @@ #define PIDGIN_STOCK_TRAY_OFFLINE "pidgin-tray-offline" #define PIDGIN_STOCK_TRAY_CONNECT "pidgin-tray-connect" #define PIDGIN_STOCK_TRAY_PENDING "pidgin-tray-pending" -/* Uncomment me after 2.0.2! - * #define PIDGIN_STOCK_TRAY_EMAIL "pidgin-tray-email" - */ +#define PIDGIN_STOCK_TRAY_EMAIL "pidgin-tray-email" /*@}*/ diff -r 086cfcb71b01 -r bd44f661f4c8 pidgin/plugins/gtkbuddynote.c --- a/pidgin/plugins/gtkbuddynote.c Fri Jun 29 01:51:13 2007 +0000 +++ b/pidgin/plugins/gtkbuddynote.c Fri Jun 29 01:54:45 2007 +0000 @@ -30,8 +30,8 @@ if (full) { const gchar *note = purple_blist_node_get_string(node, "notes"); - if (note != NULL) { - g_string_append_printf(text, _("\nBuddy Note: %s"), + if ((note != NULL) && (*note != '\0')) { + g_string_append_printf(text, _("\nBuddy Note: %s"), note); } } @@ -94,6 +94,7 @@ check_for_buddynote(gpointer data) { PurplePlugin *buddynote = NULL; + PurplePlugin *plugin = (PurplePlugin *)data; buddynote = purple_plugins_find_with_id("core-plugin_pack-buddynote"); @@ -108,6 +109,18 @@ info.dependencies = g_list_append(info.dependencies, "core-plugin_pack-buddynote"); + + /* If non-gtk buddy note plugin is loaded, but we are not, then load + * ourselves, otherwise people upgrading from pre-gtkbuddynote days + * will not have 'Buddy Notes' showing as loaded in the plugins list. + * We also trigger a save on the list of plugins because it's not been + * loaded through the UI. */ + if (purple_plugin_is_loaded(buddynote) && + !purple_plugin_is_loaded(plugin)) { + purple_plugin_load(plugin); + pidgin_plugins_save(); + } + } else { info.flags = PURPLE_PLUGIN_FLAG_INVISIBLE; }