From 5beed509a66de125f95d8ef0dabc92910df6e936 Mon Sep 17 00:00:00 2001 From: Chris Allegretta Date: Sun, 5 Jan 2003 20:41:21 +0000 Subject: [PATCH] Ken's search history patch, minus the .nano_history stuff git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1334 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 8 ++ files.c | 36 ++++----- global.c | 33 +++++++- nano.c | 13 +++- nano.h | 25 ++++++ proto.h | 23 ++++++ rcfile.c | 9 ++- search.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++----- winio.c | 106 ++++++++++++++++++++----- 9 files changed, 418 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index 04915755..fcd1a855 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 719bd960..e37935db 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 5ffaa9f6..b9a09bd3 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 cbe94ecb..e8de005c 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 70581c56..ca8a5d73 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 51388a17..01278bf1 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 24994087..234bb1c2 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 115b9a64..80b0a4a7 100644 --- a/search.c +++ b/search.c @@ -26,10 +26,17 @@ #include #include #include +#include #include #include "proto.h" #include "nano.h" +#ifndef NANO_SMALL +#ifdef ENABLE_NANORC +#include +#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 e15b4b43..d6d74304 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: - case KEY_DOWN: +#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'; -#ifndef DISABLE_TABCOMP - ret = nanogetstr(tabs, foo, def, s, &list); -#else - ret = nanogetstr(tabs, foo, def, s); + ret = nanogetstr(tabs, foo, def, +#ifndef NANO_SMALL + which_history, #endif + s +#ifndef DISABLE_TABCOMP + , &list +#endif + ); free(foo); switch (ret) {