1
1

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
Этот коммит содержится в:
Chris Allegretta 2003-01-05 20:41:21 +00:00
родитель 95e0cf584c
Коммит 5beed509a6
9 изменённых файлов: 418 добавлений и 62 удалений

Просмотреть файл

@ -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
Просмотреть файл

@ -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);

Просмотреть файл

@ -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
Просмотреть файл

@ -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
Просмотреть файл

@ -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
Просмотреть файл

@ -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);

Просмотреть файл

@ -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);

215
search.c
Просмотреть файл

@ -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 */
@ -118,16 +125,29 @@ int search_init(int replacing)
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,6 +161,9 @@ 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,
#ifndef NANO_SMALL
&search_history,
#endif
"%s%s%s%s%s%s", "%s%s%s%s%s%s",
_("Search"), _("Search"),
@ -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();
@ -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;
} }
@ -821,6 +885,8 @@ int do_find_bracket(void)
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 */

102
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 /* 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);
@ -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) {