diff --git a/ChangeLog b/ChangeLog
index 8137dd21ea170b630eef4fef504f0d0ded98099f..7a9d139e2f4e3efd1852324e17d554be40b8f047 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -45,19 +45,38 @@ CVS code -
 	  do_mouse() and moved to nano.c), do_verbatim_input(),
 	  do_tab(), main(), and get_ascii_kbinput() (renamed to
 	  get_word_kbinput()).  The wide version of ncurses is required
-	  in order for output to work properly. (DLR; buffered
-	  input/output based on ideas from mutt 1.4.2.1; double-Escape
-	  input of Unicode characters suggested by Michael Piefel)
+	  in order for wide/multibyte input and output to work properly.
+	  (DLR; buffered input/output based on ideas from mutt 1.4.2.1;
+	  double-Escape input of Unicode characters suggested by Michael
+	  Piefel)
 	- More steps toward wide character/multibyte character support.
 	  Movement and cursor display in the edit window should now work
 	  properly with files containing multibyte characters, and text
-	  display of such files should work properly some of the time.
-	  New functions control_rep(), parse_char(), move_left(),
+	  display of such files should now work properly as well.  New
+	  functions control_rep(), parse_char(), move_left(),
 	  move_right(), and display_string_len(); changes to do_left(),
 	  do_right(), do_delete(), breakable(), break_line(),
 	  do_output(), get_buffer(), unget_input(), actual_x(),
 	  strnlenpt(), display_string(), titlebar(), statusbar(),
 	  onekey(), and do_credits(). (David Benbennick and DLR)
+	- Overhaul the high-level input routines for the statusbar to
+	  make them read the shortcut lists for functions instead of
+	  manually running them, to make nanogetstr() less complex, and
+	  to increase flexibility.  Note that currshortcut is now used
+	  regardless of #ifdefs.  Changes to shortcut_init() and
+	  nanogetstr(); new functions do_statusbar_input(),
+	  do_statusbar_mouse(), do_statusbar_home(), do_statusbar_end(),
+	  do_statusbar_right(), do_statusbar_left(),
+	  do_statusbar_backspace(), do_statusbar_delete(),
+	  do_statusbar_cut_text(), and do_statusbar_output(). (DLR)
+	- Even more steps toward wide character/multibyte character
+	  support.  Movement and (most) cursor display at the statusbar
+	  prompt should now work properly with a string containing
+	  multibyte characters, and text display of such strings should
+	  now (mostly) work properly as well.  Changes to
+	  do_statusbar_right(), do_statusbar_left(),
+	  do_statusbar_backspace(), and do_statusbar_delete(). (David
+	  Benbennick and DLR)
 - cut.c:
   do_cut_text()
 	- If keep_cutbuffer is FALSE, only blow away the text in the
@@ -100,6 +119,9 @@ CVS code -
 	  loop if there are no more paragraphs after the current one and
 	  the paragraph search left us on the magicline, so as to avoid
 	  a segfault. (DLR)
+  do_input()
+	- Add finished parameter, used to indicate when we run or try to
+	  run a function associated with a shortcut. (DLR)
   main()
 	- Try to automatically detect whether UTF-8 support is needed by
 	  setting the NO_UTF8 flag if setlocale() returns a string that
diff --git a/src/files.c b/src/files.c
index 7e6228d6702e3cac856ea829575798b6fc5f213e..7598640bae981e7d6c2eda9dfb1c82d478f685c6 100644
--- a/src/files.c
+++ b/src/files.c
@@ -2,7 +2,7 @@
 /**************************************************************************
  *   files.c                                                              *
  *                                                                        *
- *   Copyright (C) 1999-2004 Chris Allegretta                             *
+ *   Copyright (C) 1999-2005 Chris Allegretta                             *
  *   This program is free software; you can redistribute it and/or modify *
  *   it under the terms of the GNU General Public License as published by *
  *   the Free Software Foundation; either version 2, or (at your option)  *
@@ -1738,9 +1738,7 @@ int do_writeout(bool exiting)
     static bool did_cred = FALSE;
 #endif
 
-#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE)
     currshortcut = writefile_list;
-#endif
 
     if (exiting && filename[0] != '\0' && ISSET(TEMP_FILE)) {
 	retval = write_file(filename, FALSE, 0, FALSE);
@@ -2541,9 +2539,7 @@ char *do_browser(const char *inpath)
 
 	check_statusblank();
 
-#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
 	currshortcut = browser_list;
-#endif
 
  	editline = 0;
 	col = 0;
diff --git a/src/global.c b/src/global.c
index 4c4d2ec2ecf25f6fd4d261a5f06ed9b5f32f78fa..0db515ee7d7ab254a15cf2bae2779e4ada4e6b1f 100644
--- a/src/global.c
+++ b/src/global.c
@@ -2,7 +2,7 @@
 /**************************************************************************
  *   global.c                                                             *
  *                                                                        *
- *   Copyright (C) 1999-2004 Chris Allegretta                             *
+ *   Copyright (C) 1999-2005 Chris Allegretta                             *
  *   This program is free software; you can redistribute it and/or modify *
  *   it under the terms of the GNU General Public License as published by *
  *   the Free Software Foundation; either version 2, or (at your option)  *
@@ -159,9 +159,7 @@ syntaxtype *syntaxes = NULL;
 char *syntaxstr = NULL;
 #endif
 
-#if !defined(DISABLE_BROWSER) || !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
 const shortcut *currshortcut;	/* Current shortcut list we're using */
