]> git.wh0rd.org Git - nano.git/commitdiff
overhaul the history code to work more consistently, and clean up
authorDavid Lawrence Ramsey <pooka109@gmail.com>
Mon, 23 May 2005 16:30:06 +0000 (16:30 +0000)
committerDavid Lawrence Ramsey <pooka109@gmail.com>
Mon, 23 May 2005 16:30:06 +0000 (16:30 +0000)
various parts of it; note that history tab completion has been removed

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2533 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

ChangeLog
src/files.c
src/global.c
src/nano.h
src/proto.h
src/search.c
src/winio.c

index d0d3cfbd08d034fcc71aab4d17a9cb2c33c30f97..0a5fba7866fdf474eefb9faf058df59eb4f26fff 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -20,6 +20,15 @@ CVS code -
          do_gotolinecolumn()), do_gotoline_void() (renamed
          do_gotolinecolumn_void()), nano.1, and nano.texi. (DLR,
          suggested by PFTank)
+       - Overhaul the history code to work more consistently, and clean
+         up various parts of it.  Note that history tab completion has
+         been removed.  New function history_has_changed(); changes to
+         load_history(), writehist(), thanks_for_all_the_fish(),
+         history_init(), find_node() (renamed find_history()),
+         update_history(), get_history_older(), get_history_newer(),
+         do_search(), do_replace(), nanogetstr(), and statusq();
+         removal of remove_node(), insert_node(), and
+         get_history_completion(). (DLR)
 - cut.c:
   cut_line()
        - Set placewewant properly after cutting a line, to avoid a
index bd5ebb88ed0ae14b22b2f6b4e82f1df6dc6912a8..c7a1502ee90234e00de8439dfb7275003bc892f6 100644 (file)
@@ -2866,7 +2866,12 @@ void load_history(void)
                    ;
            }
        } else {
-           historyheadtype *history = &search_history;
+           /* Load a history (first the search history, then the
+            * replace history) from oldest to newest.  Assume the last
+            * history entry is a blank line. */
+           filestruct **history = &search_history;
+           filestruct **historyage = &searchage;
+           filestruct **historybot = &searchbot;
            char *line = NULL;
            size_t buflen = 0;
            ssize_t read;
@@ -2878,31 +2883,38 @@ void load_history(void)
                }
                if (read > 0) {
                    unsunder(line, read);
-                   update_history(history, line);
-               } else
+                   update_history(history, historyage, historybot,
+                       line);
+               } else {
                    history = &replace_history;
+                   historyage = &replaceage;
+                   historybot = &replacebot;
+               }
            }
+
            fclose(hist);
            free(line);
-           UNSET(HISTORY_CHANGED);
        }
        free(nanohist);
     }
 }
 
-bool writehist(FILE *hist, historyheadtype *histhead)
+bool writehist(FILE *hist, filestruct *h)
 {
-    historytype *p;
+    filestruct *p;
 
-    /* Write oldest history first. */
-    for (p = histhead->tail; p->prev != NULL; p = p->prev) {
+    /* Write history from oldest to newest.  Assume the last history
+     * entry is a blank line. */
+    for (p = h; p != NULL; p = p->next) {
        size_t p_len = strlen(p->data);
 
        sunder(p->data);
+
        if (fwrite(p->data, sizeof(char), p_len, hist) < p_len ||
                putc('\n', hist) == EOF)
            return FALSE;
     }
+
     return TRUE;
 }
 
@@ -2912,8 +2924,8 @@ void save_history(void)
     char *nanohist;
 
     /* Don't save unchanged or empty histories. */
-    if (!ISSET(HISTORY_CHANGED) || (search_history.count == 0 &&
-       replace_history.count == 0))
+    if (!history_has_changed() || (searchbot->lineno == 1 &&
+       replacebot->lineno == 1))
        return;
 
     nanohist = histfilename();
@@ -2929,13 +2941,14 @@ void save_history(void)
             * history file. */
            chmod(nanohist, S_IRUSR | S_IWUSR);
 
-           if (!writehist(hist, &search_history) ||
-                   putc('\n', hist) == EOF ||
-                   !writehist(hist, &replace_history))
+           if (!writehist(hist, searchage) || !writehist(hist,
+               replaceage))
                rcfile_error(N_("Error writing %s: %s"), nanohist,
                        strerror(errno));
+
            fclose(hist);
        }
+
        free(nanohist);
     }
 }
