about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/command/cmd_ac.c604
-rw-r--r--src/command/cmd_ac.h4
-rw-r--r--src/command/cmd_funcs.c12
-rw-r--r--src/config/accounts.c8
-rw-r--r--src/config/accounts.h4
-rw-r--r--src/config/preferences.c8
-rw-r--r--src/config/preferences.h4
-rw-r--r--src/config/tlscerts.c4
-rw-r--r--src/config/tlscerts.h2
-rw-r--r--src/pgp/gpg.c4
-rw-r--r--src/pgp/gpg.h2
-rw-r--r--src/plugins/autocompleters.c6
-rw-r--r--src/plugins/autocompleters.h2
-rw-r--r--src/plugins/plugins.c4
-rw-r--r--src/plugins/plugins.h2
-rw-r--r--src/tools/autocomplete.c133
-rw-r--r--src/tools/autocomplete.h12
-rw-r--r--src/ui/console.c12
-rw-r--r--src/ui/inputwin.c51
-rw-r--r--src/ui/rosterwin.c8
-rw-r--r--src/ui/ui.h2
-rw-r--r--src/ui/window_list.c8
-rw-r--r--src/ui/window_list.h4
-rw-r--r--src/xmpp/blocking.c4
-rw-r--r--src/xmpp/bookmark.c4
-rw-r--r--src/xmpp/muc.c20
-rw-r--r--src/xmpp/muc.h6
-rw-r--r--src/xmpp/presence.c14
-rw-r--r--src/xmpp/roster_list.c18
-rw-r--r--src/xmpp/roster_list.h10
-rw-r--r--src/xmpp/xmpp.h8
-rw-r--r--tests/unittests/pgp/stub_gpg.c2
-rw-r--r--tests/unittests/test_autocomplete.c41
-rw-r--r--tests/unittests/test_autocomplete.h1
-rw-r--r--tests/unittests/test_roster_list.c28
-rw-r--r--tests/unittests/ui/stub_ui.c2
-rw-r--r--tests/unittests/unittests.c1
-rw-r--r--tests/unittests/xmpp/stub_xmpp.c8
38 files changed, 599 insertions, 468 deletions
diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c
index 544719d4..9d0ee08b 100644
--- a/src/command/cmd_ac.c
+++ b/src/command/cmd_ac.c
@@ -57,51 +57,51 @@
 #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* _script_autocomplete_func(const char *const prefix);
-
-static char* _cmd_ac_complete_params(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* _script_autocomplete_func(const char *const prefix, gboolean previous);
+
+static char* _cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previous);
 
 static Autocomplete commands_ac;
 static Autocomplete who_room_ac;
@@ -842,16 +842,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
@@ -861,32 +861,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;
         }
@@ -1149,7 +1149,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;
 
@@ -1247,7 +1247,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;
     }
@@ -1256,7 +1256,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;
@@ -1269,7 +1269,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;
         }
@@ -1286,7 +1286,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;
@@ -1301,7 +1301,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;
@@ -1311,7 +1311,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;
             }
@@ -1319,7 +1319,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;
         }
@@ -1327,7 +1327,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;
         }
@@ -1337,7 +1337,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;
         }
@@ -1398,9 +1398,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;
@@ -1408,13 +1408,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;
         }
@@ -1424,18 +1424,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;
     }
@@ -1444,15 +1444,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;
     }
@@ -1461,12 +1461,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;
         }
@@ -1479,14 +1479,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;
         }
@@ -1496,135 +1496,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;
     }
@@ -1633,36 +1633,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;
     }
@@ -1671,16 +1671,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;
     }
@@ -1689,7 +1689,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;
 
@@ -1702,7 +1702,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);
@@ -1713,7 +1713,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);
@@ -1723,7 +1723,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);
@@ -1734,7 +1734,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);
@@ -1744,7 +1744,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);
@@ -1755,7 +1755,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);
@@ -1766,34 +1766,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;
     }
@@ -1801,46 +1801,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;
     }
@@ -1849,30 +1849,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;
     }
@@ -1881,19 +1881,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;
     }
@@ -1902,16 +1902,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;
     }
@@ -1920,20 +1920,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;
     }
@@ -1950,7 +1950,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);
@@ -1960,12 +1960,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;
     }
@@ -1974,20 +1974,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;
     }
@@ -2002,7 +2002,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);
@@ -2013,13 +2013,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;
     }