-#endif
 
 #ifndef NANO_SMALL
 toggle *toggles = NULL;
@@ -614,12 +612,12 @@ void shortcut_init(bool unjustify)
     /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, NANO_TOOTHERSEARCH_KEY, replace_msg,
 	IFHELP(nano_replace_msg, NANO_NO_KEY), NANO_REPLACE_FKEY,
-	NANO_NO_KEY, VIEW, do_replace);
+	NANO_NO_KEY, VIEW, 0);
 
     /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, NANO_TOGOTOLINE_KEY, go_to_line_msg,
 	IFHELP(nano_gotoline_msg, NANO_NO_KEY), NANO_GOTOLINE_FKEY,
-	NANO_NO_KEY, VIEW, do_gotoline_void);
+	NANO_NO_KEY, VIEW, 0);
 
 #ifndef DISABLE_JUSTIFY
     /* Translators: try to keep this string under 10 characters long */
@@ -691,11 +689,11 @@ void shortcut_init(bool unjustify)
     /* Translators: try to keep this string under 12 characters long */
     sc_init_one(&replace_list, NANO_TOOTHERSEARCH_KEY, N_("No Replace"),
 	IFHELP(nano_whereis_msg, NANO_NO_KEY), NANO_REPLACE_FKEY,
-	NANO_NO_KEY, VIEW, do_search);
+	NANO_NO_KEY, VIEW, 0);
 
     sc_init_one(&replace_list, NANO_TOGOTOLINE_KEY, go_to_line_msg,
 	IFHELP(nano_gotoline_msg, NANO_NO_KEY), NANO_GOTOLINE_FKEY,
-	NANO_NO_KEY, VIEW, do_gotoline_void);
+	NANO_NO_KEY, VIEW, 0);
 
 #ifndef NANO_SMALL
     sc_init_one(&replace_list, NANO_NO_KEY, case_sens_msg,
@@ -773,7 +771,7 @@ void shortcut_init(bool unjustify)
 
     sc_init_one(&gotoline_list, NANO_TOOTHERWHEREIS_KEY,
 	N_("Go To Text"), IFHELP(nano_whereis_msg, NANO_NO_KEY),
-	NANO_NO_KEY, NANO_NO_KEY, VIEW, do_search);
+	NANO_NO_KEY, NANO_NO_KEY, VIEW, 0);
 
 #ifndef DISABLE_HELP
     free_shortcutage(&help_list);
diff --git a/src/nano.c b/src/nano.c
index 755fbefd09f38231b6fcf33598307821827c70dd..559ac14bfc9e09527460454707450824be463279 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -2,7 +2,7 @@
 /**************************************************************************
  *   nano.c                                                               *
  *                                                                        *
- *   Copyright (C) 1999-2004 Chris Allegretta                             *
+ *   Copyright (C) 1999-2005 Chris Allegretta                             *
  *   This program is free software; you can redistribute it and/or modify *
  *   it under the terms of the GNU General Public License as published by *
  *   the Free Software Foundation; either version 2, or (at your option)  *
@@ -2718,7 +2718,7 @@ void do_justify(bool full_justify)
     size_t mark_beginx_save = mark_beginx;
 #endif
     int kbinput;
-    bool meta_key, func_key, s_or_t;
+    bool meta_key, func_key, s_or_t, finished;
 
     /* If we're justifying the entire file, start at the beginning. */
     if (full_justify)
@@ -2984,7 +2984,7 @@ void do_justify(bool full_justify)
 
     /* Now get a keystroke and see if it's unjustify.  If not, put back
      * the keystroke and return. */
