diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index d2c1c96e..7986ae16 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -57,52 +57,52 @@ #include "pgp/gpg.h" #endif -static char* _sub_autocomplete(ProfWin *window, const char *const input); -static char* _notify_autocomplete(ProfWin *window, const char *const input); -static char* _theme_autocomplete(ProfWin *window, const char *const input); -static char* _autoaway_autocomplete(ProfWin *window, const char *const input); -static char* _autoconnect_autocomplete(ProfWin *window, const char *const input); -static char* _account_autocomplete(ProfWin *window, const char *const input); -static char* _who_autocomplete(ProfWin *window, const char *const input); -static char* _roster_autocomplete(ProfWin *window, const char *const input); -static char* _group_autocomplete(ProfWin *window, const char *const input); -static char* _bookmark_autocomplete(ProfWin *window, const char *const input); -static char* _otr_autocomplete(ProfWin *window, const char *const input); -static char* _pgp_autocomplete(ProfWin *window, const char *const input); -static char* _connect_autocomplete(ProfWin *window, const char *const input); -static char* _alias_autocomplete(ProfWin *window, const char *const input); -static char* _join_autocomplete(ProfWin *window, const char *const input); -static char* _log_autocomplete(ProfWin *window, const char *const input); -static char* _form_autocomplete(ProfWin *window, const char *const input); -static char* _form_field_autocomplete(ProfWin *window, const char *const input); -static char* _occupants_autocomplete(ProfWin *window, const char *const input); -static char* _kick_autocomplete(ProfWin *window, const char *const input); -static char* _ban_autocomplete(ProfWin *window, const char *const input); -static char* _affiliation_autocomplete(ProfWin *window, const char *const input); -static char* _role_autocomplete(ProfWin *window, const char *const input); -static char* _resource_autocomplete(ProfWin *window, const char *const input); -static char* _wintitle_autocomplete(ProfWin *window, const char *const input); -static char* _inpblock_autocomplete(ProfWin *window, const char *const input); -static char* _time_autocomplete(ProfWin *window, const char *const input); -static char* _receipts_autocomplete(ProfWin *window, const char *const input); -static char* _help_autocomplete(ProfWin *window, const char *const input); -static char* _wins_autocomplete(ProfWin *window, const char *const input); -static char* _tls_autocomplete(ProfWin *window, const char *const input); -static char* _script_autocomplete(ProfWin *window, const char *const input); -static char* _subject_autocomplete(ProfWin *window, const char *const input); -static char* _console_autocomplete(ProfWin *window, const char *const input); -static char* _win_autocomplete(ProfWin *window, const char *const input); -static char* _close_autocomplete(ProfWin *window, const char *const input); -static char* _plugins_autocomplete(ProfWin *window, const char *const input); -static char* _sendfile_autocomplete(ProfWin *window, const char *const input); -static char* _blocked_autocomplete(ProfWin *window, const char *const input); -static char* _tray_autocomplete(ProfWin *window, const char *const input); -static char* _presence_autocomplete(ProfWin *window, const char *const input); -static char* _correct_autocomplete(ProfWin *window, const char *const input); +static char* _sub_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _notify_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _theme_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _autoaway_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _autoconnect_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _account_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _who_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _roster_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _group_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _bookmark_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _otr_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _pgp_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _connect_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _alias_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _join_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _log_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _form_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _form_field_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _occupants_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _kick_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _ban_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _affiliation_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _role_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _resource_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _wintitle_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _inpblock_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _time_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _receipts_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _help_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _wins_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _tls_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _script_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _subject_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _console_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _win_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _close_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _plugins_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _sendfile_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _blocked_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _tray_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _presence_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _correct_autocomplete(ProfWin *window, const char *const input, gboolean previous); -static char* _script_autocomplete_func(const char *const prefix); +static char* _script_autocomplete_func(const char *const prefix, gboolean previous); -static char* _cmd_ac_complete_params(ProfWin *window, const char *const input); +static char* _cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previous); static Autocomplete commands_ac; static Autocomplete who_room_ac; @@ -205,6 +205,8 @@ cmd_ac_init(void) help_ac = autocomplete_new(); autocomplete_add(help_ac, "commands"); autocomplete_add(help_ac, "navigation"); + autocomplete_add(help_ac, "search_all"); + autocomplete_add(help_ac, "search_any"); help_commands_ac = autocomplete_new(); autocomplete_add(help_commands_ac, "chat"); @@ -843,16 +845,16 @@ cmd_ac_add_form_fields(DataForm *form) return; } - GSList *fields = autocomplete_create_list(form->tag_ac); - GSList *curr_field = fields; + GList *fields = autocomplete_create_list(form->tag_ac); + GList *curr_field = fields; while (curr_field) { GString *field_str = g_string_new("/"); g_string_append(field_str, curr_field->data); cmd_ac_add(field_str->str); g_string_free(field_str, TRUE); - curr_field = g_slist_next(curr_field); + curr_field = g_list_next(curr_field); } - g_slist_free_full(fields, free); + g_list_free_full(fields, free); } void @@ -862,32 +864,32 @@ cmd_ac_remove_form_fields(DataForm *form) return; } - GSList *fields = autocomplete_create_list(form->tag_ac); - GSList *curr_field = fields; + GList *fields = autocomplete_create_list(form->tag_ac); + GList *curr_field = fields; while (curr_field) { GString *field_str = g_string_new("/"); g_string_append(field_str, curr_field->data); cmd_ac_remove(field_str->str); g_string_free(field_str, TRUE); - curr_field = g_slist_next(curr_field); + curr_field = g_list_next(curr_field); } - g_slist_free_full(fields, free); + g_list_free_full(fields, free); } char* -cmd_ac_complete(ProfWin *window, const char *const input) +cmd_ac_complete(ProfWin *window, const char *const input, gboolean previous) { // autocomplete command if ((strncmp(input, "/", 1) == 0) && (!str_contains(input, strlen(input), ' '))) { char *found = NULL; - found = autocomplete_complete(commands_ac, input, TRUE); + found = autocomplete_complete(commands_ac, input, TRUE, previous); if (found) { return found; } // autocomplete parameters } else { - char *found = _cmd_ac_complete_params(window, input); + char *found = _cmd_ac_complete_params(window, input, previous); if (found) { return found; } @@ -1150,7 +1152,7 @@ cmd_ac_uninit(void) } char* -cmd_ac_complete_filepath(const char *const input, char *const startstr) +cmd_ac_complete_filepath(const char *const input, char *const startstr, gboolean previous) { static char* last_directory = NULL; @@ -1248,7 +1250,7 @@ cmd_ac_complete_filepath(const char *const input, char *const startstr) } free(foofile); - result = autocomplete_param_with_ac(input, startstr, filepath_ac, TRUE); + result = autocomplete_param_with_ac(input, startstr, filepath_ac, TRUE, previous); if (result) { return result; } @@ -1257,7 +1259,7 @@ cmd_ac_complete_filepath(const char *const input, char *const startstr) } static char* -_cmd_ac_complete_params(ProfWin *window, const char *const input) +_cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previous) { int i; char *result = NULL; @@ -1270,7 +1272,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input) "/lastactivity" }; for (i = 0; i < ARRAY_SIZE(boolean_choices); i++) { - result = autocomplete_param_with_func(input, boolean_choices[i], prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, boolean_choices[i], prefs_autocomplete_boolean_choice, previous); if (result) { return result; } @@ -1287,7 +1289,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input) // Remove quote character before and after names when doing autocomplete char *unquoted = strip_arg_quotes(input); for (i = 0; i < ARRAY_SIZE(nick_choices); i++) { - result = autocomplete_param_with_ac(unquoted, nick_choices[i], nick_ac, TRUE); + result = autocomplete_param_with_ac(unquoted, nick_choices[i], nick_ac, TRUE, previous); if (result) { free(unquoted); return result; @@ -1302,7 +1304,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input) // Remove quote character before and after names when doing autocomplete char *unquoted = strip_arg_quotes(input); for (i = 0; i < ARRAY_SIZE(contact_choices); i++) { - result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_contact_autocomplete); + result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_contact_autocomplete, previous); if (result) { free(unquoted); return result; @@ -1312,7 +1314,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input) gchar *resource_choices[] = { "/caps", "/software", "/ping" }; for (i = 0; i < ARRAY_SIZE(resource_choices); i++) { - result = autocomplete_param_with_func(input, resource_choices[i], roster_fulljid_autocomplete); + result = autocomplete_param_with_func(input, resource_choices[i], roster_fulljid_autocomplete, previous); if (result) { return result; } @@ -1320,7 +1322,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input) } if (conn_status == JABBER_CONNECTED) { - result = autocomplete_param_with_func(input, "/invite", roster_contact_autocomplete); + result = autocomplete_param_with_func(input, "/invite", roster_contact_autocomplete, previous); if (result) { return result; } @@ -1328,7 +1330,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input) gchar *invite_choices[] = { "/decline", "/join" }; for (i = 0; i < ARRAY_SIZE(invite_choices); i++) { - result = autocomplete_param_with_func(input, invite_choices[i], muc_invites_find); + result = autocomplete_param_with_func(input, invite_choices[i], muc_invites_find, previous); if (result) { return result; } @@ -1338,7 +1340,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input) Autocomplete completers[] = { prefs_ac, disco_ac, room_ac, autoping_ac, winpos_ac, winpos_ac, winpos_ac, winpos_ac }; for (i = 0; i < ARRAY_SIZE(cmds); i++) { - result = autocomplete_param_with_ac(input, cmds[i], completers[i], TRUE); + result = autocomplete_param_with_ac(input, cmds[i], completers[i], TRUE, previous); if (result) { return result; } @@ -1400,9 +1402,9 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input) } parsed[i] = '\0'; - char * (*ac_func)(ProfWin*, const char * const) = g_hash_table_lookup(ac_funcs, parsed); + char * (*ac_func)(ProfWin*, const char * const, gboolean) = g_hash_table_lookup(ac_funcs, parsed); if (ac_func) { - result = ac_func(window, input); + result = ac_func(window, input, previous); if (result) { g_hash_table_destroy(ac_funcs); return result; @@ -1410,13 +1412,13 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input) } g_hash_table_destroy(ac_funcs); - result = plugins_autocomplete(input); + result = plugins_autocomplete(input, previous); if (result) { return result; } if (g_str_has_prefix(input, "/field")) { - result = _form_field_autocomplete(window, input); + result = _form_field_autocomplete(window, input, previous); if (result) { return result; } @@ -1426,18 +1428,18 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input) } static char* -_sub_autocomplete(ProfWin *window, const char *const input) +_sub_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_func(input, "/sub allow", presence_sub_request_find); + result = autocomplete_param_with_func(input, "/sub allow", presence_sub_request_find, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/sub deny", presence_sub_request_find); + result = autocomplete_param_with_func(input, "/sub deny", presence_sub_request_find, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/sub", sub_ac, TRUE); + result = autocomplete_param_with_ac(input, "/sub", sub_ac, TRUE, previous); if (result) { return result; } @@ -1446,15 +1448,15 @@ _sub_autocomplete(ProfWin *window, const char *const input) } static char* -_tray_autocomplete(ProfWin *window, const char *const input) +_tray_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_func(input, "/tray read", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/tray read", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/tray", tray_ac, FALSE); + result = autocomplete_param_with_ac(input, "/tray", tray_ac, FALSE, previous); if (result) { return result; } @@ -1463,12 +1465,12 @@ _tray_autocomplete(ProfWin *window, const char *const input) } static char* -_who_autocomplete(ProfWin *window, const char *const input) +_who_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; if (window->type == WIN_MUC) { - result = autocomplete_param_with_ac(input, "/who", who_room_ac, TRUE); + result = autocomplete_param_with_ac(input, "/who", who_room_ac, TRUE, previous); if (result) { return result; } @@ -1481,14 +1483,14 @@ _who_autocomplete(ProfWin *window, const char *const input) "/who unavailable" }; for (i = 0; i < ARRAY_SIZE(group_commands); i++) { - result = autocomplete_param_with_func(input, group_commands[i], roster_group_autocomplete); + result = autocomplete_param_with_func(input, group_commands[i], roster_group_autocomplete, previous); if (result) { return result; } } } - result = autocomplete_param_with_ac(input, "/who", who_roster_ac, TRUE); + result = autocomplete_param_with_ac(input, "/who", who_roster_ac, TRUE, previous); if (result) { return result; } @@ -1498,135 +1500,135 @@ _who_autocomplete(ProfWin *window, const char *const input) } static char* -_roster_autocomplete(ProfWin *window, const char *const input) +_roster_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_ac(input, "/roster room private char", roster_char_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster room private char", roster_char_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster room private", roster_header_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster room private", roster_header_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster header char", roster_char_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster header char", roster_char_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster contact char", roster_char_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster contact char", roster_char_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster room char", roster_char_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster room char", roster_char_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster private char", roster_char_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster private char", roster_char_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster resource char", roster_char_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster resource char", roster_char_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/roster resource join", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/roster resource join", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster room position", roster_room_position_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster room position", roster_room_position_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster room by", roster_room_by_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster room by", roster_room_by_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster room order", roster_room_order_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster room order", roster_room_order_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster room unread", roster_unread_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster room unread", roster_unread_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/roster count zero", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/roster count zero", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } jabber_conn_status_t conn_status = connection_get_status(); if (conn_status == JABBER_CONNECTED) { - result = autocomplete_param_with_func(input, "/roster nick", roster_barejid_autocomplete); + result = autocomplete_param_with_func(input, "/roster nick", roster_barejid_autocomplete, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/roster clearnick", roster_barejid_autocomplete); + result = autocomplete_param_with_func(input, "/roster clearnick", roster_barejid_autocomplete, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/roster remove", roster_barejid_autocomplete); + result = autocomplete_param_with_func(input, "/roster remove", roster_barejid_autocomplete, previous); if (result) { return result; } } - result = autocomplete_param_with_ac(input, "/roster remove_all", roster_remove_all_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster remove_all", roster_remove_all_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster show", roster_show_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster show", roster_show_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster hide", roster_show_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster hide", roster_show_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster by", roster_by_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster by", roster_by_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster count", roster_count_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster count", roster_count_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster order", roster_order_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster order", roster_order_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster unread", roster_unread_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster unread", roster_unread_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster room", roster_room_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster room", roster_room_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/roster wrap", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/roster wrap", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster header", roster_header_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster header", roster_header_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster contact", roster_contact_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster contact", roster_contact_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster resource", roster_resource_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster resource", roster_resource_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster presence", roster_presence_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster presence", roster_presence_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster private", roster_private_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster private", roster_private_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/roster", roster_ac, TRUE); + result = autocomplete_param_with_ac(input, "/roster", roster_ac, TRUE, previous); if (result) { return result; } @@ -1635,36 +1637,36 @@ _roster_autocomplete(ProfWin *window, const char *const input) } static char* -_group_autocomplete(ProfWin *window, const char *const input) +_group_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; jabber_conn_status_t conn_status = connection_get_status(); if (conn_status == JABBER_CONNECTED) { - result = autocomplete_param_with_func(input, "/group show", roster_group_autocomplete); + result = autocomplete_param_with_func(input, "/group show", roster_group_autocomplete, previous); if (result) { return result; } - result = autocomplete_param_no_with_func(input, "/group add", 4, roster_contact_autocomplete); + result = autocomplete_param_no_with_func(input, "/group add", 4, roster_contact_autocomplete, previous); if (result) { return result; } - result = autocomplete_param_no_with_func(input, "/group remove", 4, roster_contact_autocomplete); + result = autocomplete_param_no_with_func(input, "/group remove", 4, roster_contact_autocomplete, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/group add", roster_group_autocomplete); + result = autocomplete_param_with_func(input, "/group add", roster_group_autocomplete, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/group remove", roster_group_autocomplete); + result = autocomplete_param_with_func(input, "/group remove", roster_group_autocomplete, previous); if (result) { return result; } } - result = autocomplete_param_with_ac(input, "/group", group_ac, TRUE); + result = autocomplete_param_with_ac(input, "/group", group_ac, TRUE, previous); if (result) { return result; } @@ -1673,16 +1675,16 @@ _group_autocomplete(ProfWin *window, const char *const input) } static char* -_blocked_autocomplete(ProfWin *window, const char *const input) +_blocked_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_func(input, "/blocked remove", blocked_ac_find); + result = autocomplete_param_with_func(input, "/blocked remove", blocked_ac_find, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/blocked", blocked_ac, FALSE); + result = autocomplete_param_with_ac(input, "/blocked", blocked_ac, FALSE, previous); if (result) { return result; } @@ -1691,7 +1693,7 @@ _blocked_autocomplete(ProfWin *window, const char *const input) } static char* -_bookmark_autocomplete(ProfWin *window, const char *const input) +_bookmark_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; @@ -1704,7 +1706,7 @@ _bookmark_autocomplete(ProfWin *window, const char *const input) if ((num_args == 2 && space_at_end) || (num_args == 3 && !space_at_end)) { GString *beginning = g_string_new("/bookmark"); g_string_append_printf(beginning, " %s %s", args[0], args[1]); - found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -1715,7 +1717,7 @@ _bookmark_autocomplete(ProfWin *window, const char *const input) || (num_args == 4 && (g_strcmp0(args[2], "autojoin") == 0) && !space_at_end)) { GString *beginning = g_string_new("/bookmark"); g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]); - found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -1725,7 +1727,7 @@ _bookmark_autocomplete(ProfWin *window, const char *const input) if ((num_args == 4 && space_at_end) || (num_args == 5 && !space_at_end)) { GString *beginning = g_string_new("/bookmark"); g_string_append_printf(beginning, " %s %s %s %s", args[0], args[1], args[2], args[3]); - found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -1736,7 +1738,7 @@ _bookmark_autocomplete(ProfWin *window, const char *const input) || (num_args == 6 && (g_strcmp0(args[4], "autojoin") == 0) && !space_at_end)) { GString *beginning = g_string_new("/bookmark"); g_string_append_printf(beginning, " %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4]); - found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -1746,7 +1748,7 @@ _bookmark_autocomplete(ProfWin *window, const char *const input) if ((num_args == 6 && space_at_end) || (num_args == 7 && !space_at_end)) { GString *beginning = g_string_new("/bookmark"); g_string_append_printf(beginning, " %s %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4], args[5]); - found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -1757,7 +1759,7 @@ _bookmark_autocomplete(ProfWin *window, const char *const input) || (num_args == 8 && (g_strcmp0(args[6], "autojoin") == 0) && !space_at_end)) { GString *beginning = g_string_new("/bookmark"); g_string_append_printf(beginning, " %s %s %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -1768,34 +1770,34 @@ _bookmark_autocomplete(ProfWin *window, const char *const input) g_strfreev(args); - found = autocomplete_param_with_func(input, "/bookmark remove", bookmark_find); + found = autocomplete_param_with_func(input, "/bookmark remove", bookmark_find, previous); if (found) { return found; } - found = autocomplete_param_with_func(input, "/bookmark join", bookmark_find); + found = autocomplete_param_with_func(input, "/bookmark join", bookmark_find, previous); if (found) { return found; } - found = autocomplete_param_with_func(input, "/bookmark update", bookmark_find); + found = autocomplete_param_with_func(input, "/bookmark update", bookmark_find, previous); if (found) { return found; } - found = autocomplete_param_with_func(input, "/bookmark invites", prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, "/bookmark invites", prefs_autocomplete_boolean_choice, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/bookmark", bookmark_ac, TRUE); + found = autocomplete_param_with_ac(input, "/bookmark", bookmark_ac, TRUE, previous); return found; } static char* -_notify_autocomplete(ProfWin *window, const char *const input) +_notify_autocomplete(ProfWin *window, const char *const input, gboolean previous) { int i = 0; char *result = NULL; - result = autocomplete_param_with_func(input, "/notify room trigger remove", prefs_autocomplete_room_trigger); + result = autocomplete_param_with_func(input, "/notify room trigger remove", prefs_autocomplete_room_trigger, previous); if (result) { return result; } @@ -1803,46 +1805,46 @@ _notify_autocomplete(ProfWin *window, const char *const input) gchar *boolean_choices1[] = { "/notify room current", "/notify chat current", "/notify typing current", "/notify room text", "/notify chat text" }; for (i = 0; i < ARRAY_SIZE(boolean_choices1); i++) { - result = autocomplete_param_with_func(input, boolean_choices1[i], prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, boolean_choices1[i], prefs_autocomplete_boolean_choice, previous); if (result) { return result; } } - result = autocomplete_param_with_ac(input, "/notify room mention", notify_mention_ac, TRUE); + result = autocomplete_param_with_ac(input, "/notify room mention", notify_mention_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/notify room trigger", notify_trigger_ac, TRUE); + result = autocomplete_param_with_ac(input, "/notify room trigger", notify_trigger_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/notify room", notify_room_ac, TRUE); + result = autocomplete_param_with_ac(input, "/notify room", notify_room_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/notify chat", notify_chat_ac, TRUE); + result = autocomplete_param_with_ac(input, "/notify chat", notify_chat_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/notify typing", notify_typing_ac, TRUE); + result = autocomplete_param_with_ac(input, "/notify typing", notify_typing_ac, TRUE, previous); if (result) { return result; } gchar *boolean_choices2[] = { "/notify invite", "/notify sub", "/notify mention", "/notify trigger"}; for (i = 0; i < ARRAY_SIZE(boolean_choices2); i++) { - result = autocomplete_param_with_func(input, boolean_choices2[i], prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, boolean_choices2[i], prefs_autocomplete_boolean_choice, previous); if (result) { return result; } } - result = autocomplete_param_with_ac(input, "/notify", notify_ac, TRUE); + result = autocomplete_param_with_ac(input, "/notify", notify_ac, TRUE, previous); if (result) { return result; } @@ -1851,30 +1853,30 @@ _notify_autocomplete(ProfWin *window, const char *const input) } static char* -_autoaway_autocomplete(ProfWin *window, const char *const input) +_autoaway_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_ac(input, "/autoaway mode", autoaway_mode_ac, TRUE); + result = autocomplete_param_with_ac(input, "/autoaway mode", autoaway_mode_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/autoaway time", autoaway_presence_ac, TRUE); + result = autocomplete_param_with_ac(input, "/autoaway time", autoaway_presence_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/autoaway message", autoaway_presence_ac, TRUE); + result = autocomplete_param_with_ac(input, "/autoaway message", autoaway_presence_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/autoaway check", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/autoaway check", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/autoaway", autoaway_ac, TRUE); + result = autocomplete_param_with_ac(input, "/autoaway", autoaway_ac, TRUE, previous); if (result) { return result; } @@ -1883,19 +1885,19 @@ _autoaway_autocomplete(ProfWin *window, const char *const input) } static char* -_log_autocomplete(ProfWin *window, const char *const input) +_log_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_func(input, "/log rotate", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/log rotate", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/log shared", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/log shared", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/log", log_ac, TRUE); + result = autocomplete_param_with_ac(input, "/log", log_ac, TRUE, previous); if (result) { return result; } @@ -1904,16 +1906,16 @@ _log_autocomplete(ProfWin *window, const char *const input) } static char* -_autoconnect_autocomplete(ProfWin *window, const char *const input) +_autoconnect_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_func(input, "/autoconnect set", accounts_find_enabled); + result = autocomplete_param_with_func(input, "/autoconnect set", accounts_find_enabled, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/autoconnect", autoconnect_ac, TRUE); + result = autocomplete_param_with_ac(input, "/autoconnect", autoconnect_ac, TRUE, previous); if (result) { return result; } @@ -1922,20 +1924,20 @@ _autoconnect_autocomplete(ProfWin *window, const char *const input) } static char* -_otr_autocomplete(ProfWin *window, const char *const input) +_otr_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; jabber_conn_status_t conn_status = connection_get_status(); if (conn_status == JABBER_CONNECTED) { - found = autocomplete_param_with_func(input, "/otr start", roster_contact_autocomplete); + found = autocomplete_param_with_func(input, "/otr start", roster_contact_autocomplete, previous); if (found) { return found; } } - found = autocomplete_param_with_ac(input, "/otr log", otr_log_ac, TRUE); + found = autocomplete_param_with_ac(input, "/otr log", otr_log_ac, TRUE, previous); if (found) { return found; } @@ -1952,7 +1954,7 @@ _otr_autocomplete(ProfWin *window, const char *const input) g_string_append(beginning, args[1]); } - found = autocomplete_param_with_func(input, beginning->str, roster_contact_autocomplete); + found = autocomplete_param_with_func(input, beginning->str, roster_contact_autocomplete, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -1962,12 +1964,12 @@ _otr_autocomplete(ProfWin *window, const char *const input) g_strfreev(args); } - found = autocomplete_param_with_ac(input, "/otr policy", otr_policy_ac, TRUE); + found = autocomplete_param_with_ac(input, "/otr policy", otr_policy_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/otr", otr_ac, TRUE); + found = autocomplete_param_with_ac(input, "/otr", otr_ac, TRUE, previous); if (found) { return found; } @@ -1976,20 +1978,20 @@ _otr_autocomplete(ProfWin *window, const char *const input) } static char* -_pgp_autocomplete(ProfWin *window, const char *const input) +_pgp_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; jabber_conn_status_t conn_status = connection_get_status(); if (conn_status == JABBER_CONNECTED) { - found = autocomplete_param_with_func(input, "/pgp start", roster_contact_autocomplete); + found = autocomplete_param_with_func(input, "/pgp start", roster_contact_autocomplete, previous); if (found) { return found; } } - found = autocomplete_param_with_ac(input, "/pgp log", pgp_log_ac, TRUE); + found = autocomplete_param_with_ac(input, "/pgp log", pgp_log_ac, TRUE, previous); if (found) { return found; } @@ -2004,7 +2006,7 @@ _pgp_autocomplete(ProfWin *window, const char *const input) g_string_append(beginning, " "); g_string_append(beginning, args[1]); } - found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key); + found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2015,13 +2017,13 @@ _pgp_autocomplete(ProfWin *window, const char *const input) #endif if (conn_status == JABBER_CONNECTED) { - found = autocomplete_param_with_func(input, "/pgp setkey", roster_barejid_autocomplete); + found = autocomplete_param_with_func(input, "/pgp setkey", roster_barejid_autocomplete, previous); if (found) { return found; } } - found = autocomplete_param_with_ac(input, "/pgp", pgp_ac, TRUE); + found = autocomplete_param_with_ac(input, "/pgp", pgp_ac, TRUE, previous); if (found) { return found; } @@ -2030,20 +2032,20 @@ _pgp_autocomplete(ProfWin *window, const char *const input) } static char* -_plugins_autocomplete(ProfWin *window, const char *const input) +_plugins_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; if (strncmp(input, "/plugins sourcepath set ", 24) == 0) { - return cmd_ac_complete_filepath(input, "/plugins sourcepath set"); + return cmd_ac_complete_filepath(input, "/plugins sourcepath set", previous); } if (strncmp(input, "/plugins install ", 17) == 0) { - return cmd_ac_complete_filepath(input, "/plugins install"); + return cmd_ac_complete_filepath(input, "/plugins install", previous); } if (strncmp(input, "/plugins sourcepath ", 20) == 0) { - result = autocomplete_param_with_ac(input, "/plugins sourcepath", plugins_sourcepath_ac, TRUE); + result = autocomplete_param_with_ac(input, "/plugins sourcepath", plugins_sourcepath_ac, TRUE, previous); if (result) { return result; } @@ -2060,7 +2062,7 @@ _plugins_autocomplete(ProfWin *window, const char *const input) } g_slist_free_full(plugins, g_free); } - result = autocomplete_param_with_ac(input, "/plugins load", plugins_load_ac, TRUE); + result = autocomplete_param_with_ac(input, "/plugins load", plugins_load_ac, TRUE, previous); if (result) { return result; } @@ -2077,7 +2079,7 @@ _plugins_autocomplete(ProfWin *window, const char *const input) } g_list_free(plugins); } - result = autocomplete_param_with_ac(input, "/plugins reload", plugins_reload_ac, TRUE); + result = autocomplete_param_with_ac(input, "/plugins reload", plugins_reload_ac, TRUE, previous); if (result) { return result; } @@ -2094,13 +2096,13 @@ _plugins_autocomplete(ProfWin *window, const char *const input) } g_list_free(plugins); } - result = autocomplete_param_with_ac(input, "/plugins unload", plugins_unload_ac, TRUE); + result = autocomplete_param_with_ac(input, "/plugins unload", plugins_unload_ac, TRUE, previous); if (result) { return result; } } - result = autocomplete_param_with_ac(input, "/plugins", plugins_ac, TRUE); + result = autocomplete_param_with_ac(input, "/plugins", plugins_ac, TRUE, previous); if (result) { return result; } @@ -2109,7 +2111,7 @@ _plugins_autocomplete(ProfWin *window, const char *const input) } static char* -_theme_autocomplete(ProfWin *window, const char *const input) +_theme_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; if (strncmp(input, "/theme load ", 12) == 0) { @@ -2124,12 +2126,12 @@ _theme_autocomplete(ProfWin *window, const char *const input) g_slist_free_full(themes, g_free); autocomplete_add(theme_load_ac, "default"); } - result = autocomplete_param_with_ac(input, "/theme load", theme_load_ac, TRUE); + result = autocomplete_param_with_ac(input, "/theme load", theme_load_ac, TRUE, previous); if (result) { return result; } } - result = autocomplete_param_with_ac(input, "/theme", theme_ac, TRUE); + result = autocomplete_param_with_ac(input, "/theme", theme_ac, TRUE, previous); if (result) { return result; } @@ -2138,7 +2140,7 @@ _theme_autocomplete(ProfWin *window, const char *const input) } static char* -_script_autocomplete_func(const char *const prefix) +_script_autocomplete_func(const char *const prefix, gboolean previous) { if (script_show_ac == NULL) { script_show_ac = autocomplete_new(); @@ -2151,29 +2153,29 @@ _script_autocomplete_func(const char *const prefix) g_slist_free_full(scripts, g_free); } - return autocomplete_complete(script_show_ac, prefix, FALSE); + return autocomplete_complete(script_show_ac, prefix, FALSE, previous); } static char* -_script_autocomplete(ProfWin *window, const char *const input) +_script_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; if (strncmp(input, "/script show ", 13) == 0) { - result = autocomplete_param_with_func(input, "/script show", _script_autocomplete_func); + result = autocomplete_param_with_func(input, "/script show", _script_autocomplete_func, previous); if (result) { return result; } } if (strncmp(input, "/script run ", 12) == 0) { - result = autocomplete_param_with_func(input, "/script run", _script_autocomplete_func); + result = autocomplete_param_with_func(input, "/script run", _script_autocomplete_func, previous); if (result) { return result; } } - result = autocomplete_param_with_ac(input, "/script", script_ac, TRUE); + result = autocomplete_param_with_ac(input, "/script", script_ac, TRUE, previous); if (result) { return result; } @@ -2182,7 +2184,7 @@ _script_autocomplete(ProfWin *window, const char *const input) } static char* -_resource_autocomplete(ProfWin *window, const char *const input) +_resource_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; @@ -2193,24 +2195,24 @@ _resource_autocomplete(ProfWin *window, const char *const input) PContact contact = roster_get_contact(chatwin->barejid); if (contact) { Autocomplete ac = p_contact_resource_ac(contact); - found = autocomplete_param_with_ac(input, "/resource set", ac, FALSE); + found = autocomplete_param_with_ac(input, "/resource set", ac, FALSE, previous); if (found) { return found; } } } - found = autocomplete_param_with_func(input, "/resource title", prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, "/resource title", prefs_autocomplete_boolean_choice, previous); if (found) { return found; } - found = autocomplete_param_with_func(input, "/resource message", prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, "/resource message", prefs_autocomplete_boolean_choice, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/resource", resource_ac, FALSE); + found = autocomplete_param_with_ac(input, "/resource", resource_ac, FALSE, previous); if (found) { return found; } @@ -2219,21 +2221,21 @@ _resource_autocomplete(ProfWin *window, const char *const input) } static char* -_wintitle_autocomplete(ProfWin *window, const char *const input) +_wintitle_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; - found = autocomplete_param_with_func(input, "/wintitle show", prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, "/wintitle show", prefs_autocomplete_boolean_choice, previous); if (found) { return found; } - found = autocomplete_param_with_func(input, "/wintitle goodbye", prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, "/wintitle goodbye", prefs_autocomplete_boolean_choice, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/wintitle", wintitle_ac, FALSE); + found = autocomplete_param_with_ac(input, "/wintitle", wintitle_ac, FALSE, previous); if (found) { return found; } @@ -2242,16 +2244,16 @@ _wintitle_autocomplete(ProfWin *window, const char *const input) } static char* -_inpblock_autocomplete(ProfWin *window, const char *const input) +_inpblock_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; - found = autocomplete_param_with_func(input, "/inpblock dynamic", prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, "/inpblock dynamic", prefs_autocomplete_boolean_choice, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/inpblock", inpblock_ac, FALSE); + found = autocomplete_param_with_ac(input, "/inpblock", inpblock_ac, FALSE, previous); if (found) { return found; } @@ -2260,7 +2262,7 @@ _inpblock_autocomplete(ProfWin *window, const char *const input) } static char* -_form_autocomplete(ProfWin *window, const char *const input) +_form_autocomplete(ProfWin *window, const char *const input, gboolean previous) { if (window->type != WIN_MUC_CONFIG) { return NULL; @@ -2271,13 +2273,13 @@ _form_autocomplete(ProfWin *window, const char *const input) ProfMucConfWin *confwin = (ProfMucConfWin*)window; DataForm *form = confwin->form; if (form) { - found = autocomplete_param_with_ac(input, "/form help", form->tag_ac, TRUE); + found = autocomplete_param_with_ac(input, "/form help", form->tag_ac, TRUE, previous); if (found) { return found; } } - found = autocomplete_param_with_ac(input, "/form", form_ac, TRUE); + found = autocomplete_param_with_ac(input, "/form", form_ac, TRUE, previous); if (found) { return found; } @@ -2286,7 +2288,7 @@ _form_autocomplete(ProfWin *window, const char *const input) } static char* -_form_field_autocomplete(ProfWin *window, const char *const input) +_form_field_autocomplete(ProfWin *window, const char *const input, gboolean previous) { if (window->type != WIN_MUC_CONFIG) { return NULL; @@ -2313,13 +2315,13 @@ _form_field_autocomplete(ProfWin *window, const char *const input) if (((g_strcmp0(split[1], "add") == 0) || (g_strcmp0(split[1], "remove") == 0)) && field_type == FIELD_LIST_MULTI) { - found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE, previous); } else if ((g_strcmp0(split[1], "remove") == 0) && field_type == FIELD_TEXT_MULTI) { - found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE, previous); } else if ((g_strcmp0(split[1], "remove") == 0) && field_type == FIELD_JID_MULTI) { - found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE, previous); } g_string_free(beginning, TRUE); @@ -2334,15 +2336,15 @@ _form_field_autocomplete(ProfWin *window, const char *const input) switch (field_type) { case FIELD_BOOLEAN: - found = autocomplete_param_with_func(input, split[0], prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, split[0], prefs_autocomplete_boolean_choice, previous); break; case FIELD_LIST_SINGLE: - found = autocomplete_param_with_ac(input, split[0], value_ac, TRUE); + found = autocomplete_param_with_ac(input, split[0], value_ac, TRUE, previous); break; case FIELD_LIST_MULTI: case FIELD_JID_MULTI: case FIELD_TEXT_MULTI: - found = autocomplete_param_with_ac(input, split[0], form_field_multi_ac, TRUE); + found = autocomplete_param_with_ac(input, split[0], form_field_multi_ac, TRUE, previous); break; default: break; @@ -2356,36 +2358,36 @@ _form_field_autocomplete(ProfWin *window, const char *const input) } static char* -_occupants_autocomplete(ProfWin *window, const char *const input) +_occupants_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; - found = autocomplete_param_with_ac(input, "/occupants default show", occupants_show_ac, TRUE); + found = autocomplete_param_with_ac(input, "/occupants default show", occupants_show_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/occupants default hide", occupants_show_ac, TRUE); + found = autocomplete_param_with_ac(input, "/occupants default hide", occupants_show_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/occupants default", occupants_default_ac, TRUE); + found = autocomplete_param_with_ac(input, "/occupants default", occupants_default_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/occupants show", occupants_show_ac, TRUE); + found = autocomplete_param_with_ac(input, "/occupants show", occupants_show_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/occupants hide", occupants_show_ac, TRUE); + found = autocomplete_param_with_ac(input, "/occupants hide", occupants_show_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/occupants", occupants_ac, TRUE); + found = autocomplete_param_with_ac(input, "/occupants", occupants_ac, TRUE, previous); if (found) { return found; } @@ -2394,51 +2396,51 @@ _occupants_autocomplete(ProfWin *window, const char *const input) } static char* -_time_autocomplete(ProfWin *window, const char *const input) +_time_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; - found = autocomplete_param_with_ac(input, "/time statusbar", time_format_ac, TRUE); + found = autocomplete_param_with_ac(input, "/time statusbar", time_format_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/time lastactivity", time_format_ac, TRUE); + found = autocomplete_param_with_ac(input, "/time lastactivity", time_format_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/time console", time_format_ac, TRUE); + found = autocomplete_param_with_ac(input, "/time console", time_format_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/time chat", time_format_ac, TRUE); + found = autocomplete_param_with_ac(input, "/time chat", time_format_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/time muc", time_format_ac, TRUE); + found = autocomplete_param_with_ac(input, "/time muc", time_format_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/time mucconfig", time_format_ac, TRUE); + found = autocomplete_param_with_ac(input, "/time mucconfig", time_format_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/time private", time_format_ac, TRUE); + found = autocomplete_param_with_ac(input, "/time private", time_format_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/time xml", time_format_ac, TRUE); + found = autocomplete_param_with_ac(input, "/time xml", time_format_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/time", time_ac, TRUE); + found = autocomplete_param_with_ac(input, "/time", time_ac, TRUE, previous); if (found) { return found; } @@ -2447,7 +2449,7 @@ _time_autocomplete(ProfWin *window, const char *const input) } static char* -_kick_autocomplete(ProfWin *window, const char *const input) +_kick_autocomplete(ProfWin *window, const char *const input, gboolean previous) { if (window->type != WIN_MUC) { return NULL; @@ -2460,13 +2462,13 @@ _kick_autocomplete(ProfWin *window, const char *const input) return NULL; } - char *result = autocomplete_param_with_ac(input, "/kick", nick_ac, TRUE); + char *result = autocomplete_param_with_ac(input, "/kick", nick_ac, TRUE, previous); return result; } static char* -_ban_autocomplete(ProfWin *window, const char *const input) +_ban_autocomplete(ProfWin *window, const char *const input, gboolean previous) { if (window->type != WIN_MUC) { return NULL; @@ -2479,13 +2481,13 @@ _ban_autocomplete(ProfWin *window, const char *const input) return NULL; } - char *result = autocomplete_param_with_ac(input, "/ban", jid_ac, TRUE); + char *result = autocomplete_param_with_ac(input, "/ban", jid_ac, TRUE, previous); return result; } static char* -_affiliation_autocomplete(ProfWin *window, const char *const input) +_affiliation_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; @@ -2505,7 +2507,7 @@ _affiliation_autocomplete(ProfWin *window, const char *const input) g_string_append(beginning, args[1]); } - result = autocomplete_param_with_ac(input, beginning->str, jid_ac, TRUE); + result = autocomplete_param_with_ac(input, beginning->str, jid_ac, TRUE, previous); g_string_free(beginning, TRUE); if (result) { g_strfreev(args); @@ -2516,17 +2518,17 @@ _affiliation_autocomplete(ProfWin *window, const char *const input) g_strfreev(args); } - result = autocomplete_param_with_ac(input, "/affiliation set", affiliation_ac, TRUE); + result = autocomplete_param_with_ac(input, "/affiliation set", affiliation_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/affiliation list", affiliation_ac, TRUE); + result = autocomplete_param_with_ac(input, "/affiliation list", affiliation_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/affiliation", privilege_cmd_ac, TRUE); + result = autocomplete_param_with_ac(input, "/affiliation", privilege_cmd_ac, TRUE, previous); if (result) { return result; } @@ -2535,7 +2537,7 @@ _affiliation_autocomplete(ProfWin *window, const char *const input) } static char* -_role_autocomplete(ProfWin *window, const char *const input) +_role_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; @@ -2555,7 +2557,7 @@ _role_autocomplete(ProfWin *window, const char *const input) g_string_append(beginning, args[1]); } - result = autocomplete_param_with_ac(input, beginning->str, nick_ac, TRUE); + result = autocomplete_param_with_ac(input, beginning->str, nick_ac, TRUE, previous); g_string_free(beginning, TRUE); if (result) { g_strfreev(args); @@ -2566,17 +2568,17 @@ _role_autocomplete(ProfWin *window, const char *const input) g_strfreev(args); } - result = autocomplete_param_with_ac(input, "/role set", role_ac, TRUE); + result = autocomplete_param_with_ac(input, "/role set", role_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/role list", role_ac, TRUE); + result = autocomplete_param_with_ac(input, "/role list", role_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/role", privilege_cmd_ac, TRUE); + result = autocomplete_param_with_ac(input, "/role", privilege_cmd_ac, TRUE, previous); if (result) { return result; } @@ -2585,16 +2587,16 @@ _role_autocomplete(ProfWin *window, const char *const input) } static char* -_wins_autocomplete(ProfWin *window, const char *const input) +_wins_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_func(input, "/wins autotidy", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/wins autotidy", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/wins", wins_ac, TRUE); + result = autocomplete_param_with_ac(input, "/wins", wins_ac, TRUE, previous); if (result) { return result; } @@ -2603,31 +2605,31 @@ _wins_autocomplete(ProfWin *window, const char *const input) } static char* -_tls_autocomplete(ProfWin *window, const char *const input) +_tls_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_func(input, "/tls revoke", tlscerts_complete); + result = autocomplete_param_with_func(input, "/tls revoke", tlscerts_complete, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/tls cert", tlscerts_complete); + result = autocomplete_param_with_func(input, "/tls cert", tlscerts_complete, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/tls certpath", tls_certpath_ac, TRUE); + result = autocomplete_param_with_ac(input, "/tls certpath", tls_certpath_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/tls show", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/tls show", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/tls", tls_ac, TRUE); + result = autocomplete_param_with_ac(input, "/tls", tls_ac, TRUE, previous); if (result) { return result; } @@ -2636,21 +2638,21 @@ _tls_autocomplete(ProfWin *window, const char *const input) } static char* -_receipts_autocomplete(ProfWin *window, const char *const input) +_receipts_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_func(input, "/receipts send", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/receipts send", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } - result = autocomplete_param_with_func(input, "/receipts request", prefs_autocomplete_boolean_choice); + result = autocomplete_param_with_func(input, "/receipts request", prefs_autocomplete_boolean_choice, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/receipts", receipts_ac, TRUE); + result = autocomplete_param_with_ac(input, "/receipts", receipts_ac, TRUE, previous); if (result) { return result; } @@ -2659,16 +2661,16 @@ _receipts_autocomplete(ProfWin *window, const char *const input) } static char* -_alias_autocomplete(ProfWin *window, const char *const input) +_alias_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_ac(input, "/alias remove", aliases_ac, TRUE); + result = autocomplete_param_with_ac(input, "/alias remove", aliases_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/alias", alias_ac, TRUE); + result = autocomplete_param_with_ac(input, "/alias", alias_ac, TRUE, previous); if (result) { return result; } @@ -2677,7 +2679,7 @@ _alias_autocomplete(ProfWin *window, const char *const input) } static char* -_connect_autocomplete(ProfWin *window, const char *const input) +_connect_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; gboolean result = FALSE; @@ -2690,7 +2692,7 @@ _connect_autocomplete(ProfWin *window, const char *const input) if ((num_args == 1 && space_at_end) || (num_args == 2 && !space_at_end)) { GString *beginning = g_string_new("/connect"); g_string_append_printf(beginning, " %s", args[0]); - found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2701,7 +2703,7 @@ _connect_autocomplete(ProfWin *window, const char *const input) || (num_args == 3 && (g_strcmp0(args[1], "tls") == 0) && !space_at_end)) { GString *beginning = g_string_new("/connect"); g_string_append_printf(beginning, " %s %s", args[0], args[1]); - found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2711,7 +2713,7 @@ _connect_autocomplete(ProfWin *window, const char *const input) if ((num_args == 3 && space_at_end) || (num_args == 4 && !space_at_end)) { GString *beginning = g_string_new("/connect"); g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]); - found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2722,7 +2724,7 @@ _connect_autocomplete(ProfWin *window, const char *const input) || (num_args == 5 && (g_strcmp0(args[3], "tls") == 0) && !space_at_end)) { GString *beginning = g_string_new("/connect"); g_string_append_printf(beginning, " %s %s %s %s", args[0], args[1], args[2], args[3]); - found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2732,7 +2734,7 @@ _connect_autocomplete(ProfWin *window, const char *const input) if ((num_args == 5 && space_at_end) || (num_args == 6 && !space_at_end)) { GString *beginning = g_string_new("/connect"); g_string_append_printf(beginning, " %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4]); - found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2743,7 +2745,7 @@ _connect_autocomplete(ProfWin *window, const char *const input) || (num_args == 7 && (g_strcmp0(args[5], "tls") == 0) && !space_at_end)) { GString *beginning = g_string_new("/connect"); g_string_append_printf(beginning, " %s %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4], args[5]); - found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2754,7 +2756,7 @@ _connect_autocomplete(ProfWin *window, const char *const input) g_strfreev(args); - found = autocomplete_param_with_func(input, "/connect", accounts_find_enabled); + found = autocomplete_param_with_func(input, "/connect", accounts_find_enabled, previous); if (found) { return found; } @@ -2763,16 +2765,16 @@ _connect_autocomplete(ProfWin *window, const char *const input) } static char* -_help_autocomplete(ProfWin *window, const char *const input) +_help_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_ac(input, "/help commands", help_commands_ac, TRUE); + result = autocomplete_param_with_ac(input, "/help commands", help_commands_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/help", help_ac, TRUE); + result = autocomplete_param_with_ac(input, "/help", help_ac, TRUE, previous); if (result) { return result; } @@ -2781,7 +2783,7 @@ _help_autocomplete(ProfWin *window, const char *const input) } static char* -_join_autocomplete(ProfWin *window, const char *const input) +_join_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; gboolean result = FALSE; @@ -2794,7 +2796,7 @@ _join_autocomplete(ProfWin *window, const char *const input) if ((num_args == 1 && space_at_end) || (num_args == 2 && !space_at_end)) { GString *beginning = g_string_new("/join"); g_string_append_printf(beginning, " %s", args[0]); - found = autocomplete_param_with_ac(input, beginning->str, join_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, join_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2804,7 +2806,7 @@ _join_autocomplete(ProfWin *window, const char *const input) if ((num_args == 3 && space_at_end) || (num_args == 4 && !space_at_end)) { GString *beginning = g_string_new("/join"); g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]); - found = autocomplete_param_with_ac(input, beginning->str, join_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, join_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2815,7 +2817,7 @@ _join_autocomplete(ProfWin *window, const char *const input) g_strfreev(args); - found = autocomplete_param_with_func(input, "/join", bookmark_find); + found = autocomplete_param_with_func(input, "/join", bookmark_find, previous); if (found) { return found; } @@ -2824,24 +2826,24 @@ _join_autocomplete(ProfWin *window, const char *const input) } static char* -_console_autocomplete(ProfWin *window, const char *const input) +_console_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; - result = autocomplete_param_with_ac(input, "/console chat", console_msg_ac, TRUE); + result = autocomplete_param_with_ac(input, "/console chat", console_msg_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/console muc", console_msg_ac, TRUE); + result = autocomplete_param_with_ac(input, "/console muc", console_msg_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/console private", console_msg_ac, TRUE); + result = autocomplete_param_with_ac(input, "/console private", console_msg_ac, TRUE, previous); if (result) { return result; } - result = autocomplete_param_with_ac(input, "/console", console_ac, TRUE); + result = autocomplete_param_with_ac(input, "/console", console_ac, TRUE, previous); if (result) { return result; } @@ -2850,25 +2852,25 @@ _console_autocomplete(ProfWin *window, const char *const input) } static char* -_win_autocomplete(ProfWin *window, const char *const input) +_win_autocomplete(ProfWin *window, const char *const input, gboolean previous) { - return autocomplete_param_with_func(input, "/win", win_autocomplete); + return autocomplete_param_with_func(input, "/win", win_autocomplete, previous); } static char* -_close_autocomplete(ProfWin *window, const char *const input) +_close_autocomplete(ProfWin *window, const char *const input, gboolean previous) { - return autocomplete_param_with_func(input, "/close", win_close_autocomplete); + return autocomplete_param_with_func(input, "/close", win_close_autocomplete, previous); } static char* -_sendfile_autocomplete(ProfWin *window, const char *const input) +_sendfile_autocomplete(ProfWin *window, const char *const input, gboolean previous) { - return cmd_ac_complete_filepath(input, "/sendfile"); + return cmd_ac_complete_filepath(input, "/sendfile", previous); } static char* -_correct_autocomplete(ProfWin *window, const char *const input) +_correct_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *last_message = NULL; switch(window->type) { @@ -2896,7 +2898,7 @@ _correct_autocomplete(ProfWin *window, const char *const input) } static char* -_subject_autocomplete(ProfWin *window, const char *const input) +_subject_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; @@ -2925,7 +2927,7 @@ _subject_autocomplete(ProfWin *window, const char *const input) return result; } - result = autocomplete_param_with_ac(input, "/subject", subject_ac, TRUE); + result = autocomplete_param_with_ac(input, "/subject", subject_ac, TRUE, previous); if (result) { return result; } @@ -2934,7 +2936,7 @@ _subject_autocomplete(ProfWin *window, const char *const input) } static char* -_account_autocomplete(ProfWin *window, const char *const input) +_account_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; gboolean result = FALSE; @@ -2946,7 +2948,7 @@ _account_autocomplete(ProfWin *window, const char *const input) if ((num_args == 2 && space_at_end) || (num_args == 3 && !space_at_end)) { GString *beginning = g_string_new("/account"); g_string_append_printf(beginning, " %s %s", args[0], args[1]); - found = autocomplete_param_with_ac(input, beginning->str, account_set_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, account_set_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2957,7 +2959,7 @@ _account_autocomplete(ProfWin *window, const char *const input) || (num_args == 4 && (g_strcmp0(args[2], "otr") == 0) && !space_at_end)) { GString *beginning = g_string_new("/account"); g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]); - found = autocomplete_param_with_ac(input, beginning->str, otr_policy_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, otr_policy_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2968,7 +2970,7 @@ _account_autocomplete(ProfWin *window, const char *const input) || (num_args == 4 && (g_strcmp0(args[2], "status") == 0) && !space_at_end)) { GString *beginning = g_string_new("/account"); g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]); - found = autocomplete_param_with_ac(input, beginning->str, account_status_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, account_status_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2979,7 +2981,7 @@ _account_autocomplete(ProfWin *window, const char *const input) || (num_args == 4 && (g_strcmp0(args[2], "tls") == 0) && !space_at_end)) { GString *beginning = g_string_new("/account"); g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]); - found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -2990,7 +2992,7 @@ _account_autocomplete(ProfWin *window, const char *const input) || (num_args == 4 && (g_strcmp0(args[2], "startscript") == 0) && !space_at_end)) { GString *beginning = g_string_new("/account"); g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]); - found = autocomplete_param_with_func(input, beginning->str, _script_autocomplete_func); + found = autocomplete_param_with_func(input, beginning->str, _script_autocomplete_func, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -3012,7 +3014,7 @@ _account_autocomplete(ProfWin *window, const char *const input) g_slist_free_full(themes, g_free); autocomplete_add(theme_load_ac, "default"); } - found = autocomplete_param_with_ac(input, beginning->str, theme_load_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, theme_load_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -3024,7 +3026,7 @@ _account_autocomplete(ProfWin *window, const char *const input) || (num_args == 4 && (g_strcmp0(args[2], "pgpkeyid") == 0) && !space_at_end)) { GString *beginning = g_string_new("/account"); g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]); - found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key); + found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -3037,7 +3039,7 @@ _account_autocomplete(ProfWin *window, const char *const input) if ((strncmp(input, "/account clear", 14) == 0) && (result == TRUE)) { GString *beginning = g_string_new("/account clear "); g_string_append(beginning, args[1]); - found = autocomplete_param_with_ac(input, beginning->str, account_clear_ac, TRUE); + found = autocomplete_param_with_ac(input, beginning->str, account_clear_ac, TRUE, previous); g_string_free(beginning, TRUE); if (found) { g_strfreev(args); @@ -3047,7 +3049,7 @@ _account_autocomplete(ProfWin *window, const char *const input) g_strfreev(args); - found = autocomplete_param_with_ac(input, "/account default", account_default_ac, TRUE); + found = autocomplete_param_with_ac(input, "/account default", account_default_ac, TRUE, previous); if(found){ return found; } @@ -3058,42 +3060,42 @@ _account_autocomplete(ProfWin *window, const char *const input) "/account default set" }; for (i = 0; i < ARRAY_SIZE(account_choice); i++) { - found = autocomplete_param_with_func(input, account_choice[i], accounts_find_all); + found = autocomplete_param_with_func(input, account_choice[i], accounts_find_all, previous); if (found) { return found; } } - found = autocomplete_param_with_ac(input, "/account", account_ac, TRUE); + found = autocomplete_param_with_ac(input, "/account", account_ac, TRUE, previous); return found; } static char* -_presence_autocomplete(ProfWin *window, const char *const input) +_presence_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *found = NULL; - found = autocomplete_param_with_func(input, "/presence titlebar", prefs_autocomplete_boolean_choice); + found = autocomplete_param_with_func(input, "/presence titlebar", prefs_autocomplete_boolean_choice, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/presence console", presence_setting_ac, TRUE); + found = autocomplete_param_with_ac(input, "/presence console", presence_setting_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/presence chat", presence_setting_ac, TRUE); + found = autocomplete_param_with_ac(input, "/presence chat", presence_setting_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/presence room", presence_setting_ac, TRUE); + found = autocomplete_param_with_ac(input, "/presence room", presence_setting_ac, TRUE, previous); if (found) { return found; } - found = autocomplete_param_with_ac(input, "/presence", presence_ac, TRUE); + found = autocomplete_param_with_ac(input, "/presence", presence_ac, TRUE, previous); if (found) { return found; } diff --git a/src/command/cmd_ac.h b/src/command/cmd_ac.h index b5e2f7d6..d56d0e30 100644 --- a/src/command/cmd_ac.h +++ b/src/command/cmd_ac.h @@ -40,7 +40,7 @@ void cmd_ac_init(void); void cmd_ac_uninit(void); -char* cmd_ac_complete(ProfWin *window, const char *const input); +char* cmd_ac_complete(ProfWin *window, const char *const input, gboolean previous); void cmd_ac_reset(ProfWin *window); gboolean cmd_ac_exists(char *cmd); @@ -57,6 +57,6 @@ void cmd_ac_remove_alias_value(char *value); void cmd_ac_add_form_fields(DataForm *form); void cmd_ac_remove_form_fields(DataForm *form); -char* cmd_ac_complete_filepath(const char *const input, char *const startstr); +char* cmd_ac_complete_filepath(const char *const input, char *const startstr, gboolean previous); #endif diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 312c4b74..55f46fbd 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -113,12 +113,12 @@ static gboolean _cmd_has_tag(Command *pcmd, const char *const tag); static struct cmd_t command_defs[] = { { "/help", - parse_args, 0, 2, NULL, + parse_args_with_freetext, 0, 2, NULL, CMD_NOSUBFUNCS CMD_MAINFUNC(cmd_help) CMD_NOTAGS CMD_SYN( - "/help [|]") + "/help [||search_all|search_any] []") CMD_DESC( "Help on using Profanity. Passing no arguments list help areas. " "For command help, optional arguments are shown using square brackets, " @@ -126,9 +126,12 @@ static struct cmd_t command_defs[] = "Arguments that may be one of a number of values are separated by a pipe " "e.g. val1|val2|val3.") CMD_ARGS( - { "", "Summary help for commands in a certain area of functionality." }, - { "", "Full help for a specific command, for example '/help connect'." }) + { "", "Summary help for commands in a certain area of functionality." }, + { "", "Full help for a specific command, for example '/help connect'." }, + { "search_all ", "Search commands for returning matches that contain all of the search terms." }, + { "search_any ", "Search commands for returning matches that contain any of the search terms." }) CMD_EXAMPLES( + "/help search_all presence online", "/help commands", "/help presence", "/help who") @@ -2283,6 +2286,110 @@ static struct cmd_t command_defs[] = } }; +static GHashTable *search_index; + +char* +_cmd_index(Command *cmd) { + GString *index_source = g_string_new(""); + index_source = g_string_append(index_source, cmd->cmd); + index_source = g_string_append(index_source, " "); + index_source = g_string_append(index_source, cmd->help.desc); + index_source = g_string_append(index_source, " "); + + int len = g_strv_length(cmd->help.tags); + int i = 0; + for (i = 0; i < len; i++) { + index_source = g_string_append(index_source, cmd->help.tags[i]); + index_source = g_string_append(index_source, " "); + } + len = g_strv_length(cmd->help.synopsis); + for (i = 0; i < len; i++) { + index_source = g_string_append(index_source, cmd->help.synopsis[i]); + index_source = g_string_append(index_source, " "); + } + for (i = 0; cmd->help.args[i][0] != NULL; i++) { + index_source = g_string_append(index_source, cmd->help.args[i][0]); + index_source = g_string_append(index_source, " "); + index_source = g_string_append(index_source, cmd->help.args[i][1]); + index_source = g_string_append(index_source, " "); + } + + gchar **tokens = g_str_tokenize_and_fold(index_source->str, NULL, NULL); + g_string_free(index_source, TRUE); + + GString *index = g_string_new(""); + i = 0; + for (i = 0; i < g_strv_length(tokens); i++) { + index = g_string_append(index, tokens[i]); + index = g_string_append(index, " "); + } + g_strfreev(tokens); + + char *res = index->str; + g_string_free(index, FALSE); + + return res; +} + +GList* +cmd_search_index_any(char *term) +{ + GList *results = NULL; + + gchar **processed_terms = g_str_tokenize_and_fold(term, NULL, NULL); + int terms_len = g_strv_length(processed_terms); + + int i = 0; + for (i = 0; i < terms_len; i++) { + GList *index_keys = g_hash_table_get_keys(search_index); + GList *curr = index_keys; + while (curr) { + char *index_entry = g_hash_table_lookup(search_index, curr->data); + if (g_str_match_string(processed_terms[i], index_entry, FALSE)) { + results = g_list_append(results, curr->data); + } + curr = g_list_next(curr); + } + g_list_free(index_keys); + } + + g_strfreev(processed_terms); + + return results; +} + +GList* +cmd_search_index_all(char *term) +{ + GList *results = NULL; + + gchar **terms = g_str_tokenize_and_fold(term, NULL, NULL); + int terms_len = g_strv_length(terms); + + GList *commands = g_hash_table_get_keys(search_index); + GList *curr = commands; + while (curr) { + char *command = curr->data; + int matches = 0; + int i = 0; + for (i = 0; i < terms_len; i++) { + char *command_index = g_hash_table_lookup(search_index, command); + if (g_str_match_string(terms[i], command_index, FALSE)) { + matches++; + } + } + if (matches == terms_len) { + results = g_list_append(results, command); + } + curr = g_list_next(curr); + } + + g_list_free(commands); + g_strfreev(terms); + + return results; +} + /* * Initialise command autocompleter and history */ @@ -2293,6 +2400,8 @@ cmd_init(void) cmd_ac_init(); + search_index = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); + // load command defs into hash table commands = g_hash_table_new(g_str_hash, g_str_equal); unsigned int i; @@ -2302,6 +2411,9 @@ cmd_init(void) // add to hash g_hash_table_insert(commands, pcmd->cmd, pcmd); + // add to search index + g_hash_table_insert(search_index, strdup(pcmd->cmd), strdup(_cmd_index(pcmd))); + // add to commands and help autocompleters cmd_ac_add_cmd(pcmd); } @@ -2321,6 +2433,7 @@ void cmd_uninit(void) { cmd_ac_uninit(); + g_hash_table_destroy(search_index); } gboolean diff --git a/src/command/cmd_defs.h b/src/command/cmd_defs.h index 074970c9..e0cadaf2 100644 --- a/src/command/cmd_defs.h +++ b/src/command/cmd_defs.h @@ -49,4 +49,7 @@ gboolean cmd_valid_tag(const char *const str); void command_docgen(void); +GList* cmd_search_index_all(char *term); +GList* cmd_search_index_any(char *term); + #endif diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index d70d435d..eed417cb 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -1484,6 +1484,41 @@ cmd_win(ProfWin *window, const char *const command, gchar **args) return TRUE; } +static void +_cmd_list_commands(GList *commands) { + int maxlen = 0; + GList *curr = commands; + while (curr) { + gchar *cmd = curr->data; + int len = strlen(cmd); + if (len > maxlen) maxlen = len; + curr = g_list_next(curr); + } + + GString *cmds = g_string_new(""); + curr = commands; + int count = 0; + while (curr) { + gchar *cmd = curr->data; + if (count == 5) { + cons_show(cmds->str); + g_string_free(cmds, TRUE); + cmds = g_string_new(""); + count = 0; + } + g_string_append_printf(cmds, "%-*s", maxlen + 1, cmd); + curr = g_list_next(curr); + count++; + } + cons_show(cmds->str); + g_string_free(cmds, TRUE); + g_list_free(curr); + + cons_show(""); + cons_show("Use /help [command] without the leading slash, for help on a specific command"); + cons_show(""); +} + static void _cmd_help_cmd_list(const char *const tag) { @@ -1520,38 +1555,8 @@ _cmd_help_cmd_list(const char *const tag) } } - int maxlen = 0; - GList *curr = ordered_commands; - while (curr) { - gchar *cmd = curr->data; - int len = strlen(cmd); - if (len > maxlen) maxlen = len; - curr = g_list_next(curr); - } - - GString *cmds = g_string_new(""); - curr = ordered_commands; - int count = 0; - while (curr) { - gchar *cmd = curr->data; - if (count == 5) { - cons_show(cmds->str); - g_string_free(cmds, TRUE); - cmds = g_string_new(""); - count = 0; - } - g_string_append_printf(cmds, "%-*s", maxlen + 1, cmd); - curr = g_list_next(curr); - count++; - } - cons_show(cmds->str); - g_string_free(cmds, TRUE); + _cmd_list_commands(ordered_commands); g_list_free(ordered_commands); - g_list_free(curr); - - cons_show(""); - cons_show("Use /help [command] without the leading slash, for help on a specific command"); - cons_show(""); } gboolean @@ -1560,6 +1565,46 @@ cmd_help(ProfWin *window, const char *const command, gchar **args) int num_args = g_strv_length(args); if (num_args == 0) { cons_help(); + } else if (strcmp(args[0], "search_all") == 0) { + if (args[1] == NULL) { + cons_bad_cmd_usage(command); + } else { + GList *cmds = cmd_search_index_all(args[1]); + if (cmds == NULL) { + cons_show("No commands found."); + } else { + GList *curr = cmds; + GList *results = NULL; + while (curr) { + results = g_list_insert_sorted(results, curr->data, (GCompareFunc)g_strcmp0); + curr = g_list_next(curr); + } + cons_show("Search results:"); + _cmd_list_commands(results); + g_list_free(results); + } + g_list_free(cmds); + } + } else if (strcmp(args[0], "search_any") == 0) { + if (args[1] == NULL) { + cons_bad_cmd_usage(command); + } else { + GList *cmds = cmd_search_index_any(args[1]); + if (cmds == NULL) { + cons_show("No commands found."); + } else { + GList *curr = cmds; + GList *results = NULL; + while (curr) { + results = g_list_insert_sorted(results, curr->data, (GCompareFunc)g_strcmp0); + curr = g_list_next(curr); + } + cons_show("Search results:"); + _cmd_list_commands(results); + g_list_free(results); + } + g_list_free(cmds); + } } else if (strcmp(args[0], "commands") == 0) { if (args[1]) { if (!cmd_valid_tag(args[1])) { @@ -2133,16 +2178,16 @@ cmd_group(ProfWin *window, const char *const command, gchar **args) // list all groups if (args[0] == NULL) { - GSList *groups = roster_get_groups(); - GSList *curr = groups; + GList *groups = roster_get_groups(); + GList *curr = groups; if (curr) { cons_show("Groups:"); while (curr) { cons_show(" %s", curr->data); - curr = g_slist_next(curr); + curr = g_list_next(curr); } - g_slist_free_full(groups, g_free); + g_list_free_full(groups, g_free); } else { cons_show("No groups."); } @@ -3562,9 +3607,9 @@ cmd_invite(ProfWin *window, const char *const command, gchar **args) gboolean cmd_invites(ProfWin *window, const char *const command, gchar **args) { - GSList *invites = muc_invites(); + GList *invites = muc_invites(); cons_show_room_invites(invites); - g_slist_free_full(invites, g_free); + g_list_free_full(invites, g_free); return TRUE; } diff --git a/src/common.c b/src/common.c index d9c7d73f..fa3af68c 100644 --- a/src/common.c +++ b/src/common.c @@ -467,11 +467,18 @@ prof_occurrences(const char *const needle, const char *const haystack, int offse gchar *needle_last_ch = g_utf8_offset_to_pointer(needle, g_utf8_strlen(needle, -1)- 1); int needle_last_ch_len = mblen(needle_last_ch, MB_CUR_MAX); - gchar *haystack_before_ch = g_utf8_prev_char(haystack_curr); - gchar *haystack_after_ch = g_utf8_next_char(haystack_curr + strlen(needle) - needle_last_ch_len); + gunichar before = 0; + gchar *haystack_before_ch = g_utf8_find_prev_char(haystack, haystack_curr); + if (haystack_before_ch) { + before = g_utf8_get_char(haystack_before_ch); + } + + gunichar after = 0; + gchar *haystack_after_ch = g_utf8_find_next_char(haystack_curr + strlen(needle) - needle_last_ch_len, NULL); + if (haystack_after_ch) { + after = g_utf8_get_char(haystack_after_ch); + } - gunichar before = g_utf8_get_char(haystack_before_ch); - gunichar after = g_utf8_get_char(haystack_after_ch); if (!g_unichar_isalnum(before) && !g_unichar_isalnum(after)) { *result = g_slist_append(*result, GINT_TO_POINTER(offset)); } diff --git a/src/config/accounts.c b/src/config/accounts.c index fd57a177..fb7b4a0e 100644 --- a/src/config/accounts.c +++ b/src/config/accounts.c @@ -96,15 +96,15 @@ accounts_close(void) } char* -accounts_find_enabled(const char *const prefix) +accounts_find_enabled(const char *const prefix, gboolean previous) { - return autocomplete_complete(enabled_ac, prefix, TRUE); + return autocomplete_complete(enabled_ac, prefix, TRUE, previous); } char* -accounts_find_all(const char *const prefix) +accounts_find_all(const char *const prefix, gboolean previous) { - return autocomplete_complete(all_ac, prefix, TRUE); + return autocomplete_complete(all_ac, prefix, TRUE, previous); } void diff --git a/src/config/accounts.h b/src/config/accounts.h index f5735f07..51969ab8 100644 --- a/src/config/accounts.h +++ b/src/config/accounts.h @@ -43,8 +43,8 @@ void accounts_load(void); void accounts_close(void); -char* accounts_find_all(const char *const prefix); -char* accounts_find_enabled(const char *const prefix); +char* accounts_find_all(const char *const prefix, gboolean previous); +char* accounts_find_enabled(const char *const prefix, gboolean previous); void accounts_reset_all_search(void); void accounts_reset_enabled_search(void); void accounts_add(const char *jid, const char *altdomain, const int port, const char *const tls_policy); diff --git a/src/config/preferences.c b/src/config/preferences.c index 11fa7d9e..347caf27 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -183,9 +183,9 @@ prefs_close(void) } char* -prefs_autocomplete_boolean_choice(const char *const prefix) +prefs_autocomplete_boolean_choice(const char *const prefix, gboolean previous) { - return autocomplete_complete(boolean_choice_ac, prefix, TRUE); + return autocomplete_complete(boolean_choice_ac, prefix, TRUE, previous); } void @@ -195,9 +195,9 @@ prefs_reset_boolean_choice(void) } char* -prefs_autocomplete_room_trigger(const char *const prefix) +prefs_autocomplete_room_trigger(const char *const prefix, gboolean previous) { - return autocomplete_complete(room_trigger_ac, prefix, TRUE); + return autocomplete_complete(room_trigger_ac, prefix, TRUE, previous); } void diff --git a/src/config/preferences.h b/src/config/preferences.h index 235534b5..19b9c4a5 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -162,10 +162,10 @@ void prefs_close(void); char* prefs_find_login(char *prefix); void prefs_reset_login_search(void); -char* prefs_autocomplete_boolean_choice(const char *const prefix); +char* prefs_autocomplete_boolean_choice(const char *const prefix, gboolean previous); void prefs_reset_boolean_choice(void); -char* prefs_autocomplete_room_trigger(const char *const prefix); +char* prefs_autocomplete_room_trigger(const char *const prefix, gboolean previous); void prefs_reset_room_trigger_ac(void); gint prefs_get_gone(void); diff --git a/src/config/tlscerts.c b/src/config/tlscerts.c index a664eabb..39733405 100644 --- a/src/config/tlscerts.c +++ b/src/config/tlscerts.c @@ -368,9 +368,9 @@ tlscerts_get_trusted(const char * const fingerprint) } char* -tlscerts_complete(const char *const prefix) +tlscerts_complete(const char *const prefix, gboolean previous) { - return autocomplete_complete(certs_ac, prefix, TRUE); + return autocomplete_complete(certs_ac, prefix, TRUE, previous); } void diff --git a/src/config/tlscerts.h b/src/config/tlscerts.h index c32412de..e1a1758f 100644 --- a/src/config/tlscerts.h +++ b/src/config/tlscerts.h @@ -89,7 +89,7 @@ void tlscerts_free(TLSCertificate *cert); GList* tlscerts_list(void); -char* tlscerts_complete(const char *const prefix); +char* tlscerts_complete(const char *const prefix, gboolean previous); void tlscerts_reset_ac(void); diff --git a/src/pgp/gpg.c b/src/pgp/gpg.c index 2a875404..051f99f0 100644 --- a/src/pgp/gpg.c +++ b/src/pgp/gpg.c @@ -749,9 +749,9 @@ p_gpg_free_decrypted(char *decrypted) } char* -p_gpg_autocomplete_key(const char *const search_str) +p_gpg_autocomplete_key(const char *const search_str, gboolean previous) { - return autocomplete_complete(key_ac, search_str, TRUE); + return autocomplete_complete(key_ac, search_str, TRUE, previous); } void diff --git a/src/pgp/gpg.h b/src/pgp/gpg.h index 81128df2..8377b05d 100644 --- a/src/pgp/gpg.h +++ b/src/pgp/gpg.h @@ -67,7 +67,7 @@ void p_gpg_verify(const char *const barejid, const char *const sign); char* p_gpg_encrypt(const char *const barejid, const char *const message, const char *const fp); char* p_gpg_decrypt(const char *const cipher); void p_gpg_free_decrypted(char *decrypted); -char* p_gpg_autocomplete_key(const char *const search_str); +char* p_gpg_autocomplete_key(const char *const search_str, gboolean previous); void p_gpg_autocomplete_key_reset(void); char* p_gpg_format_fp_str(char *fp); diff --git a/src/plugins/autocompleters.c b/src/plugins/autocompleters.c index 1f0d3c4c..20abaddf 100644 --- a/src/plugins/autocompleters.c +++ b/src/plugins/autocompleters.c @@ -129,7 +129,7 @@ autocompleters_filepath_add(const char *const plugin_name, const char *prefix) } char* -autocompleters_complete(const char * const input) +autocompleters_complete(const char * const input, gboolean previous) { char *result = NULL; @@ -141,7 +141,7 @@ autocompleters_complete(const char * const input) GList *keys = g_hash_table_get_keys(key_to_ac); GList *curr = keys; while (curr) { - result = autocomplete_param_with_ac(input, curr->data, g_hash_table_lookup(key_to_ac, curr->data), TRUE); + result = autocomplete_param_with_ac(input, curr->data, g_hash_table_lookup(key_to_ac, curr->data), TRUE, previous); if (result) { g_list_free(ac_hashes); g_list_free(keys); @@ -164,7 +164,7 @@ autocompleters_complete(const char * const input) while (curr_prefix) { char *prefix = curr_prefix->data; if (g_str_has_prefix(input, prefix)) { - result = cmd_ac_complete_filepath(input, prefix); + result = cmd_ac_complete_filepath(input, prefix, previous); if (result) { g_list_free(filepath_hashes); g_list_free(prefixes); diff --git a/src/plugins/autocompleters.h b/src/plugins/autocompleters.h index 2d6b072d..37539e27 100644 --- a/src/plugins/autocompleters.h +++ b/src/plugins/autocompleters.h @@ -42,7 +42,7 @@ void autocompleters_add(const char *const plugin_name, const char *key, char **i void autocompleters_remove(const char *const plugin_name, const char *key, char **items); void autocompleters_clear(const char *const plugin_name, const char *key); void autocompleters_filepath_add(const char *const plugin_name, const char *prefix); -char* autocompleters_complete(const char * const input); +char* autocompleters_complete(const char * const input, gboolean previous); void autocompleters_reset(void); void autocompleters_destroy(void); diff --git a/src/plugins/plugins.c b/src/plugins/plugins.c index 92d605e8..06b1417f 100644 --- a/src/plugins/plugins.c +++ b/src/plugins/plugins.c @@ -369,9 +369,9 @@ plugins_loaded_list(void) } char * -plugins_autocomplete(const char * const input) +plugins_autocomplete(const char * const input, gboolean previous) { - return autocompleters_complete(input); + return autocompleters_complete(input, previous); } void diff --git a/src/plugins/plugins.h b/src/plugins/plugins.h index af659757..0aa490f0 100644 --- a/src/plugins/plugins.h +++ b/src/plugins/plugins.h @@ -108,7 +108,7 @@ typedef struct prof_plugin_t { void plugins_init(void); GSList *plugins_unloaded_list(void); GList *plugins_loaded_list(void); -char* plugins_autocomplete(const char *const input); +char* plugins_autocomplete(const char *const input, gboolean previous); void plugins_reset_autocomplete(void); void plugins_shutdown(void); diff --git a/src/tools/autocomplete.c b/src/tools/autocomplete.c index b94db481..c4a843ba 100644 --- a/src/tools/autocomplete.c +++ b/src/tools/autocomplete.c @@ -40,14 +40,16 @@ #include "common.h" #include "tools/autocomplete.h" #include "tools/parser.h" +#include "ui/ui.h" struct autocomplete_t { - GSList *items; - GSList *last_found; + GList *items; + GList *last_found; gchar *search_str; }; -static gchar* _search_from(Autocomplete ac, GSList *curr, gboolean quote); +static gchar* _search_next(Autocomplete ac, GList *curr, gboolean quote); +static gchar* _search_prev(Autocomplete ac, GList *curr, gboolean quote); Autocomplete autocomplete_new(void) @@ -64,7 +66,7 @@ void autocomplete_clear(Autocomplete ac) { if (ac) { - g_slist_free_full(ac->items, free); + g_list_free_full(ac->items, free); ac->items = NULL; autocomplete_reset(ac); @@ -95,7 +97,7 @@ autocomplete_length(Autocomplete ac) } else if (!ac->items) { return 0; } else { - return g_slist_length(ac->items); + return g_list_length(ac->items); } } @@ -104,7 +106,7 @@ autocomplete_add(Autocomplete ac, const char *item) { if (ac) { char *item_cpy; - GSList *curr = g_slist_find_custom(ac->items, item, (GCompareFunc)strcmp); + GList *curr = g_list_find_custom(ac->items, item, (GCompareFunc)strcmp); // if item already exists if (curr) { @@ -112,7 +114,7 @@ autocomplete_add(Autocomplete ac, const char *item) } item_cpy = strdup(item); - ac->items = g_slist_insert_sorted(ac->items, item_cpy, (GCompareFunc)strcmp); + ac->items = g_list_insert_sorted(ac->items, item_cpy, (GCompareFunc)strcmp); } return; @@ -131,7 +133,7 @@ void autocomplete_remove(Autocomplete ac, const char *const item) { if (ac) { - GSList *curr = g_slist_find_custom(ac->items, item, (GCompareFunc)strcmp); + GList *curr = g_list_find_custom(ac->items, item, (GCompareFunc)strcmp); if (!curr) { return; @@ -143,7 +145,7 @@ autocomplete_remove(Autocomplete ac, const char *const item) } free(curr->data); - ac->items = g_slist_delete_link(ac->items, curr); + ac->items = g_list_delete_link(ac->items, curr); } return; @@ -158,15 +160,15 @@ autocomplete_remove_all(Autocomplete ac, char **items) } } -GSList* +GList* autocomplete_create_list(Autocomplete ac) { - GSList *copy = NULL; - GSList *curr = ac->items; + GList *copy = NULL; + GList *curr = ac->items; while(curr) { - copy = g_slist_append(copy, strdup(curr->data)); - curr = g_slist_next(curr); + copy = g_list_append(copy, strdup(curr->data)); + curr = g_list_next(curr); } return copy; @@ -175,20 +177,20 @@ autocomplete_create_list(Autocomplete ac) gboolean autocomplete_contains(Autocomplete ac, const char *value) { - GSList *curr = ac->items; + GList *curr = ac->items; while(curr) { if (strcmp(curr->data, value) == 0) { return TRUE; } - curr = g_slist_next(curr); + curr = g_list_next(curr); } return FALSE; } gchar* -autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote) +autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote, gboolean previous) { gchar *found = NULL; @@ -209,22 +211,38 @@ autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote) } ac->search_str = strdup(search_str); - found = _search_from(ac, ac->items, quote); + found = _search_next(ac, ac->items, quote); return found; // subsequent search attempt } else { - // search from here+1 to end - found = _search_from(ac, g_slist_next(ac->last_found), quote); - if (found) { - return found; + if (previous) { + // search from here-1 to beginning + found = _search_prev(ac, g_list_previous(ac->last_found), quote); + if (found) { + return found; + } + } else { + // search from here+1 to end + found = _search_next(ac, g_list_next(ac->last_found), quote); + if (found) { + return found; + } } - // search from beginning - found = _search_from(ac, ac->items, quote); - if (found) { - return found; + if (previous) { + // search from end + found = _search_prev(ac, g_list_last(ac->items), quote); + if (found) { + return found; + } + } else { + // search from beginning + found = _search_next(ac, ac->items, quote); + if (found) { + return found; + } } // we found nothing, reset search @@ -235,7 +253,7 @@ autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote) } char* -autocomplete_param_with_func(const char *const input, char *command, autocomplete_func func) +autocomplete_param_with_func(const char *const input, char *command, autocomplete_func func, gboolean previous) { GString *auto_msg = NULL; char *result = NULL; @@ -252,7 +270,7 @@ autocomplete_param_with_func(const char *const input, char *command, autocomplet } prefix[inp_len - len] = '\0'; - char *found = func(prefix); + char *found = func(prefix, previous); if (found) { auto_msg = g_string_new(command_cpy); g_string_append(auto_msg, found); @@ -266,7 +284,7 @@ autocomplete_param_with_func(const char *const input, char *command, autocomplet } char* -autocomplete_param_with_ac(const char *const input, char *command, Autocomplete ac, gboolean quote) +autocomplete_param_with_ac(const char *const input, char *command, Autocomplete ac, gboolean quote, gboolean previous) { GString *auto_msg = NULL; char *result = NULL; @@ -282,7 +300,7 @@ autocomplete_param_with_ac(const char *const input, char *command, Autocomplete } prefix[inp_len - len] = '\0'; - char *found = autocomplete_complete(ac, prefix, quote); + char *found = autocomplete_complete(ac, prefix, quote, previous); if (found) { auto_msg = g_string_new(command_cpy); g_string_append(auto_msg, found); @@ -297,7 +315,7 @@ autocomplete_param_with_ac(const char *const input, char *command, Autocomplete } char* -autocomplete_param_no_with_func(const char *const input, char *command, int arg_number, autocomplete_func func) +autocomplete_param_no_with_func(const char *const input, char *command, int arg_number, autocomplete_func func, gboolean previous) { if (strncmp(input, command, strlen(command)) == 0) { GString *result_str = NULL; @@ -312,7 +330,7 @@ autocomplete_param_no_with_func(const char *const input, char *command, int arg_ // autocomplete param if (comp_str) { - char *found = func(comp_str); + char *found = func(comp_str, previous); if (found) { result_str = g_string_new(""); g_string_append(result_str, start_str); @@ -329,7 +347,7 @@ autocomplete_param_no_with_func(const char *const input, char *command, int arg_ } static gchar* -_search_from(Autocomplete ac, GSList *curr, gboolean quote) +_search_next(Autocomplete ac, GList *curr, gboolean quote) { gchar *search_str_ascii = g_str_to_ascii(ac->search_str, NULL); gchar *search_str_lower = g_ascii_strdown(search_str_ascii, -1); @@ -368,7 +386,54 @@ _search_from(Autocomplete ac, GSList *curr, gboolean quote) } g_free(curr_lower); - curr = g_slist_next(curr); + curr = g_list_next(curr); + } + + g_free(search_str_lower); + return NULL; +} + +static gchar* +_search_prev(Autocomplete ac, GList *curr, gboolean quote) +{ + gchar *search_str_ascii = g_str_to_ascii(ac->search_str, NULL); + gchar *search_str_lower = g_ascii_strdown(search_str_ascii, -1); + g_free(search_str_ascii); + + while(curr) { + gchar *curr_ascii = g_str_to_ascii(curr->data, NULL); + gchar *curr_lower = g_ascii_strdown(curr_ascii, -1); + g_free(curr_ascii); + + // match found + if (strncmp(curr_lower, search_str_lower, strlen(search_str_lower)) == 0) { + + // set pointer to last found + ac->last_found = curr; + + // if contains space, quote before returning + if (quote && g_strrstr(curr->data, " ")) { + GString *quoted = g_string_new("\""); + g_string_append(quoted, curr->data); + g_string_append(quoted, "\""); + + gchar *result = quoted->str; + g_string_free(quoted, FALSE); + + g_free(search_str_lower); + g_free(curr_lower); + return result; + + // otherwise just return the string + } else { + g_free(search_str_lower); + g_free(curr_lower); + return strdup(curr->data); + } + } + + g_free(curr_lower); + curr = g_list_previous(curr); } g_free(search_str_lower); diff --git a/src/tools/autocomplete.h b/src/tools/autocomplete.h index bead7f12..f62309ba 100644 --- a/src/tools/autocomplete.h +++ b/src/tools/autocomplete.h @@ -37,7 +37,7 @@ #include -typedef char* (*autocomplete_func)(const char *const); +typedef char* (*autocomplete_func)(const char *const, gboolean); typedef struct autocomplete_t *Autocomplete; // allocate new autocompleter with no items @@ -55,19 +55,19 @@ void autocomplete_remove(Autocomplete ac, const char *const item); void autocomplete_remove_all(Autocomplete ac, char **items); // find the next item prefixed with search string -gchar* autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote); +gchar* autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote, gboolean previous); -GSList* autocomplete_create_list(Autocomplete ac); +GList* autocomplete_create_list(Autocomplete ac); gint autocomplete_length(Autocomplete ac); char* autocomplete_param_with_func(const char *const input, char *command, - autocomplete_func func); + autocomplete_func func, gboolean previous); char* autocomplete_param_with_ac(const char *const input, char *command, - Autocomplete ac, gboolean quote); + Autocomplete ac, gboolean quote, gboolean previous); char* autocomplete_param_no_with_func(const char *const input, char *command, - int arg_number, autocomplete_func func); + int arg_number, autocomplete_func func, gboolean previous); void autocomplete_reset(Autocomplete ac); diff --git a/src/ui/console.c b/src/ui/console.c index 4c24b450..cb5a10b0 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -142,7 +142,7 @@ cons_show_help(const char *const cmd, CommandHelp *help) if (g_strv_length((gchar**)help->examples) > 0) { cons_show(""); - win_println(console, THEME_HELP_HEADER, '-', "Arguments"); + win_println(console, THEME_HELP_HEADER, '-', "Examples"); ui_show_lines(console, help->examples); } } @@ -505,7 +505,7 @@ cons_show_wins(gboolean unread) } void -cons_show_room_invites(GSList *invites) +cons_show_room_invites(GList *invites) { cons_show(""); if (invites == NULL) { @@ -514,7 +514,7 @@ cons_show_room_invites(GSList *invites) cons_show("Chat room invites, use /join or /decline commands:"); while (invites) { cons_show(" %s", invites->data); - invites = g_slist_next(invites); + invites = g_list_next(invites); } } @@ -608,17 +608,17 @@ cons_show_caps(const char *const fulljid, resource_presence_t presence) void cons_show_received_subs(void) { - GSList *received = presence_get_subscription_requests(); + GList *received = presence_get_subscription_requests(); if (received == NULL) { cons_show("No outstanding subscription requests."); } else { cons_show("Outstanding subscription requests from:", - g_slist_length(received)); + g_list_length(received)); while (received) { cons_show(" %s", received->data); - received = g_slist_next(received); + received = g_list_next(received); } - g_slist_free_full(received, g_free); + g_list_free_full(received, g_free); } cons_alert(); diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index b42c366a..e4da800b 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -96,6 +96,7 @@ static void _inp_rl_addfuncs(void); static int _inp_rl_getc(FILE *stream); static void _inp_rl_linehandler(char *line); static int _inp_rl_tab_handler(int count, int key); +static int _inp_rl_shift_tab_handler(int count, int key); static int _inp_rl_win_clear_handler(int count, int key); static int _inp_rl_win_1_handler(int count, int key); static int _inp_rl_win_2_handler(int count, int key); @@ -421,6 +422,7 @@ _inp_rl_startup_hook(void) rl_bind_keyseq("\\eOs", _inp_rl_win_pagedown_handler); rl_bind_key('\t', _inp_rl_tab_handler); + rl_bind_keyseq("\\e[Z", _inp_rl_shift_tab_handler); // unbind unwanted mappings rl_bind_keyseq("\\e=", NULL); @@ -449,10 +451,27 @@ _inp_rl_linehandler(char *line) inp_line = line; } +static gboolean shift_tab = FALSE; + static int _inp_rl_getc(FILE *stream) { int ch = rl_getc(stream); + + // 27, 91, 90 = Shift tab + if (ch == 27) { + shift_tab = TRUE; + return ch; + } + if (shift_tab && ch == 91) { + return ch; + } + if (shift_tab && ch == 90) { + return ch; + } + + shift_tab = FALSE; + if (_inp_printable(ch)) { ProfWin *window = wins_get_current(); cmd_ac_reset(window); @@ -477,7 +496,7 @@ _inp_rl_tab_handler(int count, int key) ProfWin *current = wins_get_current(); if ((strncmp(rl_line_buffer, "/", 1) != 0) && (current->type == WIN_MUC)) { - char *result = muc_autocomplete(current, rl_line_buffer); + char *result = muc_autocomplete(current, rl_line_buffer, FALSE); if (result) { rl_replace_line(result, 1); rl_point = rl_end; @@ -485,7 +504,35 @@ _inp_rl_tab_handler(int count, int key) } } else if (strncmp(rl_line_buffer, "/", 1) == 0) { ProfWin *window = wins_get_current(); - char *result = cmd_ac_complete(window, rl_line_buffer); + char *result = cmd_ac_complete(window, rl_line_buffer, FALSE); + if (result) { + rl_replace_line(result, 1); + rl_point = rl_end; + free(result); + } + } + + return 0; +} + +static int +_inp_rl_shift_tab_handler(int count, int key) +{ + if (rl_point != rl_end || !rl_line_buffer) { + return 0; + } + + ProfWin *current = wins_get_current(); + if ((strncmp(rl_line_buffer, "/", 1) != 0) && (current->type == WIN_MUC)) { + char *result = muc_autocomplete(current, rl_line_buffer, TRUE); + if (result) { + rl_replace_line(result, 1); + rl_point = rl_end; + free(result); + } + } else if (strncmp(rl_line_buffer, "/", 1) == 0) { + ProfWin *window = wins_get_current(); + char *result = cmd_ac_complete(window, rl_line_buffer, TRUE); if (result) { rl_replace_line(result, 1); rl_point = rl_end; diff --git a/src/ui/rosterwin.c b/src/ui/rosterwin.c index 30dedea6..bbeaba21 100644 --- a/src/ui/rosterwin.c +++ b/src/ui/rosterwin.c @@ -138,13 +138,13 @@ rosterwin_roster(void) _rosterwin_contacts_by_presence(layout, "dnd", "Do not disturb"); _rosterwin_contacts_by_presence(layout, "offline", "Offline"); } else if (g_strcmp0(by, "group") == 0) { - GSList *groups = roster_get_groups(); - GSList *curr_group = groups; + GList *groups = roster_get_groups(); + GList *curr_group = groups; while (curr_group) { _rosterwin_contacts_by_group(layout, curr_group->data); - curr_group = g_slist_next(curr_group); + curr_group = g_list_next(curr_group); } - g_slist_free_full(groups, free); + g_list_free_full(groups, free); _rosterwin_contacts_by_group(layout, NULL); } else { _rosterwin_contacts_all(layout); diff --git a/src/ui/ui.h b/src/ui/ui.h index 10788987..3a022f7d 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -274,7 +274,7 @@ void cons_show_incoming_room_message(const char *const nick, const char *const r gboolean mention, GList *triggers, int unread); void cons_show_incoming_message(const char *const short_from, const int win_index, int unread); void cons_show_incoming_private_message(const char *const nick, const char *const room, const int win_index, int unread); -void cons_show_room_invites(GSList *invites); +void cons_show_room_invites(GList *invites); void cons_show_received_subs(void); void cons_show_sent_subs(void); void cons_alert(void); diff --git a/src/ui/window_list.c b/src/ui/window_list.c index 14e74cd2..5686b48a 100644 --- a/src/ui/window_list.c +++ b/src/ui/window_list.c @@ -1073,15 +1073,15 @@ wins_create_summary(gboolean unread) } char* -win_autocomplete(const char *const search_str) +win_autocomplete(const char *const search_str, gboolean previous) { - return autocomplete_complete(wins_ac, search_str, TRUE); + return autocomplete_complete(wins_ac, search_str, TRUE, previous); } char* -win_close_autocomplete(const char *const search_str) +win_close_autocomplete(const char *const search_str, gboolean previous) { - return autocomplete_complete(wins_close_ac, search_str, TRUE); + return autocomplete_complete(wins_close_ac, search_str, TRUE, previous); } void diff --git a/src/ui/window_list.h b/src/ui/window_list.h index 450175b7..dc1f3be4 100644 --- a/src/ui/window_list.h +++ b/src/ui/window_list.h @@ -91,9 +91,9 @@ gboolean wins_swap(int source_win, int target_win); void wins_hide_subwin(ProfWin *window); void wins_show_subwin(ProfWin *window); -char* win_autocomplete(const char *const search_str); +char* win_autocomplete(const char *const search_str, gboolean previous); void win_reset_search_attempts(void); -char* win_close_autocomplete(const char *const search_str); +char* win_close_autocomplete(const char *const search_str, gboolean previous); void win_close_reset_search_attempts(void); #endif diff --git a/src/xmpp/blocking.c b/src/xmpp/blocking.c index 05b80380..2a8fb316 100644 --- a/src/xmpp/blocking.c +++ b/src/xmpp/blocking.c @@ -92,9 +92,9 @@ blocked_list(void) } char* -blocked_ac_find(const char *const search_str) +blocked_ac_find(const char *const search_str, gboolean previous) { - return autocomplete_complete(blocked_ac, search_str, TRUE); + return autocomplete_complete(blocked_ac, search_str, TRUE, previous); } void diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c index 84b5e4bb..99b2e20d 100644 --- a/src/xmpp/bookmark.c +++ b/src/xmpp/bookmark.c @@ -212,9 +212,9 @@ bookmark_get_list(void) } char* -bookmark_find(const char *const search_str) +bookmark_find(const char *const search_str, gboolean previous) { - return autocomplete_complete(bookmark_ac, search_str, TRUE); + return autocomplete_complete(bookmark_ac, search_str, TRUE, previous); } void diff --git a/src/xmpp/muc.c b/src/xmpp/muc.c index 7e926593..69cacba1 100644 --- a/src/xmpp/muc.c +++ b/src/xmpp/muc.c @@ -120,7 +120,7 @@ muc_invites_count(void) return autocomplete_length(invite_ac); } -GSList* +GList* muc_invites(void) { return autocomplete_create_list(invite_ac); @@ -135,17 +135,17 @@ muc_invite_password(const char *const room) gboolean muc_invites_contain(const char *const room) { - GSList *invites = autocomplete_create_list(invite_ac); - GSList *curr = invites; + GList *invites = autocomplete_create_list(invite_ac); + GList *curr = invites; while (curr) { if (strcmp(curr->data, room) == 0) { - g_slist_free_full(invites, g_free); + g_list_free_full(invites, g_free); return TRUE; } else { - curr = g_slist_next(curr); + curr = g_list_next(curr); } } - g_slist_free_full(invites, g_free); + g_list_free_full(invites, g_free); return FALSE; } @@ -157,9 +157,9 @@ muc_invites_reset_ac(void) } char* -muc_invites_find(const char *const search_str) +muc_invites_find(const char *const search_str, gboolean previous) { - return autocomplete_complete(invite_ac, search_str, TRUE); + return autocomplete_complete(invite_ac, search_str, TRUE, previous); } void @@ -663,7 +663,7 @@ muc_roster_nick_change_complete(const char *const room, const char *const nick) } char* -muc_autocomplete(ProfWin *window, const char *const input) +muc_autocomplete(ProfWin *window, const char *const input, gboolean previous) { if (window->type == WIN_MUC) { ProfMucWin *mucwin = (ProfMucWin*)window; @@ -686,7 +686,7 @@ muc_autocomplete(ProfWin *window, const char *const input) } } - char *result = autocomplete_complete(chat_room->nick_ac, search_str, FALSE); + char *result = autocomplete_complete(chat_room->nick_ac, search_str, FALSE, previous); if (result) { GString *replace_with = g_string_new(chat_room->autocomplete_prefix); g_string_append(replace_with, result); diff --git a/src/xmpp/muc.h b/src/xmpp/muc.h index fedabc2a..6c6408f3 100644 --- a/src/xmpp/muc.h +++ b/src/xmpp/muc.h @@ -120,10 +120,10 @@ char* muc_roster_nick_change_complete(const char *const room, const char *const void muc_invites_add(const char *const room, const char *const password); void muc_invites_remove(const char *const room); gint muc_invites_count(void); -GSList* muc_invites(void); +GList* muc_invites(void); gboolean muc_invites_contain(const char *const room); void muc_invites_reset_ac(void); -char* muc_invites_find(const char *const search_str); +char* muc_invites_find(const char *const search_str, gboolean previous); void muc_invites_clear(void); char* muc_invite_password(const char *const room); @@ -133,7 +133,7 @@ char* muc_subject(const char *const room); void muc_pending_broadcasts_add(const char *const room, const char *const message); GList* muc_pending_broadcasts(const char *const room); -char* muc_autocomplete(ProfWin *window, const char *const input); +char* muc_autocomplete(ProfWin *window, const char *const input, gboolean previous); void muc_autocomplete_reset(const char *const room); gboolean muc_requires_config(const char *const room); diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index f2772f59..97e3d461 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -141,7 +141,7 @@ presence_subscription(const char *const jid, const jabber_subscr_t action) xmpp_stanza_release(presence); } -GSList* +GList* presence_get_subscription_requests(void) { return autocomplete_create_list(sub_requests_ac); @@ -160,9 +160,9 @@ presence_clear_sub_requests(void) } char* -presence_sub_request_find(const char *const search_str) +presence_sub_request_find(const char *const search_str, gboolean previous) { - return autocomplete_complete(sub_requests_ac, search_str, TRUE); + return autocomplete_complete(sub_requests_ac, search_str, TRUE, previous); } gboolean @@ -170,16 +170,16 @@ presence_sub_request_exists(const char *const bare_jid) { gboolean result = FALSE; - GSList *requests = autocomplete_create_list(sub_requests_ac); - GSList *curr = requests; + GList *requests = autocomplete_create_list(sub_requests_ac); + GList *curr = requests; while (curr) { if (strcmp(curr->data, bare_jid) == 0) { result = TRUE; break; } - curr = g_slist_next(curr); + curr = g_list_next(curr); } - g_slist_free_full(requests, free); + g_list_free_full(requests, free); return result; } diff --git a/src/xmpp/roster_list.c b/src/xmpp/roster_list.c index 19d0ea06..839ea0b8 100644 --- a/src/xmpp/roster_list.c +++ b/src/xmpp/roster_list.c @@ -472,19 +472,19 @@ roster_has_pending_subscriptions(void) } char* -roster_contact_autocomplete(const char *const search_str) +roster_contact_autocomplete(const char *const search_str, gboolean previous) { assert(roster != NULL); - return autocomplete_complete(roster->name_ac, search_str, TRUE); + return autocomplete_complete(roster->name_ac, search_str, TRUE, previous); } char* -roster_fulljid_autocomplete(const char *const search_str) +roster_fulljid_autocomplete(const char *const search_str, gboolean previous) { assert(roster != NULL); - return autocomplete_complete(roster->fulljid_ac, search_str, TRUE); + return autocomplete_complete(roster->fulljid_ac, search_str, TRUE, previous); } GSList* @@ -526,7 +526,7 @@ roster_get_group(const char *const group, roster_ord_t order) return result; } -GSList* +GList* roster_get_groups(void) { assert(roster != NULL); @@ -535,19 +535,19 @@ roster_get_groups(void) } char* -roster_group_autocomplete(const char *const search_str) +roster_group_autocomplete(const char *const search_str, gboolean previous) { assert(roster != NULL); - return autocomplete_complete(roster->groups_ac, search_str, TRUE); + return autocomplete_complete(roster->groups_ac, search_str, TRUE, previous); } char* -roster_barejid_autocomplete(const char *const search_str) +roster_barejid_autocomplete(const char *const search_str, gboolean previous) { assert(roster != NULL); - return autocomplete_complete(roster->barejid_ac, search_str, TRUE); + return autocomplete_complete(roster->barejid_ac, search_str, TRUE, previous); } static gboolean diff --git a/src/xmpp/roster_list.h b/src/xmpp/roster_list.h index 971285c2..4e6b1d47 100644 --- a/src/xmpp/roster_list.h +++ b/src/xmpp/roster_list.h @@ -62,12 +62,12 @@ char* roster_barejid_from_name(const char *const name); GSList* roster_get_contacts(roster_ord_t order); GSList* roster_get_contacts_online(void); gboolean roster_has_pending_subscriptions(void); -char* roster_contact_autocomplete(const char *const search_str); -char* roster_fulljid_autocomplete(const char *const search_str); +char* roster_contact_autocomplete(const char *const search_str, gboolean previous); +char* roster_fulljid_autocomplete(const char *const search_str, gboolean previous); GSList* roster_get_group(const char *const group, roster_ord_t order); -GSList* roster_get_groups(void); -char* roster_group_autocomplete(const char *const search_str); -char* roster_barejid_autocomplete(const char *const search_str); +GList* roster_get_groups(void); +char* roster_group_autocomplete(const char *const search_str, gboolean previous); +char* roster_barejid_autocomplete(const char *const search_str, gboolean previous); GSList* roster_get_contacts_by_presence(const char *const presence); char* roster_get_msg_display_name(const char *const barejid, const char *const resource); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 64918715..5742a67c 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -147,10 +147,10 @@ void message_send_gone(const char *const jid); void message_send_invite(const char *const room, const char *const contact, const char *const reason); void presence_subscription(const char *const jid, const jabber_subscr_t action); -GSList* presence_get_subscription_requests(void); +GList* presence_get_subscription_requests(void); gint presence_sub_request_count(void); void presence_reset_sub_request_search(void); -char* presence_sub_request_find(const char *const search_str); +char* presence_sub_request_find(const char *const search_str, gboolean previous); void presence_join_room(const char *const room, const char *const nick, const char *const passwd); void presence_change_room_nick(const char *const room, const char *const nick); void presence_leave_chat_room(const char *const room_jid); @@ -194,7 +194,7 @@ gboolean bookmark_update(const char *jid, const char *nick, const char *password gboolean bookmark_remove(const char *jid); gboolean bookmark_join(const char *jid); GList* bookmark_get_list(void); -char* bookmark_find(const char *const search_str); +char* bookmark_find(const char *const search_str, gboolean previous); void bookmark_autocomplete_reset(void); gboolean bookmark_exists(const char *const room); @@ -207,7 +207,7 @@ void roster_send_remove(const char *const barejid); GList* blocked_list(void); gboolean blocked_add(char *jid); gboolean blocked_remove(char *jid); -char* blocked_ac_find(const char *const search_str); +char* blocked_ac_find(const char *const search_str, gboolean previous); void blocked_ac_reset(void); void form_destroy(DataForm *form); diff --git a/tests/unittests/pgp/stub_gpg.c b/tests/unittests/pgp/stub_gpg.c index 02ccb4c8..edaab4e0 100644 --- a/tests/unittests/pgp/stub_gpg.c +++ b/tests/unittests/pgp/stub_gpg.c @@ -56,7 +56,7 @@ void p_gpg_free_keys(GHashTable *keys) {} void p_gpg_autocomplete_key_reset(void) {} -char * p_gpg_autocomplete_key(const char * const search_str) +char * p_gpg_autocomplete_key(const char * const search_str, gboolean previous) { return NULL; } diff --git a/tests/unittests/test_autocomplete.c b/tests/unittests/test_autocomplete.c index 755e01c9..519973c4 100644 --- a/tests/unittests/test_autocomplete.c +++ b/tests/unittests/test_autocomplete.c @@ -24,7 +24,7 @@ void reset_after_create(void **state) void find_after_create(void **state) { Autocomplete ac = autocomplete_new(); - autocomplete_complete(ac, "hello", TRUE); + autocomplete_complete(ac, "hello", TRUE, FALSE); autocomplete_clear(ac); } @@ -43,7 +43,7 @@ void add_one_and_complete(void **state) { Autocomplete ac = autocomplete_new(); autocomplete_add(ac, "Hello"); - char *result = autocomplete_complete(ac, "Hel", TRUE); + char *result = autocomplete_complete(ac, "Hel", TRUE, FALSE); assert_string_equal("Hello", result); @@ -55,7 +55,7 @@ void add_two_and_complete_returns_first(void **state) Autocomplete ac = autocomplete_new(); autocomplete_add(ac, "Hello"); autocomplete_add(ac, "Help"); - char *result = autocomplete_complete(ac, "Hel", TRUE); + char *result = autocomplete_complete(ac, "Hel", TRUE, FALSE); assert_string_equal("Hello", result); @@ -67,8 +67,8 @@ void add_two_and_complete_returns_second(void **state) Autocomplete ac = autocomplete_new(); autocomplete_add(ac, "Hello"); autocomplete_add(ac, "Help"); - char *result1 = autocomplete_complete(ac, "Hel", TRUE); - char *result2 = autocomplete_complete(ac, result1, TRUE); + char *result1 = autocomplete_complete(ac, "Hel", TRUE, FALSE); + char *result2 = autocomplete_complete(ac, result1, TRUE, FALSE); assert_string_equal("Help", result2); @@ -123,7 +123,7 @@ void complete_accented_with_accented(void **state) Autocomplete ac = autocomplete_new(); autocomplete_add(ac, "èâîô"); - char *result = autocomplete_complete(ac, "èâ", TRUE); + char *result = autocomplete_complete(ac, "èâ", TRUE, FALSE); assert_string_equal("èâîô", result); @@ -135,7 +135,7 @@ void complete_accented_with_base(void **state) Autocomplete ac = autocomplete_new(); autocomplete_add(ac, "èâîô"); - char *result = autocomplete_complete(ac, "ea", TRUE); + char *result = autocomplete_complete(ac, "ea", TRUE, FALSE); assert_string_equal("èâîô", result); @@ -148,8 +148,8 @@ void complete_both_with_accented(void **state) autocomplete_add(ac, "eaooooo"); autocomplete_add(ac, "èâîô"); - char *result1 = autocomplete_complete(ac, "èâ", TRUE); - char *result2 = autocomplete_complete(ac, result1, TRUE); + char *result1 = autocomplete_complete(ac, "èâ", TRUE, FALSE); + char *result2 = autocomplete_complete(ac, result1, TRUE, FALSE); assert_string_equal("èâîô", result2); @@ -162,8 +162,8 @@ void complete_both_with_base(void **state) autocomplete_add(ac, "eaooooo"); autocomplete_add(ac, "èâîô"); - char *result1 = autocomplete_complete(ac, "ea", TRUE); - char *result2 = autocomplete_complete(ac, result1, TRUE); + char *result1 = autocomplete_complete(ac, "ea", TRUE, FALSE); + char *result2 = autocomplete_complete(ac, result1, TRUE, FALSE); assert_string_equal("èâîô", result2); @@ -175,9 +175,26 @@ void complete_ignores_case(void **state) Autocomplete ac = autocomplete_new(); autocomplete_add(ac, "MyBuddy"); - char *result = autocomplete_complete(ac, "myb", TRUE); + char *result = autocomplete_complete(ac, "myb", TRUE, FALSE); assert_string_equal("MyBuddy", result); autocomplete_clear(ac); } + +void complete_previous(void **state) +{ + Autocomplete ac = autocomplete_new(); + autocomplete_add(ac, "MyBuddy1"); + autocomplete_add(ac, "MyBuddy2"); + autocomplete_add(ac, "MyBuddy3"); + + char *result1 = autocomplete_complete(ac, "myb", TRUE, FALSE); + char *result2 = autocomplete_complete(ac, result1, TRUE, FALSE); + char *result3 = autocomplete_complete(ac, result2, TRUE, FALSE); + char *result4 = autocomplete_complete(ac, result3, TRUE, TRUE); + + assert_string_equal("MyBuddy2", result4); + + autocomplete_clear(ac); +} diff --git a/tests/unittests/test_autocomplete.h b/tests/unittests/test_autocomplete.h index a9dd34cb..746ea2af 100644 --- a/tests/unittests/test_autocomplete.h +++ b/tests/unittests/test_autocomplete.h @@ -13,3 +13,4 @@ void complete_accented_with_base(void **state); void complete_both_with_accented(void **state); void complete_both_with_base(void **state); void complete_ignores_case(void **state); +void complete_previous(void **state); diff --git a/tests/unittests/test_roster_list.c b/tests/unittests/test_roster_list.c index c2c63a6b..5352e420 100644 --- a/tests/unittests/test_roster_list.c +++ b/tests/unittests/test_roster_list.c @@ -158,7 +158,7 @@ void find_first_exists(void **state) char *search = strdup("B"); - char *result = roster_contact_autocomplete(search); + char *result = roster_contact_autocomplete(search, FALSE); assert_string_equal("Bob", result); free(result); free(search); @@ -172,7 +172,7 @@ void find_second_exists(void **state) roster_add("Dave", NULL, NULL, NULL, FALSE); roster_add("Bob", NULL, NULL, NULL, FALSE); - char *result = roster_contact_autocomplete("Dav"); + char *result = roster_contact_autocomplete("Dav", FALSE); assert_string_equal("Dave", result); free(result); roster_destroy(); @@ -185,7 +185,7 @@ void find_third_exists(void **state) roster_add("Dave", NULL, NULL, NULL, FALSE); roster_add("Bob", NULL, NULL, NULL, FALSE); - char *result = roster_contact_autocomplete("Ja"); + char *result = roster_contact_autocomplete("Ja", FALSE); assert_string_equal("James", result); free(result); roster_destroy(); @@ -198,7 +198,7 @@ void find_returns_null(void **state) roster_add("Dave", NULL, NULL, NULL, FALSE); roster_add("Bob", NULL, NULL, NULL, FALSE); - char *result = roster_contact_autocomplete("Mike"); + char *result = roster_contact_autocomplete("Mike", FALSE); assert_null(result); roster_destroy(); } @@ -206,7 +206,7 @@ void find_returns_null(void **state) void find_on_empty_returns_null(void **state) { roster_create(); - char *result = roster_contact_autocomplete("James"); + char *result = roster_contact_autocomplete("James", FALSE); assert_null(result); roster_destroy(); } @@ -218,8 +218,8 @@ void find_twice_returns_second_when_two_match(void **state) roster_add("Jamie", NULL, NULL, NULL, FALSE); roster_add("Bob", NULL, NULL, NULL, FALSE); - char *result1 = roster_contact_autocomplete("Jam"); - char *result2 = roster_contact_autocomplete(result1); + char *result1 = roster_contact_autocomplete("Jam", FALSE); + char *result2 = roster_contact_autocomplete(result1, FALSE); assert_string_equal("Jamie", result2); free(result1); free(result2); @@ -240,11 +240,11 @@ void find_five_times_finds_fifth(void **state) roster_add("Jamy", NULL, NULL, NULL, FALSE); roster_add("Jamz", NULL, NULL, NULL, FALSE); - char *result1 = roster_contact_autocomplete("Jam"); - char *result2 = roster_contact_autocomplete(result1); - char *result3 = roster_contact_autocomplete(result2); - char *result4 = roster_contact_autocomplete(result3); - char *result5 = roster_contact_autocomplete(result4); + char *result1 = roster_contact_autocomplete("Jam", FALSE); + char *result2 = roster_contact_autocomplete(result1, FALSE); + char *result3 = roster_contact_autocomplete(result2, FALSE); + char *result4 = roster_contact_autocomplete(result3, FALSE); + char *result5 = roster_contact_autocomplete(result4, FALSE); assert_string_equal("Jamo", result5); free(result1); free(result2); @@ -261,9 +261,9 @@ void find_twice_returns_first_when_two_match_and_reset(void **state) roster_add("Jamie", NULL, NULL, NULL, FALSE); roster_add("Bob", NULL, NULL, NULL, FALSE); - char *result1 = roster_contact_autocomplete("Jam"); + char *result1 = roster_contact_autocomplete("Jam", FALSE); roster_reset_search_attempts(); - char *result2 = roster_contact_autocomplete(result1); + char *result2 = roster_contact_autocomplete(result1, FALSE); assert_string_equal("James", result2); free(result1); free(result2); diff --git a/tests/unittests/ui/stub_ui.c b/tests/unittests/ui/stub_ui.c index 94dca1c1..9effe89a 100644 --- a/tests/unittests/ui/stub_ui.c +++ b/tests/unittests/ui/stub_ui.c @@ -410,7 +410,7 @@ void cons_check_version(gboolean not_available_msg) {} void cons_show_typing(const char * const barejid) {} void cons_show_incoming_room_message(const char *const nick, const char *const room, const int win_index, gboolean mention, GList *triggers, int unread) {} void cons_show_incoming_message(const char * const short_from, const int win_index, int unread) {} -void cons_show_room_invites(GSList *invites) {} +void cons_show_room_invites(GList *invites) {} void cons_show_received_subs(void) {} void cons_show_sent_subs(void) {} void cons_alert(void) {} diff --git a/tests/unittests/unittests.c b/tests/unittests/unittests.c index 5c411ab6..41f99424 100644 --- a/tests/unittests/unittests.c +++ b/tests/unittests/unittests.c @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include #include "config.h" #include "xmpp/chat_session.h" @@ -38,7 +40,21 @@ #include "test_plugins_disco.h" int main(int argc, char* argv[]) { - setlocale(LC_ALL, ""); + setlocale(LC_ALL, "en_GB.UTF-8"); + char *codeset = nl_langinfo(CODESET); + char *lang = getenv("LANG"); + + printf("Charset information:\n"); + + if (lang) { + printf(" LANG: %s\n", lang); + } + if (codeset) { + printf(" CODESET: %s\n", codeset); + } + printf(" MB_CUR_MAX: %d\n", MB_CUR_MAX); + printf(" MB_LEN_MAX: %d\n", MB_LEN_MAX); + const UnitTest all_tests[] = { unit_test(replace_one_substr), @@ -95,6 +111,7 @@ int main(int argc, char* argv[]) { unit_test(complete_both_with_accented), unit_test(complete_both_with_base), unit_test(complete_ignores_case), + unit_test(complete_previous), unit_test(create_jid_from_null_returns_null), unit_test(create_jid_from_empty_string_returns_null), diff --git a/tests/unittests/xmpp/stub_xmpp.c b/tests/unittests/xmpp/stub_xmpp.c index 3a17a00e..9f2c239c 100644 --- a/tests/unittests/xmpp/stub_xmpp.c +++ b/tests/unittests/xmpp/stub_xmpp.c @@ -127,7 +127,7 @@ void message_send_invite(const char * const room, const char * const contact, // presence functions void presence_subscription(const char * const jid, const jabber_subscr_t action) {} -GSList* presence_get_subscription_requests(void) +GList* presence_get_subscription_requests(void) { return NULL; } @@ -139,7 +139,7 @@ gint presence_sub_request_count(void) void presence_reset_sub_request_search(void) {} -char * presence_sub_request_find(const char * const search_str) +char * presence_sub_request_find(const char * const search_str, gboolean previous) { return NULL; } @@ -249,7 +249,7 @@ GList * bookmark_get_list(void) return (GList *)mock(); } -char * bookmark_find(const char * const search_str) +char * bookmark_find(const char * const search_str, gboolean previous) { return NULL; } @@ -297,7 +297,7 @@ gboolean blocked_remove(char *jid) return TRUE; } -char* blocked_ac_find(const char *const search_str) +char* blocked_ac_find(const char *const search_str, gboolean previous) { return NULL; }