about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2015-01-16 23:12:00 +0000
committerJames Booth <boothj5@gmail.com>2015-01-16 23:12:00 +0000
commit972d524fdcbcf7d706f5970853180a856ff044b8 (patch)
tree613b1a215ede3314cd4600783550baf849dda7ce
parent9fad03af747a2345fa3da7d071a6acd1017d204b (diff)
parent4c6cfcdca0f7aec1f0e3243a60d88ed494357a5d (diff)
downloadprofani-tty-972d524fdcbcf7d706f5970853180a856ff044b8.tar.gz
Merge branch 'master' into inp-utf8
-rw-r--r--Makefile.am8
-rw-r--r--src/command/command.c434
-rw-r--r--src/command/command.h6
-rw-r--r--src/command/history.c81
-rw-r--r--src/command/history.h40
-rw-r--r--src/common.c2
-rw-r--r--src/common.h2
-rw-r--r--src/config/accounts.c4
-rw-r--r--src/config/accounts.h4
-rw-r--r--src/config/preferences.c2
-rw-r--r--src/config/preferences.h2
-rw-r--r--src/muc.c16
-rw-r--r--src/muc.h4
-rw-r--r--src/roster_list.c8
-rw-r--r--src/roster_list.h8
-rw-r--r--src/tools/autocomplete.c54
-rw-r--r--src/tools/autocomplete.h10
-rw-r--r--src/tools/parser.c4
-rw-r--r--src/tools/parser.h4
-rw-r--r--src/ui/core.c8
-rw-r--r--src/ui/inputwin.c53
-rw-r--r--src/ui/inputwin.h3
-rw-r--r--src/ui/ui.h3
-rw-r--r--src/xmpp/bookmark.c2
-rw-r--r--src/xmpp/presence.c2
-rw-r--r--src/xmpp/xmpp.h4
-rw-r--r--tests/ui/stub_ui.c3
-rw-r--r--tests/xmpp/stub_xmpp.c4
28 files changed, 317 insertions, 458 deletions
diff --git a/Makefile.am b/Makefile.am
index 9d44c003..d9fa9729 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,9 +21,9 @@ core_sources = \
 	src/ui/windows.c src/ui/windows.h \
 	src/ui/rosterwin.c src/ui/occupantswin.c \
 	src/ui/buffer.c src/ui/buffer.h \
-	src/command/command.h src/command/command.c src/command/history.c \
+	src/command/command.h src/command/command.c \
 	src/command/commands.h src/command/commands.c \
-	src/command/history.h src/tools/parser.c \
+	src/tools/parser.c \
 	src/tools/parser.h \
 	src/tools/p_sha1.h src/tools/p_sha1.c \
 	src/tools/autocomplete.c src/tools/autocomplete.h \
@@ -44,9 +44,9 @@ tests_sources = \
 	src/roster_list.c src/roster_list.h \
 	src/xmpp/xmpp.h src/xmpp/form.c \
 	src/ui/ui.h \
-	src/command/command.h src/command/command.c src/command/history.c \
+	src/command/command.h src/command/command.c \
 	src/command/commands.h src/command/commands.c \
-	src/command/history.h src/tools/parser.c \
+	src/tools/parser.c \
 	src/tools/parser.h \
 	src/tools/p_sha1.h src/tools/p_sha1.c \
 	src/tools/autocomplete.c src/tools/autocomplete.h \
diff --git a/src/command/command.c b/src/command/command.c
index 5535c022..8e16276b 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -45,7 +45,6 @@
 #include "chat_session.h"
 #include "command/command.h"
 #include "command/commands.h"
-#include "command/history.h"
 #include "common.h"
 #include "config/accounts.h"
 #include "config/preferences.h"
@@ -74,34 +73,34 @@ static gboolean _cmd_execute(const char * const command, const char * const inp)
 static gboolean _cmd_execute_default(const char * inp);
 static gboolean _cmd_execute_alias(const char * const inp, gboolean *ran);
 
-static void _cmd_complete_parameters(char *input, int *size);
-
-static char * _sub_autocomplete(char *input, int *size);
-static char * _notify_autocomplete(char *input, int *size);
-static char * _theme_autocomplete(char *input, int *size);
-static char * _autoaway_autocomplete(char *input, int *size);
-static char * _autoconnect_autocomplete(char *input, int *size);
-static char * _account_autocomplete(char *input, int *size);
-static char * _who_autocomplete(char *input, int *size);
-static char * _roster_autocomplete(char *input, int *size);
-static char * _group_autocomplete(char *input, int *size);
-static char * _bookmark_autocomplete(char *input, int *size);
-static char * _otr_autocomplete(char *input, int *size);
-static char * _connect_autocomplete(char *input, int *size);
-static char * _statuses_autocomplete(char *input, int *size);
-static char * _alias_autocomplete(char *input, int *size);
-static char * _join_autocomplete(char *input, int *size);
-static char * _log_autocomplete(char *input, int *size);
-static char * _form_autocomplete(char *input, int *size);
-static char * _form_field_autocomplete(char *input, int *size);
-static char * _occupants_autocomplete(char *input, int *size);
-static char * _kick_autocomplete(char *input, int *size);
-static char * _ban_autocomplete(char *input, int *size);
-static char * _affiliation_autocomplete(char *input, int *size);
-static char * _role_autocomplete(char *input, int *size);
-static char * _resource_autocomplete(char *input, int *size);
-static char * _titlebar_autocomplete(char *input, int *size);
-static char * _inpblock_autocomplete(char *input, int *size);
+static char * _cmd_complete_parameters(const char * const input);
+
+static char * _sub_autocomplete(const char * const input);
+static char * _notify_autocomplete(const char * const input);
+static char * _theme_autocomplete(const char * const input);
+static char * _autoaway_autocomplete(const char * const input);
+static char * _autoconnect_autocomplete(const char * const input);
+static char * _account_autocomplete(const char * const input);
+static char * _who_autocomplete(const char * const input);
+static char * _roster_autocomplete(const char * const input);
+static char * _group_autocomplete(const char * const input);
+static char * _bookmark_autocomplete(const char * const input);
+static char * _otr_autocomplete(const char * const input);
+static char * _connect_autocomplete(const char * const input);
+static char * _statuses_autocomplete(const char * const input);
+static char * _alias_autocomplete(const char * const input);
+static char * _join_autocomplete(const char * const input);
+static char * _log_autocomplete(const char * const input);
+static char * _form_autocomplete(const char * const input);
+static char * _form_field_autocomplete(const char * const input);
+static char * _occupants_autocomplete(const char * const input);
+static char * _kick_autocomplete(const char * const input);
+static char * _ban_autocomplete(const char * const input);
+static char * _affiliation_autocomplete(const char * const input);
+static char * _role_autocomplete(const char * const input);
+static char * _resource_autocomplete(const char * const input);
+static char * _titlebar_autocomplete(const char * const input);
+static char * _inpblock_autocomplete(const char * const input);
 
 GHashTable *commands = NULL;
 
@@ -1480,8 +1479,6 @@ cmd_init(void)
     inpblock_ac = autocomplete_new();
     autocomplete_add(inpblock_ac, "timeout");
     autocomplete_add(inpblock_ac, "dynamic");
-
-    cmd_history_init();
 }
 
 void
@@ -1617,30 +1614,26 @@ cmd_alias_remove(char *value)
 }
 
 // Command autocompletion functions
-void
-cmd_autocomplete(char *input, int *size)
+char*
+cmd_autocomplete(const char * const input)
 {
     // autocomplete command
-    if ((strncmp(input, "/", 1) == 0) && (!str_contains(input, *size, ' '))) {
-        int i = 0;
+    if ((strncmp(input, "/", 1) == 0) && (!str_contains(input, strlen(input), ' '))) {
         char *found = NULL;
-        char inp_cpy[*size];
-        for(i = 0; i < *size; i++) {
-            inp_cpy[i] = input[i];
-        }
-        inp_cpy[i] = '\0';
-        found = autocomplete_complete(commands_ac, inp_cpy, TRUE);
+        found = autocomplete_complete(commands_ac, input, TRUE);
         if (found != NULL) {
-            char *auto_msg = strdup(found);
-            ui_replace_input(input, auto_msg, size);
-            free(auto_msg);
-            free(found);
+            return found;
         }
 
     // autocomplete parameters
     } else {
-        _cmd_complete_parameters(input, size);
+        char *found = _cmd_complete_parameters(input);
+        if (found) {
+            return found;
+        }
     }
+
+    return NULL;
 }
 
 void
@@ -1745,7 +1738,7 @@ cmd_process_input(char *inp)
 
     // add line to history if something typed
     if (strlen(inp) > 0) {
-        cmd_history_append(inp);
+        ui_inp_history_append(inp);
     }
 
     // just carry on if no input
@@ -1952,8 +1945,8 @@ _cmd_execute_default(const char * inp)
     return TRUE;
 }
 
