diff --git a/ChangeLog b/ChangeLog
index 0491575537f0c1a78b4a7eb4c118f7d1e584934e..fcd1a85576900759208fe089b3b64b781c432f1a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 CVS code -
+Changes
 - General:
+	- Search history and replace history up/down cursor arrows, w/history 
+	  tab completion, not available w/NANO_SMALL.  Changes to 
+	  statusq, others (Ken Tyler).  Added shortcut to search/replace 
+	  shortcuts so people will know it's there, forced KEY_UP and KEY_DOWN
+	  defs in nano.h (Chris, in case blame needs to be placed later).
 	- Translation updates (see po/ChangeLog for details).
 	- Forward-ported Chris' --disable-wrapping-as-root option from
 	  1.0.9.  Per Jordi's suggestions, have it override
@@ -62,6 +68,8 @@ CVS code -
 	- If there's a page or less of text, do an edit_update() if the
 	  mark is on; otherwise, the highlight won't be displayed. (DLR)
 - nano.c:
+	- Added free_history list calls clean up, added init of list headers
+	   modified statusq calls (Ken Tyler).
   do_prev_word()
 	- Make the assert match that in do_next_word(). (DLR)
   do_enter()
diff --git a/files.c b/files.c
index 719bd960e15d18921da8f2674379279d3397a3be..e37935db5903184264bd8dcf332900796a4dc711 100644
--- a/files.c
+++ b/files.c
@@ -426,21 +426,21 @@ int do_insertfile(int loading_file)
     if (operating_dir != NULL && strcmp(operating_dir, ".") != 0)
 #ifdef ENABLE_MULTIBUFFER 
 	if (ISSET(MULTIBUFFER))