-    kbinput = do_input(&meta_key, &func_key, &s_or_t, FALSE);
+    kbinput = do_input(&meta_key, &func_key, &s_or_t, &finished, FALSE);
 
     if (!meta_key && !func_key && s_or_t &&
 	kbinput == NANO_UNJUSTIFY_KEY) {
@@ -3386,7 +3386,7 @@ void terminal_init(void)
 }
 
 int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
-	allow_funcs)
+	*finished, bool allow_funcs)
 {
     int input;
 	/* The character we read in. */
@@ -3402,6 +3402,7 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
 #endif
 
     *s_or_t = FALSE;
+    *finished = FALSE;
 
     /* Read in a character. */
     input = get_kbinput(edit, meta_key, func_key);
@@ -3477,7 +3478,8 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
 
 	if (have_shortcut) {
 	    switch (input) {
-		/* Handle the "universal" edit window shortcuts. */
+		/* Handle the "universal" statusbar prompt shortcuts,
+		 * setting ran_s_or_t to TRUE to indicate it. */
 		case NANO_XON_KEY:
 		    statusbar(_("XON ignored, mumble mumble."));
 		    break;
@@ -3490,21 +3492,23 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
 			do_suspend(0);
 		    break;
 #endif
-		/* Handle the normal edit window shortcuts. */
+		/* Handle the normal edit window shortcuts, setting
+		 * finished to TRUE to indicate that we're done after
+		 * running or trying to run their associated
+		 * functions. */
 		default:
 		    /* Blow away the text in the cutbuffer if we aren't
 		     * cutting text. */
 		    if (s->func != do_cut_text)
 			cutbuffer_reset();
 
-		    /* Run the function associated with this shortcut,
-		     * if there is one. */
 		    if (s->func != NULL) {
 			if (ISSET(VIEW_MODE) && !s->viewok)
 			    print_view_warning();
 			else
 			    s->func();
 		    }
+		    *finished = TRUE;
 		    break;
 	    }
 	}
@@ -3577,9 +3581,6 @@ bool do_mouse(void)
 	    edit_refresh();
 	}
     }
-    /* FIXME: If we clicked on a location in the statusbar, the cursor
-     * should move to the location we clicked on.  This functionality
-     * should be in do_statusbar_mouse() when it's written. */
 
     return retval;
 }
@@ -4225,6 +4226,9 @@ int main(int argc, char **argv)
 		/* Whether we got a function key. */
 	bool s_or_t;
 		/* Whether we got a shortcut or toggle. */
+	bool ran_s_or_t;
+		/* Whether we ran a function associated with a
+		 * shortcut. */
 
 	/* Make sure the cursor is in the edit window. */
 	reset_cursor();
@@ -4234,12 +4238,10 @@ int main(int argc, char **argv)
 	if (ISSET(CONSTUPDATE))
 	    do_cursorpos(TRUE);
 
-#if !defined(DISABLE_BROWSER) || !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
 	currshortcut = main_list;
-#endif
 
 	/* Read in and interpret characters. */
-	do_input(&meta_key, &func_key, &s_or_t, TRUE);
+	do_input(&meta_key, &func_key, &s_or_t, &ran_s_or_t, TRUE);
     }
     assert(FALSE);
 }
