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
This commit is contained in:
Chris Allegretta 2003-01-05 20:41:21 +00:00
parent 95e0cf584c
commit 5beed509a6
9 changed files with 418 additions and 62 deletions

View File

@ -1,5 +1,11 @@
CVS code - CVS code -
Changes
- General: - 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). - Translation updates (see po/ChangeLog for details).
- Forward-ported Chris' --disable-wrapping-as-root option from - Forward-ported Chris' --disable-wrapping-as-root option from
1.0.9. Per Jordi's suggestions, have it override 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 - 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) mark is on; otherwise, the highlight won't be displayed. (DLR)
- nano.c: - nano.c:
- Added free_history list calls clean up, added init of list headers
modified statusq calls (Ken Tyler).
do_prev_word() do_prev_word()
- Make the assert match that in do_next_word(). (DLR) - Make the assert match that in do_next_word(). (DLR)
do_enter() do_enter()

36
files.c
View File

@ -426,21 +426,21 @@ int do_insertfile(int loading_file)
if (operating_dir != NULL && strcmp(operating_dir, ".") != 0) if (operating_dir != NULL && strcmp(operating_dir, ".") != 0)
#ifdef ENABLE_MULTIBUFFER #ifdef ENABLE_MULTIBUFFER
if (ISSET(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); operating_dir);
else else
#endif #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); operating_dir);
else else
#endif #endif
#ifdef ENABLE_MULTIBUFFER #ifdef ENABLE_MULTIBUFFER
if (ISSET(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 else
#endif #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) { if (i != -1) {
inspath = mallocstrcpy(inspath, answer); inspath = mallocstrcpy(inspath, answer);
@ -492,7 +492,7 @@ int do_insertfile(int loading_file)
#endif /* ENABLE_MULTIBUFFER */ #endif /* ENABLE_MULTIBUFFER */
if (i == NANO_EXTCMD_KEY) { if (i == NANO_EXTCMD_KEY) {
int ts; 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') { if (ts == -1 || answer == NULL || answer[0] == '\0') {
statusbar(_("Cancelled")); statusbar(_("Cancelled"));
UNSET(KEEP_CUTBUFFER); UNSET(KEEP_CUTBUFFER);
@ -1711,34 +1711,34 @@ int do_writeout(const char *path, int exiting, int append)
/* Be nice to the translation folks */ /* Be nice to the translation folks */
if (ISSET(MARK_ISSET) && !exiting) { if (ISSET(MARK_ISSET) && !exiting) {
if (append == 2) if (append == 2)
i = statusq(1, writefile_list, "", i = statusq(1, writefile_list, "", 0,
"%s%s%s", _("Prepend Selection to File"), formatstr, backupstr); "%s%s%s", _("Prepend Selection to File"), formatstr, backupstr);
else if (append == 1) else if (append)
i = statusq(1, writefile_list, "", i = statusq(1, writefile_list, "", 0,
"%s%s%s", _("Append Selection to File"), formatstr, backupstr); "%s%s%s", _("Append Selection to File"), formatstr, backupstr);
else else
i = statusq(1, writefile_list, "", i = statusq(1, writefile_list, "", 0,
"%s%s%s", _("Write Selection to File"), formatstr, backupstr); "%s%s%s", _("Write Selection to File"), formatstr, backupstr);
} else { } else {
if (append == 2) 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); "%s%s%s", _("File Name to Prepend to"), formatstr, backupstr);
else if (append == 1) else if (append)
i = statusq(1, writefile_list, answer, i = statusq(1, writefile_list, answer, 0,
"%s%s%s", _("File Name to Append to"), formatstr, backupstr); "%s%s%s", _("File Name to Append to"), formatstr, backupstr);
else else
i = statusq(1, writefile_list, answer, i = statusq(1, writefile_list, answer, 0,
"%s%s%s", _("File Name to Write"), formatstr, backupstr); "%s%s%s", _("File Name to Write"), formatstr, backupstr);
} }
#else #else
if (append == 2) if (append == 2)
i = statusq(1, writefile_list, answer, i = statusq(1, writefile_list, answer, 0,
"%s", _("File Name to Prepend to")); "%s", _("File Name to Prepend to"));
else if (append == 1) else if (append)
i = statusq(1, writefile_list, answer, i = statusq(1, writefile_list, answer, 0,
"%s", _("File Name to Append to")); "%s", _("File Name to Append to"));
else else
i = statusq(1, writefile_list, answer, i = statusq(1, writefile_list, answer, 0,
"%s", _("File Name to Write")); "%s", _("File Name to Write"));
#endif /* !NANO_SMALL */ #endif /* !NANO_SMALL */
@ -2650,7 +2650,7 @@ char *do_browser(const char *inpath)
case NANO_GOTO_KEY: case NANO_GOTO_KEY:
curs_set(1); curs_set(1);
j = statusq(0, gotodir_list, "", _("Goto Directory")); j = statusq(0, gotodir_list, "", 0, _("Goto Directory"));
bottombars(browser_list); bottombars(browser_list);
curs_set(0); curs_set(0);

View File

@ -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_search = NULL; /* Last string we searched for */
char *last_replace = NULL; /* Last replacement string */ char *last_replace = NULL; /* Last replacement string */
int search_last_line; /* Is this the last search line? */ 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 */ int flags = 0; /* Our new flag containing many options */
WINDOW *edit; /* The file portion of the editor */ WINDOW *edit; /* The file portion of the editor */
@ -134,6 +135,11 @@ const shortcut *currshortcut; /* Current shortcut list we're using */
toggle *toggles = NULL; toggle *toggles = NULL;
#endif #endif
#ifndef NANO_SMALL
historyheadtype search_history;
historyheadtype replace_history;
#endif
/* Regular expressions */ /* Regular expressions */
#ifdef HAVE_REGEX_H #ifdef HAVE_REGEX_H
@ -327,7 +333,7 @@ void shortcut_init(int unjustify)
"", *nano_gotodir_msg = "", *nano_case_msg = "", *nano_gotodir_msg = "", *nano_case_msg =
"", *nano_reverse_msg = "", *nano_execute_msg = "", *nano_reverse_msg = "", *nano_execute_msg =
"", *nano_dos_msg = "", *nano_mac_msg = "", *nano_dos_msg = "", *nano_mac_msg =
"", *nano_backup_msg = ""; "", *nano_backup_msg = "", *nano_editstr_msg = "";
#ifdef ENABLE_MULTIBUFFER #ifdef ENABLE_MULTIBUFFER
const char *nano_openprev_msg = "", *nano_opennext_msg = 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_dos_msg = _("Write file out in DOS format");
nano_mac_msg = _("Write file out in Mac format"); nano_mac_msg = _("Write file out in Mac format");
nano_backup_msg = _("Back up original file when saving"); nano_backup_msg = _("Back up original file when saving");
nano_editstr_msg = _("Edit the previous search/replace strings");
#ifdef HAVE_REGEX_H #ifdef HAVE_REGEX_H
nano_regexp_msg = _("Use regular expressions"); nano_regexp_msg = _("Use regular expressions");
nano_bracket_msg = _("Find other bracket"); nano_bracket_msg = _("Find other bracket");
@ -606,6 +613,14 @@ void shortcut_init(int unjustify)
sc_init_one(&whereis_list, TOGGLE_REGEXP_KEY, _("Regexp"), sc_init_one(&whereis_list, TOGGLE_REGEXP_KEY, _("Regexp"),
IFHELP(nano_regexp_msg, 0), 0, 0, VIEW, 0); IFHELP(nano_regexp_msg, 0), 0, 0, VIEW, 0);
#endif #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 */ #endif /* !NANO_SMALL */
free_shortcutage(&replace_list); free_shortcutage(&replace_list);
@ -639,6 +654,12 @@ void shortcut_init(int unjustify)
sc_init_one(&replace_list, TOGGLE_REGEXP_KEY, _("Regexp"), sc_init_one(&replace_list, TOGGLE_REGEXP_KEY, _("Regexp"),
IFHELP(nano_regexp_msg, 0), 0, 0, VIEW, 0); IFHELP(nano_regexp_msg, 0), 0, 0, VIEW, 0);
#endif #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 */ #endif /* !NANO_SMALL */
free_shortcutage(&replace_list_2); 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"), sc_init_one(&replace_list_2, NANO_LASTLINE_KEY, _("Last Line"),
IFHELP(nano_lastline_msg, 0), 0, 0, VIEW, do_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); free_shortcutage(&goto_list);
sc_init_one(&goto_list, NANO_HELP_KEY, _("Get Help"), sc_init_one(&goto_list, NANO_HELP_KEY, _("Get Help"),
@ -885,5 +911,10 @@ void thanks_for_all_the_fish(void)
free(bill); free(bill);
} }
#endif /* ENABLE_COLOR */ #endif /* ENABLE_COLOR */
#ifndef NANO_SMALL
/* free history lists */
free_history(&search_history);
free_history(&replace_history);
#endif
} }
#endif /* DEBUG */ #endif /* DEBUG */