index e71183a8a1afd09468e8680c341b13db0aba6831..2134881ddca2ee08420084b931aa031e568cab7d 100644 (file)
@@ -168,8 +168,12 @@ toggle *toggles = NULL;
 #endif
 
 #ifndef NANO_SMALL
-historyheadtype search_history;
-historyheadtype replace_history;
+filestruct *search_history = NULL;
+filestruct *searchage = NULL;
+filestruct *searchbot = NULL;
+filestruct *replace_history = NULL;
+filestruct *replaceage = NULL;
+filestruct *replacebot = NULL;
 #endif
 
 /* Regular expressions */
@@ -1260,8 +1264,8 @@ void thanks_for_all_the_fish(void)
 #endif /* ENABLE_COLOR */
 #ifndef NANO_SMALL
     /* Free the history lists. */
-    free_history(&search_history);
-    free_history(&replace_history);
+    free_filestruct(searchage);
+    free_filestruct(replaceage);
 #endif
 #ifdef ENABLE_NANORC
     free(homedir);
index d86a41de0a965a9a97ff4144b82dc7430f60abd2..e6efdcbfa27cfa60c1043c6ad6678dfaf0e26a4c 100644 (file)
@@ -265,25 +265,6 @@ typedef struct syntaxtype {
 } syntaxtype;
 #endif
 
-#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 the same order as in
-                                * historytype. */
-    struct historytype *tail;
-    struct historytype *current;
-    int count;
-    int len;
-} historyheadtype;
-#endif
-
 /* Bitwise flags so that we can save space (or, more correctly, not
  * waste it). */
 #define MODIFIED               (1<<0)
@@ -310,13 +291,12 @@ typedef struct historyheadtype {
 #define NO_RCFILE              (1<<21)
 #define NO_COLOR_SYNTAX                (1<<22)
 #define PRESERVE               (1<<23)
-#define HISTORY_CHANGED                (1<<24)
-#define HISTORYLOG             (1<<25)
-#define RESTRICTED             (1<<26)
-#define SMART_HOME             (1<<27)
-#define WHITESPACE_DISPLAY     (1<<28)
-#define MORE_SPACE             (1<<29)
-#define NO_UTF8                        (1<<30)
+#define HISTORYLOG             (1<<24)
+#define RESTRICTED             (1<<25)
+#define SMART_HOME             (1<<26)
+#define WHITESPACE_DISPLAY     (1<<27)
+#define MORE_SPACE             (1<<28)
+#define NO_UTF8                        (1<<29)
 
 /* Control key sequences.  Changing these would be very, very bad. */
 #define NANO_CONTROL_SPACE 0
@@ -518,7 +498,8 @@ typedef struct historyheadtype {
 /* Default width of a tab. */
 #define WIDTH_OF_TAB 8
 
-/* Maximum number of search/replace history strings saved. */
+/* Maximum number of search/replace history strings saved, not counting
+ * the blank lines at their ends. */
 #define MAX_SEARCH_HISTORY 100
 
 /* Maximum number of bytes we read from a file at one time. */
index 775a6c0ef3d376c19518ea499bd37fde1bfdb768..abdb350216fe762f7da645ddf8d3f8f2b3e47f94 100644 (file)
@@ -144,8 +144,12 @@ extern toggle *toggles;
 #endif
 
 #ifndef NANO_SMALL
-extern historyheadtype search_history;
-extern historyheadtype replace_history;
+extern filestruct *search_history;
+extern filestruct *searchage;
+extern filestruct *searchbot;
+extern filestruct *replace_history;
+extern filestruct *replaceage;
+extern filestruct *replacebot;
 #endif
 
 extern bool curses_ended;
@@ -316,7 +320,7 @@ char *do_browse_from(const char *inpath);
 #if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
 char *histfilename(void);
 void load_history(void);
-bool writehist(FILE *hist, historyheadtype *histhead);
+bool writehist(FILE *hist, filestruct *histhead);
 void save_history(void);
 #endif
 
@@ -524,17 +528,13 @@ void do_gotopos(int line, size_t pos_x, int pos_y, size_t pos_pww);
 #endif
 void do_find_bracket(void);
 #ifndef NANO_SMALL
+bool history_has_changed(void);
 void history_init(void);
-historytype *find_node(historytype *h, const char *s);
-void remove_node(historytype *r);
-void insert_node(historytype *h, const char *s);
-void update_history(historyheadtype *h, const char *s);
-char *get_history_older(historyheadtype *h);
-char *get_history_newer(historyheadtype *h);
-char *get_history_completion(historyheadtype *h, char *s);
-#ifdef DEBUG
-void free_history(historyheadtype *h);
-#endif
+filestruct *find_history(filestruct *h, const char *s);
+void update_history(filestruct **h, filestruct **hage, filestruct
+       **hbot, const char *s);
+char *get_history_older(filestruct **h);
+char *get_history_newer(filestruct **h);
 #endif
 
 /* Public functions in utils.c. */
@@ -652,7 +652,7 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
 void nanoget_repaint(const char *buf, const char *inputbuf, size_t x);
 int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
 #ifndef NANO_SMALL
-       historyheadtype *history_list,
+       filestruct *history_list,
 #endif
        const shortcut *s
 #ifndef DISABLE_TABCOMP
@@ -661,7 +661,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
        );
 int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
 #ifndef NANO_SMALL
-       historyheadtype *history_list,
+       filestruct *history_list,
 #endif
        const char *msg, ...);
 void statusq_abort(void);