-static void
-_cmd_complete_parameters(char *input, int *size)
+static char *
+_cmd_complete_parameters(const char * const input)
 {
     int i;
     char *result = NULL;
@@ -1964,12 +1957,9 @@ _cmd_complete_parameters(char *input, int *size)
         "/vercheck", "/privileges", "/presence", "/wrap" };
 
     for (i = 0; i < ARRAY_SIZE(boolean_choices); i++) {
-        result = autocomplete_param_with_func(input, size, boolean_choices[i],
-            prefs_autocomplete_boolean_choice);
-        if (result != NULL) {
-            ui_replace_input(input, result, size);
-            g_free(result);
-            return;
+        result = autocomplete_param_with_func(input, boolean_choices[i], prefs_autocomplete_boolean_choice);
+        if (result) {
+            return result;
         }
     }
 
@@ -1977,16 +1967,13 @@ _cmd_complete_parameters(char *input, int *size)
     if (ui_current_win_type() == WIN_MUC) {
         ProfMucWin *mucwin = wins_get_current_muc();
         Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
-        if (nick_ac != NULL) {
+        if (nick_ac) {
             gchar *nick_choices[] = { "/msg", "/info", "/caps", "/status", "/software" } ;
 
             for (i = 0; i < ARRAY_SIZE(nick_choices); i++) {
-                result = autocomplete_param_with_ac(input, size, nick_choices[i],
-                    nick_ac, TRUE);
-                if (result != NULL) {
-                    ui_replace_input(input, result, size);
-                    g_free(result);
-                    return;
+                result = autocomplete_param_with_ac(input, nick_choices[i], nick_ac, TRUE);
+                if (result) {
+                    return result;
                 }
             }
         }
@@ -1995,42 +1982,31 @@ _cmd_complete_parameters(char *input, int *size)
     } else {
         gchar *contact_choices[] = { "/msg", "/info", "/status" };
         for (i = 0; i < ARRAY_SIZE(contact_choices); i++) {
-            result = autocomplete_param_with_func(input, size, contact_choices[i],
-                roster_contact_autocomplete);
-            if (result != NULL) {
-                ui_replace_input(input, result, size);
-                g_free(result);
-                return;
+            result = autocomplete_param_with_func(input, contact_choices[i], roster_contact_autocomplete);
+            if (result) {
+                return result;
             }
         }
 
         gchar *resource_choices[] = { "/caps", "/software", "/ping" };
         for (i = 0; i < ARRAY_SIZE(resource_choices); i++) {
-            result = autocomplete_param_with_func(input, size, resource_choices[i],
-                roster_fulljid_autocomplete);
-            if (result != NULL) {
-                ui_replace_input(input, result, size);
-                g_free(result);
-                return;
+            result = autocomplete_param_with_func(input, resource_choices[i], roster_fulljid_autocomplete);
+            if (result) {
+                return result;
             }
         }
     }
 
-    result = autocomplete_param_with_func(input, size, "/invite", roster_contact_autocomplete);
-    if (result != NULL) {
-        ui_replace_input(input, result, size);
-        g_free(result);
-        return;
+    result = autocomplete_param_with_func(input, "/invite", roster_contact_autocomplete);
+    if (result) {
+        return result;
     }
 
     gchar *invite_choices[] = { "/decline", "/join" };
     for (i = 0; i < ARRAY_SIZE(invite_choices); i++) {
-        result = autocomplete_param_with_func(input, size, invite_choices[i],
-            muc_invites_find);
-        if (result != NULL) {
-            ui_replace_input(input, result, size);
-            g_free(result);
-            return;
+        result = autocomplete_param_with_func(input, invite_choices[i], muc_invites_find);
+        if (result) {
+            return result;
         }
     }
 
@@ -2038,11 +2014,9 @@ _cmd_complete_parameters(char *input, int *size)
     Autocomplete completers[] = { help_ac, prefs_ac, disco_ac, close_ac, wins_ac, subject_ac, room_ac, time_ac };
 
     for (i = 0; i < ARRAY_SIZE(cmds); i++) {
-        result = autocomplete_param_with_ac(input, size, cmds[i], completers[i], TRUE);
-        if (result != NULL) {
-            ui_replace_input(input, result, size);
-            g_free(result);
-            return;
+        result = autocomplete_param_with_ac(input, cmds[i], completers[i], TRUE);
+        if (result) {
+            return result;
         }
     }
 
@@ -2073,9 +2047,10 @@ _cmd_complete_parameters(char *input, int *size)
     g_hash_table_insert(ac_funcs, "/titlebar",      _titlebar_autocomplete);
     g_hash_table_insert(ac_funcs, "/inpblock",      _inpblock_autocomplete);
 
-    char parsed[*size+1];
+    int len = strlen(input);
+    char parsed[len+1];
     i = 0;
-    while (i < *size) {
+    while (i < len) {
         if (input[i] == ' ') {
             break;
         } else {
@@ -2085,44 +2060,39 @@ _cmd_complete_parameters(char *input, int *size)
     }
     parsed[i] = '\0';
 
-    char * (*ac_func)(char *, int *) = g_hash_table_lookup(ac_funcs, parsed);
+    char * (*ac_func)(const char * const) = g_hash_table_lookup(ac_funcs, parsed);
     if (ac_func != NULL) {
-        result = ac_func(input, size);
-        if (result != NULL) {
-            ui_replace_input(input, result, size);
-            g_free(result);
+        result = ac_func(input);
+        if (result) {
             g_hash_table_destroy(ac_funcs);
-            return;
+            return result;
         }
     }
     g_hash_table_destroy(ac_funcs);
 
-    input[*size] = '\0';
     if (g_str_has_prefix(input, "/field")) {
-        result = _form_field_autocomplete(input, size);
-        if (result != NULL) {
-            ui_replace_input(input, result, size);
-            g_free(result);
-            return;
+        result = _form_field_autocomplete(input);
+        if (result) {
+            return result;
         }
     }
 
-    return;
+    return NULL;
 }
 
 static char *
-_sub_autocomplete(char *input, int *size)
+_sub_autocomplete(const char * const input)
 {
     char *result = NULL;
-    result = autocomplete_param_with_func(input, size, "/sub allow", presence_sub_request_find);
+    result = autocomplete_param_with_func(input, "/sub allow", presence_sub_request_find);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_func(input, size, "/sub deny", presence_sub_request_find);
+    result = autocomplete_param_with_func(input, "/sub deny", presence_sub_request_find);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_ac(input, size, "/sub", sub_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/sub", sub_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2131,13 +2101,13 @@ _sub_autocomplete(char *input, int *size)
 }
 
 static char *
-_who_autocomplete(char *input, int *size)
+_who_autocomplete(const char * const input)
 {
     char *result = NULL;
     win_type_t win_type = ui_current_win_type();
 
     if (win_type == WIN_MUC) {
-        result = autocomplete_param_with_ac(input, size, "/who", who_room_ac, TRUE);
+        result = autocomplete_param_with_ac(input, "/who", who_room_ac, TRUE);
         if (result != NULL) {
             return result;
         }
@@ -2148,13 +2118,13 @@ _who_autocomplete(char *input, int *size)
             "/who unavailable" };
 
         for (i = 0; i < ARRAY_SIZE(group_commands); i++) {
-            result = autocomplete_param_with_func(input, size, group_commands[i], roster_group_autocomplete);
+            result = autocomplete_param_with_func(input, group_commands[i], roster_group_autocomplete);
             if (result != NULL) {
                 return result;
             }
         }
 
-        result = autocomplete_param_with_ac(input, size, "/who", who_roster_ac, TRUE);
+        result = autocomplete_param_with_ac(input, "/who", who_roster_ac, TRUE);
         if (result != NULL) {
             return result;
         }
@@ -2164,34 +2134,34 @@ _who_autocomplete(char *input, int *size)
 }
 
 static char *
-_roster_autocomplete(char *input, int *size)
+_roster_autocomplete(const char * const input)
 {
     char *result = NULL;
-    result = autocomplete_param_with_func(input, size, "/roster nick", roster_barejid_autocomplete);
+    result = autocomplete_param_with_func(input, "/roster nick", roster_barejid_autocomplete);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_func(input, size, "/roster clearnick", roster_barejid_autocomplete);
+    result = autocomplete_param_with_func(input, "/roster clearnick", roster_barejid_autocomplete);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_func(input, size, "/roster remove", roster_barejid_autocomplete);
+    result = autocomplete_param_with_func(input, "/roster remove", roster_barejid_autocomplete);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_ac(input, size, "/roster show", roster_option_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/roster show", roster_option_ac, TRUE);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_ac(input, size, "/roster hide", roster_option_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/roster hide", roster_option_ac, TRUE);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_ac(input, size, "/roster by", roster_by_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/roster by", roster_by_ac, TRUE);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_ac(input, size, "/roster", roster_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/roster", roster_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2200,31 +2170,31 @@ _roster_autocomplete(char *input, int *size)
 }
 
 static char *
-_group_autocomplete(char *input, int *size)
+_group_autocomplete(const char * const input)
 {
     char *result = NULL;
-    result = autocomplete_param_with_func(input, size, "/group show", roster_group_autocomplete);
+    result = autocomplete_param_with_func(input, "/group show", roster_group_autocomplete);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_no_with_func(input, size, "/group add", 4, roster_contact_autocomplete);
+    result = autocomplete_param_no_with_func(input, "/group add", 4, roster_contact_autocomplete);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_no_with_func(input, size, "/group remove", 4, roster_contact_autocomplete);
+    result = autocomplete_param_no_with_func(input, "/group remove", 4, roster_contact_autocomplete);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_func(input, size, "/group add", roster_group_autocomplete);
+    result = autocomplete_param_with_func(input, "/group add", roster_group_autocomplete);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_func(input, size, "/group remove", roster_group_autocomplete);
+    result = autocomplete_param_with_func(input, "/group remove", roster_group_autocomplete);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_ac(input, size, "/group", group_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/group", group_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2233,7 +2203,7 @@ _group_autocomplete(char *input, int *size)
 }
 
 static char *
-_bookmark_autocomplete(char *input, int *size)
+_bookmark_autocomplete(const char * const input)
 {
     char *found = NULL;
 
@@ -2281,9 +2251,9 @@ _bookmark_autocomplete(char *input, int *size)
         }
 
         if (autojoin) {
-            found = autocomplete_param_with_func(input, size, beginning->str, prefs_autocomplete_boolean_choice);
+            found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice);
         } else {
-            found = autocomplete_param_with_ac(input, size, beginning->str, bookmark_property_ac, TRUE);
+            found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE);
         }
         g_string_free(beginning, TRUE);
         if (found != NULL) {
@@ -2294,79 +2264,79 @@ _bookmark_autocomplete(char *input, int *size)
 
     g_strfreev(args);
 
-    found = autocomplete_param_with_func(input, size, "/bookmark remove", bookmark_find);
+    found = autocomplete_param_with_func(input, "/bookmark remove", bookmark_find);
     if (found != NULL) {
         return found;
     }
-    found = autocomplete_param_with_func(input, size, "/bookmark join", bookmark_find);
+    found = autocomplete_param_with_func(input, "/bookmark join", bookmark_find);
     if (found != NULL) {
         return found;
     }
-    found = autocomplete_param_with_func(input, size, "/bookmark update", bookmark_find);
+    found = autocomplete_param_with_func(input, "/bookmark update", bookmark_find);
     if (found != NULL) {
         return found;
     }
 
-    found = autocomplete_param_with_ac(input, size, "/bookmark", bookmark_ac, TRUE);
+    found = autocomplete_param_with_ac(input, "/bookmark", bookmark_ac, TRUE);
     return found;
 }
 
 static char *
-_notify_autocomplete(char *input, int *size)
+_notify_autocomplete(const char * const input)
 {
     int i = 0;
     char *result = NULL;
 
-    result = autocomplete_param_with_func(input, size, "/notify room current", prefs_autocomplete_boolean_choice);
+    result = autocomplete_param_with_func(input, "/notify room current", prefs_autocomplete_boolean_choice);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_func(input, size, "/notify message current", prefs_autocomplete_boolean_choice);
+    result = autocomplete_param_with_func(input, "/notify message current", prefs_autocomplete_boolean_choice);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_func(input, size, "/notify typing current", prefs_autocomplete_boolean_choice);
+    result = autocomplete_param_with_func(input, "/notify typing current", prefs_autocomplete_boolean_choice);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_func(input, size, "/notify room text", prefs_autocomplete_boolean_choice);
+    result = autocomplete_param_with_func(input, "/notify room text", prefs_autocomplete_boolean_choice);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_func(input, size, "/notify message text", prefs_autocomplete_boolean_choice);
+    result = autocomplete_param_with_func(input, "/notify message text", prefs_autocomplete_boolean_choice);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/notify room", notify_room_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/notify room", notify_room_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/notify message", notify_message_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/notify message", notify_message_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/notify typing", notify_typing_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/notify typing", notify_typing_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
     gchar *boolean_choices[] = { "/notify invite", "/notify sub" };
     for (i = 0; i < ARRAY_SIZE(boolean_choices); i++) {
-        result = autocomplete_param_with_func(input, size, boolean_choices[i],
+        result = autocomplete_param_with_func(input, boolean_choices[i],
             prefs_autocomplete_boolean_choice);
         if (result != NULL) {
             return result;
         }
     }
 
-    result = autocomplete_param_with_ac(input, size, "/notify", notify_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/notify", notify_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2375,20 +2345,20 @@ _notify_autocomplete(char *input, int *size)
 }
 
 static char *
-_autoaway_autocomplete(char *input, int *size)
+_autoaway_autocomplete(const char * const input)
 {
     char *result = NULL;
 
-    result = autocomplete_param_with_ac(input, size, "/autoaway mode", autoaway_mode_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/autoaway mode", autoaway_mode_ac, TRUE);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_func(input, size, "/autoaway check",
+    result = autocomplete_param_with_func(input, "/autoaway check",
         prefs_autocomplete_boolean_choice);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_ac(input, size, "/autoaway", autoaway_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/autoaway", autoaway_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2397,21 +2367,21 @@ _autoaway_autocomplete(char *input, int *size)
 }
 
 static char *
-_log_autocomplete(char *input, int *size)
+_log_autocomplete(const char * const input)
 {
     char *result = NULL;
 
-    result = autocomplete_param_with_func(input, size, "/log rotate",
+    result = autocomplete_param_with_func(input, "/log rotate",
         prefs_autocomplete_boolean_choice);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_func(input, size, "/log shared",
+    result = autocomplete_param_with_func(input, "/log shared",
         prefs_autocomplete_boolean_choice);
     if (result != NULL) {
         return result;
     }
-    result = autocomplete_param_with_ac(input, size, "/log", log_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/log", log_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2420,16 +2390,16 @@ _log_autocomplete(char *input, int *size)
 }
 
 static char *
-_autoconnect_autocomplete(char *input, int *size)
+_autoconnect_autocomplete(const char * const input)
 {
     char *result = NULL;
 
-    result = autocomplete_param_with_func(input, size, "/autoconnect set", accounts_find_enabled);
+    result = autocomplete_param_with_func(input, "/autoconnect set", accounts_find_enabled);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/autoconnect", autoconnect_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/autoconnect", autoconnect_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2438,16 +2408,16 @@ _autoconnect_autocomplete(char *input, int *size)
 }
 
 static char *
-_otr_autocomplete(char *input, int *size)
+_otr_autocomplete(const char * const input)
 {
     char *found = NULL;
 
-    found = autocomplete_param_with_func(input, size, "/otr start", roster_contact_autocomplete);
+    found = autocomplete_param_with_func(input, "/otr start", roster_contact_autocomplete);
     if (found != NULL) {
         return found;
     }
 
-    found = autocomplete_param_with_ac(input, size, "/otr log", otr_log_ac, TRUE);
+    found = autocomplete_param_with_ac(input, "/otr log", otr_log_ac, TRUE);
     if (found != NULL) {
         return found;
     }
@@ -2461,7 +2431,7 @@ _otr_autocomplete(char *input, int *size)
         g_string_append(beginning, " ");
         g_string_append(beginning, args[1]);
 
-        found = autocomplete_param_with_func(input, size, beginning->str, roster_contact_autocomplete);
+        found = autocomplete_param_with_func(input, beginning->str, roster_contact_autocomplete);
         g_string_free(beginning, TRUE);
         if (found != NULL) {
             g_strfreev(args);
@@ -2471,18 +2441,18 @@ _otr_autocomplete(char *input, int *size)
 
     g_strfreev(args);
 
-    found = autocomplete_param_with_ac(input, size, "/otr policy", otr_policy_ac, TRUE);
+    found = autocomplete_param_with_ac(input, "/otr policy", otr_policy_ac, TRUE);
     if (found != NULL) {
         return found;
     }
 
-    found = autocomplete_param_with_func(input, size, "/otr warn",
+    found = autocomplete_param_with_func(input, "/otr warn",
         prefs_autocomplete_boolean_choice);
     if (found != NULL) {
         return found;
     }
 
-    found = autocomplete_param_with_ac(input, size, "/otr", otr_ac, TRUE);
+    found = autocomplete_param_with_ac(input, "/otr", otr_ac, TRUE);
     if (found != NULL) {
         return found;
     }
@@ -2491,10 +2461,10 @@ _otr_autocomplete(char *input, int *size)
 }
 
 static char *
-_theme_autocomplete(char *input, int *size)
+_theme_autocomplete(const char * const input)
 {
     char *result = NULL;
-    if ((strncmp(input, "/theme set ", 11) == 0) && (*size > 11)) {
+    if ((strncmp(input, "/theme set ", 11) == 0) && (strlen(input) > 11)) {
         if (theme_load_ac == NULL) {
             theme_load_ac = autocomplete_new();
             GSList *themes = theme_list();
@@ -2505,12 +2475,12 @@ _theme_autocomplete(char *input, int *size)
             g_slist_free(themes);
             autocomplete_add(theme_load_ac, "default");
         }
-        result = autocomplete_param_with_ac(input, size, "/theme set", theme_load_ac, TRUE);
+        result = autocomplete_param_with_ac(input, "/theme set", theme_load_ac, TRUE);
         if (result != NULL) {
             return result;
         }
     }
-    result = autocomplete_param_with_ac(input, size, "/theme", theme_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/theme", theme_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2519,7 +2489,7 @@ _theme_autocomplete(char *input, int *size)
 }
 
 static char *
-_resource_autocomplete(char *input, int *size)
+_resource_autocomplete(const char * const input)
 {
     char *found = NULL;
 
@@ -2529,24 +2499,24 @@ _resource_autocomplete(char *input, int *size)
         PContact contact = roster_get_contact(chatwin->barejid);
         if (contact) {
             Autocomplete ac = p_contact_resource_ac(contact);
-            found = autocomplete_param_with_ac(input, size, "/resource set", ac, FALSE);
+            found = autocomplete_param_with_ac(input, "/resource set", ac, FALSE);
             if (found != NULL) {
                 return found;
             }
         }
     }
 
-    found = autocomplete_param_with_func(input, size, "/resource title", prefs_autocomplete_boolean_choice);
+    found = autocomplete_param_with_func(input, "/resource title", prefs_autocomplete_boolean_choice);
     if (found != NULL) {
         return found;
     }
 
-    found = autocomplete_param_with_func(input, size, "/resource message", prefs_autocomplete_boolean_choice);
+    found = autocomplete_param_with_func(input, "/resource message", prefs_autocomplete_boolean_choice);
     if (found != NULL) {
         return found;
     }
 
-    found = autocomplete_param_with_ac(input, size, "/resource", resource_ac, FALSE);
+    found = autocomplete_param_with_ac(input, "/resource", resource_ac, FALSE);
     if (found != NULL) {
         return found;
     }
@@ -2555,21 +2525,21 @@ _resource_autocomplete(char *input, int *size)
 }
 
 static char *
-_titlebar_autocomplete(char *input, int *size)
+_titlebar_autocomplete(const char * const input)
 {
     char *found = NULL;
 
-    found = autocomplete_param_with_func(input, size, "/titlebar show", prefs_autocomplete_boolean_choice);
+    found = autocomplete_param_with_func(input, "/titlebar show", prefs_autocomplete_boolean_choice);
     if (found != NULL) {
         return found;
     }
 
-    found = autocomplete_param_with_func(input, size, "/titlebar goodbye", prefs_autocomplete_boolean_choice);
+    found = autocomplete_param_with_func(input, "/titlebar goodbye", prefs_autocomplete_boolean_choice);
     if (found != NULL) {
         return found;
     }
 
-    found = autocomplete_param_with_ac(input, size, "/titlebar", titlebar_ac, FALSE);
+    found = autocomplete_param_with_ac(input, "/titlebar", titlebar_ac, FALSE);
     if (found != NULL) {
         return found;
     }
@@ -2578,16 +2548,16 @@ _titlebar_autocomplete(char *input, int *size)
 }
 
 static char *
-_inpblock_autocomplete(char *input, int *size)
+_inpblock_autocomplete(const char * const input)
 {
     char *found = NULL;
 
-    found = autocomplete_param_with_func(input, size, "/inpblock dynamic", prefs_autocomplete_boolean_choice);
+    found = autocomplete_param_with_func(input, "/inpblock dynamic", prefs_autocomplete_boolean_choice);
     if (found != NULL) {
         return found;
     }
 
-    found = autocomplete_param_with_ac(input, size, "/inpblock", inpblock_ac, FALSE);
+    found = autocomplete_param_with_ac(input, "/inpblock", inpblock_ac, FALSE);
     if (found != NULL) {
         return found;
     }
@@ -2596,7 +2566,7 @@ _inpblock_autocomplete(char *input, int *size)
 }
 
 static char *
-_form_autocomplete(char *input, int *size)
+_form_autocomplete(const char * const input)
 {
     ProfWin *current = wins_get_current();
     if (current->type != WIN_MUC_CONFIG) {
@@ -2608,13 +2578,13 @@ _form_autocomplete(char *input, int *size)
     ProfMucConfWin *confwin = (ProfMucConfWin*)current;
     DataForm *form = confwin->form;
     if (form) {
-        found = autocomplete_param_with_ac(input, size, "/form help", form->tag_ac, TRUE);
+        found = autocomplete_param_with_ac(input, "/form help", form->tag_ac, TRUE);
         if (found != NULL) {
             return found;
         }
     }
 
-    found = autocomplete_param_with_ac(input, size, "/form", form_ac, TRUE);
+    found = autocomplete_param_with_ac(input, "/form", form_ac, TRUE);
     if (found != NULL) {
         return found;
     }
@@ -2623,7 +2593,7 @@ _form_autocomplete(char *input, int *size)
 }
 
 static char *
-_form_field_autocomplete(char *input, int *size)
+_form_field_autocomplete(const char * const input)
 {
     ProfWin *current = wins_get_current();
     if (current->type != WIN_MUC_CONFIG) {
@@ -2638,7 +2608,6 @@ _form_field_autocomplete(char *input, int *size)
         return NULL;
     }
 
-    input[*size] = '\0';
     gchar **split = g_strsplit(input, " ", 0);
 
     if (g_strv_length(split) == 3) {
@@ -2652,13 +2621,13 @@ _form_field_autocomplete(char *input, int *size)
 
             if (((g_strcmp0(split[1], "add") == 0) || (g_strcmp0(split[1], "remove") == 0))
                     && field_type == FIELD_LIST_MULTI) {
-                found = autocomplete_param_with_ac(input, size, beginning->str, value_ac, TRUE);
+                found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE);
 
             } else if ((g_strcmp0(split[1], "remove") == 0) && field_type == FIELD_TEXT_MULTI) {
-                found = autocomplete_param_with_ac(input, size, beginning->str, value_ac, TRUE);
+                found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE);
 
             } else if ((g_strcmp0(split[1], "remove") == 0) && field_type == FIELD_JID_MULTI) {
-                found = autocomplete_param_with_ac(input, size, beginning->str, value_ac, TRUE);
+                found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE);
             }
 
             g_string_free(beginning, TRUE);
@@ -2673,15 +2642,15 @@ _form_field_autocomplete(char *input, int *size)
             switch (field_type)
             {
                 case FIELD_BOOLEAN:
-                    found = autocomplete_param_with_func(input, size, split[0], prefs_autocomplete_boolean_choice);
+                    found = autocomplete_param_with_func(input, split[0], prefs_autocomplete_boolean_choice);
                     break;
                 case FIELD_LIST_SINGLE:
-                    found = autocomplete_param_with_ac(input, size, split[0], value_ac, TRUE);
+                    found = autocomplete_param_with_ac(input, split[0], value_ac, TRUE);
                     break;
                 case FIELD_LIST_MULTI:
                 case FIELD_JID_MULTI:
                 case FIELD_TEXT_MULTI:
-                    found = autocomplete_param_with_ac(input, size, split[0], form_field_multi_ac, TRUE);
+                    found = autocomplete_param_with_ac(input, split[0], form_field_multi_ac, TRUE);
                     break;
                 default:
                     break;
@@ -2695,16 +2664,16 @@ _form_field_autocomplete(char *input, int *size)
 }
 
 static char *
-_occupants_autocomplete(char *input, int *size)
+_occupants_autocomplete(const char * const input)
 {
     char *found = NULL;
 
-    found = autocomplete_param_with_ac(input, size, "/occupants default", occupants_default_ac, TRUE);
+    found = autocomplete_param_with_ac(input, "/occupants default", occupants_default_ac, TRUE);
     if (found != NULL) {
         return found;
     }
 
-    found = autocomplete_param_with_ac(input, size, "/occupants", occupants_ac, TRUE);
+    found = autocomplete_param_with_ac(input, "/occupants", occupants_ac, TRUE);
     if (found != NULL) {
         return found;
     }
@@ -2713,7 +2682,7 @@ _occupants_autocomplete(char *input, int *size)
 }
 
 static char *
-_kick_autocomplete(char *input, int *size)
+_kick_autocomplete(const char * const input)
 {
     char *result = NULL;
 
@@ -2722,7 +2691,7 @@ _kick_autocomplete(char *input, int *size)
         Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
 
         if (nick_ac != NULL) {
-            result = autocomplete_param_with_ac(input, size, "/kick", nick_ac, TRUE);
+            result = autocomplete_param_with_ac(input, "/kick", nick_ac, TRUE);
             if (result != NULL) {
                 return result;
             }
@@ -2733,7 +2702,7 @@ _kick_autocomplete(char *input, int *size)
 }
 
 static char *
-_ban_autocomplete(char *input, int *size)
+_ban_autocomplete(const char * const input)
 {
     char *result = NULL;
 
@@ -2742,7 +2711,7 @@ _ban_autocomplete(char *input, int *size)
         Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid);
 
         if (jid_ac != NULL) {
-            result = autocomplete_param_with_ac(input, size, "/ban", jid_ac, TRUE);
+            result = autocomplete_param_with_ac(input, "/ban", jid_ac, TRUE);
             if (result != NULL) {
                 return result;
             }
@@ -2753,7 +2722,7 @@ _ban_autocomplete(char *input, int *size)
 }
 
 static char *
-_affiliation_autocomplete(char *input, int *size)
+_affiliation_autocomplete(const char * const input)
 {
     char *result = NULL;
 
@@ -2762,7 +2731,6 @@ _affiliation_autocomplete(char *input, int *size)
         gboolean parse_result;
         Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid);
 
-        input[*size] = '\0';
         gchar **args = parse_args(input, 3, 3, &parse_result);
 
         if ((strncmp(input, "/affiliation", 12) == 0) && (parse_result == TRUE)) {
@@ -2771,7 +2739,7 @@ _affiliation_autocomplete(char *input, int *size)
             g_string_append(beginning, " ");
             g_string_append(beginning, args[1]);
 
-            result = autocomplete_param_with_ac(input, size, beginning->str, jid_ac, TRUE);
+            result = autocomplete_param_with_ac(input, beginning->str, jid_ac, TRUE);
             g_string_free(beginning, TRUE);
             if (result != NULL) {
                 g_strfreev(args);
@@ -2782,17 +2750,17 @@ _affiliation_autocomplete(char *input, int *size)
         g_strfreev(args);
     }
 
-    result = autocomplete_param_with_ac(input, size, "/affiliation set", affiliation_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/affiliation set", affiliation_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/affiliation list", affiliation_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/affiliation list", affiliation_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/affiliation", privilege_cmd_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/affiliation", privilege_cmd_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2801,7 +2769,7 @@ _affiliation_autocomplete(char *input, int *size)
 }
 
 static char *
-_role_autocomplete(char *input, int *size)
+_role_autocomplete(const char * const input)
 {
     char *result = NULL;
 
@@ -2810,7 +2778,6 @@ _role_autocomplete(char *input, int *size)
         gboolean parse_result;
         Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
 
-        input[*size] = '\0';
         gchar **args = parse_args(input, 3, 3, &parse_result);
 
         if ((strncmp(input, "/role", 5) == 0) && (parse_result == TRUE)) {
@@ -2819,7 +2786,7 @@ _role_autocomplete(char *input, int *size)
             g_string_append(beginning, " ");
             g_string_append(beginning, args[1]);
 
-            result = autocomplete_param_with_ac(input, size, beginning->str, nick_ac, TRUE);
+            result = autocomplete_param_with_ac(input, beginning->str, nick_ac, TRUE);
             g_string_free(beginning, TRUE);
             if (result != NULL) {
                 g_strfreev(args);
@@ -2830,17 +2797,17 @@ _role_autocomplete(char *input, int *size)
         g_strfreev(args);
     }
 
-    result = autocomplete_param_with_ac(input, size, "/role set", role_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/role set", role_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/role list", role_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/role list", role_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/role", privilege_cmd_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/role", privilege_cmd_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2849,26 +2816,26 @@ _role_autocomplete(char *input, int *size)
 }
 
 static char *
-_statuses_autocomplete(char *input, int *size)
+_statuses_autocomplete(const char * const input)
 {
     char *result = NULL;
 
-    result = autocomplete_param_with_ac(input, size, "/statuses console", statuses_setting_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/statuses console", statuses_setting_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/statuses chat", statuses_setting_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/statuses chat", statuses_setting_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/statuses muc", statuses_setting_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/statuses muc", statuses_setting_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/statuses", statuses_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/statuses", statuses_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2877,16 +2844,16 @@ _statuses_autocomplete(char *input, int *size)
 }
 
 static char *
-_alias_autocomplete(char *input, int *size)
+_alias_autocomplete(const char * const input)
 {
     char *result = NULL;
 
-    result = autocomplete_param_with_ac(input, size, "/alias remove", aliases_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/alias remove", aliases_ac, TRUE);
     if (result != NULL) {
         return result;
     }
 
-    result = autocomplete_param_with_ac(input, size, "/alias", alias_ac, TRUE);
+    result = autocomplete_param_with_ac(input, "/alias", alias_ac, TRUE);
     if (result != NULL) {
         return result;
     }
@@ -2895,12 +2862,11 @@ _alias_autocomplete(char *input, int *size)
 }
 
 static char *
-_connect_autocomplete(char *input, int *size)
+_connect_autocomplete(const char * const input)
 {
     char *found = NULL;
     gboolean result = FALSE;
 
-    input[*size] = '\0';
     gchar **args = parse_args(input, 2, 4, &result);
 
     if ((strncmp(input, "/connect", 8) == 0) && (result == TRUE)) {
@@ -2912,7 +2878,7 @@ _connect_autocomplete(char *input, int *size)
             g_string_append(beginning, " ");
             g_string_append(beginning, args[2]);
         }
-        found = autocomplete_param_with_ac(input, size, beginning->str, connect_property_ac, TRUE);
+        found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE);
         g_string_free(beginning, TRUE);
         if (found != NULL) {
             g_strfreev(args);
@@ -2922,7 +2888,7 @@ _connect_autocomplete(char *input, int *size)
 
     g_strfreev(args);
 
-    found = autocomplete_param_with_func(input, size, "/connect", accounts_find_enabled);
+    found = autocomplete_param_with_func(input, "/connect", accounts_find_enabled);
     if (found != NULL) {
         return found;
     }
@@ -2931,14 +2897,12 @@ _connect_autocomplete(char *input, int *size)
 }
 
 static char *
-_join_autocomplete(char *input, int *size)
+_join_autocomplete(const char * const input)
 {
     char *found = NULL;
     gboolean result = FALSE;
 
-    input[*size] = '\0';
-
-    found = autocomplete_param_with_func(input, size, "/join", bookmark_find);
+    found = autocomplete_param_with_func(input, "/join", bookmark_find);
     if (found != NULL) {
         return found;
     }
@@ -2954,7 +2918,7 @@ _join_autocomplete(char *input, int *size)
             g_string_append(beginning, " ");
             g_string_append(beginning, args[2]);
         }
-        found = autocomplete_param_with_ac(input, size, beginning->str, join_property_ac, TRUE);
+        found = autocomplete_param_with_ac(input, beginning->str, join_property_ac, TRUE);
         g_string_free(beginning, TRUE);
         if (found != NULL) {
             g_strfreev(args);
@@ -2968,12 +2932,11 @@ _join_autocomplete(char *input, int *size)
 }
 
 static char *
-_account_autocomplete(char *input, int *size)
+_account_autocomplete(const char * const input)
 {
     char *found = NULL;
     gboolean result = FALSE;
 
-    input[*size] = '\0';
     gchar **args = parse_args(input, 3, 4, &result);
 
     if ((strncmp(input, "/account set", 12) == 0) && (result == TRUE)) {
@@ -2982,14 +2945,14 @@ _account_autocomplete(char *input, int *size)
         if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "otr")) == 0) {
             g_string_append(beginning, " ");
             g_string_append(beginning, args[2]);
-            found = autocomplete_param_with_ac(input, size, beginning->str, otr_policy_ac, TRUE);
+            found = autocomplete_param_with_ac(input, beginning->str, otr_policy_ac, TRUE);
             g_string_free(beginning, TRUE);
             if (found != NULL) {
                 g_strfreev(args);
                 return found;
             }
         } else {
-            found = autocomplete_param_with_ac(input, size, beginning->str, account_set_ac, TRUE);
+            found = autocomplete_param_with_ac(input, beginning->str, account_set_ac, TRUE);
             g_string_free(beginning, TRUE);
             if (found != NULL) {
                 g_strfreev(args);
@@ -3001,7 +2964,7 @@ _account_autocomplete(char *input, int *size)
     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, size, beginning->str, account_clear_ac, TRUE);
+        found = autocomplete_param_with_ac(input, beginning->str, account_clear_ac, TRUE);
         g_string_free(beginning, TRUE);
         if (found != NULL) {
             g_strfreev(args);
@@ -3011,7 +2974,7 @@ _account_autocomplete(char *input, int *size)
 
     g_strfreev(args);
 
-    found = autocomplete_param_with_ac(input, size, "/account default", account_default_ac, TRUE);
+    found = autocomplete_param_with_ac(input, "/account default", account_default_ac, TRUE);
     if(found){
         return found;
     }
@@ -3022,13 +2985,12 @@ _account_autocomplete(char *input, int *size)
         "/account default set" };
 
     for (i = 0; i < ARRAY_SIZE(account_choice); i++) {
-        found = autocomplete_param_with_func(input, size, account_choice[i],
-            accounts_find_all);
+        found = autocomplete_param_with_func(input, account_choice[i], accounts_find_all);
         if (found != NULL) {
             return found;
         }
     }
 
-    found = autocomplete_param_with_ac(input, size, "/account", account_ac, TRUE);
+    found = autocomplete_param_with_ac(input, "/account", account_ac, TRUE);
     return found;
 }
diff --git a/src/command/command.h b/src/command/command.h
index d8c1cd09..ffbccfa4 100644
--- a/src/command/command.h
+++ b/src/command/command.h
@@ -44,7 +44,7 @@ GHashTable *commands;
 void cmd_init(void);
 void cmd_uninit(void);
 
-void cmd_autocomplete(char *input, int *size);
+char* cmd_autocomplete(const char * const input);
 void cmd_reset_autocomplete(void);
 void cmd_autocomplete_add(char *value);
 void cmd_autocomplete_remove(char *value);
@@ -63,7 +63,7 @@ GSList * cmd_get_settings_help(void);
 GSList * cmd_get_presence_help(void);
 
 void cmd_history_append(char *inp);
-char *cmd_history_previous(char *inp, int *size);
-char *cmd_history_next(char *inp, int *size);
+char *cmd_history_previous(char *inp);
+char *cmd_history_next(char *inp);
 
 #endif
diff --git a/src/command/history.c b/src/command/history.c
deleted file mode 100644
index 92846246..00000000
--- a/src/command/history.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * history.c
- *
- * Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
- *
- * This file is part of Profanity.
- *
- * Profanity is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Profanity is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
- *
- * In addition, as a special exception, the copyright holders give permission to
- * link the code of portions of this program with the OpenSSL library under
- * certain conditions as described in each individual source file, and
- * distribute linked combinations including the two.
- *
- * You must obey the GNU General Public License in all respects for all of the
- * code used other than OpenSSL. If you modify file(s) with this exception, you
- * may extend this exception to your version of the file(s), but you are not
- * obligated to do so. If you do not wish to do so, delete this exception
- * statement from your version. If you delete this exception statement from all
- * source files in the program, then also delete it here.
- *
- */
-
-#include "tools/history.h"
-
-#define MAX_HISTORY 100
-
-static History history;
-
-void _stringify_input(char *inp, int size, char *string);
-
-void
-cmd_history_init(void)
-{
-    history = history_new(MAX_HISTORY);
-}
-
-void
-cmd_history_append(char *inp)
-{
-    history_append(history, inp);
-}
-
-char *
-cmd_history_previous(char *inp, int *size)
-{
-    char inp_str[*size + 1];
-    _stringify_input(inp, *size, inp_str);
-
-    return history_previous(history, inp_str);
-}
-
-char *
-cmd_history_next(char *inp, int *size)
-{
-    char inp_str[*size + 1];
-    _stringify_input(inp, *size, inp_str);
-
-    return history_next(history, inp_str);
-}
-
-void
-_stringify_input(char *inp, int size, char *string)
-{
-    int i;
-    for (i = 0; i < size; i++) {
-        string[i] = inp[i];
-    }
-    string[size] = '\0';
-}
diff --git a/src/command/history.h b/src/command/history.h
deleted file mode 100644
index f2d7c26b..00000000
--- a/src/command/history.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * history.h
- *
- * Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
- *
- * This file is part of Profanity.
- *
- * Profanity is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Profanity is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
- *
- * In addition, as a special exception, the copyright holders give permission to
- * link the code of portions of this program with the OpenSSL library under
- * certain conditions as described in each individual source file, and
- * distribute linked combinations including the two.
- *
- * You must obey the GNU General Public License in all respects for all of the
- * code used other than OpenSSL. If you modify file(s) with this exception, you
- * may extend this exception to your version of the file(s), but you are not
- * obligated to do so. If you do not wish to do so, delete this exception
- * statement from your version. If you delete this exception statement from all
- * source files in the program, then also delete it here.
- *
- */
-
-#ifndef COMMAND_HISTORY_H
-#define COMMAND_HISTORY_H
-
-void cmd_history_init(void);
-
-#endif
diff --git a/src/common.c b/src/common.c
index ffd12899..0f7693e9 100644
--- a/src/common.c
+++ b/src/common.c
@@ -191,7 +191,7 @@ str_replace(const char *string, const char *substr,
 }
 
 int
-str_contains(char str[], int size, char ch)
+str_contains(const char str[], int size, char ch)
 {
     int i;
     for (i = 0; i < size; i++) {
diff --git a/src/common.h b/src/common.h
index 55451dea..4e00e275 100644
--- a/src/common.h
+++ b/src/common.h
@@ -103,7 +103,7 @@ gboolean create_dir(char *name);
 gboolean mkdir_recursive(const char *dir);
 char * str_replace(const char *string, const char *substr,
     const char *replacement);
-int str_contains(char str[], int size, char ch);
+int str_contains(const char str[], int size, char ch);
 char * prof_getline(FILE *stream);
 char* release_get_latest(void);
 gboolean release_is_new(char *found_version);
diff --git a/src/config/accounts.c b/src/config/accounts.c
index d86fe3af..4d4d47d0 100644
--- a/src/config/accounts.c
+++ b/src/config/accounts.c
@@ -117,13 +117,13 @@ accounts_close(void)
 }
 
 char *
-accounts_find_enabled(char *prefix)
+accounts_find_enabled(const char * const prefix)
 {
     return autocomplete_complete(enabled_ac, prefix, TRUE);
 }
 
 char *
-accounts_find_all(char *prefix)
+accounts_find_all(const char * const prefix)
 {
     return autocomplete_complete(all_ac, prefix, TRUE);
 }
diff --git a/src/config/accounts.h b/src/config/accounts.h
index a1dda018..cbbe88e6 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(char *prefix);
-char * accounts_find_enabled(char *prefix);
+char * accounts_find_all(const char * const prefix);
+char * accounts_find_enabled(const char * const prefix);
 void accounts_reset_all_search(void);
 void accounts_reset_enabled_search(void);
 void accounts_add(const char *jid, const char *altdomain, const int port);
diff --git a/src/config/preferences.c b/src/config/preferences.c
index 5b683426..67f12b18 100644
--- a/src/config/preferences.c
+++ b/src/config/preferences.c
@@ -154,7 +154,7 @@ prefs_close(void)
 }
 
 char *
-prefs_autocomplete_boolean_choice(char *prefix)
+prefs_autocomplete_boolean_choice(const char * const prefix)
 {
     return autocomplete_complete(boolean_choice_ac, prefix, TRUE);
 }
diff --git a/src/config/preferences.h b/src/config/preferences.h
index 9590eb64..68286f09 100644
--- a/src/config/preferences.h
+++ b/src/config/preferences.h
@@ -114,7 +114,7 @@ void prefs_close(void);
 
 char * prefs_find_login(char *prefix);
 void prefs_reset_login_search(void);
-char * prefs_autocomplete_boolean_choice(char *prefix);
+char * prefs_autocomplete_boolean_choice(const char * const prefix);
 void prefs_reset_boolean_choice(void);
 
 gint prefs_get_gone(void);
diff --git a/src/muc.c b/src/muc.c
index 74e0d66e..f50f3879 100644
--- a/src/muc.c
+++ b/src/muc.c
@@ -141,7 +141,7 @@ muc_invites_reset_ac(void)
 }
 
 char *
-muc_invites_find(char *search_str)
+muc_invites_find(const char * const search_str)
 {
     return autocomplete_complete(invite_ac, search_str, TRUE);
 }
@@ -632,8 +632,8 @@ muc_roster_nick_change_complete(const char * const room,
     return NULL;
 }
 
-void
-muc_autocomplete(char *input, int *size)
+char *
+muc_autocomplete(const char * const input)
 {
     win_type_t wintype = ui_current_win_type();
     if (wintype == WIN_MUC) {
@@ -641,8 +641,7 @@ muc_autocomplete(char *input, int *size)
         ChatRoom *chat_room = g_hash_table_lookup(rooms, mucwin->roomjid);
 
         if (chat_room && chat_room->nick_ac) {
-            input[*size] = '\0';
-            char *search_str = NULL;
+            const char * search_str = NULL;
 
             gchar *last_space = g_strrstr(input, " ");
             if (!last_space) {
@@ -664,12 +663,15 @@ muc_autocomplete(char *input, int *size)
                 if (!last_space || (*(last_space+1) == '\0')) {
                     g_string_append(replace_with, ": ");
                 }
-                ui_replace_input(input, replace_with->str, size);
-                g_string_free(replace_with, TRUE);
                 g_free(result);
+                result = replace_with->str;
+                g_string_free(replace_with, FALSE);
+                return result;
             }
         }
     }
+
+    return NULL;
 }
 
 void
diff --git a/src/muc.h b/src/muc.h
index 3f4ea876..01f8b44b 100644
--- a/src/muc.h
+++ b/src/muc.h
@@ -114,7 +114,7 @@ gint muc_invites_count(void);
 GSList* muc_invites(void);
 gboolean muc_invites_contain(const char * const room);
 void muc_invites_reset_ac(void);
-char* muc_invites_find(char *search_str);
+char* muc_invites_find(const char * const search_str);
 void muc_invites_clear(void);
 
 void muc_set_subject(const char * const room, const char * const subject);
@@ -123,7 +123,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);
 
-void muc_autocomplete(char *input, int *size);
+char* muc_autocomplete(const char * const input);
 void muc_autocomplete_reset(const char * const room);
 
 gboolean muc_requires_config(const char * const room);
diff --git a/src/roster_list.c b/src/roster_list.c
index 2d01d205..44d05ff0 100644
--- a/src/roster_list.c
+++ b/src/roster_list.c
@@ -344,13 +344,13 @@ roster_has_pending_subscriptions(void)
 }
 
 char *
-roster_contact_autocomplete(char *search_str)
+roster_contact_autocomplete(const char * const search_str)
 {
     return autocomplete_complete(name_ac, search_str, TRUE);
 }
 
 char *
-roster_fulljid_autocomplete(char *search_str)
+roster_fulljid_autocomplete(const char * const search_str)
 {
     return autocomplete_complete(fulljid_ac, search_str, TRUE);
 }
@@ -406,13 +406,13 @@ roster_get_groups(void)
 }
 
 char *
-roster_group_autocomplete(char *search_str)
+roster_group_autocomplete(const char * const search_str)
 {
     return autocomplete_complete(groups_ac, search_str, TRUE);
 }
 
 char *
-roster_barejid_autocomplete(char *search_str)
+roster_barejid_autocomplete(const char * const search_str)
 {
     return autocomplete_complete(barejid_ac, search_str, TRUE);
 }
diff --git a/src/roster_list.h b/src/roster_list.h
index 7743ece6..e193085b 100644
--- a/src/roster_list.h
+++ b/src/roster_list.h
@@ -59,12 +59,12 @@ char * roster_barejid_from_name(const char * const name);
 GSList * roster_get_contacts(void);
 GSList * roster_get_contacts_online(void);
 gboolean roster_has_pending_subscriptions(void);
-char * roster_contact_autocomplete(char *search_str);
-char * roster_fulljid_autocomplete(char *search_str);
+char * roster_contact_autocomplete(const char * const search_str);
+char * roster_fulljid_autocomplete(const char * const search_str);
 GSList * roster_get_group(const char * const group);
 GSList * roster_get_groups(void);
-char * roster_group_autocomplete(char *search_str);
-char * roster_barejid_autocomplete(char *search_str);
+char * roster_group_autocomplete(const char * const search_str);
+char * roster_barejid_autocomplete(const char * const search_str);
 GSList * roster_get_contacts_by_presence(const char * const presence);
 GSList * roster_get_nogroup(void);
 
diff --git a/src/tools/autocomplete.c b/src/tools/autocomplete.c
index 486fd2ba..2623c828 100644
--- a/src/tools/autocomplete.c
+++ b/src/tools/autocomplete.c
@@ -169,7 +169,7 @@ autocomplete_contains(Autocomplete ac, const char *value)
 }
 
 gchar *
-autocomplete_complete(Autocomplete ac, gchar *search_str, gboolean quote)
+autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote)
 {
     gchar *found = NULL;
 
@@ -216,8 +216,7 @@ autocomplete_complete(Autocomplete ac, gchar *search_str, gboolean quote)
 }
 
 char *
-autocomplete_param_with_func(char *input, int *size, char *command,
-    autocomplete_func func)
+autocomplete_param_with_func(const char * const input, char *command, autocomplete_func func)
 {
     GString *auto_msg = NULL;
     char *result = NULL;
@@ -225,15 +224,16 @@ autocomplete_param_with_func(char *input, int *size, char *command,
     sprintf(command_cpy, "%s ", command);
     int len = strlen(command_cpy);
 
-    if ((strncmp(input, command_cpy, len) == 0) && (*size > len)) {
+    if ((strncmp(input, command_cpy, len) == 0) && (strlen(input) > len)) {
         int i;
-        char inp_cpy[*size];
-        for(i = len; i < *size; i++) {
-            inp_cpy[i-len] = input[i];
+        int inp_len = strlen(input);
+        char prefix[inp_len];
+        for(i = len; i < inp_len; i++) {
+            prefix[i-len] = input[i];
         }
-        inp_cpy[(*size) - len] = '\0';
+        prefix[inp_len - len] = '\0';
 
-        char *found = func(inp_cpy);
+        char *found = func(prefix);
         if (found) {
             auto_msg = g_string_new(command_cpy);
             g_string_append(auto_msg, found);
@@ -247,23 +247,23 @@ autocomplete_param_with_func(char *input, int *size, char *command,
 }
 
 char *
-autocomplete_param_with_ac(char *input, int *size, char *command,
-    Autocomplete ac, gboolean quote)
+autocomplete_param_with_ac(const char * const input, char *command, Autocomplete ac, gboolean quote)
 {
     GString *auto_msg = NULL;
     char *result = NULL;
     char *command_cpy = malloc(strlen(command) + 2);
     sprintf(command_cpy, "%s ", command);
     int len = strlen(command_cpy);
-    if ((strncmp(input, command_cpy, len) == 0) && (*size > len)) {
+    int inp_len = strlen(input);
+    if ((strncmp(input, command_cpy, len) == 0) && (strlen(input) > len)) {
         int i;
-        char inp_cpy[*size];
-        for(i = len; i < *size; i++) {
-            inp_cpy[i-len] = input[i];
+        char prefix[inp_len];
+        for(i = len; i < inp_len; i++) {
+            prefix[i-len] = input[i];
         }
-        inp_cpy[(*size) - len] = '\0';
+        prefix[inp_len - len] = '\0';
 
-        char *found = autocomplete_complete(ac, inp_cpy, quote);
+        char *found = autocomplete_complete(ac, prefix, quote);
         if (found) {
             auto_msg = g_string_new(command_cpy);
             g_string_append(auto_msg, found);
@@ -278,28 +278,18 @@ autocomplete_param_with_ac(char *input, int *size, char *command,
 }
 
 char *
-autocomplete_param_no_with_func(char *input, int *size, 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)
 {
-    if (strncmp(input, command, strlen(command)) == 0 && (*size > strlen(command))) {
-        int i = 0;
+    if (strncmp(input, command, strlen(command)) == 0 && (strlen(input) > strlen(command))) {
         GString *result_str = NULL;
 
-        // copy and null terminate input
-        gchar inp_cpy[*size];
-        for (i = 0; i < *size; i++) {
-            inp_cpy[i] = input[i];
-        }
-        inp_cpy[i] = '\0';
-        g_strstrip(inp_cpy);
-
         // count tokens properly
-        int num_tokens = count_tokens(inp_cpy);
+        int num_tokens = count_tokens(input);
 
         // if correct number of tokens, then candidate for autocompletion of last param
         if (num_tokens == arg_number) {
-            gchar *start_str = get_start(inp_cpy, arg_number);
-            gchar *comp_str = g_strdup(&inp_cpy[strlen(start_str)]);
+            gchar *start_str = get_start(input, arg_number);
+            gchar *comp_str = g_strdup(&input[strlen(start_str)]);
 
             // autocomplete param
             if (comp_str) {
diff --git a/src/tools/autocomplete.h b/src/tools/autocomplete.h
index a029b7ef..70cd8f30 100644
--- a/src/tools/autocomplete.h
+++ b/src/tools/autocomplete.h
@@ -37,7 +37,7 @@
 
 #include <glib.h>
 
-typedef char*(*autocomplete_func)(char *);
+typedef char*(*autocomplete_func)(const char * const);
 typedef struct autocomplete_t *Autocomplete;
 
 // allocate new autocompleter with no items
@@ -53,18 +53,18 @@ void autocomplete_add(Autocomplete ac, const char *item);
 void autocomplete_remove(Autocomplete ac, const char * const item);
 
 // find the next item prefixed with search string
-gchar * autocomplete_complete(Autocomplete ac, gchar *search_str, gboolean quote);
+gchar * autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote);
 
 GSList * autocomplete_create_list(Autocomplete ac);
 gint autocomplete_length(Autocomplete ac);
 
-char * autocomplete_param_with_func(char *input, int *size, char *command,
+char * autocomplete_param_with_func(const char * const input, char *command,
     autocomplete_func func);
 
-char * autocomplete_param_with_ac(char *input, int *size, char *command,
+char * autocomplete_param_with_ac(const char * const input, char *command,
     Autocomplete ac, gboolean quote);
 
-char * autocomplete_param_no_with_func(char *input, int *size, char *command,
+char * autocomplete_param_no_with_func(const char * const input, char *command,
     int arg_number, autocomplete_func func);
 
 void autocomplete_reset(Autocomplete ac);
diff --git a/src/tools/parser.c b/src/tools/parser.c
index ae149155..e91b227d 100644
--- a/src/tools/parser.c
+++ b/src/tools/parser.c
@@ -316,7 +316,7 @@ parse_args_with_freetext(const char * const inp, int min, int max, gboolean *res
 }
 
 int
-count_tokens(char *string)
+count_tokens(const char * const string)
 {
     int length = g_utf8_strlen(string, -1);
     gboolean in_quotes = FALSE;
@@ -347,7 +347,7 @@ count_tokens(char *string)
 }
 
 char *
-get_start(char *string, int tokens)
+get_start(const char * const string, int tokens)
 {
     GString *result = g_string_new("");
     int length = g_utf8_strlen(string, -1);
diff --git a/src/tools/parser.h b/src/tools/parser.h
index 7ecef3fc..eeb97df3 100644
--- a/src/tools/parser.h
+++ b/src/tools/parser.h
@@ -39,8 +39,8 @@
 
 gchar** parse_args(const char * const inp, int min, int max, gboolean *result);
 gchar** parse_args_with_freetext(const char * const inp, int min, int max, gboolean *result);
-int count_tokens(char *string);
-char* get_start(char *string, int tokens);
+int count_tokens(const char * const string);
+char* get_start(const char * const string, int tokens);
 GHashTable* parse_options(gchar **args, gchar **keys, gboolean *res);
 void options_destroy(GHashTable *options);
 
diff --git a/src/ui/core.c b/src/ui/core.c
index 3e4d2c80..14ea2c17 100644
--- a/src/ui/core.c
+++ b/src/ui/core.c
@@ -204,15 +204,15 @@ ui_readline(void)
 }
 
 void
-ui_input_clear(void)
+ui_inp_history_append(char *inp)
 {
-    inp_win_reset();
+    inp_history_append(inp);
 }
 
 void
-ui_replace_input(char *input, const char * const new_input, int *size)
+ui_input_clear(void)
 {
-    inp_replace_input(input, new_input, size);
+    inp_win_reset();
 }
 
 void
diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c
index 956dc156..af5eeed9 100644
--- a/src/ui/inputwin.c
+++ b/src/ui/inputwin.c
@@ -50,6 +50,7 @@
 #include "config/accounts.h"
 #include "config/preferences.h"
 #include "config/theme.h"
+#include "tools/history.h"
 #include "log.h"
 #include "muc.h"
 #include "profanity.h"
@@ -72,6 +73,7 @@
 #define KEY_CTRL_U 0025
 #define KEY_CTRL_W 0027
 
+#define MAX_HISTORY 100
 #define INP_WIN_MAX 1000
 
 static WINDOW *inp_win;
@@ -79,6 +81,7 @@ static int pad_start = 0;
 static int rows, cols;
 static char line[INP_WIN_MAX];
 static int inp_size;
+static History history;
 
 static int _handle_edit(int key_type, const wint_t ch);
 static int _handle_alt_key(int key);
@@ -103,6 +106,7 @@ create_input_window(void)
     keypad(inp_win, TRUE);
     wmove(inp_win, 0, 0);
     _inp_win_update_virtual();
+    history = history_new(MAX_HISTORY);
 }
 
 void
@@ -227,7 +231,7 @@ inp_read(int *key_type, wint_t *ch)
     echo();
 
     if (*ch == '\n') {
-        line[inp_size++] = '\0';
+        line[inp_size] = '\0';
         inp_size = 0;
         return strdup(line);
     } else {
@@ -273,13 +277,13 @@ _get_display_length(void)
 }
 
 void
-inp_replace_input(char *input, const char * const new_input, int *size)
+inp_replace_input(const char * const new_input)
 {
-    strncpy(input, new_input, INP_WIN_MAX);
-    *size = strlen(input);
+    strncpy(line, new_input, INP_WIN_MAX);
+    inp_size = strlen(line);
     inp_win_reset();
-    input[*size] = '\0';
-    waddstr(inp_win, input);
+    line[inp_size] = '\0';
+    waddstr(inp_win, line);
     _go_to_end();
 }
 
@@ -291,6 +295,12 @@ inp_win_reset(void)
     _inp_win_update_virtual();
 }
 
+void
+inp_history_append(char *inp)
+{
+    history_append(history, inp);
+}
+
 static void
 _clear_input(void)
 {
@@ -514,9 +524,10 @@ _handle_edit(int key_type, const wint_t ch)
                 return 0;
             }
         case KEY_CTRL_P:
-            prev = cmd_history_previous(line, &inp_size);
+            line[inp_size] = '\0';
+            prev = history_previous(history, line);
             if (prev) {
-                inp_replace_input(line, prev, &inp_size);
+                inp_replace_input(prev);
             }
             return 1;
 
@@ -525,13 +536,14 @@ _handle_edit(int key_type, const wint_t ch)
                 return 0;
             }
         case KEY_CTRL_N:
-            next = cmd_history_next(line, &inp_size);
+            line[inp_size] = '\0';
+            next = history_next(history, line);
             if (next) {
-                inp_replace_input(line, next, &inp_size);
+                inp_replace_input(next);
             } else if (inp_size != 0) {
                 line[inp_size] = '\0';
-                cmd_history_append(line);
-                inp_replace_input(line, "", &inp_size);
+                history_append(history, line);
+                inp_replace_input("");
             }
             return 1;
 
@@ -555,10 +567,21 @@ _handle_edit(int key_type, const wint_t ch)
 
         case 9: // tab
             if (inp_size != 0) {
+                line[inp_size] = '\0';
                 if ((strncmp(line, "/", 1) != 0) && (ui_current_win_type() == WIN_MUC)) {
-                    muc_autocomplete(line, &inp_size);
+                    char *result = muc_autocomplete(line);
+                    if (result) {
+                        cons_debug("ac result = %s", result);
+                        inp_replace_input(result);
+                        free(result);
+                    }
                 } else if (strncmp(line, "/", 1) == 0) {
-                    cmd_autocomplete(line, &inp_size);
+                    char *result = cmd_autocomplete(line);
+                    if (result) {
+                        cons_debug("ac result = %s", result);
+                        inp_replace_input(result);
+                        free(result);
+                    }
                 }
             }
             return 1;
@@ -777,4 +800,4 @@ _printable(const wint_t ch)
     bytes[utf_len] = '\0';
     gunichar unichar = g_utf8_get_char(bytes);
     return g_unichar_isprint(unichar) && (ch != KEY_MOUSE);
-}
\ No newline at end of file
+}
diff --git a/src/ui/inputwin.h b/src/ui/inputwin.h
index f121c9d9..39fde720 100644
--- a/src/ui/inputwin.h
+++ b/src/ui/inputwin.h
@@ -43,6 +43,7 @@ void inp_put_back(void);
 void inp_non_block(gint);
 void inp_block(void);
 void inp_get_password(char *passwd);
-void inp_replace_input(char *input, const char * const new_input, int *size);
+void inp_replace_input(const char * const new_input);
+void inp_history_append(char *inp);
 
 #endif
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 90dd4d28..99e73b4a 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -230,7 +230,6 @@ void ui_statusbar_new(const int win);
 char * ui_readline(void);
 void ui_input_clear(void);
 void ui_input_nonblocking(gboolean);
-void ui_replace_input(char *input, const char * const new_input, int *size);
 
 void ui_invalid_command_usage(const char * const usage, void (*setting_func)(void));
 
@@ -240,6 +239,8 @@ void ui_open_xmlconsole_win(void);
 
 gboolean ui_win_has_unsaved_form(int num);
 
+void ui_inp_history_append(char *inp);
+
 // console window actions
 void cons_show(const char * const msg, ...);
 void cons_about(void);
diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c
index ddc6e300..94adabea 100644
--- a/src/xmpp/bookmark.c
+++ b/src/xmpp/bookmark.c
@@ -220,7 +220,7 @@ bookmark_get_list(void)
 }
 
 char *
-bookmark_find(char *search_str)
+bookmark_find(const char * const search_str)
 {
     return autocomplete_complete(bookmark_ac, search_str, TRUE);
 }
diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c
index 1b3e7fc7..65384a0d 100644
--- a/src/xmpp/presence.c
+++ b/src/xmpp/presence.c
@@ -158,7 +158,7 @@ presence_clear_sub_requests(void)
 }
 
 char *
-presence_sub_request_find(char * search_str)
+presence_sub_request_find(const char * const search_str)
 {
     return autocomplete_complete(sub_requests_ac, search_str, TRUE);
 }
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index 161eebdf..a004a4bf 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -163,7 +163,7 @@ void presence_subscription(const char * const jid, const jabber_subscr_t action)
 GSList* presence_get_subscription_requests(void);
 gint presence_sub_request_count(void);
 void presence_reset_sub_request_search(void);
-char * presence_sub_request_find(char * search_str);
+char * presence_sub_request_find(const char * const search_str);
 void presence_join_room(char *room, char *nick, char * passwd);
 void presence_change_room_nick(const char * const room, const char * const nick);
 void presence_leave_chat_room(const char * const room_jid);
@@ -208,7 +208,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);
 const GList * bookmark_get_list(void);
-char * bookmark_find(char *search_str);
+char * bookmark_find(const char * const search_str);
 void bookmark_autocomplete_reset(void);
 
 void roster_send_name_change(const char * const barejid, const char * const new_name, GSList *groups);
diff --git a/tests/ui/stub_ui.c b/tests/ui/stub_ui.c
index 2c7cebf6..51b82d42 100644
--- a/tests/ui/stub_ui.c
+++ b/tests/ui/stub_ui.c
@@ -328,9 +328,10 @@ char * ui_readline(void)
     return NULL;
 }
 
+void ui_inp_history_append(char *inp) {}
+
 void ui_input_clear(void) {}
 void ui_input_nonblocking(gboolean reset) {}
-void ui_replace_input(char *input, const char * const new_input, int *size) {}
 
 void ui_invalid_command_usage(const char * const usage, void (*setting_func)(void)) {}
 
diff --git a/tests/xmpp/stub_xmpp.c b/tests/xmpp/stub_xmpp.c
index cc5ad5fc..281857f0 100644
--- a/tests/xmpp/stub_xmpp.c
+++ b/tests/xmpp/stub_xmpp.c
@@ -91,7 +91,7 @@ gint presence_sub_request_count(void)
 
 void presence_reset_sub_request_search(void) {}
 
-char * presence_sub_request_find(char * search_str)
+char * presence_sub_request_find(const char * const search_str)
 {
     return  NULL;
 }
@@ -189,7 +189,7 @@ const GList * bookmark_get_list(void)
     return (GList *)mock();
 }
 
-char * bookmark_find(char *search_str)
+char * bookmark_find(const char * const search_str)
 {
     return NULL;
 }