diff --git a/src/proto.h b/src/proto.h
index cb2d0f14120dd222799965d9c575cd563a07b9ae..2441932400f97d480ac62ab002d7a7a1dc1bf91d 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -2,7 +2,7 @@
 /**************************************************************************
  *   proto.h                                                              *
  *                                                                        *
- *   Copyright (C) 1999-2004 Chris Allegretta                             *
+ *   Copyright (C) 1999-2005 Chris Allegretta                             *
  *   This program is free software; you can redistribute it and/or modify *
  *   it under the terms of the GNU General Public License as published by *
  *   the Free Software Foundation; either version 2, or (at your option)  *
@@ -122,9 +122,7 @@ extern shortcut *spell_list;
 extern shortcut *browser_list, *gotodir_list;
 #endif
 
-#if !defined(DISABLE_BROWSER) || !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
 extern const shortcut *currshortcut;
-#endif
 
 #ifdef HAVE_REGEX_H
 extern regex_t search_regexp;
@@ -391,7 +389,7 @@ void disable_flow_control(void);
 void enable_flow_control(void);
 void terminal_init(void);
 int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
-	allow_funcs);
+	*finished, bool allow_funcs);
 #ifndef DISABLE_MOUSE
 bool do_mouse(void);
 #endif
@@ -569,6 +567,19 @@ const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
 #ifndef NANO_SMALL
 const toggle *get_toggle(int kbinput, bool meta_key);
 #endif
+int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
+	bool *finished, bool allow_funcs);
+#ifndef DISABLE_MOUSE
+bool do_statusbar_mouse(void);
+#endif
+void do_statusbar_home(void);
+void do_statusbar_end(void);
+void do_statusbar_right(void);
+void do_statusbar_left(void);
+void do_statusbar_backspace(void);
+void do_statusbar_delete(void);
+void do_statusbar_cut_text(void);
+void do_statusbar_output(int *kbinput, size_t kbinput_len);
 size_t xplustabs(void);
 size_t actual_x(const char *str, size_t xplus);
 size_t strnlenpt(const char *buf, size_t size);
diff --git a/src/winio.c b/src/winio.c
index d116b89960a6727a93a9487cdcb046c8bd3c3077..4cc6c77e0a997f4412eea9b008149771382550a9 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -2,7 +2,7 @@
 /**************************************************************************
  *   winio.c                                                              *
  *                                                                        *
- *   Copyright (C) 1999-2004 Chris Allegretta                             *
+ *   Copyright (C) 1999-2005 Chris Allegretta                             *
  *   This program is free software; you can redistribute it and/or modify *
  *   it under the terms of the GNU General Public License as published by *
  *   the Free Software Foundation; either version 2, or (at your option)  *
@@ -46,6 +46,10 @@ static size_t key_buffer_len = 0;
 static int statusblank = 0;	/* The number of keystrokes left after
 				 * we call statusbar(), before we
 				 * actually blank the statusbar. */
+static size_t statusbar_x = (size_t)-1;
+				/* The cursor position in answer. */
+static size_t statusbar_xend = 0;
+				/* The length of answer. */
 static bool resetstatuspos = FALSE;
 				/* Should we reset the cursor position
 				 * at the statusbar prompt? */
@@ -1609,6 +1613,271 @@ const toggle *get_toggle(int kbinput, bool meta_key)
 }
 #endif /* !NANO_SMALL */
 
