Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/lib/libedit/readline.c,v rcsdiff: /ftp/cvs/cvsroot/src/lib/libedit/readline.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.120 retrieving revision 1.133 diff -u -p -r1.120 -r1.133 --- src/lib/libedit/readline.c 2016/02/15 23:36:30 1.120 +++ src/lib/libedit/readline.c 2016/05/13 15:55:59 1.133 @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.120 2016/02/15 23:36:30 christos Exp $ */ +/* $NetBSD: readline.c,v 1.133 2016/05/13 15:55:59 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -31,29 +31,28 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.120 2016/02/15 23:36:30 christos Exp $"); +__RCSID("$NetBSD: readline.c,v 1.133 2016/05/13 15:55:59 christos Exp $"); #endif /* not lint && not SCCSID */ #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include +#include #include #include +#include +#include #include +#include +#include +#include +#include +#include #include #include "readline/readline.h" #include "el.h" -#include "fcns.h" /* for EL_NUM_FCNS */ -#include "histedit.h" +#include "fcns.h" #include "filecomplete.h" void rl_prep_terminal(int); @@ -157,6 +156,14 @@ char *rl_special_prefixes = NULL; */ int rl_completion_append_character = ' '; +/* + * When the history cursor is on the newest element and next_history() + * is called, GNU readline moves the cursor beyond the newest element. + * The editline library does not provide data structures to express + * that state, so we need a local flag. + */ +static int current_history_valid = 1; + /* stuff below is used internally by libedit for readline emulation */ static History *h = NULL; @@ -168,13 +175,13 @@ static jmp_buf topbuf; static unsigned char _el_rl_complete(EditLine *, int); static unsigned char _el_rl_tstp(EditLine *, int); static char *_get_prompt(EditLine *); -static int _getc_function(EditLine *, char *); +static int _getc_function(EditLine *, wchar_t *); static HIST_ENTRY *_move_history(int); static int _history_expand_command(const char *, size_t, size_t, char **); static char *_rl_compat_sub(const char *, const char *, const char *, int); -static int _rl_event_read_char(EditLine *, char *); +static int _rl_event_read_char(EditLine *, wchar_t *); static void _rl_update_pos(void); @@ -211,14 +218,14 @@ _move_history(int op) */ static int /*ARGSUSED*/ -_getc_function(EditLine *el __attribute__((__unused__)), char *c) +_getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c) { int i; i = (*rl_getc_function)(NULL); if (i == -1) return 0; - *c = (char)i; + *c = (wchar_t)i; return 1; } @@ -268,7 +275,7 @@ rl_set_prompt(const char *prompt) if (!prompt) prompt = ""; - if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) + if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) return 0; if (rl_prompt) el_free(rl_prompt); @@ -292,6 +299,8 @@ rl_initialize(void) int editmode = 1; struct termios t; + current_history_valid = 1; + if (e != NULL) el_end(e); if (h != NULL) @@ -362,7 +371,7 @@ rl_initialize(void) "ReadLine compatible suspend function", _el_rl_tstp); el_set(e, EL_BIND, "^Z", "rl_tstp", NULL); - + /* * Set some readline compatible key-bindings. */ @@ -1169,12 +1178,24 @@ void stifle_history(int max) { HistEvent ev; + HIST_ENTRY *he; + int i, len; if (h == NULL || e == NULL) rl_initialize(); - if (history(h, &ev, H_SETSIZE, max) == 0) + len = history_length; + if (history(h, &ev, H_SETSIZE, max) == 0) { max_input_history = max; + if (max < len) + history_base += len - max; + for (i = 0; i < len - max; i++) { + he = remove_history(i); + el_free(he->data); + el_free((void *)(unsigned long)he->line); + el_free(he); + } + } } @@ -1389,25 +1410,37 @@ history_get(int num) if (h == NULL || e == NULL) rl_initialize(); + if (num < history_base) + return NULL; + /* save current position */ if (history(h, &ev, H_CURR) != 0) return NULL; curr_num = ev.num; - /* start from the oldest */ - if (history(h, &ev, H_LAST) != 0) - return NULL; /* error */ - - /* look forwards for event matching specified offset */ - if (history(h, &ev, H_NEXT_EVDATA, num, &she.data)) - return NULL; + /* + * use H_DELDATA to set to nth history (without delete) by passing + * (void **)-1 -- as in history_set_pos + */ + if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0) + goto out; + /* get current entry */ + if (history(h, &ev, H_CURR) != 0) + goto out; + if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0) + goto out; she.line = ev.str; /* restore pointer to where it was */ (void)history(h, &ev, H_SET, curr_num); return &she; + +out: + /* restore pointer to where it was */ + (void)history(h, &ev, H_SET, curr_num); + return NULL; } @@ -1428,6 +1461,7 @@ add_history(const char *line) (void)history(h, &ev, H_ENTER, line); if (history(h, &ev, H_GETSIZE) == 0) history_length = ev.num; + current_history_valid = 1; return !(history_length > 0); /* return 0 if all is okay */ } @@ -1520,6 +1554,7 @@ clear_history(void) (void)history(h, &ev, H_CLEAR); history_length = 0; + current_history_valid = 1; } @@ -1536,9 +1571,12 @@ where_history(void) return 0; curr_num = ev.num; - (void)history(h, &ev, H_FIRST); - off = 1; - while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) + /* start from the oldest */ + (void)history(h, &ev, H_LAST); + + /* position is zero-based */ + off = 0; + while (ev.num != curr_num && history(h, &ev, H_PREV) == 0) off++; return off; @@ -1552,7 +1590,7 @@ HIST_ENTRY * current_history(void) { - return _move_history(H_CURR); + return current_history_valid ? _move_history(H_CURR) : NULL; } @@ -1593,10 +1631,11 @@ history_set_pos(int pos) int curr_num; if (pos >= history_length || pos < 0) - return -1; + return 0; (void)history(h, &ev, H_CURR); curr_num = ev.num; + current_history_valid = 1; /* * use H_DELDATA to set to nth history (without delete) by passing @@ -1604,20 +1643,25 @@ history_set_pos(int pos) */ if (history(h, &ev, H_DELDATA, pos, (void **)-1)) { (void)history(h, &ev, H_SET, curr_num); - return -1; + return 0; } - return 0; + return 1; } /* * returns previous event in history and shifts pointer accordingly + * Note that readline and editline define directions in opposite ways. */ HIST_ENTRY * previous_history(void) { - return _move_history(H_PREV); + if (current_history_valid == 0) { + current_history_valid = 1; + return _move_history(H_CURR); + } + return _move_history(H_NEXT); } @@ -1627,8 +1671,12 @@ previous_history(void) HIST_ENTRY * next_history(void) { + HIST_ENTRY *he; - return _move_history(H_NEXT); + he = _move_history(H_PREV); + if (he == NULL) + current_history_valid = 0; + return he; } @@ -1689,7 +1737,7 @@ history_search_pos(const char *str, return -1; curr_num = ev.num; - if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0) + if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0) return -1; for (;;) { @@ -1807,9 +1855,7 @@ _rl_completion_append_character_function int rl_complete(int ignore __attribute__((__unused__)), int invoking_key) { -#ifdef WIDECHAR static ct_buffer_t wbreak_conv, sprefix_conv; -#endif char *breakchars; if (h == NULL || e == NULL) @@ -2009,7 +2055,7 @@ rl_callback_read_char(void) } } -void +void rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc) { if (e == NULL) { @@ -2018,9 +2064,9 @@ rl_callback_handler_install(const char * (void)rl_set_prompt(prompt); rl_linefunc = linefunc; el_set(e, EL_UNBUFFERED, 1); -} +} -void +void rl_callback_handler_remove(void) { el_set(e, EL_UNBUFFERED, 0); @@ -2101,12 +2147,14 @@ rl_stuff_char(int c) } static int -_rl_event_read_char(EditLine *el, char *cp) +_rl_event_read_char(EditLine *el, wchar_t *wc) { + char ch; int n; ssize_t num_read = 0; - *cp = '\0'; + ch = '\0'; + *wc = L'\0'; while (rl_event_hook) { (*rl_event_hook)(); @@ -2115,7 +2163,7 @@ _rl_event_read_char(EditLine *el, char * if (ioctl(el->el_infd, FIONREAD, &n) < 0) return -1; if (n) - num_read = read(el->el_infd, cp, (size_t)1); + num_read = read(el->el_infd, &ch, (size_t)1); else num_read = 0; #elif defined(F_SETFL) && defined(O_NDELAY) @@ -2123,12 +2171,12 @@ _rl_event_read_char(EditLine *el, char * return -1; if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0) return -1; - num_read = read(el->el_infd, cp, 1); + num_read = read(el->el_infd, &ch, 1); if (fcntl(el->el_infd, F_SETFL, n)) return -1; #else /* not non-blocking, but what you gonna do? */ - num_read = read(el->el_infd, cp, 1); + num_read = read(el->el_infd, &ch, 1); return -1; #endif @@ -2140,6 +2188,7 @@ _rl_event_read_char(EditLine *el, char * } if (!rl_event_hook) el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); + *wc = (wchar_t)ch; return (int)num_read; } @@ -2220,7 +2269,7 @@ rl_completion_matches(const char *str, r list[0][min] = '\0'; } return list; - + out: el_free(list); return NULL;