# HG changeset patch # User Casey Harkins # Date 1192730320 0 # Node ID 8b9c48347004b7dc8519a34df1618530d97d99a6 # Parent 33822d7271e5432c25000cbb81d59e4c06c88705# Parent ae330012956f7d355134bfa57dcb9d3140ae1ad5 propagate from branch 'im.pidgin.charkins.dockletgeom' (head 0ac7285573f2998a702d7cbc62e7e8cc91e616e8) to branch 'im.pidgin.pidgin.next.minor' (head 365b126365cc18309aea7f8eef0e9b2a19e6bda8) diff -r 33822d7271e5 -r 8b9c48347004 COPYRIGHT --- a/COPYRIGHT Fri Oct 12 17:10:34 2007 +0000 +++ b/COPYRIGHT Thu Oct 18 17:58:40 2007 +0000 @@ -196,6 +196,7 @@ Akuke Kok Konstantin Korikov Cole Kowalski +Matt Kramer Gary Kramlich Jan Kratochvil Andrej Krivulčík @@ -267,6 +268,7 @@ Ruediger Oertel Gudmundur Bjarni Olafsson Bartosz Oler +Stefan Ott Shawn Outman Nathan Owens (pianocomp81) John Oyler diff -r 33822d7271e5 -r 8b9c48347004 ChangeLog --- a/ChangeLog Fri Oct 12 17:10:34 2007 +0000 +++ b/ChangeLog Thu Oct 18 17:58:40 2007 +0000 @@ -1,5 +1,28 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.3.0: + http://developer.pidgin.im/query?status=closed&milestone=2.3.0 + + libpurple: + * We now honor a PURPLE_DISABLE_DEPRECATED define to allow plugins to + catch deprecated functions earlier rather than later. + + Pidgin: + * If a plugin says it can't be unloaded, we now display an error and + remove the plugin from the list of saved plugins so it won't load + at the next startup. Previously, we were ignoring this case, which + could lead to crashes. + * Mark dialog windows as transient for appropriate parent windows to + help window managers do the right thing (Gabriel Schulhof) + + Finch: + * If a plugin says it can't be unloaded, we now display an error and + remove the plugin from the list of saved plugins so it won't load + at the next startup. Previously, we were ignoring this case, which + could lead to crashes. + * It's possible to bind key-strokes to specific menuitems in the windows. + Read the 'Menus' section in the man-page for details. + version 2.2.2: http://developer.pidgin.im/query?status=closed&milestone=2.2.2 NOTE: Due to 2.2.1 being a security fix release, some bugs @@ -31,6 +54,8 @@ * Pidgin's display is now saved with the command line for session restoration. (David Mohr) * ICQ Birthday notifications are shown as buddy list emblems. + * Plugin actions are now available from the docklet context menu + in addition to the Tool menu of the buddy list. version 2.2.1 (09/29/2007): http://developer.pidgin.im/query?status=closed&milestone=2.2.1 diff -r 33822d7271e5 -r 8b9c48347004 ChangeLog.API --- a/ChangeLog.API Fri Oct 12 17:10:34 2007 +0000 +++ b/ChangeLog.API Thu Oct 18 17:58:40 2007 +0000 @@ -1,13 +1,118 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul -Version 2.2.2 (??/??/????): +version 2.3.0 (??/??/????): + libpurple: + Added: + * purple_request_field_blist_nodes_new and its accessory functions. + * a PurpleConversation field in PurpleConvMessage + * account-authorization signals (see account-signals.dox for + details) (Stefan Ott) + * libpurple/purple.h, which includes #define's and #include's + required to compile stand-alone plugins + * PURPLE_STATUS_TUNE as a new PurpleStatusPrimitive + * purple_plugin_disable(), which is intended to be called when + a purple_plugin_unload()--which was called when a user tried + to unload a plugin--fails. This then prevents the plugin + from being saved in the saved plugins list, so it'll won't + be loaded at the next startup. + * purple_util_init() + * purple_util_uninit() + + * pidgin_dialogs_about_with_parent() + * pidgin_log_show_contact_with_parent() + * pidgin_log_show_with_parent() + * pidgin_plugin_dialog_show_with_parent() + * pidgin_pounce_editor_show_with_parent() + * pidgin_pounces_manager_show_with_parent() + * pidgin_syslog_show_with_parent() + + * purple_request_accept_cancel_with_hint() + * purple_request_action_varg_with_hint() + * purple_request_action_with_hint() + * purple_request_choice_varg_with_hint() + * purple_request_choice_with_hint() + * purple_request_fields_with_hint() + * purple_request_file_with_hint() + * purple_request_folder_with_hint() + * purple_request_input_with_hint() + * purple_request_ok_cancel_with_hint() + * purple_request_yes_no_with_hint() + + UI hints set by libpurple: + * PURPLE_REQUEST_UI_HINT_ACCOUNT + * PURPLE_REQUEST_UI_HINT_BLIST + * PURPLE_REQUEST_UI_HINT_BUDDY + * PURPLE_REQUEST_UI_HINT_CONV + * PURPLE_REQUEST_UI_HINT_REGISTER + * PURPLE_REQUEST_UI_HINT_XFER + + Common UI hints set by UIs: + * PURPLE_REQUEST_UI_HINT_ACCOUNTMGR + * PURPLE_REQUEST_UI_HINT_CERTMGR + * PURPLE_REQUEST_UI_HINT_PLUGINMGR + * PURPLE_REQUEST_UI_HINT_POUNCEMGR + * PURPLE_REQUEST_UI_HINT_PREFSMGR + * PURPLE_REQUEST_UI_HINT_STATUSMGR + + Changed: + * purple_plugin_unload() now honors the return value of a + plugin's unload function and can actually return FALSE now. + * purple_plugin_unload() no longer does its own notifications + when a dependent plugin fails to unload. The UI should do + something appropriate. + + Deprecated: + * pidgin_dialogs_about() + * pidgin_log_show_contact() + * pidgin_log_show() + * pidgin_plugin_dialog_show() + * pidgin_pounce_editor_show() + * pidgin_pounces_manager_show() + * pidgin_syslog_show() + + * purple_request_accept_cancel() + * purple_request_action_varg() + * purple_request_action() + * purple_request_choice_varg() + * purple_request_choice() + * purple_request_fields() + * purple_request_file() + * purple_request_folder() + * purple_request_input() + * purple_request_ok_cancel() + * purple_request_yes_no() + + MSN: + * A new independant status type with PURPLE_STATUS_TUNE primitive, and + PURPLE_TUNE_ARTIST, PURPLE_TUNE_ALBUM and PURPLE_TUNE_TITLE + attributes. + + XMPP: + * A new independant status type with PURPLE_STATUS_TUNE primitive, and + PURPLE_TUNE_{ARTIST, TITLE, ALBUM, GENRE, COMMENT, TRACK, TIME, + YEAR, URL} attributes. + + Finch: + libgnt: + * Added gnt_color_pair, which will try to intelligenty set text + attributes in place of colors if the terminal doesn't have color + support. (Bug: #3560) All future code should use gnt_color_pair + instead of COLOR_PAIR. + * Added gnt_menuitem_set_id and gnt_menuitem_get_id to set and get the + string id of a menuitem respectively. + * Added gnt_window_get_accel_item, which returns a the id of a menuitem + bound to a keystroke. + * Added gnt_menu_get_item to activate and return a menuitem of the + given id from a menu. + +version 2.2.2 (??/??/????): libpurple: Changed: * The size parameter of purple_util_write_data_to_file_absolute has been changed to gssize instead of a size_t to correctly indicate that -1 can be used for a nul-delimited string. -Version 2.2.0 (09/13/2007): +version 2.2.0 (09/13/2007): libpurple: Added: * PURPLE_MESSAGE_INVISIBLE flag, which can be used by @@ -64,7 +169,7 @@ * gnt_util_parse_xhtml_to_textview to parse XHTML strings in a GntTextView (this works only if libxml2 is available) -Version 2.1.1 (08/20/2007): +version 2.1.1 (08/20/2007): libpurple: Changed: * PurpleAccountUiOps.request_authorize's authorize_cb and diff -r 33822d7271e5 -r 8b9c48347004 Doxyfile.in --- a/Doxyfile.in Fri Oct 12 17:10:34 2007 +0000 +++ b/Doxyfile.in Thu Oct 18 17:58:40 2007 +0000 @@ -169,7 +169,8 @@ "endsignalproto=@endcode" \ "signaldesc=@par Description:" \ "signals=@b Signals:" \ - "endsignals=" + "endsignals=" \ + "constreturn=@note The return value of this function must not be modified or freed. @return" # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. @@ -457,7 +458,8 @@ # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = +EXCLUDE = libpurple/purple-client.h \ + libpurple/purple-client-bindings.h # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. @@ -857,7 +859,7 @@ # feature is still experimental and incomplete at the # moment. -GENERATE_XML = NO +GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be @@ -1160,7 +1162,7 @@ # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. -MAX_DOT_GRAPH_DEPTH = 0 +MAX_DOT_GRAPH_DEPTH = 2 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. diff -r 33822d7271e5 -r 8b9c48347004 Makefile.am --- a/Makefile.am Fri Oct 12 17:10:34 2007 +0000 +++ b/Makefile.am Thu Oct 18 17:58:40 2007 +0000 @@ -48,6 +48,13 @@ if HAVE_DOXYGEN @echo "Running doxygen..." @doxygen +if HAVE_XSLTPROC + @echo "Generating devhelp index..." + @xsltproc doxy2devhelp.xsl doc/xml/index.xml > doc/html/pidgin.devhelp + @echo "(Symlink doc/html to ~/.local/share/gtk-doc/html/pidgin to make devhelp see the documentation)" +else + @echo "Not generating devhelp index: xsltproc was not found by configure" +endif else @echo "doxygen was not found during configure. Aborting." @echo; diff -r 33822d7271e5 -r 8b9c48347004 configure.ac --- a/configure.ac Fri Oct 12 17:10:34 2007 +0000 +++ b/configure.ac Thu Oct 18 17:58:40 2007 +0000 @@ -43,10 +43,10 @@ # # Make sure to update finch/libgnt/configure.ac with libgnt version changes. # -m4_define([purple_lt_current], [2]) +m4_define([purple_lt_current], [3]) m4_define([purple_major_version], [2]) -m4_define([purple_minor_version], [2]) -m4_define([purple_micro_version], [2]) +m4_define([purple_minor_version], [3]) +m4_define([purple_micro_version], [0]) m4_define([purple_version_suffix], []) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) @@ -2101,6 +2101,10 @@ [AC_HELP_STRING([--enable-dot], [enable graphs in doxygen via 'dot'])], enable_dot="$enableval", enable_dot="yes") +AC_ARG_ENABLE(devhelp, + [AC_HELP_STRING([--enable-devhelp], + [enable building index for devhelp documentation browser])], + enable_devhelp="$enableval", enable_devhelp="yes") if test "x$enable_doxygen" = xyes; then AC_CHECK_PROG(DOXYGEN, doxygen, true, false) @@ -2120,14 +2124,28 @@ AC_DEFINE_UNQUOTED(HAVE_DOT, 1, [whether or not we have dot]) fi fi + + if test "x$enable_devhelp" = "xyes"; then + AC_CHECK_PROG(XSLTPROC, xsltproc, true, false) + + if test $XSLTPROC = false; then + enable_devhelp="no"; + AC_MSG_WARN([*** xsltproc not found; devhelp index will not be created]) + else + AC_DEFINE_UNQUOTED(HAVE_XSLTPROC, 1, [whether or not we have xsltproc for devhelp index]) + fi + fi fi else enable_dot="no" + enable_devhelp="no" fi AC_SUBST(enable_doxygen) AC_SUBST(enable_dot) +AC_SUBST(enable_devhelp) AM_CONDITIONAL(HAVE_DOXYGEN, test "x$enable_doxygen" = "xyes") +AM_CONDITIONAL(HAVE_XSLTPROC, test "x$enable_devhelp" = "xyes") AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug], [compile with debugging support])], , enable_debug=no) diff -r 33822d7271e5 -r 8b9c48347004 doc/account-signals.dox --- a/doc/account-signals.dox Fri Oct 12 17:10:34 2007 +0000 +++ b/doc/account-signals.dox Thu Oct 18 17:58:40 2007 +0000 @@ -9,6 +9,9 @@ @signal account-setting-info @signal account-set-info @signal account-status-changed + @signal account-authorization-requested + @signal account-authorization-denied + @signal account-authorization-granted @endsignals @see account.h @@ -102,5 +105,41 @@ @param old The alias before change. @endsignaldef + @signaldef account-authorization-requested + @signalproto +void (*account_authorization_requested)(PurpleAccount *account, const char *user); + @endsignalproto + @signaldesc + Emitted when a user requests authorization. + @param account The account. + @param user The name of the user requesting authorization. + @return Less than zero to deny the request without prompting, greater + than zero if the request should be granted. If zero is returned, + then the user will be prompted with the request. + @since 2.3.0 + @endsignaldef + + @signaldef account-authorization-denied + @signalproto +void (*account_authorization_denied)(PurpleAccount *account, const char *user); + @endsignalproto + @signaldesc + Emitted when the authorization request for a buddy is denied. + @param account The account. + @param user The name of the user requesting authorization. + @since 2.3.0 + @endsignaldef + + @signaldef account-authorization-granted + @signalproto +void (*account_authorization_granted)(PurpleAccount *account, const char *user); + @endsignalproto + @signaldesc + Emitted when the authorization request for a buddy is granted. + @param account The account. + @param user The name of the user requesting authorization. + @since 2.3.0 + @endsignaldef + */ // vim: syntax=c.doxygen tw=75 et diff -r 33822d7271e5 -r 8b9c48347004 doc/finch.1.in --- a/doc/finch.1.in Fri Oct 12 17:10:34 2007 +0000 +++ b/doc/finch.1.in Thu Oct 18 17:58:40 2007 +0000 @@ -351,6 +351,35 @@ one of \fBa-\fR, \fBalt-\fR, \fBm-\fR or \fBmeta-\fR. You can also use \fBhome\fR, \fBend\fR, \fBleft\fR, \fBright\fR etc. keys. +.SH Menus +You can also specify key-bindings to trigger specific menuitems in windows. For example, the following entry in \fI~/.gntrc\fR will bind \fBCtrl + t\fR to the 'Send IM...' item in the buddylist: + +[buddylist::menu] +.br +c-t = send-im + +The following is the list of IDs of the current menuitems in the buddylist: + +send-im +.br +join-chat +.br +show-empty-groups +.br +show-offline-buddies +.br +sort-status +.br +sort-alpha +.br +sort-log +.br +add-buddy +.br +add-chat +.br +add-group + .SH Mouse Support There is experimental mouse support. You can focus windows, activate buttons, select rows in a list, scroll using the wheel-scroll etc. Selecting text in a diff -r 33822d7271e5 -r 8b9c48347004 doxy2devhelp.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doxy2devhelp.xsl Thu Oct 18 17:58:40 2007 +0000 @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .html + + + + + + + + + + + + + + + + .html# + + + + + + + + + + + .html# + + + + diff -r 33822d7271e5 -r 8b9c48347004 finch/gntaccount.c --- a/finch/gntaccount.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/gntaccount.c Thu Oct 18 17:58:40 2007 +0000 @@ -632,8 +632,8 @@ prompt = g_strdup_printf(_("Are you sure you want to delete %s?"), purple_account_get_username(account)); - purple_request_action(account, _("Delete Account"), prompt, NULL, 0, - account, NULL, NULL, account, 2, + purple_request_action_with_hint(account, _("Delete Account"), prompt, NULL, 0, + account, NULL, NULL, PURPLE_REQUEST_UI_HINT_ACCOUNTMGR, account, 2, _("Delete"), really_delete_account, _("Cancel"), NULL); g_free(prompt); @@ -881,10 +881,10 @@ data->alias = (alias != NULL ? g_strdup(alias) : NULL); buffer = make_info(account, gc, remote_user, id, alias, msg); - purple_request_action(NULL, NULL, _("Add buddy to your list?"), + purple_request_action_with_hint(NULL, NULL, _("Add buddy to your list?"), buffer, PURPLE_DEFAULT_ACTION_NONE, account, remote_user, NULL, - data, 2, + PURPLE_REQUEST_UI_HINT_BLIST, data, 2, _("Add"), G_CALLBACK(add_user_cb), _("Cancel"), G_CALLBACK(free_add_user_data)); g_free(buffer); @@ -969,10 +969,10 @@ 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, + widget = purple_request_action_with_hint(NULL, _("Authorize buddy?"), buffer, NULL, PURPLE_DEFAULT_ACTION_NONE, account, remote_user, NULL, - aa, 2, + PURPLE_REQUEST_UI_HINT_BLIST, aa, 2, _("Authorize"), authorize_and_add_cb, _("Deny"), deny_no_add_cb); gnt_screen_release(widget); @@ -996,10 +996,10 @@ 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, + uihandle = purple_request_action_with_hint(NULL, _("Authorize buddy?"), buffer, NULL, PURPLE_DEFAULT_ACTION_NONE, account, remote_user, NULL, - user_data, 2, + PURPLE_REQUEST_UI_HINT_BLIST, user_data, 2, _("Authorize"), auth_cb, _("Deny"), deny_cb); } diff -r 33822d7271e5 -r 8b9c48347004 finch/gntblist.c --- a/finch/gntblist.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/gntblist.c Thu Oct 18 17:58:40 2007 +0000 @@ -338,12 +338,12 @@ purple_request_field_account_set_value(field, account); purple_request_field_group_add_field(group, field); - purple_request_fields(NULL, _("Add Buddy"), NULL, _("Please enter buddy information."), + purple_request_fields_with_hint(NULL, _("Add Buddy"), NULL, _("Please enter buddy information."), fields, _("Add"), G_CALLBACK(add_buddy_cb), _("Cancel"), NULL, account, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_BLIST, NULL); } static void @@ -416,11 +416,11 @@ field = purple_request_field_bool_new("autojoin", _("Auto-join"), FALSE); purple_request_field_group_add_field(group, field); - purple_request_fields(NULL, _("Add Chat"), NULL, + purple_request_fields_with_hint(NULL, _("Add Chat"), NULL, _("You can edit more information from the context menu later."), fields, _("Add"), G_CALLBACK(add_chat_cb), _("Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_BLIST, NULL); } static void @@ -451,11 +451,11 @@ static void finch_request_add_group() { - purple_request_input(NULL, _("Add Group"), NULL, _("Enter the name of the group"), + purple_request_input_with_hint(NULL, _("Add Group"), NULL, _("Enter the name of the group"), NULL, FALSE, FALSE, NULL, _("Add"), G_CALLBACK(add_group_cb), _("Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_BLIST, NULL); } static PurpleBlistUiOps blist_ui_ops = @@ -799,10 +799,10 @@ g_list_free(parts); - purple_request_fields(NULL, _("Edit Chat"), NULL, _("Please Update the necessary fields."), + purple_request_fields_with_hint(NULL, _("Edit Chat"), NULL, _("Please Update the necessary fields."), fields, _("Edit"), G_CALLBACK(chat_components_edit_ok), _("Cancel"), NULL, NULL, NULL, NULL, - chat); + PURPLE_REQUEST_UI_HINT_BLIST, chat); } static void @@ -1000,11 +1000,11 @@ prompt = g_strdup_printf(_("Please enter the new name for %s"), name); text = PURPLE_BLIST_NODE_IS_GROUP(node) ? _("Rename") : _("Set Alias"); - purple_request_input(node, text, prompt, _("Enter empty string to reset the name."), + purple_request_input_with_hint(node, text, prompt, _("Enter empty string to reset the name."), name, FALSE, FALSE, NULL, text, G_CALLBACK(rename_blist_node), _("Cancel"), NULL, NULL, NULL, NULL, - node); + PURPLE_REQUEST_UI_HINT_BLIST, node); g_free(prompt); } @@ -1092,11 +1092,11 @@ primary = g_strdup_printf(_("Are you sure you want to remove %s?"), name); /* XXX: anything to do with the returned ui-handle? */ - purple_request_action(node, _("Confirm Remove"), + purple_request_action_with_hint(node, _("Confirm Remove"), primary, sec, 1, account, name, NULL, - node, 2, + PURPLE_REQUEST_UI_HINT_BLIST, node, 2, _("Remove"), finch_blist_remove_node, _("Cancel"), NULL); g_free(primary); @@ -2215,7 +2215,7 @@ purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("New Instant Message"), + purple_request_fields_with_hint(purple_get_blist(), _("New Instant Message"), NULL, _("Please enter the screen name or alias of the person " "you would like to IM."), @@ -2223,7 +2223,7 @@ _("OK"), G_CALLBACK(send_im_select_cb), _("Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_BLIST, NULL); } static void @@ -2279,14 +2279,14 @@ purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("Join a Chat"), + purple_request_fields_with_hint(purple_get_blist(), _("Join a Chat"), NULL, _("Please enter the name of the chat you want to join."), fields, _("Join"), G_CALLBACK(join_chat_select_cb), _("Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_BLIST, NULL); } static void @@ -2328,10 +2328,12 @@ gnt_menuitem_set_submenu(item, GNT_MENU(sub)); item = gnt_menuitem_new(_("Send IM...")); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), "send-im"); gnt_menu_add_item(GNT_MENU(sub), item); gnt_menuitem_set_callback(GNT_MENU_ITEM(item), send_im_select, NULL); item = gnt_menuitem_new(_("Join Chat...")); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), "join-chat"); gnt_menu_add_item(GNT_MENU(sub), item); gnt_menuitem_set_callback(GNT_MENU_ITEM(item), join_chat_select, NULL); @@ -2341,12 +2343,14 @@ gnt_menuitem_set_submenu(item, GNT_MENU(subsub)); item = gnt_menuitem_check_new(_("Empty groups")); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), "show-empty-groups"); gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), purple_prefs_get_bool(PREF_ROOT "/emptygroups")); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(GNT_MENU_ITEM(item), toggle_pref_cb, PREF_ROOT "/emptygroups"); item = gnt_menuitem_check_new(_("Offline buddies")); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), "show-offline-buddies"); gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), purple_prefs_get_bool(PREF_ROOT "/showoffline")); gnt_menu_add_item(GNT_MENU(subsub), item); @@ -2358,14 +2362,17 @@ gnt_menuitem_set_submenu(item, GNT_MENU(subsub)); item = gnt_menuitem_new(_("By Status")); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), "sort-status"); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(GNT_MENU_ITEM(item), sort_blist_change_cb, "status"); item = gnt_menuitem_new(_("Alphabetically")); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), "sort-alpha"); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(GNT_MENU_ITEM(item), sort_blist_change_cb, "text"); item = gnt_menuitem_new(_("By Log Size")); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), "sort-log"); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(GNT_MENU_ITEM(item), sort_blist_change_cb, "log"); @@ -2376,14 +2383,17 @@ gnt_menuitem_set_submenu(item, GNT_MENU(subsub)); item = gnt_menuitem_new("Buddy"); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), "add-buddy"); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(item, menu_add_buddy_cb, NULL); item = gnt_menuitem_new("Chat"); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), "add-chat"); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(item, menu_add_chat_cb, NULL); item = gnt_menuitem_new("Group"); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), "add-group"); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(item, menu_add_group_cb, NULL); diff -r 33822d7271e5 -r 8b9c48347004 finch/gntcertmgr.c --- a/finch/gntcertmgr.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/gntcertmgr.c Thu Oct 18 17:58:40 2007 +0000 @@ -82,7 +82,7 @@ if (crt != NULL) { gchar *default_hostname; default_hostname = purple_certificate_get_subject_name(crt); - purple_request_input(NULL, + purple_request_input_with_hint(NULL, _("Certificate Import"), _("Specify a hostname"), _("Type the host name this certificate is for."), @@ -90,7 +90,7 @@ _("OK"), G_CALLBACK(tls_peers_mgmt_import_ok2_cb), _("Cancel"), G_CALLBACK(tls_peers_mgmt_import_cancel2_cb), NULL, NULL, NULL, - crt); + PURPLE_REQUEST_UI_HINT_CERTMGR, crt); g_free(default_hostname); } else { gchar * secondary; @@ -106,13 +106,13 @@ static void add_cert_cb(GntWidget *button, gpointer null) { - purple_request_file(NULL, + purple_request_file_with_hint(NULL, _("Select a PEM certificate"), "certificate.pem", FALSE, G_CALLBACK(tls_peers_mgmt_import_ok_cb), NULL, - NULL, NULL, NULL, NULL ); + NULL, NULL, NULL, PURPLE_REQUEST_UI_HINT_CERTMGR, NULL ); } /* Save certs in some file */ @@ -155,13 +155,13 @@ return; } - purple_request_file((void*)key, + purple_request_file_with_hint((void*)key, _("PEM X.509 Certificate Export"), "certificate.pem", TRUE, G_CALLBACK(tls_peers_mgmt_export_ok_cb), G_CALLBACK(purple_certificate_destroy), NULL, NULL, NULL, - crt); + PURPLE_REQUEST_UI_HINT_CERTMGR, crt); } /* Show information about a cert */ @@ -233,10 +233,10 @@ primary = g_strdup_printf(_("Really delete certificate for %s?"), key); purple_request_close_with_handle((void *)key); - purple_request_yes_no((void *)key, _("Confirm certificate delete"), + purple_request_yes_no_with_hint((void *)key, _("Confirm certificate delete"), primary, NULL, 2, - NULL, NULL, NULL, + NULL, NULL, NULL, PURPLE_REQUEST_UI_HINT_CERTMGR, g_strdup(key), tls_peers_mgmt_delete_confirm_cb, g_free); diff -r 33822d7271e5 -r 8b9c48347004 finch/gntconn.c --- a/finch/gntconn.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/gntconn.c Thu Oct 18 17:58:40 2007 +0000 @@ -130,9 +130,9 @@ "Finch will not attempt to reconnect the account until you " "correct the error and re-enable the account."), text); - purple_request_action(account, NULL, primary, secondary, 2, + purple_request_action_with_hint(account, NULL, primary, secondary, 2, account, NULL, NULL, - account, 3, + PURPLE_REQUEST_UI_HINT_BLIST, account, 3, _("OK"), NULL, _("Modify Account"), PURPLE_CALLBACK(ce_modify_account_cb), _("Re-enable Account"), PURPLE_CALLBACK(ce_enable_account_cb)); diff -r 33822d7271e5 -r 8b9c48347004 finch/gntnotify.c --- a/finch/gntnotify.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/gntnotify.c Thu Oct 18 17:58:40 2007 +0000 @@ -194,6 +194,7 @@ PurpleAccount *account = purple_connection_get_account(gc); GString *message = g_string_new(NULL); void *ret; + static int key = 0; if (!detailed) { @@ -212,7 +213,7 @@ to = g_strdup_printf("%s (%s)", tos ? *tos : purple_account_get_username(account), purple_account_get_protocol_name(account)); - gnt_tree_add_row_after(GNT_TREE(emaildialog.tree), GINT_TO_POINTER(time(NULL)), + gnt_tree_add_row_after(GNT_TREE(emaildialog.tree), GINT_TO_POINTER(++key), gnt_tree_create_row(GNT_TREE(emaildialog.tree), to, froms ? *froms : "[Unknown sender]", *subjects), @@ -360,7 +361,8 @@ i = 0; for (iter = results->columns; iter; iter = iter->next) { - gnt_tree_set_column_title(GNT_TREE(tree), i, iter->data); + PurpleNotifySearchColumn *column = iter->data; + gnt_tree_set_column_title(GNT_TREE(tree), i, column->title); i++; } diff -r 33822d7271e5 -r 8b9c48347004 finch/gntplugin.c --- a/finch/gntplugin.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/gntplugin.c Thu Oct 18 17:58:40 2007 +0000 @@ -83,6 +83,7 @@ if (!purple_plugin_unload(plugin)) { purple_notify_error(NULL, _("ERROR"), _("unloading plugin failed"), NULL); + purple_plugin_disable(plugin); gnt_tree_set_choice(GNT_TREE(tree), plugin, TRUE); } @@ -468,9 +469,9 @@ } } - return purple_request_fields(NULL, _("Preferences"), NULL, NULL, fields, + return purple_request_fields_with_hint(NULL, _("Preferences"), NULL, NULL, fields, _("Save"), G_CALLBACK(finch_request_save_in_prefs), _("Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_PLUGINMGR, NULL); } diff -r 33822d7271e5 -r 8b9c48347004 finch/gntpounce.c --- a/finch/gntpounce.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/gntpounce.c Thu Oct 18 17:58:40 2007 +0000 @@ -660,9 +660,9 @@ pouncer = purple_account_get_username(account); pouncee = purple_pounce_get_pouncee(pounce); buf = g_strdup_printf(_("Are you sure you want to delete the pounce on %s for %s?"), pouncee, pouncer); - purple_request_action(pounce, NULL, buf, NULL, 0, + purple_request_action_with_hint(pounce, NULL, buf, NULL, 0, account, pouncee, NULL, - pounce, 2, + PURPLE_REQUEST_UI_HINT_POUNCEMGR, pounce, 2, _("Delete"), pounces_manager_delete_confirm_cb, _("Cancel"), NULL); g_free(buf); diff -r 33822d7271e5 -r 8b9c48347004 finch/gntprefs.c --- a/finch/gntprefs.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/gntprefs.c Thu Oct 18 17:58:40 2007 +0000 @@ -261,9 +261,9 @@ add_pref_group(fields, _("Idle"), idle); pref_request.showing = TRUE; - pref_request.window = purple_request_fields(NULL, _("Preferences"), NULL, NULL, fields, + pref_request.window = purple_request_fields_with_hint(NULL, _("Preferences"), NULL, NULL, fields, _("Save"), G_CALLBACK(save_cb), _("Cancel"), free_strings, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_PREFSMGR, NULL); } diff -r 33822d7271e5 -r 8b9c48347004 finch/gntrequest.c --- a/finch/gntrequest.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/gntrequest.c Thu Oct 18 17:58:40 2007 +0000 @@ -148,7 +148,7 @@ const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data) + const char *ui_hint, void *user_data) { GntWidget *window, *box, *entry; @@ -205,7 +205,7 @@ const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, va_list choices) + const char *ui_hint, void *user_data, va_list choices) { GntWidget *window, *combo, *box; const char *text; @@ -249,7 +249,7 @@ finch_request_action(const char *title, const char *primary, const char *secondary, int default_value, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, size_t actioncount, + const char *ui_hint, void *user_data, size_t actioncount, va_list actions) { GntWidget *window, *box, *button; @@ -393,7 +393,7 @@ const char *ok, GCallback ok_cb, const char *cancel, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *userdata) + const char *ui_hint, void *userdata) { GntWidget *window, *box; GList *grlist; @@ -645,7 +645,7 @@ gboolean savedialog, GCallback ok_cb, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data) + const char *ui_hint, void *user_data) { GntWidget *window = gnt_file_sel_new(); GntFileSel *sel = GNT_FILE_SEL(window); diff -r 33822d7271e5 -r 8b9c48347004 finch/gntstatus.c --- a/finch/gntstatus.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/gntstatus.c Thu Oct 18 17:58:40 2007 +0000 @@ -138,9 +138,9 @@ ask = g_strdup_printf(_("Are you sure you want to delete \"%s\""), purple_savedstatus_get_title(saved)); - purple_request_action(saved, _("Delete Status"), ask, NULL, 0, + purple_request_action_with_hint(saved, _("Delete Status"), ask, NULL, 0, NULL, NULL, NULL, - saved, 2, + PURPLE_REQUEST_UI_HINT_STATUSMGR, saved, 2, _("Delete"), really_delete_status, _("Cancel"), NULL); g_free(ask); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gnt.h --- a/finch/libgnt/gnt.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gnt.h Thu Oct 18 17:58:40 2007 +0000 @@ -46,19 +46,19 @@ #endif /** - * + * Initialize GNT. */ void gnt_init(void); /** - * + * Start running the mainloop for gnt. */ void gnt_main(void); /** - * + * Check whether the terminal is capable of UTF8 display. * - * @return + * @return @c FALSE if the terminal is capable of drawing UTF-8, @c TRUE otherwise. */ gboolean gnt_ascii_only(void); @@ -71,106 +71,133 @@ * @since 2.0.0 (gnt), 2.1.0 (pidgin) */ void gnt_window_present(GntWidget *window); + /** - * - * @param widget + * @internal + * Use #gnt_widget_show instead. */ void gnt_screen_occupy(GntWidget *widget); /** - * - * @param widget + * @internal + * Use #gnt_widget_hide instead. */ void gnt_screen_release(GntWidget *widget); /** - * - * @param widget + * @internal + * Use #gnt_widget_draw instead. */ void gnt_screen_update(GntWidget *widget); /** - * - * @param widget - * @param width - * @param height + * Resize a widget. + * + * @param widget The widget to resize. + * @param width The desired width. + * @param height The desired height. */ void gnt_screen_resize_widget(GntWidget *widget, int width, int height); /** - * - * @param widget - * @param x - * @param y + * Move a widget. + * + * @param widget The widget to move. + * @param x The desired x-coordinate. + * @param y The desired y-coordinate. */ void gnt_screen_move_widget(GntWidget *widget, int x, int y); /** - * - * @param widget - * @param text + * Rename a widget. + * + * @param widget The widget to rename. + * @param text The new name for the widget. */ void gnt_screen_rename_widget(GntWidget *widget, const char *text); /** - * - * @param widget + * Check whether a widget has focus. * - * @return + * @param widget The widget. + * + * @return @c TRUE if the widget has the current focus, @c FALSE otherwise. */ gboolean gnt_widget_has_focus(GntWidget *widget); /** - * - * @param widget + * Set the URGENT hint for a widget. + * + * @param widget The widget to set the URGENT hint for. */ void gnt_widget_set_urgent(GntWidget *widget); /** - * - * @param label - * @param callback + * Register a global action. + * + * @param label The user-visible label for the action. + * @param callback The callback function for the action. */ void gnt_register_action(const char *label, void (*callback)()); /** - * - * @param menu + * Show a menu. * - * @return + * @param menu The menu to display. + * + * @return @c TRUE if the menu is displayed, @c FALSE otherwise (e.g., if another menu is currently displayed). */ gboolean gnt_screen_menu_show(gpointer menu); /** - * + * Terminate the mainloop of gnt. */ void gnt_quit(void); /** - * + * Get the global clipboard. * - * @return + * @return The clipboard. */ GntClipboard * gnt_get_clipboard(void); /** - * + * Get the string in the clipboard. * - * @return + * @return A copy of the string in the clipboard. The caller must @c g_free the string. */ gchar * gnt_get_clipboard_string(void); /** - * - * @param string + * Set the contents of the global clipboard. + * + * @param string The new content of the new clipboard. */ -void gnt_set_clipboard_string(gchar *string); +void gnt_set_clipboard_string(const gchar *string); /** * Spawn a different application that will consume the console. + * + * @param wd The working directory for the new application. + * @param argv The argument vector. + * @param envp The environment, or @c NULL. + * @param stin Location to store the child's stdin, or @c NULL. + * @param stout Location to store the child's stdout, or @c NULL. + * @param sterr Location to store the child's stderr, or @c NULL. + * @param callback The callback to call after the child exits. + * @param data The data to pass to the callback. + * + * @return @c TRUE if the child was successfully spawned, @c FALSE otherwise. */ gboolean gnt_giveup_console(const char *wd, char **argv, char **envp, gint *stin, gint *stout, gint *sterr, void (*callback)(int status, gpointer data), gpointer data); +/** + * Check whether a child process is in control of the current terminal. + * + * @return @c TRUE if a child process (eg., PAGER) is occupying the current + * terminal, @c FALSE otherwise. + */ gboolean gnt_is_refugee(void); + diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntbindable.h --- a/finch/libgnt/gntbindable.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntbindable.h Thu Oct 18 17:58:40 2007 +0000 @@ -160,8 +160,8 @@ /** * Returns a GntTree populated with "key" -> "binding" for the widget. - * - * @param widget The object to list the bindings for. + * + * @param bind The object to list the bindings for. * * @return The GntTree. */ @@ -170,9 +170,9 @@ /** * Builds a window that list the key bindings for a GntBindable object. * From this window a user can select a listing to rebind a new key for the given action. - * + * * @param bindable The object to list the bindings for. - * + * * @return @c TRUE */ diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntbox.c --- a/finch/libgnt/gntbox.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntbox.c Thu Oct 18 17:58:40 2007 +0000 @@ -80,12 +80,12 @@ get_title_thingies(box, title, &pos, &right); if (gnt_widget_has_focus(widget)) - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE)); + wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_TITLE)); else - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE_D)); - mvwaddch(widget->window, 0, pos-1, ACS_RTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_TITLE_D)); + mvwaddch(widget->window, 0, pos-1, ACS_RTEE | gnt_color_pair(GNT_COLOR_NORMAL)); mvwaddstr(widget->window, 0, pos, title); - mvwaddch(widget->window, 0, right, ACS_LTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); + mvwaddch(widget->window, 0, right, ACS_LTEE | gnt_color_pair(GNT_COLOR_NORMAL)); g_free(title); } @@ -603,7 +603,7 @@ /* Erase the old title */ int pos, right; get_title_thingies(b, prev, &pos, &right); - mvwhline(w->window, 0, pos - 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + mvwhline(w->window, 0, pos - 1, ACS_HLINE | gnt_color_pair(GNT_COLOR_NORMAL), right - pos + 2); g_free(prev); } diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntbutton.c --- a/finch/libgnt/gntbutton.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntbutton.c Thu Oct 18 17:58:40 2007 +0000 @@ -47,7 +47,7 @@ else type = GNT_COLOR_NORMAL; - wbkgdset(widget->window, '\0' | COLOR_PAIR(type)); + wbkgdset(widget->window, '\0' | gnt_color_pair(type)); mvwaddstr(widget->window, (small_button) ? 0 : 1, 2, button->priv->text); if (small_button) { type = GNT_COLOR_HIGHLIGHT; @@ -126,6 +126,7 @@ widget->priv.minh = small_button ? 1 : 3; if (small_button) GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); + GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y); GNTDEBUG; } diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntcheckbox.c --- a/finch/libgnt/gntcheckbox.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntcheckbox.c Thu Oct 18 17:58:40 2007 +0000 @@ -43,13 +43,13 @@ else type = GNT_COLOR_NORMAL; - wbkgdset(widget->window, '\0' | COLOR_PAIR(type)); + wbkgdset(widget->window, '\0' | gnt_color_pair(type)); text = g_strdup_printf("[%c]", cb->checked ? 'X' : ' '); mvwaddstr(widget->window, 0, 0, text); g_free(text); - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_NORMAL)); mvwaddstr(widget->window, 0, 4, GNT_BUTTON(cb)->priv->text); GNTDEBUG; diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntcolors.c --- a/finch/libgnt/gntcolors.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntcolors.c Thu Oct 18 17:58:40 2007 +0000 @@ -32,6 +32,7 @@ #include #include +static gboolean hascolors; static struct { short r, g, b; @@ -75,6 +76,8 @@ init = TRUE; start_color(); + if (!(hascolors = has_colors())) + return; defaults = use_default_colors(); if (can_use_custom_color()) @@ -276,3 +279,11 @@ } #endif /* GKeyFile */ + +int gnt_color_pair(int pair) +{ + return (hascolors ? COLOR_PAIR(pair) : + ((pair == GNT_COLOR_NORMAL || pair == GNT_COLOR_HIGHLIGHT_D || + pair == GNT_COLOR_TITLE_D || pair == GNT_COLOR_DISABLED) ? 0 : A_STANDOUT)); +} + diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntcolors.h --- a/finch/libgnt/gntcolors.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntcolors.h Thu Oct 18 17:58:40 2007 +0000 @@ -88,4 +88,17 @@ #endif +/** + * Return the appropriate character attribute for a specified color. + * If the terminal doesn't have color support, this returns A_STANDOUT + * when deemed appropriate. + * + * @param color The color code. + * + * @return A character attribute. + * + * @since 2.3.0 + */ +int gnt_color_pair(int color); + #endif diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntcombobox.c --- a/finch/libgnt/gntcombobox.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntcombobox.c Thu Oct 18 17:58:40 2007 +0000 @@ -85,15 +85,15 @@ else type = GNT_COLOR_NORMAL; - wbkgdset(widget->window, '\0' | COLOR_PAIR(type)); + wbkgdset(widget->window, '\0' | gnt_color_pair(type)); s = (char*)gnt_util_onscreen_width_to_pointer(text, widget->priv.width - 4, &len); *s = '\0'; mvwaddstr(widget->window, 1, 1, text); - whline(widget->window, ' ' | COLOR_PAIR(type), widget->priv.width - 4 - len); - mvwaddch(widget->window, 1, widget->priv.width - 3, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL)); - mvwaddch(widget->window, 1, widget->priv.width - 2, ACS_DARROW | COLOR_PAIR(GNT_COLOR_NORMAL)); + whline(widget->window, ' ' | gnt_color_pair(type), widget->priv.width - 4 - len); + mvwaddch(widget->window, 1, widget->priv.width - 3, ACS_VLINE | gnt_color_pair(GNT_COLOR_NORMAL)); + mvwaddch(widget->window, 1, widget->priv.width - 2, ACS_DARROW | gnt_color_pair(GNT_COLOR_NORMAL)); g_free(text); GNTDEBUG; diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntentry.c --- a/finch/libgnt/gntentry.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntentry.c Thu Oct 18 17:58:40 2007 +0000 @@ -201,9 +201,9 @@ gboolean focus; if ((focus = gnt_widget_has_focus(widget))) - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TEXT_NORMAL)); + wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_TEXT_NORMAL)); else - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); + wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_HIGHLIGHT_D)); if (entry->masked) { diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntfilesel.c --- a/finch/libgnt/gntfilesel.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntfilesel.c Thu Oct 18 17:58:40 2007 +0000 @@ -718,6 +718,7 @@ void gnt_file_sel_set_suggested_filename(GntFileSel *sel, const char *suggest) { + g_free(sel->suggest); sel->suggest = g_strdup(suggest); } diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntfilesel.h --- a/finch/libgnt/gntfilesel.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntfilesel.h Thu Oct 18 17:58:40 2007 +0000 @@ -98,113 +98,123 @@ G_BEGIN_DECLS /** - * - * - * @return + * @return GType for GntFileSel. */ GType gnt_file_sel_get_gtype(void); /** - * + * Create a new file selector. * - * @return + * @return The newly created file selector. */ GntWidget * gnt_file_sel_new(void); /** - * - * @param sel - * @param path + * Set the current location of the file selector. * - * @return + * @param sel The file selector. + * @param path The current path of the selector. + * + * @return @c TRUE if the current location was successfully changed, @c FALSE otherwise. */ gboolean gnt_file_sel_set_current_location(GntFileSel *sel, const char *path); /** - * - * @param sel - * @param dirs + * Set wheter to only allow selecting directories. + * + * @param sel The file selector. + * @param dirs @c TRUE if only directories can be selected, @c FALSE if files + * can also be selected. */ void gnt_file_sel_set_dirs_only(GntFileSel *sel, gboolean dirs); /** - * - * @param sel + * Check whether the file selector allows only selecting directories. * - * @return + * @param sel The file selector. + * + * @return @c TRUE if only directories can be selected. */ gboolean gnt_file_sel_get_dirs_only(GntFileSel *sel); /** - * - * @param sel - * @param must + * Set whether a selected file must exist. + * + * @param sel The file selector. + * @param must @c TRUE if the selected file must exist. */ void gnt_file_sel_set_must_exist(GntFileSel *sel, gboolean must); /** - * - * @param sel + * Check whether the selector allows selecting non-existent files. * - * @return + * @param sel The file selector. + * + * @return @c TRUE if the selected file must exist, @c FALSE if a non-existent + * file can be selected. */ gboolean gnt_file_sel_get_must_exist(GntFileSel *sel); /** - * - * @param sel + * Get the selected file in the selector. * - * @return + * @param sel The file selector. + * + * @return The path of the selected file. The caller should g_free the returned + * string. */ char * gnt_file_sel_get_selected_file(GntFileSel *sel); - /* The returned value should be free'd */ - /** - * - * @param sel + * Get the list of selected files in the selector. * - * @return + * @param sel The file selector. + * + * @return A list of paths for the selected files. The caller must g_free the + * contents of the list, and g_list_free the list. */ GList * gnt_file_sel_get_selected_multi_files(GntFileSel *sel); /** - * - * @param sel - * @param set + * Allow selecting multiple files. + * + * @param sel The file selector. + * @param set @c TRUE if selecting multiple files should be allowed. */ void gnt_file_sel_set_multi_select(GntFileSel *sel, gboolean set); /** - * - * @param sel - * @param suggest + * Set the suggested file to have selected at startup. + * + * @param sel The file selector. + * @param suggest The suggested filename. */ void gnt_file_sel_set_suggested_filename(GntFileSel *sel, const char *suggest); /** - * - * @param sel - * @param path - * @param files - * @param error) + * Set custom functions to read the names of files. + * + * @param sel The file selector. + * @param read_fn The custom read function. */ void gnt_file_sel_set_read_fn(GntFileSel *sel, gboolean (*read_fn)(const char *path, GList **files, GError **error)); /** - * - * @param name - * @param size + * Create a new GntFile. * - * @return + * @param name The name of the file. + * @param size The size of the file. + * + * @return The newly created GntFile. */ GntFile* gnt_file_new(const char *name, unsigned long size); /** - * - * @param name + * Create a new GntFile for a directory. * - * @return + * @param name The name of the directory. + * + * @return The newly created GntFile. */ GntFile* gnt_file_new_dir(const char *name); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntkeys.h --- a/finch/libgnt/gntkeys.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntkeys.h Thu Oct 18 17:58:40 2007 +0000 @@ -104,41 +104,59 @@ #define GNT_KEY_F12 SAFE(key_f12) /** - * This will do stuff with the terminal settings and stuff. - */ -/** - * + * Initialize the keys. */ void gnt_init_keys(void); /** - * - * @param text + * Refine input text. This usually looks at what the terminal claims it is, + * and tries to change the text to work around some oft-broken terminfo entries. + * + * @param text The input text to refine. */ void gnt_keys_refine(char *text); +/** + * Translate a user-readable representation of an input to a machine-readable representation. + * + * @param name The user-readable representation of an input (eg.: c-t) + * + * @return A machine-readable representation of the input. + */ const char *gnt_key_translate(const char *name); + +/** + * Translate a machine-readable representation of an input to a user-readable representation. + * + * @param key The machine-readable representation of an input. + * + * @return A user-readable representation of the input (eg.: c-t). + */ const char *gnt_key_lookup(const char *key); /** - * - * @param path + * Add a key combination to the internal key-tree. + * + * @param key The key to add */ -void gnt_keys_add_combination(const char *path); +void gnt_keys_add_combination(const char *key); /** - * - * @param path + * Remove a key combination from the internal key-tree. + * + * @param key The key to remove. */ -void gnt_keys_del_combination(const char *path); +void gnt_keys_del_combination(const char *key); /** - * - * @param path + * Find a combination from the given string. + * + * @param key The input string. * - * @return + * @return The number of bytes in the combination that starts at the beginning + * of key (can be 0). */ -int gnt_keys_find_combination(const char *path); +int gnt_keys_find_combination(const char *key); /* A lot of commonly used variable names are defined in . * #undef them to make life easier for everyone. */ diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntlabel.h --- a/finch/libgnt/gntlabel.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntlabel.h Thu Oct 18 17:58:40 2007 +0000 @@ -67,33 +67,34 @@ G_BEGIN_DECLS /** - * - * - * @return + * @return GType for GntLabel. */ GType gnt_label_get_gtype(void); /** - * - * @param text + * Create a new GntLabel. * - * @return + * @param text The text of the label. + * + * @return The newly created label. */ GntWidget * gnt_label_new(const char *text); /** - * - * @param text - * @param flags + * Create a new label with specified text attributes. * - * @return + * @param text The text. + * @param flags Text attributes for the text. + * + * @return The newly created label. */ GntWidget * gnt_label_new_with_format(const char *text, GntTextFormatFlags flags); /** - * - * @param label - * @param text + * Change the text of a label. + * + * @param label The label. + * @param text The new text to set in the label. */ void gnt_label_set_text(GntLabel *label, const char *text); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntline.c --- a/finch/libgnt/gntline.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntline.c Thu Oct 18 17:58:40 2007 +0000 @@ -40,10 +40,10 @@ { GntLine *line = GNT_LINE(widget); if (line->vertical) - mvwvline(widget->window, 1, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + mvwvline(widget->window, 1, 0, ACS_VLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.height - 2); else - mvwhline(widget->window, 0, 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + mvwhline(widget->window, 0, 1, ACS_HLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.width - 2); } diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntline.h --- a/finch/libgnt/gntline.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntline.h Thu Oct 18 17:58:40 2007 +0000 @@ -67,9 +67,7 @@ G_BEGIN_DECLS /** - * - * - * @return + * @return GType for GntLine. */ GType gnt_line_get_gtype(void); @@ -77,10 +75,11 @@ #define gnt_vline_new() gnt_line_new(TRUE) /** - * - * @param vertical + * Create new line * - * @return + * @param vertical @c TRUE if the line should be vertical, @c FALSE for a horizontal line. + * + * @return The newly created line. */ GntWidget * gnt_line_new(gboolean vertical); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntmain.c --- a/finch/libgnt/gntmain.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntmain.c Thu Oct 18 17:58:40 2007 +0000 @@ -482,7 +482,7 @@ gnt_init_colors(); - wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgdset(stdscr, '\0' | gnt_color_pair(GNT_COLOR_NORMAL)); refresh(); #ifdef ALL_MOUSE_EVENTS @@ -490,7 +490,7 @@ mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); #endif - wbkgdset(stdscr, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgdset(stdscr, '\0' | gnt_color_pair(GNT_COLOR_NORMAL)); werase(stdscr); wrefresh(stdscr); @@ -646,7 +646,7 @@ return TRUE; } -void gnt_set_clipboard_string(gchar *string) +void gnt_set_clipboard_string(const gchar *string) { gnt_clipboard_set_string(clipboard, string); } diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntmenu.c --- a/finch/libgnt/gntmenu.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntmenu.c Thu Oct 18 17:58:40 2007 +0000 @@ -56,12 +56,12 @@ int i; if (menu->type == GNT_MENU_TOPLEVEL) { - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); + wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_HIGHLIGHT)); werase(widget->window); for (i = 0, iter = menu->list; iter; iter = iter->next, i++) { GntMenuItem *item = GNT_MENU_ITEM(iter->data); - type = ' ' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT); + type = ' ' | gnt_color_pair(GNT_COLOR_HIGHLIGHT); if (i == menu->selected) type |= A_REVERSE; item->priv.x = getcurx(widget->window) + widget->priv.x; @@ -459,3 +459,34 @@ menu->list = g_list_append(menu->list, item); } +GntMenuItem *gnt_menu_get_item(GntMenu *menu, const char *id) +{ + GntMenuItem *item = NULL; + GList *iter = menu->list; + + if (!id || !*id) + return NULL; + + for (; iter; iter = iter->next) { + GntMenu *sub; + item = iter->data; + sub = gnt_menuitem_get_submenu(item); + if (sub) { + item = gnt_menu_get_item(sub, id); + if (item) + break; + } else { + const char *itid = gnt_menuitem_get_id(item); + if (itid && strcmp(itid, id) == 0) + break; + /* XXX: Perhaps look at the menu-label as well? */ + } + item = NULL; + } + + if (item) + menuitem_activate(menu, item); + + return item; +} + diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntmenu.h --- a/finch/libgnt/gntmenu.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntmenu.h Thu Oct 18 17:58:40 2007 +0000 @@ -86,27 +86,39 @@ G_BEGIN_DECLS /** - * - * - * @return + * @return The GType for GntMenu. */ GType gnt_menu_get_gtype(void); /** - * - * @param type + * Create a new menu. * - * @return + * @param type The type of the menu, whether it's a toplevel menu or a popup menu. + * + * @return The newly created menu. */ GntWidget * gnt_menu_new(GntMenuType type); /** - * - * @param menu - * @param item + * Add an item to the menu. + * + * @param menu The menu. + * @param item The item to add to the menu. */ void gnt_menu_add_item(GntMenu *menu, GntMenuItem *item); +/** + * Activate and return the GntMenuItem with the given ID. + * + * @param menu The menu. + * @param id The ID for an item. + * + * @return The menuitem with the given ID, or @c NULL. + * + * @since 2.3.0 + */ +GntMenuItem *gnt_menu_get_item(GntMenu *menu, const char *id); + G_END_DECLS #endif /* GNT_MENU_H */ diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntmenuitem.c --- a/finch/libgnt/gntmenuitem.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntmenuitem.c Thu Oct 18 17:58:40 2007 +0000 @@ -33,6 +33,7 @@ item->text = NULL; if (item->submenu) gnt_widget_destroy(GNT_WIDGET(item->submenu)); + g_free(item->priv.id); parent_class->dispose(obj); } @@ -104,6 +105,11 @@ item->submenu = menu; } +GntMenu *gnt_menuitem_get_submenu(GntMenuItem *item) +{ + return item->submenu; +} + void gnt_menuitem_set_trigger(GntMenuItem *item, char trigger) { item->priv.trigger = trigger; @@ -114,3 +120,14 @@ return item->priv.trigger; } +void gnt_menuitem_set_id(GntMenuItem *item, const char *id) +{ + g_free(item->priv.id); + item->priv.id = g_strdup(id); +} + +const char * gnt_menuitem_get_id(GntMenuItem *item) +{ + return item->priv.id; +} + diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntmenuitem.h --- a/finch/libgnt/gntmenuitem.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntmenuitem.h Thu Oct 18 17:58:40 2007 +0000 @@ -53,6 +53,7 @@ int x; int y; char trigger; + char *id; }; typedef void (*GntMenuItemCallback)(GntMenuItem *item, gpointer data); @@ -86,36 +87,48 @@ G_BEGIN_DECLS /** - * - * - * @return + * @return GType for GntMenuItem. */ GType gnt_menuitem_get_gtype(void); /** - * - * @param text + * Create a new menuitem. * - * @return + * @param text Label for the menuitem. + * + * @return The newly created menuitem. */ GntMenuItem * gnt_menuitem_new(const char *text); /** - * - * @param item - * @param callback - * @param data + * Set a callback function for a menuitem. + * + * @param item The menuitem. + * @param callback The callback function. + * @param data Data to send to the callback function. */ void gnt_menuitem_set_callback(GntMenuItem *item, GntMenuItemCallback callback, gpointer data); /** - * - * @param item - * @param menu + * Set a submenu for a menuitem. A menuitem with a submenu cannot have a callback. + * + * @param item The menuitem. + * @param menu The submenu. */ void gnt_menuitem_set_submenu(GntMenuItem *item, GntMenu *menu); /** + * Get the submenu for a menuitem. + * + * @param item The menuitem. + * + * @return The submenu, or @c NULL. + * + * @since 2.3.0 + */ +GntMenu *gnt_menuitem_get_submenu(GntMenuItem *item); + +/** * Set a trigger key for the item. * * @param item The menuitem @@ -134,6 +147,27 @@ */ char gnt_menuitem_get_trigger(GntMenuItem *item); +/** + * Set an ID for the menuitem. + * + * @param item The menuitem. + * @param id The ID for the menuitem. + * + * @since 2.3.0 + */ +void gnt_menuitem_set_id(GntMenuItem *item, const char *id); + +/** + * Get the ID of the menuitem. + * + * @param item The menuitem. + * + * @return The ID for the menuitem. + * + * @since 2.3.0 + */ +const char * gnt_menuitem_get_id(GntMenuItem *item); + G_END_DECLS #endif /* GNT_MENUITEM_H */ diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntmenuitemcheck.h --- a/finch/libgnt/gntmenuitemcheck.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntmenuitemcheck.h Thu Oct 18 17:58:40 2007 +0000 @@ -66,32 +66,33 @@ G_BEGIN_DECLS /** - * - * - * @return + * @return GType for GntMenuItemCheck. */ GType gnt_menuitem_check_get_gtype(void); /** - * - * @param text + * Create a new menuitem. * - * @return + * @param text The text for the menuitem. + * + * @return The newly created menuitem. */ GntMenuItem * gnt_menuitem_check_new(const char *text); /** - * - * @param item + * Check whether the menuitem is checked or not. * - * @return + * @param item The menuitem. + * + * @return @c TRUE if the item is checked, @c FALSE otherwise. */ gboolean gnt_menuitem_check_get_checked(GntMenuItemCheck *item); /** - * - * @param item - * @param set + * Set whether the menuitem is checked or not. + * + * @param item The menuitem. + * @param set @c TRUE if the item should be checked, @c FALSE otherwise. */ void gnt_menuitem_check_set_checked(GntMenuItemCheck *item, gboolean set); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntslider.c --- a/finch/libgnt/gntslider.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntslider.c Thu Oct 18 17:58:40 2007 +0000 @@ -84,21 +84,21 @@ else position = 0; if (slider->vertical) { - mvwvline(widget->window, size-position, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL) | A_BOLD, + mvwvline(widget->window, size-position, 0, ACS_VLINE | gnt_color_pair(GNT_COLOR_NORMAL) | A_BOLD, position); - mvwvline(widget->window, 0, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + mvwvline(widget->window, 0, 0, ACS_VLINE | gnt_color_pair(GNT_COLOR_NORMAL), size-position); } else { - mvwhline(widget->window, 0, 0, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL) | A_BOLD, + mvwhline(widget->window, 0, 0, ACS_HLINE | gnt_color_pair(GNT_COLOR_NORMAL) | A_BOLD, position); - mvwhline(widget->window, 0, position, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + mvwhline(widget->window, 0, position, ACS_HLINE | gnt_color_pair(GNT_COLOR_NORMAL), size - position); } mvwaddch(widget->window, slider->vertical ? (size - position - 1) : 0, slider->vertical ? 0 : position, - ACS_CKBOARD | COLOR_PAIR(attr)); + ACS_CKBOARD | gnt_color_pair(attr)); } static void diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntstyle.c --- a/finch/libgnt/gntstyle.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntstyle.c Thu Oct 18 17:58:40 2007 +0000 @@ -227,6 +227,65 @@ #endif } +gboolean gnt_style_read_menu_accels(const char *name, GHashTable *table) +{ +#if GLIB_CHECK_VERSION(2,6,0) + char *kname; + GError *error = NULL; + gboolean ret = FALSE; + + kname = g_strdup_printf("%s::menu", name); + + if (g_key_file_has_group(gkfile, kname)) + { + gsize len = 0; + char **keys; + + keys = g_key_file_get_keys(gkfile, kname, &len, &error); + if (error) + { + g_printerr("GntStyle: %s\n", error->message); + g_error_free(error); + g_free(kname); + return ret; + } + + while (len--) + { + char *key, *menuid; + + key = g_strdup(keys[len]); + menuid = g_key_file_get_string(gkfile, kname, keys[len], &error); + + if (error) + { + g_printerr("GntStyle: %s\n", error->message); + g_error_free(error); + error = NULL; + } + else + { + const char *keycode = parse_key(key); + if (keycode == NULL) { + g_printerr("GntStyle: Invalid key-binding %s\n", key); + } else { + ret = TRUE; + g_hash_table_replace(table, g_strdup(keycode), menuid); + menuid = NULL; + } + } + g_free(key); + g_free(menuid); + } + g_strfreev(keys); + } + + g_free(kname); + return ret; +#endif + return FALSE; +} + void gnt_styles_get_keyremaps(GType type, GHashTable *hash) { #if GLIB_CHECK_VERSION(2,6,0) diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntstyle.h --- a/finch/libgnt/gntstyle.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntstyle.h Thu Oct 18 17:58:40 2007 +0000 @@ -38,11 +38,17 @@ } GntStyle; /** - * - * @param filename + * Read configuration from a file. + * + * @param filename The filename to read configuration from. */ void gnt_style_read_configure_file(const char *filename); +/** + * Get the user-setting for a style. + * @param style The style. + * @return The user-setting, or @c NULL. + */ const char *gnt_style_get(GntStyle style); /** @@ -70,38 +76,49 @@ gboolean gnt_style_parse_bool(const char *value); /** - * - * @param style - * @param def + * Get the boolean value for a user-setting. * - * @return + * @param style The style. + * @param def The default value (i.e, the value if the user didn't define + * any value) + * + * @return The value of the setting. */ gboolean gnt_style_get_bool(GntStyle style, gboolean def); -/* This should be called only once for the each type */ /** - * - * @param type - * @param hash + * @internal */ void gnt_styles_get_keyremaps(GType type, GHashTable *hash); /** - * - * @param type - * @param klass + * @internal */ void gnt_style_read_actions(GType type, GntBindableClass *klass); +/** + * Read menu-accels from ~/.gntrc + * + * @param name The name of the window. + * @param table The hastable to store the accel information. + * + * @return @c TRUE if some accels were read, @c FALSE otherwise. + */ +gboolean gnt_style_read_menu_accels(const char *name, GHashTable *table); + +/** + * @internal + * Read workspace information. + */ void gnt_style_read_workspaces(GntWM *wm); /** - * + * Initialize style settings. */ void gnt_init_styles(void); /** - * + * Uninitialize style settings. */ void gnt_uninit_styles(void); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gnttextview.c --- a/finch/libgnt/gnttextview.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gnttextview.c Thu Oct 18 17:58:40 2007 +0000 @@ -71,7 +71,7 @@ int comp = 0; /* Used for top-aligned text */ gboolean has_scroll = !(view->flags & GNT_TEXT_VIEW_NO_SCROLL); - wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgd(widget->window, gnt_color_pair(GNT_COLOR_NORMAL)); werase(widget->window); if ((view->flags & GNT_TEXT_VIEW_TOP_ALIGN) && @@ -158,15 +158,15 @@ position = rows - showing; mvwvline(widget->window, position + 1, scrcol, - ACS_CKBOARD | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D), showing); + ACS_CKBOARD | gnt_color_pair(GNT_COLOR_HIGHLIGHT_D), showing); } if (has_scroll) { mvwaddch(widget->window, 0, scrcol, - (lines ? ACS_UARROW : ' ') | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); + (lines ? ACS_UARROW : ' ') | gnt_color_pair(GNT_COLOR_HIGHLIGHT_D)); mvwaddch(widget->window, widget->priv.height - 1, scrcol, ((view->list && view->list->prev) ? ACS_DARROW : ' ') | - COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); + gnt_color_pair(GNT_COLOR_HIGHLIGHT_D)); } GNTDEBUG; @@ -645,11 +645,11 @@ fl |= A_BLINK; if (flags & GNT_TEXT_FLAG_DIM) - fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_DISABLED)); + fl |= (A_DIM | gnt_color_pair(GNT_COLOR_DISABLED)); else if (flags & GNT_TEXT_FLAG_HIGHLIGHT) - fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); + fl |= (A_DIM | gnt_color_pair(GNT_COLOR_HIGHLIGHT)); else - fl |= COLOR_PAIR(GNT_COLOR_NORMAL); + fl |= gnt_color_pair(GNT_COLOR_NORMAL); return fl; } diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gnttextview.h --- a/finch/libgnt/gnttextview.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gnttextview.h Thu Oct 18 17:58:40 2007 +0000 @@ -88,116 +88,144 @@ G_BEGIN_DECLS /** - * - * - * @return + * @return GType for GntTextView. */ GType gnt_text_view_get_gtype(void); -/* XXX: For now, don't set a textview to have any border. - * If you want borders real bad, put it in a box. */ /** - * + * Create a new textview. * - * @return + * @return The newly created textview. */ GntWidget * gnt_text_view_new(void); -/* scroll > 0 means scroll up, < 0 means scroll down, == 0 means scroll to the end */ /** - * - * @param view - * @param scroll + * Scroll the textview. + * @param view The textview to scroll. + * @param scroll scroll > 0 means scroll up, < 0 means scroll down, == 0 means scroll to the end. */ void gnt_text_view_scroll(GntTextView *view, int scroll); /** - * - * @param view - * @param text - * @param flags + * Append new text in a textview. + * + * @param view The textview. + * @param text The text to append to the textview. + * @param flags The text-flags to apply to the new text. */ void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags); /** - * - * @param view - * @param text - * @param flags - * @param tag + * Append text in the textview, with some identifier (tag) for the added text. + * + * @param view The textview. + * @param text The text to append. + * @param flags The text-flags to apply to the new text. + * @param tag The tag for the appended text, so it can be changed later (@see gnt_text_view_tag_change) */ void gnt_text_view_append_text_with_tag(GntTextView *view, const char *text, GntTextFormatFlags flags, const char *tag); -/* Move the cursor to the beginning of the next line and resets text-attributes. - * It first completes the current line with the current text-attributes. */ /** - * - * @param view + * Move the cursor to the beginning of the next line and resets text-attributes. + * It first completes the current line with the current text-attributes. + * + * @param view The textview. */ void gnt_text_view_next_line(GntTextView *view); /** - * - * @param flags + * Convert GNT-text formats to ncurses-text attributes. * - * @return + * @param flags The GNT text format. + * + * @return Nucrses text attribute. */ chtype gnt_text_format_flag_to_chtype(GntTextFormatFlags flags); /** - * - * @param view + * Clear the contents of the textview. + * + * @param view The textview. */ void gnt_text_view_clear(GntTextView *view); /** - * - * @param view + * The number of lines below the bottom-most visible line. * - * @return + * @param view The textview. + * + * @return Number of lines below the bottom-most visible line. */ int gnt_text_view_get_lines_below(GntTextView *view); /** - * - * @param view + * The number of lines above the topmost visible line. * - * @return + * @param view The textview. + * + * @return Number of lines above the topmost visible line. */ int gnt_text_view_get_lines_above(GntTextView *view); -/* If text is NULL, then the tag is removed. */ /** - * - * @param view - * @param name - * @param text - * @param all + * Change the text of a tag. * - * @return + * @param view The textview. + * @param name The name of the tag. + * @param text The new text for the text. If 'text' is @c NULL, the tag is removed. + * @param all @c TRUE if all of the instancess of the tag should be changed, @c FALSE if + * only the first instance should be changed. + * + * @return The number of instances changed. */ int gnt_text_view_tag_change(GntTextView *view, const char *name, const char *text, gboolean all); /** - * - * @param view - * @param widget + * Setup hooks so that pressing up/down/page-up/page-down keys when 'widget' is + * in focus scrolls the textview. + * + * @param view The textview. + * @param widget The trigger widget. */ void gnt_text_view_attach_scroll_widget(GntTextView *view, GntWidget *widget); /** - * - * @param view - * @param widget + * Setup appropriate hooks so that pressing some keys when the 'pager' widget + * is in focus triggers the PAGER to popup with the contents of the textview + * in it. + * + * The default key-combination to trigger the pager is a-v, and the default + * PAGER application is $PAGER. Both can be changed in ~/.gntrc like this: + * + * @code + * [pager] + * key = a-v + * path = /path/to/pager + * @endcode + * + * @param view The textview. + * @param pager The widget to trigger the PAGER. */ void gnt_text_view_attach_pager_widget(GntTextView *view, GntWidget *pager); /** - * - * @param view - * @param widget + * Setup appropriate hooks so that pressing some keys when 'widget' + * is in focus triggers the EDITOR to popup with the contents of the textview + * in it. + * + * The default key-combination to trigger the pager is a-e, and the default + * EDITOR application is $EDITOR. Both can be changed in ~/.gntrc like this: + * + * @code + * [editor] + * key = a-e + * path = /path/to/editor + * @endcode + * + * @param view The textview. + * @param widget The widget to trigger the EDITOR. */ -void gnt_text_view_attach_editor_widget(GntTextView *view, GntWidget *pager); +void gnt_text_view_attach_editor_widget(GntTextView *view, GntWidget *widget); /** * Set a GntTextViewFlag for the textview widget. diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gnttree.c --- a/finch/libgnt/gnttree.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gnttree.c Thu Oct 18 17:58:40 2007 +0000 @@ -432,7 +432,7 @@ tree_selection_changed(tree, NULL, tree->current); } - wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgd(widget->window, gnt_color_pair(GNT_COLOR_NORMAL)); start = 0; if (tree->show_title) @@ -440,9 +440,9 @@ int i; int x = pos; - mvwhline(widget->window, pos + 1, pos, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + mvwhline(widget->window, pos + 1, pos, ACS_HLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.width - pos - 1); - mvwhline(widget->window, pos, pos, ' ' | COLOR_PAIR(GNT_COLOR_NORMAL), + mvwhline(widget->window, pos, pos, ' ' | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.width - pos - 1); for (i = 0; i < tree->ncol; i++) @@ -455,14 +455,14 @@ } if (pos) { - tree_mark_columns(tree, pos, 0, ACS_TTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); + tree_mark_columns(tree, pos, 0, ACS_TTEE | gnt_color_pair(GNT_COLOR_NORMAL)); tree_mark_columns(tree, pos, widget->priv.height - pos, - ACS_BTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); + ACS_BTEE | gnt_color_pair(GNT_COLOR_NORMAL)); } tree_mark_columns(tree, pos, pos + 1, - (tree->show_separator ? ACS_PLUS : ACS_HLINE) | COLOR_PAIR(GNT_COLOR_NORMAL)); + (tree->show_separator ? ACS_PLUS : ACS_HLINE) | gnt_color_pair(GNT_COLOR_NORMAL)); tree_mark_columns(tree, pos, pos, - (tree->show_separator ? ACS_VLINE : ' ') | COLOR_PAIR(GNT_COLOR_NORMAL)); + (tree->show_separator ? ACS_VLINE : ' ') | gnt_color_pair(GNT_COLOR_NORMAL)); start = 2; } @@ -514,18 +514,18 @@ if (row == tree->current) { if (gnt_widget_has_focus(widget)) - attr |= COLOR_PAIR(GNT_COLOR_HIGHLIGHT); + attr |= gnt_color_pair(GNT_COLOR_HIGHLIGHT); else - attr |= COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D); + attr |= gnt_color_pair(GNT_COLOR_HIGHLIGHT_D); } else { if (flags & GNT_TEXT_FLAG_DIM) - attr |= (A_DIM | COLOR_PAIR(GNT_COLOR_DISABLED)); + attr |= (A_DIM | gnt_color_pair(GNT_COLOR_DISABLED)); else if (flags & GNT_TEXT_FLAG_HIGHLIGHT) - attr |= (A_DIM | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); + attr |= (A_DIM | gnt_color_pair(GNT_COLOR_HIGHLIGHT)); else - attr |= COLOR_PAIR(GNT_COLOR_NORMAL); + attr |= gnt_color_pair(GNT_COLOR_NORMAL); } wbkgdset(widget->window, '\0' | attr); @@ -537,7 +537,7 @@ (tree->show_separator ? ACS_VLINE : ' ') | attr); } - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_NORMAL)); while (i < widget->priv.height - pos) { mvwhline(widget->window, i, pos, ' ', @@ -576,22 +576,22 @@ position += pos + start + 1; mvwvline(widget->window, pos + start + 1, scrcol, - ' ' | COLOR_PAIR(GNT_COLOR_NORMAL), rows); + ' ' | gnt_color_pair(GNT_COLOR_NORMAL), rows); mvwvline(widget->window, position, scrcol, - ACS_CKBOARD | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D), showing); + ACS_CKBOARD | gnt_color_pair(GNT_COLOR_HIGHLIGHT_D), showing); } mvwaddch(widget->window, start + pos, scrcol, ((tree->top != tree->root) ? ACS_UARROW : ' ') | - COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); + gnt_color_pair(GNT_COLOR_HIGHLIGHT_D)); mvwaddch(widget->window, widget->priv.height - pos - 1, scrcol, - (row ? ACS_DARROW : ' ') | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); + (row ? ACS_DARROW : ' ') | gnt_color_pair(GNT_COLOR_HIGHLIGHT_D)); /* If there's a search-text, show it in the bottom of the tree */ if (tree->priv->search && tree->priv->search->len > 0) { const char *str = gnt_util_onscreen_width_to_pointer(tree->priv->search->str, scrcol - 1, NULL); - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); + wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_HIGHLIGHT_D)); mvwaddnstr(widget->window, widget->priv.height - pos - 1, pos, tree->priv->search->str, str - tree->priv->search->str); } @@ -1328,7 +1328,6 @@ tree->list = g_list_insert(tree->list, key, position + 1); } } - redraw_tree(tree); return row; diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntutils.h --- a/finch/libgnt/gntutils.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntutils.h Thu Oct 18 17:58:40 2007 +0000 @@ -153,5 +153,5 @@ * * @since 2.0.0 (gnt), 2.1.0 (pidgin) */ -void gnt_util_set_trigger_widget(GntWidget *wid, const char *text, GntWidget *button); +void gnt_util_set_trigger_widget(GntWidget *widget, const char *key, GntWidget *button); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntwidget.c --- a/finch/libgnt/gntwidget.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntwidget.c Thu Oct 18 17:58:40 2007 +0000 @@ -420,7 +420,7 @@ gnt_widget_hide(GntWidget *widget) { g_signal_emit(widget, signals[SIG_HIDE], 0); - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_NORMAL)); #if 0 /* XXX: I have no clue why, but this seemed to be necessary. */ if (gnt_widget_has_shadow(widget)) @@ -477,31 +477,31 @@ if (!gnt_widget_has_shadow(widget)) shadow = FALSE; - wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgd(widget->window, gnt_color_pair(GNT_COLOR_NORMAL)); werase(widget->window); if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER)) { /* - This is ugly. */ /* - What's your point? */ - mvwvline(widget->window, 0, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.height); + mvwvline(widget->window, 0, 0, ACS_VLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.height); mvwvline(widget->window, 0, widget->priv.width - 1, - ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.height); + ACS_VLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.height); mvwhline(widget->window, widget->priv.height - 1, 0, - ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.width); - mvwhline(widget->window, 0, 0, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), widget->priv.width); - mvwaddch(widget->window, 0, 0, ACS_ULCORNER | COLOR_PAIR(GNT_COLOR_NORMAL)); + ACS_HLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.width); + mvwhline(widget->window, 0, 0, ACS_HLINE | gnt_color_pair(GNT_COLOR_NORMAL), widget->priv.width); + mvwaddch(widget->window, 0, 0, ACS_ULCORNER | gnt_color_pair(GNT_COLOR_NORMAL)); mvwaddch(widget->window, 0, widget->priv.width - 1, - ACS_URCORNER | COLOR_PAIR(GNT_COLOR_NORMAL)); + ACS_URCORNER | gnt_color_pair(GNT_COLOR_NORMAL)); mvwaddch(widget->window, widget->priv.height - 1, 0, - ACS_LLCORNER | COLOR_PAIR(GNT_COLOR_NORMAL)); + ACS_LLCORNER | gnt_color_pair(GNT_COLOR_NORMAL)); mvwaddch(widget->window, widget->priv.height - 1, widget->priv.width - 1, - ACS_LRCORNER | COLOR_PAIR(GNT_COLOR_NORMAL)); + ACS_LRCORNER | gnt_color_pair(GNT_COLOR_NORMAL)); } if (shadow) { - wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_SHADOW)); + wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_SHADOW)); mvwvline(widget->window, 1, widget->priv.width, ' ', widget->priv.height); mvwhline(widget->window, widget->priv.height, 1, ' ', widget->priv.width); } @@ -617,7 +617,7 @@ return; while (widget->parent) widget = widget->parent; - + if (!g_object_get_data(G_OBJECT(widget), "gnt:queue_update")) { int id = g_timeout_add(0, update_queue_callback, widget); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntwidget.h --- a/finch/libgnt/gntwidget.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntwidget.h Thu Oct 18 17:58:40 2007 +0000 @@ -140,167 +140,176 @@ G_BEGIN_DECLS /** - * - * - * @return + * @return GType for GntWidget. */ GType gnt_widget_get_gtype(void); /** - * - * @param widget + * Destroy a widget. + * @param widget The widget to destroy. */ void gnt_widget_destroy(GntWidget *widget); /** - * - * @param widget + * Show a widget. This should only be used for toplevel widgets. For the rest + * of the widgets, use #gnt_widget_draw instead. + * + * @param widget The widget to show. */ void gnt_widget_show(GntWidget *widget); /** - * - * @param widget + * Draw a widget. + * @param widget The widget to draw. */ void gnt_widget_draw(GntWidget *widget); /** - * - * @param widget - * @param x - * @param y - * @param width - * @param height + * @internal + * Expose part of a widget. */ void gnt_widget_expose(GntWidget *widget, int x, int y, int width, int height); /** - * - * @param widget + * Hide a widget. + * @param widget The widget to hide. */ void gnt_widget_hide(GntWidget *widget); /** - * - * @param widget - * @param x - * @param y + * Get the position of a widget. + * + * @param widget The widget. + * @param x Location to store the x-coordinate of the widget. + * @param y Location to store the y-coordinate of the widget. */ void gnt_widget_get_position(GntWidget *widget, int *x, int *y); /** - * - * @param widget - * @param x - * @param y + * Set the position of a widget. + * @param widget The widget to reposition. + * @param x The x-coordinate of the widget. + * @param y The x-coordinate of the widget. */ void gnt_widget_set_position(GntWidget *widget, int x, int y); /** - * - * @param widget + * Request a widget to calculate its desired size. + * @param widget The widget. */ void gnt_widget_size_request(GntWidget *widget); /** - * - * @param widget - * @param width - * @param height + * Get the size of a widget. + * @param widget The widget. + * @param width Location to store the width of the widget. + * @param height Location to store the height of the widget. */ void gnt_widget_get_size(GntWidget *widget, int *width, int *height); /** - * - * @param widget - * @param width - * @param height + * Set the size of a widget. * - * @return + * @param widget The widget to resize. + * @param width The width of the widget. + * @param height The height of the widget. + * + * @return If the widget was resized to the new size. */ gboolean gnt_widget_set_size(GntWidget *widget, int width, int height); /** - * - * @param widget - * @param width - * @param height + * Confirm a requested a size for a widget. * - * @return + * @param widget The widget. + * @param width The requested width. + * @param height The requested height. + * + * @return @c TRUE if the new size was confirmed, @c FALSE otherwise. */ gboolean gnt_widget_confirm_size(GntWidget *widget, int width, int height); /** - * - * @param widget - * @param keys + * Trigger the key-press callbacks for a widget. * - * @return + * @param widget The widget. + * @param keys The keypress on the widget. + * + * @return @c TRUE if the key-press was handled, @c FALSE otherwise. */ gboolean gnt_widget_key_pressed(GntWidget *widget, const char *keys); /** - * - * @param widget - * @param event - * @param x - * @param y + * Trigger the 'click' callback of a widget. * - * @return + * @param widget The widget. + * @param event The mouseevent. + * @param x The x-coordinate of the mouse. + * @param y The y-coordinate of the mouse. + * + * @return @c TRUE if the event was handled, @c FALSE otherwise. */ gboolean gnt_widget_clicked(GntWidget *widget, GntMouseEvent event, int x, int y); /** - * - * @param widget - * @param set + * Give or remove focus to a widget. + * @param widget The widget. + * @param set @c TRUE of focus should be given to the widget, @c FALSE if + * focus should be removed. * - * @return + * @return @c TRUE if the focus has been changed, @c FALSE otherwise. */ gboolean gnt_widget_set_focus(GntWidget *widget, gboolean set); /** - * - * @param widget + * Activate a widget. This only applies to widgets that can be activated (eg. GntButton) + * @param widget The widget to activate. */ void gnt_widget_activate(GntWidget *widget); /** - * - * @param widget - * @param name + * Set the name of a widget. + * @param widget The widget. + * @param name A new name for the widget. */ void gnt_widget_set_name(GntWidget *widget, const char *name); +/** + * Get the name of a widget. + * @param widget The widget. + * @return The name of the widget. + */ const char *gnt_widget_get_name(GntWidget *widget); -/* Widget-subclasses should call this from the draw-callback. - * Applications should just call gnt_widget_draw instead of this. */ /** - * - * @param widget + * @internal + * Use #gnt_widget_draw instead. */ void gnt_widget_queue_update(GntWidget *widget); /** - * - * @param widget - * @param set + * Set whether a widget can take focus or not. + * + * @param widget The widget. + * @param set @c TRUE if the widget can take focus. */ void gnt_widget_set_take_focus(GntWidget *widget, gboolean set); /** - * - * @param widget - * @param set + * Set the visibility of a widget. + * + * @param widget The widget. + * @param set Whether the widget is visible or not. */ void gnt_widget_set_visible(GntWidget *widget, gboolean set); /** - * - * @param widget + * Check whether the widget has shadows. * - * @return + * @param widget The widget. + * + * @return @c TRUE if the widget has shadows. This checks both the user-setting + * and whether the widget can have shadows at all. */ gboolean gnt_widget_has_shadow(GntWidget *widget); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntwindow.c --- a/finch/libgnt/gntwindow.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntwindow.c Thu Oct 18 17:58:40 2007 +0000 @@ -25,6 +25,11 @@ #include +struct _GntWindowPriv +{ + GHashTable *accels; /* key => menuitem-id */ +}; + enum { SIG_WORKSPACE_HIDE, @@ -55,6 +60,10 @@ GntWindow *window = GNT_WINDOW(widget); if (window->menu) gnt_widget_destroy(GNT_WIDGET(window->menu)); + if (window->priv) { + g_hash_table_destroy(window->priv->accels); + g_free(window->priv); + } org_destroy(widget); } @@ -98,8 +107,11 @@ gnt_window_init(GTypeInstance *instance, gpointer class) { GntWidget *widget = GNT_WIDGET(instance); + GntWindow *win = GNT_WINDOW(widget); GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS); + win->priv = g_new0(GntWindowPriv, 1); + win->priv->accels = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); GNTDEBUG; } @@ -170,8 +182,23 @@ void gnt_window_set_menu(GntWindow *window, GntMenu *menu) { /* If a menu already existed, then destroy that first. */ + const char *name = gnt_widget_get_name(GNT_WIDGET(window)); if (window->menu) gnt_widget_destroy(GNT_WIDGET(window->menu)); window->menu = menu; + if (name && window->priv) { + if (!gnt_style_read_menu_accels(name, window->priv->accels)) { + g_hash_table_destroy(window->priv->accels); + g_free(window->priv); + window->priv = NULL; + } + } } +const char * gnt_window_get_accel_item(GntWindow *window, const char *key) +{ + if (window->priv) + return g_hash_table_lookup(window->priv->accels, key); + return NULL; +} + diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntwindow.h --- a/finch/libgnt/gntwindow.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntwindow.h Thu Oct 18 17:58:40 2007 +0000 @@ -52,6 +52,7 @@ { GntBox parent; GntMenu *menu; + GntWindowPriv *priv; }; struct _GntWindowClass @@ -67,9 +68,7 @@ G_BEGIN_DECLS /** - * - * - * @return + * @return GType for GntWindow. */ GType gnt_window_get_gtype(void); @@ -77,28 +76,42 @@ #define gnt_hwindow_new(homo) gnt_window_box_new(homo, FALSE) /** - * + * Create a new window. * - * @return + * @return The newly created window. */ GntWidget * gnt_window_new(void); /** - * - * @param homo - * @param vert + * Create a new window. * - * @return + * @param homo @c TRUE if the widgets inside the window should have the same dimensions. + * @param vert @c TRUE if the widgets inside the window should be stacked vertically. + * + * @return The newly created window. */ GntWidget * gnt_window_box_new(gboolean homo, gboolean vert); /** - * - * @param window - * @param menu + * Set the menu for a window. + * + * @param window The window. + * @param menu The menu for the window. */ void gnt_window_set_menu(GntWindow *window, GntMenu *menu); +/** + * Return the id of a menuitem specified to a keystroke. + * + * @param window The window. + * @param key The keystroke. + * + * @return The id of the menuitem bound to the keystroke, or @c NULL. + * + * @since 2.3.0 + */ +const char * gnt_window_get_accel_item(GntWindow *window, const char *key); + void gnt_window_workspace_hiding(GntWindow *); void gnt_window_workspace_showing(GntWindow *); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntwm.c --- a/finch/libgnt/gntwm.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntwm.c Thu Oct 18 17:58:40 2007 +0000 @@ -1046,7 +1046,7 @@ GntWM *wm = GNT_WM(wim); GntWidget *w = GNT_WIDGET(wid); wm->tagged = g_list_remove(wm->tagged, w); - mvwhline(w->window, 0, 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), 3); + mvwhline(w->window, 0, 1, ACS_HLINE | gnt_color_pair(GNT_COLOR_NORMAL), 3); gnt_widget_draw(w); } @@ -1066,7 +1066,7 @@ } wm->tagged = g_list_prepend(wm->tagged, widget); - wbkgdset(widget->window, ' ' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); + wbkgdset(widget->window, ' ' | gnt_color_pair(GNT_COLOR_HIGHLIGHT)); mvwprintw(widget->window, 0, 1, "[T]"); gnt_widget_draw(widget); return TRUE; @@ -1675,7 +1675,7 @@ { while (widget->parent) widget = widget->parent; - + if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_INVISIBLE) || g_hash_table_lookup(wm->nodes, widget)) { update_screen(wm); @@ -1852,8 +1852,19 @@ ret = gnt_widget_key_pressed(GNT_WIDGET(wm->menu), keys); else if (wm->_list.window) ret = gnt_widget_key_pressed(wm->_list.window, keys); - else if (wm->cws->ordered) - ret = gnt_widget_key_pressed(GNT_WIDGET(wm->cws->ordered->data), keys); + else if (wm->cws->ordered) { + GntWidget *win = wm->cws->ordered->data; + if (GNT_IS_WINDOW(win)) { + GntMenu *menu = GNT_WINDOW(win)->menu; + if (menu) { + const char *id = gnt_window_get_accel_item(GNT_WINDOW(win), keys); + if (id) + ret = (gnt_menu_get_item(menu, id) != NULL); + } + } + if (!ret) + ret = gnt_widget_key_pressed(win, keys); + } return ret; } diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntwm.h --- a/finch/libgnt/gntwm.h Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntwm.h Thu Oct 18 17:58:40 2007 +0000 @@ -113,7 +113,7 @@ * whether to give focus to a new window. */ gboolean event_stack; - + GntKeyPressMode mode; GHashTable *positions; @@ -184,108 +184,149 @@ G_BEGIN_DECLS /** - * - * - * @return + * @return GType for GntWM. */ GType gnt_wm_get_gtype(void); +/** + * Add a workspace. + * @param wm The window-manager. + * @param ws The workspace to add. + */ void gnt_wm_add_workspace(GntWM *wm, GntWS *ws); +/** + * Switch to a workspace. + * @param wm The window-manager. + * @param n Index of the workspace to switch to. + * + * @return @c TRUE if the switch was successful. + */ gboolean gnt_wm_switch_workspace(GntWM *wm, gint n); + +/** + * Switch to the previous workspace from the current one. + * @param wm The window-manager. + */ gboolean gnt_wm_switch_workspace_prev(GntWM *wm); + +/** + * Switch to the next workspace from the current one. + * @param wm The window-manager. + */ gboolean gnt_wm_switch_workspace_next(GntWM *wm); + +/** + * Move a window to a specific workspace. + * @param wm The window manager. + * @param neww The new workspace. + * @param widget The widget to move. + */ void gnt_wm_widget_move_workspace(GntWM *wm, GntWS *neww, GntWidget *widget); + +/** + * Set the list of workspaces . + * @param wm The window manager. + * @param workspaces The list of workspaces. + */ void gnt_wm_set_workspaces(GntWM *wm, GList *workspaces); + +/** + * Find the workspace that contains a specific widget. + * @param wm The window-manager. + * @param widget The widget to find. + * @return The workspace that has the widget. + */ GntWS *gnt_wm_widget_find_workspace(GntWM *wm, GntWidget *widget); /** - * - * @param wm - * @param widget + * Process a new window. + * + * @param wm The window-manager. + * @param widget The new window. */ void gnt_wm_new_window(GntWM *wm, GntWidget *widget); /** - * - * @param wm - * @param widget + * Decorate a window. + * @param wm The window-manager. + * @param widget The widget to decorate. */ void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget); /** - * - * @param wm - * @param widget + * Close a window. + * @param wm The window-manager. + * @param widget The window to close. */ void gnt_wm_window_close(GntWM *wm, GntWidget *widget); /** - * - * @param wm - * @param string + * Process input. * - * @return + * @param wm The window-manager. + * @param string The input string to process. + * + * @return @c TRUE of the string was processed, @c FALSE otherwise. */ gboolean gnt_wm_process_input(GntWM *wm, const char *string); /** - * - * @param wm - * @param event - * @param x - * @param y - * @param widget + * Process a click event. + * @param wm The window manager. + * @param event The mouse event. + * @param x The x-coordinate of the mouse. + * @param y The y-coordinate of the mouse. + * @param widget The widget under the mouse. * - * @return + * @return @c TRUE if the event was handled, @c FALSE otherwise. */ gboolean gnt_wm_process_click(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget); /** - * - * @param wm - * @param widget - * @param width - * @param height + * Resize a window. + * @param wm The window manager. + * @param widget The window to resize. + * @param width The desired width of the window. + * @param height The desired height of the window. */ void gnt_wm_resize_window(GntWM *wm, GntWidget *widget, int width, int height); /** - * - * @param wm - * @param widget - * @param x - * @param y + * Move a window. + * @param wm The window manager. + * @param widget The window to move. + * @param x The desired x-coordinate of the window. + * @param y The desired y-coordinate of the window. */ void gnt_wm_move_window(GntWM *wm, GntWidget *widget, int x, int y); /** - * - * @param wm - * @param widget + * Update a window. + * @param wm The window-manager. + * @param widget The window to update. */ void gnt_wm_update_window(GntWM *wm, GntWidget *widget); /** - * - * @param wm - * @param widget + * Raise a window. + * @param wm The window-manager. + * @param widget The window to raise. */ void gnt_wm_raise_window(GntWM *wm, GntWidget *widget); /** - * - * @param wm - * @param set + * @internal */ void gnt_wm_set_event_stack(GntWM *wm, gboolean set); +/** + * @internal + */ void gnt_wm_copy_win(GntWidget *widget, GntNode *node); /** - * - * - * @return + * @return The idle time of the user. */ time_t gnt_wm_get_idle_time(void); diff -r 33822d7271e5 -r 8b9c48347004 finch/libgnt/gntws.c --- a/finch/libgnt/gntws.c Fri Oct 12 17:10:34 2007 +0000 +++ b/finch/libgnt/gntws.c Thu Oct 18 17:58:40 2007 +0000 @@ -45,7 +45,7 @@ mvwin(taskbar, Y_MAX, 0); } - wbkgdset(taskbar, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + wbkgdset(taskbar, '\0' | gnt_color_pair(GNT_COLOR_NORMAL)); werase(taskbar); n = g_list_length(ws->list); @@ -66,15 +66,15 @@ } else { color = GNT_COLOR_NORMAL; } - wbkgdset(taskbar, '\0' | COLOR_PAIR(color)); + wbkgdset(taskbar, '\0' | gnt_color_pair(color)); if (iter->next) - mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), width); + mvwhline(taskbar, 0, width * i, ' ' | gnt_color_pair(color), width); else - mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), getmaxx(stdscr) - width * i); + mvwhline(taskbar, 0, width * i, ' ' | gnt_color_pair(color), getmaxx(stdscr) - width * i); title = GNT_BOX(w)->title; mvwprintw(taskbar, 0, width * i, "%s", title ? title : ""); if (i) - mvwaddch(taskbar, 0, width *i - 1, ACS_VLINE | A_STANDOUT | COLOR_PAIR(GNT_COLOR_NORMAL)); + mvwaddch(taskbar, 0, width *i - 1, ACS_VLINE | A_STANDOUT | gnt_color_pair(GNT_COLOR_NORMAL)); } wrefresh(taskbar); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/Makefile.am --- a/libpurple/Makefile.am Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/Makefile.am Thu Oct 18 17:58:40 2007 +0000 @@ -114,6 +114,7 @@ privacy.h \ proxy.h \ prpl.h \ + purple.h \ request.h \ roomlist.h \ savedstatuses.h \ diff -r 33822d7271e5 -r 8b9c48347004 libpurple/account.c --- a/libpurple/account.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/account.c Thu Oct 18 17:58:40 2007 +0000 @@ -63,7 +63,10 @@ PurpleAccountRequestType type; PurpleAccount *account; void *ui_handle; - + char *user; + gpointer userdata; + PurpleAccountRequestAuthorizationCb auth_cb; + PurpleAccountRequestAuthorizationCb deny_cb; } PurpleAccountRequestInfo; static PurpleAccountUiOps *account_ui_ops = NULL; @@ -1004,7 +1007,7 @@ field = purple_request_field_bool_new("remember", _("Save password"), FALSE); purple_request_field_group_add_field(group, field); - purple_request_fields(account, + purple_request_fields_with_hint(account, NULL, primary, NULL, @@ -1012,7 +1015,7 @@ _("OK"), ok_cb, _("Cancel"), cancel_cb, account, NULL, NULL, - user_data); + PURPLE_REQUEST_UI_HINT_ACCOUNT, user_data); g_free(primary); } @@ -1157,6 +1160,28 @@ } } +static void +request_auth_cb(void *data) +{ + PurpleAccountRequestInfo *info = data; + info->auth_cb(info->userdata); + purple_signal_emit(purple_accounts_get_handle(), + "account-authorization-granted", info->account, info->user); + g_free(info->user); + g_free(info); +} + +static void +request_deny_cb(void *data) +{ + PurpleAccountRequestInfo *info = data; + info->deny_cb(info->userdata); + purple_signal_emit(purple_accounts_get_handle(), + "account-authorization-denied", info->account, info->user); + g_free(info->user); + g_free(info); +} + void * purple_account_request_authorization(PurpleAccount *account, const char *remote_user, const char *id, const char *alias, const char *message, gboolean on_list, @@ -1164,18 +1189,35 @@ { PurpleAccountUiOps *ui_ops; PurpleAccountRequestInfo *info; + int plugin_return; g_return_val_if_fail(account != NULL, NULL); g_return_val_if_fail(remote_user != NULL, NULL); ui_ops = purple_accounts_get_ui_ops(); + plugin_return = GPOINTER_TO_INT( + purple_signal_emit_return_1(purple_accounts_get_handle(), + "account-authorization-requested", account, remote_user)); + + if (plugin_return > 0) { + auth_cb(user_data); + return NULL; + } else if (plugin_return < 0) { + deny_cb(user_data); + return NULL; + } + if (ui_ops != NULL && ui_ops->request_authorize != NULL) { info = g_new0(PurpleAccountRequestInfo, 1); info->type = PURPLE_ACCOUNT_REQUEST_AUTHORIZATION; info->account = account; + info->auth_cb = auth_cb; + info->deny_cb = deny_cb; + info->userdata = user_data; + info->user = g_strdup(remote_user); info->ui_handle = ui_ops->request_authorize(account, remote_user, id, alias, message, - on_list, auth_cb, deny_cb, user_data); + on_list, request_auth_cb, request_deny_cb, info); handles = g_list_append(handles, info); return info->ui_handle; @@ -1253,7 +1295,7 @@ /* I'm sticking this somewhere in the code: bologna */ - purple_request_fields(purple_account_get_connection(account), + purple_request_fields_with_hint(purple_account_get_connection(account), NULL, primary, _("Please enter your current password and your " @@ -1262,7 +1304,7 @@ _("OK"), G_CALLBACK(change_password_cb), _("Cancel"), NULL, account, NULL, NULL, - account); + PURPLE_REQUEST_UI_HINT_ACCOUNT, account); } static void @@ -1290,14 +1332,14 @@ _("Change user information for %s"), purple_account_get_username(account)); - purple_request_input(gc, _("Set User Info"), primary, NULL, + purple_request_input_with_hint(gc, _("Set User Info"), primary, NULL, purple_account_get_user_info(account), TRUE, FALSE, ((gc != NULL) && (gc->flags & PURPLE_CONNECTION_HTML) ? "html" : NULL), _("Save"), G_CALLBACK(set_user_info_cb), _("Cancel"), NULL, account, NULL, NULL, - account); + PURPLE_REQUEST_UI_HINT_ACCOUNT, account); } void @@ -2452,6 +2494,25 @@ PURPLE_SUBTYPE_ACCOUNT), purple_value_new(PURPLE_TYPE_STRING)); + purple_signal_register(handle, "account-authorization-requested", + purple_marshal_INT__POINTER_POINTER, + purple_value_new(PURPLE_TYPE_INT), 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "account-authorization-denied", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "account-authorization-granted", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING)); + load_accounts(); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/blist.h --- a/libpurple/blist.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/blist.h Thu Oct 18 17:58:40 2007 +0000 @@ -40,6 +40,8 @@ typedef struct _PurpleContact PurpleContact; typedef struct _PurpleBuddy PurpleBuddy; +typedef gboolean (*PurpleFilterBlistFunc)(PurpleBlistNode *node); + /**************************************************************************/ /* Enumerations */ /**************************************************************************/ @@ -65,9 +67,12 @@ typedef enum { PURPLE_BLIST_NODE_FLAG_NO_SAVE = 1 << 0, /**< node should not be saved with the buddy list */ + PURPLE_BLIST_NODE_HAS_CONVERSATION = 1 << 1, /**< node (buddy or chat) has an open conversation */ } PurpleBlistNodeFlags; +#define PURPLE_BLIST_NODE_SET_FLAG(node, f) (((PurpleBlistNode *)node)->flags |= (f)) +#define PURPLE_BLIST_NODE_UNSET_FLAG(node, f) (((PurpleBlistNode *)node)->flags &= ~(f)) #define PURPLE_BLIST_NODE_HAS_FLAG(b, f) (((PurpleBlistNode*)(b))->flags & (f)) #define PURPLE_BLIST_NODE_SHOULD_SAVE(b) (! PURPLE_BLIST_NODE_HAS_FLAG(b, PURPLE_BLIST_NODE_FLAG_NO_SAVE)) @@ -482,6 +487,7 @@ */ PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact); +#ifndef PURPLE_DISABLE_DEPRECATED /** * Sets the alias for a contact. * @@ -491,6 +497,7 @@ * @deprecated Use purple_blist_alias_contact() instead. */ void purple_contact_set_alias(PurpleContact *contact, const char *alias); +#endif /** * Gets the alias for a contact. diff -r 33822d7271e5 -r 8b9c48347004 libpurple/certificate.c --- a/libpurple/certificate.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/certificate.c Thu Oct 18 17:58:40 2007 +0000 @@ -563,7 +563,7 @@ secondary = g_strdup_printf(_("Common name: %s %s\nFingerprint (SHA1): %s"), cn, cn_match, sha_asc); /* Make a semi-pretty display */ - purple_request_accept_cancel( + purple_request_accept_cancel_with_hint( vrq->cb_data, /* TODO: Find what the handle ought to be */ _("Single-use Certificate Verification"), primary, @@ -572,6 +572,7 @@ NULL, /* No account */ NULL, /* No other user */ NULL, /* No associated conversation */ + PURPLE_REQUEST_UI_HINT_BLIST, vrq, x509_singleuse_verify_cb, x509_singleuse_verify_cb ); @@ -1185,7 +1186,7 @@ vrq->subject_name); /* Make a semi-pretty display */ - purple_request_action( + purple_request_action_with_hint( vrq->cb_data, /* TODO: Find what the handle ought to be */ _("SSL Certificate Verification"), primary, @@ -1194,6 +1195,7 @@ NULL, /* No account */ NULL, /* No other user */ NULL, /* No associated conversation */ + PURPLE_REQUEST_UI_HINT_BLIST, x509_tls_cached_ua_ctx_new(vrq, reason), 3, /* Number of actions */ _("Accept"), x509_tls_cached_user_auth_accept_cb, diff -r 33822d7271e5 -r 8b9c48347004 libpurple/certificate.h --- a/libpurple/certificate.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/certificate.h Thu Oct 18 17:58:40 2007 +0000 @@ -435,7 +435,7 @@ * * @return TRUE if 'crt' has a valid signature made by 'issuer', * otherwise FALSE - * @TODO Find a way to give the reason (bad signature, not the issuer, etc.) + * @todo Find a way to give the reason (bad signature, not the issuer, etc.) */ gboolean purple_certificate_signed_by(PurpleCertificate *crt, PurpleCertificate *issuer); @@ -450,7 +450,7 @@ * @param chain List of PurpleCertificate instances comprising the chain, * in the order certificate, issuer, issuer's issuer, etc. * @return TRUE if the chain is valid. See description. - * @TODO Specify which certificate in the chain caused a failure + * @todo Specify which certificate in the chain caused a failure */ gboolean purple_certificate_check_signature_chain(GList *chain); @@ -781,7 +781,7 @@ * Displays a window showing X.509 certificate information * * @param crt Certificate under an "x509" Scheme - * @TODO Will break on CA certs, as they have no Common Name + * @todo Will break on CA certs, as they have no Common Name */ void purple_certificate_display_x509(PurpleCertificate *crt); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/connection.h --- a/libpurple/connection.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/connection.h Thu Oct 18 17:58:40 2007 +0000 @@ -150,6 +150,7 @@ /**************************************************************************/ /*@{*/ +#ifndef PURPLE_DISABLE_DEPRECATED /** * This function should only be called by purple_account_connect() * in account.c. If you're trying to sign on an account, use that @@ -166,10 +167,14 @@ * @param regist Whether we are registering a new account or just * trying to do a normal signon. * @param password The password to use. + * + * @deprecated As this is internal, we should make it private in 3.0.0. */ void purple_connection_new(PurpleAccount *account, gboolean regist, const char *password); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * This function should only be called by purple_account_unregister() * in account.c. @@ -179,9 +184,15 @@ * * @param account The account to unregister * @param password The password to use. + * @param cb Optional callback to be called when unregistration is complete + * @param user_data user data to pass to the callback + * + * @deprecated As this is internal, we should make it private in 3.0.0. */ void purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Disconnects and destroys a PurpleConnection. * @@ -190,8 +201,11 @@ * function instead. * * @param gc The purple connection to destroy. + * + * @deprecated As this is internal, we should make it private in 3.0.0. */ void purple_connection_destroy(PurpleConnection *gc); +#endif /** * Sets the connection state. PRPLs should call this and pass in diff -r 33822d7271e5 -r 8b9c48347004 libpurple/conversation.c --- a/libpurple/conversation.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/conversation.c Thu Oct 18 17:58:40 2007 +0000 @@ -225,6 +225,7 @@ msg->flags = flags; msg->what = g_strdup(message); msg->when = when; + msg->conv = conv; conv->message_history = g_list_prepend(conv->message_history, msg); } @@ -1208,9 +1209,9 @@ data[0] = conv; data[1] = (gpointer)message; - purple_request_action(conv, NULL, _("Send Message"), text, 0, + purple_request_action_with_hint(conv, NULL, _("Send Message"), text, 0, purple_conversation_get_account(conv), NULL, conv, - data, 2, + PURPLE_REQUEST_UI_HINT_CONV, data, 2, _("_Send Message"), G_CALLBACK(purple_conv_send_confirm_cb), _("Cancel"), NULL); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/conversation.h --- a/libpurple/conversation.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/conversation.h Thu Oct 18 17:58:40 2007 +0000 @@ -294,6 +294,7 @@ char *what; PurpleMessageFlags flags; time_t when; + PurpleConversation *conv; }; /** diff -r 33822d7271e5 -r 8b9c48347004 libpurple/core.c --- a/libpurple/core.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/core.c Thu Oct 18 17:58:40 2007 +0000 @@ -94,6 +94,8 @@ /* The signals subsystem is important and should be first. */ purple_signals_init(); + purple_util_init(); + purple_signal_register(core, "uri-handler", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER, purple_value_new(PURPLE_TYPE_BOOLEAN), 3, @@ -229,6 +231,9 @@ #ifdef HAVE_DBUS purple_dbus_uninit(); #endif + + purple_util_uninit(); + purple_signals_uninit(); g_free(core->ui); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/dnsquery.h --- a/libpurple/dnsquery.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/dnsquery.h Thu Oct 18 17:58:40 2007 +0000 @@ -59,7 +59,7 @@ PurpleDnsQueryFailedCallback failed_cb); /** Called just before @a query_data is freed; this should cancel any - * further use of @q query_data the UI would make. Unneeded if + * further use of @a query_data the UI would make. Unneeded if * #resolve_host is not implemented. */ void (*destroy)(PurpleDnsQueryData *query_data); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/ft.c --- a/libpurple/ft.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/ft.c Thu Oct 18 17:58:40 2007 +0000 @@ -309,12 +309,12 @@ static int purple_xfer_choose_file(PurpleXfer *xfer) { - purple_request_file(xfer, NULL, purple_xfer_get_filename(xfer), + purple_request_file_with_hint(xfer, NULL, purple_xfer_get_filename(xfer), (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE), G_CALLBACK(purple_xfer_choose_file_ok_cb), G_CALLBACK(purple_xfer_choose_file_cancel_cb), purple_xfer_get_account(xfer), xfer->who, NULL, - xfer); + PURPLE_REQUEST_UI_HINT_XFER, xfer); return 0; } @@ -359,10 +359,10 @@ serv_got_im(purple_account_get_connection(xfer->account), xfer->who, xfer->message, 0, time(NULL)); - purple_request_accept_cancel(xfer, NULL, buf, NULL, + purple_request_accept_cancel_with_hint(xfer, NULL, buf, NULL, PURPLE_DEFAULT_ACTION_NONE, xfer->account, xfer->who, NULL, - xfer, + PURPLE_REQUEST_UI_HINT_XFER, xfer, G_CALLBACK(purple_xfer_choose_file), G_CALLBACK(cancel_recv_cb)); @@ -402,10 +402,10 @@ "Remote host: %s\nRemote port: %d"), purple_xfer_get_remote_ip(xfer), purple_xfer_get_remote_port(xfer)); - purple_request_accept_cancel(xfer, NULL, buf, buf2, + purple_request_accept_cancel_with_hint(xfer, NULL, buf, buf2, PURPLE_DEFAULT_ACTION_NONE, xfer->account, xfer->who, NULL, - xfer, + PURPLE_REQUEST_UI_HINT_XFER, xfer, G_CALLBACK(ask_accept_ok), G_CALLBACK(ask_accept_cancel)); g_free(buf); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/notify.h --- a/libpurple/notify.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/notify.h Thu Oct 18 17:58:40 2007 +0000 @@ -289,7 +289,7 @@ */ void purple_notify_searchresults_row_add(PurpleNotifySearchResults *results, GList *row); - +#ifndef PURPLE_DISABLE_DEPRECATED /** * Returns a number of the rows in the search results object. * @@ -308,7 +308,9 @@ * @return Number of the result rows. */ guint purple_notify_searchresults_get_rows_count(PurpleNotifySearchResults *results); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Returns a number of the columns in the search results object. * @@ -327,7 +329,9 @@ * @return Number of the columns. */ guint purple_notify_searchresults_get_columns_count(PurpleNotifySearchResults *results); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Returns a row of the results from the search results object. * @@ -348,7 +352,9 @@ */ GList *purple_notify_searchresults_row_get(PurpleNotifySearchResults *results, unsigned int row_id); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Returns a title of the search results object's column. * @@ -367,6 +373,7 @@ */ char *purple_notify_searchresults_column_get_title(PurpleNotifySearchResults *results, unsigned int column_id); +#endif /*@}*/ diff -r 33822d7271e5 -r 8b9c48347004 libpurple/plugin.c --- a/libpurple/plugin.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/plugin.c Thu Oct 18 17:58:40 2007 +0000 @@ -58,13 +58,9 @@ #ifdef PURPLE_PLUGINS static GList *load_queue = NULL; static GList *plugin_loaders = NULL; +static GList *plugins_to_disable = NULL; #endif -/* - * TODO: I think the intention was to allow multiple load and unload - * callback functions. Perhaps using a GList instead of a - * pointer to a single function. - */ static void (*probe_cb)(void *) = NULL; static void *probe_cb_data = NULL; static void (*load_cb)(PurplePlugin *, void *) = NULL; @@ -254,7 +250,6 @@ * plugins being added to the global name space. * * G_MODULE_BIND_LOCAL was added in glib 2.3.3. - * TODO: I guess there's nothing we can do about that? */ #if GLIB_CHECK_VERSION(2,3,3) plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL); @@ -625,7 +620,6 @@ plugin->loaded = TRUE; - /* TODO */ if (load_cb != NULL) load_cb(plugin, load_cb_data); @@ -643,43 +637,37 @@ { #ifdef PURPLE_PLUGINS GList *l; + GList *ll; g_return_val_if_fail(plugin != NULL, FALSE); - - loaded_plugins = g_list_remove(loaded_plugins, plugin); - if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin)) - protocol_plugins = g_list_remove(protocol_plugins, plugin); - g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE); purple_debug_info("plugins", "Unloading plugin %s\n", plugin->info->name); - /* cancel any pending dialogs the plugin has */ - purple_request_close_with_handle(plugin); - purple_notify_close_with_handle(plugin); - - plugin->loaded = FALSE; - /* Unload all plugins that depend on this plugin. */ - while ((l = plugin->dependent_plugins) != NULL) - { + for (l = plugin->dependent_plugins; l != NULL; l = ll) { const char * dep_name = (const char *)l->data; PurplePlugin *dep_plugin; + /* Store a pointer to the next element in the list. + * This is because we'll be modifying this list in the loop. */ + ll = l->next; + dep_plugin = purple_plugins_find_with_id(dep_name); if (dep_plugin != NULL && purple_plugin_is_loaded(dep_plugin)) { if (!purple_plugin_unload(dep_plugin)) { - char *tmp; - - tmp = g_strdup_printf(_("The dependent plugin %s failed to unload."), - _(dep_plugin->info->name)); - - purple_notify_error(NULL, NULL, - _("There were errors unloading the plugin."), tmp); - g_free(tmp); + g_free(plugin->error); + plugin->error = g_strdup_printf(_("%s requires %s, but it failed to unload."), + _(plugin->info->name), + _(dep_plugin->info->name)); + return FALSE; + } + else + { + plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l); } } } @@ -699,8 +687,8 @@ } if (plugin->native_plugin) { - if (plugin->info->unload != NULL) - plugin->info->unload(plugin); + if (plugin->info->unload && !plugin->info->unload(plugin)) + return FALSE; if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) { PurplePluginProtocolInfo *prpl_info; @@ -724,8 +712,7 @@ prpl_info->protocol_options = NULL; } } - } - else { + } else { PurplePlugin *loader; PurplePluginLoaderInfo *loader_info; @@ -736,14 +723,30 @@ loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); - if (loader_info->unload != NULL) - loader_info->unload(plugin); + if (loader_info->unload && !loader_info->unload(plugin)) + return FALSE; } + /* cancel any pending dialogs the plugin has */ + purple_request_close_with_handle(plugin); + purple_notify_close_with_handle(plugin); + purple_signals_disconnect_by_handle(plugin); purple_plugin_ipc_unregister_all(plugin); - /* TODO */ + loaded_plugins = g_list_remove(loaded_plugins, plugin); + if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin)) + protocol_plugins = g_list_remove(protocol_plugins, plugin); + plugins_to_disable = g_list_remove(plugins_to_disable, plugin); + plugin->loaded = FALSE; + + /* We wouldn't be anywhere near here if the plugin wasn't loaded, so + * if plugin->error is set at all, it had to be from a previous + * unload failure. It's obviously okay now. + */ + g_free(plugin->error); + plugin->error = NULL; + if (unload_cb != NULL) unload_cb(plugin, unload_cb_data); @@ -757,6 +760,15 @@ #endif /* PURPLE_PLUGINS */ } +void +purple_plugin_disable(PurplePlugin *plugin) +{ + g_return_if_fail(plugin != NULL); + + if (!g_list_find(plugins_to_disable, plugin)) + plugins_to_disable = g_list_prepend(plugins_to_disable, plugin); +} + gboolean purple_plugin_reload(PurplePlugin *plugin) { @@ -1222,14 +1234,14 @@ #ifdef PURPLE_PLUGINS GList *pl; GList *files = NULL; - PurplePlugin *p; for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) { - p = pl->data; + PurplePlugin *plugin = pl->data; - if (p->info->type != PURPLE_PLUGIN_PROTOCOL && - p->info->type != PURPLE_PLUGIN_LOADER) { - files = g_list_append(files, p->path); + if (plugin->info->type != PURPLE_PLUGIN_PROTOCOL && + plugin->info->type != PURPLE_PLUGIN_LOADER && + !g_list_find(plugins_to_disable, plugin)) { + files = g_list_append(files, plugin->path); } } @@ -1391,6 +1403,7 @@ if (probe_cb != NULL) probe_cb(probe_cb_data); + #endif /* PURPLE_PLUGINS */ } @@ -1464,7 +1477,6 @@ void purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data) { - /* TODO */ probe_cb = func; probe_cb_data = data; } @@ -1472,7 +1484,6 @@ void purple_plugins_unregister_probe_notify_cb(void (*func)(void *)) { - /* TODO */ probe_cb = NULL; probe_cb_data = NULL; } @@ -1481,7 +1492,6 @@ purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *), void *data) { - /* TODO */ load_cb = func; load_cb_data = data; } @@ -1489,7 +1499,6 @@ void purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *)) { - /* TODO */ load_cb = NULL; load_cb_data = NULL; } @@ -1498,7 +1507,6 @@ purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *), void *data) { - /* TODO */ unload_cb = func; unload_cb_data = data; } @@ -1506,7 +1514,6 @@ void purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *, void *)) { - /* TODO */ unload_cb = NULL; unload_cb_data = NULL; } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/plugin.h --- a/libpurple/plugin.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/plugin.h Thu Oct 18 17:58:40 2007 +0000 @@ -70,11 +70,6 @@ * * This is used in the version 2.0 API and up. */ -/* TODO We need to figure out exactly what parts of this are required. The - * dependent plugin unloading stuff was causing crashes with perl and tcl - * plugins because they didn't set ids and the dependency code was requiring - * them. Then we need to actually make sure that plugins have all the right - * parts before loading them. */ struct _PurplePluginInfo { unsigned int magic; @@ -296,6 +291,18 @@ gboolean purple_plugin_unload(PurplePlugin *plugin); /** + * Disable a plugin. + * + * This function adds the plugin to a list of plugins to "disable at the next + * startup" by excluding said plugins from the list of plugins to save. The + * UI needs to call purple_plugins_save_loaded() after calling this for it + * to have any effect. + * + * @since 2.3.0 + */ +void purple_plugin_disable(PurplePlugin *plugin); + +/** * Reloads a plugin. * * @param plugin The old plugin handle. @@ -525,53 +532,71 @@ */ gboolean purple_plugins_enabled(void); +#ifndef PURPLE_DISABLE_DEPRECATED /** * Registers a function that will be called when probing is finished. * * @param func The callback function. * @param data Data to pass to the callback. + * @deprecated If you need this, ask for a plugin-probe signal to be added. */ void purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Unregisters a function that would be called when probing is finished. * * @param func The callback function. + * @deprecated If you need this, ask for a plugin-probe signal to be added. */ void purple_plugins_unregister_probe_notify_cb(void (*func)(void *)); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Registers a function that will be called when a plugin is loaded. * * @param func The callback function. * @param data Data to pass to the callback. + * @deprecated Use the plugin-load signal instead. */ void purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *), void *data); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Unregisters a function that would be called when a plugin is loaded. * * @param func The callback function. + * @deprecated Use the plugin-load signal instead. */ void purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *)); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Registers a function that will be called when a plugin is unloaded. * * @param func The callback function. * @param data Data to pass to the callback. + * @deprecated Use the plugin-unload signal instead. */ void purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *), void *data); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Unregisters a function that would be called when a plugin is unloaded. * * @param func The callback function. + * @deprecated Use the plugin-unload signal instead. */ void purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *, void *)); +#endif /** * Finds a plugin with the specified name. diff -r 33822d7271e5 -r 8b9c48347004 libpurple/plugins/autoaccept.c --- a/libpurple/plugins/autoaccept.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/plugins/autoaccept.c Thu Oct 18 17:58:40 2007 +0000 @@ -159,12 +159,12 @@ message = g_strdup_printf(_("When a file-transfer request arrives from %s"), purple_contact_get_alias((PurpleContact *)node)); - purple_request_choice(plugin, _("Set Autoaccept Setting"), message, + purple_request_choice_with_hint(plugin, _("Set Autoaccept Setting"), message, NULL, purple_blist_node_get_int(node, "autoaccept"), _("_Save"), G_CALLBACK(save_cb), _("_Cancel"), NULL, NULL, NULL, NULL, - node, + PURPLE_REQUEST_UI_HINT_XFER, node, _("Ask"), FT_ASK, _("Auto Accept"), FT_ACCEPT, _("Auto Reject"), FT_REJECT, diff -r 33822d7271e5 -r 8b9c48347004 libpurple/plugins/buddynote.c --- a/libpurple/plugins/buddynote.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/plugins/buddynote.c Thu Oct 18 17:58:40 2007 +0000 @@ -43,14 +43,14 @@ note = purple_blist_node_get_string(node, "notes"); - purple_request_input(node, _("Notes"), + purple_request_input_with_hint(node, _("Notes"), _("Enter your notes below..."), NULL, note, TRUE, FALSE, "html", _("Save"), G_CALLBACK(do_it_cb), _("Cancel"), G_CALLBACK(dont_do_it_cb), NULL, NULL, NULL, - node); + PURPLE_REQUEST_UI_HINT_BUDDY, node); } static void diff -r 33822d7271e5 -r 8b9c48347004 libpurple/plugins/idle.c --- a/libpurple/plugins/idle.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/plugins/idle.c Thu Oct 18 17:58:40 2007 +0000 @@ -161,7 +161,7 @@ request = purple_request_fields_new(); purple_request_fields_add_group(request, group); - purple_request_fields(action->plugin, + purple_request_fields_with_hint(action->plugin, N_("I'dle Mak'er"), _("Set Account Idle Time"), NULL, @@ -169,7 +169,7 @@ _("_Set"), G_CALLBACK(idle_action_ok), _("_Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_ACCOUNT, NULL); } static void @@ -195,7 +195,7 @@ request = purple_request_fields_new(); purple_request_fields_add_group(request, group); - purple_request_fields(action->plugin, + purple_request_fields_with_hint(action->plugin, N_("I'dle Mak'er"), _("Unset Account Idle Time"), NULL, @@ -203,7 +203,7 @@ _("_Unset"), G_CALLBACK(unidle_action_ok), _("_Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_ACCOUNT, NULL); } static void @@ -221,7 +221,7 @@ request = purple_request_fields_new(); purple_request_fields_add_group(request, group); - purple_request_fields(action->plugin, + purple_request_fields_with_hint(action->plugin, N_("I'dle Mak'er"), _("Set Idle Time for All Accounts"), NULL, @@ -229,7 +229,7 @@ _("_Set"), G_CALLBACK(idle_all_action_ok), _("_Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_ACCOUNT, NULL); } static void diff -r 33822d7271e5 -r 8b9c48347004 libpurple/plugins/log_reader.c --- a/libpurple/plugins/log_reader.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/plugins/log_reader.c Thu Oct 18 17:58:40 2007 +0000 @@ -28,6 +28,19 @@ NAME_GUESS_THEM }; +/* Some common functions. */ +static int get_month(const char *month) +{ + int iter; + const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; + for (iter = 0; months[iter]; iter++) { + if (strcmp(month, months[iter]) == 0) + break; + } + return iter; +} + /***************************************************************************** * Adium Logger * @@ -103,9 +116,10 @@ } else { char *filename = g_build_filename(path, file, NULL); FILE *handle = g_fopen(filename, "rb"); - char *contents; + char contents[57]; /* XXX: This is really inflexible. */ char *contents2; struct adium_logger_data *data; + size_t rd; PurpleLog *log; if (!handle) { @@ -113,11 +127,9 @@ continue; } - /* XXX: This is really inflexible. */ - contents = g_malloc(57); - fread(contents, 56, 1, handle); + rd = fread(contents, 1, 56, handle) == 0; fclose(handle); - contents[56] = '\0'; + contents[rd] = '\0'; /* XXX: This is fairly inflexible. */ contents2 = contents; @@ -135,11 +147,9 @@ purple_debug_error("Adium log parse", "Contents timestamp parsing error\n"); - g_free(contents); g_free(filename); continue; } - g_free(contents); data = g_new0(struct adium_logger_data, 1); data->path = filename; @@ -168,21 +178,20 @@ } else { char *filename = g_build_filename(path, file, NULL); FILE *handle = g_fopen(filename, "rb"); - char *contents; + char contents[14]; /* XXX: This is really inflexible. */ char *contents2; struct adium_logger_data *data; PurpleLog *log; + size_t rd; if (!handle) { g_free(filename); continue; } - /* XXX: This is really inflexible. */ - contents = g_malloc(14); - fread(contents, 13, 1, handle); + rd = fread(contents, 1, 13, handle); fclose(handle); - contents[13] = '\0'; + contents[rd] = '\0'; contents2 = contents; while (*contents2 && *contents2 != '(') @@ -195,13 +204,10 @@ purple_debug_error("Adium log parse", "Contents timestamp parsing error\n"); - g_free(contents); g_free(filename); continue; } - g_free(contents); - tm.tm_year -= 1900; tm.tm_mon -= 1; @@ -1355,36 +1361,7 @@ * daylight savings time. */ tm.tm_isdst = -1; - - /* Ugly hack, in case current locale - * is not English. This code is taken - * from log.c. - */ - if (strcmp(month, "Jan") == 0) { - tm.tm_mon= 0; - } else if (strcmp(month, "Feb") == 0) { - tm.tm_mon = 1; - } else if (strcmp(month, "Mar") == 0) { - tm.tm_mon = 2; - } else if (strcmp(month, "Apr") == 0) { - tm.tm_mon = 3; - } else if (strcmp(month, "May") == 0) { - tm.tm_mon = 4; - } else if (strcmp(month, "Jun") == 0) { - tm.tm_mon = 5; - } else if (strcmp(month, "Jul") == 0) { - tm.tm_mon = 6; - } else if (strcmp(month, "Aug") == 0) { - tm.tm_mon = 7; - } else if (strcmp(month, "Sep") == 0) { - tm.tm_mon = 8; - } else if (strcmp(month, "Oct") == 0) { - tm.tm_mon = 9; - } else if (strcmp(month, "Nov") == 0) { - tm.tm_mon = 10; - } else if (strcmp(month, "Dec") == 0) { - tm.tm_mon = 11; - } + tm.tm_mon = get_month(month); data = g_new0( struct trillian_logger_data, 1); @@ -1446,7 +1423,7 @@ file = g_fopen(data->path, "rb"); fseek(file, data->offset, SEEK_SET); - fread(read, data->length, 1, file); + data->length = fread(read, 1, data->length, file); fclose(file); if (read[data->length-1] == '\n') { @@ -1945,7 +1922,7 @@ contents = g_malloc(data->length + 2); fseek(file, data->offset, SEEK_SET); - fread(contents, data->length, 1, file); + data->length = fread(contents, 1, data->length, file); fclose(file); contents[data->length] = '\n'; @@ -2098,6 +2075,347 @@ g_free(data); } +/************************************************************************* + * aMSN Logger * + *************************************************************************/ + +/* The aMSN logger doesn't write logs, only reads them. This is to include + * aMSN logs in the log viewer transparently. + */ + +static PurpleLogLogger *amsn_logger; + +struct amsn_logger_data { + char *path; + int offset; + int length; +}; + +#define AMSN_LOG_CONV_START "|\"LRED[Conversation started on " +#define AMSN_LOG_CONV_END "|\"LRED[You have closed the window on " +#define AMSN_LOG_CONV_EXTRA "01 Aug 2001 00:00:00]" + +static GList *amsn_logger_parse_file(char *filename, const char *sn, PurpleAccount *account) +{ + GList *list = NULL; + GError *error; + char *contents; + struct amsn_logger_data *data; + PurpleLog *log; + + purple_debug_info("aMSN logger", "Reading %s\n", filename); + error = NULL; + if (!g_file_get_contents(filename, &contents, NULL, &error)) { + purple_debug_error("aMSN logger", + "Couldn't read file %s: %s \n", filename, + (error && error->message) ? + error->message : "Unknown error"); + if (error) + g_error_free(error); + } else { + char *c = contents; + gboolean found_start = FALSE; + char *start_log = c; + int offset = 0; + struct tm tm; + while (c && *c) { + if (purple_str_has_prefix(c, AMSN_LOG_CONV_START)) { + char month[4]; + if (sscanf(c + strlen(AMSN_LOG_CONV_START), + "%u %3s %u %u:%u:%u", + &tm.tm_mday, (char*)&month, &tm.tm_year, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + found_start = FALSE; + purple_debug_error("aMSN logger", + "Error parsing start date for %s\n", + filename); + } else { + tm.tm_year -= 1900; + + /* Let the C library deal with + * daylight savings time. + */ + tm.tm_isdst = -1; + tm.tm_mon = get_month(month); + + found_start = TRUE; + offset = c - contents; + start_log = c; + } + } else if (purple_str_has_prefix(c, AMSN_LOG_CONV_END) && found_start) { + data = g_new0(struct amsn_logger_data, 1); + data->path = g_strdup(filename); + data->offset = offset; + data->length = c - start_log + + strlen(AMSN_LOG_CONV_END) + + strlen(AMSN_LOG_CONV_EXTRA); + log = purple_log_new(PURPLE_LOG_IM, sn, account, NULL, mktime(&tm), NULL); + log->logger = amsn_logger; + log->logger_data = data; + list = g_list_prepend(list, log); + found_start = FALSE; + + purple_debug_info("aMSN logger", + "Found log for %s:" + " path = (%s)," + " offset = (%d)," + " length = (%d)\n", + sn, data->path, data->offset, data->length); + } + c = strstr(c, "\n"); + c++; + } + + /* I've seen the file end without the AMSN_LOG_CONV_END bit */ + if (found_start) { + data = g_new0(struct amsn_logger_data, 1); + data->path = g_strdup(filename); + data->offset = offset; + data->length = c - start_log + + strlen(AMSN_LOG_CONV_END) + + strlen(AMSN_LOG_CONV_EXTRA); + log = purple_log_new(PURPLE_LOG_IM, sn, account, NULL, mktime(&tm), NULL); + log->logger = amsn_logger; + log->logger_data = data; + list = g_list_prepend(list, log); + found_start = FALSE; + + purple_debug_info("aMSN logger", + "Found log for %s:" + " path = (%s)," + " offset = (%d)," + " length = (%d)\n", + sn, data->path, data->offset, data->length); + } + g_free(contents); + } + + return list; +} + +/* `log_dir`/username@hotmail.com/logs/buddyname@hotmail.com.log */ +/* `log_dir`/username@hotmail.com/logs/Month Year/buddyname@hotmail.com.log */ +static GList *amsn_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account) +{ + GList *list = NULL; + const char *logdir; + char *username; + char *log_path; + char *buddy_log; + char *filename; + GDir *dir; + const char *name; + + logdir = purple_prefs_get_string("/plugins/core/log_reader/amsn/log_directory"); + + /* By clearing the log directory path, this logger can be (effectively) disabled. */ + if (!logdir || !*logdir) + return NULL; + + /* aMSN only works with MSN/WLM */ + if (strcmp(account->protocol_id, "prpl-msn")) + return NULL; + + username = g_strdup(purple_normalize(account, account->username)); + buddy_log = g_strdup_printf("%s.log", purple_normalize(account, sn)); + log_path = g_build_filename(logdir, username, "logs", NULL); + + /* First check in the top-level */ + filename = g_build_filename(log_path, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = amsn_logger_parse_file(filename, sn, account); + else + g_free(filename); + + /* Check in previous months */ + dir = g_dir_open(log_path, 0, NULL); + if (dir) { + while ((name = g_dir_read_name(dir)) != NULL) { + filename = g_build_filename(log_path, name, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); + g_free(filename); + } + g_dir_close(dir); + } + + g_free(log_path); + + /* New versions use 'friendlier' directory names */ + purple_util_chrreplace(username, '@', '_'); + purple_util_chrreplace(username, '.', '_'); + + log_path = g_build_filename(logdir, username, "logs", NULL); + + /* First check in the top-level */ + filename = g_build_filename(log_path, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); + g_free(filename); + + /* Check in previous months */ + dir = g_dir_open(log_path, 0, NULL); + if (dir) { + while ((name = g_dir_read_name(dir)) != NULL) { + filename = g_build_filename(log_path, name, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); + g_free(filename); + } + g_dir_close(dir); + } + + g_free(log_path); + g_free(username); + g_free(buddy_log); + + return list; +} + +/* Really it's |"L, but the string's been escaped */ +#define AMSN_LOG_FORMAT_TAG "|"L" + +static char *amsn_logger_read(PurpleLog *log, PurpleLogReadFlags *flags) +{ + struct amsn_logger_data *data; + FILE *file; + char *contents; + char *escaped; + GString *formatted; + char *start; + gboolean in_span = FALSE; + + if (flags != NULL) + *flags = PURPLE_LOG_READ_NO_NEWLINE; + + g_return_val_if_fail(log != NULL, g_strdup("")); + + data = log->logger_data; + + g_return_val_if_fail(data->path != NULL, g_strdup("")); + g_return_val_if_fail(data->length > 0, g_strdup("")); + + contents = g_malloc(data->length + 2); + + file = g_fopen(data->path, "rb"); + g_return_val_if_fail(file != NULL, g_strdup("")); + + fseek(file, data->offset, SEEK_SET); + data->length = fread(contents, 1, data->length, file); + fclose(file); + + contents[data->length] = '\n'; + contents[data->length + 1] = '\0'; + + escaped = g_markup_escape_text(contents, -1); + g_free(contents); + contents = escaped; + + formatted = g_string_sized_new(data->length + 2); + + start = contents; + while (start && *start) { + char *end; + char *old_tag; + char *tag; + end = strstr(start, "\n"); + if (!end) + break; + *end = '\0'; + if (purple_str_has_prefix(start, AMSN_LOG_FORMAT_TAG) && in_span) { + /* New format for this line */ + g_string_append(formatted, "
"); + in_span = FALSE; + } else if (start != contents) { + /* Continue format from previous line */ + g_string_append(formatted, "
"); + } + old_tag = start; + tag = strstr(start, AMSN_LOG_FORMAT_TAG); + while (tag) { + g_string_append_len(formatted, old_tag, tag - old_tag); + tag += strlen(AMSN_LOG_FORMAT_TAG); + if (in_span) { + g_string_append(formatted, ""); + in_span = FALSE; + } + if (*tag == 'C') { + /* |"LCxxxxxx is a hex colour */ + char colour[7]; + strncpy(colour, tag + 1, 6); + colour[6] = '\0'; + g_string_append_printf(formatted, "", colour); + /* This doesn't appear to work? */ + /* g_string_append_printf(formatted, "", tag + 1); */ + in_span = TRUE; + old_tag = tag + 7; /* C + xxxxxx */ + } else { + /* |"Lxxx is a 3-digit colour code */ + if (purple_str_has_prefix(tag, "RED")) { + g_string_append(formatted, ""); + in_span = TRUE; + } else if (purple_str_has_prefix(tag, "GRA")) { + g_string_append(formatted, ""); + in_span = TRUE; + } else if (purple_str_has_prefix(tag, "NOR")) { + g_string_append(formatted, ""); + in_span = TRUE; + } else if (purple_str_has_prefix(tag, "ITA")) { + g_string_append(formatted, ""); + in_span = TRUE; + } else if (purple_str_has_prefix(tag, "GRE")) { + g_string_append(formatted, ""); + in_span = TRUE; + } else { + purple_debug_info("aMSN logger", "Unknown colour format: %3s\n", tag); + } + old_tag = tag + 3; + } + tag = strstr(tag, AMSN_LOG_FORMAT_TAG); + } + g_string_append(formatted, old_tag); + start = end + 1; + } + if (in_span) + g_string_append(formatted, ""); + + g_free(contents); + + return g_string_free(formatted, FALSE); +} + +static int amsn_logger_size(PurpleLog *log) +{ + struct amsn_logger_data *data; + char *text; + int size; + + g_return_val_if_fail(log != NULL, 0); + + data = log->logger_data; + + if (purple_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) { + return data ? data->length : 0; + } + + text = amsn_logger_read(log, NULL); + size = strlen(text); + g_free(text); + + return size; +} + +static void amsn_logger_finalize(PurpleLog *log) +{ + struct amsn_logger_data *data; + + g_return_if_fail(log != NULL); + + data = log->logger_data; + g_free(data->path); + g_free(data); +} + /***************************************************************************** * Plugin Code * *****************************************************************************/ @@ -2347,6 +2665,19 @@ #endif purple_prefs_add_string("/plugins/core/log_reader/qip/log_directory", path ? path : ""); g_free(path); + + /* Add aMSN Messenger log directory preference. */ + purple_prefs_add_none("/plugins/core/log_reader/amsn"); + + /* Calculate default aMSN log directory. */ +#ifdef _WIN32 + folder = wpurple_get_special_folder(CSIDL_PROFILE); /* Silly aMSN, not using CSIDL_APPDATA */ + path = g_build_filename(folder, "amsn", NULL); +#else + path = g_build_filename(purple_home_dir(), ".amsn", NULL); +#endif + purple_prefs_add_string("/plugins/core/log_reader/amsn/log_directory", path); + g_free(path); } static gboolean @@ -2429,6 +2760,18 @@ trillian_logger_size); purple_log_logger_add(trillian_logger); + /* The names of IM clients are marked for translation at the request of + translators who wanted to transliterate them. Many translators + choose to leave them alone. Choose what's best for your language. */ + amsn_logger = purple_log_logger_new("amsn", _("aMSN"), 6, + NULL, + NULL, + amsn_logger_finalize, + amsn_logger_list, + amsn_logger_read, + amsn_logger_size); + purple_log_logger_add(amsn_logger); + return TRUE; } @@ -2445,6 +2788,7 @@ purple_log_logger_remove(msn_logger); purple_log_logger_remove(trillian_logger); purple_log_logger_remove(qip_logger); + purple_log_logger_remove(amsn_logger); return TRUE; } @@ -2505,6 +2849,10 @@ "/plugins/core/log_reader/trillian/log_directory", _("Trillian")); purple_plugin_pref_frame_add(frame, ppref); + ppref = purple_plugin_pref_new_with_name_and_label( + "/plugins/core/log_reader/amsn/log_directory", _("aMSN")); + purple_plugin_pref_frame_add(frame, ppref); + return frame; } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/plugins/offlinemsg.c --- a/libpurple/plugins/offlinemsg.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/plugins/offlinemsg.c Thu Oct 18 17:58:40 2007 +0000 @@ -157,11 +157,11 @@ "rest of the messages in a pounce and automatically send them " "when \"%s\" logs back in?"), who, who); - purple_request_action(handle, _("Offline Message"), ask, + purple_request_action_with_hint(handle, _("Offline Message"), ask, _("You can edit/delete the pounce from the `Buddy Pounces' dialog"), 1, offline->account, offline->who, offline->conv, - offline, 2, + PURPLE_REQUEST_UI_HINT_BUDDY, offline, 2, _("Yes"), record_pounce, _("No"), cancel_poune); g_free(ask); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/plugins/perl/common/Request.xs --- a/libpurple/plugins/perl/common/Request.xs Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/plugins/perl/common/Request.xs Thu Oct 18 17:58:40 2007 +0000 @@ -141,7 +141,38 @@ gpr->cancel_cb = g_strdup_printf("Purple::Script::%s::%s", basename, SvPV(cancel_cb, len)); g_free(basename); - RETVAL = purple_request_input(handle, title, primary, secondary, default_value, multiline, masked, hint, ok_text, G_CALLBACK(purple_perl_request_ok_cb), cancel_text, G_CALLBACK(purple_perl_request_cancel_cb), NULL, NULL, NULL, gpr); + RETVAL = purple_request_input_with_hint(handle, title, primary, secondary, default_value, multiline, masked, hint, ok_text, G_CALLBACK(purple_perl_request_ok_cb), cancel_text, G_CALLBACK(purple_perl_request_cancel_cb), NULL, NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, gpr); +OUTPUT: + RETVAL + +void * +purple_request_input_with_hint(handle, title, primary, secondary, default_value, multiline, masked, hint, ok_text, ok_cb, cancel_text, cancel_cb, ui_hint) + Purple::Plugin handle + const char * title + const char * primary + const char * secondary + const char * default_value + gboolean multiline + gboolean masked + gchar * hint + const char * ok_text + SV * ok_cb + const char * cancel_text + SV * cancel_cb + const char * ui_hint +CODE: + PurplePerlRequestData *gpr; + STRLEN len; + char *basename; + + basename = g_path_get_basename(handle->path); + purple_perl_normalize_script_name(basename); + gpr = g_new(PurplePerlRequestData, 1); + gpr->ok_cb = g_strdup_printf("Purple::Script::%s::%s", basename, SvPV(ok_cb, len)); + gpr->cancel_cb = g_strdup_printf("Purple::Script::%s::%s", basename, SvPV(cancel_cb, len)); + g_free(basename); + + RETVAL = purple_request_input_with_hint(handle, title, primary, secondary, default_value, multiline, masked, hint, ok_text, G_CALLBACK(purple_perl_request_ok_cb), cancel_text, G_CALLBACK(purple_perl_request_cancel_cb), NULL, NULL, NULL, ui_hint, gpr); OUTPUT: RETVAL @@ -165,7 +196,32 @@ gpr->cancel_cb = g_strdup_printf("Purple::Script::%s::%s", basename, SvPV(cancel_cb, len)); g_free(basename); - RETVAL = purple_request_file(handle, title, filename, savedialog, G_CALLBACK(purple_perl_request_ok_cb), G_CALLBACK(purple_perl_request_cancel_cb), NULL, NULL, NULL, gpr); + RETVAL = purple_request_file_with_hint(handle, title, filename, savedialog, G_CALLBACK(purple_perl_request_ok_cb), G_CALLBACK(purple_perl_request_cancel_cb), NULL, NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, gpr); +OUTPUT: + RETVAL + +void * +purple_request_file_with_hint(handle, title, filename, savedialog, ok_cb, cancel_cb, ui_hint) + Purple::Plugin handle + const char * title + const char * filename + gboolean savedialog + SV * ok_cb + SV * cancel_cb + const char * ui_hint +CODE: + PurplePerlRequestData *gpr; + STRLEN len; + char *basename; + + basename = g_path_get_basename(handle->path); + purple_perl_normalize_script_name(basename); + gpr = g_new(PurplePerlRequestData, 1); + gpr->ok_cb = g_strdup_printf("Purple::Script::%s::%s", basename, SvPV(ok_cb, len)); + gpr->cancel_cb = g_strdup_printf("Purple::Script::%s::%s", basename, SvPV(cancel_cb, len)); + g_free(basename); + + RETVAL = purple_request_file_with_hint(handle, title, filename, savedialog, G_CALLBACK(purple_perl_request_ok_cb), G_CALLBACK(purple_perl_request_cancel_cb), NULL, NULL, NULL, ui_hint, gpr); OUTPUT: RETVAL @@ -192,7 +248,35 @@ gpr->cancel_cb = g_strdup_printf("Purple::Script::%s::%s", basename, SvPV(cancel_cb, len)); g_free(basename); - RETVAL = purple_request_fields(handle, title, primary, secondary, fields, ok_text, G_CALLBACK(purple_perl_request_ok_cb), cancel_text, G_CALLBACK(purple_perl_request_cancel_cb), NULL, NULL, NULL, gpr); + RETVAL = purple_request_fields_with_hint(handle, title, primary, secondary, fields, ok_text, G_CALLBACK(purple_perl_request_ok_cb), cancel_text, G_CALLBACK(purple_perl_request_cancel_cb), NULL, NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, gpr); +OUTPUT: + RETVAL + +void * +purple_request_fields_with_hint(handle, title, primary, secondary, fields, ok_text, ok_cb, cancel_text, cancel_cb, ui_hint) + Purple::Plugin handle + const char * title + const char * primary + const char * secondary + Purple::Request::Fields fields + const char * ok_text + SV * ok_cb + const char * cancel_text + SV * cancel_cb + const char *ui_hint +CODE: + PurplePerlRequestData *gpr; + STRLEN len; + char *basename; + + basename = g_path_get_basename(handle->path); + purple_perl_normalize_script_name(basename); + gpr = g_new(PurplePerlRequestData, 1); + gpr->ok_cb = g_strdup_printf("Purple::Script::%s::%s", basename, SvPV(ok_cb, len)); + gpr->cancel_cb = g_strdup_printf("Purple::Script::%s::%s", basename, SvPV(cancel_cb, len)); + g_free(basename); + + RETVAL = purple_request_fields_with_hint(handle, title, primary, secondary, fields, ok_text, G_CALLBACK(purple_perl_request_ok_cb), cancel_text, G_CALLBACK(purple_perl_request_cancel_cb), NULL, NULL, NULL, ui_hint, gpr); OUTPUT: RETVAL diff -r 33822d7271e5 -r 8b9c48347004 libpurple/plugins/signals-test.c --- a/libpurple/plugins/signals-test.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/plugins/signals-test.c Thu Oct 18 17:58:40 2007 +0000 @@ -76,6 +76,28 @@ old, purple_account_get_alias(account)); } +static int +account_authorization_requested_cb(PurpleAccount *account, const char *user, gpointer data) +{ + purple_debug_misc("signals test", "account-authorization-requested (%s, %s)\n", + purple_account_get_username(account), user); + return 0; +} + +static void +account_authorization_granted_cb(PurpleAccount *account, const char *user, gpointer data) +{ + purple_debug_misc("signals test", "account-authorization-granted (%s, %s)\n", + purple_account_get_username(account), user); +} + +static void +account_authorization_denied_cb(PurpleAccount *account, const char *user, gpointer data) +{ + purple_debug_misc("signals test", "account-authorization-denied (%s, %s)\n", + purple_account_get_username(account), user); +} + /************************************************************************** * Buddy Icons signal callbacks **************************************************************************/ @@ -568,6 +590,12 @@ plugin, PURPLE_CALLBACK(account_status_changed), NULL); purple_signal_connect(accounts_handle, "account-alias-changed", plugin, PURPLE_CALLBACK(account_alias_changed), NULL); + purple_signal_connect(accounts_handle, "account-authorization-requested", + plugin, PURPLE_CALLBACK(account_authorization_requested_cb), NULL); + purple_signal_connect(accounts_handle, "account-authorization-denied", + plugin, PURPLE_CALLBACK(account_authorization_denied_cb), NULL); + purple_signal_connect(accounts_handle, "account-authorization-granted", + plugin, PURPLE_CALLBACK(account_authorization_granted_cb), NULL); /* Buddy List subsystem signals */ purple_signal_connect(blist_handle, "buddy-status-changed", diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/bonjour/buddy.c --- a/libpurple/protocols/bonjour/buddy.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.c Thu Oct 18 17:58:40 2007 +0000 @@ -62,9 +62,11 @@ } void -set_bonjour_buddy_value(BonjourBuddy* buddy, const char *record_key, const char *value, uint32_t len){ +set_bonjour_buddy_value(BonjourBuddy* buddy, const char *record_key, const char *value, guint32 len){ gchar **fld = NULL; + g_return_if_fail(record_key != NULL); + if (!strcmp(record_key, "1st")) fld = &buddy->first; else if(!strcmp(record_key, "email")) diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/bonjour/buddy.h --- a/libpurple/protocols/bonjour/buddy.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.h Thu Oct 18 17:58:40 2007 +0000 @@ -83,7 +83,7 @@ /** * Sets a value in the BonjourBuddy struct, destroying the old value */ -void set_bonjour_buddy_value(BonjourBuddy *buddy, const char *record_key, const char *value, uint32_t len); +void set_bonjour_buddy_value(BonjourBuddy *buddy, const char *record_key, const char *value, guint32 len); /** * Check if all the compulsory buddy data is present. diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/gg/gg.c --- a/libpurple/protocols/gg/gg.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/gg/gg.c Thu Oct 18 17:58:40 2007 +0000 @@ -333,10 +333,10 @@ { PurpleConnection *gc = (PurpleConnection *)action->context; - purple_request_file(action, _("Save buddylist..."), NULL, TRUE, + purple_request_file_with_hint(action, _("Save buddylist..."), NULL, TRUE, G_CALLBACK(ggp_callback_buddylist_save_ok), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_BLIST, gc); } /* }}} */ @@ -347,10 +347,10 @@ { PurpleConnection *gc = (PurpleConnection *)action->context; - purple_request_file(action, "Load buddylist from file...", NULL, FALSE, + purple_request_file_with_hint(action, "Load buddylist from file...", NULL, FALSE, G_CALLBACK(ggp_callback_buddylist_load_ok), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_BLIST, gc); } /* }}} */ @@ -498,7 +498,7 @@ _("Current token"), token->data, token->size); purple_request_field_group_add_field(group, field); - purple_request_fields(account, + purple_request_fields_with_hint(account, _("Register New Gadu-Gadu Account"), _("Register New Gadu-Gadu Account"), _("Please, fill in the following fields"), @@ -506,7 +506,7 @@ _("OK"), G_CALLBACK(ggp_callback_register_account_ok), _("Cancel"), G_CALLBACK(ggp_callback_register_account_cancel), purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_REGISTER, gc); } /* }}} */ @@ -657,7 +657,7 @@ _("Only online"), FALSE); purple_request_field_group_add_field(group, field); - purple_request_fields(gc, + purple_request_fields_with_hint(gc, _("Find buddies"), _("Find buddies"), _("Please, enter your search criteria below"), @@ -665,7 +665,7 @@ _("OK"), G_CALLBACK(ggp_callback_find_buddies), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_BLIST, gc); } /* }}} */ @@ -795,14 +795,14 @@ _("Please, enter your current password and your new password for UIN: "), ggp_get_uin(purple_connection_get_account(gc))); - purple_request_fields(gc, + purple_request_fields_with_hint(gc, _("Change Gadu-Gadu Password"), _("Change Gadu-Gadu Password"), msg, fields, _("OK"), G_CALLBACK(ggp_callback_change_passwd_ok), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); g_free(msg); } @@ -875,7 +875,7 @@ msg = g_strdup_printf(_("Select a chat for buddy: %s"), purple_buddy_get_alias(buddy)); - purple_request_fields(gc, + purple_request_fields_with_hint(gc, _("Add to chat..."), _("Add to chat..."), msg, @@ -883,7 +883,7 @@ _("Add"), G_CALLBACK(ggp_callback_add_to_chat_ok), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_BUDDY, gc); g_free(msg); } /* }}} */ diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/auth.c --- a/libpurple/protocols/jabber/auth.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/auth.c Thu Oct 18 17:58:40 2007 +0000 @@ -318,10 +318,10 @@ } else if (!plaintext) { char *msg = g_strdup_printf(_("%s requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), js->gc->account->username); - purple_request_yes_no(js->gc, _("Plaintext Authentication"), + purple_request_yes_no_with_hint(js->gc, _("Plaintext Authentication"), _("Plaintext Authentication"), msg, - 2, js->gc->account, NULL, NULL, js->gc->account, + 2, js->gc->account, NULL, NULL, PURPLE_REQUEST_UI_HINT_ACCOUNT, js->gc->account, allow_cyrus_plaintext_auth, disallow_plaintext_auth); g_free(msg); @@ -507,13 +507,13 @@ if(js->gsc == NULL && !purple_account_get_bool(js->gc->account, "auth_plain_in_clear", FALSE)) { char *msg = g_strdup_printf(_("%s requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), js->gc->account->username); - purple_request_yes_no(js->gc, _("Plaintext Authentication"), + purple_request_yes_no_with_hint(js->gc, _("Plaintext Authentication"), _("Plaintext Authentication"), msg, 2, purple_connection_get_account(js->gc), NULL, NULL, - purple_connection_get_account(js->gc), allow_plaintext_auth, - disallow_plaintext_auth); + PURPLE_REQUEST_UI_HINT_ACCOUNT, purple_connection_get_account(js->gc), + allow_plaintext_auth, disallow_plaintext_auth); g_free(msg); return; } @@ -595,13 +595,13 @@ } else if(xmlnode_get_child(query, "password")) { if(js->gsc == NULL && !purple_account_get_bool(js->gc->account, "auth_plain_in_clear", FALSE)) { - purple_request_yes_no(js->gc, _("Plaintext Authentication"), + purple_request_yes_no_with_hint(js->gc, _("Plaintext Authentication"), _("Plaintext Authentication"), _("This server requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), 2, purple_connection_get_account(js->gc), NULL, NULL, - purple_connection_get_account(js->gc), allow_plaintext_auth, - disallow_plaintext_auth); + PURPLE_REQUEST_UI_HINT_ACCOUNT, purple_connection_get_account(js->gc), + allow_plaintext_auth, disallow_plaintext_auth); return; } finish_plaintext_authentication(js); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/buddy.c Thu Oct 18 17:58:40 2007 +0000 @@ -719,7 +719,7 @@ if(x_vc_data != NULL) xmlnode_free(x_vc_data); - purple_request_fields(gc, _("Edit XMPP vCard"), + purple_request_fields_with_hint(gc, _("Edit XMPP vCard"), _("Edit XMPP vCard"), _("All items below are optional. Enter only the " "information with which you feel comfortable."), @@ -727,7 +727,7 @@ _("Save"), G_CALLBACK(jabber_format_info), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); } /*---------------------------------------*/ @@ -2410,12 +2410,12 @@ usi->js = js; usi->directory_server = g_strdup(from); - purple_request_fields(js->gc, _("Search for XMPP users"), + purple_request_fields_with_hint(js->gc, _("Search for XMPP users"), _("Search for XMPP users"), instructions, fields, _("Search"), G_CALLBACK(user_search_cb), _("Cancel"), G_CALLBACK(user_search_cancel_cb), purple_connection_get_account(js->gc), NULL, NULL, - usi); + PURPLE_REQUEST_UI_HINT_ACCOUNT, usi); g_free(instructions); } @@ -2444,14 +2444,14 @@ PurpleConnection *gc = (PurpleConnection *) action->context; JabberStream *js = gc->proto_data; - purple_request_input(gc, _("Enter a User Directory"), _("Enter a User Directory"), + purple_request_input_with_hint(gc, _("Enter a User Directory"), _("Enter a User Directory"), _("Select a user directory to search"), js->user_directories ? js->user_directories->data : NULL, FALSE, FALSE, NULL, _("Search Directory"), PURPLE_CALLBACK(jabber_user_search), _("Cancel"), NULL, NULL, NULL, NULL, - js); + PURPLE_REQUEST_UI_HINT_ACCOUNT, js); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/chat.c Thu Oct 18 17:58:40 2007 +0000 @@ -778,14 +778,14 @@ purple_roomlist_set_fields(js->roomlist, fields); - purple_request_input(gc, _("Enter a Conference Server"), _("Enter a Conference Server"), + purple_request_input_with_hint(gc, _("Enter a Conference Server"), _("Enter a Conference Server"), _("Select a conference server to query"), js->chat_servers ? js->chat_servers->data : NULL, FALSE, FALSE, NULL, _("Find Rooms"), PURPLE_CALLBACK(roomlist_ok_cb), _("Cancel"), PURPLE_CALLBACK(roomlist_cancel_cb), purple_connection_get_account(gc), NULL, NULL, - js); + PURPLE_REQUEST_UI_HINT_CONV, js); return js->roomlist; } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/google.c --- a/libpurple/protocols/jabber/google.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/google.c Thu Oct 18 17:58:40 2007 +0000 @@ -516,3 +516,22 @@ } return g_string_free(str, FALSE); } + +void jabber_google_presence_incoming(JabberStream *js, const char *user, JabberBuddyResource *jbr) +{ + if (!js->googletalk) + return; + if (jbr->status && !strncmp(jbr->status, "♫ ", strlen("♫ "))) { + purple_prpl_got_user_status(js->gc->account, user, "tune", + PURPLE_TUNE_TITLE, jbr->status + strlen("♫ "), NULL); + jbr->status = NULL; + } else { + purple_prpl_got_user_status_deactive(js->gc->account, user, "tune"); + } +} + +char *jabber_google_presence_outgoing(PurpleStatus *tune) +{ + char *ret = g_strdup_printf("♫ %s", purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE)); + return ret; +} diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/google.h --- a/libpurple/protocols/jabber/google.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/google.h Thu Oct 18 17:58:40 2007 +0000 @@ -36,6 +36,10 @@ * if this roster item should continue to be processed */ gboolean jabber_google_roster_incoming(JabberStream *js, xmlnode *item); + +void jabber_google_presence_incoming(JabberStream *js, const char *who, JabberBuddyResource *jbr); +char *jabber_google_presence_outgoing(PurpleStatus *tune); + void jabber_google_roster_add_deny(PurpleConnection *gc, const char *who); void jabber_google_roster_rem_deny(PurpleConnection *gc, const char *who); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Thu Oct 18 17:58:40 2007 +0000 @@ -1002,21 +1002,21 @@ cbdata->who = g_strdup(from); if(js->registration) - purple_request_fields(js->gc, _("Register New XMPP Account"), + purple_request_fields_with_hint(js->gc, _("Register New XMPP Account"), _("Register New XMPP Account"), instructions, fields, _("Register"), G_CALLBACK(jabber_register_cb), _("Cancel"), G_CALLBACK(jabber_register_cancel_cb), purple_connection_get_account(js->gc), NULL, NULL, - cbdata); + PURPLE_REQUEST_UI_HINT_REGISTER, cbdata); else { char *title = registered?g_strdup_printf(_("Change Account Registration at %s"), from) :g_strdup_printf(_("Register New Account at %s"), from); - purple_request_fields(js->gc, title, + purple_request_fields_with_hint(js->gc, title, title, instructions, fields, registered?_("Change Registration"):_("Register"), G_CALLBACK(jabber_register_cb), _("Cancel"), G_CALLBACK(jabber_register_cancel_cb), purple_connection_get_account(js->gc), NULL, NULL, - cbdata); + PURPLE_REQUEST_UI_HINT_REGISTER, cbdata); g_free(title); } @@ -1400,10 +1400,11 @@ char *stripped; if(!(stripped = purple_markup_strip_html(jabber_buddy_get_status_msg(jb)))) { - PurpleStatus *status = purple_presence_get_active_status(purple_buddy_get_presence(b)); - - if(!purple_status_is_available(status)) - stripped = g_strdup(purple_status_get_name(status)); + PurplePresence *presence = purple_buddy_get_presence(b); + if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) { + PurpleStatus *status = purple_presence_get_status(presence, "tune"); + stripped = g_strdup(purple_status_get_attr_string(status, PURPLE_TUNE_TITLE)); + } } if(stripped) { @@ -1429,6 +1430,7 @@ if(jb) { JabberBuddyResource *jbr = NULL; + PurplePresence *presence = purple_buddy_get_presence(b); const char *sub; GList *l; const char *mood; @@ -1455,7 +1457,7 @@ purple_notify_user_info_add_pair(user_info, _("Subscription"), sub); - status = purple_presence_get_active_status(purple_buddy_get_presence(b)); + status = purple_presence_get_active_status(presence); value = purple_status_get_attr_value(status, "mood"); if (value && purple_value_get_type(value) == PURPLE_TYPE_STRING && (mood = purple_value_get_string(value))) { @@ -1467,7 +1469,12 @@ g_free(moodplustext); } else purple_notify_user_info_add_pair(user_info, _("Mood"), mood); - } + } + if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) { + PurpleStatus *tune = purple_presence_get_status(presence, "tune"); + const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE); + purple_notify_user_info_add_pair(user_info, _("Current media"), title); + } } for(l=jb->resources; l; l = l->next) { @@ -1532,15 +1539,6 @@ "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); @@ -1555,15 +1553,6 @@ "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); @@ -1578,15 +1567,6 @@ "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); @@ -1601,15 +1581,6 @@ "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); @@ -1624,15 +1595,6 @@ "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); @@ -1650,6 +1612,20 @@ NULL); types = g_list_append(types, type); + type = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE, + "tune", NULL, TRUE, TRUE, TRUE, + PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), + PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), + NULL); + types = g_list_append(types, type); + return types; } @@ -1731,12 +1707,12 @@ purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(js->gc, _("Change XMPP Password"), + purple_request_fields_with_hint(js->gc, _("Change XMPP Password"), _("Change XMPP Password"), _("Please enter your new password"), fields, _("OK"), G_CALLBACK(jabber_password_change_cb), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - js); + PURPLE_REQUEST_UI_HINT_ACCOUNT, js); } GList *jabber_actions(PurplePlugin *plugin, gpointer context) diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/message.c Thu Oct 18 17:58:40 2007 +0000 @@ -104,6 +104,7 @@ g_snprintf(buf, sizeof(buf), _("%s has left the conversation."), escaped); + g_free(escaped); /* At some point when we restructure PurpleConversation, * this should be able to be implemented by removing the diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/presence.c Thu Oct 18 17:58:40 2007 +0000 @@ -33,6 +33,7 @@ #include "buddy.h" #include "chat.h" +#include "google.h" #include "presence.h" #include "iq.h" #include "jutil.h" @@ -104,13 +105,14 @@ char *stripped = NULL; JabberBuddyState state; int priority; - const char *artist, *title, *source, *uri, *track; - int length; + const char *artist = NULL, *title = NULL, *source = NULL, *uri = NULL, *track = NULL; + int length = -1; gboolean allowBuzz; + PurplePresence *p = purple_account_get_presence(account); + PurpleStatus *tune; - if(NULL == status) { - PurplePresence *gpresence = purple_account_get_presence(account); - status = purple_presence_get_active_status(gpresence); + if (NULL == status) { + status = purple_presence_get_active_status(p); } if(!purple_status_is_active(status)) @@ -144,6 +146,12 @@ if (allowBuzz != js->allowBuzz || js->old_state != state || CHANGED(js->old_msg, stripped) || js->old_priority != priority || CHANGED(js->old_avatarhash, js->avatar_hash)) { js->allowBuzz = allowBuzz; + + if (js->googletalk && stripped == NULL && purple_presence_is_status_primitive_active(p, PURPLE_STATUS_TUNE)) { + tune = purple_presence_get_status(p, "tune"); + stripped = jabber_google_presence_outgoing(tune); + } + presence = jabber_presence_create_js(js, state, stripped, priority); if(js->avatar_hash) { @@ -172,12 +180,16 @@ } /* next, check if there are any changes to the tune values */ - artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST); - title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE); - source = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM); - uri = purple_status_get_attr_string(status, PURPLE_TUNE_URL); - track = purple_status_get_attr_string(status, PURPLE_TUNE_TRACK); - length = (!purple_status_get_attr_value(status, PURPLE_TUNE_TIME))?-1:purple_status_get_attr_int(status, PURPLE_TUNE_TIME); + tune = purple_presence_get_status(p, "tune"); + if (tune && purple_status_is_active(tune)) { + artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST); + title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE); + source = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM); + uri = purple_status_get_attr_string(tune, PURPLE_TUNE_URL); + track = purple_status_get_attr_string(tune, PURPLE_TUNE_TRACK); + length = (!purple_status_get_attr_value(tune, PURPLE_TUNE_TIME)) ? -1 : + purple_status_get_attr_int(tune, PURPLE_TUNE_TIME); + } if(CHANGED(artist, js->old_artist) || CHANGED(title, js->old_title) || CHANGED(source, js->old_source) || CHANGED(uri, js->old_uri) || CHANGED(track, js->old_track) || (length != js->old_length)) { @@ -500,7 +512,7 @@ if((chat = jabber_chat_find(js, jid->node, jid->domain))) { chat->config_dialog_type = PURPLE_REQUEST_ACTION; chat->config_dialog_handle = - purple_request_action(js->gc, + purple_request_action_with_hint(js->gc, _("Create New Room"), _("Create New Room"), _("You are creating a new room. Would" @@ -508,7 +520,7 @@ " accept the default settings?"), /* Default Action */ 1, purple_connection_get_account(js->gc), NULL, chat->conv, - chat, 2, + PURPLE_REQUEST_UI_HINT_CONV, chat, 2, _("_Configure Room"), G_CALLBACK(jabber_chat_request_room_configure), _("_Accept Defaults"), G_CALLBACK(jabber_chat_create_instant_room)); } @@ -731,7 +743,8 @@ } if((found_jbr = jabber_buddy_find_resource(jb, 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); + jabber_google_presence_incoming(js, buddy_name, found_jbr); + purple_prpl_got_user_status(js->gc->account, buddy_name, jabber_buddy_state_get_status_id(found_jbr->state), "priority", found_jbr->priority, "message", found_jbr->status, NULL); } else { purple_prpl_got_user_status(js->gc->account, buddy_name, "offline", status ? "message" : NULL, status, NULL); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/si.c Thu Oct 18 17:58:40 2007 +0000 @@ -870,9 +870,9 @@ purple_request_fields_add_group(fields, group); - purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, fields, + purple_request_fields_with_hint(jsx->js->gc, _("Select a Resource"), msg, NULL, fields, _("Send File"), G_CALLBACK(resource_select_ok_cb), _("Cancel"), G_CALLBACK(resource_select_cancel_cb), - jsx->js->gc->account, xfer->who, NULL, xfer); + jsx->js->gc->account, xfer->who, NULL, PURPLE_REQUEST_UI_HINT_XFER, xfer); g_free(msg); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/usermood.c --- a/libpurple/protocols/jabber/usermood.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/usermood.c Thu Oct 18 17:58:40 2007 +0000 @@ -194,14 +194,14 @@ FALSE); purple_request_field_group_add_field(group, field); - purple_request_fields(gc, _("Edit User Mood"), + purple_request_fields_with_hint(gc, _("Edit User Mood"), _("Edit User Mood"), _("Please select your mood from the list."), fields, _("Set"), G_CALLBACK(do_mood_set_from_fields), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_BLIST, gc); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/usernick.c --- a/libpurple/protocols/jabber/usernick.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/usernick.c Thu Oct 18 17:58:40 2007 +0000 @@ -73,10 +73,10 @@ oldnickname = xmlnode_get_data(nick); } - purple_request_input(js->gc, _("Set User Nickname"), _("Please specify a new nickname for you."), + purple_request_input_with_hint(js->gc, _("Set User Nickname"), _("Please specify a new nickname for you."), _("This information is visible to all contacts on your contact list, so choose something appropriate."), oldnickname, FALSE, FALSE, NULL, _("Set"), PURPLE_CALLBACK(do_nick_set), _("Cancel"), NULL, - purple_connection_get_account(js->gc), NULL, NULL, js); + purple_connection_get_account(js->gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, js); g_free(oldnickname); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/usertune.c --- a/libpurple/protocols/jabber/usertune.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/usertune.c Thu Oct 18 17:58:40 2007 +0000 @@ -35,7 +35,6 @@ xmlnode *tuneinfo, *tune; PurpleJabberTuneInfo tuneinfodata; JabberBuddyResource *resource; - const char *status_id; /* ignore the tune of people not on our buddy list */ if (!buddy || !item) @@ -81,9 +80,8 @@ } } } - status_id = jabber_buddy_state_get_status_id(resource->state); - purple_prpl_got_user_status(js->gc->account, from, status_id, + purple_prpl_got_user_status(js->gc->account, from, "tune", PURPLE_TUNE_ARTIST, tuneinfodata.artist, PURPLE_TUNE_TITLE, tuneinfodata.title, PURPLE_TUNE_ALBUM, tuneinfodata.album, diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/jabber/xdata.c --- a/libpurple/protocols/jabber/xdata.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/jabber/xdata.c Thu Oct 18 17:58:40 2007 +0000 @@ -395,11 +395,11 @@ if((x = xmlnode_get_child(packet, "instructions"))) instructions = xmlnode_get_data(x); - handle = purple_request_fields(js->gc, title, title, instructions, fields, + handle = purple_request_fields_with_hint(js->gc, title, title, instructions, fields, _("OK"), G_CALLBACK(jabber_x_data_ok_cb), _("Cancel"), G_CALLBACK(jabber_x_data_cancel_cb), purple_connection_get_account(js->gc), /* XXX Do we have a who here? */ NULL, NULL, - data); + PURPLE_REQUEST_UI_HINT_ACCOUNT, data); g_free(title); g_free(instructions); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/msn/dialog.c --- a/libpurple/protocols/msn/dialog.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/msn/dialog.c Thu Oct 18 17:58:40 2007 +0000 @@ -135,9 +135,9 @@ passport); } - purple_request_action(gc, NULL, msg, reason, PURPLE_DEFAULT_ACTION_NONE, + purple_request_action_with_hint(gc, NULL, msg, reason, PURPLE_DEFAULT_ACTION_NONE, purple_connection_get_account(gc), data->who, NULL, - data, 2, + PURPLE_REQUEST_UI_HINT_BLIST, data, 2, _("Yes"), G_CALLBACK(msn_add_cb), _("No"), G_CALLBACK(msn_rem_cb)); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/msn/msn.c Thu Oct 18 17:58:40 2007 +0000 @@ -282,14 +282,14 @@ gc = (PurpleConnection *) action->context; - purple_request_input(gc, NULL, _("Set your friendly name."), + purple_request_input_with_hint(gc, NULL, _("Set your friendly name."), _("This is the name that other MSN buddies will " "see you as."), purple_connection_get_display_name(gc), FALSE, FALSE, NULL, _("OK"), G_CALLBACK(msn_act_id), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); } static void @@ -301,12 +301,12 @@ gc = (PurpleConnection *) action->context; session = gc->proto_data; - purple_request_input(gc, NULL, _("Set your home phone number."), NULL, + purple_request_input_with_hint(gc, NULL, _("Set your home phone number."), NULL, msn_user_get_home_phone(session->user), FALSE, FALSE, NULL, _("OK"), G_CALLBACK(msn_set_home_phone_cb), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); } static void @@ -318,12 +318,12 @@ gc = (PurpleConnection *) action->context; session = gc->proto_data; - purple_request_input(gc, NULL, _("Set your work phone number."), NULL, + purple_request_input_with_hint(gc, NULL, _("Set your work phone number."), NULL, msn_user_get_work_phone(session->user), FALSE, FALSE, NULL, _("OK"), G_CALLBACK(msn_set_work_phone_cb), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); } static void @@ -335,12 +335,12 @@ gc = (PurpleConnection *) action->context; session = gc->proto_data; - purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL, + purple_request_input_with_hint(gc, NULL, _("Set your mobile phone number."), NULL, msn_user_get_mobile_phone(session->user), FALSE, FALSE, NULL, _("OK"), G_CALLBACK(msn_set_mobile_phone_cb), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); } static void @@ -350,13 +350,13 @@ gc = (PurpleConnection *) action->context; - purple_request_action(gc, NULL, _("Allow MSN Mobile pages?"), + purple_request_action_with_hint(gc, NULL, _("Allow MSN Mobile pages?"), _("Do you want to allow or disallow people on " "your buddy list to send you MSN Mobile pages " "to your cell phone or other mobile device?"), -1, purple_connection_get_account(gc), NULL, NULL, - gc, 3, + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc, 3, _("Allow"), G_CALLBACK(enable_msn_pages_cb), _("Disallow"), G_CALLBACK(disable_msn_pages_cb), _("Cancel"), NULL); @@ -400,12 +400,12 @@ data->gc = gc; data->passport = buddy->name; - purple_request_input(gc, NULL, _("Send a mobile message."), NULL, + purple_request_input_with_hint(gc, NULL, _("Send a mobile message."), NULL, NULL, TRUE, FALSE, NULL, _("Page"), G_CALLBACK(send_to_mobile_cb), _("Close"), G_CALLBACK(close_mobile_page_cb), purple_connection_get_account(gc), purple_buddy_get_name(buddy), NULL, - data); + PURPLE_REQUEST_UI_HINT_ACCOUNT, data); } static gboolean @@ -539,25 +539,36 @@ /* * Set the User status text - * Add the PSM String Using "Name - PSM String" format */ static char * msn_status_text(PurpleBuddy *buddy) { PurplePresence *presence; PurpleStatus *status; - const char *msg, *cmedia; + const char *msg; presence = purple_buddy_get_presence(buddy); status = purple_presence_get_active_status(presence); + /* I think status message should take precedence over media */ msg = purple_status_get_attr_string(status, "message"); - cmedia = purple_status_get_attr_string(status, "currentmedia"); - - if (cmedia) - return g_markup_escape_text(cmedia, -1); - else if (msg) + if (msg && *msg) return g_markup_escape_text(msg, -1); + + if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) { + const char *title, *artist; + char *media, *esc; + status = purple_presence_get_status(presence, "tune"); + title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE); + artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST); + + media = g_strdup_printf("%s%s%s", title, artist ? " - " : "", + artist ? artist : ""); + esc = g_markup_escape_text(media, -1); + g_free(media); + return esc; + } + return NULL; } @@ -570,14 +581,21 @@ user = buddy->proto_data; - if (purple_presence_is_online(presence)) { - const char *psm, *currentmedia, *name; + const char *psm, *name; + char *currentmedia = NULL; char *tmp; psm = purple_status_get_attr_string(status, "message"); - currentmedia = purple_status_get_attr_string(status, "currentmedia"); + if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) { + PurpleStatus *tune = purple_presence_get_status(presence, "tune"); + const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE); + const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST); + currentmedia = g_strdup_printf("%s%s%s", title, artist ? " - " : "", + artist ? artist : ""); + /* We could probably just use user->media.title etc. here */ + } if (!purple_presence_is_available(presence)) { name = purple_status_get_name(status); @@ -609,6 +627,7 @@ tmp = g_markup_escape_text(currentmedia, -1); purple_notify_user_info_add_pair(user_info, _("Current media"), tmp); g_free(tmp); + g_free(currentmedia); } } @@ -632,40 +651,34 @@ status = purple_status_type_new_with_attrs( PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), NULL); types = g_list_append(types, status); status = purple_status_type_new_with_attrs( PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), NULL); types = g_list_append(types, status); status = purple_status_type_new_with_attrs( PURPLE_STATUS_AWAY, "brb", _("Be Right Back"), TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), NULL); types = g_list_append(types, status); status = purple_status_type_new_with_attrs( PURPLE_STATUS_UNAVAILABLE, "busy", _("Busy"), TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), NULL); types = g_list_append(types, status); status = purple_status_type_new_with_attrs( PURPLE_STATUS_UNAVAILABLE, "phone", _("On the Phone"), TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), NULL); types = g_list_append(types, status); status = purple_status_type_new_with_attrs( PURPLE_STATUS_AWAY, "lunch", _("Out to Lunch"), TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), NULL); types = g_list_append(types, status); @@ -681,6 +694,14 @@ "mobile", NULL, FALSE, FALSE, TRUE); types = g_list_append(types, status); + status = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE, + "tune", NULL, TRUE, TRUE, TRUE, + PURPLE_TUNE_ARTIST, _("Artist"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ALBUM, _("Album"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_TITLE, _("Title"), purple_value_new(PURPLE_TYPE_STRING), + NULL); + types = g_list_append(types, status); + return types; } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/msn/notification.c --- a/libpurple/protocols/msn/notification.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/msn/notification.c Thu Oct 18 17:58:40 2007 +0000 @@ -1616,10 +1616,8 @@ PurpleAccount *account; MsnUser *user; const char *passport; - char *psm_str, *currentmedia_str, *str; - - /*get the payload content*/ -// purple_debug_info("MSNP14","UBX {%s} payload{%s}\n",cmd->params[0], cmd->payload); + char *psm_str, *str; + CurrentMedia media = {NULL, NULL, NULL}; session = cmdproc->session; account = session->account; @@ -1628,16 +1626,17 @@ user = msn_userlist_find_user(session->userlist, passport); psm_str = msn_get_psm(cmd->payload,len); - currentmedia_str = msn_parse_currentmedia( - str = msn_get_currentmedia(cmd->payload, len)); + msn_user_set_statusline(user, psm_str); + g_free(psm_str); + + str = msn_get_currentmedia(cmd->payload, len); + if (msn_parse_currentmedia(str, &media)) + msn_user_set_currentmedia(user, &media); + else + msn_user_set_currentmedia(user, NULL); g_free(str); - msn_user_set_statusline(user, psm_str); - msn_user_set_currentmedia(user, currentmedia_str); msn_user_update(user); - - g_free(psm_str); - g_free(currentmedia_str); } static void diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/msn/state.c --- a/libpurple/protocols/msn/state.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/msn/state.c Thu Oct 18 17:58:40 2007 +0000 @@ -83,60 +83,56 @@ } /* parse CurrentMedia string */ -char * -msn_parse_currentmedia(const char *cmedia) +gboolean +msn_parse_currentmedia(const char *cmedia, CurrentMedia *media) { char **cmedia_array; - GString *buffer = NULL; int strings; if ((cmedia == NULL) || (*cmedia == '\0')) { purple_debug_info("msn", "No currentmedia string\n"); - return NULL; + return FALSE; } purple_debug_info("msn", "Parsing currentmedia string: \"%s\"\n", cmedia); cmedia_array = g_strsplit(cmedia, "\\0", 0); + /* + * 0: Media Player + * 1: 'Music' + * 2: '1' if enabled, '0' if not + * 3: Format (eg. {0} by {1}) + * 4: Title + * 5: Artist + * 6: Album + * 7: ? + */ strings = 0; - /* Yes, we want to skip the first element here, as it is empty due to - * the cmedia string starting with \0 -- see the examples below. */ while (cmedia_array[++strings] != NULL); - /* The cmedia_array[2] field contains a 1 if enabled. */ - if ((strings > 3) && (!strcmp(cmedia_array[2], "1"))) { - char *inptr = cmedia_array[3]; - - buffer = g_string_new(NULL); - - while (*inptr != '\0') { - if ((*inptr == '{') && ((*(inptr + 1) != '\0') && (*(inptr+2) == '}'))) { - char *tmpptr; - int tmp; - - errno = 0; - tmp = strtol(inptr + 1, &tmpptr, 10); + if (strings < 4) + return FALSE; + if (strcmp(cmedia_array[2], "1")) + return FALSE; - if (errno == 0 && tmpptr != inptr + 1 && - tmp + 4 < strings) { - /* Replace {?} tag with appropriate text only when successful. - * Skip otherwise. */ - buffer = g_string_append(buffer, cmedia_array[tmp + 4]); - } - inptr += 3; /* Skip to the next char after '}' */ - } else { - buffer = g_string_append_c(buffer, *inptr++); - } - } - purple_debug_info("msn", "Parsed currentmedia string, result: \"%s\"\n", - buffer->str); + if (strings == 4) { + media->title = g_strdup(cmedia_array[3]); } else { - purple_debug_info("msn", "Current media marked disabled, not parsing.\n"); + media->title = g_strdup(cmedia_array[4]); } - g_strfreev(cmedia_array); - return buffer ? g_string_free(buffer, FALSE) : NULL; + if (strings > 5) + media->artist = g_strdup(cmedia_array[5]); + else + media->artist = NULL; + + if (strings > 6) + media->album = g_strdup(cmedia_array[6]); + else + media->album = NULL; + + return TRUE; } /* get the CurrentMedia info from the XML string */ @@ -191,6 +187,27 @@ return psm; } +static char * +create_media_string(PurplePresence *presence) +{ + const char *artist, *title, *album; + char *ret; + PurpleStatus *status = purple_presence_get_status(presence, "tune"); + if (!status || !purple_status_is_active(status)) + return g_strdup_printf("WMP\\0Music\\00\\0{0} - {1}\\0\\0\\0\\0\\0"); + + artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST); + title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE); + album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM); + + ret = g_strdup_printf("WMP\\0Music\\0%c\\0{0} - {1}\\0%s\\0%s\\0%s\\0\\0", + (title && *title) ? '1' : '0', + title ? title : "", + artist ? artist : "", + album ? album : ""); + return ret; +} + /* set the MSN's PSM info,Currently Read from the status Line * Thanks for Cris Code */ @@ -204,7 +221,7 @@ MsnTransaction *trans; char *payload; const char *statusline; - gchar *unescapedstatusline; + gchar *unescapedstatusline, *media = NULL; g_return_if_fail(session != NULL); g_return_if_fail(session->notification != NULL); @@ -219,8 +236,10 @@ status = purple_presence_get_active_status(presence); statusline = purple_status_get_attr_string(status, "message"); unescapedstatusline = purple_unescape_html(statusline); - session->psm = msn_build_psm(unescapedstatusline, NULL, NULL); + media = create_media_string(presence); + session->psm = msn_build_psm(unescapedstatusline, media, NULL); g_free(unescapedstatusline); + g_free(media); payload = session->psm; purple_debug_misc("MSNP14","Sending UUX command with payload: %s\n",payload); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/msn/state.h --- a/libpurple/protocols/msn/state.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/msn/state.h Thu Oct 18 17:58:40 2007 +0000 @@ -62,7 +62,7 @@ void msn_set_psm(MsnSession *session); /* Parse CurrentMedia string */ -char * msn_parse_currentmedia(const char *cmedia); +gboolean msn_parse_currentmedia(const char *cmedia, CurrentMedia *media); /* Get the CurrentMedia info from the XML string */ char * msn_get_currentmedia(char *xml_str,gsize len); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/msn/user.c --- a/libpurple/protocols/msn/user.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/msn/user.c Thu Oct 18 17:58:40 2007 +0000 @@ -80,6 +80,9 @@ g_free(user->phone.home); g_free(user->phone.work); g_free(user->phone.mobile); + g_free(user->media.artist); + g_free(user->media.title); + g_free(user->media.album); g_free(user); } @@ -91,23 +94,24 @@ account = user->userlist->session->account; - if (user->statusline != NULL && user->currentmedia != NULL) { + if (user->status != NULL) { + gboolean offline = (strcmp(user->status, "offline") == 0); purple_prpl_got_user_status(account, user->passport, user->status, - "message", user->statusline, - "currentmedia", user->currentmedia, NULL); - } else if (user->currentmedia != NULL) { - purple_prpl_got_user_status(account, user->passport, user->status, "currentmedia", - user->currentmedia, NULL); - } else if (user->statusline != NULL) { - //char *status = g_strdup_printf("%s - %s", user->status, user->statusline); - purple_prpl_got_user_status(account, user->passport, user->status, - "message", user->statusline, NULL); - } else if (user->status != NULL) { - if (!strcmp(user->status, "offline") && user->mobile) { - purple_prpl_got_user_status(account, user->passport, "offline", NULL); + "message", user->statusline, NULL); + + if (!offline && user->media.title) { + purple_prpl_got_user_status(account, user->passport, "tune", + PURPLE_TUNE_ARTIST, user->media.artist, + PURPLE_TUNE_ALBUM, user->media.album, + PURPLE_TUNE_TITLE, user->media.title, + NULL); + } else { + purple_prpl_got_user_status_deactive(account, user->passport, "tune"); + } + + if (!offline && user->mobile) { purple_prpl_got_user_status(account, user->passport, "mobile", NULL); } else { - purple_prpl_got_user_status(account, user->passport, user->status, NULL); purple_prpl_got_user_status_deactive(account, user->passport, "mobile"); } } @@ -172,12 +176,17 @@ } void -msn_user_set_currentmedia(MsnUser *user, const char *currentmedia) +msn_user_set_currentmedia(MsnUser *user, const CurrentMedia *media) { g_return_if_fail(user != NULL); - g_free(user->currentmedia); - user->currentmedia = g_strdup(currentmedia); + g_free(user->media.title); + g_free(user->media.album); + g_free(user->media.artist); + + user->media.title = media ? g_strdup(media->title) : NULL; + user->media.artist = media ? g_strdup(media->artist) : NULL; + user->media.album = media ? g_strdup(media->album) : NULL; } void diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/msn/user.h --- a/libpurple/protocols/msn/user.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/msn/user.h Thu Oct 18 17:58:40 2007 +0000 @@ -43,6 +43,16 @@ } MsnUserType; /** + * Current media. + */ +typedef struct _CurrentMedia +{ + char *artist; /**< Artist. */ + char *album; /**< Album. */ + char *title; /**< Title. */ +} CurrentMedia; + +/** * A user. */ struct _MsnUser @@ -60,7 +70,7 @@ const char *status; /**< The state of the user. */ char *statusline; /**< The state of the user. */ - char *currentmedia; /**< The current media of the user. */ + CurrentMedia media; /**< Current media of the user. */ gboolean idle; /**< The idle state of the user. */ @@ -134,10 +144,10 @@ /** * Sets the current media of user. * - * @param user The user. - * @param state The statusline string. + * @param user The user. + * @param cmedia Current media. */ -void msn_user_set_currentmedia(MsnUser *user, const char *currentmedia); +void msn_user_set_currentmedia(MsnUser *user, const CurrentMedia *cmedia); /** * Sets the new state of user. diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/novell/novell.c --- a/libpurple/protocols/novell/novell.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/novell/novell.c Thu Oct 18 17:58:40 2007 +0000 @@ -1912,10 +1912,10 @@ /* Prompt the user */ gc = purple_account_get_connection(user->client_data); - purple_request_action(gc, title, primary, secondary, + purple_request_action_with_hint(gc, title, primary, secondary, PURPLE_DEFAULT_ACTION_NONE, purple_connection_get_account(gc), name, NULL, - parms, 2, + PURPLE_REQUEST_UI_HINT_CONV, parms, 2, _("Yes"), G_CALLBACK(_join_conference_cb), _("No"), G_CALLBACK(_reject_conference_cb)); @@ -2165,7 +2165,7 @@ if (server == NULL || *server == '\0') { /* TODO: Would be nice to prompt if not set! - * purple_request_fields(gc, _("Server Address"),...); + * purple_request_fields_with_hint(gc, _("Server Address"),...); */ /* ...but for now just error out with a nice message. */ diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Thu Oct 18 17:58:40 2007 +0000 @@ -1448,13 +1448,13 @@ purple_debug_info("oscar", "Got SecurID request\n"); primary = g_strdup_printf("Enter the SecurID key for %s.", purple_account_get_username(account)); - purple_request_input(gc, NULL, _("Enter SecurID"), primary, + purple_request_input_with_hint(gc, NULL, _("Enter SecurID"), primary, _("Enter the 6 digit number from the digital display."), FALSE, FALSE, NULL, _("_OK"), G_CALLBACK(purple_parse_auth_securid_request_yes_cb), _("_Cancel"), G_CALLBACK(purple_parse_auth_securid_request_no_cb), account, NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); g_free(primary); return 1; @@ -2241,12 +2241,12 @@ data->gc = gc; data->name = g_strdup(name); - purple_request_input(data->gc, NULL, _("Authorization Request Message:"), + purple_request_input_with_hint(data->gc, NULL, _("Authorization Request Message:"), NULL, _("Please authorize me!"), TRUE, FALSE, NULL, _("_OK"), G_CALLBACK(purple_auth_request), _("_Cancel"), G_CALLBACK(purple_auth_dontrequest), purple_connection_get_account(gc), name, NULL, - data); + PURPLE_REQUEST_UI_HINT_BLIST, data); } @@ -2290,12 +2290,12 @@ purple_auth_dontgrant_msgprompt(gpointer cbdata) { struct name_data *data = cbdata; - purple_request_input(data->gc, NULL, _("Authorization Denied Message:"), + purple_request_input_with_hint(data->gc, NULL, _("Authorization Denied Message:"), NULL, _("No reason given."), TRUE, FALSE, NULL, _("_OK"), G_CALLBACK(purple_auth_dontgrant), _("_Cancel"), G_CALLBACK(oscar_free_name_data), purple_connection_get_account(data->gc), data->name, NULL, - data); + PURPLE_REQUEST_UI_HINT_BLIST, data); } /* When someone sends you buddies */ @@ -2476,12 +2476,12 @@ data->name = g_strdup(text[i*2+1]); data->nick = g_strdup(text[i*2+2]); - purple_request_action(gc, NULL, message, + purple_request_action_with_hint(gc, NULL, message, _("Do you want to add this buddy " "to your buddy list?"), PURPLE_DEFAULT_ACTION_NONE, purple_connection_get_account(gc), data->name, NULL, - data, 2, + PURPLE_REQUEST_UI_HINT_BLIST, data, 2, _("_Add"), G_CALLBACK(purple_icq_buddyadd), _("_Decline"), G_CALLBACK(oscar_free_name_data)); g_free(message); @@ -5233,10 +5233,10 @@ data->name = g_strdup(sn); data->nick = (buddy ? g_strdup(purple_buddy_get_alias_only(buddy)) : NULL); - purple_request_yes_no(gc, NULL, _("Authorization Given"), dialog_msg, + purple_request_yes_no_with_hint(gc, NULL, _("Authorization Given"), dialog_msg, PURPLE_DEFAULT_ACTION_NONE, purple_connection_get_account(gc), sn, NULL, - data, + PURPLE_REQUEST_UI_HINT_BLIST, data, G_CALLBACK(purple_icq_buddyadd), G_CALLBACK(oscar_free_name_data)); g_free(dialog_msg); @@ -5932,12 +5932,12 @@ data->nick = g_strdup(purple_buddy_get_alias_only(buddy)); title = g_strdup_printf(_("Buddy Comment for %s"), data->name); - purple_request_input(gc, title, _("Buddy Comment:"), NULL, + purple_request_input_with_hint(gc, title, _("Buddy Comment:"), NULL, comment_utf8, TRUE, FALSE, NULL, _("_OK"), G_CALLBACK(oscar_ssi_editcomment), _("_Cancel"), G_CALLBACK(oscar_free_name_data), purple_connection_get_account(gc), data->name, NULL, - data); + PURPLE_REQUEST_UI_HINT_BUDDY, data); g_free(title); g_free(comment); @@ -5982,13 +5982,13 @@ buf = g_strdup_printf(_("You have selected to open a Direct IM connection with %s."), buddy->name); - purple_request_action(gc, NULL, buf, + purple_request_action_with_hint(gc, NULL, buf, _("Because this reveals your IP address, it " "may be considered a security risk. Do you " "wish to continue?"), 0, purple_connection_get_account(gc), data->who, NULL, - data, 2, + PURPLE_REQUEST_UI_HINT_BUDDY, data, 2, _("C_onnect"), G_CALLBACK(oscar_ask_directim_yes_cb), _("_Cancel"), G_CALLBACK(oscar_ask_directim_no_cb)); g_free(buf); @@ -6140,12 +6140,12 @@ purple_request_fields_add_group(fields, g); - purple_request_fields(gc, _("ICQ Privacy Options"), _("ICQ Privacy Options"), + purple_request_fields_with_hint(gc, _("ICQ Privacy Options"), _("ICQ Privacy Options"), NULL, fields, _("OK"), G_CALLBACK(oscar_icq_privacy_opts), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); } static void oscar_format_screenname(PurpleConnection *gc, const char *nick) { @@ -6213,12 +6213,12 @@ static void oscar_show_change_email(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *) action->context; - purple_request_input(gc, NULL, _("Change Address To:"), NULL, NULL, + purple_request_input_with_hint(gc, NULL, _("Change Address To:"), NULL, NULL, FALSE, FALSE, NULL, _("_OK"), G_CALLBACK(oscar_change_email), _("_Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); } static void oscar_show_awaitingauth(PurplePluginAction *action) @@ -6280,7 +6280,7 @@ static void oscar_show_find_email(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *) action->context; - purple_request_input(gc, _("Find Buddy by E-Mail"), + purple_request_input_with_hint(gc, _("Find Buddy by E-Mail"), _("Search for a buddy by e-mail address"), _("Type the e-mail address of the buddy you are " "searching for."), @@ -6288,7 +6288,7 @@ _("_Search"), G_CALLBACK(search_by_email_cb), _("_Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); } static void oscar_show_set_info(PurplePluginAction *action) diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/oscar/peer.c --- a/libpurple/protocols/oscar/peer.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/oscar/peer.c Thu Oct 18 17:58:40 2007 +0000 @@ -1033,7 +1033,7 @@ buf = g_strdup_printf(_("%s has just asked to directly connect to %s"), sn, purple_account_get_username(account)); - purple_request_action(conn, NULL, buf, + purple_request_action_with_hint(conn, NULL, buf, _("This requires a direct connection between " "the two computers and is necessary for IM " "Images. Because your IP address will be " @@ -1041,7 +1041,7 @@ "risk."), PURPLE_DEFAULT_ACTION_NONE, account, sn, NULL, - conn, 2, + PURPLE_REQUEST_UI_HINT_BUDDY, conn, 2, _("C_onnect"), G_CALLBACK(peer_connection_got_proposition_yes_cb), _("Cancel"), G_CALLBACK(peer_connection_got_proposition_no_cb)); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/qq/buddy_info.c --- a/libpurple/protocols/qq/buddy_info.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/qq/buddy_info.c Thu Oct 18 17:58:40 2007 +0000 @@ -519,12 +519,12 @@ mid->info->qq_show = g_strdup(info->qq_show); mid->info->unknown6 = g_strdup(info->unknown6); - purple_request_fields(gc, _("Modify my information"), + purple_request_fields_with_hint(gc, _("Modify my information"), _("Modify my information"), NULL, fields, _("Update my information"), G_CALLBACK(modify_info_ok_cb), _("Cancel"), G_CALLBACK(modify_info_cancel_cb), purple_connection_get_account(gc), NULL, NULL, - mid); + "account", mid); } } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/qq/buddy_opt.c --- a/libpurple/protocols/qq/buddy_opt.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/qq/buddy_opt.c Thu Oct 18 17:58:40 2007 +0000 @@ -209,11 +209,11 @@ msg2 = g_strdup(_("Input your reason:")); nombre = uid_to_purple_name(uid); - purple_request_input(gc, _("Reject request"), msg1, msg2, + purple_request_input_with_hint(gc, _("Reject request"), msg1, msg2, _("Sorry, you are not my type..."), TRUE, FALSE, NULL, _("Reject"), G_CALLBACK(_qq_reject_add_request_real), _("Cancel"), NULL, purple_connection_get_account(gc), nombre, NULL, - g2); + PURPLE_REQUEST_UI_HINT_BUDDY, g2); g_free(nombre); } @@ -402,7 +402,7 @@ g->gc = gc; g->uid = for_uid; msg = g_strdup_printf(_("User %d needs authentication"), for_uid); - purple_request_input(gc, NULL, msg, + purple_request_input_with_hint(gc, NULL, msg, _("Input request here"), /* TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands */ _("Would you be my friend?"), TRUE, FALSE, NULL, _("Send"), @@ -410,7 +410,7 @@ (_qq_send_packet_add_buddy_auth_with_gc_and_uid), _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid), purple_connection_get_account(gc), nombre, NULL, - g); + PURPLE_REQUEST_UI_HINT_BUDDY, g); g_free(msg); g_free(nombre); } else { /* add OK */ diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/qq/group.c --- a/libpurple/protocols/qq/group.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/qq/group.c Thu Oct 18 17:58:40 2007 +0000 @@ -116,14 +116,14 @@ purple_roomlist_set_fields(rl, fields); purple_roomlist_set_in_progress(qd->roomlist, TRUE); - purple_request_input(gc, _("QQ Qun"), + purple_request_input_with_hint(gc, _("QQ Qun"), _("Please enter external group ID"), _("You can only search for permanent QQ groups\n"), NULL, FALSE, FALSE, NULL, _("Search"), G_CALLBACK(_qq_group_search_callback), _("Cancel"), G_CALLBACK(_qq_group_search_cancel_callback), purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_CONV, gc); return qd->roomlist; } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/qq/group_im.c --- a/libpurple/protocols/qq/group_im.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/qq/group_im.c Thu Oct 18 17:58:40 2007 +0000 @@ -133,11 +133,11 @@ nombre = uid_to_purple_name(user_uid); - purple_request_action(gc, _("QQ Qun Operation"), + purple_request_action_with_hint(gc, _("QQ Qun Operation"), msg, reason, 2, purple_connection_get_account(gc), nombre, NULL, - g, 3, + PURPLE_REQUEST_UI_HINT_CONV, g, 3, _("Approve"), G_CALLBACK (qq_group_approve_application_with_struct), diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/qq/group_join.c --- a/libpurple/protocols/qq/group_join.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/qq/group_join.c Thu Oct 18 17:58:40 2007 +0000 @@ -132,14 +132,14 @@ g = g_new0(gc_and_uid, 1); g->gc = gc; g->uid = group->internal_group_id; - purple_request_input(gc, NULL, msg, + purple_request_input_with_hint(gc, NULL, msg, _("Input request here"), _("Would you be my friend?"), TRUE, FALSE, NULL, _("Send"), G_CALLBACK(_qq_group_join_auth_with_gc_and_id), _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid), purple_connection_get_account(gc), group->group_name_utf8, NULL, - g); + PURPLE_REQUEST_UI_HINT_CONV, g); g_free(msg); } @@ -356,13 +356,13 @@ g->gc = gc; g->uid = internal_group_id; - purple_request_action(gc, _("QQ Qun Operation"), + purple_request_action_with_hint(gc, _("QQ Qun Operation"), _("Are you sure you want to leave this Qun?"), _ ("Note, if you are the creator, \nthis operation will eventually remove this Qun."), 1, purple_connection_get_account(gc), NULL, NULL, - g, 2, _("Cancel"), + PURPLE_REQUEST_UI_HINT_CONV, g, 2, _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid), _("Continue"), G_CALLBACK(_qq_group_exit_with_gc_and_id)); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/qq/group_opt.c --- a/libpurple/protocols/qq/group_opt.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/qq/group_opt.c Thu Oct 18 17:58:40 2007 +0000 @@ -121,9 +121,9 @@ g_return_if_fail(g != NULL && g->gc != NULL && g->member > 0); qq_send_packet_get_info(g->gc, g->member, TRUE); /* we want to see window */ - purple_request_action(g->gc, NULL, _("Do you want to approve the request?"), "", 2, + purple_request_action_with_hint(g->gc, NULL, _("Do you want to approve the request?"), "", 2, purple_connection_get_account(g->gc), NULL, NULL, - g, 2, + PURPLE_REQUEST_UI_HINT_CONV, g, 2, _("Reject"), G_CALLBACK(qq_group_reject_application_with_struct), _("Approve"), G_CALLBACK(qq_group_approve_application_with_struct)); } @@ -137,13 +137,13 @@ msg2 = g_strdup(_("Enter your reason:")); nombre = uid_to_purple_name(g->member); - purple_request_input(g->gc, /* title */ NULL, msg1, msg2, + purple_request_input_with_hint(g->gc, /* title */ NULL, msg1, msg2, _("Sorry, you are not my type..."), /* multiline */ TRUE, /* masked */ FALSE, /* hint */ NULL, _("Send"), G_CALLBACK(_qq_group_reject_application_real), _("Cancel"), G_CALLBACK(_qq_group_do_nothing_with_struct), purple_connection_get_account(g->gc), nombre, NULL, - g); + PURPLE_REQUEST_UI_HINT_CONV, g); g_free(msg1); g_free(msg2); @@ -388,13 +388,13 @@ g->gc = gc; g->uid = internal_group_id; - purple_request_action(gc, _("QQ Qun Operation"), + purple_request_action_with_hint(gc, _("QQ Qun Operation"), _("You have successfully created a Qun"), _ ("Would you like to set up the Qun details now?"), 1, purple_connection_get_account(gc), NULL, NULL, - g, 2, + PURPLE_REQUEST_UI_HINT_CONV, g, 2, _("Setup"), G_CALLBACK(qq_group_setup_with_gc_and_uid), _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid)); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/qq/qq.c --- a/libpurple/protocols/qq/qq.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/qq/qq.c Thu Oct 18 17:58:40 2007 +0000 @@ -417,9 +417,9 @@ g->gc = gc; g->uid = uid; - purple_request_action(gc, _("Block Buddy"), + purple_request_action_with_hint(gc, _("Block Buddy"), _("Are you sure you want to block this buddy?"), NULL, - 1, g, 2, + 1, g, "blist", 2, _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid), _("Block"), G_CALLBACK(qq_block_buddy_with_gc_and_uid)); @@ -470,11 +470,11 @@ static void _qq_menu_create_permanent_group(PurplePluginAction * action) { PurpleConnection *gc = (PurpleConnection *) action->context; - purple_request_input(gc, _("Create QQ Qun"), + purple_request_input_with_hint(gc, _("Create QQ Qun"), _("Input Qun name here"), _("Only QQ members can create permanent Qun"), "OpenQ", FALSE, FALSE, NULL, - _("Create"), G_CALLBACK(qq_group_create_with_name), _("Cancel"), NULL, gc); + _("Create"), G_CALLBACK(qq_group_create_with_name), _("Cancel"), NULL, "blist", gc); } */ diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/qq/sys_msg.c --- a/libpurple/protocols/qq/sys_msg.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/qq/sys_msg.c Thu Oct 18 17:58:40 2007 +0000 @@ -83,10 +83,10 @@ qq_send_packet_get_info(gc, uid, TRUE); /* we want to see window */ nombre = uid_to_purple_name(uid); - purple_request_action + purple_request_action_with_hint (gc, NULL, _("Do you want to approve the request?"), "", 2, purple_connection_get_account(gc), nombre, NULL, - g, 2, + PURPLE_REQUEST_UI_HINT_CONV, g, 2, _("Reject"), G_CALLBACK(qq_reject_add_request_with_gc_and_uid), _("Approve"), G_CALLBACK(qq_approve_add_request_with_gc_and_uid)); g_free(nombre); @@ -106,11 +106,11 @@ qq_send_packet_get_info(gc, uid, TRUE); /* we want to see window */ nombre = uid_to_purple_name(uid); - purple_request_action + purple_request_action_with_hint (gc, NULL, _("Do you want to add this buddy?"), "", 2, purple_connection_get_account(gc), nombre, NULL, - g, 2, - _("Cancel"), NULL, + PURPLE_REQUEST_UI_HINT_BUDDY, g, 2, + _("Cancel"), NULL, _("Add"), G_CALLBACK(qq_add_buddy_with_gc_and_uid)); g_free(nombre); } @@ -165,10 +165,10 @@ g->uid = uid; /* only need to get value */ message = g_strdup_printf(_("You have been added by %s"), from); _qq_sys_msg_log_write(gc, message, from); - purple_request_action(gc, NULL, message, + purple_request_action_with_hint(gc, NULL, message, _("Would you like to add him?"), 2, purple_connection_get_account(gc), name, NULL, - g, 3, + PURPLE_REQUEST_UI_HINT_BUDDY, g, 3, _("Cancel"), NULL, _("Add"), G_CALLBACK(qq_add_buddy_with_gc_and_uid), _("Search"), G_CALLBACK(_qq_search_before_add_with_gc_and_uid)); @@ -239,10 +239,10 @@ reason = g_strdup_printf(_("Message: %s"), msg_utf8); _qq_sys_msg_log_write(gc, message, from); - purple_request_action + purple_request_action_with_hint (gc, NULL, message, reason, 2, purple_connection_get_account(gc), name, NULL, - g, 3, + PURPLE_REQUEST_UI_HINT_BUDDY, g, 3, _("Reject"), G_CALLBACK(qq_reject_add_request_with_gc_and_uid), _("Approve"), @@ -259,10 +259,10 @@ g2->gc = gc; g2->uid = strtol(from, NULL, 10); message = g_strdup_printf(_("%s is not in your buddy list"), from); - purple_request_action(gc, NULL, message, + purple_request_action_with_hint(gc, NULL, message, _("Would you like to add him?"), 2, purple_connection_get_account(gc), name, NULL, - g2, 3, + PURPLE_REQUEST_UI_HINT_BLIST, g2, 3, _("Cancel"), NULL, _("Add"), G_CALLBACK(qq_add_buddy_with_gc_and_uid), _("Search"), G_CALLBACK(_qq_search_before_add_with_gc_and_uid)); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/sametime/sametime.c --- a/libpurple/protocols/sametime/sametime.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/sametime/sametime.c Thu Oct 18 17:58:40 2007 +0000 @@ -3382,12 +3382,12 @@ " message to be sent to %s"); msg1 = g_strdup_printf(msgB, buddy->name); - purple_request_fields(gc, _("New Conference"), + purple_request_fields_with_hint(gc, _("New Conference"), msgA, msg1, fields, _("Create"), G_CALLBACK(conf_create_prompt_join), _("Cancel"), G_CALLBACK(conf_create_prompt_cancel), acct, purple_buddy_get_name(buddy), NULL, - buddy); + PURPLE_REQUEST_UI_HINT_CONV, buddy); g_free(msg1); } @@ -3468,12 +3468,12 @@ " create a new conference to invite this user to."); msg = g_strdup_printf(msgB, buddy->name); - purple_request_fields(gc, _("Invite to Conference"), + purple_request_fields_with_hint(gc, _("Invite to Conference"), msgA, msg, fields, _("Invite"), G_CALLBACK(conf_select_prompt_invite), _("Cancel"), G_CALLBACK(conf_select_prompt_cancel), acct, purple_buddy_get_name(buddy), NULL, - buddy); + PURPLE_REQUEST_UI_HINT_CONV, buddy); g_free(msg); } @@ -3638,13 +3638,13 @@ " continue logging in."); msg = g_strdup_printf(msgA, NSTR(purple_account_get_username(acct))); - purple_request_input(gc, _("Meanwhile Connection Setup"), + purple_request_input_with_hint(gc, _("Meanwhile Connection Setup"), _("No Sametime Community Server Specified"), msg, MW_PLUGIN_DEFAULT_HOST, FALSE, FALSE, NULL, _("Connect"), G_CALLBACK(prompt_host_ok_cb), _("Cancel"), G_CALLBACK(prompt_host_cancel_cb), acct, NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_CONV, gc); g_free(msg); } @@ -5215,10 +5215,10 @@ title = g_strdup_printf(_("Import Sametime List for Account %s"), purple_account_get_username(account)); - purple_request_file(gc, title, NULL, FALSE, + purple_request_file_with_hint(gc, title, NULL, FALSE, G_CALLBACK(st_import_action_cb), NULL, account, NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_CONV, gc); g_free(title); } @@ -5255,10 +5255,10 @@ title = g_strdup_printf(_("Export Sametime List for Account %s"), purple_account_get_username(account)); - purple_request_file(gc, title, NULL, TRUE, + purple_request_file_with_hint(gc, title, NULL, TRUE, G_CALLBACK(st_export_action_cb), NULL, account, NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_CONV, gc); g_free(title); } @@ -5391,12 +5391,12 @@ " the list below to add it to your buddy list."); msg = g_strdup_printf(msgB, result->name); - purple_request_fields(gc, _("Select Notes Address Book"), + purple_request_fields_with_hint(gc, _("Select Notes Address Book"), msgA, msg, fields, _("Add Group"), G_CALLBACK(remote_group_multi_cb), _("Cancel"), G_CALLBACK(remote_group_multi_cleanup), purple_connection_get_account(gc), result->name, NULL, - pd); + PURPLE_REQUEST_UI_HINT_BLIST, pd); g_free(msg); } @@ -5481,12 +5481,12 @@ msgB = _("Enter the name of a Notes Address Book group in the field below" " to add the group and its members to your buddy list."); - purple_request_input(gc, _("Add Group"), msgA, msgB, NULL, + purple_request_input_with_hint(gc, _("Add Group"), msgA, msgB, NULL, FALSE, FALSE, NULL, _("Add"), G_CALLBACK(remote_group_action_cb), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_BLIST, gc); } @@ -5606,12 +5606,12 @@ msgB = _("Enter a name or partial ID in the field below to search" " for matching users in your Sametime community."); - purple_request_input(gc, _("User Search"), msgA, msgB, NULL, + purple_request_input_with_hint(gc, _("User Search"), msgA, msgB, NULL, FALSE, FALSE, NULL, _("Search"), G_CALLBACK(search_action_cb), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_BLIST, gc); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc/buddy.c --- a/libpurple/protocols/silc/buddy.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc/buddy.c Thu Oct 18 17:58:40 2007 +0000 @@ -312,9 +312,9 @@ a->hostname = strdup(hostname); a->port = port; - purple_request_action(client->application, _("Key Agreement Request"), tmp, + purple_request_action_with_hint(client->application, _("Key Agreement Request"), tmp, hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname, - NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb), + NULL, PURPLE_REQUEST_UI_HINT_BLIST, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb), _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb)); } @@ -449,11 +449,11 @@ p->client = sg->client; p->conn = sg->conn; p->client_id = client_entry->id; - purple_request_input(gc, _("IM With Password"), NULL, + purple_request_input_with_hint(gc, _("IM With Password"), NULL, _("Set IM Password"), NULL, FALSE, TRUE, NULL, _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb), _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb), - gc->account, NULL, NULL, p); + gc->account, NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, p); silc_client_list_free(sg->client, sg->conn, clients); } @@ -1056,10 +1056,10 @@ } /* Open file selector to select the public key. */ - purple_request_file(r->client->application, _("Open..."), NULL, FALSE, + purple_request_file_with_hint(r->client->application, _("Open..."), NULL, FALSE, G_CALLBACK(silcpurple_add_buddy_ask_import), G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel), - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); + purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, PURPLE_REQUEST_UI_HINT_BLIST, r); } @@ -1069,10 +1069,10 @@ char tmp[512]; g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"), r->b->name); - purple_request_action(r->client->application, _("Add Buddy"), tmp, + purple_request_action_with_hint(r->client->application, _("Add Buddy"), tmp, _("To add the buddy you must import his/her public key. " "Press Import to import a public key."), 0, - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2, + purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, PURPLE_REQUEST_UI_HINT_BLIST, r, 2, _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb), _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb)); } @@ -1179,7 +1179,7 @@ silc_free(fingerprint); } - purple_request_fields(r->client->application, _("Add Buddy"), + purple_request_fields_with_hint(r->client->application, _("Add Buddy"), _("Select correct user"), r->pubkey_search ? _("More than one user was found with the same public key. Select " @@ -1189,7 +1189,7 @@ fields, _("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb), _("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel), - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); + purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, PURPLE_REQUEST_UI_HINT_BLIST, r); } static void diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc/chat.c --- a/libpurple/protocols/silc/chat.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc/chat.c Thu Oct 18 17:58:40 2007 +0000 @@ -301,10 +301,10 @@ f = purple_request_fields_get_field(fields, "list"); if (!purple_request_field_list_get_selected(f)) { /* Add new public key */ - purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE, + purple_request_file_with_hint(sg->gc, _("Open Public Key..."), NULL, FALSE, G_CALLBACK(silcpurple_chat_chpk_add), G_CALLBACK(silcpurple_chat_chpk_cancel), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); + purple_connection_get_account(sg->gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_CONV, sgc); return; } @@ -441,11 +441,11 @@ if (!channel_pubkeys || !silc_dlist_count(channel_pubkeys)) { f = purple_request_field_list_new("list", NULL); purple_request_field_group_add_field(g, f); - purple_request_fields(sg->gc, _("Channel Authentication"), + purple_request_fields_with_hint(sg->gc, _("Channel Authentication"), _("Channel Authentication"), t, fields, _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); + purple_connection_get_account(sg->gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_CONV, sgc); if (channel_pubkeys) silc_dlist_uninit(channel_pubkeys); return; @@ -476,11 +476,11 @@ } purple_request_field_list_set_multi_select(f, FALSE); - purple_request_fields(sg->gc, _("Channel Authentication"), + purple_request_fields_with_hint(sg->gc, _("Channel Authentication"), _("Channel Authentication"), t, fields, _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); + purple_connection_get_account(sg->gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_CONV, sgc); } static void @@ -611,10 +611,10 @@ g_snprintf(tmp, sizeof(tmp), _("Please enter the %s channel private group name and passphrase."), p->channel); - purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields, + purple_request_fields_with_hint(gc, _("Add Channel Private Group"), NULL, tmp, fields, _("Add"), G_CALLBACK(silcpurple_chat_prv_add), _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel), - purple_connection_get_account(gc), NULL, NULL, p); + purple_connection_get_account(gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_CONV, p); } @@ -739,12 +739,12 @@ s->channel = ch; s->sg = sg; g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit); - purple_request_input(gc, _("User Limit"), NULL, + purple_request_input_with_hint(gc, _("User Limit"), NULL, _("Set user limit on channel. Set to zero to reset user limit."), tmp, FALSE, FALSE, NULL, _("OK"), G_CALLBACK(silcpurple_chat_ulimit_cb), _("Cancel"), G_CALLBACK(silcpurple_chat_ulimit_cb), - purple_connection_get_account(gc), NULL, NULL, s); + purple_connection_get_account(gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_CONV, s); } static void diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc/ops.c --- a/libpurple/protocols/silc/ops.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc/ops.c Thu Oct 18 17:58:40 2007 +0000 @@ -1810,11 +1810,11 @@ return; internal->u.ask_pass = completion; internal->context = context; - purple_request_input(gc, _("Passphrase"), NULL, + purple_request_input_with_hint(gc, _("Passphrase"), NULL, _("Passphrase required"), NULL, FALSE, TRUE, NULL, _("OK"), G_CALLBACK(silc_ask_passphrase_cb), _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb), - purple_connection_get_account(gc), NULL, NULL, internal); + purple_connection_get_account(gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, internal); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc/pk.c --- a/libpurple/protocols/silc/pk.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc/pk.c Thu Oct 18 17:58:40 2007 +0000 @@ -107,9 +107,9 @@ _("Fingerprint and babbleprint for the %s key are:\n\n" "%s\n%s\n"), entity, fingerprint, babbleprint); - purple_request_action(gc, _("Verify Public Key"), tmp, tmp2, + purple_request_action_with_hint(gc, _("Verify Public Key"), tmp, tmp2, PURPLE_DEFAULT_ACTION_NONE, - purple_connection_get_account(gc), entity, NULL, verify, 3, + purple_connection_get_account(gc), entity, NULL, PURPLE_REQUEST_UI_HINT_BLIST, verify, 3, _("Yes"), G_CALLBACK(silcpurple_verify_cb), _("No"), G_CALLBACK(silcpurple_verify_cb), _("_View..."), G_CALLBACK(silcpurple_verify_details)); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc/silc.c --- a/libpurple/protocols/silc/silc.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc/silc.c Thu Oct 18 17:58:40 2007 +0000 @@ -813,7 +813,7 @@ purple_request_field_group_add_field(g, f); purple_request_fields_add_group(fields, g); - purple_request_fields(gc, _("User Online Status Attributes"), + purple_request_fields_with_hint(gc, _("User Online Status Attributes"), _("User Online Status Attributes"), _("You can let other users see your online status information " "and your personal information. Please fill the information " @@ -821,7 +821,7 @@ fields, _("OK"), G_CALLBACK(silcpurple_attrs_cb), _("Cancel"), G_CALLBACK(silcpurple_attrs_cancel), - gc->account, NULL, NULL, gc); + gc->account, NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, gc); } static void @@ -1025,11 +1025,11 @@ purple_request_field_group_add_field(g, f); purple_request_fields_add_group(fields, g); - purple_request_fields(gc, _("Create New SILC Key Pair"), + purple_request_fields_with_hint(gc, _("Create New SILC Key Pair"), _("Create New SILC Key Pair"), NULL, fields, _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb), _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel), - gc->account, NULL, NULL, gc); + gc->account, NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, gc); g_strfreev(u); silc_free(hostname); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc/util.c --- a/libpurple/protocols/silc/util.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc/util.c Thu Oct 18 17:58:40 2007 +0000 @@ -376,10 +376,10 @@ buf = g_string_free(s, FALSE); - purple_request_action(sg->gc, _("Public Key Information"), + purple_request_action_with_hint(sg->gc, _("Public Key Information"), _("Public Key Information"), buf, 0, purple_connection_get_account(sg->gc), - NULL, NULL, context, 1, _("Close"), callback); + NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, context, 1, _("Close"), callback); g_free(buf); silc_free(fingerprint); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc/wb.c --- a/libpurple/protocols/silc/wb.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc/wb.c Thu Oct 18 17:58:40 2007 +0000 @@ -299,8 +299,8 @@ req->channel = channel; req->sg = sg; - purple_request_action(gc, _("Whiteboard"), tmp, NULL, 1, - sg->account, sender->nickname, NULL, req, 2, + purple_request_action_with_hint(gc, _("Whiteboard"), tmp, NULL, 1, + sg->account, sender->nickname, NULL, PURPLE_REQUEST_UI_HINT_BLIST, req, 2, _("Yes"), G_CALLBACK(silcpurple_wb_request_cb), _("No"), G_CALLBACK(silcpurple_wb_request_cb)); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc10/buddy.c --- a/libpurple/protocols/silc10/buddy.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc10/buddy.c Thu Oct 18 17:58:40 2007 +0000 @@ -309,9 +309,9 @@ a->hostname = strdup(hostname); a->port = port; - purple_request_action(client->application, _("Key Agreement Request"), tmp, + purple_request_action_with_hint(client->application, _("Key Agreement Request"), tmp, hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname, - NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb), + NULL, a, PURPLE_REQUEST_UI_HINT_BLIST, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb), _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb)); } @@ -462,11 +462,11 @@ p->client = sg->client; p->conn = sg->conn; p->client_id = *clients[0]->id; - purple_request_input(gc, _("IM With Password"), NULL, + purple_request_input_with_hint(gc, _("IM With Password"), NULL, _("Set IM Password"), NULL, FALSE, TRUE, NULL, _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb), _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb), - gc->account, NULL, NULL, p); + gc->account, NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, p); silc_free(clients); silc_free(nickname); @@ -1064,10 +1064,10 @@ } /* Open file selector to select the public key. */ - purple_request_file(r->client->application, _("Open..."), NULL, FALSE, + purple_request_file_with_hint(r->client->application, _("Open..."), NULL, FALSE, G_CALLBACK(silcpurple_add_buddy_ask_import), G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel), - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); + purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, PURPLE_REQUEST_UI_HINT_BLIST, r); } @@ -1077,10 +1077,10 @@ char tmp[512]; g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"), r->b->name); - purple_request_action(r->client->application, _("Add Buddy"), tmp, + purple_request_action_with_hint(r->client->application, _("Add Buddy"), tmp, _("To add the buddy you must import his/her public key. " "Press Import to import a public key."), 0, - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2, + purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, PURPLE_REQUEST_UI_HINT_BLIST, r, 2, _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb), _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb)); } @@ -1177,7 +1177,7 @@ silc_free(fingerprint); } - purple_request_fields(r->client->application, _("Add Buddy"), + purple_request_fields_with_hint(r->client->application, _("Add Buddy"), _("Select correct user"), r->pubkey_search ? _("More than one user was found with the same public key. Select " @@ -1187,7 +1187,7 @@ fields, _("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb), _("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel), - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); + purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, PURPLE_REQUEST_UI_HINT_BLIST, r); } static void diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc10/chat.c --- a/libpurple/protocols/silc10/chat.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc10/chat.c Thu Oct 18 17:58:40 2007 +0000 @@ -288,10 +288,10 @@ f = purple_request_fields_get_field(fields, "list"); if (!purple_request_field_list_get_selected(f)) { /* Add new public key */ - purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE, + purple_request_file_with_hint(sg->gc, _("Open Public Key..."), NULL, FALSE, G_CALLBACK(silcpurple_chat_chpk_add), G_CALLBACK(silcpurple_chat_chpk_cancel), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); + purple_connection_get_account(sg->gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_CONV, sgc); return; } @@ -419,11 +419,11 @@ if (!channel_pubkeys) { f = purple_request_field_list_new("list", NULL); purple_request_field_group_add_field(g, f); - purple_request_fields(sg->gc, _("Channel Authentication"), + purple_request_fields_with_hint(sg->gc, _("Channel Authentication"), _("Channel Authentication"), t, fields, _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); + purple_connection_get_account(sg->gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_CONV, sgc); return; } sgc->pubkeys = silc_buffer_copy(channel_pubkeys); @@ -458,11 +458,11 @@ } purple_request_field_list_set_multi_select(f, FALSE); - purple_request_fields(sg->gc, _("Channel Authentication"), + purple_request_fields_with_hint(sg->gc, _("Channel Authentication"), _("Channel Authentication"), t, fields, _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); + purple_connection_get_account(sg->gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_CONV, sgc); silc_argument_payload_free(chpks); } @@ -595,10 +595,10 @@ g_snprintf(tmp, sizeof(tmp), _("Please enter the %s channel private group name and passphrase."), p->channel); - purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields, + purple_request_fields_with_hint(gc, _("Add Channel Private Group"), NULL, tmp, fields, _("Add"), G_CALLBACK(silcpurple_chat_prv_add), _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel), - purple_connection_get_account(gc), NULL, NULL, p); + purple_connection_get_account(gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_CONV, p); } @@ -723,12 +723,12 @@ s->channel = ch; s->sg = sg; g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit); - purple_request_input(gc, _("User Limit"), NULL, + purple_request_input_with_hint(gc, _("User Limit"), NULL, _("Set user limit on channel. Set to zero to reset user limit."), tmp, FALSE, FALSE, NULL, _("OK"), G_CALLBACK(silcpurple_chat_ulimit_cb), _("Cancel"), G_CALLBACK(silcpurple_chat_ulimit_cb), - purple_connection_get_account(gc), NULL, NULL, s); + purple_connection_get_account(gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_CONV, s); } static void diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc10/ops.c --- a/libpurple/protocols/silc10/ops.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc10/ops.c Thu Oct 18 17:58:40 2007 +0000 @@ -1291,9 +1291,9 @@ #if 0 /* XXX for now, let's not show attrs here */ if (client_entry->attrs) - purple_request_action(gc, _("User Information"), + purple_request_action_with_hint(gc, _("User Information"), _("User Information"), - buf, 1, client_entry, 2, + buf, 1, PURPLE_REQUEST_UI_HINT_BLIST, client_entry, 2, _("OK"), G_CALLBACK(silcpurple_whois_more), _("_More..."), G_CALLBACK(silcpurple_whois_more), gc->account, NULL, NULL); else @@ -1898,11 +1898,11 @@ return; internal->completion = completion; internal->context = context; - purple_request_input(gc, _("Passphrase"), NULL, + purple_request_input_with_hint(gc, _("Passphrase"), NULL, _("Passphrase required"), NULL, FALSE, TRUE, NULL, _("OK"), G_CALLBACK(silc_ask_passphrase_cb), _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb), - purple_connection_get_account(gc), NULL, NULL, internal); + purple_connection_get_account(gc), NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, internal); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc10/pk.c --- a/libpurple/protocols/silc10/pk.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc10/pk.c Thu Oct 18 17:58:40 2007 +0000 @@ -113,9 +113,9 @@ _("Fingerprint and babbleprint for the %s key are:\n\n" "%s\n%s\n"), entity, fingerprint, babbleprint); - purple_request_action(gc, _("Verify Public Key"), tmp, tmp2, + purple_request_action_with_hint(gc, _("Verify Public Key"), tmp, tmp2, PURPLE_DEFAULT_ACTION_NONE, - purple_connection_get_account(gc), entity, NULL, verify, 3, + purple_connection_get_account(gc), entity, NULL, verify, PURPLE_REQUEST_UI_HINT_BLIST, 3, _("Yes"), G_CALLBACK(silcpurple_verify_cb), _("No"), G_CALLBACK(silcpurple_verify_cb), _("_View..."), G_CALLBACK(silcpurple_verify_details)); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc10/silc.c --- a/libpurple/protocols/silc10/silc.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc10/silc.c Thu Oct 18 17:58:40 2007 +0000 @@ -726,7 +726,7 @@ purple_request_field_group_add_field(g, f); purple_request_fields_add_group(fields, g); - purple_request_fields(gc, _("User Online Status Attributes"), + purple_request_fields_with_hint(gc, _("User Online Status Attributes"), _("User Online Status Attributes"), _("You can let other users see your online status information " "and your personal information. Please fill the information " @@ -734,7 +734,7 @@ fields, _("OK"), G_CALLBACK(silcpurple_attrs_cb), _("Cancel"), G_CALLBACK(silcpurple_attrs_cancel), - gc->account, NULL, NULL, gc); + gc->account, NULL, NULL, PURPLE_REQUEST_UI_HINT_BLIST, gc); } static void @@ -940,7 +940,7 @@ _("Create New SILC Key Pair"), NULL, fields, _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb), _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel), - gc->account, NULL, NULL, gc); + gc->account, NULL, NULL, "blist", gc); g_strfreev(u); silc_free(hostname); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc10/util.c --- a/libpurple/protocols/silc10/util.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc10/util.c Thu Oct 18 17:58:40 2007 +0000 @@ -371,10 +371,10 @@ buf = g_string_free(s, FALSE); - purple_request_action(sg->gc, _("Public Key Information"), + purple_request_action_with_hint(sg->gc, _("Public Key Information"), _("Public Key Information"), buf, 0, purple_connection_get_account(sg->gc), - NULL, NULL, context, 1, _("Close"), callback); + NULL, NULL, context, PURPLE_REQUEST_UI_HINT_BLIST, 1, _("Close"), callback); g_free(buf); silc_free(fingerprint); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/silc10/wb.c --- a/libpurple/protocols/silc10/wb.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/silc10/wb.c Thu Oct 18 17:58:40 2007 +0000 @@ -299,8 +299,8 @@ req->channel = channel; req->sg = sg; - purple_request_action(gc, _("Whiteboard"), tmp, NULL, 1, - sg->account, sender->nickname, NULL, req, 2, + purple_request_action_with_hint(gc, _("Whiteboard"), tmp, NULL, 1, + sg->account, sender->nickname, NULL, PURPLE_REQUEST_UI_HINT_CONV, req, 2, _("Yes"), G_CALLBACK(silcpurple_wb_request_cb), _("No"), G_CALLBACK(silcpurple_wb_request_cb)); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/simple/simple.c --- a/libpurple/protocols/simple/simple.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/simple/simple.c Thu Oct 18 17:58:40 2007 +0000 @@ -80,14 +80,15 @@ static gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc); static void send_notify(struct simple_account_data *sip, struct simple_watcher *); -static void send_publish(struct simple_account_data *sip); +static void send_open_publish(struct simple_account_data *sip); +static void send_closed_publish(struct simple_account_data *sip); static void do_notifies(struct simple_account_data *sip) { GSList *tmp = sip->watcher; purple_debug_info("simple", "do_notifies()\n"); if((sip->republish != -1) || sip->republish < time(NULL)) { if(purple_account_get_bool(sip->account, "dopublish", TRUE)) { - send_publish(sip); + send_open_publish(sip); } } @@ -1020,7 +1021,7 @@ case 200: if(sip->registerstatus < SIMPLE_REGISTER_COMPLETE) { /* registered */ if(purple_account_get_bool(sip->account, "dopublish", TRUE)) { - send_publish(sip); + send_open_publish(sip); } } sip->registerstatus = SIMPLE_REGISTER_COMPLETE; @@ -1072,7 +1073,7 @@ static void process_incoming_notify(struct simple_account_data *sip, struct sipmsg *msg) { gchar *from; gchar *fromhdr; - gchar *tmp2; + gchar *basicstatus_data; xmlnode *pidf; xmlnode *basicstatus = NULL, *tuple, *status; gboolean isonline = FALSE; @@ -1085,8 +1086,9 @@ if(!pidf) { purple_debug_info("simple", "process_incoming_notify: no parseable pidf\n"); + purple_prpl_got_user_status(sip->account, from, "offline", NULL); + send_sip_response(sip->gc, msg, 200, "OK", NULL); g_free(from); - send_sip_response(sip->gc, msg, 200, "OK", NULL); return; } @@ -1101,27 +1103,28 @@ return; } - tmp2 = xmlnode_get_data(basicstatus); + basicstatus_data = xmlnode_get_data(basicstatus); - if(!tmp2) { + if(!basicstatus_data) { purple_debug_info("simple", "process_incoming_notify: no basic data found\n"); xmlnode_free(pidf); g_free(from); return; } - if(strstr(tmp2, "open")) { + if(strstr(basicstatus_data, "open")) isonline = TRUE; - } + - g_free(tmp2); - - if(isonline) purple_prpl_got_user_status(sip->account, from, "available", NULL); - else purple_prpl_got_user_status(sip->account, from, "offline", NULL); + if(isonline) + purple_prpl_got_user_status(sip->account, from, "available", NULL); + else + purple_prpl_got_user_status(sip->account, from, "offline", NULL); xmlnode_free(pidf); + g_free(from); + g_free(basicstatus_data); - g_free(from); send_sip_response(sip->gc, msg, 200, "OK", NULL); } @@ -1188,28 +1191,27 @@ return doc; } - - -static gchar* gen_pidf(struct simple_account_data *sip) { +static gchar* gen_pidf(struct simple_account_data *sip, gboolean open) { gchar *doc = g_strdup_printf("\n" "\n" "\n" "\n" - "open\n" + "%s\n" "\n" "%s\n" "\n" "", sip->username, sip->servername, - sip->status); + (open == TRUE) ? "open" : "closed", + (open == TRUE) ? sip->status : ""); return doc; } static void send_notify(struct simple_account_data *sip, struct simple_watcher *watcher) { - gchar *doc = watcher->needsxpidf ? gen_xpidf(sip) : gen_pidf(sip); + gchar *doc = watcher->needsxpidf ? gen_xpidf(sip) : gen_pidf(sip, TRUE); gchar *hdr = watcher->needsxpidf ? "Event: presence\r\nContent-Type: application/xpidf+xml\r\n" : "Event: presence\r\nContent-Type: application/pidf+xml\r\n"; send_sip_request(sip->gc, "NOTIFY", watcher->name, watcher->name, hdr, doc, &watcher->dialog, NULL); g_free(doc); @@ -1223,9 +1225,9 @@ return TRUE; } -static void send_publish(struct simple_account_data *sip) { +static void send_open_publish(struct simple_account_data *sip) { gchar *uri = g_strdup_printf("sip:%s@%s", sip->username, sip->servername); - gchar *doc = gen_pidf(sip); + gchar *doc = gen_pidf(sip, TRUE); send_sip_request(sip->gc, "PUBLISH", uri, uri, "Expires: 600\r\nEvent: presence\r\n" "Content-Type: application/pidf+xml\r\n", @@ -1235,6 +1237,18 @@ g_free(doc); } +static void send_closed_publish(struct simple_account_data *sip) { + gchar *uri = g_strdup_printf("sip:%s@%s", sip->username, sip->servername); + gchar *doc = gen_pidf(sip, FALSE); + send_sip_request(sip->gc, "PUBLISH", uri, uri, + "Expires: 600\r\nEvent: presence\r\n" + "Content-Type: application/pidf+xml\r\n", + doc, NULL, process_publish_response); + /*sip->republish = time(NULL) + 500;*/ + g_free(uri); + g_free(doc); +} + static void process_incoming_subscribe(struct simple_account_data *sip, struct sipmsg *msg) { const char *from_hdr = sipmsg_find_header(msg, "From"); gchar *from = parse_from(from_hdr); @@ -1738,7 +1752,14 @@ if(sip) { /* unregister */ if (sip->registerstatus == SIMPLE_REGISTER_COMPLETE) + { + if(purple_account_get_bool(sip->account, + "dopublish", + TRUE)) + send_closed_publish(sip); + do_register_exp(sip, 0); + } connection_free_all(sip); if (sip->query_data != NULL) diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/toc/toc.c --- a/libpurple/protocols/toc/toc.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/toc/toc.c Thu Oct 18 17:58:40 2007 +0000 @@ -2216,8 +2216,8 @@ g_snprintf(buf, sizeof(buf), _("%s requests you to send them a file"), ft->user); } - purple_request_accept_cancel(ft->gc, NULL, buf, NULL, - PURPLE_DEFAULT_ACTION_NONE, ft, + purple_request_accept_cancel_with_hint(ft->gc, NULL, buf, NULL, + PURPLE_DEFAULT_ACTION_NONE, PURPLE_REQUEST_UI_HINT_XFER, ft, G_CALLBACK(toc_accept_ft), G_CALLBACK(toc_reject_ft)); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/protocols/yahoo/yahoo.c --- a/libpurple/protocols/yahoo/yahoo.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Thu Oct 18 17:58:40 2007 +0000 @@ -1028,12 +1028,12 @@ static void yahoo_buddy_add_deny_reason_cb(gpointer data) { struct yahoo_add_request *add_req = data; - purple_request_input(add_req->gc, NULL, _("Authorization denied message:"), + purple_request_input_with_hint(add_req->gc, NULL, _("Authorization denied message:"), NULL, _("No reason given."), TRUE, FALSE, NULL, _("OK"), G_CALLBACK(yahoo_buddy_add_deny_cb), _("Cancel"), G_CALLBACK(yahoo_buddy_add_deny_noreason_cb), purple_connection_get_account(add_req->gc), add_req->who, NULL, - add_req); + PURPLE_REQUEST_UI_HINT_BLIST, add_req); } static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason) @@ -2065,9 +2065,9 @@ g_snprintf(buf, sizeof(buf), _("You have tried to ignore %s, but the " "user is on your buddy list. Clicking \"Yes\" " "will remove and ignore the buddy."), who); - purple_request_yes_no(gc, NULL, _("Ignore buddy?"), buf, 0, + purple_request_yes_no_with_hint(gc, NULL, _("Ignore buddy?"), buf, 0, gc->account, who, NULL, - b, + PURPLE_REQUEST_UI_HINT_BLIST, b, G_CALLBACK(ignore_buddy), G_CALLBACK(keep_buddy)); break; @@ -3494,23 +3494,23 @@ static void yahoo_show_act_id(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *) action->context; - purple_request_input(gc, NULL, _("Activate which ID?"), NULL, + purple_request_input_with_hint(gc, NULL, _("Activate which ID?"), NULL, purple_connection_get_display_name(gc), FALSE, FALSE, NULL, _("OK"), G_CALLBACK(yahoo_act_id), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_ACCOUNT, gc); } static void yahoo_show_chat_goto(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *) action->context; - purple_request_input(gc, NULL, _("Join whom in chat?"), NULL, + purple_request_input_with_hint(gc, NULL, _("Join who in chat?"), NULL, "", FALSE, FALSE, NULL, _("OK"), G_CALLBACK(yahoo_chat_goto), _("Cancel"), NULL, purple_connection_get_account(gc), NULL, NULL, - gc); + PURPLE_REQUEST_UI_HINT_CONV, gc); } static GList *yahoo_actions(PurplePlugin *plugin, gpointer context) { diff -r 33822d7271e5 -r 8b9c48347004 libpurple/prpl.h --- a/libpurple/prpl.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/prpl.h Thu Oct 18 17:58:40 2007 +0000 @@ -226,11 +226,17 @@ void (*tooltip_text)(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full); /** - * This must be implemented, and must add at least the offline - * and online states. + * Returns a list of #PurpleStatusType which exist for this account; + * this must be implemented, and must add at least the offline and + * online states. */ GList *(*status_types)(PurpleAccount *account); + /** + * Returns a list of #PurpleMenuAction structs, which represent extra + * actions to be shown in (for example) the right-click menu for @a + * node. + */ GList *(*blist_node_menu)(PurpleBlistNode *node); GList *(*chat_info)(PurpleConnection *); GHashTable *(*chat_info_defaults)(PurpleConnection *, const char *chat_name); @@ -258,6 +264,10 @@ void (*set_info)(PurpleConnection *, const char *info); unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleTypingState state); + /** + * Should arrange for purple_notify_userinfo() to be called with + * @a who's user info. + */ void (*get_info)(PurpleConnection *, const char *who); void (*set_status)(PurpleAccount *account, PurpleStatus *status); @@ -287,8 +297,14 @@ /** new user registration */ void (*register_user)(PurpleAccount *); - /* get "chat buddy" info and away message */ + /** + * @deprecated Use #PurplePluginProtocolInfo.get_info instead. + */ void (*get_cb_info)(PurpleConnection *, int, const char *who); + /** + * @deprecated Use #PurplePluginProtocolInfo.get_cb_real_name and + * #PurplePluginProtocolInfo.status_text instead. + */ void (*get_cb_away)(PurpleConnection *, int, const char *who); /** save/store buddy's alias on server list/roster */ @@ -348,9 +364,12 @@ /* room list serialize */ char *(*roomlist_room_serialize)(PurpleRoomlistRoom *room); - /* Remove the user from the server. (This is only at the bottom to keep binary compatibility.) - * The account can either be connected or disconnected. After the removal is finished, - * the connection will stay open and has to be closed! + /** Remove the user from the server. The account can either be + * connected or disconnected. After the removal is finished, the + * connection will stay open and has to be closed! + */ + /* This is here rather than next to register_user for API compatibility + * reasons. */ void (*unregister_user)(PurpleAccount *, PurpleAccountUnregistrationCb cb, void *user_data); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/purple.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/purple.h Thu Oct 18 17:58:40 2007 +0000 @@ -0,0 +1,92 @@ +/** + * @file purple.h Header files and defines + * This file contains all the necessary preprocessor directives to include + * libpurple's headers and other preprocessor directives required for plugins + * or UIs to build. Inlcuding this file eliminates the need to directly + * include any other libpurple files. It will still be necessary for plugins + * to define @c PURPLE_PLUGINS before including this header. + * + * @ingroup core libpurple + */ + +/* purple + * + * Purple 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 program 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef _PURPLE_H +#define _PURPLE_H + +#ifndef G_GNUC_NULL_TERMINATED +# if __GNUC__ >= 4 +# define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) +# else +# define G_GNUC_NULL_TERMINATED +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff -r 33822d7271e5 -r 8b9c48347004 libpurple/request.c --- a/libpurple/request.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/request.c Thu Oct 18 17:58:40 2007 +0000 @@ -377,6 +377,13 @@ g_hash_table_destroy(field->u.list.item_data); g_hash_table_destroy(field->u.list.selected_table); } + else if (field->type == PURPLE_REQUEST_FIELD_BLIST) + { + if (field->u.blist.default_nodes) + g_list_free(field->u.blist.default_nodes); + if (field->u.blist.selecteds) + g_list_free(field->u.blist.selecteds); + } g_free(field); } @@ -1133,6 +1140,85 @@ /* -- */ +PurpleRequestField *purple_request_field_blist_nodes_new(const char *id, + const char *text, PurpleRequestBlistFlags flags, GList *selected) +{ + PurpleRequestField *field; + + g_return_val_if_fail(id != NULL, NULL); + g_return_val_if_fail(text != NULL, NULL); + + field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_BLIST); + + field->u.blist.flags = flags; + field->u.blist.default_nodes = selected; + purple_request_field_blist_set_selection_list(field, selected); + + return field; +} + +PurpleFilterBlistFunc +purple_request_field_blist_set_filter(PurpleRequestField *field, PurpleFilterBlistFunc filter) +{ + PurpleFilterBlistFunc old; + g_return_val_if_fail(field != NULL, NULL); + g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BLIST, NULL); + old = field->u.blist.filter; + field->u.blist.filter = filter; + return old; +} + +PurpleFilterBlistFunc +purple_request_field_blist_get_filter(const PurpleRequestField *field) +{ + g_return_val_if_fail(field != NULL, NULL); + g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BLIST, NULL); + return field->u.blist.filter; +} + +GList *purple_request_field_blist_get_selection_list(const PurpleRequestField *field) +{ + g_return_val_if_fail(field != NULL, NULL); + g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BLIST, NULL); + return field->u.blist.selecteds; +} + +gboolean purple_request_field_blist_add(PurpleRequestField *field, PurpleBlistNode *node) +{ + g_return_val_if_fail(field != NULL, FALSE); + g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BLIST, FALSE); + if (!g_list_find(field->u.blist.selecteds, node)) { + field->u.blist.selecteds = g_list_append(field->u.blist.selecteds, node); + return TRUE; + } else { + return FALSE; + } +} + +gboolean purple_request_field_blist_remove(PurpleRequestField *field, PurpleBlistNode *node) +{ + GList *search; + g_return_val_if_fail(field != NULL, FALSE); + g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_BLIST, FALSE); + if ((search = g_list_find(field->u.blist.selecteds, node)) != NULL) { + field->u.blist.selecteds = g_list_delete_link(field->u.blist.selecteds, search); + return TRUE; + } else { + return FALSE; + } +} + +void purple_request_field_blist_set_selection_list(PurpleRequestField *field, GList *selecteds) +{ + g_return_if_fail(field != NULL); + g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_BLIST); + if (field->u.blist.selecteds) + g_list_free(field->u.blist.selecteds); + field->u.blist.selecteds = selecteds; +} + +/* -- */ + void * purple_request_input(void *handle, const char *title, const char *primary, const char *secondary, const char *default_value, @@ -1142,6 +1228,20 @@ PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data) { + return purple_request_input_with_hint( + handle, title, primary, secondary, default_value, multiline, masked, hint, ok_text, ok_cb, + cancel_text, cancel_cb, account, who, conv, PURPLE_REQUEST_UI_HINT_BLIST, user_data); +} + +void * +purple_request_input_with_hint(void *handle, const char *title, const char *primary, + const char *secondary, const char *default_value, + gboolean multiline, gboolean masked, gchar *hint, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data) +{ PurpleRequestUiOps *ops; g_return_val_if_fail(ok_text != NULL, NULL); @@ -1161,7 +1261,7 @@ ok_text, ok_cb, cancel_text, cancel_cb, account, who, conv, - user_data); + ui_hint, user_data); handles = g_list_append(handles, info); @@ -1186,10 +1286,34 @@ g_return_val_if_fail(ok_cb != NULL, NULL); va_start(args, user_data); - ui_handle = purple_request_choice_varg(handle, title, primary, secondary, + ui_handle = purple_request_choice_varg_with_hint(handle, title, primary, secondary, default_value, ok_text, ok_cb, cancel_text, cancel_cb, - account, who, conv, user_data, args); + account, who, conv, PURPLE_REQUEST_UI_HINT_BLIST, user_data, args); + va_end(args); + + return ui_handle; +} + +void * +purple_request_choice_with_hint(void *handle, const char *title, const char *primary, + const char *secondary, int default_value, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data, ...) +{ + void *ui_handle; + va_list args; + + g_return_val_if_fail(ok_text != NULL, NULL); + g_return_val_if_fail(ok_cb != NULL, NULL); + + va_start(args, user_data); + ui_handle = purple_request_choice_varg_with_hint(handle, title, primary, secondary, + default_value, ok_text, ok_cb, + cancel_text, cancel_cb, + account, who, conv, ui_hint, user_data, args); va_end(args); return ui_handle; @@ -1204,6 +1328,20 @@ PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, va_list choices) { + return purple_request_choice_varg_with_hint( + handle, title, primary, secondary, default_value, ok_text, ok_cb, + cancel_text, cancel_cb, account, who, conv, PURPLE_REQUEST_UI_HINT_BLIST, user_data, choices); +} + +void * +purple_request_choice_varg_with_hint(void *handle, const char *title, + const char *primary, const char *secondary, + int default_value, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data, va_list choices) +{ PurpleRequestUiOps *ops; g_return_val_if_fail(ok_text != NULL, NULL); @@ -1222,7 +1360,7 @@ ok_text, ok_cb, cancel_text, cancel_cb, account, who, conv, - user_data, choices); + ui_hint, user_data, choices); handles = g_list_append(handles, info); @@ -1244,9 +1382,29 @@ g_return_val_if_fail(action_count > 0, NULL); va_start(args, action_count); - ui_handle = purple_request_action_varg(handle, title, primary, secondary, + ui_handle = purple_request_action_varg_with_hint(handle, title, primary, secondary, default_action, account, who, conv, - user_data, action_count, args); + PURPLE_REQUEST_UI_HINT_BLIST, user_data, action_count, args); + va_end(args); + + return ui_handle; +} + +void * +purple_request_action_with_hint(void *handle, const char *title, const char *primary, + const char *secondary, int default_action, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data, size_t action_count, ...) +{ + void *ui_handle; + va_list args; + + g_return_val_if_fail(action_count > 0, NULL); + + va_start(args, action_count); + ui_handle = purple_request_action_varg_with_hint(handle, title, primary, secondary, + default_action, account, who, conv, + ui_hint, user_data, action_count, args); va_end(args); return ui_handle; @@ -1257,7 +1415,19 @@ const char *primary, const char *secondary, int default_action, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, size_t action_count, va_list actions) + void *user_data, size_t action_count, va_list actions) +{ + return purple_request_action_varg_with_hint( + handle, title, primary, secondary, default_action, account, who, conv, + PURPLE_REQUEST_UI_HINT_BLIST, user_data, action_count, actions); +} + +void * +purple_request_action_varg_with_hint(void *handle, const char *title, + const char *primary, const char *secondary, + int default_action, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data, size_t action_count, va_list actions) { PurpleRequestUiOps *ops; @@ -1273,7 +1443,7 @@ info->handle = handle; info->ui_handle = ops->request_action(title, primary, secondary, default_action, account, who, conv, - user_data, action_count, actions); + ui_hint, user_data, action_count, actions); handles = g_list_append(handles, info); @@ -1291,6 +1461,19 @@ PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data) { + return purple_request_fields_with_hint( + handle, title, primary, secondary, fields, ok_text, ok_cb, + cancel_text, cancel_cb, account, who, conv, PURPLE_REQUEST_UI_HINT_BLIST, user_data); +} + +void * +purple_request_fields_with_hint(void *handle, const char *title, const char *primary, + const char *secondary, PurpleRequestFields *fields, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data) +{ PurpleRequestUiOps *ops; g_return_val_if_fail(fields != NULL, NULL); @@ -1309,7 +1492,7 @@ fields, ok_text, ok_cb, cancel_text, cancel_cb, account, who, conv, - user_data); + ui_hint, user_data); handles = g_list_append(handles, info); @@ -1326,6 +1509,17 @@ PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data) { + return purple_request_file_with_hint( + handle, title, filename, savedialog, ok_cb, cancel_cb, account, who, conv, PURPLE_REQUEST_UI_HINT_BLIST, user_data); +} + +void * +purple_request_file_with_hint(void *handle, const char *title, const char *filename, + gboolean savedialog, + GCallback ok_cb, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data) +{ PurpleRequestUiOps *ops; ops = purple_request_get_ui_ops(); @@ -1338,7 +1532,7 @@ info->handle = handle; info->ui_handle = ops->request_file(title, filename, savedialog, ok_cb, cancel_cb, - account, who, conv, user_data); + account, who, conv, ui_hint, user_data); handles = g_list_append(handles, info); return info->ui_handle; } @@ -1352,6 +1546,16 @@ PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data) { + return purple_request_folder_with_hint( + handle, title, dirname, ok_cb, cancel_cb, account, who, conv, PURPLE_REQUEST_UI_HINT_BLIST, user_data); +} + +void * +purple_request_folder_with_hint(void *handle, const char *title, const char *dirname, + GCallback ok_cb, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data) +{ PurpleRequestUiOps *ops; ops = purple_request_get_ui_ops(); @@ -1365,7 +1569,7 @@ info->ui_handle = ops->request_folder(title, dirname, ok_cb, cancel_cb, account, who, conv, - user_data); + ui_hint, user_data); handles = g_list_append(handles, info); return info->ui_handle; } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/request.h --- a/libpurple/request.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/request.h Thu Oct 18 17:58:40 2007 +0000 @@ -61,7 +61,8 @@ PURPLE_REQUEST_FIELD_LIST, PURPLE_REQUEST_FIELD_LABEL, PURPLE_REQUEST_FIELD_IMAGE, - PURPLE_REQUEST_FIELD_ACCOUNT + PURPLE_REQUEST_FIELD_ACCOUNT, + PURPLE_REQUEST_FIELD_BLIST, } PurpleRequestFieldType; @@ -94,6 +95,17 @@ } PurpleRequestFieldGroup; /** + * Flags that can be used for Buddylist Fields. + */ +typedef enum +{ + PURPLE_REQUEST_BLIST_FLAG_BUDDY = 0x01, /**< Include buddies in the list. */ + PURPLE_REQUEST_BLIST_FLAG_CHAT = 0x02, /**< Include chats in the list. */ + PURPLE_REQUEST_BLIST_FLAG_GROUP = 0x04, /**< Include groups in the list. */ + PURPLE_REQUEST_BLIST_FLAG_ALLOW_OFFLINE = 0x08, /**< Include offline buddies in the list. */ +} PurpleRequestBlistFlags; + +/** * A request field. */ typedef struct @@ -172,12 +184,91 @@ gsize size; } image; + struct + { + GList *default_nodes; + PurpleRequestBlistFlags flags; + GList *selecteds; + PurpleFilterBlistFunc filter; + } blist; + } u; void *ui_data; } PurpleRequestField; +/* + * UI hints for the request functions. These are used by libpurple. + */ + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_ACCOUNT "account" + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_BLIST "blist" + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_BUDDY "buddy" + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_CONV "conversation" + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_REGISTER "register-account" + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_XFER "xfer" + + +/* + * UI hints for the request functions. These are common hints used by UIs. + * UIs can still define any hints they like, but standardization is good. + */ + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_ACCOUNTMGR "accountmgr" + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_CERTMGR "certmgr" + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_PLUGINMGR "pluginmgr" + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_POUNCEMGR "pouncemgr" + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_PREFSMGR "preferences" + +/** + * @since 2.3.0 + */ +#define PURPLE_REQUEST_UI_HINT_STATUSMGR "statusmgr" + + /** * Request UI operations. */ @@ -189,33 +280,33 @@ const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); + const char *ui_hint, void *user_data); void *(*request_choice)(const char *title, const char *primary, const char *secondary, int default_value, const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, va_list choices); + const char *ui_hint, void *user_data, va_list choices); void *(*request_action)(const char *title, const char *primary, const char *secondary, int default_action, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, size_t action_count, + const char *ui_hint, void *user_data, size_t action_count, va_list actions); void *(*request_fields)(const char *title, const char *primary, const char *secondary, PurpleRequestFields *fields, const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); + const char *ui_hint, void *user_data); void *(*request_file)(const char *title, const char *filename, gboolean savedialog, GCallback ok_cb, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); + const char *ui_hint, void *user_data); void (*close_request)(PurpleRequestType type, void *ui_handle); void *(*request_folder)(const char *title, const char *dirname, GCallback ok_cb, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); + const char *ui_hint, void *user_data); void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); @@ -1151,6 +1242,98 @@ /*@}*/ /**************************************************************************/ +/** @name Buddylist Field API */ +/**************************************************************************/ +/*@{*/ + +/** + * Creates a buddylist field. + * + * @param id The field ID. + * @param text The label for the field. + * @param flag Flags dictating what kind of blist nodes should be + * included in the request field. + * @param selected A list of PurpleBlistNode's to select by default, or @c NULL. + * + * @return The new field. + * + * @since 2.3.0 + */ +PurpleRequestField *purple_request_field_blist_nodes_new(const char *id, const char *text, + PurpleRequestBlistFlags flag, GList *selected); + +/** + * Set a filter for the request field. + * + * @param field The request field. + * @param filter The filter function. + * + * @return The old filter function, or @c NULL if there was none. + * + * @since 2.3.0 + */ +PurpleFilterBlistFunc purple_request_field_blist_set_filter(PurpleRequestField *field, PurpleFilterBlistFunc filter); + +/** + * Get the filter function for the request field. + * + * @param field The request field. + * + * @return The filter function, or @c NULL if there isn't any. + * + * @since 2.3.0 + */ +PurpleFilterBlistFunc purple_request_field_blist_get_filter(const PurpleRequestField *field); + +/** + * Add a PurpleBlistNode to the selected list. + * + * @param field The request field. + * @param node The buddylist node to add to the list. + * + * @return @c TRUE if the node is added to the list, @c FALSE if it was already in the list. + * + * @since 2.3.0 + */ +gboolean purple_request_field_blist_add(PurpleRequestField *field, PurpleBlistNode *node); + +/** + * Remove a PurpleBlistNode from the selected list. + * + * @param field The request field. + * @param node The buddylist node to remove from the list. + * + * @return @c TRUE if the node is removed from the list, @c FALSE if the node is not in the list. + * + * @since 2.3.0 + */ +gboolean purple_request_field_blist_remove(PurpleRequestField *field, PurpleBlistNode *node); + +/** + * Set the list of selected nodes in the request field. + * + * @param field The request field. + * @param selecteds The list of selected PurpleBlistNode's. Note that the request field + * becomes the owner of the list, and so the caller should not modify it. + * + * @since 2.3.0 + */ +void purple_request_field_blist_set_selection_list(PurpleRequestField *field, GList *selecteds); + +/** + * Get a list of the selected buddylist nodes. + * + * @param field The request field. + * + * @return A GList of PurpleBlistNode's. + * + * @since 2.3.0 + */ +GList *purple_request_field_blist_get_selection_list(const PurpleRequestField *field); + +/*@}*/ + +/**************************************************************************/ /** @name Request API */ /**************************************************************************/ /*@{*/ @@ -1187,9 +1370,60 @@ * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param ui_hint UI hint * @param user_data The data to pass to the callback. * * @return A UI-specific handle. + * + * @since 2.3.0 + */ +void *purple_request_input_with_hint(void *handle, const char *title, + const char *primary, const char *secondary, + const char *default_value, + gboolean multiline, gboolean masked, gchar *hint, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * Prompts the user for text input. + * + * @param handle The plugin or connection handle. For some + * things this is EXTREMELY important. The + * handle is used to programmatically close + * the request dialog when it is no longer + * needed. For PRPLs this is often a pointer + * to the PurpleConnection instance. For plugins + * this should be a similar, unique memory + * location. This value is important because + * it allows a request to be closed, say, when + * you sign offline. If the request is NOT + * closed it is VERY likely to cause a crash + * whenever the callback handler functions are + * triggered. + * @param title The title of the message. + * @param primary The main point of the message. + * @param secondary The secondary information. + * @param default_value The default value. + * @param multiline TRUE if the inputted text can span multiple lines. + * @param masked TRUE if the inputted text should be masked in some way. + * @param hint Optionally suggest how the input box should appear. + * Use "html," for example, to allow the user to enter + * HTML. + * @param ok_text The text for the @c OK button. + * @param ok_cb The callback for the @c OK button. + * @param cancel_text The text for the @c Cancel button. + * @param cancel_cb The callback for the @c Cancel button. + * @param account The PurpleAccount associated with this request, or NULL if none is + * @param who The username of the buddy assocaited with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param user_data The data to pass to the callback. + * + * @return A UI-specific handle. + * + * @deprecated Please use purple_request_input_with_hint() instead. */ void *purple_request_input(void *handle, const char *title, const char *primary, const char *secondary, @@ -1199,6 +1433,7 @@ const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data); +#endif /** * Prompts the user for multiple-choice input. @@ -1217,11 +1452,48 @@ * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param ui_hint UI hint + * @param user_data The data to pass to the callback. + * @param ... The choices. This argument list should be + * terminated with a NULL parameter. + * + * @return A UI-specific handle. + * + * @since 2.3.0 + */ +void *purple_request_choice_with_hint(void *handle, const char *title, + const char *primary, const char *secondary, + int default_value, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data, ...) G_GNUC_NULL_TERMINATED; + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * Prompts the user for multiple-choice input. + * + * @param handle The plugin or connection handle. For some + * things this is EXTREMELY important. See + * the comments on purple_request_input. + * @param title The title of the message. + * @param primary The main point of the message. + * @param secondary The secondary information. + * @param default_value The default value. + * @param ok_text The text for the @c OK button. + * @param ok_cb The callback for the @c OK button. + * @param cancel_text The text for the @c Cancel button. + * @param cancel_cb The callback for the @c Cancel button. + * @param account The PurpleAccount associated with this request, or NULL if none is + * @param who The username of the buddy assocaited with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * @param ... The choices. This argument list should be * terminated with a NULL parameter. * * @return A UI-specific handle. + * + * @deprecated Please use purple_request_choice_with_hint() instead. */ void *purple_request_choice(void *handle, const char *title, const char *primary, const char *secondary, @@ -1230,6 +1502,7 @@ const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, ...) G_GNUC_NULL_TERMINATED; +#endif /** * Prompts the user for multiple-choice input. @@ -1248,11 +1521,48 @@ * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param ui_hint UI hint + * @param user_data The data to pass to the callback. + * @param choices The choices. This argument list should be + * terminated with a @c NULL parameter. + * + * @return A UI-specific handle. + * + * @since 2.3.0 + */ +void *purple_request_choice_varg_with_hint(void *handle, const char *title, + const char *primary, const char *secondary, + int default_value, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data, va_list choices); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * Prompts the user for multiple-choice input. + * + * @param handle The plugin or connection handle. For some + * things this is EXTREMELY important. See + * the comments on purple_request_input. + * @param title The title of the message. + * @param primary The main point of the message. + * @param secondary The secondary information. + * @param default_value The default value. + * @param ok_text The text for the @c OK button. + * @param ok_cb The callback for the @c OK button. + * @param cancel_text The text for the @c Cancel button. + * @param cancel_cb The callback for the @c Cancel button. + * @param account The PurpleAccount associated with this request, or NULL if none is + * @param who The username of the buddy assocaited with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * @param choices The choices. This argument list should be * terminated with a @c NULL parameter. * * @return A UI-specific handle. + * + * @deprecated Please use purple_request_choice_varg_with_hint() instead. */ void *purple_request_choice_varg(void *handle, const char *title, const char *primary, const char *secondary, @@ -1261,6 +1571,7 @@ const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, va_list choices); +#endif /** * Prompts the user for an action. @@ -1277,6 +1588,43 @@ * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param ui_hint UI hint + * @param user_data The data to pass to the callback. + * @param action_count The number of actions. + * @param ... A list of actions. These are pairs of + * arguments. The first of each pair is the + * string that appears on the button. It should + * have an underscore before the letter you want + * to use as the accelerator key for the button. + * The second of each pair is the callback + * function to use when the button is clicked. + * + * @return A UI-specific handle. + * + * @since 2.3.0 + */ +void *purple_request_action_with_hint(void *handle, const char *title, + const char *primary, const char *secondary, + int default_action, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data, size_t action_count, ...); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * Prompts the user for an action. + * + * This is often represented as a dialog with a button for each action. + * + * @param handle The plugin or connection handle. For some + * things this is EXTREMELY important. See + * the comments on purple_request_input. + * @param title The title of the message. + * @param primary The main point of the message. + * @param secondary The secondary information. + * @param default_action The default value. + * @param account The PurpleAccount associated with this request, or NULL if none is + * @param who The username of the buddy assocaited with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * @param action_count The number of actions. * @param ... A list of actions. These are pairs of @@ -1288,12 +1636,15 @@ * function to use when the button is clicked. * * @return A UI-specific handle. + * + * @deprecated Please use purple_request_action_with_hint() instead. */ void *purple_request_action(void *handle, const char *title, const char *primary, const char *secondary, int default_action, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, size_t action_count, ...); +#endif /** * Prompts the user for an action. @@ -1310,11 +1661,45 @@ * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param ui_hint UI hint + * @param user_data The data to pass to the callback. + * @param action_count The number of actions. + * @param actions A list of actions and callbacks. + * + * @return A UI-specific handle. + * + * @since 2.3.0 + */ +void *purple_request_action_varg_with_hint(void *handle, const char *title, + const char *primary, const char *secondary, + int default_action, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data, size_t action_count, + va_list actions); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * Prompts the user for an action. + * + * This is often represented as a dialog with a button for each action. + * + * @param handle The plugin or connection handle. For some + * things this is EXTREMELY important. See + * the comments on purple_request_input. + * @param title The title of the message. + * @param primary The main point of the message. + * @param secondary The secondary information. + * @param default_action The default value. + * @param account The PurpleAccount associated with this request, or NULL if none is + * @param who The username of the buddy assocaited with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * @param action_count The number of actions. * @param actions A list of actions and callbacks. * * @return A UI-specific handle. + * + * @deprecated Please use purple_request_action_varg_with_hint() instead. */ void *purple_request_action_varg(void *handle, const char *title, const char *primary, const char *secondary, @@ -1322,6 +1707,7 @@ PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, size_t action_count, va_list actions); +#endif /** * Displays groups of fields for the user to fill in. @@ -1340,9 +1726,44 @@ * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy associated with this request, or NULL if none is * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param ui_hint UI hint + * @param user_data The data to pass to the callback. + * + * @return A UI-specific handle. + * + * @since 2.3.0 + */ +void *purple_request_fields_with_hint(void *handle, const char *title, + const char *primary, const char *secondary, + PurpleRequestFields *fields, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * Displays groups of fields for the user to fill in. + * + * @param handle The plugin or connection handle. For some + * things this is EXTREMELY important. See + * the comments on purple_request_input. + * @param title The title of the message. + * @param primary The main point of the message. + * @param secondary The secondary information. + * @param fields The list of fields. + * @param ok_text The text for the @c OK button. + * @param ok_cb The callback for the @c OK button. + * @param cancel_text The text for the @c Cancel button. + * @param cancel_cb The callback for the @c Cancel button. + * @param account The PurpleAccount associated with this request, or NULL if none is + * @param who The username of the buddy associated with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * * @return A UI-specific handle. + * + * @deprecated Please use purple_request_fields_with_hint() instead. */ void *purple_request_fields(void *handle, const char *title, const char *primary, const char *secondary, @@ -1351,6 +1772,7 @@ const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data); +#endif /** * Closes a request. @@ -1369,6 +1791,21 @@ /** * A wrapper for purple_request_action() that uses @c Yes and @c No buttons. + * + * @since 2.3.0 + */ +#define purple_request_yes_no_with_hint(handle, title, primary, secondary, \ + default_action, account, who, conv, \ + ui_hint, user_data, yes_cb, no_cb) \ + purple_request_action_with_hint((handle), (title), (primary), (secondary), \ + (default_action), account, who, conv, (ui_hint), (user_data), 2, \ + _("_Yes"), (yes_cb), _("_No"), (no_cb)) + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * A wrapper for purple_request_action() that uses @c Yes and @c No buttons. + * + * @deprecated Please use purple_request_yes_no_with_hint instead. */ #define purple_request_yes_no(handle, title, primary, secondary, \ default_action, account, who, conv, \ @@ -1376,9 +1813,25 @@ purple_request_action((handle), (title), (primary), (secondary), \ (default_action), account, who, conv, (user_data), 2, \ _("_Yes"), (yes_cb), _("_No"), (no_cb)) +#endif /** * A wrapper for purple_request_action() that uses @c OK and @c Cancel buttons. + * + * @since 2.3.0 + */ +#define purple_request_ok_cancel_with_hint(handle, title, primary, secondary, \ + default_action, account, who, conv, \ + ui_hint, user_data, ok_cb, cancel_cb) \ + purple_request_action_with_hint((handle), (title), (primary), (secondary), \ + (default_action), account, who, conv, (ui_hint), (user_data), 2, \ + _("_OK"), (ok_cb), _("_Cancel"), (cancel_cb)) + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * A wrapper for purple_request_action() that uses @c OK and @c Cancel buttons. + * + * @deprecated Please use purple_request_ok_cancel_with_hint instead. */ #define purple_request_ok_cancel(handle, title, primary, secondary, \ default_action, account, who, conv, \ @@ -1386,9 +1839,25 @@ purple_request_action((handle), (title), (primary), (secondary), \ (default_action), account, who, conv, (user_data), 2, \ _("_OK"), (ok_cb), _("_Cancel"), (cancel_cb)) +#endif /** * A wrapper for purple_request_action() that uses Accept and Cancel buttons. + * + * @since 2.3.0 + */ +#define purple_request_accept_cancel_with_hint(handle, title, primary, secondary, \ + default_action, account, who, conv, \ + ui_hint, user_data, accept_cb, cancel_cb) \ + purple_request_action_with_hint((handle), (title), (primary), (secondary), \ + (default_action), account, who, conv, (ui_hint), (user_data), 2, \ + _("_Accept"), (accept_cb), _("_Cancel"), (cancel_cb)) + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * A wrapper for purple_request_action() that uses Accept and Cancel buttons. + * + * @deprecated Please use purple_request_accept_cancel_with_hint instead. */ #define purple_request_accept_cancel(handle, title, primary, secondary, \ default_action, account, who, conv, \ @@ -1396,6 +1865,7 @@ purple_request_action((handle), (title), (primary), (secondary), \ (default_action), account, who, conv, (user_data), 2, \ _("_Accept"), (accept_cb), _("_Cancel"), (cancel_cb)) +#endif /** * Displays a file selector request dialog. Returns the selected filename to @@ -1413,15 +1883,48 @@ * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param ui_hint UI hint + * @param user_data The data to pass to the callback. + * + * @return A UI-specific handle. + * + * @since 2.3.0 + */ +void *purple_request_file_with_hint(void *handle, const char *title, const char *filename, + gboolean savedialog, + GCallback ok_cb, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * Displays a file selector request dialog. Returns the selected filename to + * the callback. Can be used for either opening a file or saving a file. + * + * @param handle The plugin or connection handle. For some + * things this is EXTREMELY important. See + * the comments on purple_request_input. + * @param title The title for the dialog (may be @c NULL) + * @param filename The default filename (may be @c NULL) + * @param savedialog True if this dialog is being used to save a file. + * False if it is being used to open a file. + * @param ok_cb The callback for the @c OK button. + * @param cancel_cb The callback for the @c Cancel button. + * @param account The PurpleAccount associated with this request, or NULL if none is + * @param who The username of the buddy assocaited with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * * @return A UI-specific handle. + * + * @deprecated Please use purple_request_file_with_hint() instead. */ void *purple_request_file(void *handle, const char *title, const char *filename, gboolean savedialog, GCallback ok_cb, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data); +#endif /** * Displays a folder select dialog. Returns the selected filename to @@ -1437,14 +1940,44 @@ * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param ui_hint UI hint + * @param user_data The data to pass to the callback. + * + * @return A UI-specific handle. + * + * @since 2.3.0 + */ +void *purple_request_folder_with_hint(void *handle, const char *title, const char *dirname, + GCallback ok_cb, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + const char *ui_hint, void *user_data); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * Displays a folder select dialog. Returns the selected filename to + * the callback. + * + * @param handle The plugin or connection handle. For some + * things this is EXTREMELY important. See + * the comments on purple_request_input. + * @param title The title for the dialog (may be @c NULL) + * @param dirname The default directory name (may be @c NULL) + * @param ok_cb The callback for the @c OK button. + * @param cancel_cb The callback for the @c Cancel button. + * @param account The PurpleAccount associated with this request, or NULL if none is + * @param who The username of the buddy assocaited with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * * @return A UI-specific handle. + * + * @deprecated Please use purple_request_folder_with_hint() instead. */ void *purple_request_folder(void *handle, const char *title, const char *dirname, GCallback ok_cb, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data); +#endif /*@}*/ diff -r 33822d7271e5 -r 8b9c48347004 libpurple/server.c --- a/libpurple/server.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/server.c Thu Oct 18 17:58:40 2007 +0000 @@ -799,9 +799,9 @@ who, purple_account_get_username(account), name); - purple_request_accept_cancel(gc, NULL, _("Accept chat invitation?"), buf2, + purple_request_accept_cancel_with_hint(gc, NULL, _("Accept chat invitation?"), buf2, PURPLE_DEFAULT_ACTION_NONE, account, who, NULL, - cid, G_CALLBACK(chat_invite_accept), + "chat", cid, G_CALLBACK(chat_invite_accept), G_CALLBACK(chat_invite_reject)); } else if (plugin_return > 0) diff -r 33822d7271e5 -r 8b9c48347004 libpurple/signals.c --- a/libpurple/signals.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/signals.c Thu Oct 18 17:58:40 2007 +0000 @@ -794,6 +794,19 @@ *return_val = GINT_TO_POINTER(ret_val); } +void +purple_marshal_INT__POINTER_POINTER(PurpleCallback cb, va_list args, void *data, + void **return_val) +{ + gint ret_val; + void *arg1 = va_arg(args, void *); + void *arg2 = va_arg(args, void *); + + ret_val = ((gint (*)(void *, void *, void *))cb)(arg1, arg2, data); + + if (return_val != NULL) + *return_val = GINT_TO_POINTER(ret_val); +} void purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER( diff -r 33822d7271e5 -r 8b9c48347004 libpurple/signals.h --- a/libpurple/signals.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/signals.h Thu Oct 18 17:58:40 2007 +0000 @@ -307,6 +307,8 @@ PurpleCallback cb, va_list args, void *data, void **return_val); void purple_marshal_INT__INT_INT( PurpleCallback cb, va_list args, void *data, void **return_val); +void purple_marshal_INT__POINTER_POINTER( + PurpleCallback cb, va_list args, void *data, void **return_val); void purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER( PurpleCallback cb, va_list args, void *data, void **return_val); diff -r 33822d7271e5 -r 8b9c48347004 libpurple/sslconn.h --- a/libpurple/sslconn.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/sslconn.h Thu Oct 18 17:58:40 2007 +0000 @@ -185,6 +185,7 @@ PurpleSslErrorFunction error_func, void *data); +#ifndef PURPLE_DISABLE_DEPRECATED /** * Makes a SSL connection using an already open file descriptor. * @@ -202,6 +203,7 @@ PurpleSslInputFunction func, PurpleSslErrorFunction error_func, void *data); +#endif /** * Makes a SSL connection using an already open file descriptor. diff -r 33822d7271e5 -r 8b9c48347004 libpurple/status.c --- a/libpurple/status.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/status.c Thu Oct 18 17:58:40 2007 +0000 @@ -157,7 +157,8 @@ { PURPLE_STATUS_INVISIBLE, "invisible", N_("Invisible") }, { PURPLE_STATUS_AWAY, "away", N_("Away") }, { PURPLE_STATUS_EXTENDED_AWAY, "extended_away", N_("Extended away") }, - { PURPLE_STATUS_MOBILE, "mobile", N_("Mobile") } + { PURPLE_STATUS_MOBILE, "mobile", N_("Mobile") }, + { PURPLE_STATUS_TUNE, "tune", N_("Listening to music") } }; const char * @@ -903,6 +904,8 @@ } g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_STRING); + /* XXX: Check if the value has actually changed. If it has, and the status + * is active, should this trigger 'status_has_changed'? */ purple_value_set_string(attr_value, value); } diff -r 33822d7271e5 -r 8b9c48347004 libpurple/status.h --- a/libpurple/status.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/status.h Thu Oct 18 17:58:40 2007 +0000 @@ -94,6 +94,10 @@ /** * A primitive defining the basic structure of a status type. */ +/* + * If you add a value to this enum, make sure you update + * the status_primitive_map array in status.c. + */ typedef enum { PURPLE_STATUS_UNSET = 0, @@ -104,6 +108,7 @@ PURPLE_STATUS_AWAY, PURPLE_STATUS_EXTENDED_AWAY, PURPLE_STATUS_MOBILE, + PURPLE_STATUS_TUNE, PURPLE_STATUS_NUM_PRIMITIVES } PurpleStatusPrimitive; diff -r 33822d7271e5 -r 8b9c48347004 libpurple/util.c --- a/libpurple/util.c Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/util.c Thu Oct 18 17:58:40 2007 +0000 @@ -70,6 +70,7 @@ static char *custom_user_dir = NULL; static char *user_dir = NULL; + PurpleMenuAction * purple_menu_action_new(const char *label, PurpleCallback callback, gpointer data, GList *children) @@ -91,6 +92,25 @@ g_free(act); } +void +purple_util_init(void) +{ + /* This does nothing right now. It exists for symmetry with + * purple_util_uninit() and forwards compatibility. */ +} + +void +purple_util_uninit(void) +{ + /* Free these so we don't have leaks at shutdown. */ + + g_free(custom_user_dir); + custom_user_dir = NULL; + + g_free(user_dir); + user_dir = NULL; +} + /************************************************************************** * Base16 Functions **************************************************************************/ @@ -2565,6 +2585,8 @@ purple_debug_info("util", "Writing file %s\n", filename_full); + g_return_val_if_fail((size >= -1), FALSE); + filename_temp = g_strdup_printf("%s.save", filename_full); /* Remove an old temporary file, if one exists */ @@ -2590,7 +2612,7 @@ } /* Write to file */ - real_size = (size == -1) ? strlen(data) : size; + real_size = (size == -1) ? strlen(data) : (size_t) size; byteswritten = fwrite(data, 1, real_size, file); /* Close file */ diff -r 33822d7271e5 -r 8b9c48347004 libpurple/util.h --- a/libpurple/util.h Fri Oct 12 17:10:34 2007 +0000 +++ b/libpurple/util.h Thu Oct 18 17:58:40 2007 +0000 @@ -86,6 +86,27 @@ void purple_menu_action_free(PurpleMenuAction *act); /**************************************************************************/ +/** @name Utility Subsystem */ +/**************************************************************************/ +/*@{*/ + +/** + * Initializes the utility subsystem. + * + * @since 2.3.0 + */ +void purple_util_init(void); + +/** + * Uninitializes the util subsystem. + * + * @since 2.3.0 + */ +void purple_util_uninit(void); + +/*@}*/ + +/**************************************************************************/ /** @name Base16 Functions */ /**************************************************************************/ /*@{*/ diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkaccount.c --- a/pidgin/gtkaccount.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkaccount.c Thu Oct 18 17:58:40 2007 +0000 @@ -1902,9 +1902,9 @@ purple_account_get_username(account)); purple_request_close_with_handle(account); - purple_request_action(account, NULL, buf, NULL, 0, + purple_request_action_with_hint(account, NULL, buf, NULL, 0, account, NULL, NULL, - account, 2, + PURPLE_REQUEST_UI_HINT_ACCOUNTMGR, account, 2, _("Delete"), delete_account_cb, _("Cancel"), NULL); g_free(buf); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkblist.c --- a/pidgin/gtkblist.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkblist.c Thu Oct 18 17:58:40 2007 +0000 @@ -522,9 +522,9 @@ if (i > 1) { char *msg = g_strdup_printf(ngettext("You have %d contact named %s. Would you like to merge them?", "You currently have %d contacts named %s. Would you like to merge them?", i), i, alias); - purple_request_action(NULL, NULL, msg, _("Merging these contacts will cause them to share a single entry on the buddy list and use a single conversation window. " + purple_request_action_with_hint(NULL, NULL, msg, _("Merging these contacts will cause them to share a single entry on the buddy list and use a single conversation window. " "You can separate them again by choosing 'Expand' from the contact's context menu"), 0, NULL, NULL, NULL, - merges, 2, _("_Merge"), PURPLE_CALLBACK(gtk_blist_do_personize), _("_Cancel"), PURPLE_CALLBACK(g_list_free)); + PURPLE_REQUEST_UI_HINT_BLIST, merges, 2, _("_Merge"), PURPLE_CALLBACK(gtk_blist_do_personize), _("_Cancel"), PURPLE_CALLBACK(g_list_free)); g_free(msg); } else g_list_free(merges); @@ -617,7 +617,7 @@ static void gtk_blist_menu_bp_cb(GtkWidget *w, PurpleBuddy *b) { - pidgin_pounce_editor_show(b->account, b->name, NULL); + pidgin_pounce_editor_show_with_parent(GTK_WINDOW(gtkblist->window), b->account, b->name, NULL); } static void gtk_blist_menu_showlog_cb(GtkWidget *w, PurpleBlistNode *node) @@ -643,7 +643,7 @@ name = prpl_info->get_chat_name(c->components); } } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { - pidgin_log_show_contact((PurpleContact *)node); + pidgin_log_show_contact_with_parent(GTK_WINDOW(gtkblist->window), (PurpleContact *)node); pidgin_clear_cursor(gtkblist->window); return; } else { @@ -655,7 +655,7 @@ } if (name && account) { - pidgin_log_show(type, name, account); + pidgin_log_show_with_parent(GTK_WINDOW(gtkblist->window), type, name, account); g_free(name); pidgin_clear_cursor(gtkblist->window); @@ -682,11 +682,6 @@ pidgin_blist_update(purple_get_blist(), node); } -static void gtk_blist_show_systemlog_cb() -{ - pidgin_syslog_show(); -} - static void gtk_blist_show_onlinehelp_cb() { purple_notify_uri(NULL, PURPLE_WEBSITE "documentation"); @@ -3057,6 +3052,11 @@ !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/enabled")); } +static void +pidgin_blist_show_with_parent(gpointer data1, void (*callback)(GtkWindow *parent), gpointer data3) +{ + callback(GTK_WINDOW(gtkblist->window)); +} /*************************************************** * Crap * @@ -3090,15 +3090,15 @@ /* Tools */ { N_("/_Tools"), NULL, NULL, 0, "", NULL }, - { N_("/Tools/Buddy _Pounces"), NULL, pidgin_pounces_manager_show, 0, "", NULL }, + { N_("/Tools/Buddy _Pounces"), NULL, pidgin_blist_show_with_parent, (int)pidgin_pounces_manager_show_with_parent, "", NULL }, { N_("/Tools/_Certificates"), NULL, pidgin_certmgr_show, 0, "", NULL }, - { N_("/Tools/Plu_gins"), "U", pidgin_plugin_dialog_show, 0, "", PIDGIN_STOCK_TOOLBAR_PLUGINS }, + { N_("/Tools/Plu_gins"), "U", pidgin_blist_show_with_parent, (int)pidgin_plugin_dialog_show_with_parent, "", PIDGIN_STOCK_TOOLBAR_PLUGINS }, { N_("/Tools/Pr_eferences"), "P", pidgin_prefs_show, 0, "", GTK_STOCK_PREFERENCES }, { N_("/Tools/Pr_ivacy"), NULL, pidgin_privacy_dialog_show, 0, "", NULL }, { "/Tools/sep2", NULL, NULL, 0, "", NULL }, { N_("/Tools/_File Transfers"), "T", pidgin_xfer_dialog_show, 0, "", NULL }, { N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "", NULL }, - { N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, "", NULL }, + { N_("/Tools/System _Log"), NULL, pidgin_blist_show_with_parent, (int)pidgin_syslog_show_with_parent, "", NULL }, { "/Tools/sep3", NULL, NULL, 0, "", NULL }, { N_("/Tools/Mute _Sounds"), "S", pidgin_blist_mute_sounds_cb, 0, "", NULL }, /* Help */ @@ -3106,9 +3106,9 @@ { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "", GTK_STOCK_HELP }, { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "", NULL }, #if GTK_CHECK_VERSION(2,6,0) - { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "", GTK_STOCK_ABOUT }, + { N_("/Help/_About"), NULL, pidgin_blist_show_with_parent, (int)pidgin_dialogs_about_with_parent, "", GTK_STOCK_ABOUT }, #else - { N_("/Help/_About"), NULL, pidgin_dialogs_about, 0, "", NULL }, + { N_("/Help/_About"), NULL, pidgin_blist_show_with_parent, (int)pidgin_dialogs_about_with_parent, "", NULL }, #endif }; @@ -3384,7 +3384,7 @@ return ret; } - if (purple_status_get_attr_string(purple_presence_get_active_status(p), PURPLE_TUNE_TITLE)) { + if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_TUNE)) { path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "music.png", NULL); ret = gdk_pixbuf_new_from_file(path, NULL); g_free(path); @@ -4323,9 +4323,9 @@ text = g_hash_table_lookup(gtkblist->connection_errors, account); enabled = purple_account_get_enabled(account, purple_core_get_ui()); - purple_request_action(account, _("Connection Error"), primary, text, 2, + purple_request_action_with_hint(account, _("Connection Error"), primary, text, 2, account, NULL, NULL, - account, 3, + PURPLE_REQUEST_UI_HINT_ACCOUNT, account, 3, _("OK"), NULL, _("Modify Account"), PURPLE_CALLBACK(ce_modify_account_cb), enabled ? _("Connect") : _("Re-enable Account"), @@ -5787,11 +5787,13 @@ gtkblist = PIDGIN_BLIST(purple_get_blist()); data->window = gtk_dialog_new_with_buttons(_("Add Buddy"), - NULL, GTK_DIALOG_NO_SEPARATOR, + gtkblist ? GTK_WINDOW(gtkblist->window) : NULL, GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_ADD, GTK_RESPONSE_OK, NULL); + if (gtkblist) + gtk_window_set_transient_for(GTK_WINDOW(data->window), GTK_WINDOW(gtkblist->window)); gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); gtk_container_set_border_width(GTK_CONTAINER(data->window), PIDGIN_HIG_BOX_SPACE); gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); @@ -6169,11 +6171,13 @@ data->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); data->window = gtk_dialog_new_with_buttons(_("Add Chat"), - NULL, GTK_DIALOG_NO_SEPARATOR, + gtkblist ? GTK_WINDOW(gtkblist->window) : NULL, GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_ADD, GTK_RESPONSE_OK, NULL); + if (gtkblist) + gtk_window_set_transient_for(GTK_WINDOW(data->window), GTK_WINDOW(gtkblist->window)); gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); gtk_container_set_border_width(GTK_CONTAINER(data->window), PIDGIN_HIG_BOX_SPACE); gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); @@ -6277,13 +6281,13 @@ static void pidgin_blist_request_add_group(void) { - purple_request_input(NULL, _("Add Group"), NULL, + purple_request_input_with_hint(NULL, _("Add Group"), NULL, _("Please enter the name of the group to be added."), NULL, FALSE, FALSE, NULL, _("Add"), G_CALLBACK(add_group_cb), _("Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_BLIST, NULL); } void diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkcertmgr.c --- a/pidgin/gtkcertmgr.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkcertmgr.c Thu Oct 18 17:58:40 2007 +0000 @@ -184,7 +184,7 @@ if the window gets closed unusually, such as by handle deletion */ /* TODO: Display some more information on the certificate? */ - purple_request_input(tpm_dat, + purple_request_input_with_hint(tpm_dat, _("Certificate Import"), _("Specify a hostname"), _("Type the host name this certificate is for."), @@ -197,7 +197,7 @@ _("Cancel"), G_CALLBACK(tls_peers_mgmt_import_cancel2_cb), NULL, NULL, NULL, /* No account/who/conv*/ - crt /* Pass cert instance to callback*/ + PURPLE_REQUEST_UI_HINT_CERTMGR, crt /* Pass cert instance to callback*/ ); g_free(default_hostname); @@ -220,13 +220,13 @@ tls_peers_mgmt_import_cb(GtkWidget *button, gpointer data) { /* TODO: need to tell the user that we want a .PEM file! */ - purple_request_file(tpm_dat, + purple_request_file_with_hint(tpm_dat, _("Select a PEM certificate"), "certificate.pem", FALSE, /* Not a save dialog */ G_CALLBACK(tls_peers_mgmt_import_ok_cb), NULL, /* Do nothing if cancelled */ - NULL, NULL, NULL, NULL );/* No account,conv,etc. */ + NULL, NULL, NULL, PURPLE_REQUEST_UI_HINT_CERTMGR, NULL );/* No account,conv,etc. */ } static void @@ -295,14 +295,14 @@ /* TODO: inform user that it will be a PEM? */ - purple_request_file(tpm_dat, + purple_request_file_with_hint(tpm_dat, _("PEM X.509 Certificate Export"), "certificate.pem", TRUE, /* Is a save dialog */ G_CALLBACK(tls_peers_mgmt_export_ok_cb), G_CALLBACK(tls_peers_mgmt_export_cancel_cb), NULL, NULL, NULL, /* No account,conv,etc. */ - crt); /* Pass the certificate on to the callback */ + PURPLE_REQUEST_UI_HINT_CERTMGR, crt); /* Pass the certificate on to the callback */ } static void @@ -371,10 +371,11 @@ primary = g_strdup_printf( _("Really delete certificate for %s?"), id ); - purple_request_yes_no(tpm_dat, _("Confirm certificate delete"), + purple_request_yes_no_with_hint(tpm_dat, _("Confirm certificate delete"), primary, NULL, /* Can this be NULL? */ 2, /* NO is default action */ NULL, NULL, NULL, + PURPLE_REQUEST_UI_HINT_CERTMGR, id, /* id ownership passed to callback */ tls_peers_mgmt_delete_confirm_cb, tls_peers_mgmt_delete_confirm_cb ); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkconv.c Thu Oct 18 17:58:40 2007 +0000 @@ -1029,11 +1029,11 @@ if (*c == '/' || *c == '\\') *c = ' '; } - purple_request_file(PIDGIN_CONVERSATION(conv), _("Save Conversation"), + purple_request_file_with_hint(PIDGIN_CONVERSATION(conv), _("Save Conversation"), buf, TRUE, G_CALLBACK(savelog_writefile_cb), NULL, NULL, NULL, conv, - conv); + PURPLE_REQUEST_UI_HINT_BLIST, conv); g_free(buf); } @@ -1081,7 +1081,7 @@ PurpleBlistNode *node = cur->data; if ((node != NULL) && ((node->prev != NULL) || (node->next != NULL))) { - pidgin_log_show_contact((PurpleContact *)node->parent); + pidgin_log_show_contact_with_parent(GTK_WINDOW(win->window), (PurpleContact *)node->parent); g_slist_free(buddies); gdk_window_set_cursor(gtkblist->window->window, NULL); gdk_window_set_cursor(win->window->window, NULL); @@ -1090,7 +1090,7 @@ } g_slist_free(buddies); - pidgin_log_show(type, name, account); + pidgin_log_show_with_parent(GTK_WINDOW(win->window), type, name, account); gdk_window_set_cursor(gtkblist->window->window, NULL); gdk_window_set_cursor(win->window->window, NULL); @@ -1236,7 +1236,7 @@ conv = pidgin_conv_window_get_active_gtkconv(win)->active_conv; - pidgin_pounce_editor_show(purple_conversation_get_account(conv), + pidgin_pounce_editor_show_with_parent(GTK_WINDOW(win->window), purple_conversation_get_account(conv), purple_conversation_get_name(conv), NULL); } @@ -2718,10 +2718,10 @@ buf = g_strdup_printf("%s.%s", purple_normalize(conv->account, conv->name), ext); - purple_request_file(gtkconv, _("Save Icon"), buf, TRUE, + purple_request_file_with_hint(gtkconv, _("Save Icon"), buf, TRUE, G_CALLBACK(saveicon_writefile_cb), NULL, conv->account, NULL, conv, - gtkconv); + PURPLE_REQUEST_UI_HINT_BLIST, gtkconv); g_free(buf); } @@ -6519,6 +6519,7 @@ AtkObject *accessibility_obj; /* I think this is a little longer than it needs to be but I'm lazy. */ char *style; + gboolean bold = FALSE; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) im = PURPLE_CONV_IM(conv); @@ -6552,7 +6553,7 @@ gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter), CONV_TEXT_COLUMN, markup, -1); /* XXX seanegan Why do I have to do this? */ - gtk_widget_queue_draw(gtkconv->infopane); + gtk_widget_queue_draw(gtkconv->infopane); if (title != markup) g_free(markup); @@ -6571,31 +6572,41 @@ style = "color=\"#c4a000\""; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) { atk_object_set_description(accessibility_obj, _("Nick Said")); - style = "color=\"#204a87\" weight=\"bold\""; + style = "color=\"#cc0000\""; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) { atk_object_set_description(accessibility_obj, _("Unread Messages")); - style = "color=\"#cc0000\" weight=\"bold\""; + if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_CHAT) + style = "color=\"#204a87\" weight=\"bold\""; + else + style = "color=\"#cc0000\" weight=\"bold\""; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) { atk_object_set_description(accessibility_obj, _("New Event")); - style = "color=\"#888a85\" weight=\"bold\""; + style = "color=\"#888a85\""; } else { - style = ""; - } + style = NULL; + } + + if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT || + gtkconv->unseen_state == PIDGIN_UNSEEN_NICK || + gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) + bold = TRUE; - if (*style != '\0') + if (style || bold) { char *html_title,*label; html_title = g_markup_escape_text(title, -1); - label = g_strdup_printf("%s", - style, html_title); + label = g_strdup_printf("%s", + style ? style : "", + bold ? "weight=\"bold\"" : "", + html_title); g_free(html_title); gtk_label_set_markup(GTK_LABEL(gtkconv->tab_label), label); g_free(label); } else gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), title); - + if (pidgin_conv_window_is_active_conversation(conv)) update_typing_icon(gtkconv); @@ -7397,6 +7408,17 @@ pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); } +/* Message history stuff */ + +/* Compare two PurpleConvMessage's, according to time in ascending order. */ +static int +message_compare(gconstpointer p1, gconstpointer p2) +{ + const PurpleConvMessage *m1 = p1, *m2 = p2; + return (m1->when > m2->when); +} + +/* Adds some message history to the gtkconv. This happens in a idle-callback. */ static gboolean add_message_history_to_gtkconv(gpointer data) { @@ -7404,49 +7426,106 @@ int count = 0; int timer = gtkconv->attach.timer; time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time")); + gboolean im = (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM); gtkconv->attach.timer = 0; while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */ PurpleConvMessage *msg = gtkconv->attach.current->data; - if (when && when < msg->when) { + if (!im && when && when < msg->when) { gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "

", 0); g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); } - pidgin_conv_write_conv(gtkconv->active_conv, msg->who, msg->who, msg->what, msg->flags, msg->when); - gtkconv->attach.current = gtkconv->attach.current->prev; + pidgin_conv_write_conv(msg->conv, msg->who, msg->who, msg->what, msg->flags, msg->when); + if (im) { + gtkconv->attach.current = g_list_delete_link(gtkconv->attach.current, gtkconv->attach.current); + } else { + gtkconv->attach.current = gtkconv->attach.current->prev; + } count++; } gtkconv->attach.timer = timer; if (gtkconv->attach.current) return TRUE; + g_source_remove(gtkconv->attach.timer); + gtkconv->attach.timer = 0; + if (im) { + /* Print any message that was sent while the old history was being added back. */ + GList *msgs = NULL; + GList *iter = gtkconv->convs; + for (; iter; iter = iter->next) { + PurpleConversation *conv = iter->data; + GList *history = purple_conversation_get_message_history(conv); + for (; history; history = history->next) { + PurpleConvMessage *msg = history->data; + if (msg->when > when) + msgs = g_list_prepend(msgs, msg); + } + } + msgs = g_list_sort(msgs, message_compare); + for (; msgs; msgs = g_list_delete_link(msgs, msgs)) { + PurpleConvMessage *msg = msgs->data; + pidgin_conv_write_conv(msg->conv, msg->who, msg->who, msg->what, msg->flags, msg->when); + } + gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "

", 0); + g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); + } + g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); purple_signal_emit(pidgin_conversations_get_handle(), "conversation-displayed", gtkconv); - g_source_remove(gtkconv->attach.timer); - gtkconv->attach.timer = 0; return FALSE; } +static void +pidgin_conv_attach(PurpleConversation *conv) +{ + int timer; + purple_conversation_set_data(conv, "unseen-count", NULL); + purple_conversation_set_ui_ops(conv, pidgin_conversations_get_conv_ui_ops()); + private_gtkconv_new(conv, FALSE); + timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); + if (timer) + purple_timeout_remove(timer); +} + gboolean pidgin_conv_attach_to_conversation(PurpleConversation *conv) { GList *list; PidginConversation *gtkconv; - int timer; if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) return FALSE; - purple_conversation_set_data(conv, "unseen-count", NULL); - purple_conversation_set_ui_ops(conv, pidgin_conversations_get_conv_ui_ops()); - private_gtkconv_new(conv, FALSE); + pidgin_conv_attach(conv); gtkconv = PIDGIN_CONVERSATION(conv); list = purple_conversation_get_message_history(conv); if (list) { + switch (purple_conversation_get_type(conv)) { + case PURPLE_CONV_TYPE_IM: + { + GList *convs; + list = g_list_copy(list); + for (convs = purple_get_ims(); convs; convs = convs->next) + if (convs->data != conv && + pidgin_conv_find_gtkconv(convs->data) == gtkconv) { + pidgin_conv_attach(convs->data); + list = g_list_concat(list, g_list_copy(purple_conversation_get_message_history(convs->data))); + } + list = g_list_sort(list, message_compare); + gtkconv->attach.current = list; + list = g_list_last(list); + break; + } + case PURPLE_CONV_TYPE_CHAT: + gtkconv->attach.current = g_list_last(list); + break; + default: + g_return_val_if_reached(TRUE); + } g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", GINT_TO_POINTER(((PurpleConvMessage*)(list->data))->when)); - gtkconv->attach.current = g_list_last(list); gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv); } else { purple_signal_emit(pidgin_conversations_get_handle(), @@ -7458,9 +7537,6 @@ pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE); } - timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); - if (timer) - purple_timeout_remove(timer); return TRUE; } @@ -9791,3 +9867,4 @@ return colors; } + diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkdebug.c --- a/pidgin/gtkdebug.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkdebug.c Thu Oct 18 17:58:40 2007 +0000 @@ -36,6 +36,7 @@ #include "gtkimhtml.h" #include "gtkutils.h" #include "pidginstock.h" +#include "gtkblist.h" #ifdef HAVE_REGEX_H # include @@ -231,10 +232,10 @@ static void save_cb(GtkWidget *w, DebugWindow *win) { - purple_request_file(win, _("Save Debug Log"), "purple-debug.log", TRUE, + purple_request_file_with_hint(win, _("Save Debug Log"), "purple-debug.log", TRUE, G_CALLBACK(save_writefile_cb), NULL, NULL, NULL, NULL, - win); + PURPLE_REQUEST_UI_HINT_BLIST, win); } static void @@ -673,6 +674,7 @@ static DebugWindow * debug_window_new(void) { + PidginBuddyList *blist; DebugWindow *win; GtkWidget *vbox; GtkWidget *toolbar; @@ -687,6 +689,9 @@ height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/height"); PIDGIN_DIALOG(win->window); + if ((blist = pidgin_blist_get_default_gtk_blist()) != NULL) + if (blist->window) + gtk_window_set_transient_for(GTK_WINDOW(win->window), GTK_WINDOW(blist->window)); purple_debug_info("gtkdebug", "Setting dimensions to %d, %d\n", width, height); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkdialogs.c --- a/pidgin/gtkdialogs.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkdialogs.c Thu Oct 18 17:58:40 2007 +0000 @@ -334,6 +334,13 @@ void pidgin_dialogs_about() { + PidginBuddyList *blist = pidgin_blist_get_default_gtk_blist(); + + pidgin_dialogs_about_with_parent(blist ? GTK_WINDOW(blist->window) : NULL); +} + +void pidgin_dialogs_about_with_parent(GtkWindow *parent) +{ GtkWidget *hbox; GtkWidget *vbox; GtkWidget *logo; @@ -349,11 +356,15 @@ GdkPixbuf *pixbuf; if (about != NULL) { + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(about), parent); gtk_window_present(GTK_WINDOW(about)); return; } PIDGIN_DIALOG(about); + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(about), parent); tmp = g_strdup_printf(_("About %s"), PIDGIN_NAME); gtk_window_set_title(GTK_WINDOW(about), tmp); g_free(tmp); @@ -756,6 +767,10 @@ purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); + field = purple_request_field_blist_nodes_new("blistnodes", _("Buddy"), + PURPLE_REQUEST_BLIST_FLAG_BUDDY, NULL); + purple_request_field_group_add_field(group, field); + field = purple_request_field_account_new("account", _("_Account"), NULL); purple_request_field_set_type_hint(field, "account"); purple_request_field_set_visible(field, @@ -764,7 +779,7 @@ purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("New Instant Message"), + purple_request_fields_with_hint(purple_get_blist(), _("New Instant Message"), NULL, _("Please enter the screen name or alias of the person " "you would like to IM."), @@ -772,7 +787,7 @@ _("OK"), G_CALLBACK(pidgin_dialogs_im_cb), _("Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_BLIST, NULL); } void @@ -903,7 +918,7 @@ purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("Get User Info"), + purple_request_fields_with_hint(purple_get_blist(), _("Get User Info"), NULL, _("Please enter the screen name or alias of the person " "whose info you would like to view."), @@ -911,7 +926,7 @@ _("OK"), G_CALLBACK(pidgin_dialogs_info_cb), _("Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_BLIST, NULL); } static void @@ -939,7 +954,7 @@ PurpleBlistNode *node = cur->data; if ((node != NULL) && ((node->prev != NULL) || (node->next != NULL))) { - pidgin_log_show_contact((PurpleContact *)node->parent); + pidgin_log_show_contact_with_parent(GTK_WINDOW(gtkblist->window), (PurpleContact *)node->parent); g_slist_free(buddies); pidgin_clear_cursor(gtkblist->window); g_free(username); @@ -948,7 +963,7 @@ } g_slist_free(buddies); - pidgin_log_show(PURPLE_LOG_IM, username, account); + pidgin_log_show_with_parent(GTK_WINDOW(gtkblist->window), PURPLE_LOG_IM, username, account); pidgin_clear_cursor(gtkblist->window); } @@ -995,7 +1010,7 @@ purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("View User Log"), + purple_request_fields_with_hint(purple_get_blist(), _("View User Log"), NULL, _("Please enter the screen name or alias of the person " "whose log you would like to view."), @@ -1003,7 +1018,7 @@ _("OK"), G_CALLBACK(pidgin_dialogs_log_cb), _("Cancel"), NULL, NULL, NULL, NULL, - NULL); + PURPLE_REQUEST_UI_HINT_BLIST, NULL); } static void @@ -1017,13 +1032,13 @@ { g_return_if_fail(contact != NULL); - purple_request_input(NULL, _("Alias Contact"), NULL, + purple_request_input_with_hint(NULL, _("Alias Contact"), NULL, _("Enter an alias for this contact."), contact->alias, FALSE, FALSE, NULL, _("Alias"), G_CALLBACK(pidgin_dialogs_alias_contact_cb), _("Cancel"), NULL, NULL, purple_contact_get_alias(contact), NULL, - contact); + PURPLE_REQUEST_UI_HINT_BLIST, contact); } static void @@ -1042,12 +1057,12 @@ secondary = g_strdup_printf(_("Enter an alias for %s."), buddy->name); - purple_request_input(NULL, _("Alias Buddy"), NULL, + purple_request_input_with_hint(NULL, _("Alias Buddy"), NULL, secondary, buddy->alias, FALSE, FALSE, NULL, _("Alias"), G_CALLBACK(pidgin_dialogs_alias_buddy_cb), _("Cancel"), NULL, purple_buddy_get_account(buddy), purple_buddy_get_name(buddy), NULL, - buddy); + PURPLE_REQUEST_UI_HINT_BLIST, buddy); g_free(secondary); } @@ -1063,13 +1078,13 @@ { g_return_if_fail(chat != NULL); - purple_request_input(NULL, _("Alias Chat"), NULL, + purple_request_input_with_hint(NULL, _("Alias Chat"), NULL, _("Enter an alias for this chat."), chat->alias, FALSE, FALSE, NULL, _("Alias"), G_CALLBACK(pidgin_dialogs_alias_chat_cb), _("Cancel"), NULL, chat->account, NULL, NULL, - chat); + PURPLE_REQUEST_UI_HINT_BLIST, chat); } static void @@ -1111,9 +1126,9 @@ "want to continue?", contact->totalsize - 1), buddy->name, contact->totalsize - 1); - purple_request_action(contact, NULL, _("Remove Contact"), text, 0, + purple_request_action_with_hint(contact, NULL, _("Remove Contact"), text, 0, NULL, purple_contact_get_alias(contact), NULL, - contact, 2, + PURPLE_REQUEST_UI_HINT_BLIST, contact, 2, _("_Remove Contact"), G_CALLBACK(pidgin_dialogs_remove_contact_cb), _("Cancel"), NULL); @@ -1152,9 +1167,9 @@ ggp->parent = source; ggp->new_name = g_strdup(new_name); - purple_request_action(source, NULL, _("Merge Groups"), text, 0, + purple_request_action_with_hint(source, NULL, _("Merge Groups"), text, 0, NULL, NULL, NULL, - ggp, 2, + PURPLE_REQUEST_UI_HINT_BLIST, ggp, 2, _("_Merge Groups"), G_CALLBACK(pidgin_dialogs_merge_groups_cb), _("Cancel"), G_CALLBACK(free_ggmo)); @@ -1208,9 +1223,9 @@ text = g_strdup_printf(_("You are about to remove the group %s and all its members from your buddy list. Do you want to continue?"), group->name); - purple_request_action(group, NULL, _("Remove Group"), text, 0, + purple_request_action_with_hint(group, NULL, _("Remove Group"), text, 0, NULL, NULL, NULL, - group, 2, + PURPLE_REQUEST_UI_HINT_BLIST, group, 2, _("_Remove Group"), G_CALLBACK(pidgin_dialogs_remove_group_cb), _("Cancel"), NULL); @@ -1247,9 +1262,9 @@ text = g_strdup_printf(_("You are about to remove %s from your buddy list. Do you want to continue?"), buddy->name); - purple_request_action(buddy, NULL, _("Remove Buddy"), text, 0, + purple_request_action_with_hint(buddy, NULL, _("Remove Buddy"), text, 0, purple_buddy_get_account(buddy), purple_buddy_get_name(buddy), NULL, - buddy, 2, + PURPLE_REQUEST_UI_HINT_BLIST, buddy, 2, _("_Remove Buddy"), G_CALLBACK(pidgin_dialogs_remove_buddy_cb), _("Cancel"), NULL); @@ -1274,9 +1289,9 @@ text = g_strdup_printf(_("You are about to remove the chat %s from your buddy list. Do you want to continue?"), name ? name : ""); - purple_request_action(chat, NULL, _("Remove Chat"), text, 0, + purple_request_action_with_hint(chat, NULL, _("Remove Chat"), text, 0, chat->account, NULL, NULL, - chat, 2, + PURPLE_REQUEST_UI_HINT_BLIST, chat, 2, _("_Remove Chat"), G_CALLBACK(pidgin_dialogs_remove_chat_cb), _("Cancel"), NULL); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkdialogs.h --- a/pidgin/gtkdialogs.h Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkdialogs.h Thu Oct 18 17:58:40 2007 +0000 @@ -31,18 +31,33 @@ #include "conversation.h" /* Functions in gtkdialogs.c (these should actually stay in this file) */ + void pidgin_dialogs_destroy_all(void); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * @deprecated Use pidgin_dialogs_about_with_parent() instead. + */ void pidgin_dialogs_about(void); +#endif + +/** + * @since 2.3.0 + */ +void pidgin_dialogs_about_with_parent(GtkWindow *parent); + void pidgin_dialogs_im(void); void pidgin_dialogs_im_with_user(PurpleAccount *, const char *); void pidgin_dialogs_info(void); void pidgin_dialogs_log(void); +#ifndef PURPLE_DISABLE_DEPRECATED /** * @deprecated This function is no longer used and will be removed in * Pidgin 3.0.0 unless there is sufficient demand to keep it. */ void pidgin_dialogs_alias_contact(PurpleContact *); +#endif void pidgin_dialogs_alias_buddy(PurpleBuddy *); void pidgin_dialogs_alias_chat(PurpleChat *); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkdocklet.c --- a/pidgin/gtkdocklet.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkdocklet.c Thu Oct 18 17:58:40 2007 +0000 @@ -407,7 +407,7 @@ GdkPixbuf *pixbuf; GtkWidget *image; - menuitem = gtk_image_menu_item_new_with_mnemonic(str); + menuitem = gtk_image_menu_item_new_with_label(str); if (menu) gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); @@ -474,6 +474,7 @@ } + static void plugin_act(GtkObject *obj, PurplePluginAction *pam) { @@ -553,7 +554,6 @@ pidgin_separator(menu); } - static void docklet_menu() { static GtkWidget *menu = NULL; diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkimhtmltoolbar.c --- a/pidgin/gtkimhtmltoolbar.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Thu Oct 18 17:58:40 2007 +0000 @@ -184,6 +184,8 @@ g_signal_connect_after(G_OBJECT(toolbar->font_dialog), "realize", G_CALLBACK(realize_toolbar_font), toolbar); } + gtk_window_set_transient_for(GTK_WINDOW(toolbar->font_dialog), + GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar)))); gtk_window_present(GTK_WINDOW(toolbar->font_dialog)); } else { cancel_toolbar_font(font, toolbar); @@ -427,14 +429,14 @@ } toolbar->link_dialog = - purple_request_fields(toolbar, _("Insert Link"), + purple_request_fields_with_hint(toolbar, _("Insert Link"), NULL, - msg, + msg, fields, _("_Insert"), G_CALLBACK(do_insert_link_cb), _("Cancel"), G_CALLBACK(cancel_link_cb), - NULL, NULL, NULL, - toolbar); + NULL, NULL, NULL, + PURPLE_REQUEST_UI_HINT_CONV, toolbar); g_free(msg); g_free(desc); } else { @@ -709,6 +711,8 @@ gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_window_set_role(GTK_WINDOW(dialog), "smiley_dialog"); gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); + gtk_window_set_transient_for(GTK_WINDOW(dialog), + GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar)))); if (unique_smileys != NULL) { struct smiley_button_list *ls, *it, *it_tmp; diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtklog.c --- a/pidgin/gtklog.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtklog.c Thu Oct 18 17:58:40 2007 +0000 @@ -321,9 +321,9 @@ data2[0] = lv->treestore; data2[1] = data[3]; /* iter */ data2[2] = log; - purple_request_action(lv, NULL, "Delete Log?", tmp, 0, + purple_request_action_with_hint(lv, NULL, "Delete Log?", tmp, 0, NULL, NULL, NULL, - data2, 2, + "log_viewer", data2, 2, _("Delete"), delete_log_cb, _("Cancel"), delete_log_cleanup_cb); g_free(tmp); @@ -523,7 +523,7 @@ } } -static PidginLogViewer *display_log_viewer(struct log_viewer_hash_t *ht, GList *logs, +static PidginLogViewer *display_log_viewer(GtkWindow *parent, struct log_viewer_hash_t *ht, GList *logs, const char *title, GtkWidget *icon, int log_size) { PidginLogViewer *lv; @@ -569,7 +569,7 @@ g_hash_table_insert(log_viewers, ht, lv); /* Window ***********/ - lv->window = gtk_dialog_new_with_buttons(title, NULL, 0, + lv->window = gtk_dialog_new_with_buttons(title, parent, 0, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); #ifdef _WIN32 /* Steal the "HELP" response and use it to trigger browsing to the logs folder */ @@ -676,6 +676,10 @@ } void pidgin_log_show(PurpleLogType type, const char *screenname, PurpleAccount *account) { + pidgin_log_show_with_parent(NULL, type, screenname, account); +} + +void pidgin_log_show_with_parent(GtkWindow *parent, PurpleLogType type, const char *screenname, PurpleAccount *account) { struct log_viewer_hash_t *ht; PidginLogViewer *lv = NULL; const char *name = screenname; @@ -720,7 +724,7 @@ prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); - display_log_viewer(ht, purple_log_get_logs(type, screenname, account), + display_log_viewer(parent, ht, purple_log_get_logs(type, screenname, account), title, gtk_image_new_from_pixbuf(prpl_icon), purple_log_get_total_size(type, screenname, account)); @@ -730,6 +734,10 @@ } void pidgin_log_show_contact(PurpleContact *contact) { + pidgin_log_show_contact_with_parent(NULL, contact); +} + +void pidgin_log_show_contact_with_parent(GtkWindow *parent, PurpleContact *contact) { struct log_viewer_hash_t *ht = g_new0(struct log_viewer_hash_t, 1); PurpleBlistNode *child; PidginLogViewer *lv = NULL; @@ -783,11 +791,16 @@ } title = g_strdup_printf(_("Conversations with %s"), name); - display_log_viewer(ht, logs, title, image, total_log_size); + display_log_viewer(parent, ht, logs, title, image, total_log_size); g_free(title); } -void pidgin_syslog_show() +void pidgin_syslog_show(void) +{ + pidgin_syslog_show_with_parent(NULL); +} + +void pidgin_syslog_show_with_parent(GtkWindow *parent) { GList *accounts = NULL; GList *logs = NULL; @@ -807,7 +820,7 @@ } logs = g_list_sort(logs, purple_log_compare); - syslog_viewer = display_log_viewer(NULL, logs, _("System Log"), NULL, 0); + syslog_viewer = display_log_viewer(parent, NULL, logs, _("System Log"), NULL, 0); } /**************************************************************************** diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtklog.h --- a/pidgin/gtklog.h Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtklog.h Thu Oct 18 17:58:40 2007 +0000 @@ -52,11 +52,41 @@ }; +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * @deprecated Use pidgin_log_show_with_parent() instead. + */ +void pidgin_log_show(PurpleLogType type, const char *screenname, PurpleAccount *account); +#endif -void pidgin_log_show(PurpleLogType type, const char *screenname, PurpleAccount *account); +/** + * @since 2.3.0 + */ +void pidgin_log_show_with_parent(GtkWindow *parent, PurpleLogType type, const char *screenname, PurpleAccount *account); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * @deprecated pidgin_log_show_contact_with_parent() instead. + */ void pidgin_log_show_contact(PurpleContact *contact); +#endif +/** + * @since 2.3.0 + */ +void pidgin_log_show_contact_with_parent(GtkWindow *parent, PurpleContact *contact); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * @deprecated Use pidgin_syslog_show_with_parent() instead. + */ void pidgin_syslog_show(void); +#endif + +/** + * @since 2.3.0 + */ +void pidgin_syslog_show_with_parent(GtkWindow *parent); /**************************************************************************/ /** @name GTK+ Log Subsystem */ diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtknotify.c --- a/pidgin/gtknotify.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtknotify.c Thu Oct 18 17:58:40 2007 +0000 @@ -270,8 +270,9 @@ primary_esc = g_markup_escape_text(primary, -1); secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; g_snprintf(label_text, sizeof(label_text), - "%s\n\n%s", - primary_esc, (secondary ? secondary_esc : "")); + "%s%s%s", + primary_esc, (secondary ? "\n\n" : ""), + (secondary ? secondary_esc : "")); g_free(primary_esc); g_free(secondary_esc); @@ -740,7 +741,7 @@ GtkListStore *model; GtkCellRenderer *renderer; guint col_num; - GList *column; + GList *columniter; guint i; GtkWidget *vbox; @@ -824,11 +825,12 @@ -1, "", renderer, "pixbuf", 0, NULL); i = 1; - for (column = results->columns; column != NULL; column = column->next) { + for (columniter = results->columns; columniter != NULL; columniter = columniter->next) { + PurpleNotifySearchColumn *column = columniter->data; renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1, - column->data, renderer, "text", i, NULL); + column->title, renderer, "text", i, NULL); i++; } diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkplugin.c --- a/pidgin/gtkplugin.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkplugin.c Thu Oct 18 17:58:40 2007 +0000 @@ -280,11 +280,11 @@ cb_data[1] = model; cb_data[2] = iter; - purple_request_action(plugin_dialog, NULL, + purple_request_action_with_hint(plugin_dialog, NULL, _("Multiple plugins will be unloaded."), tmp->str, 0, - NULL, NULL, NULL, - cb_data, 2, + NULL, NULL, NULL, + PURPLE_REQUEST_UI_HINT_PLUGINMGR, cb_data, 2, _("Unload Plugins"), G_CALLBACK(plugin_unload_confirm_cb), _("Cancel"), g_free); g_string_free(tmp, TRUE); @@ -303,7 +303,24 @@ { pidgin_set_cursor(plugin_dialog, GDK_WATCH); - purple_plugin_unload(plug); + if (!purple_plugin_unload(plug)) + { + const char *primary = _("Could not unload plugin"); + const char *reload = _("The plugin could not be unloaded now, but will be disabled at the next startup."); + + if (!plug->error) + { + purple_notify_warning(NULL, NULL, primary, reload); + } + else + { + char *tmp = g_strdup_printf("%s\n\n%s", reload, plug->error); + purple_notify_warning(NULL, NULL, primary, tmp); + g_free(tmp); + } + + purple_plugin_disable(plug); + } pidgin_clear_cursor(plugin_dialog); } @@ -516,6 +533,11 @@ void pidgin_plugin_dialog_show() { + pidgin_plugin_dialog_show_with_parent(NULL); +} + +void pidgin_plugin_dialog_show_with_parent(GtkWindow *parent) +{ GtkWidget *sw; GtkWidget *event_view; GtkListStore *ls; @@ -524,6 +546,8 @@ GtkTreeSelection *sel; if (plugin_dialog != NULL) { + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(plugin_dialog), parent); gtk_window_present(GTK_WINDOW(plugin_dialog)); return; } @@ -532,6 +556,8 @@ NULL, GTK_DIALOG_NO_SEPARATOR, NULL); + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(plugin_dialog), parent); pref_button = gtk_dialog_add_button(GTK_DIALOG(plugin_dialog), _("Configure Pl_ugin"), PIDGIN_RESPONSE_CONFIGURE); gtk_dialog_add_button(GTK_DIALOG(plugin_dialog), diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkplugin.h --- a/pidgin/gtkplugin.h Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkplugin.h Thu Oct 18 17:58:40 2007 +0000 @@ -72,9 +72,20 @@ */ void pidgin_plugins_save(void); +#ifndef PURPLE_DISABLE_DEPRECATED /** * Shows the Plugins dialog + * + * @deprecated Use pidgin_plugin_dialog_show_with_parent() instead. */ void pidgin_plugin_dialog_show(void); +#endif + +/** + * Shows the Plugins dialog, transient to a parent window + * + * @since 2.3.0 + */ +void pidgin_plugin_dialog_show_with_parent(GtkWindow *parent); #endif /* _PIDGINPLUGIN_H_ */ diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkpounce.c --- a/pidgin/gtkpounce.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkpounce.c Thu Oct 18 17:58:40 2007 +0000 @@ -154,10 +154,10 @@ entry = (GtkWidget *)data; name = gtk_entry_get_text(GTK_ENTRY(entry)); - purple_request_file(entry, _("Select a file"), name, FALSE, + purple_request_file_with_hint(entry, _("Select a file"), name, FALSE, G_CALLBACK(pounce_update_entry_fields), NULL, NULL, NULL, NULL, - entry); + "buddy_pounce", entry); g_signal_connect_swapped(G_OBJECT(entry), "destroy", G_CALLBACK(purple_request_close_with_handle), entry); } @@ -472,6 +472,13 @@ pidgin_pounce_editor_show(PurpleAccount *account, const char *name, PurplePounce *cur_pounce) { + pidgin_pounce_editor_show_with_parent(NULL, account, name, cur_pounce); +} + +void +pidgin_pounce_editor_show_with_parent(GtkWindow *parent, PurpleAccount *account, const char *name, + PurplePounce *cur_pounce) +{ PidginPounceDialog *dialog; GtkWidget *window; GtkWidget *label; @@ -1050,7 +1057,7 @@ static void pounces_manager_add_cb(GtkButton *button, gpointer user_data) { - pidgin_pounce_editor_show(NULL, NULL, NULL); + pidgin_pounce_editor_show_with_parent(GTK_WINDOW(pounces_manager->window), NULL, NULL, NULL); } static void @@ -1060,7 +1067,7 @@ PurplePounce *pounce; gtk_tree_model_get(model, iter, POUNCES_MANAGER_COLUMN_POUNCE, &pounce, -1); - pidgin_pounce_editor_show(NULL, NULL, pounce); + pidgin_pounce_editor_show_with_parent(GTK_WINDOW(pounces_manager->window), NULL, NULL, pounce); } static void @@ -1101,9 +1108,9 @@ pouncee = purple_pounce_get_pouncee(pounce); buf = g_strdup_printf(_("Are you sure you want to delete the pounce on %s for %s?"), pouncee, pouncer); - purple_request_action(pounce, NULL, buf, NULL, 0, + purple_request_action_with_hint(pounce, NULL, buf, NULL, 0, account, pouncee, NULL, - pounce, 2, + PURPLE_REQUEST_UI_HINT_POUNCEMGR, pounce, 2, _("Delete"), pounces_manager_delete_confirm_cb, _("Cancel"), NULL); g_free(buf); @@ -1160,7 +1167,7 @@ if ((pounce != NULL) && (event->button == 1) && (event->type == GDK_2BUTTON_PRESS)) { - pidgin_pounce_editor_show(NULL, NULL, pounce); + pidgin_pounce_editor_show_with_parent(GTK_WINDOW(pounces_manager->window), NULL, NULL, pounce); return TRUE; } @@ -1311,6 +1318,12 @@ void pidgin_pounces_manager_show(void) { + pidgin_pounces_manager_show_with_parent(NULL); +} + +void +pidgin_pounces_manager_show_with_parent(GtkWindow *parent) +{ PouncesManager *dialog; GtkWidget *bbox; GtkWidget *button; @@ -1321,6 +1334,7 @@ if (pounces_manager != NULL) { gtk_window_present(GTK_WINDOW(pounces_manager->window)); + gtk_window_set_transient_for(GTK_WINDOW(pounces_manager->window), parent); return; } @@ -1331,6 +1345,7 @@ dialog->window = win = pidgin_create_window(_("Buddy Pounces"), PIDGIN_HIG_BORDER, "pounces", TRUE); gtk_window_set_default_size(GTK_WINDOW(win), width, height); + gtk_window_set_transient_for(GTK_WINDOW(win), parent); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(pounces_manager_destroy_cb), dialog); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkpounce.h --- a/pidgin/gtkpounce.h Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkpounce.h Thu Oct 18 17:58:40 2007 +0000 @@ -28,20 +28,48 @@ #include "pounce.h" +#ifndef PURPLE_DISABLE_DEPRECATED /** * Displays a New Buddy Pounce or Edit Buddy Pounce dialog. * * @param account The optional account to use. * @param name The optional name to pounce on. * @param cur_pounce The current buddy pounce, if editing an existing one. + * + * @deprecated Use pidgin_pounce_editor_show_with_parent() instead. */ void pidgin_pounce_editor_show(PurpleAccount *account, const char *name, PurplePounce *cur_pounce); +#endif + +/** + * Displays a New Buddy Pounce or Edit Buddy Pounce dialog. + * + * @param parent The parent window. + * @param account The optional account to use. + * @param name The optional name to pounce on. + * @param cur_pounce The current buddy pounce, if editing an existing one. + * + * @since 2.3.0 + */ +void pidgin_pounce_editor_show_with_parent(GtkWindow *parent, PurpleAccount *account, const char *name, + PurplePounce *cur_pounce); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * Shows the pounces manager window. + * + * @deprecated Use pidgin_pounces_manager_show_with_parent() instead. + */ +void pidgin_pounces_manager_show(void); +#endif /** * Shows the pounces manager window. + * + * @since 2.3.0 */ -void pidgin_pounces_manager_show(void); +void pidgin_pounces_manager_show_with_parent(GtkWindow *parent); /** * Hides the pounces manager window. diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkprefs.c Thu Oct 18 17:58:40 2007 +0000 @@ -641,7 +641,8 @@ static void add_theme_button_clicked_cb(GtkWidget *widget, gpointer null) { - purple_request_file(NULL, _("Install Theme"), NULL, FALSE, (GCallback)request_theme_file_name_cb, NULL, NULL, NULL, NULL, NULL) ; + purple_request_file_with_hint(NULL, _("Install Theme"), NULL, FALSE, + (GCallback)request_theme_file_name_cb, NULL, NULL, NULL, NULL, PURPLE_REQUEST_UI_HINT_PREFSMGR, NULL) ; } static void @@ -1624,9 +1625,9 @@ if (*filename == '\0') filename = NULL; - purple_request_file(prefs, _("Sound Selection"), filename, FALSE, + purple_request_file_with_hint(prefs, _("Sound Selection"), filename, FALSE, G_CALLBACK(sound_chosen_cb), NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, PURPLE_REQUEST_UI_HINT_PREFSMGR, GINT_TO_POINTER(sound_row_sel)); } diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkprivacy.c --- a/pidgin/gtkprivacy.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkprivacy.c Thu Oct 18 17:58:40 2007 +0000 @@ -88,6 +88,8 @@ static PidginPrivacyDialog *privacy_dialog = NULL; +#define PIDGIN_REQUEST_HINT_PRIVACY "privacy" + static void rebuild_allow_list(PidginPrivacyDialog *dialog) { @@ -367,7 +369,7 @@ dialog = g_new0(PidginPrivacyDialog, 1); - dialog->win = pidgin_create_window(_("Privacy"), PIDGIN_HIG_BORDER, "privacy", TRUE); + dialog->win = pidgin_create_window(_("Privacy"), PIDGIN_HIG_BORDER, PIDGIN_REQUEST_HINT_PRIVACY, TRUE); g_signal_connect(G_OBJECT(dialog->win), "delete_event", G_CALLBACK(destroy_cb), dialog); @@ -554,7 +556,7 @@ data->block = FALSE; if (name == NULL) { - purple_request_input(account, _("Permit User"), + purple_request_input_with_hint(account, _("Permit User"), _("Type a user you permit to contact you."), _("Please enter the name of the user you wish to be " "able to contact you."), @@ -562,7 +564,7 @@ _("_Permit"), G_CALLBACK(add_permit_block_cb), _("Cancel"), G_CALLBACK(destroy_request_data), account, name, NULL, - data); + PIDGIN_REQUEST_HINT_PRIVACY, data); } else { char *primary = g_strdup_printf(_("Allow %s to contact you?"), name); @@ -571,10 +573,10 @@ "%s to contact you?"), name); - purple_request_action(account, _("Permit User"), primary, secondary, + purple_request_action_with_hint(account, _("Permit User"), primary, secondary, 0, account, name, NULL, - data, 2, + PIDGIN_REQUEST_HINT_PRIVACY, data, 2, _("_Permit"), G_CALLBACK(confirm_permit_block_cb), _("Cancel"), G_CALLBACK(destroy_request_data)); @@ -596,24 +598,24 @@ data->block = TRUE; if (name == NULL) { - purple_request_input(account, _("Block User"), + purple_request_input_with_hint(account, _("Block User"), _("Type a user to block."), _("Please enter the name of the user you wish to block."), NULL, FALSE, FALSE, NULL, _("_Block"), G_CALLBACK(add_permit_block_cb), _("Cancel"), G_CALLBACK(destroy_request_data), account, name, NULL, - data); + PIDGIN_REQUEST_HINT_PRIVACY, data); } else { char *primary = g_strdup_printf(_("Block %s?"), name); char *secondary = g_strdup_printf(_("Are you sure you want to block %s?"), name); - purple_request_action(account, _("Block User"), primary, secondary, + purple_request_action_with_hint(account, _("Block User"), primary, secondary, 0, account, name, NULL, - data, 2, + PIDGIN_REQUEST_HINT_PRIVACY, data, 2, _("_Block"), G_CALLBACK(confirm_permit_block_cb), _("Cancel"), G_CALLBACK(destroy_request_data)); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkrequest.c --- a/pidgin/gtkrequest.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkrequest.c Thu Oct 18 17:58:40 2007 +0000 @@ -29,11 +29,13 @@ #include "prefs.h" #include "util.h" +#include "gtkblist.h" #include "gtkimhtml.h" #include "gtkimhtmltoolbar.h" #include "gtkrequest.h" #include "gtkutils.h" #include "pidginstock.h" +#include "gtkblist.h" #include @@ -79,6 +81,55 @@ } PidginRequestData; +static GtkWindow * +find_toplevel(GList *ll_toplevels, const char *role) +{ + const char *window_role = NULL; + GList *ll_itr = NULL; + + for (ll_itr = ll_toplevels ; ll_itr ; ll_itr = ll_itr->next) { + if ((window_role = gtk_window_get_role(GTK_WINDOW(ll_itr->data))) != NULL) { + if (!strcmp(window_role, role)) + return GTK_WINDOW(ll_itr->data); + } + } + + return NULL; +} + +static GtkWindow * +get_request_parent(const char *ui_hint, PidginConversation *convo) +{ + GtkWindow *toplevel = NULL; + PidginBuddyList *blist = NULL; + + if (convo) + return GTK_WINDOW(convo->win->window); + + if (strcmp(ui_hint, PURPLE_REQUEST_UI_HINT_BLIST)) { + GList *ll_toplevels = NULL; + + ll_toplevels = gtk_window_list_toplevels(); + + if (!(toplevel = find_toplevel(ll_toplevels, ui_hint))) { + if (!strcmp(ui_hint, PURPLE_REQUEST_UI_HINT_REGISTER)) + toplevel = find_toplevel(ll_toplevels, "account"); + else + if (!strcmp(ui_hint, PURPLE_REQUEST_UI_HINT_XFER)) + toplevel = find_toplevel(ll_toplevels, "file transfer"); + } + + g_list_free(ll_toplevels); + } + + /* Takes care of "pidgin-statusbox" as well */ + if (!toplevel) + if ((blist = pidgin_blist_get_default_gtk_blist()) != NULL) + return GTK_WINDOW(blist->window); + + return toplevel; +} + static void generic_response_start(PidginRequestData *data) { @@ -287,7 +338,7 @@ const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data) + const char *ui_hint, void *user_data) { PidginRequestData *data; GtkWidget *dialog; @@ -312,7 +363,7 @@ /* Create the dialog. */ dialog = gtk_dialog_new_with_buttons(title ? title : PIDGIN_ALERT_TITLE, - NULL, 0, + get_request_parent(ui_hint, conv ? PIDGIN_CONVERSATION(conv) : NULL), 0, text_to_stock(cancel_text), 1, text_to_stock(ok_text), 0, NULL); @@ -450,7 +501,7 @@ const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, va_list args) + const char *ui_hint, void *user_data, va_list args) { PidginRequestData *data; GtkWidget *dialog; @@ -474,6 +525,8 @@ /* Create the dialog. */ data->dialog = dialog = gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog), + get_request_parent(ui_hint, conv ? PIDGIN_CONVERSATION(conv) : NULL)); if (title != NULL) gtk_window_set_title(GTK_WINDOW(dialog), title); @@ -554,7 +607,7 @@ pidgin_request_action(const char *title, const char *primary, const char *secondary, int default_action, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, size_t action_count, va_list actions) + const char *ui_hint, void *user_data, size_t action_count, va_list actions) { PidginRequestData *data; GtkWidget *dialog; @@ -584,6 +637,8 @@ /* Create the dialog. */ data->dialog = dialog = gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog), + get_request_parent(ui_hint, conv ? PIDGIN_CONVERSATION(conv) : NULL)); #if GTK_CHECK_VERSION(2,10,0) gtk_window_set_deletable(GTK_WINDOW(data->dialog), FALSE); @@ -952,6 +1007,92 @@ return widget; } +static GtkWidget * +create_blist_field(PurpleRequestField *field) +{ + GtkTreeStore *model; + GtkWidget *tree, *sw; + PurpleBlistNode *node; + GtkCellRenderer *rend; + GtkTreeViewColumn *column; + GtkTreeIter parent = {0, NULL, NULL, NULL}, iter; + PurpleRequestBlistFlags flags = field->u.blist.flags; + gboolean offline = !!(field->u.blist.flags & PURPLE_REQUEST_BLIST_FLAG_ALLOW_OFFLINE); + + /* Create the treeview. Populate the blistnodes. + * Hook to signed-on, signed-off signals to update the list when account goes online/offline. + * Hook to buddy-signed-on/off, -status-changed signals to update the status pixbuf. + */ + + model = gtk_tree_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDK_TYPE_PIXBUF); + node = purple_blist_get_root(); + while (node) { + GdkPixbuf *status = NULL, *prpl = NULL; + const char *name = NULL; + if ((PURPLE_BLIST_NODE_IS_BUDDY(node) || PURPLE_BLIST_NODE_IS_CONTACT(node)) + && (flags & PURPLE_REQUEST_BLIST_FLAG_BUDDY)) { + PurpleBuddy *buddy; + GtkTreeIter *p = NULL; + if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + buddy = (PurpleBuddy*)node; + p = &parent; + } else { + buddy = purple_contact_get_priority_buddy((PurpleContact*)node); + parent = iter; + } + if (PURPLE_BUDDY_IS_ONLINE(buddy)) { + gtk_tree_store_append(model, &iter, p); + name = purple_buddy_get_name(buddy); + status = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_SMALL); + } + } else if (PURPLE_BLIST_NODE_IS_CHAT(node) && (flags & PURPLE_REQUEST_BLIST_FLAG_CHAT)) { + gtk_tree_store_append(model, &iter, NULL); + name = purple_chat_get_name((PurpleChat*)node); + status = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_SMALL); + } + if (name) + gtk_tree_store_set(model, &iter, + 0, status, + 1, name, + 2, prpl, + -1); + if (prpl) + gdk_pixbuf_unref(prpl); + if (status) + gdk_pixbuf_unref(status); + node = purple_blist_node_next(node, offline); + } + + tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE); + gtk_tree_view_set_search_column(GTK_TREE_VIEW(tree), 1); + gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(tree), pidgin_tree_view_search_equal_func, NULL, NULL); + gtk_widget_show(tree); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); + + rend = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(column, rend, FALSE); + gtk_tree_view_column_set_attributes(column, rend, "pixbuf", 0, NULL); + + rend = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(column, rend, TRUE); + gtk_tree_view_column_set_attributes(column, rend, "markup", 1, NULL); + + rend = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(column, rend, FALSE); + gtk_tree_view_column_set_attributes(column, rend, "pixbuf", 2, NULL); + + sw = gtk_scrolled_window_new(NULL,NULL); + gtk_widget_show(sw); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_NONE); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(sw), tree); + + return sw; +} + static void select_field_list_item(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) @@ -1051,7 +1192,7 @@ const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data) + const char *ui_hint, void *user_data) { PidginRequestData *data; GtkWidget *win; @@ -1092,6 +1233,8 @@ #else /* !_WIN32 */ data->dialog = win = pidgin_create_window(title, PIDGIN_HIG_BORDER, "multifield", TRUE) ; #endif /* _WIN32 */ + gtk_window_set_transient_for(GTK_WINDOW(win), + get_request_parent(ui_hint, conv ? PIDGIN_CONVERSATION(conv) : NULL)); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(destroy_multifield_cb), data); @@ -1328,6 +1471,8 @@ widget = create_image_field(field); else if (type == PURPLE_REQUEST_FIELD_ACCOUNT) widget = create_account_field(field); + else if (type == PURPLE_REQUEST_FIELD_BLIST) + widget = create_blist_field(field); else continue; @@ -1504,10 +1649,10 @@ if ((data->u.file.savedialog == TRUE) && (g_file_test(data->u.file.name, G_FILE_TEST_EXISTS))) { - purple_request_action(data, NULL, _("That file already exists"), + purple_request_action_with_hint(data, NULL, _("That file already exists"), _("Would you like to overwrite it?"), 0, NULL, NULL, NULL, - data, 2, + "pidgin-request-file", data, 2, _("Overwrite"), G_CALLBACK(file_yes_no_cb), _("Choose New Name"), G_CALLBACK(file_yes_no_cb)); } else @@ -1532,7 +1677,7 @@ gboolean savedialog, GCallback ok_cb, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data) + const char *ui_hint, void *user_data) { PidginRequestData *data; GtkWidget *filesel; @@ -1620,6 +1765,9 @@ g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked", G_CALLBACK(file_ok_check_if_exists_cb), data); #endif /* FILECHOOSER */ + gtk_window_set_role(GTK_WINDOW(filesel), "pidgin-request-file"); + gtk_window_set_transient_for(GTK_WINDOW(filesel), + get_request_parent(ui_hint, conv ? PIDGIN_CONVERSATION(conv) : NULL)); data->dialog = filesel; gtk_widget_show(filesel); @@ -1631,7 +1779,7 @@ pidgin_request_folder(const char *title, const char *dirname, GCallback ok_cb, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data) + const char *ui_hint, void *user_data) { PidginRequestData *data; GtkWidget *dirsel; @@ -1670,6 +1818,9 @@ g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(dirsel)->ok_button), "clicked", G_CALLBACK(file_ok_check_if_exists_cb), data); #endif + gtk_window_set_role(GTK_WINDOW(dirsel), "pidgin-request-dir"); + gtk_window_set_transient_for(GTK_WINDOW(dirsel), + get_request_parent(ui_hint, conv ? PIDGIN_CONVERSATION(conv) : NULL)); data->dialog = dirsel; gtk_widget_show(dirsel); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtksavedstatuses.c --- a/pidgin/gtksavedstatuses.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtksavedstatuses.c Thu Oct 18 17:58:40 2007 +0000 @@ -63,7 +63,7 @@ }; /** - * These is used for the GtkTreeView containing the list of accounts + * These are used for the GtkTreeView containing the list of accounts * at the bottom of the window when you're editing a particular * saved status. */ @@ -338,9 +338,9 @@ handle = dialog; } - purple_request_action(handle, NULL, title, NULL, 0, + purple_request_action_with_hint(handle, NULL, title, NULL, 0, NULL, NULL, NULL, - sel_titles, 2, + PURPLE_REQUEST_UI_HINT_STATUSMGR, sel_titles, 2, _("Delete"), status_window_delete_confirm_cb, _("Cancel"), status_window_delete_cancel_cb); @@ -898,6 +898,12 @@ for (i = PURPLE_STATUS_UNSET + 1; i < PURPLE_STATUS_NUM_PRIMITIVES; i++) { + if (i == PURPLE_STATUS_MOBILE || i == PURPLE_STATUS_TUNE) + /* + * Special-case these. They're intended to be independent + * status types, so don't show them in the list. + */ + continue; item = gtk_menu_item_new_with_label(purple_primitive_get_name_from_type(i)); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); } @@ -1588,8 +1594,12 @@ status_type = list->data; - /* Only allow users to select statuses that are flagged as "user settable" */ - if (!purple_status_type_is_user_settable(status_type)) + /* + * Only allow users to select statuses that are flagged as + * "user settable" and that aren't independent. + */ + if (!purple_status_type_is_user_settable(status_type) || + purple_status_type_is_independent(status_type)) continue; id = purple_status_type_get_id(status_type); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtksound.c --- a/pidgin/gtksound.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtksound.c Thu Oct 18 17:58:40 2007 +0000 @@ -118,12 +118,9 @@ if (conv != NULL && PIDGIN_IS_PIDGIN_CONVERSATION(conv)) { PidginConversation *gtkconv; - PidginWindow *win; gboolean has_focus; gtkconv = PIDGIN_CONVERSATION(conv); - win = gtkconv->win; - has_focus = purple_conversation_has_focus(conv); if (!gtkconv->make_sound || diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkstatusbox.c --- a/pidgin/gtkstatusbox.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkstatusbox.c Thu Oct 18 17:58:40 2007 +0000 @@ -1586,9 +1586,9 @@ msg = g_strdup_printf(_("Are you sure you want to delete %s?"), purple_savedstatus_get_title(saved)); - purple_request_action(saved, NULL, msg, NULL, 0, + purple_request_action_with_hint(saved, NULL, msg, NULL, 0, NULL, NULL, NULL, - data, 2, + "pidgin-statusbox", data, 2, _("Delete"), tree_view_delete_current_selection_cb, _("Cancel"), NULL); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/gtkutils.c Thu Oct 18 17:58:40 2007 +0000 @@ -1526,28 +1526,30 @@ if (prpl_info && prpl_info->can_receive_file) ft = prpl_info->can_receive_file(gc, who); + else if (prpl_info && prpl_info->send_file) + ft = TRUE; if (im && ft) - purple_request_choice(NULL, NULL, + purple_request_choice_with_hint(NULL, NULL, _("You have dragged an image"), _("You can send this image as a file transfer, " "embed it into this message, or use it as the buddy icon for this user."), DND_FILE_TRANSFER, "OK", (GCallback)dnd_image_ok_callback, "Cancel", (GCallback)dnd_image_cancel_callback, account, who, NULL, - data, + PURPLE_REQUEST_UI_HINT_CONV, data, _("Set as buddy icon"), DND_BUDDY_ICON, _("Send image file"), DND_FILE_TRANSFER, _("Insert in message"), DND_IM_IMAGE, NULL); else if (!(im || ft)) - purple_request_yes_no(NULL, NULL, _("You have dragged an image"), + purple_request_yes_no_with_hint(NULL, NULL, _("You have dragged an image"), _("Would you like to set it as the buddy icon for this user?"), 0, account, who, NULL, - data, (GCallback)dnd_set_icon_ok_cb, (GCallback)dnd_set_icon_cancel_cb); + PURPLE_REQUEST_UI_HINT_CONV, data, (GCallback)dnd_set_icon_ok_cb, (GCallback)dnd_set_icon_cancel_cb); else - purple_request_choice(NULL, NULL, + purple_request_choice_with_hint(NULL, NULL, _("You have dragged an image"), (ft ? _("You can send this image as a file transfer, or use it as the buddy icon for this user.") : _("You can insert this image into this message, or use it as the buddy icon for this user")), @@ -1555,10 +1557,11 @@ "OK", (GCallback)dnd_image_ok_callback, "Cancel", (GCallback)dnd_image_cancel_callback, account, who, NULL, - data, + PURPLE_REQUEST_UI_HINT_CONV, data, _("Set as buddy icon"), DND_BUDDY_ICON, (ft ? _("Send image file") : _("Insert in message")), (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE), NULL); + gdk_pixbuf_unref(pb); return; } diff -r 33822d7271e5 -r 8b9c48347004 pidgin/plugins/history.c --- a/pidgin/plugins/history.c Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/plugins/history.c Thu Oct 18 17:58:40 2007 +0000 @@ -42,6 +42,7 @@ GtkIMHtmlOptions options = GTK_IMHTML_NO_COLOURS; char *header; char *protocol; + char *escaped_alias; convtype = purple_conversation_get_type(c); gtkconv = PIDGIN_CONVERSATION(c); @@ -120,10 +121,12 @@ if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)))) gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "
", options); - header = g_strdup_printf(_("Conversation with %s on %s:
"), alias, + escaped_alias = g_markup_escape_text(alias, -1); + header = g_strdup_printf(_("Conversation with %s on %s:
"), escaped_alias, purple_date_format_full(localtime(&((PurpleLog *)logs->data)->time))); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), header, options); g_free(header); + g_free(escaped_alias); g_strchomp(history); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), history, options); diff -r 33822d7271e5 -r 8b9c48347004 pidgin/plugins/perl/common/GtkDialogs.xs --- a/pidgin/plugins/perl/common/GtkDialogs.xs Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkDialogs.xs Thu Oct 18 17:58:40 2007 +0000 @@ -10,6 +10,10 @@ pidgin_dialogs_about() void +pidgin_dialogs_about_with_parent(parent) + void * parent + +void pidgin_dialogs_im() void diff -r 33822d7271e5 -r 8b9c48347004 pidgin/plugins/perl/common/GtkLog.xs --- a/pidgin/plugins/perl/common/GtkLog.xs Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkLog.xs Thu Oct 18 17:58:40 2007 +0000 @@ -13,11 +13,27 @@ Purple::Account account void +pidgin_log_show_with_parent(parent, type, screenname, account) + void * parent + Purple::LogType type + const char * screenname + Purple::Account account + +void pidgin_log_show_contact(contact) Purple::BuddyList::Contact contact +void +pidgin_log_show_contact_with_parent(parent, contact) + void * parent + Purple::BuddyList::Contact contact + MODULE = Pidgin::Log PACKAGE = Pidgin::SysLog PREFIX = pidgin_syslog_ PROTOTYPES: ENABLE void pidgin_syslog_show() + +void +pidgin_syslog_show_with_parent(parent) + void * parent diff -r 33822d7271e5 -r 8b9c48347004 pidgin/plugins/perl/common/GtkPlugin.xs --- a/pidgin/plugins/perl/common/GtkPlugin.xs Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkPlugin.xs Thu Oct 18 17:58:40 2007 +0000 @@ -11,3 +11,7 @@ void pidgin_plugin_dialog_show() + +void +pidgin_plugin_dialog_show_with_parent(parent) + void * parent diff -r 33822d7271e5 -r 8b9c48347004 pidgin/plugins/perl/common/GtkPounce.xs --- a/pidgin/plugins/perl/common/GtkPounce.xs Fri Oct 12 17:10:34 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkPounce.xs Thu Oct 18 17:58:40 2007 +0000 @@ -9,6 +9,13 @@ const char * name Purple::Pounce cur_pounce +void +pidgin_pounce_editor_show_with_parent(parent, account, name, cur_pounce) + void * parent + Purple::Account account + const char * name + Purple::Pounce cur_pounce + MODULE = Pidgin::Pounce PACKAGE = Pidgin::Pounces PREFIX = pidgin_pounces_ PROTOTYPES: ENABLE @@ -22,4 +29,8 @@ pidgin_pounces_manager_show() void +pidgin_pounces_manager_show_with_parent(parent) + void * parent + +void pidgin_pounces_manager_hide()