+int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
+	bool *finished, bool allow_funcs)
+{
+    int input;
+	/* The character we read in. */
+    static int *kbinput = NULL;
+	/* The input buffer. */
+    static size_t kbinput_len = 0;
+	/* The length of the input buffer. */
+    const shortcut *s;
+    bool have_shortcut;
+
+    *s_or_t = FALSE;
+    *finished = FALSE;
+
+    /* Read in a character. */
+    input = get_kbinput(bottomwin, meta_key, func_key);
+
+#ifndef DISABLE_MOUSE
+    /* If we got a mouse click and it was on a shortcut, read in the
+     * shortcut character. */
+    if (allow_funcs && func_key && input == KEY_MOUSE) {
+	if (do_mouse())
+	    input = get_kbinput(bottomwin, meta_key, func_key);
+	else
+	    input = ERR;
+    }
+#endif
+
+    /* Check for a shortcut in the current list. */
+    s = get_shortcut(currshortcut, &input, meta_key, func_key);
+
+    /* If we got a shortcut from the current list, or a "universal"
+     * statusbar prompt shortcut, set have_shortcut to TRUE. */
+    have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
+	input == NANO_HOME_KEY || input == NANO_END_KEY ||
+	input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
+	input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
+	input == NANO_CUT_KEY);
+
+    /* Set s_or_t to TRUE if we got a shortcut. */
+    *s_or_t = have_shortcut;
+
+    if (allow_funcs) {
+	if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) {
+	    /* If we're using restricted mode, the filename isn't blank,
+	     * and we're at the "Write File" prompt, disable text
+	     * input. */
+	    if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
+		currshortcut != writefile_list) {
+		kbinput_len++;
+		kbinput = (int *)nrealloc(kbinput, kbinput_len *
+			sizeof(int));
+		kbinput[kbinput_len - 1] = input;
+	    }
+	}
+
+	/* If we got a shortcut, or if there aren't any other characters
+	 * waiting after the one we read in, we need to display all the
+	 * characters in the input buffer if it isn't empty. */
+	 if (*s_or_t == TRUE || get_buffer_len() == 0) {
+	    if (kbinput != NULL) {
+		/* Display all the characters in the input buffer at
+		 * once. */
+		do_statusbar_output(kbinput, kbinput_len);
+
+		/* Empty the input buffer. */
+		kbinput_len = 0;
+		free(kbinput);
+		kbinput = NULL;
+	    }
+	}
+
+	if (have_shortcut) {
+	    switch (input) {
+		/* Handle the "universal" statusbar prompt shortcuts. */
+		case NANO_REFRESH_KEY:
+		    total_refresh();
+		    break;
+		case NANO_HOME_KEY:
+		    do_statusbar_home();
+		    break;
+		case NANO_END_KEY:
+		    do_statusbar_end();
+		    break;
+		case NANO_FORWARD_KEY:
+		    do_statusbar_right();
+		    break;
+		case NANO_BACK_KEY:
+		    do_statusbar_left();
+		    break;
+		case NANO_BACKSPACE_KEY:
+		    /* If we're using restricted mode, the filename
+		     * isn't blank, and we're at the "Write File"
+		     * prompt, disable Backspace. */
+		    if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
+			currshortcut != writefile_list)
+			do_statusbar_backspace();
+		    break;
+		case NANO_DELETE_KEY:
+		    /* If we're using restricted mode, the filename
+		     * isn't blank, and we're at the "Write File"
+		     * prompt, disable Delete. */
+		    if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
+			currshortcut != writefile_list)
+			do_statusbar_delete();
+		    break;
+		case NANO_CUT_KEY:
+		    /* If we're using restricted mode, the filename
+		     * isn't blank, and we're at the "Write File"
+		     * prompt, disable Cut. */
+		    if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
+			currshortcut != writefile_list)
+			do_statusbar_cut_text();
+		    break;
+		/* Handle the normal statusbar prompt shortcuts, setting
+		 * finished to TRUE to indicate that we're done after
+		 * running or trying to run their associated
+		 * functions. */
+		default:
+		    if (s->func != NULL) {
+			if (ISSET(VIEW_MODE) && !s->viewok)
+			    print_view_warning();
+			else
+			    s->func();
+		    }
+		    *finished = TRUE;
+	    }
+	}
+    }
+
+    return input;
+}
+
+#ifndef DISABLE_MOUSE
+bool do_statusbar_mouse(void)
+{
+    /* FIXME: If we clicked on a location in the statusbar, the cursor
+     * should move to the location we clicked on.  This functionality
+     * should be in this function. */
+    int mouse_x, mouse_y;
+    return get_mouseinput(&mouse_x, &mouse_y, TRUE);
+}
+#endif
+
+void do_statusbar_home(void)
+{
+#ifndef NANO_SMALL
+    if (ISSET(SMART_HOME)) {
+	size_t statusbar_x_save = statusbar_x;
+	for (statusbar_x = 0; isblank(answer[statusbar_x]) &&
+		statusbar_x < statusbar_xend; statusbar_x++)
+	    ;
+	if (statusbar_x == statusbar_x_save ||
+		statusbar_x == statusbar_xend)
+	    statusbar_x = 0;
+    } else
+#endif
+	statusbar_x = 0;
+}
+
+void do_statusbar_end(void)
+{
+    statusbar_x = statusbar_xend;
+}
+
+void do_statusbar_right(void)
+{
+    if (statusbar_x < statusbar_xend)
+	statusbar_x = move_right(answer, statusbar_x);
+}
+
+void do_statusbar_left(void)
+{
+    if (statusbar_x > 0)
+	statusbar_x = move_left(answer, statusbar_x);
+}
+
+void do_statusbar_backspace(void)
+{
+    if (statusbar_x > 0) {
+	do_statusbar_left();
+	do_statusbar_delete();
+    }
+}
+
+void do_statusbar_delete(void)
+{
+    if (statusbar_x < statusbar_xend) {
+	int char_len = parse_char(answer + statusbar_x, NULL, NULL
+#ifdef NANO_WIDE
+		, NULL
+#endif
+		);
+
+	charmove(answer + statusbar_x, answer + statusbar_x + char_len,
+		statusbar_xend - statusbar_x - char_len + 1);
+	statusbar_xend -= char_len;
+    }
+}
+
+void do_statusbar_cut_text(void)
+{
+    null_at(&answer, 0);
+    statusbar_x = 0;
+    statusbar_xend = 0;
+}
+
+void do_statusbar_output(int *kbinput, size_t kbinput_len)
+{
+    size_t i;
+
+    char *key =
+#ifdef NANO_WIDE
+	!ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
+#endif
+	charalloc(1);
+
+    assert(answer != NULL);
+
+    for (i = 0; i < kbinput_len; i++) {
+	int key_len;
+
+	/* Null to newline, if needed. */
+	if (kbinput[i] == '\0')
+	    kbinput[i] = '\n';
+	/* Newline to Enter, if needed. */
+	else if (kbinput[i] == '\n')
+	    /* FIXME: We need to indicate when this happens, so that we
+	     * can break out of the statusbar prompt properly. */
+	    return;
+
+#ifdef NANO_WIDE
+	/* Change the wide character to its multibyte value.  If it's
+	 * invalid, go on to the next character. */
+	if (!ISSET(NO_UTF8)) {
+	    key_len = wctomb(key, (wchar_t)kbinput[i]);
+
+	    if (key_len == -1)
+		continue;
+	/* Interpret the character as a single-byte sequence. */
+	} else {
+#endif
+	    key_len = 1;
+	    key[0] = (unsigned char)kbinput[i];
+#ifdef NANO_WIDE
+	}
+#endif
+
+	/* More dangerousness fun =) */
+	answer = charealloc(answer, statusbar_xend + key_len + 1);
+
+	assert(statusbar_x <= statusbar_xend);
+
+	charmove(&answer[statusbar_x + key_len], &answer[statusbar_x],
+		statusbar_xend - statusbar_x + key_len);
+	charcpy(&answer[statusbar_x], key, key_len);
+	statusbar_xend += key_len;
+
+	do_statusbar_right();
+    }
+
+    free(key);
+}
+
 /* Return the placewewant associated with current_x.  That is, xplustabs
  * is the zero-based column position of the cursor.  Value is no smaller
  * than current_x. */