-	    i = statusq(1, insertfile_list, inspath, _("File to insert into new buffer [from %s] "),
+	    i = statusq(1, insertfile_list, inspath, 0, _("File to insert into new buffer [from %s] "),
 		operating_dir);
 	else
 #endif
-	    i = statusq(1, insertfile_list, inspath, _("File to insert [from %s] "),
+	    i = statusq(1, insertfile_list, inspath, 0, _("File to insert [from %s] "),
 		operating_dir);
 
     else
 #endif
 #ifdef ENABLE_MULTIBUFFER 
 	if (ISSET(MULTIBUFFER))
-	    i = statusq(1, insertfile_list, inspath, _("File to insert into new buffer [from ./] "));
+	    i = statusq(1, insertfile_list, inspath, 0, _("File to insert into new buffer [from ./] "));
 	else
 #endif
-	    i = statusq(1, insertfile_list, inspath, _("File to insert [from ./] "));
+	    i = statusq(1, insertfile_list, inspath, 0, _("File to insert [from ./] "));
 
     if (i != -1) {
 	inspath = mallocstrcpy(inspath, answer);
@@ -492,7 +492,7 @@ int do_insertfile(int loading_file)
 #endif /* ENABLE_MULTIBUFFER */
 	if (i == NANO_EXTCMD_KEY) {
 	    int ts;
-	    ts = statusq(1, extcmd_list, "", _("Command to execute "));
+	    ts = statusq(1, extcmd_list, "", 0, _("Command to execute "));
 	    if (ts == -1  || answer == NULL || answer[0] == '\0') {
 		statusbar(_("Cancelled"));
 		UNSET(KEEP_CUTBUFFER);
@@ -1711,34 +1711,34 @@ int do_writeout(const char *path, int exiting, int append)
 	/* Be nice to the translation folks */
 	if (ISSET(MARK_ISSET) && !exiting) {
 	    if (append == 2)
-		i = statusq(1, writefile_list, "",
+		i = statusq(1, writefile_list, "", 0,
 		    "%s%s%s", _("Prepend Selection to File"), formatstr, backupstr);
-	    else if (append == 1)
-		i = statusq(1, writefile_list, "",
+	    else if (append)
+		i = statusq(1, writefile_list, "", 0,
 		    "%s%s%s", _("Append Selection to File"), formatstr, backupstr);
 	    else
-		i = statusq(1, writefile_list, "",
+		i = statusq(1, writefile_list, "", 0,
 		    "%s%s%s", _("Write Selection to File"), formatstr, backupstr);
 	} else {
 	    if (append == 2)
-		i = statusq(1, writefile_list, answer,
+		i = statusq(1, writefile_list, answer, 0,
 		    "%s%s%s", _("File Name to Prepend to"), formatstr, backupstr);
-	    else if (append == 1)
-		i = statusq(1, writefile_list, answer,
+	    else if (append)
+		i = statusq(1, writefile_list, answer, 0,
 		    "%s%s%s", _("File Name to Append to"), formatstr, backupstr);
 	    else
-		i = statusq(1, writefile_list, answer,
+		i = statusq(1, writefile_list, answer, 0,
 		    "%s%s%s", _("File Name to Write"), formatstr, backupstr);
 	}
 #else
 	if (append == 2)
-	    i = statusq(1, writefile_list, answer,
+	    i = statusq(1, writefile_list, answer, 0,
 		"%s", _("File Name to Prepend to"));
-	else if (append == 1)
-	    i = statusq(1, writefile_list, answer,
+	else if (append)
+	    i = statusq(1, writefile_list, answer, 0,
 		"%s", _("File Name to Append to"));
 	else
-	    i = statusq(1, writefile_list, answer,
+	    i = statusq(1, writefile_list, answer, 0,
 		"%s", _("File Name to Write"));
 #endif /* !NANO_SMALL */
 
@@ -2650,7 +2650,7 @@ char *do_browser(const char *inpath)
 	case NANO_GOTO_KEY:
 
 	    curs_set(1);
-	    j = statusq(0, gotodir_list, "", _("Goto Directory"));
+	    j = statusq(0, gotodir_list, "", 0, _("Goto Directory"));
 	    bottombars(browser_list);
 	    curs_set(0);
 
diff --git a/global.c b/global.c
index 5ffaa9f60533f82365264e5c909c5c9d436d43a8..b9a09bd3fc7988363f5e13242b4e46fa6ecc26f4 100644
--- a/global.c
+++ b/global.c
@@ -36,6 +36,7 @@ int wrap_at = -CHARS_FROM_EOL;/* Right justified fill value, allows resize */
 char *last_search = NULL;	/* Last string we searched for */
 char *last_replace = NULL;	/* Last replacement string */
 int search_last_line;		/* Is this the last search line? */
+int past_editbuff;		/* search lines not displayed */
 
 int flags = 0;			/* Our new flag containing many options */
 WINDOW *edit;			/* The file portion of the editor */
@@ -134,6 +135,11 @@ const shortcut *currshortcut;	/* Current shortcut list we're using */
 toggle *toggles = NULL;
 #endif
 
+#ifndef NANO_SMALL
+historyheadtype search_history;
+historyheadtype replace_history;
+#endif
+
 /* Regular expressions */
 
 #ifdef HAVE_REGEX_H
@@ -327,7 +333,7 @@ void shortcut_init(int unjustify)
 	"", *nano_gotodir_msg = "", *nano_case_msg =
 	"", *nano_reverse_msg = "", *nano_execute_msg =
 	"", *nano_dos_msg = "", *nano_mac_msg =
-	"", *nano_backup_msg = "";
+	"", *nano_backup_msg = "", *nano_editstr_msg = "";
 
 #ifdef ENABLE_MULTIBUFFER
     const char *nano_openprev_msg = "", *nano_opennext_msg =
@@ -383,6 +389,7 @@ void shortcut_init(int unjustify)
     nano_dos_msg = _("Write file out in DOS format");
     nano_mac_msg = _("Write file out in Mac format");
     nano_backup_msg = _("Back up original file when saving");
+    nano_editstr_msg = _("Edit the previous search/replace strings");
 #ifdef HAVE_REGEX_H
     nano_regexp_msg = _("Use regular expressions");
     nano_bracket_msg = _("Find other bracket");
@@ -606,6 +613,14 @@ void shortcut_init(int unjustify)
     sc_init_one(&whereis_list, TOGGLE_REGEXP_KEY, _("Regexp"),
 		IFHELP(nano_regexp_msg, 0), 0, 0, VIEW, 0);
 #endif
+
+#ifndef NANO_SMALL
+    sc_init_one(&whereis_list, KEY_UP, _("History"),
+		IFHELP(nano_editstr_msg, 0), 0, 0, VIEW, 0);
+#endif
+
+
+
 #endif /* !NANO_SMALL */
 
     free_shortcutage(&replace_list);
@@ -639,6 +654,12 @@ void shortcut_init(int unjustify)
     sc_init_one(&replace_list, TOGGLE_REGEXP_KEY, _("Regexp"),
 		IFHELP(nano_regexp_msg, 0), 0, 0, VIEW, 0);
 #endif
+
+#ifndef NANO_SMALL
+    sc_init_one(&replace_list, KEY_UP, _("History"),
+		IFHELP(nano_editstr_msg, 0), 0, 0, VIEW, 0);
+#endif
+
 #endif /* !NANO_SMALL */
 
     free_shortcutage(&replace_list_2);
@@ -655,6 +676,11 @@ void shortcut_init(int unjustify)
     sc_init_one(&replace_list_2, NANO_LASTLINE_KEY, _("Last Line"),
 		IFHELP(nano_lastline_msg, 0), 0, 0, VIEW, do_last_line);
 
+#ifndef NANO_SMALL
+    sc_init_one(&replace_list_2, KEY_UP, _("History"),
+		IFHELP(nano_editstr_msg, 0), 0, 0, VIEW, 0);
+#endif
+
     free_shortcutage(&goto_list);
 
     sc_init_one(&goto_list, NANO_HELP_KEY, _("Get Help"),
@@ -885,5 +911,10 @@ void thanks_for_all_the_fish(void)
 	free(bill);
     }
 #endif /* ENABLE_COLOR */
+#ifndef NANO_SMALL
+    /* free history lists */
+    free_history(&search_history);
+    free_history(&replace_history);
+#endif
 }
 #endif /* DEBUG */
diff --git a/nano.c b/nano.c
index cbe94ecb7ae71bf38cd779d8062038d66c717623..e8de005c77ba9b72002acbd46fb4f72c7ffc3f6c 100644
--- a/nano.c
+++ b/nano.c
@@ -66,6 +66,12 @@ static sigjmp_buf jmpbuf;	/* Used to return to mainloop after SIGWINCH */
 /* What we do when we're all set to exit */
 RETSIGTYPE finish(int sigage)
 {
+
+#ifndef NANO_SMALL
+    free_history(&search_history);
+    free_history(&replace_history);
+#endif
+
     keypad(edit, TRUE);
     keypad(bottomwin, TRUE);
 
@@ -1633,7 +1639,7 @@ int do_int_spell_fix(const char *word)
 	    do_replace_highlight(TRUE, word);
 
 	    /* allow replace word to be corrected */
-	    i = statusq(0, spell_list, last_replace, _("Edit a replacement"));
+	    i = statusq(0, spell_list, last_replace, 0, _("Edit a replacement"));
 
 	    do_replace_highlight(FALSE, word);
 
@@ -3093,6 +3099,7 @@ int main(int argc, char *argv[])
 #endif
 	}
     }
+
 	if (!ISSET(NO_RCFILE))
 	    do_rcfile();
 #else
@@ -3334,6 +3341,10 @@ int main(int argc, char *argv[])
 	keypad(bottomwin, TRUE);
     }
 
+#ifndef NANO_SMALL
+    history_init();
+#endif
+
 #ifdef ENABLE_COLOR
     do_colorinit();
 #endif /* ENABLE_COLOR */
diff --git a/nano.h b/nano.h
index 70581c56845fc530ddad49a9fd8ede1b9d2800b5..ca8a5d73370cbc61f6e68cfcacb73614bb2565dd 100644
--- a/nano.h
+++ b/nano.h
@@ -90,6 +90,14 @@
 #define KEY_END -1
 #endif /* KEY_END */
 
+/* Snatch these out of the ncurse sdefs, so we can use them in search
+   history regardless of whethere we're using ncurses or not */
+#ifndef KEY_UP
+#define KEY_UP   0403
+#define KEY_DOWN 0402
+#endif /* KEY_UP */
+
+
 #define VERMSG "GNU nano " VERSION
 
 #if defined(DISABLE_WRAPPING) && defined(DISABLE_JUSTIFY)
@@ -190,6 +198,21 @@ typedef struct syntaxtype {
 
 #endif /* ENABLE_COLOR */
 
+#ifndef NANO_SMALL
+typedef struct historytype {
+    struct historytype *next;
+    struct historytype *prev;
+    char *data;
+} historytype;
+typedef struct historyheadtype {
+    struct historytype *next;	/* keep *next and *prev members together */
+    struct historytype *prev;	/* and in same order as in historytype */
+    struct historytype *tail;
+    struct historytype *current;
+    int count;
+    int len;
+} historyheadtype;
+#endif /* !NANO_SMALL */
 
 /* Bitwise flags so we can save space (or more correctly, not waste it) */
 
@@ -397,4 +420,6 @@ typedef enum {
 /* Minimum fill length (space available for text before wrapping occurs) */
 #define MIN_FILL_LENGTH 10
 
+/* Maximum number of search history strings saved, same value used for replace history */
+#define MAX_SEARCH_HISTORY 100
 #endif /* !NANO_H */
diff --git a/proto.h b/proto.h
index 51388a179a12f321bd0021ed71df3a940e40395d..01278bf1d404955511443ffc89bb93fa582b5b1c 100644
--- a/proto.h
+++ b/proto.h
@@ -40,6 +40,7 @@ extern long totsize;
 extern int temp_opt;
 extern int wrap_at, flags, tabsize;
 extern int search_last_line;
+extern int past_editbuff;
 extern int currslen;
 
 #ifndef DISABLE_JUSTIFY
@@ -109,6 +110,11 @@ extern regmatch_t synfilematches[1];
 extern toggle *toggles;
 #endif
 
+#ifndef NANO_SMALL
+extern historyheadtype search_history;
+extern historyheadtype replace_history;
+#endif
+
 /* Functions we want available */
 
 /* Public functions in color.c */
@@ -355,6 +361,17 @@ int do_gotoline_void(void);
 void do_gotopos(int line, int pos_x, int pos_y, int pos_placewewant);
 #endif
 int do_find_bracket(void);
+#ifndef NANO_SMALL
+void history_init(void);
+historytype *find_node(historytype *h, char *s);
+void remove_node(historytype *r);
+void insert_node(historytype *h, const char *s);
+void update_history(historyheadtype *h, char *s);
+char *get_history_older(historyheadtype *h);
+char *get_history_newer(historyheadtype *h);
+char *get_history_completion(historyheadtype *h, char *s);
+void free_history(historyheadtype *h);
+#endif
 
 /* Public functions in utils.c */
 int is_cntrl_char(int c);
@@ -398,6 +415,9 @@ void blank_statusbar_refresh(void);
 void check_statblank(void);
 void nanoget_repaint(const char *buf, const char *inputbuf, int x);
 int nanogetstr(int allowtabs, const char *buf, const char *def,
+#ifndef NANO_SMALL
+		historyheadtype *history_list,
+#endif
 		const shortcut *s
 #ifndef DISABLE_TABCOMP
 		, int *list
@@ -426,6 +446,9 @@ void edit_refresh(void);
 void edit_refresh_clearok(void);
 void edit_update(filestruct *fileptr, topmidbotnone location);
 int statusq(int tabs, const shortcut *s, const char *def,
+#ifndef NANO_SMALL
+		historyheadtype *history_list,
+#endif
 		const char *msg, ...);
 int do_yesno(int all, int leavecursor, const char *msg, ...);
 int total_refresh(void);
diff --git a/rcfile.c b/rcfile.c
index 24994087490c25721970d862183b05440713daa3..234bb1c273de3c9feac3e4d4e2f9aca2bd95e759 100644
--- a/rcfile.c
+++ b/rcfile.c
@@ -607,9 +607,10 @@ void do_rcfile(void)
 
     lineno = 0;
 
-    if (userage == NULL)
+    if (userage == NULL) {
 	rcfile_error(_("I can't find my home directory!  Wah!"));
-    else {
+	SET(NO_RCFILE); /* if no .nanorc, don't try to read .nano_history */
+    } else {
 	nanorc = nrealloc(nanorc, strlen(userage->pw_dir) + 9);
 	sprintf(nanorc, "%s/.nanorc", userage->pw_dir);
 
@@ -621,9 +622,11 @@ void do_rcfile(void)
 #endif
 	if ((rcstream = fopen(nanorc, "r")) == NULL) {
 	    /* Don't complain about the file not existing */
-	    if (errno != ENOENT)
+	    if (errno != ENOENT) {
 		rcfile_error(_("Unable to open ~/.nanorc file, %s"),
 			strerror(errno));
+		SET(NO_RCFILE);
+	    }
 	} else {
 	    parse_rcfile(rcstream);
 	    fclose(rcstream);
diff --git a/search.c b/search.c
index 115b9a64ecfa0800088d776f71a38e7b86d92d71..80b0a4a7d9de402e99c3eb72316b531eec549c76 100644
--- a/search.c
+++ b/search.c
@@ -26,10 +26,17 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <ctype.h>
+#include <errno.h>
 #include <assert.h>
 #include "proto.h"
 #include "nano.h"
 
+#ifndef NANO_SMALL
+#ifdef ENABLE_NANORC
+#include <pwd.h>
+#endif
+#endif
+
 static int past_editbuff;
 	/* findnextstr() is now searching lines not displayed */
 
@@ -89,7 +96,7 @@ void search_init_globals(void)
 }
 
 /* Set up the system variables for a search or replace.  Returns -1 on
-   abort, 0 on success, and 1 on rerun calling program 
+   abort, 0 on success, and 1 on rerun calling program
    Return -2 to run opposite program (search -> replace, replace ->
    search).
 
@@ -110,24 +117,37 @@ int search_init(int replacing)
 	backupstring = NULL;
 	UNSET(CLEAR_BACKUPSTRING);
     }
-	
-     /* Okay, fun time.  backupstring is our holder for what is being 
+
+     /* Okay, fun time.  backupstring is our holder for what is being
 	returned from the statusq call.  Using answer for this would be tricky.
 	Here, if we're using PICO_MODE, we only want nano to put the
 	old string back up as editable if it's not the same as last_search.
 
 	Otherwise, if we don't already have a backupstring, set it to
 	last_search. */
-
+#if 0
+/* might need again ;)*/
     if (ISSET(PICO_MODE)) {
 	if (backupstring == NULL || !strcmp(backupstring, last_search)) {
+	    /* backupstring = mallocstrcpy(backupstring, ""); */
 	    backupstring = charalloc(1);
 	    backupstring[0] = '\0';
 	}
-    }
-    else if (backupstring == NULL)
+    } else
+#endif
+    if (backupstring == NULL)
+#ifndef NANO_SMALL
+	backupstring = mallocstrcpy(backupstring, search_history.current->data);
+#else
 	backupstring = mallocstrcpy(backupstring, last_search);
+#endif
 
+/* NEW TEST */
+    if (ISSET(PICO_MODE)) {
+	backupstring = mallocstrcpy(backupstring, "");
+	search_history.current = (historytype *)&search_history.next;
+    }
+/* */
     /* If using Pico messages, we do things the old fashioned way... */
     if (ISSET(PICO_MODE) && last_search[0] != '\0') {
 	buf = charalloc(COLS / 3 + 7);
@@ -141,7 +161,10 @@ int search_init(int replacing)
 
     /* This is now one simple call.  It just does a lot */
     i = statusq(0, replacing ? replace_list : whereis_list, backupstring,
-	"%s%s%s%s%s%s", 
+#ifndef NANO_SMALL
+	&search_history,
+#endif
+	"%s%s%s%s%s%s",
 	_("Search"),
 
 	/* This string is just a modifier for the search prompt,
@@ -168,6 +191,9 @@ int search_init(int replacing)
 	reset_cursor();
 	free(backupstring);
 	backupstring = NULL;
+#ifndef NANO_SMALL
+	search_history.current = search_history.next;
+#endif
 	return -1;
     } else {
 	switch (i) {
@@ -210,7 +236,14 @@ int search_init(int replacing)
 	case NANO_FROMSEARCHTOGOTO_KEY:
 	    free(backupstring);
 	    backupstring = NULL;
-	    do_gotoline_void();
+#ifndef NANO_SMALL
+	    search_history.current = search_history.next;
+#endif
+	    i = (int)strtol(answer, &buf, 10);		/* just testing answer here */
+	    if (!(errno == ERANGE || *answer == '\0' || *buf != '\0'))
+		do_gotoline(-1, 0);
+	    else
+		do_gotoline_void();
 	    return -3;
 	default:
 	    do_early_abort();
@@ -301,7 +334,7 @@ filestruct *findnextstr(int quiet, int bracket_mode,
 		not_found_msg(needle);
 	    return NULL;
 	}
-    } 
+    }
 #ifndef NANO_SMALL
     else {	/* reverse search */
 	current_x_find = current_x - 1;
@@ -403,6 +436,9 @@ int do_search(void)
     /* The sneaky user deleted the previous search string */
     if (!ISSET(PICO_MODE) && answer[0] == '\0') {
 	statusbar(_("Search Cancelled"));
+#ifndef NANO_SMALL
+	search_history.current = search_history.next;
+#endif
 	search_abort();
 	return 0;
     }
@@ -415,6 +451,11 @@ int do_search(void)
     else
 	last_search = mallocstrcpy(last_search, answer);
 
+#ifndef NANO_SMALL
+    /* add this search string to the search history list */
+    update_history(&search_history, answer);
+#endif	/* !NANO_SMALL */
+
     search_last_line = 0;
     didfind = findnextstr(FALSE, FALSE, current, current_x, answer);
 
@@ -697,6 +738,10 @@ int do_replace(void)
 	return 0;
     }
 
+#ifndef NANO_SMALL
+    update_history(&search_history, answer);
+#endif	/* !NANO_SMALL */
+
     /* Again, there was a previous string, but they deleted it and hit enter */
     if (!ISSET(PICO_MODE) && answer[0] == '\0') {
 	statusbar(_("Replace Cancelled"));
@@ -710,6 +755,7 @@ int do_replace(void)
 	answer = mallocstrcpy(answer, last_search);
     else
 	last_search = mallocstrcpy(last_search, answer);
+
     prevanswer = mallocstrcpy(prevanswer, last_search);
 
     if (ISSET(PICO_MODE) && last_replace[0] != '\0') {
@@ -718,16 +764,34 @@ int do_replace(void)
 
 	    strncpy(buf, last_replace, COLS / 3 - 1);
 	    strcpy(buf + COLS / 3 - 1, "...");
-	    i = statusq(0, replace_list_2, "", _("Replace with [%s]"),
-			buf);
+	    i = statusq(0, replace_list_2, "",
+#ifndef NANO_SMALL
+		&replace_history,
+#endif
+		_("Replace with [%s]"), buf);
 	    free(buf);
 	} else
-	    i = statusq(0, replace_list_2, "", _("Replace with [%s]"),
-			last_replace);
-    } else
-	i = statusq(0, replace_list_2, last_replace, _("Replace with"));
+	    i = statusq(0, replace_list_2, "",
+#ifndef NANO_SMALL
+		 &replace_history,
+#endif
+		_("Replace with [%s]") ,last_replace);
+    } else {
+#ifndef NANO_SMALL
+	replace_history.current = (historytype *)&replace_history.next;
+	last_replace = mallocstrcpy(last_replace, "");
+#endif
+	i = statusq(0, replace_list_2, last_replace,
+#ifndef NANO_SMALL
+		&replace_history,
+#endif
+		_("Replace with"));
+   }
+#ifndef NANO_SMALL
+    if (i == 0)
+	update_history(&replace_history, answer);
+#endif	/* !NANO_SMALL */
 
-    /* save where we are */
     begin = current;
     beginx = current_x;
     search_last_line = 0;
@@ -753,7 +817,7 @@ void goto_abort(void)
 int do_gotoline(int line, int save_pos)
 {
     if (line <= 0) {		/* Ask for it */
-	if (statusq(0, goto_list, "", _("Enter line number"))) {
+	if (statusq(0, goto_list, (line ? answer : ""), 0, _("Enter line number"))) {
 	    statusbar(_("Aborted"));
 	    goto_abort();
 	    return 0;
@@ -780,9 +844,9 @@ int do_gotoline(int line, int save_pos)
     	edit_update(current, NONE);
     else
 	edit_update(current, CENTER);
-
     placewewant = 0;
     goto_abort();
+    blank_statusbar_refresh();
     return 1;
 }
 
@@ -820,7 +884,9 @@ int do_find_bracket(void)
     filestruct *current_save;
 
     ch_under_cursor = current->data[current_x];
- 
+
+/*    if ((!(pos = strchr(brackets, ch_under_cursor))) || (!((offset = pos - brackets) < 8))) { */
+
     if (((pos = strchr(brackets, ch_under_cursor)) == NULL) || (((offset = pos - brackets) < 8) == 0)) {
 	statusbar(_("Not a bracket"));
 	return 1;
@@ -880,3 +946,126 @@ int do_find_bracket(void)
     return 0;
 }
 #endif
+
+#ifndef NANO_SMALL
+/*
+ * search and replace history list support functions
+ */
+
+/* initialize search and replace history lists */
+void history_init(void)
+{
+    search_history.next = (historytype *)&search_history.prev;
+    search_history.prev = NULL;
+    search_history.tail = (historytype *)&search_history.next;
+    search_history.current = search_history.next;
+    search_history.count = 0;
+    search_history.len = 0;
+
+    replace_history.next = (historytype *)&replace_history.prev;
+    replace_history.prev = NULL;
+    replace_history.tail = (historytype *)&replace_history.next;
+    replace_history.current = replace_history.next;
+    replace_history.count = 0;
+    replace_history.len = 0;
+}
+
+/* find first node containing string *s in history list *h */
+historytype *find_node(historytype *h, char *s)
+{
+    for ( ; h->next ; h = h->next)
+	if (strcmp(s, h->data) == 0)
+	    return h;
+    return NULL;
+}
+
+/* remove node *r */
+void remove_node(historytype *r)
+{
+    r->prev->next = r->next;
+    r->next->prev = r->prev;
+    free(r->data);
+    free(r);
+}
+
+/* add a node after node *h */
+void insert_node(historytype *h, const char *s)
+{
+    historytype *a;
+
+    a = nmalloc(sizeof(historytype));
+    a->next = h->next;
+    a->prev = h->next->prev;
+    h->next->prev = a;
+    h->next = a;
+    a->data = mallocstrcpy(NULL, s);
+}
+
+/* update history list */
+void update_history(historyheadtype *h, char *s)
+{
+    historytype *p;
+
+    if ((p = find_node(h->next, s))) {
+	if (p == h->next)		/* catch delete and re-insert of same string in 1st node */
+	    goto up_hs;
+	remove_node(p);				/* delete identical older string */
+	h->count--;
+    }
+    if (h->count == MAX_SEARCH_HISTORY) {	/* list 'full', delete oldest */
+	remove_node(h->tail);
+	h->count--;
+    }
+    insert_node((historytype *)h, s);
+    h->count++;
+up_hs:
+    h->current = h->next;
+}
+
+/* return a pointer to either the next older history or NULL if no more */
+char *get_history_older(historyheadtype *h)
+{
+    if (h->current->next) {		/* any older entries ? */
+	h->current = h->current->next;	/* yes */
+	return h->current->data;	/* return it */
+    }
+    return NULL;			/* end of list */
+}
+
+char *get_history_newer(historyheadtype *h)
+{
+    if (h->current->prev) {
+	h->current = h->current->prev;
+	if (h->current->prev)
+	    return h->current->data;
+    }
+    return NULL;
+}
+
+/* get a completion */
+char *get_history_completion(historyheadtype *h, char *s)
+{
+    historytype *p;
+
+    for (p = h->current->next ; p->next ; p = p->next) {
+	if ((strncmp(s, p->data, h->len) == 0) && (strlen(p->data) != h->len)) {
+	    h->current = p;
+	    return p->data;
+	}
+    }
+    h->current = (historytype*)h;
+    null_at(&s, h->len);
+    return s;
+}
+
+/* free a history list */
+void free_history(historyheadtype *h)
+{
+    historytype *p, *n;
+
+    for (p = h->next ; (n = p->next) ; p = n)
+	remove_node(p);
+}
+
+/* end of history support functions */
+#endif /* !NANO_SMALL */
diff --git a/winio.c b/winio.c
index e15b4b435c09c4852f456d4e6d67e61982c6ba5d..d6d743047a98f430689d878c1958ea495d062e6a 100644
--- a/winio.c
+++ b/winio.c
@@ -187,6 +187,9 @@ void nanoget_repaint(const char *buf, const char *inputbuf, int x)
 /* Get the input from the kb; this should only be called from
  * statusq(). */
 int nanogetstr(int allowtabs, const char *buf, const char *def,
+#ifndef NANO_SMALL
+		historyheadtype *history_list,
+#endif
 		const shortcut *s
 #ifndef DISABLE_TABCOMP
 		, int *list
@@ -202,6 +205,12 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
 	/* used by input_tab() */
     const shortcut *t;
 
+#ifndef NANO_SMALL
+   /* for history */
+    char *history = NULL;
+    char *complete = NULL;
+    int last_kbinput = 0;
+#endif
     xend = strlen(def);
     x = xend;
     answer = (char *)nrealloc(answer, xend + 1);
@@ -300,28 +309,74 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
 		xend--;
 	    }
 	    break;
-#ifndef DISABLE_TABCOMP
 	case NANO_CONTROL_I:
-	    if (allowtabs) {
-		int shift = 0;
+#ifndef NANO_SMALL
+	    /* tab history completion */
+	    if (history_list) {
+		if ((!complete) || (last_kbinput != NANO_CONTROL_I)) {
+		    history_list->current = (historytype *)history_list;
+		    history_list->len = strlen(answer);
+		}
 
-		answer = input_tab(answer, x, &tabbed, &shift, list);
-		xend = strlen(answer);
-		x += shift;
-		if (x > xend)
+		if (history_list->len) {
+		    complete = get_history_completion(history_list, answer);
+		    xend = strlen(complete);
 		    x = xend;
+		    answer = mallocstrcpy(answer, complete);
+		}
 	    }
-	    break;
+#ifndef DISABLE_TABCOMP
+	    else {
+#endif
 #endif
+#ifndef DISABLE_TABCOMP
+		if (allowtabs) {
+		    int shift = 0;
+
+		    answer = input_tab(answer, x, &tabbed, &shift, list);
+		    xend = strlen(answer);
+		    x += shift;
+		    if (x > xend)
+			x = xend;
+		}
+	    }
+#endif
+	    break;
 	case KEY_LEFT:
 	case NANO_BACK_KEY:
 	    if (x > 0)
 		x--;
 	    break;
 	case KEY_UP:
+#ifndef NANO_SMALL
+	    if (history_list) {
+		/* get older search from the history list */
+		if ((history = get_history_older(history_list))) {
+		    answer = mallocstrcpy(answer, history);
+		    xend = strlen(history);
+		} else {
+		    answer = mallocstrcpy(answer, "");
+		    xend = 0;
+		}
+		x = xend;
+	    }
+	    break;
+#endif
 	case KEY_DOWN:
+#ifndef NANO_SMALL
+	    if (history_list) {
+		/* get newer search from the history list */
+		if ((history = get_history_newer(history_list))) {
+		    answer = mallocstrcpy(answer, history);
+		    xend = strlen(history);
+		} else {
+		    answer = mallocstrcpy(answer, "");
+		    xend = 0;
+		}
+		x = xend;
+	    }
+#endif
 	    break;
-
 	case KEY_DC:
 	    goto do_deletekey;
 
@@ -400,7 +455,8 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
 #ifdef DEBUG
 	    fprintf(stderr, _("input \'%c\' (%d)\n"), kbinput, kbinput);
 #endif
-	}
+	} /* switch (kbinput) */
+	last_kbinput = kbinput;
 	nanoget_repaint(buf, answer, x);
 	wrefresh(bottomwin);
     } /* while (kbinput ...) */
@@ -496,11 +552,13 @@ void bottombars(const shortcut *s)
 	    wmove(bottomwin, 1 + j, i * (COLS / numcols));
 
 #ifndef NANO_SMALL
+	    /* Yucky sentinel values we can't handle a better way */
 	    if (s->val == NANO_CONTROL_SPACE)
 		strcpy(keystr, "^ ");
-	    else
-#endif /* !NANO_SMALL */
-	    if (s->val > 0) {
+	    else if (s->val == KEY_UP)
+		strcpy(keystr, _("Up"));
+#endif /* NANO_SMALL */
+	    else if (s->val > 0) {
 		if (s->val < 64)
 		    sprintf(keystr, "^%c", s->val + 64);
 		else
@@ -526,6 +584,7 @@ void bottombars(const shortcut *s)
  * very small and keystroke and desc are long. */
 void onekey(const char *keystroke, const char *desc, int len)
 {
+
     wattron(bottomwin, A_REVERSE);
     waddnstr(bottomwin, keystroke, len);
     wattroff(bottomwin, A_REVERSE);
@@ -911,8 +970,8 @@ void update_line(filestruct *fileptr, int index)
 
     original = fileptr->data;
     converted = charalloc(strlenpt(original) + 1);
-    
-    /* Next, convert all the tabs to spaces, so everything else is easy. 
+
+    /* Next, convert all the tabs to spaces, so everything else is easy.
      * Note the internal speller sends us index == -1. */
     index = fileptr == current && index > 0 ? strnlenpt(original, index) : 0;
 #ifndef NANO_SMALL
@@ -1070,6 +1129,9 @@ void edit_update(filestruct *fileptr, topmidbotnone location)
  * New arg tabs tells whether or not to allow tab completion.
  */
 int statusq(int tabs, const shortcut *s, const char *def,
+#ifndef NANO_SMALL
+		historyheadtype *which_history,
+#endif
 		const char *msg, ...)
 {
     va_list ap;
@@ -1086,11 +1148,15 @@ int statusq(int tabs, const shortcut *s, const char *def,
     va_end(ap);
     foo[COLS - 4] = '\0';
 
+    ret = nanogetstr(tabs, foo, def,
+#ifndef NANO_SMALL
+		which_history,
+#endif
+		s
 #ifndef DISABLE_TABCOMP
-    ret = nanogetstr(tabs, foo, def, s, &list);
-#else
-    ret = nanogetstr(tabs, foo, def, s);
+		, &list
 #endif
+		);
     free(foo);
 
     switch (ret) {