@@ -2028,20 +2028,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;
         }
@@ -2058,7 +2058,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;
         }
@@ -2075,7 +2075,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;
         }
@@ -2092,13 +2092,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;
     }
@@ -2107,7 +2107,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) {
@@ -2122,12 +2122,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;
     }
@@ -2136,7 +2136,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();
@@ -2149,29 +2149,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;
     }
@@ -2180,7 +2180,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;
 
@@ -2191,24 +2191,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;
     }
@@ -2217,21 +2217,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;
     }
@@ -2240,16 +2240,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;
     }
@@ -2258,7 +2258,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;
@@ -2269,13 +2269,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;
     }
@@ -2284,7 +2284,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;
@@ -2311,13 +2311,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);
@@ -2332,15 +2332,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;
@@ -2354,36 +2354,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;
     }
@@ -2392,51 +2392,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;
     }
@@ -2445,7 +2445,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;
@@ -2458,13 +2458,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;
@@ -2477,13 +2477,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;
 
@@ -2503,7 +2503,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);
@@ -2514,17 +2514,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;
     }
@@ -2533,7 +2533,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;
 
@@ -2553,7 +2553,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);
@@ -2564,17 +2564,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;
     }
@@ -2583,16 +2583,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;
     }
@@ -2601,31 +2601,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;
     }
@@ -2634,21 +2634,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;
     }
@@ -2657,16 +2657,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;
     }
@@ -2675,7 +2675,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;
@@ -2688,7 +2688,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);
@@ -2699,7 +2699,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);
@@ -2709,7 +2709,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);
@@ -2720,7 +2720,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);
@@ -2730,7 +2730,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);
@@ -2741,7 +2741,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);
@@ -2752,7 +2752,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;
     }
@@ -2761,16 +2761,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;
     }
@@ -2779,7 +2779,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;
@@ -2792,7 +2792,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);
@@ -2802,7 +2802,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);
@@ -2813,7 +2813,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;
     }
@@ -2822,24 +2822,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;
     }
@@ -2848,25 +2848,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*
-_subject_autocomplete(ProfWin *window, const char *const input)
+_subject_autocomplete(ProfWin *window, const char *const input, gboolean previous)
 {
     char *result = NULL;
 
@@ -2895,7 +2895,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;
     }
@@ -2904,7 +2904,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;
@@ -2916,7 +2916,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);
@@ -2927,7 +2927,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);
@@ -2938,7 +2938,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);
@@ -2949,7 +2949,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);
@@ -2960,7 +2960,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);
@@ -2982,7 +2982,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);
@@ -2994,7 +2994,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);
@@ -3007,7 +3007,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);
@@ -3017,7 +3017,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;
     }
@@ -3028,42 +3028,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_funcs.c b/src/command/cmd_funcs.c
index b1db10d6..a2d2571f 100644
--- a/src/command/cmd_funcs.c
+++ b/src/command/cmd_funcs.c
@@ -2133,16 +2133,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 +3562,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/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 6dc8ef32..b86f710a 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 cc605c79..134fba49 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,54 @@ 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);
+    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_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);
@@ -368,7 +433,7 @@ _search_from(Autocomplete ac, GSList *curr, gboolean quote)
         }
 
         g_free(curr_lower);
-        curr = g_slist_next(curr);
+        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 <glib.h>
 
-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..3b904c62 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -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,35 @@ _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;
+            free(result);
+        }
+    } else if (strncmp(rl_line_buffer, "/", 1) == 0) {
+        ProfWin *window = wins_get_current();
+        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;
@@ -485,7 +532,7 @@ _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, 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 a04dc9e6..c2c6a969 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -278,7 +278,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 cf16dbab..2d19ab32 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 dcbb7615..2befccd2 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 7452e581..f2d8c5d7 100644
--- a/tests/unittests/ui/stub_ui.c
+++ b/tests/unittests/ui/stub_ui.c
@@ -408,7 +408,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..2938b9ff 100644
--- a/tests/unittests/unittests.c
+++ b/tests/unittests/unittests.c
@@ -95,6 +95,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 38f7428e..630c0b19 100644
--- a/tests/unittests/xmpp/stub_xmpp.c
+++ b/tests/unittests/xmpp/stub_xmpp.c
@@ -128,7 +128,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;
 }
@@ -140,7 +140,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;
 }
@@ -250,7 +250,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;
 }
@@ -298,7 +298,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;
 }