@@ -2101,14 +2370,9 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def,
 		)
 {
     int kbinput;
-    bool meta_key, func_key;
-    static size_t x = (size_t)-1;
-	/* the cursor position in 'answer' */
-    size_t xend;
-	/* length of 'answer', the status bar text */
+    bool meta_key, func_key, s_or_t, finished;
     bool tabbed = FALSE;
 	/* used by input_tab() */
-    const shortcut *t;
 
 #ifndef NANO_SMALL
    /* for history */
@@ -2125,32 +2389,30 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def,
        answer or restored from answer to currentbuf. */
     int use_cb = 0;
 #endif
-    xend = strlen(def);
+    statusbar_xend = strlen(def);
 
-    /* Only put x at the end of the string if it's uninitialized, if it
-       would be past the end of the string as it is, or if
-       resetstatuspos is TRUE.  Otherwise, leave it alone.  This is so
-       the cursor position stays at the same place if a prompt-changing
-       toggle is pressed. */
-    if (x == (size_t)-1 || x > xend || resetstatuspos)
-	x = xend;
+    /* Only put statusbar_x at the end of the string if it's
+     * uninitialized, if it would be past the end of the string as it
+     * is, or if resetstatuspos is TRUE.  Otherwise, leave it alone.
+     * This is so the cursor position stays at the same place if a
+     * prompt-changing toggle is pressed. */
+    if (statusbar_x == (size_t)-1 || statusbar_x > statusbar_xend ||
+		resetstatuspos)
+	statusbar_x = statusbar_xend;
 
-    answer = charealloc(answer, xend + 1);
-    if (xend > 0)
+    answer = charealloc(answer, statusbar_xend + 1);
+    if (statusbar_xend > 0)
 	strcpy(answer, def);
     else
 	answer[0] = '\0';
 
-#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
     currshortcut = s;
-#endif
 
     /* Get the input! */
 
-    nanoget_repaint(buf, answer, x);
+    nanoget_repaint(buf, answer, statusbar_x);
 
-    /* Make sure any editor screen updates are displayed before getting
-       input */
+    /* Refresh the edit window before getting input. */
     wnoutrefresh(edit);
     wrefresh(bottomwin);
 
@@ -2159,105 +2421,22 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def,
      * to files not specified on the command line.  In this case,
      * disable all keys that would change the text if the filename isn't
      * blank and we're at the "Write File" prompt. */
-    while ((kbinput = get_kbinput(bottomwin, &meta_key, &func_key)) !=
-	NANO_CANCEL_KEY && kbinput != NANO_ENTER_KEY) {
-	for (t = s; t != NULL; t = t->next) {
-#ifdef DEBUG
-	    fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
-#endif
+    while ((kbinput = do_statusbar_input(&meta_key, &func_key,
+	&s_or_t, &finished, TRUE)) != NANO_CANCEL_KEY &&
+	kbinput != NANO_ENTER_KEY) {
 
-	    /* Temporary hack to interpret NANO_HELP_FKEY correctly. */
-	    if (kbinput == t->funcval)
-		kbinput = t->ctrlval;
-
-	    if (kbinput == t->ctrlval && is_cntrl_char(kbinput)) {
-
-#ifndef DISABLE_HELP
-		/* Have to do this here, it would be too late to do it
-		   in statusq() */
-		if (kbinput == NANO_HELP_KEY) {
-		    do_help();
-		    break;
-		}
-#endif
-#ifndef NANO_SMALL
-		/* Have to handle these here too, for the time being */
-		if (kbinput == NANO_PREVLINE_KEY || kbinput == NANO_NEXTLINE_KEY)
-		    break;
-#endif
+	/* If we have a shortcut with an associated function, break out
+	 * if we're finished after running the function. */
+	if (finished)
+	    break;
 
-		return t->ctrlval;
-	    }
-	}
-	assert(x <= xend && xend == strlen(answer));
+	assert(statusbar_x <= statusbar_xend &&
+		statusbar_xend == strlen(answer));
 
 	if (kbinput != '\t')
 	    tabbed = FALSE;
 
 	switch (kbinput) {
-#ifndef DISABLE_MOUSE
-	case KEY_MOUSE:
-	    {
-		int mouse_x, mouse_y;
-		get_mouseinput(&mouse_x, &mouse_y, TRUE);
-	    }
-	    break;
-#endif
-	case NANO_REFRESH_KEY:
-	    total_refresh();
-	    break;
-	case NANO_HOME_KEY:
-#ifndef NANO_SMALL
-	    if (ISSET(SMART_HOME)) {
-		size_t old_x = x;
-
-		for (x = 0; isblank(answer[x]) && x < xend; x++)
-		    ;
-
-		if (x == old_x || x == xend)
-		    x = 0;
-	    } else
-#endif
-		x = 0;
-	    break;
-	case NANO_END_KEY:
-	    x = xend;
-	    break;
-	case NANO_FORWARD_KEY:
-	    if (x < xend)
-		x++;
-	    break;
-	case NANO_DELETE_KEY:
-	    /* If we're using restricted mode, the filename isn't blank,
-	     * and we're at the "Write File" prompt, disable Delete. */
-	    if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
-		if (x < xend) {
-		    charmove(answer + x, answer + x + 1, xend - x);
-		    xend--;
-		}
-	    }
-	    break;
-	case NANO_CUT_KEY:
-	    /* If we're using restricted mode, the filename isn't blank,
-	     * and we're at the "Write File" prompt, disable Cut. */
-	    if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
-		null_at(&answer, 0);
-		xend = 0;
-		x = 0;
-	    }
-	    break;
-	case NANO_BACKSPACE_KEY:
-	    /* If we're using restricted mode, the filename isn't blank,
-	     * and we're at the "Write File" prompt, disable
-	     * Backspace. */
-	    if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
-		if (x > 0) {
-		    charmove(answer + x - 1, answer + x, xend - x + 1);
-		    x--;
-		    xend--;
-		}
-	    }
-	    break;
 	case NANO_TAB_KEY:
 #ifndef NANO_SMALL
 	    /* tab history completion */
@@ -2269,8 +2448,8 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def,
 
 		if (history_list->len > 0) {
 		    complete = get_history_completion(history_list, answer);
-		    xend = strlen(complete);
-		    x = xend;
+		    statusbar_x = strlen(complete);
+		    statusbar_xend = statusbar_x;
 		    answer = mallocstrcpy(answer, complete);
 		}
 	    }