index 9b907d0b1deab05f1f467d8d7cecf7095ce7842e..bb798cfc334300409b31bb058505c7894da8927f 100644 (file)
 
 static bool search_last_line = FALSE;
        /* Have we gone past the last line while searching? */
+#ifndef NANO_SMALL
+static bool history_changed = FALSE;
+       /* Have any of the history lists changed? */
+#endif
 #ifdef HAVE_REGEX_H
 static bool regexp_compiled = FALSE;
        /* Have we compiled any regular expressions? */
@@ -145,10 +149,6 @@ int search_init(bool replacing, bool use_answer)
 
     search_init_globals();
 
-#ifndef NANO_SMALL
-    search_history.current = (historytype *)&search_history.next;
-#endif
-
     if (last_search[0] != '\0') {
        char *disp = display_string(last_search, 0, COLS / 3, FALSE);
 
@@ -165,7 +165,7 @@ int search_init(bool replacing, bool use_answer)
     i = statusq(FALSE, replacing ? replace_list : whereis_list,
        backupstring,
 #ifndef NANO_SMALL
-       &search_history,
+       search_history,
 #endif
        "%s%s%s%s%s%s", _("Search"),
 
@@ -212,9 +212,6 @@ int search_init(bool replacing, bool use_answer)
     if (i == -1 || (i < 0 && last_search[0] == '\0') ||
            (!replacing && i == 0 && answer[0] == '\0')) {
        statusbar(_("Cancelled"));
-#ifndef NANO_SMALL
-       search_history.current = search_history.next;
-#endif
        return -1;
     } else {
        switch (i) {
@@ -252,9 +249,6 @@ int search_init(bool replacing, bool use_answer)
                backupstring = mallocstrcpy(backupstring, answer);
                return -2;      /* Call the opposite search function. */
            case NANO_TOGOTOLINE_KEY:
-#ifndef NANO_SMALL
-               search_history.current = search_history.next;
-#endif
                do_gotolinecolumn(current->lineno, placewewant, TRUE,
                        TRUE, FALSE);
                                /* Put answer up on the statusbar and
@@ -481,7 +475,7 @@ void do_search(void)
     /* If answer is not "", add this search string to the search history
      * list. */
     if (answer[0] != '\0')
-       update_history(&search_history, answer);
+       update_history(&search_history, &searchage, &searchbot, answer);
 #endif
 
     findnextstr_wrap_reset();
@@ -910,19 +904,14 @@ void do_replace(void)
      * copy answer into last_search. */
     if (answer[0] != '\0') {
 #ifndef NANO_SMALL
-       update_history(&search_history, answer);
+       update_history(&search_history, &searchage, &searchbot, answer);
 #endif
        last_search = mallocstrcpy(last_search, answer);
     }
 
-#ifndef NANO_SMALL
-    replace_history.current = (historytype *)&replace_history.next;
-    last_replace = mallocstrcpy(last_replace, "");
-#endif
-
     i = statusq(FALSE, replace_list_2, last_replace,
 #ifndef NANO_SMALL
-       &replace_history,
+       replace_history,
 #endif
        _("Replace with"));
 
@@ -930,7 +919,8 @@ void do_replace(void)
     /* Add this replace string to the replace history list.  i == 0
      * means that the string is not "". */
     if (i == 0)
-       update_history(&replace_history, answer);
+       update_history(&replace_history, &replaceage, &replacebot,
+               answer);
 #endif
 
     if (i != 0 && i != -2) {
@@ -1126,129 +1116,123 @@ void do_find_bracket(void)
 #endif
 
 #ifndef NANO_SMALL
-/*
- * search and replace history list support functions
- */
+/* Indicate whether any of the history lists have changed. */
+bool history_has_changed(void)
+{
+    return history_changed;
+}
 
-/* initialize search and replace history lists */
+/* Initialize the 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;
+    search_history = make_new_node(NULL);
+    search_history->data = mallocstrcpy(NULL, "");
+    searchage = search_history;
+    searchbot = search_history;
+
+    replace_history = make_new_node(NULL);
+    replace_history->data = mallocstrcpy(NULL, "");
+    replaceage = replace_history;
+    replacebot = replace_history;
 }
 
-/* find first node containing string *s in history list *h */
-historytype *find_node(historytype *h, const char *s)
+/* Return the first node containing the string s in the history list,
+ * starting at h, or NULL if there isn't one. */
+filestruct *find_history(filestruct *h, const char *s)
 {
+    assert(h != NULL);
+
     for (; h->next != NULL; h = h->next) {
        if (strcmp(s, h->data) == 0)
            return h;
     }
+
     return NULL;
 }
 
-/* remove node *r */
-void remove_node(historytype *r)
+/* Update a history list.  h should be the current position in the list,
+ * hage should be the top of the list, and hbot should be the bottom of
+ * the list. */
+void update_history(filestruct **h, filestruct **hage, filestruct
+       **hbot, const char *s)
 {
-    r->prev->next = r->next;
-    r->next->prev = r->prev;
-    free(r->data);
-    free(r);
-}
+    filestruct *p;
 
-/* add a node after node *h */
-void insert_node(historytype *h, const char *s)
-{
-    historytype *a;
-
-    a = (historytype *)nmalloc(sizeof(historytype));
-    a->next = h->next;
-    a->prev = h;
-    h->next->prev = a;
-    h->next = a;
-    a->data = mallocstrcpy(NULL, s);
-}
+    assert(h != NULL && hage != NULL && hbot != NULL && s != NULL);
 
-/* update history list */
-void update_history(historyheadtype *h, const char *s)
-{
-    historytype *p;
-
-    if ((p = find_node(h->next, s)) != NULL) {
-       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++;
-    SET(HISTORY_CHANGED);
-  up_hs:
-    h->current = h->next;
-}
+    /* If this string is already in the history, delete it. */
+    p = find_history(*hage, s);
 
-/* return a pointer to either the next older history or NULL if no more */
-char *get_history_older(historyheadtype *h)
-{
-    if (h->current->next != NULL) {    /* any older entries? */
-       h->current = h->current->next;  /* yes */
-       return h->current->data;        /* return it */
+    if (p != NULL) {
+       filestruct *foo, *bar;
+
+       /* If the string is at the current position, don't do
+        * anything. */
+       if (p == *h)
+           return;
+
+       /* If the string is at the beginning, move the beginning down to
+        * the next string. */
+       if (p == *hage)
+           *hage = (*hage)->next;
+
+       /* Delete the string. */
+       foo = p;
+       bar = p->next;
+       unlink_node(foo);
+       delete_node(foo);
+       renumber(bar);
     }
-    return NULL;                       /* end of list */
-}
 
-char *get_history_newer(historyheadtype *h)
-{
-    if (h->current->prev != NULL) {
-       h->current = h->current->prev;
-       if (h->current->prev != NULL)
-           return h->current->data;
+    /* If the history is full, delete the beginning entry to make room
+     * for the new entry at the end. */
+    if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) {
+       filestruct *foo = *hage;
+
+       *hage = (*hage)->next;
+       unlink_node(foo);
+       delete_node(foo);
+       renumber(*hage);
     }
-    return NULL;
+
+    /* Add the new entry to the end. */
+    (*hbot)->data = mallocstrcpy(NULL, s);
+    splice_node(*hbot, make_new_node(*hbot), (*hbot)->next);
+    *hbot = (*hbot)->next;
+    (*hbot)->data = mallocstrcpy(NULL, "");
+
+    /* Indicate that the history's been changed. */
+    history_changed = TRUE;
+
+    /* Set the current position in the list to the bottom. */
+    *h = *hbot;
 }
 
-/* get a completion */
-char *get_history_completion(historyheadtype *h, char *s)
+/* Return the string in the history list just before h, or NULL if there
+ * isn't one. */
+char *get_history_older(filestruct **h)
 {
-    historytype *p;
+    assert(h != NULL);
 
-    for (p = h->current->next; p->next != NULL; 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;
+    if ((*h)->prev == NULL)
+       return NULL;
+
+    *h = (*h)->prev;
+
+    return (*h)->data;
 }
 
-#ifdef DEBUG
-/* free a history list */
-void free_history(historyheadtype *h)
+/* Return the string in the history list just after h, or NULL if there
+ * isn't one. */
+char *get_history_newer(filestruct **h)
 {
-    historytype *p;
+    assert(h != NULL);
 
-    for (p = h->next; p->next != NULL; p = p->next)
-       remove_node(p);
-}
-#endif
+    if ((*h)->next == NULL)
+       return NULL;
 
-/* end of history support functions */
+    *h = (*h)->next;
+
+    return (*h)->data;
+}
 #endif /* !NANO_SMALL */
index c3850883bed5418137a7e2a98201a3bf5fce53d8..96f56cff36d19510238c6b30dacc57e164f9d860 100644 (file)
@@ -2430,7 +2430,7 @@ void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
  * statusq(). */
 int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
 #ifndef NANO_SMALL
-       historyheadtype *history_list,
+       filestruct *history_list,
 #endif
        const shortcut *s
 #ifndef DISABLE_TABCOMP
@@ -2443,23 +2443,15 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
     size_t answer_len = strlen(curranswer);
 #ifndef DISABLE_TABCOMP
     bool tabbed = FALSE;
-       /* Used by input_tab(). */
+       /* Whether we've pressed Tab more than once consecutively. */
 #endif
 
 #ifndef NANO_SMALL
-    /* For history. */
     char *history = NULL;
-    char *currentbuf = NULL;
-    char *complete = NULL;
-    int last_kbinput = 0;
-
-    /* This variable is used in the search history code.  use_cb == 0
-     * means that we're using the existing history and ignoring
-     * currentbuf.  use_cb == 1 means that the entry in answer should be
-     * moved to currentbuf or restored from currentbuf to answer.
-     * use_cb == 2 means that the entry in currentbuf should be moved to
-     * answer or restored from answer to currentbuf. */
-    int use_cb = 0;
+       /* The current history string. */
+    char *magichistory = NULL;
+       /* The temporary string typed at the bottom of the history, if
+        * any. */
 #endif
 
     /* Only put statusbar_x at the end of the string if it's
@@ -2500,28 +2492,6 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
 
        switch (kbinput) {
            case NANO_TAB_KEY:
-#ifndef NANO_SMALL
-               /* Tab history completion. */
-               if (history_list != NULL) {
-                   if (complete == NULL ||
-                       last_kbinput != NANO_TAB_KEY) {
-                       history_list->current =
-                               (historytype *)history_list;
-                       history_list->len = strlen(answer);
-                   }
-
-                   if (history_list->len > 0) {
-                       complete = get_history_completion(history_list,
-                               answer);
-                       answer = mallocstrcpy(answer, complete);
-                       answer_len = strlen(answer);
-                       statusbar_x = answer_len;
-                   }
-               }
-#ifndef DISABLE_TABCOMP
-               else
-#endif
-#endif
 #ifndef DISABLE_TABCOMP
                if (allow_tabs) {
                    answer = input_tab(answer, &statusbar_x, &tabbed,
@@ -2533,43 +2503,23 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
            case NANO_PREVLINE_KEY:
 #ifndef NANO_SMALL
                if (history_list != NULL) {
-                   /* If currentbuf is NULL, or if use_cb is 1 and
-                    * currentbuf is different from answer, it means
-                    * that we're scrolling up at the top of the search
-                    * history, and we need to save the current answer
-                    * in currentbuf.  Do this and reset use_cb to 0. */
-                   if (currentbuf == NULL || (use_cb == 1 &&
-                       strcmp(currentbuf, answer) != 0)) {
-                       currentbuf = mallocstrcpy(currentbuf, answer);
-                       use_cb = 0;
-                   }
-
-                   /* If currentbuf isn't NULL, use_cb is 2, and
-                    * currentbuf is different from answer, it means
-                    * that we're scrolling up at the bottom of the
-                    * search history, and we need to restore the
-                    * current answer from currentbuf.  Do this, blow
-                    * away currentbuf since we don't need it anymore,
-                    * and reset use_cb to 0. */
-                   if (currentbuf != NULL && use_cb == 2 &&
-                       strcmp(currentbuf, answer) != 0) {
-                       answer = mallocstrcpy(answer, currentbuf);
-                       answer_len = strlen(answer);
-                       free(currentbuf);
-                       currentbuf = NULL;
-                       use_cb = 0;
-                   /* Otherwise, get the older search from the history
-                    * list and save it in answer.  If there is no older
-                    * search, blank out answer. */
-                   } else if ((history =
-                       get_history_older(history_list)) != NULL) {
+                   /* If we're scrolling up at the bottom of the
+                    * history list, answer isn't blank, and
+                    * magichistory isn't set, save answer in
+                    * magichistory. */
+                   if (history_list->next == NULL &&
+                       answer[0] != '\0' && magichistory == NULL)
+                       magichistory = mallocstrcpy(NULL, answer);
+
+                   /* Get the older search from the history list and
+                    * save it in answer.  If there is no older search,
+                    * don't do anything. */
+                   if ((history =
+                       get_history_older(&history_list)) != NULL) {
                        answer = mallocstrcpy(answer, history);
-                       answer_len = strlen(history);
-                   } else {
-                       answer = mallocstrcpy(answer, "");
-                       answer_len = 0;
+                       answer_len = strlen(answer);
+                       statusbar_x = answer_len;
                    }
-                   statusbar_x = answer_len;
 
                    /* This key has a shortcut list entry when it's used
                     * to move to an older search, which means that
@@ -2584,39 +2534,25 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
 #ifndef NANO_SMALL
                if (history_list != NULL) {
                    /* Get the newer search from the history list and
-                    * save it in answer. */
+                    * save it in answer.  If there is no newer search,
+                    * don't do anything. */
                    if ((history =
-                       get_history_newer(history_list)) != NULL) {
+                       get_history_newer(&history_list)) != NULL) {
                        answer = mallocstrcpy(answer, history);
-                       answer_len = strlen(history);
-                   /* If currentbuf isn't NULL and use_cb isn't 2, it
-                    * means that we're scrolling down at the bottom of
-                    * the search history and we need to restore the
-                    * current answer from currentbuf.  Do this, blow
-                    * away currentbuf since we don't need it anymore,
-                    * and set use_cb to 1. */
-                   } else if (currentbuf != NULL && use_cb != 2) {
-                       answer = mallocstrcpy(answer, currentbuf);
                        answer_len = strlen(answer);
-                       free(currentbuf);
-                       currentbuf = NULL;
-                       use_cb = 1;
-                   /* Otherwise, if currentbuf is NULL and use_cb isn't
-                    * 2, it means that we're scrolling down at the
-                    * bottom of the search history and we need to save
-                    * the current answer (if it's not blank) in
-                    * currentbuf.  Do this, blank out answer, and set
-                    * use_cb to 2. */
-                   } else if (use_cb != 2) {
-                       if (answer[0] != '\0') {
-                           currentbuf = mallocstrcpy(currentbuf,
-                               answer);
-                           answer = mallocstrcpy(answer, "");
-                       }
-                       answer_len = 0;
-                       use_cb = 2;
+                       statusbar_x = answer_len;
+                   }
+
+                   /* If, after scrolling down, we're at the bottom of
+                    * the history list, answer is blank, and
+                    * magichistory is set, save magichistory in
+                    * answer. */
+                   if (history_list->next == NULL &&
+                       answer[0] == '\0' && magichistory != NULL) {
+                       answer = mallocstrcpy(answer, magichistory);
+                       answer_len = strlen(answer);
+                       statusbar_x = answer_len;
                    }
-                   statusbar_x = answer_len;
                }
 #endif
                break;
@@ -2628,9 +2564,6 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
        if (finished)
            break;
 
-#ifndef NANO_SMALL
-       last_kbinput = kbinput;
-#endif
        nanoget_repaint(buf, answer, statusbar_x);
        wrefresh(bottomwin);
     }
@@ -2653,7 +2586,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
  * completion. */
 int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
 #ifndef NANO_SMALL
-       historyheadtype *history_list,
+       filestruct *history_list,
 #endif
        const char *msg, ...)
 {