mirror of
git://git.sv.gnu.org/nano.git
synced 2024-11-22 21:01:24 +03:00
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:
parent
95e0cf584c
commit
5beed509a6
@ -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()
|
||||
|
36
files.c
36
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);
|
||||
|
||||
|
33
global.c
33
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 */
|
||||
|
13
nano.c
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 */
|
||||
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 */
|
||||
|
25
nano.h
25
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 */
|
||||
|
23
proto.h
23
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);
|
||||
|
9
rcfile.c
9
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);
|
||||
|
227
search.c
227
search.c
@ -26,10 +26,17 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include "proto.h"
|
||||
#include "nano.h"
|
||||
|
||||
#ifndef NANO_SMALL
|
||||
#ifdef ENABLE_NANORC
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int past_editbuff;
|
||||
/* findnextstr() is now searching lines not displayed */
|
||||
|
||||
@ -89,7 +96,7 @@ void search_init_globals(void)
|
||||
}
|
||||
|
||||
/* Set up the system variables for a search or replace. Returns -1 on
|
||||
abort, 0 on success, and 1 on rerun calling program
|
||||
abort, 0 on success, and 1 on rerun calling program
|
||||
Return -2 to run opposite program (search -> replace, replace ->
|
||||
search).
|
||||
|
||||
@ -110,24 +117,37 @@ int search_init(int replacing)
|
||||
backupstring = NULL;
|
||||
UNSET(CLEAR_BACKUPSTRING);
|
||||
}
|
||||
|
||||
/* Okay, fun time. backupstring is our holder for what is being
|
||||
|
||||
/* Okay, fun time. backupstring is our holder for what is being
|
||||
returned from the statusq call. Using answer for this would be tricky.
|
||||
Here, if we're using PICO_MODE, we only want nano to put the
|
||||
old string back up as editable if it's not the same as last_search.
|
||||
|
||||
Otherwise, if we don't already have a backupstring, set it to
|
||||
last_search. */
|
||||
|
||||
#if 0
|
||||
/* might need again ;)*/
|
||||
if (ISSET(PICO_MODE)) {
|
||||
if (backupstring == NULL || !strcmp(backupstring, last_search)) {
|
||||
/* backupstring = mallocstrcpy(backupstring, ""); */
|
||||
backupstring = charalloc(1);
|
||||
backupstring[0] = '\0';
|
||||
}
|
||||
}
|
||||
else if (backupstring == NULL)
|
||||
} else
|
||||
#endif
|
||||
if (backupstring == NULL)
|
||||
#ifndef NANO_SMALL
|
||||
backupstring = mallocstrcpy(backupstring, search_history.current->data);
|
||||
#else
|
||||
backupstring = mallocstrcpy(backupstring, last_search);
|
||||
#endif
|
||||
|
||||
/* NEW TEST */
|
||||
if (ISSET(PICO_MODE)) {
|
||||
backupstring = mallocstrcpy(backupstring, "");
|
||||
search_history.current = (historytype *)&search_history.next;
|
||||
}
|
||||
/* */
|
||||
/* If using Pico messages, we do things the old fashioned way... */
|
||||
if (ISSET(PICO_MODE) && last_search[0] != '\0') {
|
||||
buf = charalloc(COLS / 3 + 7);
|
||||
@ -141,7 +161,10 @@ int search_init(int replacing)
|
||||
|
||||
/* This is now one simple call. It just does a lot */
|
||||
i = statusq(0, replacing ? replace_list : whereis_list, backupstring,
|
||||
"%s%s%s%s%s%s",
|
||||
#ifndef NANO_SMALL
|
||||
&search_history,
|
||||
#endif
|
||||
"%s%s%s%s%s%s",
|
||||
_("Search"),
|
||||
|
||||
/* This string is just a modifier for the search prompt,
|
||||
@ -168,6 +191,9 @@ int search_init(int replacing)
|
||||
reset_cursor();
|
||||
free(backupstring);
|
||||
backupstring = NULL;
|
||||
#ifndef NANO_SMALL
|
||||
search_history.current = search_history.next;
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
switch (i) {
|
||||
@ -210,7 +236,14 @@ int search_init(int replacing)
|
||||
case NANO_FROMSEARCHTOGOTO_KEY:
|
||||
free(backupstring);
|
||||
backupstring = NULL;
|
||||
do_gotoline_void();
|
||||
#ifndef NANO_SMALL
|
||||
search_history.current = search_history.next;
|
||||
#endif
|
||||
i = (int)strtol(answer, &buf, 10); /* just testing answer here */
|
||||
if (!(errno == ERANGE || *answer == '\0' || *buf != '\0'))
|
||||
do_gotoline(-1, 0);
|
||||
else
|
||||
do_gotoline_void();
|
||||
return -3;
|
||||
default:
|
||||
do_early_abort();
|
||||
@ -301,7 +334,7 @@ filestruct *findnextstr(int quiet, int bracket_mode,
|
||||
not_found_msg(needle);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef NANO_SMALL
|
||||
else { /* reverse search */
|
||||
current_x_find = current_x - 1;
|
||||
@ -403,6 +436,9 @@ int do_search(void)
|
||||
/* The sneaky user deleted the previous search string */
|
||||
if (!ISSET(PICO_MODE) && answer[0] == '\0') {
|
||||
statusbar(_("Search Cancelled"));
|
||||
#ifndef NANO_SMALL
|
||||
search_history.current = search_history.next;
|
||||
#endif
|
||||
search_abort();
|
||||
return 0;
|
||||
}
|
||||
@ -415,6 +451,11 @@ int do_search(void)
|
||||
else
|
||||
last_search = mallocstrcpy(last_search, answer);
|
||||
|
||||
#ifndef NANO_SMALL
|
||||
/* add this search string to the search history list */
|
||||
update_history(&search_history, answer);
|
||||
#endif /* !NANO_SMALL */
|
||||
|
||||
search_last_line = 0;
|
||||
didfind = findnextstr(FALSE, FALSE, current, current_x, answer);
|
||||
|
||||
@ -697,6 +738,10 @@ int do_replace(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef NANO_SMALL
|
||||
update_history(&search_history, answer);
|
||||
#endif /* !NANO_SMALL */
|
||||
|
||||
/* Again, there was a previous string, but they deleted it and hit enter */
|
||||
if (!ISSET(PICO_MODE) && answer[0] == '\0') {
|
||||
statusbar(_("Replace Cancelled"));
|
||||
@ -710,6 +755,7 @@ int do_replace(void)
|
||||
answer = mallocstrcpy(answer, last_search);
|
||||
else
|
||||
last_search = mallocstrcpy(last_search, answer);
|
||||
|
||||
prevanswer = mallocstrcpy(prevanswer, last_search);
|
||||
|
||||
if (ISSET(PICO_MODE) && last_replace[0] != '\0') {
|
||||
@ -718,16 +764,34 @@ int do_replace(void)
|
||||
|
||||
strncpy(buf, last_replace, COLS / 3 - 1);
|
||||
strcpy(buf + COLS / 3 - 1, "...");
|
||||
i = statusq(0, replace_list_2, "", _("Replace with [%s]"),
|
||||
buf);
|
||||
i = statusq(0, replace_list_2, "",
|
||||
#ifndef NANO_SMALL
|
||||
&replace_history,
|
||||
#endif
|
||||
_("Replace with [%s]"), buf);
|
||||
free(buf);
|
||||
} else
|
||||
i = statusq(0, replace_list_2, "", _("Replace with [%s]"),
|
||||
last_replace);
|
||||
} else
|
||||
i = statusq(0, replace_list_2, last_replace, _("Replace with"));
|
||||
i = statusq(0, replace_list_2, "",
|
||||
#ifndef NANO_SMALL
|
||||
&replace_history,
|
||||
#endif
|
||||
_("Replace with [%s]") ,last_replace);
|
||||
} else {
|
||||
#ifndef NANO_SMALL
|
||||
replace_history.current = (historytype *)&replace_history.next;
|
||||
last_replace = mallocstrcpy(last_replace, "");
|
||||
#endif
|
||||
i = statusq(0, replace_list_2, last_replace,
|
||||
#ifndef NANO_SMALL
|
||||
&replace_history,
|
||||
#endif
|
||||
_("Replace with"));
|
||||
}
|
||||
#ifndef NANO_SMALL
|
||||
if (i == 0)
|
||||
update_history(&replace_history, answer);
|
||||
#endif /* !NANO_SMALL */
|
||||
|
||||
/* save where we are */
|
||||
begin = current;
|
||||
beginx = current_x;
|
||||
search_last_line = 0;
|
||||
@ -753,7 +817,7 @@ void goto_abort(void)
|
||||
int do_gotoline(int line, int save_pos)
|
||||
{
|
||||
if (line <= 0) { /* Ask for it */
|
||||
if (statusq(0, goto_list, "", _("Enter line number"))) {
|
||||
if (statusq(0, goto_list, (line ? answer : ""), 0, _("Enter line number"))) {
|
||||
statusbar(_("Aborted"));
|
||||
goto_abort();
|
||||
return 0;
|
||||
@ -780,9 +844,9 @@ int do_gotoline(int line, int save_pos)
|
||||
edit_update(current, NONE);
|
||||
else
|
||||
edit_update(current, CENTER);
|
||||
|
||||
placewewant = 0;
|
||||
goto_abort();
|
||||
blank_statusbar_refresh();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -820,7 +884,9 @@ int do_find_bracket(void)
|
||||
filestruct *current_save;
|
||||
|
||||
ch_under_cursor = current->data[current_x];
|
||||
|
||||
|
||||
/* if ((!(pos = strchr(brackets, ch_under_cursor))) || (!((offset = pos - brackets) < 8))) { */
|
||||
|
||||
if (((pos = strchr(brackets, ch_under_cursor)) == NULL) || (((offset = pos - brackets) < 8) == 0)) {
|
||||
statusbar(_("Not a bracket"));
|
||||
return 1;
|
||||
@ -880,3 +946,126 @@ int do_find_bracket(void)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NANO_SMALL
|
||||
/*
|
||||
* search and replace history list support functions
|
||||
*/
|
||||
|
||||
/* initialize search and replace history lists */
|
||||
void history_init(void)
|
||||
{
|
||||
search_history.next = (historytype *)&search_history.prev;
|
||||
search_history.prev = NULL;
|
||||
search_history.tail = (historytype *)&search_history.next;
|
||||
search_history.current = search_history.next;
|
||||
search_history.count = 0;
|
||||
search_history.len = 0;
|
||||
|
||||
replace_history.next = (historytype *)&replace_history.prev;
|
||||
replace_history.prev = NULL;
|
||||
replace_history.tail = (historytype *)&replace_history.next;
|
||||
replace_history.current = replace_history.next;
|
||||
replace_history.count = 0;
|
||||
replace_history.len = 0;
|
||||
}
|
||||
|
||||
/* find first node containing string *s in history list *h */
|
||||
historytype *find_node(historytype *h, char *s)
|
||||
{
|
||||
for ( ; h->next ; h = h->next)
|
||||
if (strcmp(s, h->data) == 0)
|
||||
return h;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* remove node *r */
|
||||
void remove_node(historytype *r)
|
||||
{
|
||||
r->prev->next = r->next;
|
||||
r->next->prev = r->prev;
|
||||
free(r->data);
|
||||
free(r);
|
||||
}
|
||||
|
||||
/* add a node after node *h */
|
||||
void insert_node(historytype *h, const char *s)
|
||||
{
|
||||
historytype *a;
|
||||
|
||||
a = nmalloc(sizeof(historytype));
|
||||
a->next = h->next;
|
||||
a->prev = h->next->prev;
|
||||
h->next->prev = a;
|
||||
h->next = a;
|
||||
a->data = mallocstrcpy(NULL, s);
|
||||
}
|
||||
|
||||
/* update history list */
|
||||
void update_history(historyheadtype *h, char *s)
|
||||
{
|
||||
historytype *p;
|
||||
|
||||
if ((p = find_node(h->next, s))) {
|
||||
if (p == h->next) /* catch delete and re-insert of same string in 1st node */
|
||||
goto up_hs;
|
||||
remove_node(p); /* delete identical older string */
|
||||
h->count--;
|
||||
}
|
||||
if (h->count == MAX_SEARCH_HISTORY) { /* list 'full', delete oldest */
|
||||
remove_node(h->tail);
|
||||
h->count--;
|
||||
}
|
||||
insert_node((historytype *)h, s);
|
||||
h->count++;
|
||||
up_hs:
|
||||
h->current = h->next;
|
||||
}
|
||||
|
||||
/* return a pointer to either the next older history or NULL if no more */
|
||||
char *get_history_older(historyheadtype *h)
|
||||
{
|
||||
if (h->current->next) { /* any older entries ? */
|
||||
h->current = h->current->next; /* yes */
|
||||
return h->current->data; /* return it */
|
||||
}
|
||||
return NULL; /* end of list */
|
||||
}
|
||||
|
||||
char *get_history_newer(historyheadtype *h)
|
||||
{
|
||||
if (h->current->prev) {
|
||||
h->current = h->current->prev;
|
||||
if (h->current->prev)
|
||||
return h->current->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get a completion */
|
||||
char *get_history_completion(historyheadtype *h, char *s)
|
||||
{
|
||||
historytype *p;
|
||||
|
||||
for (p = h->current->next ; p->next ; p = p->next) {
|
||||
if ((strncmp(s, p->data, h->len) == 0) && (strlen(p->data) != h->len)) {
|
||||
h->current = p;
|
||||
return p->data;
|
||||
}
|
||||
}
|
||||
h->current = (historytype*)h;
|
||||
null_at(&s, h->len);
|
||||
return s;
|
||||
}
|
||||
|
||||
/* free a history list */
|
||||
void free_history(historyheadtype *h)
|
||||
{
|
||||
historytype *p, *n;
|
||||
|
||||
for (p = h->next ; (n = p->next) ; p = n)
|
||||
remove_node(p);
|
||||
}
|
||||
|
||||
/* end of history support functions */
|
||||
#endif /* !NANO_SMALL */
|
||||
|
106
winio.c
106
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user