13
nano.c
View File

@ -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 */ /* What we do when we're all set to exit */
RETSIGTYPE finish(int sigage) RETSIGTYPE finish(int sigage)
{ {
#ifndef NANO_SMALL
free_history(&search_history);
free_history(&replace_history);
#endif
keypad(edit, TRUE); keypad(edit, TRUE);
keypad(bottomwin, TRUE); keypad(bottomwin, TRUE);
@ -1633,7 +1639,7 @@ int do_int_spell_fix(const char *word)
do_replace_highlight(TRUE, word); do_replace_highlight(TRUE, word);
/* allow replace word to be corrected */ /* 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); do_replace_highlight(FALSE, word);
@ -3093,6 +3099,7 @@ int main(int argc, char *argv[])
#endif #endif
} }
} }
if (!ISSET(NO_RCFILE)) if (!ISSET(NO_RCFILE))
do_rcfile(); do_rcfile();
#else #else
@ -3334,6 +3341,10 @@ int main(int argc, char *argv[])
keypad(bottomwin, TRUE); keypad(bottomwin, TRUE);
} }
#ifndef NANO_SMALL
history_init();
#endif
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
do_colorinit(); do_colorinit();
#endif /* ENABLE_COLOR */ #endif /* ENABLE_COLOR */

25
nano.h
View File

@ -90,6 +90,14 @@
#define KEY_END -1 #define KEY_END -1
#endif /* KEY_END */ #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 #define VERMSG "GNU nano " VERSION
#if defined(DISABLE_WRAPPING) && defined(DISABLE_JUSTIFY) #if defined(DISABLE_WRAPPING) && defined(DISABLE_JUSTIFY)
@ -190,6 +198,21 @@ typedef struct syntaxtype {
#endif /* ENABLE_COLOR */ #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) */ /* 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) */ /* Minimum fill length (space available for text before wrapping occurs) */
#define MIN_FILL_LENGTH 10 #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 */ #endif /* !NANO_H */

23
proto.h
View File

@ -40,6 +40,7 @@ extern long totsize;
extern int temp_opt; extern int temp_opt;
extern int wrap_at, flags, tabsize; extern int wrap_at, flags, tabsize;
extern int search_last_line; extern int search_last_line;
extern int past_editbuff;
extern int currslen; extern int currslen;
#ifndef DISABLE_JUSTIFY #ifndef DISABLE_JUSTIFY
@ -109,6 +110,11 @@ extern regmatch_t synfilematches[1];
extern toggle *toggles; extern toggle *toggles;
#endif #endif
#ifndef NANO_SMALL
extern historyheadtype search_history;
extern historyheadtype replace_history;
#endif
/* Functions we want available */ /* Functions we want available */
/* Public functions in color.c */ /* 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); void do_gotopos(int line, int pos_x, int pos_y, int pos_placewewant);
#endif #endif
int do_find_bracket(void); 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 */ /* Public functions in utils.c */
int is_cntrl_char(int c); int is_cntrl_char(int c);
@ -398,6 +415,9 @@ void blank_statusbar_refresh(void);
void check_statblank(void); void check_statblank(void);
void nanoget_repaint(const char *buf, const char *inputbuf, int x); void nanoget_repaint(const char *buf, const char *inputbuf, int x);
int nanogetstr(int allowtabs, const char *buf, const char *def, int nanogetstr(int allowtabs, const char *buf, const char *def,
#ifndef NANO_SMALL
historyheadtype *history_list,
#endif
const shortcut *s const shortcut *s
#ifndef DISABLE_TABCOMP #ifndef DISABLE_TABCOMP
, int *list , int *list
@ -426,6 +446,9 @@ void edit_refresh(void);
void edit_refresh_clearok(void); void edit_refresh_clearok(void);
void edit_update(filestruct *fileptr, topmidbotnone location); void edit_update(filestruct *fileptr, topmidbotnone location);
int statusq(int tabs, const shortcut *s, const char *def, int statusq(int tabs, const shortcut *s, const char *def,
#ifndef NANO_SMALL
historyheadtype *history_list,
#endif
const char *msg, ...); const char *msg, ...);
int do_yesno(int all, int leavecursor, const char *msg, ...); int do_yesno(int all, int leavecursor, const char *msg, ...);
int total_refresh(void); int total_refresh(void);

View File

@ -607,9 +607,10 @@ void do_rcfile(void)
lineno = 0; lineno = 0;
if (userage == NULL) if (userage == NULL) {
rcfile_error(_("I can't find my home directory! Wah!")); 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); nanorc = nrealloc(nanorc, strlen(userage->pw_dir) + 9);
sprintf(nanorc, "%s/.nanorc", userage->pw_dir); sprintf(nanorc, "%s/.nanorc", userage->pw_dir);
@ -621,9 +622,11 @@ void do_rcfile(void)
#endif #endif
if ((rcstream = fopen(nanorc, "r")) == NULL) { if ((rcstream = fopen(nanorc, "r")) == NULL) {
/* Don't complain about the file not existing */ /* Don't complain about the file not existing */
if (errno != ENOENT) if (errno != ENOENT) {
rcfile_error(_("Unable to open ~/.nanorc file, %s"), rcfile_error(_("Unable to open ~/.nanorc file, %s"),
strerror(errno)); strerror(errno));
SET(NO_RCFILE);
}
} else { } else {
parse_rcfile(rcstream); parse_rcfile(rcstream);
fclose(rcstream); fclose(rcstream);

227
search.c
View File

@ -26,10 +26,17 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h>
#include <assert.h> #include <assert.h>
#include "proto.h" #include "proto.h"
#include "nano.h" #include "nano.h"
#ifndef NANO_SMALL
#ifdef ENABLE_NANORC
#include <pwd.h>
#endif
#endif
static int past_editbuff; static int past_editbuff;
/* findnextstr() is now searching lines not displayed */ /* 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 /* 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 -> Return -2 to run opposite program (search -> replace, replace ->
search). search).
@ -110,24 +117,37 @@ int search_init(int replacing)
backupstring = NULL; backupstring = NULL;
UNSET(CLEAR_BACKUPSTRING); 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. 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 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. 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 Otherwise, if we don't already have a backupstring, set it to
last_search. */ last_search. */
#if 0
/* might need again ;)*/
if (ISSET(PICO_MODE)) { if (ISSET(PICO_MODE)) {
if (backupstring == NULL || !strcmp(backupstring, last_search)) { if (backupstring == NULL || !strcmp(backupstring, last_search)) {
/* backupstring = mallocstrcpy(backupstring, ""); */
backupstring = charalloc(1); backupstring = charalloc(1);
backupstring[0] = '\0'; backupstring[0] = '\0';
} }
} } else
else if (backupstring == NULL) #endif
if (backupstring == NULL)
#ifndef NANO_SMALL
backupstring = mallocstrcpy(backupstring, search_history.current->data);
#else
backupstring = mallocstrcpy(backupstring, last_search); 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 using Pico messages, we do things the old fashioned way... */
if (ISSET(PICO_MODE) && last_search[0] != '\0') { if (ISSET(PICO_MODE) && last_search[0] != '\0') {
buf = charalloc(COLS / 3 + 7); 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 */ /* This is now one simple call. It just does a lot */
i = statusq(0, replacing ? replace_list : whereis_list, backupstring, 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"), _("Search"),
/* This string is just a modifier for the search prompt, /* This string is just a modifier for the search prompt,
@ -168,6 +191,9 @@ int search_init(int replacing)
reset_cursor(); reset_cursor();
free(backupstring); free(backupstring);
backupstring = NULL; backupstring = NULL;
#ifndef NANO_SMALL
search_history.current = search_history.next;
#endif
return -1; return -1;
} else { } else {
switch (i) { switch (i) {
@ -210,7 +236,14 @@ int search_init(int replacing)
case NANO_FROMSEARCHTOGOTO_KEY: case NANO_FROMSEARCHTOGOTO_KEY:
free(backupstring); free(backupstring);
backupstring = NULL; 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; return -3;
default: default:
do_early_abort(); do_early_abort();
@ -301,7 +334,7 @@ filestruct *findnextstr(int quiet, int bracket_mode,
not_found_msg(needle); not_found_msg(needle);
return NULL; return NULL;
} }
} }
#ifndef NANO_SMALL #ifndef NANO_SMALL
else { /* reverse search */ else { /* reverse search */
current_x_find = current_x - 1; current_x_find = current_x - 1;
@ -403,6 +436,9 @@ int do_search(void)
/* The sneaky user deleted the previous search string */ /* The sneaky user deleted the previous search string */
if (!ISSET(PICO_MODE) && answer[0] == '\0') { if (!ISSET(PICO_MODE) && answer[0] == '\0') {
statusbar(_("Search Cancelled")); statusbar(_("Search Cancelled"));
#ifndef NANO_SMALL
search_history.current = search_history.next;
#endif
search_abort(); search_abort();
return 0; return 0;
} }
@ -415,6 +451,11 @@ int do_search(void)
else else
last_search = mallocstrcpy(last_search, answer); 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; search_last_line = 0;
didfind = findnextstr(FALSE, FALSE, current, current_x, answer); didfind = findnextstr(FALSE, FALSE, current, current_x, answer);
@ -697,6 +738,10 @@ int do_replace(void)
return 0; 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 */ /* Again, there was a previous string, but they deleted it and hit enter */
if (!ISSET(PICO_MODE) && answer[0] == '\0') { if (!ISSET(PICO_MODE) && answer[0] == '\0') {
statusbar(_("Replace Cancelled")); statusbar(_("Replace Cancelled"));
@ -710,6 +755,7 @@ int do_replace(void)
answer = mallocstrcpy(answer, last_search); answer = mallocstrcpy(answer, last_search);
else else
last_search = mallocstrcpy(last_search, answer); last_search = mallocstrcpy(last_search, answer);
prevanswer = mallocstrcpy(prevanswer, last_search); prevanswer = mallocstrcpy(prevanswer, last_search);
if (ISSET(PICO_MODE) && last_replace[0] != '\0') { if (ISSET(PICO_MODE) && last_replace[0] != '\0') {
@ -718,16 +764,34 @@ int do_replace(void)
strncpy(buf, last_replace, COLS / 3 - 1); strncpy(buf, last_replace, COLS / 3 - 1);
strcpy(buf + COLS / 3 - 1, "..."); strcpy(buf + COLS / 3 - 1, "...");
i = statusq(0, replace_list_2, "", _("Replace with [%s]"), i = statusq(0, replace_list_2, "",
buf); #ifndef NANO_SMALL
&replace_history,
#endif
_("Replace with [%s]"), buf);
free(buf); free(buf);
} else } else
i = statusq(0, replace_list_2, "", _("Replace with [%s]"), i = statusq(0, replace_list_2, "",
last_replace); #ifndef NANO_SMALL
} else &replace_history,
i = statusq(0, replace_list_2, last_replace, _("Replace with")); #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; begin = current;
beginx = current_x; beginx = current_x;
search_last_line = 0; search_last_line = 0;
@ -753,7 +817,7 @@ void goto_abort(void)
int do_gotoline(int line, int save_pos) int do_gotoline(int line, int save_pos)
{ {
if (line <= 0) { /* Ask for it */ 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")); statusbar(_("Aborted"));
goto_abort(); goto_abort();
return 0; return 0;
@ -780,9 +844,9 @@ int do_gotoline(int line, int save_pos)
edit_update(current, NONE); edit_update(current, NONE);
else else
edit_update(current, CENTER); edit_update(current, CENTER);
placewewant = 0; placewewant = 0;
goto_abort(); goto_abort();
blank_statusbar_refresh();
return 1; return 1;
} }
@ -820,7 +884,9 @@ int do_find_bracket(void)
filestruct *current_save; filestruct *current_save;
ch_under_cursor = current->data[current_x]; 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)) { if (((pos = strchr(brackets, ch_under_cursor)) == NULL) || (((offset = pos - brackets) < 8) == 0)) {
statusbar(_("Not a bracket")); statusbar(_("Not a bracket"));
return 1; return 1;
@ -880,3 +946,126 @@ int do_find_bracket(void)
return 0; return 0;
} }
#endif #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 */

106
winio.c
View File

@ -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 /* Get the input from the kb; this should only be called from
* statusq(). */ * statusq(). */
int nanogetstr(int allowtabs, const char *buf, const char *def, int nanogetstr(int allowtabs, const char *buf, const char *def,
#ifndef NANO_SMALL
historyheadtype *history_list,
#endif
const shortcut *s const shortcut *s
#ifndef DISABLE_TABCOMP #ifndef DISABLE_TABCOMP
, int *list , int *list
@ -202,6 +205,12 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
/* used by input_tab() */ /* used by input_tab() */
const shortcut *t; const shortcut *t;
#ifndef NANO_SMALL
/* for history */
char *history = NULL;
char *complete = NULL;
int last_kbinput = 0;
#endif
xend = strlen(def); xend = strlen(def);
x = xend; x = xend;
answer = (char *)nrealloc(answer, xend + 1); answer = (char *)nrealloc(answer, xend + 1);
@ -300,28 +309,74 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
xend--; xend--;
} }
break; break;
#ifndef DISABLE_TABCOMP
case NANO_CONTROL_I: case NANO_CONTROL_I:
if (allowtabs) { #ifndef NANO_SMALL
int shift = 0; /* 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); if (history_list->len) {
xend = strlen(answer); complete = get_history_completion(history_list, answer);
x += shift; xend = strlen(complete);
if (x > xend)
x = xend; x = xend;
answer = mallocstrcpy(answer, complete);
}
} }
break; #ifndef DISABLE_TABCOMP
else {
#endif #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 KEY_LEFT:
case NANO_BACK_KEY: case NANO_BACK_KEY:
if (x > 0) if (x > 0)
x--; x--;
break; break;
case KEY_UP: 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; break;
case KEY_DC: case KEY_DC:
goto do_deletekey; goto do_deletekey;
@ -400,7 +455,8 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, _("input \'%c\' (%d)\n"), kbinput, kbinput); fprintf(stderr, _("input \'%c\' (%d)\n"), kbinput, kbinput);
#endif #endif
} } /* switch (kbinput) */
last_kbinput = kbinput;
nanoget_repaint(buf, answer, x); nanoget_repaint(buf, answer, x);
wrefresh(bottomwin); wrefresh(bottomwin);
} /* while (kbinput ...) */ } /* while (kbinput ...) */
@ -496,11 +552,13 @@ void bottombars(const shortcut *s)
wmove(bottomwin, 1 + j, i * (COLS / numcols)); wmove(bottomwin, 1 + j, i * (COLS / numcols));
#ifndef NANO_SMALL #ifndef NANO_SMALL
/* Yucky sentinel values we can't handle a better way */
if (s->val == NANO_CONTROL_SPACE) if (s->val == NANO_CONTROL_SPACE)
strcpy(keystr, "^ "); strcpy(keystr, "^ ");
else else if (s->val == KEY_UP)
#endif /* !NANO_SMALL */ strcpy(keystr, _("Up"));
if (s->val > 0) { #endif /* NANO_SMALL */
else if (s->val > 0) {
if (s->val < 64) if (s->val < 64)
sprintf(keystr, "^%c", s->val + 64); sprintf(keystr, "^%c", s->val + 64);
else else
@ -526,6 +584,7 @@ void bottombars(const shortcut *s)
* very small and keystroke and desc are long. */ * very small and keystroke and desc are long. */
void onekey(const char *keystroke, const char *desc, int len) void onekey(const char *keystroke, const char *desc, int len)
{ {
wattron(bottomwin, A_REVERSE); wattron(bottomwin, A_REVERSE);
waddnstr(bottomwin, keystroke, len); waddnstr(bottomwin, keystroke, len);
wattroff(bottomwin, A_REVERSE); wattroff(bottomwin, A_REVERSE);
@ -911,8 +970,8 @@ void update_line(filestruct *fileptr, int index)
original = fileptr->data; original = fileptr->data;
converted = charalloc(strlenpt(original) + 1); 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. */ * Note the internal speller sends us index == -1. */
index = fileptr == current && index > 0 ? strnlenpt(original, index) : 0; index = fileptr == current && index > 0 ? strnlenpt(original, index) : 0;
#ifndef NANO_SMALL #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. * New arg tabs tells whether or not to allow tab completion.
*/ */
int statusq(int tabs, const shortcut *s, const char *def, int statusq(int tabs, const shortcut *s, const char *def,
#ifndef NANO_SMALL
historyheadtype *which_history,
#endif
const char *msg, ...) const char *msg, ...)
{ {
va_list ap; va_list ap;
@ -1086,11 +1148,15 @@ int statusq(int tabs, const shortcut *s, const char *def,
va_end(ap); va_end(ap);
foo[COLS - 4] = '\0'; foo[COLS - 4] = '\0';
#ifndef DISABLE_TABCOMP ret = nanogetstr(tabs, foo, def,
ret = nanogetstr(tabs, foo, def, s, &list); #ifndef NANO_SMALL
#else which_history,
ret = nanogetstr(tabs, foo, def, s);
#endif #endif
s
#ifndef DISABLE_TABCOMP
, &list
#endif
);
free(foo); free(foo);
switch (ret) { switch (ret) {