@@ -2282,18 +2461,15 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def,
 	    if (allow_tabs) {
 		int shift = 0;
 
-		answer = input_tab(answer, x, &tabbed, &shift, list);
-		xend = strlen(answer);
-		x += shift;
-		if (x > xend)
-		    x = xend;
+		answer = input_tab(answer, statusbar_x, &tabbed, &shift,
+			list);
+		statusbar_xend = strlen(answer);
+		statusbar_x += shift;
+		if (statusbar_x > statusbar_xend)
+		    statusbar_x = statusbar_xend;
 	    }
 #endif
 	    break;
-	case NANO_BACK_KEY:
-	    if (x > 0)
-		x--;
-	    break;
 	case NANO_PREVLINE_KEY:
 #ifndef NANO_SMALL
 	    if (history_list != NULL) {
@@ -2321,7 +2497,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def,
 		    answer = mallocstrcpy(answer, currentbuf);
 		    free(currentbuf);
 		    currentbuf = NULL;
-		    xend = strlen(answer);
+		    statusbar_xend = strlen(answer);
 		    use_cb = 0;
 
 		/* else get older search from the history list and save
@@ -2329,12 +2505,12 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def,
 		   answer */
 		} else if ((history = get_history_older(history_list)) != NULL) {
 		    answer = mallocstrcpy(answer, history);
-		    xend = strlen(history);
+		    statusbar_xend = strlen(history);
 		} else {
 		    answer = mallocstrcpy(answer, "");
-		    xend = 0;
+		    statusbar_xend = 0;
 		}
-		x = xend;
+		statusbar_x = statusbar_xend;
 	    }
 #endif
 	    break;
@@ -2346,7 +2522,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def,
 		   in answer */
 		if ((history = get_history_newer(history_list)) != NULL) {
 		    answer = mallocstrcpy(answer, history);
-		    xend = strlen(history);
+		    statusbar_xend = strlen(history);
 
 		/* if there is no newer search, we're here */
 		
@@ -2360,7 +2536,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def,
 		    answer = mallocstrcpy(answer, currentbuf);
 		    free(currentbuf);
 		    currentbuf = NULL;
-		    xend = strlen(answer);
+		    statusbar_xend = strlen(answer);
 		    use_cb = 1;
 
 		/* otherwise, if currentbuf is NULL and use_cb isn't 2, 
@@ -2374,53 +2550,24 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def,
 			currentbuf = mallocstrcpy(currentbuf, answer);
 			answer = mallocstrcpy(answer, "");
 		    }
-		    xend = 0;
+		    statusbar_xend = 0;
 		    use_cb = 2;
 		}
-		x = xend;
+		statusbar_x = statusbar_xend;
 	    }
 #endif
 	    break;
-	    default:
-
-		for (t = s; t != NULL; t = t->next) {
-#ifdef DEBUG
-		    fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
-			    kbinput);
-#endif
-		    if (meta_key && (kbinput == t->metaval || kbinput == t->miscval))
-			/* We hit a meta key.  Do like above.  We don't
-			 * just put back the letter and let it get
-			 * caught above cause that screws the
-			 * keypad... */
-			return kbinput;
-		}
-
-	    /* If we're using restricted mode, the filename isn't blank,
-	     * and we're at the "Write File" prompt, act as though the
-	     * unhandled character we got is a control character and
-	     * throw it away. */
-	    if (is_cntrl_char(kbinput) || (ISSET(RESTRICTED) && filename[0] != '\0' && s == writefile_list))
-		break;
-	    answer = charealloc(answer, xend + 2);
-	    charmove(answer + x + 1, answer + x, xend - x + 1);
-	    xend++;
-	    answer[x] = kbinput;
-	    x++;
-
-#ifdef DEBUG
-	    fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
-#endif
-	} /* switch (kbinput) */
+	}
 #ifndef NANO_SMALL
 	last_kbinput = kbinput;
 #endif
-	nanoget_repaint(buf, answer, x);
+	nanoget_repaint(buf, answer, statusbar_x);
 	wrefresh(bottomwin);
-    } /* while (kbinput ...) */
+    }
 
-    /* We finished putting in an answer; reset x */
-    x = (size_t)-1;
+    /* We finished putting in an answer, so reset statusbar_x. */
+    if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY)
+	statusbar_x = (size_t)-1;
 
     return kbinput;
 }
@@ -2464,36 +2611,6 @@ int statusq(bool allow_tabs, const shortcut *s, const char *def,
     resetstatuspos = FALSE;
 
     switch (ret) {
-	case NANO_FIRSTLINE_KEY:
-	case NANO_FIRSTLINE_FKEY:
-	    do_first_line();
-	    resetstatuspos = TRUE;
-	    break;
-	case NANO_LASTLINE_KEY:
-	case NANO_LASTLINE_FKEY:
-	    do_last_line();
-	    resetstatuspos = TRUE;
-	    break;
-#ifndef DISABLE_JUSTIFY
-	case NANO_PARABEGIN_KEY:
-	case NANO_PARABEGIN_ALTKEY1:
-	case NANO_PARABEGIN_ALTKEY2:
-	    do_para_begin();
-	    resetstatuspos = TRUE;
-	    break;
-	case NANO_PARAEND_KEY:
-	case NANO_PARAEND_ALTKEY1:
-	case NANO_PARAEND_ALTKEY2:
-	    do_para_end();
-	    resetstatuspos = TRUE;
-	    break;
-	case NANO_FULLJUSTIFY_KEY:
-	case NANO_FULLJUSTIFY_ALTKEY:
-	    if (!ISSET(VIEW_MODE))
-		do_full_justify();
-	    resetstatuspos = TRUE;
-	    break;
-#endif
 	case NANO_CANCEL_KEY:
 	    ret = -1;
 	    resetstatuspos = TRUE;