mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-14 07:30:49 +02:00
Bash-5.3-alpha release
This commit is contained in:
@@ -282,6 +282,9 @@ parse-colors.o: ${BUILD_DIR}/config.h colors.h parse-colors.h
|
||||
parse-colors.o: rldefs.h rlconf.h
|
||||
parse-colors.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
|
||||
|
||||
input.o: posixselect.h posixtime.h
|
||||
parens.o: posixselect.h posixtime.h
|
||||
|
||||
bind.o: rlshell.h
|
||||
histfile.o: rlshell.h
|
||||
nls.o: rlshell.h
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* A minimal stdlib.h containing extern declarations for those functions
|
||||
that bash uses. */
|
||||
|
||||
/* Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -32,13 +32,7 @@ extern double strtod ();
|
||||
/* Memory allocation functions. */
|
||||
/* Generic pointer type. */
|
||||
#ifndef PTR_T
|
||||
|
||||
#if defined (__STDC__)
|
||||
# define PTR_T void *
|
||||
#else
|
||||
# define PTR_T char *
|
||||
#endif
|
||||
|
||||
#endif /* PTR_T */
|
||||
|
||||
extern PTR_T malloc ();
|
||||
|
||||
+210
-197
@@ -1,6 +1,6 @@
|
||||
/* bind.c -- key binding and startup file support for the readline library. */
|
||||
|
||||
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -65,20 +65,15 @@ extern int errno;
|
||||
#include "rlshell.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#if !defined (strchr) && !defined (__STDC__)
|
||||
extern char *strchr (), *strrchr ();
|
||||
#endif /* !strchr && !__STDC__ */
|
||||
|
||||
/* Variables exported by this file. */
|
||||
Keymap rl_binding_keymap;
|
||||
|
||||
/* Functions exported by this file. */
|
||||
rl_macro_print_func_t *rl_macro_display_hook = (rl_macro_print_func_t *)NULL;
|
||||
|
||||
static int _rl_skip_to_delim (char *, int, int);
|
||||
|
||||
#if defined (USE_VARARGS) && defined (PREFER_STDARG)
|
||||
static void _rl_init_file_error (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
|
||||
#else
|
||||
static void _rl_init_file_error ();
|
||||
#endif
|
||||
|
||||
static rl_command_func_t *_rl_function_of_keyseq_internal (const char *, size_t, Keymap, int *);
|
||||
|
||||
@@ -531,8 +526,7 @@ rl_translate_keyseq (const char *seq, char *array, int *len)
|
||||
|
||||
/* When there are incomplete prefixes \C- or \M- (has_control || has_meta)
|
||||
without base character at the end of SEQ, they are processed as the
|
||||
prefixes for '\0'.
|
||||
*/
|
||||
prefixes for '\0'. */
|
||||
for (i = l = 0; (c = seq[i]) || has_control || has_meta; i++)
|
||||
{
|
||||
/* Only backslashes followed by a non-null character are handled
|
||||
@@ -629,11 +623,17 @@ rl_translate_keyseq (const char *seq, char *array, int *len)
|
||||
has_meta = 0;
|
||||
}
|
||||
|
||||
/* If convert-meta is turned on, convert a meta char to a key sequence */
|
||||
/* If convert-meta is turned on, convert a meta char to a key sequence */
|
||||
if (META_CHAR (c) && _rl_convert_meta_chars_to_ascii)
|
||||
{
|
||||
array[l++] = ESC; /* ESC is meta-prefix */
|
||||
array[l++] = UNMETA (c);
|
||||
int x = UNMETA (c);
|
||||
if (x)
|
||||
{
|
||||
array[l++] = ESC; /* ESC is meta-prefix */
|
||||
array[l++] = x;
|
||||
}
|
||||
else
|
||||
array[l++] = c; /* just do the best we can without sticking a NUL in there. */
|
||||
}
|
||||
else
|
||||
array[l++] = (c);
|
||||
@@ -685,7 +685,8 @@ char *
|
||||
rl_untranslate_keyseq (int seq)
|
||||
{
|
||||
static char kseq[16];
|
||||
int i, c;
|
||||
int i;
|
||||
unsigned char c;
|
||||
|
||||
i = 0;
|
||||
c = seq;
|
||||
@@ -696,36 +697,23 @@ rl_untranslate_keyseq (int seq)
|
||||
kseq[i++] = '-';
|
||||
c = UNMETA (c);
|
||||
}
|
||||
else if (c == ESC)
|
||||
{
|
||||
kseq[i++] = '\\';
|
||||
c = 'e';
|
||||
}
|
||||
else if (CTRL_CHAR (c))
|
||||
{
|
||||
kseq[i++] = '\\';
|
||||
kseq[i++] = 'C';
|
||||
kseq[i++] = '-';
|
||||
c = _rl_to_lower (UNCTRL (c));
|
||||
}
|
||||
else if (c == RUBOUT)
|
||||
{
|
||||
kseq[i++] = '\\';
|
||||
kseq[i++] = 'C';
|
||||
kseq[i++] = '-';
|
||||
c = '?';
|
||||
}
|
||||
|
||||
if (c == ESC)
|
||||
{
|
||||
kseq[i++] = '\\';
|
||||
c = 'e';
|
||||
}
|
||||
else if (c == '\\' || c == '"')
|
||||
else if (CTRL_CHAR (c) || c == RUBOUT)
|
||||
{
|
||||
kseq[i++] = '\\';
|
||||
kseq[i++] = 'C';
|
||||
kseq[i++] = '-';
|
||||
c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
|
||||
}
|
||||
|
||||
if (c == '\\' || c == '"')
|
||||
kseq[i++] = '\\';
|
||||
|
||||
kseq[i++] = (unsigned char) c;
|
||||
kseq[i] = '\0';
|
||||
return kseq;
|
||||
@@ -735,9 +723,9 @@ char *
|
||||
_rl_untranslate_macro_value (char *seq, int use_escapes)
|
||||
{
|
||||
char *ret, *r, *s;
|
||||
int c;
|
||||
unsigned char c;
|
||||
|
||||
r = ret = (char *)xmalloc (7 * strlen (seq) + 1);
|
||||
r = ret = (char *)xmalloc (8 * strlen (seq) + 1);
|
||||
for (s = seq; *s; s++)
|
||||
{
|
||||
c = *s;
|
||||
@@ -748,7 +736,9 @@ _rl_untranslate_macro_value (char *seq, int use_escapes)
|
||||
*r++ = '-';
|
||||
c = UNMETA (c);
|
||||
}
|
||||
else if (c == ESC)
|
||||
|
||||
/* We want to keep from printing literal control chars */
|
||||
if (c == ESC)
|
||||
{
|
||||
*r++ = '\\';
|
||||
c = 'e';
|
||||
@@ -773,15 +763,10 @@ _rl_untranslate_macro_value (char *seq, int use_escapes)
|
||||
c = '?';
|
||||
}
|
||||
|
||||
if (c == ESC)
|
||||
{
|
||||
*r++ = '\\';
|
||||
c = 'e';
|
||||
}
|
||||
else if (c == '\\' || c == '"')
|
||||
if (c == '\\' || c == '"')
|
||||
*r++ = '\\';
|
||||
|
||||
*r++ = (unsigned char)c;
|
||||
*r++ = c;
|
||||
}
|
||||
*r = '\0';
|
||||
return ret;
|
||||
@@ -889,21 +874,30 @@ int
|
||||
rl_trim_arg_from_keyseq (const char *keyseq, size_t len, Keymap map)
|
||||
{
|
||||
register int i, j, parsing_digits;
|
||||
unsigned char ic;
|
||||
unsigned int ic; /* int to handle ANYOTHERKEY */
|
||||
Keymap map0;
|
||||
|
||||
if (map == 0)
|
||||
map = _rl_keymap;
|
||||
map0 = map;
|
||||
|
||||
/* The digits following the initial one (e.g., the binding to digit-argument)
|
||||
or the optional `-' in a binding to digit-argument or universal-argument
|
||||
are not added to rl_executing_keyseq. This is basically everything read by
|
||||
rl_digit_loop. The parsing_digits logic is here in case they ever are. */
|
||||
/* Make sure to add the digits following the initial one (e.g., the binding
|
||||
to digit-argument) and the optional `-' in a binding to digit-argument
|
||||
or universal-argument to rl_executing_keyseq. This is basically
|
||||
everything read by rl_digit_loop. */
|
||||
for (i = j = parsing_digits = 0; keyseq && i < len; i++)
|
||||
{
|
||||
ic = keyseq[i];
|
||||
|
||||
if (parsing_digits == 2)
|
||||
{
|
||||
if (ic == '-') /* skip over runs of minus chars */
|
||||
{
|
||||
j = i + 1;
|
||||
continue;
|
||||
}
|
||||
parsing_digits = 1;
|
||||
}
|
||||
if (parsing_digits)
|
||||
{
|
||||
if (_rl_digit_p (ic))
|
||||
@@ -916,10 +910,11 @@ rl_trim_arg_from_keyseq (const char *keyseq, size_t len, Keymap map)
|
||||
|
||||
if (map[ic].type == ISKMAP)
|
||||
{
|
||||
if (i + 1 == len)
|
||||
return -1;
|
||||
map = FUNCTION_TO_KEYMAP (map, ic);
|
||||
continue;
|
||||
if (i + 1 == len)
|
||||
ic = ANYOTHERKEY;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if (map[ic].type == ISFUNC)
|
||||
{
|
||||
@@ -938,16 +933,11 @@ rl_trim_arg_from_keyseq (const char *keyseq, size_t len, Keymap map)
|
||||
|
||||
/* This logic should be identical to rl_digit_loop */
|
||||
/* We accept M-- as equivalent to M--1, C-u- as equivalent to C-u-1
|
||||
but set parsing_digits to 2 to note that we saw `-' */
|
||||
if (map[ic].function == rl_universal_argument && (i + 1 == '-'))
|
||||
{
|
||||
i++;
|
||||
parsing_digits = 2;
|
||||
}
|
||||
if (map[ic].function == rl_digit_argument && ic == '-')
|
||||
{
|
||||
parsing_digits = 2;
|
||||
}
|
||||
but set parsing_digits to 2 to note that we saw `-'. See above
|
||||
for the check that skips over one or more `-' characters. */
|
||||
if (map[ic].function == rl_universal_argument ||
|
||||
(map[ic].function == rl_digit_argument && ic == '-'))
|
||||
parsing_digits = 2;
|
||||
|
||||
map = map0;
|
||||
j = i + 1;
|
||||
@@ -978,11 +968,20 @@ _rl_read_file (char *filename, size_t *sizep)
|
||||
char *buffer;
|
||||
int i, file;
|
||||
|
||||
file = -1;
|
||||
if (((file = open (filename, O_RDONLY, 0666)) < 0) || (fstat (file, &finfo) < 0))
|
||||
file = open (filename, O_RDONLY, 0666);
|
||||
/* If the open is interrupted, retry once */
|
||||
if (file < 0 && errno == EINTR)
|
||||
{
|
||||
RL_CHECK_SIGNALS ();
|
||||
file = open (filename, O_RDONLY, 0666);
|
||||
}
|
||||
|
||||
if ((file < 0) || (fstat (file, &finfo) < 0))
|
||||
{
|
||||
i = errno;
|
||||
if (file >= 0)
|
||||
close (file);
|
||||
errno = i;
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
@@ -991,10 +990,13 @@ _rl_read_file (char *filename, size_t *sizep)
|
||||
/* check for overflow on very large files */
|
||||
if (file_size != finfo.st_size || file_size + 1 < file_size)
|
||||
{
|
||||
i = errno;
|
||||
if (file >= 0)
|
||||
close (file);
|
||||
#if defined (EFBIG)
|
||||
errno = EFBIG;
|
||||
#else
|
||||
errno = i;
|
||||
#endif
|
||||
return ((char *)NULL);
|
||||
}
|
||||
@@ -1129,25 +1131,11 @@ _rl_read_init_file (const char *filename, int include_level)
|
||||
}
|
||||
|
||||
static void
|
||||
#if defined (PREFER_STDARG)
|
||||
_rl_init_file_error (const char *format, ...)
|
||||
#else
|
||||
_rl_init_file_error (va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#if defined (PREFER_VARARGS)
|
||||
char *format;
|
||||
#endif
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
fprintf (stderr, "readline: ");
|
||||
if (currently_reading_init_file)
|
||||
fprintf (stderr, "%s: line %d: ", current_readline_init_file,
|
||||
@@ -1167,9 +1155,7 @@ _rl_init_file_error (va_alist)
|
||||
/* **************************************************************** */
|
||||
|
||||
static int
|
||||
parse_comparison_op (s, indp)
|
||||
const char *s;
|
||||
int *indp;
|
||||
parse_comparison_op (const char *s, int *indp)
|
||||
{
|
||||
int i, peekc, op;
|
||||
|
||||
@@ -1247,7 +1233,7 @@ const char *rl_readline_name = "other";
|
||||
/* Stack of previous values of parsing_conditionalized_out. */
|
||||
static unsigned char *if_stack = (unsigned char *)NULL;
|
||||
static int if_stack_depth;
|
||||
static int if_stack_size;
|
||||
static size_t if_stack_size;
|
||||
|
||||
/* Push _rl_parsing_conditionalized_out, and set parser state based
|
||||
on ARGS. */
|
||||
@@ -1672,7 +1658,6 @@ rl_parse_and_bind (char *string)
|
||||
if (_rl_stricmp (string, "set") == 0)
|
||||
{
|
||||
char *var, *value, *e;
|
||||
int s;
|
||||
|
||||
var = string + i;
|
||||
/* Make VAR point to start of variable name. */
|
||||
@@ -1850,7 +1835,7 @@ rl_parse_and_bind (char *string)
|
||||
if (*funname == '\'' || *funname == '"')
|
||||
{
|
||||
char useq[2];
|
||||
int fl = strlen (funname);
|
||||
size_t fl = strlen (funname);
|
||||
|
||||
useq[0] = key; useq[1] = '\0';
|
||||
if (fl && funname[fl - 1] == *funname)
|
||||
@@ -1917,6 +1902,7 @@ static const struct {
|
||||
{ "prefer-visible-bell", &_rl_prefer_visible_bell, V_SPECIAL },
|
||||
{ "print-completions-horizontally", &_rl_print_completions_horizontally, 0 },
|
||||
{ "revert-all-at-newline", &_rl_revert_all_at_newline, 0 },
|
||||
{ "search-ignore-case", &_rl_search_case_fold, 0 },
|
||||
{ "show-all-if-ambiguous", &_rl_complete_show_all, 0 },
|
||||
{ "show-all-if-unmodified", &_rl_complete_show_unmodified, 0 },
|
||||
{ "show-mode-in-prompt", &_rl_show_mode_in_prompt, 0 },
|
||||
@@ -2595,17 +2581,13 @@ _rl_get_keyname (int key)
|
||||
char *keyname;
|
||||
int i, c;
|
||||
|
||||
keyname = (char *)xmalloc (8);
|
||||
keyname = (char *)xmalloc (9);
|
||||
|
||||
c = key;
|
||||
/* Since this is going to be used to write out keysequence-function
|
||||
pairs for possible inclusion in an inputrc file, we don't want to
|
||||
do any special meta processing on KEY. */
|
||||
|
||||
#if 1
|
||||
/* XXX - Experimental */
|
||||
/* We might want to do this, but the old version of the code did not. */
|
||||
|
||||
/* If this is an escape character, we don't want to do any more processing.
|
||||
Just add the special ESC key sequence and return. */
|
||||
if (c == ESC)
|
||||
@@ -2615,28 +2597,23 @@ _rl_get_keyname (int key)
|
||||
keyname[2] = '\0';
|
||||
return keyname;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* RUBOUT is translated directly into \C-? */
|
||||
if (key == RUBOUT)
|
||||
if (key == ANYOTHERKEY)
|
||||
{
|
||||
keyname[0] = '\\';
|
||||
keyname[1] = 'C';
|
||||
keyname[2] = '-';
|
||||
keyname[3] = '?';
|
||||
keyname[4] = '\0';
|
||||
keyname[0] = '\0';
|
||||
return keyname;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
/* Now add special prefixes needed for control characters. This can
|
||||
potentially change C. */
|
||||
if (CTRL_CHAR (c))
|
||||
if (CTRL_CHAR (c) || c == RUBOUT)
|
||||
{
|
||||
keyname[i++] = '\\';
|
||||
keyname[i++] = 'C';
|
||||
keyname[i++] = '-';
|
||||
c = _rl_to_lower (UNCTRL (c));
|
||||
c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
|
||||
}
|
||||
|
||||
/* XXX experimental code. Turn the characters that are not ASCII or
|
||||
@@ -2678,7 +2655,7 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
|
||||
{
|
||||
register int key;
|
||||
char **result;
|
||||
int result_index, result_size;
|
||||
size_t result_index, result_size;
|
||||
|
||||
result = (char **)NULL;
|
||||
result_index = result_size = 0;
|
||||
@@ -2714,53 +2691,24 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
|
||||
{
|
||||
char **seqs;
|
||||
register int i;
|
||||
char *keyname;
|
||||
size_t knlen;
|
||||
|
||||
/* Find the list of keyseqs in this map which have FUNCTION as
|
||||
their target. Add the key sequences found to RESULT. */
|
||||
if (map[key].function)
|
||||
seqs =
|
||||
rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
|
||||
else
|
||||
if (map[key].function == 0)
|
||||
break;
|
||||
|
||||
seqs = rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
|
||||
if (seqs == 0)
|
||||
break;
|
||||
|
||||
keyname = _rl_get_keyname (key);
|
||||
knlen = RL_STRLEN (keyname);
|
||||
|
||||
for (i = 0; seqs[i]; i++)
|
||||
{
|
||||
char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
|
||||
|
||||
if (key == ESC)
|
||||
{
|
||||
/* If ESC is the meta prefix and we're converting chars
|
||||
with the eighth bit set to ESC-prefixed sequences, then
|
||||
we can use \M-. Otherwise we need to use the sequence
|
||||
for ESC. */
|
||||
if (_rl_convert_meta_chars_to_ascii && map[ESC].type == ISKMAP)
|
||||
sprintf (keyname, "\\M-");
|
||||
else
|
||||
sprintf (keyname, "\\e");
|
||||
}
|
||||
else
|
||||
{
|
||||
int c = key, l = 0;
|
||||
if (CTRL_CHAR (c) || c == RUBOUT)
|
||||
{
|
||||
keyname[l++] = '\\';
|
||||
keyname[l++] = 'C';
|
||||
keyname[l++] = '-';
|
||||
c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
|
||||
}
|
||||
|
||||
if (c == '\\' || c == '"')
|
||||
keyname[l++] = '\\';
|
||||
|
||||
keyname[l++] = (char) c;
|
||||
keyname[l++] = '\0';
|
||||
}
|
||||
|
||||
strcat (keyname, seqs[i]);
|
||||
xfree (seqs[i]);
|
||||
char *x;
|
||||
|
||||
if (result_index + 2 > result_size)
|
||||
{
|
||||
@@ -2768,10 +2716,16 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
|
||||
result = (char **)xrealloc (result, result_size * sizeof (char *));
|
||||
}
|
||||
|
||||
result[result_index++] = keyname;
|
||||
x = xmalloc (knlen + RL_STRLEN (seqs[i]) + 1);
|
||||
strcpy (x, keyname);
|
||||
strcpy (x + knlen, seqs[i]);
|
||||
xfree (seqs[i]);
|
||||
|
||||
result[result_index++] = x;
|
||||
result[result_index] = (char *)NULL;
|
||||
}
|
||||
|
||||
xfree (keyname);
|
||||
xfree (seqs);
|
||||
}
|
||||
break;
|
||||
@@ -2788,6 +2742,56 @@ rl_invoking_keyseqs (rl_command_func_t *function)
|
||||
return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
|
||||
}
|
||||
|
||||
void
|
||||
rl_print_keybinding (const char *name, Keymap kmap, int print_readably)
|
||||
{
|
||||
rl_command_func_t *function;
|
||||
char **invokers;
|
||||
|
||||
function = rl_named_function (name);
|
||||
invokers = rl_invoking_keyseqs_in_map (function, kmap ? kmap : _rl_keymap);
|
||||
|
||||
if (print_readably)
|
||||
{
|
||||
if (!invokers)
|
||||
fprintf (rl_outstream, "# %s (not bound)\n", name);
|
||||
else
|
||||
{
|
||||
register int j;
|
||||
|
||||
for (j = 0; invokers[j]; j++)
|
||||
{
|
||||
fprintf (rl_outstream, "\"%s\": %s\n", invokers[j], name);
|
||||
xfree (invokers[j]);
|
||||
}
|
||||
|
||||
xfree (invokers);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!invokers)
|
||||
fprintf (rl_outstream, "%s is not bound to any keys\n", name);
|
||||
else
|
||||
{
|
||||
register int j;
|
||||
|
||||
fprintf (rl_outstream, "%s can be found on ", name);
|
||||
|
||||
for (j = 0; invokers[j] && j < 5; j++)
|
||||
fprintf (rl_outstream, "\"%s\"%s", invokers[j], invokers[j + 1] ? ", " : ".\n");
|
||||
|
||||
if (j == 5 && invokers[j])
|
||||
fprintf (rl_outstream, "...\n");
|
||||
|
||||
for (j = 0; invokers[j]; j++)
|
||||
xfree (invokers[j]);
|
||||
|
||||
xfree (invokers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print all of the functions and their bindings to rl_outstream. If
|
||||
PRINT_READABLY is non-zero, then print the output in such a way
|
||||
that it can be read back in. */
|
||||
@@ -2803,58 +2807,7 @@ rl_function_dumper (int print_readably)
|
||||
fprintf (rl_outstream, "\n");
|
||||
|
||||
for (i = 0; name = names[i]; i++)
|
||||
{
|
||||
rl_command_func_t *function;
|
||||
char **invokers;
|
||||
|
||||
function = rl_named_function (name);
|
||||
invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
|
||||
|
||||
if (print_readably)
|
||||
{
|
||||
if (!invokers)
|
||||
fprintf (rl_outstream, "# %s (not bound)\n", name);
|
||||
else
|
||||
{
|
||||
register int j;
|
||||
|
||||
for (j = 0; invokers[j]; j++)
|
||||
{
|
||||
fprintf (rl_outstream, "\"%s\": %s\n",
|
||||
invokers[j], name);
|
||||
xfree (invokers[j]);
|
||||
}
|
||||
|
||||
xfree (invokers);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!invokers)
|
||||
fprintf (rl_outstream, "%s is not bound to any keys\n",
|
||||
name);
|
||||
else
|
||||
{
|
||||
register int j;
|
||||
|
||||
fprintf (rl_outstream, "%s can be found on ", name);
|
||||
|
||||
for (j = 0; invokers[j] && j < 5; j++)
|
||||
{
|
||||
fprintf (rl_outstream, "\"%s\"%s", invokers[j],
|
||||
invokers[j + 1] ? ", " : ".\n");
|
||||
}
|
||||
|
||||
if (j == 5 && invokers[j])
|
||||
fprintf (rl_outstream, "...\n");
|
||||
|
||||
for (j = 0; invokers[j]; j++)
|
||||
xfree (invokers[j]);
|
||||
|
||||
xfree (invokers);
|
||||
}
|
||||
}
|
||||
}
|
||||
rl_print_keybinding (name, _rl_keymap, print_readably);
|
||||
|
||||
xfree (names);
|
||||
}
|
||||
@@ -2875,9 +2828,9 @@ rl_dump_functions (int count, int key)
|
||||
static void
|
||||
_rl_macro_dumper_internal (int print_readably, Keymap map, char *prefix)
|
||||
{
|
||||
register int key;
|
||||
int key;
|
||||
char *keyname, *out;
|
||||
int prefix_len;
|
||||
size_t prefix_len;
|
||||
|
||||
for (key = 0; key < KEYMAP_SIZE; key++)
|
||||
{
|
||||
@@ -2887,6 +2840,16 @@ _rl_macro_dumper_internal (int print_readably, Keymap map, char *prefix)
|
||||
keyname = _rl_get_keyname (key);
|
||||
out = _rl_untranslate_macro_value ((char *)map[key].function, 0);
|
||||
|
||||
/* If the application wants to print macros, let it. Give it the
|
||||
ascii-fied value with backslash escapes, so it will have to use
|
||||
rl_macro_bind (with its call to rl_translate_keyseq) to get the
|
||||
same value back. */
|
||||
if (rl_macro_display_hook)
|
||||
{
|
||||
(*rl_macro_display_hook) (keyname, out, print_readably, prefix);
|
||||
break;
|
||||
}
|
||||
|
||||
if (print_readably)
|
||||
fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
|
||||
keyname,
|
||||
@@ -2950,10 +2913,40 @@ rl_dump_macros (int count, int key)
|
||||
static char *
|
||||
_rl_get_string_variable_value (const char *name)
|
||||
{
|
||||
static char numbuf[32];
|
||||
static char numbuf[64]; /* more than enough for INTMAX_MAX */
|
||||
char *ret;
|
||||
|
||||
if (_rl_stricmp (name, "bell-style") == 0)
|
||||
if (_rl_stricmp (name, "active-region-start-color") == 0)
|
||||
{
|
||||
if (_rl_active_region_start_color == 0)
|
||||
return 0;
|
||||
ret = _rl_untranslate_macro_value (_rl_active_region_start_color, 0);
|
||||
if (ret)
|
||||
{
|
||||
strncpy (numbuf, ret, sizeof (numbuf) - 1);
|
||||
xfree (ret);
|
||||
numbuf[sizeof(numbuf) - 1] = '\0';
|
||||
}
|
||||
else
|
||||
numbuf[0] = '\0';
|
||||
return numbuf;
|
||||
}
|
||||
else if (_rl_stricmp (name, "active-region-end-color") == 0)
|
||||
{
|
||||
if (_rl_active_region_end_color == 0)
|
||||
return 0;
|
||||
ret = _rl_untranslate_macro_value (_rl_active_region_end_color, 0);
|
||||
if (ret)
|
||||
{
|
||||
strncpy (numbuf, ret, sizeof (numbuf) - 1);
|
||||
xfree (ret);
|
||||
numbuf[sizeof(numbuf) - 1] = '\0';
|
||||
}
|
||||
else
|
||||
numbuf[0] = '\0';
|
||||
return numbuf;
|
||||
}
|
||||
else if (_rl_stricmp (name, "bell-style") == 0)
|
||||
{
|
||||
switch (_rl_bell_preference)
|
||||
{
|
||||
@@ -2970,24 +2963,40 @@ _rl_get_string_variable_value (const char *name)
|
||||
return (_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
|
||||
else if (_rl_stricmp (name, "completion-display-width") == 0)
|
||||
{
|
||||
#if defined (HAVE_VSNPRINTF)
|
||||
snprintf (numbuf, sizeof (numbuf), "%d", _rl_completion_columns);
|
||||
#else
|
||||
sprintf (numbuf, "%d", _rl_completion_columns);
|
||||
#endif
|
||||
return (numbuf);
|
||||
}
|
||||
else if (_rl_stricmp (name, "completion-prefix-display-length") == 0)
|
||||
{
|
||||
#if defined (HAVE_VSNPRINTF)
|
||||
snprintf (numbuf, sizeof (numbuf), "%d", _rl_completion_prefix_display_length);
|
||||
#else
|
||||
sprintf (numbuf, "%d", _rl_completion_prefix_display_length);
|
||||
#endif
|
||||
return (numbuf);
|
||||
}
|
||||
else if (_rl_stricmp (name, "completion-query-items") == 0)
|
||||
{
|
||||
#if defined (HAVE_VSNPRINTF)
|
||||
snprintf (numbuf, sizeof (numbuf), "%d", rl_completion_query_items);
|
||||
#else
|
||||
sprintf (numbuf, "%d", rl_completion_query_items);
|
||||
#endif
|
||||
return (numbuf);
|
||||
}
|
||||
else if (_rl_stricmp (name, "editing-mode") == 0)
|
||||
return (rl_get_keymap_name_from_edit_mode ());
|
||||
else if (_rl_stricmp (name, "history-size") == 0)
|
||||
{
|
||||
sprintf (numbuf, "%d", history_is_stifled() ? history_max_entries : 0);
|
||||
#if defined (HAVE_VSNPRINTF)
|
||||
snprintf (numbuf, sizeof (numbuf), "%d", history_is_stifled() ? history_max_entries : -1);
|
||||
#else
|
||||
sprintf (numbuf, "%d", history_is_stifled() ? history_max_entries : -1);
|
||||
#endif
|
||||
return (numbuf);
|
||||
}
|
||||
else if (_rl_stricmp (name, "isearch-terminators") == 0)
|
||||
@@ -3014,7 +3023,11 @@ _rl_get_string_variable_value (const char *name)
|
||||
}
|
||||
else if (_rl_stricmp (name, "keyseq-timeout") == 0)
|
||||
{
|
||||
sprintf (numbuf, "%d", _rl_keyseq_timeout);
|
||||
#if defined (HAVE_VSNPRINTF)
|
||||
snprintf (numbuf, sizeof (numbuf), "%d", _rl_keyseq_timeout);
|
||||
#else
|
||||
sprintf (numbuf, "%d", _rl_keyseq_timeout);
|
||||
#endif
|
||||
return (numbuf);
|
||||
}
|
||||
else if (_rl_stricmp (name, "emacs-mode-string") == 0)
|
||||
|
||||
+18
-3
@@ -1,6 +1,6 @@
|
||||
/* callback.c -- functions to use readline as an X `callback' mechanism. */
|
||||
|
||||
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -115,7 +115,10 @@ rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *linefunc)
|
||||
#define CALLBACK_READ_RETURN() \
|
||||
do { \
|
||||
if (rl_persistent_signal_handlers == 0) \
|
||||
rl_clear_signals (); \
|
||||
{ \
|
||||
rl_clear_signals (); \
|
||||
if (_rl_caught_signal) _rl_signal_handler (_rl_caught_signal); \
|
||||
} \
|
||||
return; \
|
||||
} while (0)
|
||||
#else
|
||||
@@ -320,6 +323,15 @@ rl_callback_handler_remove (void)
|
||||
rl_linefunc = NULL;
|
||||
RL_UNSETSTATE (RL_STATE_CALLBACK);
|
||||
RL_CHECK_SIGNALS ();
|
||||
|
||||
/* Do what we need to do to manage the undo list if we haven't already done
|
||||
it in rl_callback_read_char(). If there's no undo list, we don't need to
|
||||
do anything. It doesn't matter if we try to revert all previous lines a
|
||||
second time; none of the history entries will have an undo list. */
|
||||
if (rl_undo_list)
|
||||
readline_common_teardown ();
|
||||
/* At this point, rl_undo_list == NULL. */
|
||||
|
||||
if (in_handler)
|
||||
{
|
||||
in_handler = 0;
|
||||
@@ -360,7 +372,7 @@ rl_callback_sigcleanup (void)
|
||||
if (RL_ISSTATE (RL_STATE_ISEARCH))
|
||||
_rl_isearch_cleanup (_rl_iscxt, 0);
|
||||
else if (RL_ISSTATE (RL_STATE_NSEARCH))
|
||||
_rl_nsearch_cleanup (_rl_nscxt, 0);
|
||||
_rl_nsearch_sigcleanup (_rl_nscxt, 0);
|
||||
else if (RL_ISSTATE (RL_STATE_VIMOTION))
|
||||
RL_UNSETSTATE (RL_STATE_VIMOTION);
|
||||
else if (RL_ISSTATE (RL_STATE_NUMERICARG))
|
||||
@@ -370,6 +382,9 @@ rl_callback_sigcleanup (void)
|
||||
}
|
||||
else if (RL_ISSTATE (RL_STATE_MULTIKEY))
|
||||
RL_UNSETSTATE (RL_STATE_MULTIKEY);
|
||||
else if (RL_ISSTATE (RL_STATE_READSTR))
|
||||
_rl_readstr_sigcleanup (_rl_rscxt, 0);
|
||||
|
||||
if (RL_ISSTATE (RL_STATE_CHARSEARCH))
|
||||
RL_UNSETSTATE (RL_STATE_CHARSEARCH);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#define largest_char 255 /* Largest character value. */
|
||||
|
||||
#define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
|
||||
#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
|
||||
#define META_CHAR(c) ((unsigned char)(c) > meta_character_threshold && (unsigned char)(c) <= largest_char)
|
||||
|
||||
#define CTRL(c) ((c) & control_character_mask)
|
||||
#define META(c) ((c) | meta_character_bit)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Modified by Chet Ramey for Readline.
|
||||
|
||||
Copyright (C) 1985, 1988, 1990-1991, 1995-2021
|
||||
Copyright (C) 1985, 1988, 1990-1991, 1995-2021, 2023
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
||||
+179
-170
@@ -1,6 +1,6 @@
|
||||
/* complete.c -- filename completion for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -77,11 +77,7 @@ extern int errno;
|
||||
# include "colors.h"
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef int QSFUNC (const void *, const void *);
|
||||
#else
|
||||
typedef int QSFUNC ();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LSTAT
|
||||
# define LSTAT lstat
|
||||
@@ -250,11 +246,24 @@ rl_icppfunc_t *rl_filename_stat_hook = (rl_icppfunc_t *)NULL;
|
||||
either return its first argument (if no conversion takes place) or
|
||||
newly-allocated memory. This can, for instance, convert filenames
|
||||
between character sets for comparison against what's typed at the
|
||||
keyboard. The returned value is what is added to the list of
|
||||
matches. The second argument is the length of the filename to be
|
||||
converted. */
|
||||
keyboard (after its potential modification by rl_completion_rewrite_hook).
|
||||
The returned value is what is added to the list of matches.
|
||||
The second argument is the length of the filename to be converted. */
|
||||
rl_dequote_func_t *rl_filename_rewrite_hook = (rl_dequote_func_t *)NULL;
|
||||
|
||||
/* If non-zero, this is the address of a function to call before
|
||||
comparing the filename portion of a word to be completed with directory
|
||||
entries from the filesystem. This takes the address of the partial word
|
||||
to be completed, after any rl_filename_dequoting_function has been applied.
|
||||
The function should either return its first argument (if no conversion
|
||||
takes place) or newly-allocated memory. This can, for instance, convert
|
||||
the filename portion of the completion word to a character set suitable
|
||||
for comparison against directory entries read from the filesystem (after
|
||||
their potential modification by rl_filename_rewrite_hook).
|
||||
The returned value is what is added to the list of matches.
|
||||
The second argument is the length of the filename to be converted. */
|
||||
rl_dequote_func_t *rl_completion_rewrite_hook = (rl_dequote_func_t *)NULL;
|
||||
|
||||
/* Non-zero means readline completion functions perform tilde expansion. */
|
||||
int rl_complete_with_tilde_expansion = 0;
|
||||
|
||||
@@ -340,6 +349,15 @@ int rl_filename_completion_desired = 0;
|
||||
entry finder function. */
|
||||
int rl_filename_quoting_desired = 1;
|
||||
|
||||
/* Non-zero means we should apply filename-type quoting to all completions
|
||||
even if we are not otherwise treating the matches as filenames. This is
|
||||
ALWAYS zero on entry, and can only be changed within a completion entry
|
||||
finder function. */
|
||||
int rl_full_quoting_desired = 0;
|
||||
|
||||
#define QUOTING_DESIRED() \
|
||||
(rl_full_quoting_desired || (rl_filename_completion_desired && rl_filename_quoting_desired))
|
||||
|
||||
/* This function, if defined, is called by the completer when real
|
||||
filename completion is done, after all the matching names have been
|
||||
generated. It is passed a (char**) known as matches in the code below.
|
||||
@@ -455,6 +473,7 @@ rl_complete (int ignore, int invoking_key)
|
||||
int
|
||||
rl_possible_completions (int ignore, int invoking_key)
|
||||
{
|
||||
last_completion_failed = 0;
|
||||
rl_completion_invoking_key = invoking_key;
|
||||
return (rl_complete_internal ('?'));
|
||||
}
|
||||
@@ -484,6 +503,32 @@ rl_completion_mode (rl_command_func_t *cfunc)
|
||||
return TAB;
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/* */
|
||||
/* Completion signal handling and cleanup */
|
||||
/* */
|
||||
/********************************************/
|
||||
|
||||
/* State to clean up and free if completion is interrupted by a signal. */
|
||||
typedef struct {
|
||||
char **matches;
|
||||
char *saved_line;
|
||||
} complete_sigcleanarg_t;
|
||||
|
||||
static void
|
||||
_rl_complete_sigcleanup (int sig, void *ptr)
|
||||
{
|
||||
complete_sigcleanarg_t *arg;
|
||||
|
||||
if (sig == SIGINT) /* XXX - for now */
|
||||
{
|
||||
arg = ptr;
|
||||
_rl_free_match_list (arg->matches);
|
||||
FREE (arg->saved_line);
|
||||
_rl_complete_display_matches_interrupt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************/
|
||||
/* */
|
||||
/* Completion utility functions */
|
||||
@@ -498,16 +543,6 @@ _rl_reset_completion_state (void)
|
||||
rl_completion_quote_character = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_complete_sigcleanup (int sig, void *ptr)
|
||||
{
|
||||
if (sig == SIGINT) /* XXX - for now */
|
||||
{
|
||||
_rl_free_match_list ((char **)ptr);
|
||||
_rl_complete_display_matches_interrupt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set default values for readline word completion. These are the variables
|
||||
that application completion functions can change or inspect. */
|
||||
static void
|
||||
@@ -516,6 +551,7 @@ set_completion_defaults (int what_to_do)
|
||||
/* Only the completion entry function can change these. */
|
||||
rl_filename_completion_desired = 0;
|
||||
rl_filename_quoting_desired = 1;
|
||||
rl_full_quoting_desired = 0;
|
||||
rl_completion_type = what_to_do;
|
||||
rl_completion_suppress_append = rl_completion_suppress_quote = 0;
|
||||
rl_completion_append_character = ' ';
|
||||
@@ -1319,6 +1355,7 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
|
||||
int low; /* Count of max-matched characters. */
|
||||
int lx;
|
||||
char *dtext; /* dequoted TEXT, if needed */
|
||||
size_t len1, len2;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
int v;
|
||||
size_t v1, v2;
|
||||
@@ -1345,6 +1382,9 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
|
||||
memset (&ps2, 0, sizeof (mbstate_t));
|
||||
}
|
||||
#endif
|
||||
len1 = strlen (match_list[i]);
|
||||
len2 = strlen (match_list[i + 1]);
|
||||
|
||||
for (si = 0; (c1 = match_list[i][si]) && (c2 = match_list[i + 1][si]); si++)
|
||||
{
|
||||
if (_rl_completion_case_fold)
|
||||
@@ -1355,8 +1395,8 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
v1 = MBRTOWC (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
|
||||
v2 = MBRTOWC (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
|
||||
v1 = MBRTOWC (&wc1, match_list[i]+si, len1 - si, &ps1);
|
||||
v2 = MBRTOWC (&wc2, match_list[i+1]+si, len2 - si, &ps2);
|
||||
if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
|
||||
{
|
||||
if (c1 != c2) /* do byte comparison */
|
||||
@@ -1412,10 +1452,8 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
|
||||
check against the list of matches
|
||||
FI */
|
||||
dtext = (char *)NULL;
|
||||
if (rl_filename_completion_desired &&
|
||||
rl_filename_dequoting_function &&
|
||||
rl_completion_found_quote &&
|
||||
rl_filename_quoting_desired)
|
||||
if (QUOTING_DESIRED() && rl_completion_found_quote &&
|
||||
rl_filename_dequoting_function)
|
||||
{
|
||||
dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
|
||||
text = dtext;
|
||||
@@ -1630,7 +1668,7 @@ rl_display_match_list (char **matches, int len, int max)
|
||||
if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
|
||||
{
|
||||
lines = _rl_internal_pager (lines);
|
||||
if (lines < 0)
|
||||
if (lines < 0 || _rl_complete_display_matches_interrupt)
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1658,7 +1696,7 @@ rl_display_match_list (char **matches, int len, int max)
|
||||
if (_rl_page_completions && lines >= _rl_screenheight - 1)
|
||||
{
|
||||
lines = _rl_internal_pager (lines);
|
||||
if (lines < 0)
|
||||
if (lines < 0 || _rl_complete_display_matches_interrupt)
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1745,7 +1783,9 @@ display_matches (char **matches)
|
||||
}
|
||||
}
|
||||
|
||||
rl_display_match_list (matches, len, max);
|
||||
/* We rely on the caller to set MATCHES to 0 when this returns. */
|
||||
if (_rl_complete_display_matches_interrupt == 0)
|
||||
rl_display_match_list (matches, len, max);
|
||||
|
||||
rl_forced_update_display ();
|
||||
rl_display_fixed = 1;
|
||||
@@ -1768,9 +1808,7 @@ make_quoted_replacement (char *match, int mtype, char *qc)
|
||||
matches don't require a quoted substring. */
|
||||
replacement = match;
|
||||
|
||||
should_quote = match && rl_completer_quote_characters &&
|
||||
rl_filename_completion_desired &&
|
||||
rl_filename_quoting_desired;
|
||||
should_quote = match && rl_completer_quote_characters && QUOTING_DESIRED();
|
||||
|
||||
if (should_quote)
|
||||
should_quote = should_quote && (!qc || !*qc ||
|
||||
@@ -1784,6 +1822,11 @@ make_quoted_replacement (char *match, int mtype, char *qc)
|
||||
should_quote = rl_filename_quote_characters
|
||||
? (_rl_strpbrk (match, rl_filename_quote_characters) != 0)
|
||||
: 0;
|
||||
/* If we saw a quote in the original word, but readline thinks the
|
||||
match doesn't need to be quoted, and the application has a filename
|
||||
quoting function, give the application a chance to quote it if
|
||||
needed so we don't second-guess the user. */
|
||||
should_quote |= *qc == 0 && rl_completion_found_quote && mtype != NO_MATCH && rl_filename_quoting_function;
|
||||
|
||||
do_replace = should_quote ? mtype : NO_MATCH;
|
||||
/* Quote the replacement, since we found an embedded
|
||||
@@ -1791,6 +1834,7 @@ make_quoted_replacement (char *match, int mtype, char *qc)
|
||||
if (do_replace != NO_MATCH && rl_filename_quoting_function)
|
||||
replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
|
||||
}
|
||||
|
||||
return (replacement);
|
||||
}
|
||||
|
||||
@@ -1976,8 +2020,7 @@ compare_match (char *text, const char *match)
|
||||
char *temp;
|
||||
int r;
|
||||
|
||||
if (rl_filename_completion_desired && rl_filename_quoting_desired &&
|
||||
rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
if (QUOTING_DESIRED() && rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
{
|
||||
temp = (*rl_filename_dequoting_function) (text, rl_completion_quote_character);
|
||||
r = strcmp (temp, match);
|
||||
@@ -2001,10 +2044,11 @@ rl_complete_internal (int what_to_do)
|
||||
{
|
||||
char **matches;
|
||||
rl_compentry_func_t *our_func;
|
||||
int start, end, delimiter, found_quote, i, nontrivial_lcd;
|
||||
int start, end, delimiter, found_quote, i, nontrivial_lcd, do_display;
|
||||
char *text, *saved_line_buffer;
|
||||
char quote_char;
|
||||
int tlen, mlen, saved_last_completion_failed;
|
||||
complete_sigcleanarg_t cleanarg; /* state to clean up on signal */
|
||||
|
||||
RL_SETSTATE(RL_STATE_COMPLETING);
|
||||
|
||||
@@ -2031,9 +2075,24 @@ rl_complete_internal (int what_to_do)
|
||||
|
||||
text = rl_copy_text (start, end);
|
||||
matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char);
|
||||
/* If TEXT contains quote characters, it will be dequoted as part of
|
||||
generating the matches, and the matches will not contain any quote
|
||||
characters. We need to dequote TEXT before performing the comparison.
|
||||
Since compare_match performs the dequoting, and we only want to do it
|
||||
once, we don't call compare_matches after dequoting TEXT; we call
|
||||
strcmp directly. */
|
||||
/* nontrivial_lcd is set if the common prefix adds something to the word
|
||||
being completed. */
|
||||
nontrivial_lcd = matches && compare_match (text, matches[0]) != 0;
|
||||
if (QUOTING_DESIRED() && rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
{
|
||||
char *t;
|
||||
t = (*rl_filename_dequoting_function) (text, rl_completion_quote_character);
|
||||
xfree (text);
|
||||
text = t;
|
||||
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
|
||||
}
|
||||
else
|
||||
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
|
||||
if (what_to_do == '!' || what_to_do == '@')
|
||||
tlen = strlen (text);
|
||||
xfree (text);
|
||||
@@ -2068,6 +2127,8 @@ rl_complete_internal (int what_to_do)
|
||||
if (matches && matches[0] && *matches[0])
|
||||
last_completion_failed = 0;
|
||||
|
||||
do_display = 0;
|
||||
|
||||
switch (what_to_do)
|
||||
{
|
||||
case TAB:
|
||||
@@ -2101,13 +2162,13 @@ rl_complete_internal (int what_to_do)
|
||||
{
|
||||
if (what_to_do == '!')
|
||||
{
|
||||
display_matches (matches);
|
||||
do_display = 1;
|
||||
break;
|
||||
}
|
||||
else if (what_to_do == '@')
|
||||
{
|
||||
if (nontrivial_lcd == 0)
|
||||
display_matches (matches);
|
||||
do_display = 1;
|
||||
break;
|
||||
}
|
||||
else if (rl_editing_mode != vi_mode)
|
||||
@@ -2131,23 +2192,11 @@ rl_complete_internal (int what_to_do)
|
||||
append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rl_completion_display_matches_hook == 0)
|
||||
{
|
||||
_rl_sigcleanup = _rl_complete_sigcleanup;
|
||||
_rl_sigcleanarg = matches;
|
||||
_rl_complete_display_matches_interrupt = 0;
|
||||
}
|
||||
display_matches (matches);
|
||||
if (_rl_complete_display_matches_interrupt)
|
||||
{
|
||||
matches = 0; /* already freed by rl_complete_sigcleanup */
|
||||
_rl_complete_display_matches_interrupt = 0;
|
||||
if (rl_signal_event_hook)
|
||||
(*rl_signal_event_hook) (); /* XXX */
|
||||
}
|
||||
_rl_sigcleanup = 0;
|
||||
_rl_sigcleanarg = 0;
|
||||
/*FALLTHROUGH*/
|
||||
|
||||
case '%': /* used by menu_complete */
|
||||
case '|': /* add this for unconditional display */
|
||||
do_display = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2160,6 +2209,34 @@ rl_complete_internal (int what_to_do)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If we need to display the match list, set up to clean it up on receipt of
|
||||
a signal and do it here. If the application has registered a function to
|
||||
display the matches, let it do the work. */
|
||||
if (do_display)
|
||||
{
|
||||
if (rl_completion_display_matches_hook == 0)
|
||||
{
|
||||
_rl_sigcleanup = _rl_complete_sigcleanup;
|
||||
cleanarg.matches = matches;
|
||||
cleanarg.saved_line = saved_line_buffer;
|
||||
_rl_sigcleanarg = &cleanarg;
|
||||
_rl_complete_display_matches_interrupt = 0;
|
||||
}
|
||||
|
||||
display_matches (matches);
|
||||
|
||||
if (_rl_complete_display_matches_interrupt)
|
||||
{
|
||||
matches = 0; /* Both already freed by _rl_complete_sigcleanup */
|
||||
saved_line_buffer = 0;
|
||||
_rl_complete_display_matches_interrupt = 0;
|
||||
if (rl_signal_event_hook)
|
||||
(*rl_signal_event_hook) ();
|
||||
}
|
||||
_rl_sigcleanup = 0;
|
||||
_rl_sigcleanarg = 0;
|
||||
}
|
||||
|
||||
_rl_free_match_list (matches);
|
||||
|
||||
/* Check to see if the line has changed through all of this manipulation. */
|
||||
@@ -2200,7 +2277,7 @@ rl_completion_matches (const char *text, rl_compentry_func_t *entry_function)
|
||||
register int i;
|
||||
|
||||
/* Number of slots in match_list. */
|
||||
int match_list_size;
|
||||
size_t match_list_size;
|
||||
|
||||
/* The list of matches. */
|
||||
char **match_list;
|
||||
@@ -2265,9 +2342,9 @@ rl_completion_matches (const char *text, rl_compentry_func_t *entry_function)
|
||||
char *
|
||||
rl_username_completion_function (const char *text, int state)
|
||||
{
|
||||
#if defined (__WIN32__) || defined (__OPENNT)
|
||||
#if defined (_WIN32) || defined (__OPENNT) || !defined (HAVE_GETPWENT)
|
||||
return (char *)NULL;
|
||||
#else /* !__WIN32__ && !__OPENNT) */
|
||||
#else /* !_WIN32 && !__OPENNT) && HAVE_GETPWENT */
|
||||
static char *username = (char *)NULL;
|
||||
static struct passwd *entry;
|
||||
static int namelen, first_char, first_char_loc;
|
||||
@@ -2282,25 +2359,19 @@ rl_username_completion_function (const char *text, int state)
|
||||
|
||||
username = savestring (&text[first_char_loc]);
|
||||
namelen = strlen (username);
|
||||
#if defined (HAVE_GETPWENT)
|
||||
setpwent ();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (HAVE_GETPWENT)
|
||||
while (entry = getpwent ())
|
||||
{
|
||||
/* Null usernames should result in all users as possible completions. */
|
||||
if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (entry == 0)
|
||||
{
|
||||
#if defined (HAVE_GETPWENT)
|
||||
endpwent ();
|
||||
#endif
|
||||
return ((char *)NULL);
|
||||
}
|
||||
else
|
||||
@@ -2316,7 +2387,7 @@ rl_username_completion_function (const char *text, int state)
|
||||
|
||||
return (value);
|
||||
}
|
||||
#endif /* !__WIN32__ && !__OPENNT */
|
||||
#endif /* !_WIN32 && !__OPENNT && HAVE_GETPWENT */
|
||||
}
|
||||
|
||||
/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
|
||||
@@ -2327,18 +2398,7 @@ rl_username_completion_function (const char *text, int state)
|
||||
static int
|
||||
complete_fncmp (const char *convfn, int convlen, const char *filename, int filename_len)
|
||||
{
|
||||
register char *s1, *s2;
|
||||
int d, len;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
size_t v1, v2;
|
||||
mbstate_t ps1, ps2;
|
||||
WCHAR_T wc1, wc2;
|
||||
#endif
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (&ps1, 0, sizeof (mbstate_t));
|
||||
memset (&ps2, 0, sizeof (mbstate_t));
|
||||
#endif
|
||||
size_t len;
|
||||
|
||||
if (filename_len == 0)
|
||||
return 1;
|
||||
@@ -2346,100 +2406,26 @@ complete_fncmp (const char *convfn, int convlen, const char *filename, int filen
|
||||
return 0;
|
||||
|
||||
len = filename_len;
|
||||
s1 = (char *)convfn;
|
||||
s2 = (char *)filename;
|
||||
|
||||
/* Otherwise, if these match up to the length of filename, then
|
||||
it is a match. */
|
||||
if (_rl_completion_case_fold && _rl_completion_case_map)
|
||||
if (_rl_completion_case_fold)
|
||||
{
|
||||
/* Case-insensitive comparison treating _ and - as equivalent */
|
||||
/* Case-insensitive comparison treating _ and - as equivalent if
|
||||
_rl_completion_case_map is non-zero */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
v1 = MBRTOWC (&wc1, s1, convlen, &ps1);
|
||||
v2 = MBRTOWC (&wc2, s2, filename_len, &ps2);
|
||||
if (v1 == 0 && v2 == 0)
|
||||
return 1;
|
||||
else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
|
||||
{
|
||||
if (*s1 != *s2) /* do byte comparison */
|
||||
return 0;
|
||||
else if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
|
||||
return 0;
|
||||
s1++; s2++; len--;
|
||||
continue;
|
||||
}
|
||||
wc1 = towlower (wc1);
|
||||
wc2 = towlower (wc2);
|
||||
s1 += v1;
|
||||
s2 += v1;
|
||||
len -= v1;
|
||||
if ((wc1 == L'-' || wc1 == L'_') && (wc2 == L'-' || wc2 == L'_'))
|
||||
continue;
|
||||
if (wc1 != wc2)
|
||||
return 0;
|
||||
}
|
||||
while (len != 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
do
|
||||
{
|
||||
d = _rl_to_lower (*s1) - _rl_to_lower (*s2);
|
||||
/* *s1 == [-_] && *s2 == [-_] */
|
||||
if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
|
||||
d = 0;
|
||||
if (d != 0)
|
||||
return 0;
|
||||
s1++; s2++; /* already checked convlen >= filename_len */
|
||||
}
|
||||
while (--len != 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (_rl_completion_case_fold)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
v1 = MBRTOWC (&wc1, s1, convlen, &ps1);
|
||||
v2 = MBRTOWC (&wc2, s2, filename_len, &ps2);
|
||||
if (v1 == 0 && v2 == 0)
|
||||
return 1;
|
||||
else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
|
||||
{
|
||||
if (*s1 != *s2) /* do byte comparison */
|
||||
return 0;
|
||||
s1++; s2++; len--;
|
||||
continue;
|
||||
}
|
||||
wc1 = towlower (wc1);
|
||||
wc2 = towlower (wc2);
|
||||
if (wc1 != wc2)
|
||||
return 0;
|
||||
s1 += v1;
|
||||
s2 += v1;
|
||||
len -= v1;
|
||||
}
|
||||
while (len != 0);
|
||||
return 1;
|
||||
}
|
||||
return (_rl_mb_strcaseeqn (convfn, convlen, filename, filename_len, len, _rl_completion_case_map));
|
||||
else
|
||||
#endif
|
||||
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
|
||||
(convlen >= filename_len) &&
|
||||
(_rl_strnicmp (filename, convfn, filename_len) == 0))
|
||||
return 1;
|
||||
(convlen >= filename_len))
|
||||
return (_rl_strcaseeqn (convfn, filename, len, _rl_completion_case_map));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX - add new _rl_mb_streqn function (like mbsncmp) instead of
|
||||
relying on byte equivalence? */
|
||||
if ((convfn[0] == filename[0]) &&
|
||||
(convlen >= filename_len) &&
|
||||
(strncmp (filename, convfn, filename_len) == 0))
|
||||
@@ -2461,7 +2447,8 @@ rl_filename_completion_function (const char *text, int state)
|
||||
static char *users_dirname = (char *)NULL;
|
||||
static int filename_len;
|
||||
char *temp, *dentry, *convfn;
|
||||
int dirlen, dentlen, convlen;
|
||||
size_t dirlen;
|
||||
int dentlen, convlen;
|
||||
int tilde_dirname;
|
||||
struct dirent *entry;
|
||||
|
||||
@@ -2526,7 +2513,8 @@ rl_filename_completion_function (const char *text, int state)
|
||||
temp = tilde_expand (dirname);
|
||||
xfree (dirname);
|
||||
dirname = temp;
|
||||
tilde_dirname = 1;
|
||||
if (*dirname != '~')
|
||||
tilde_dirname = 1; /* indicate successful tilde expansion */
|
||||
}
|
||||
|
||||
/* We have saved the possibly-dequoted version of the directory name
|
||||
@@ -2545,11 +2533,16 @@ rl_filename_completion_function (const char *text, int state)
|
||||
xfree (users_dirname);
|
||||
users_dirname = savestring (dirname);
|
||||
}
|
||||
else if (tilde_dirname == 0 && rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
else if (rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
{
|
||||
/* delete single and double quotes */
|
||||
/* We already ran users_dirname through the dequoting function.
|
||||
If tilde_dirname == 1, we successfully performed tilde expansion
|
||||
on dirname. Now we need to reconcile those results. We either
|
||||
just copy the already-dequoted users_dirname or tilde expand it
|
||||
if we tilde-expanded dirname. */
|
||||
temp = tilde_dirname ? tilde_expand (users_dirname) : savestring (users_dirname);
|
||||
xfree (dirname);
|
||||
dirname = savestring (users_dirname);
|
||||
dirname = temp;
|
||||
}
|
||||
directory = opendir (dirname);
|
||||
|
||||
@@ -2564,6 +2557,18 @@ rl_filename_completion_function (const char *text, int state)
|
||||
}
|
||||
filename_len = strlen (filename);
|
||||
|
||||
/* Normalize the filename if the application has set a rewrite hook. */
|
||||
if (*filename && rl_completion_rewrite_hook)
|
||||
{
|
||||
temp = (*rl_completion_rewrite_hook) (filename, filename_len);
|
||||
if (temp != filename)
|
||||
{
|
||||
xfree (filename);
|
||||
filename = temp;
|
||||
filename_len = strlen (filename);
|
||||
}
|
||||
}
|
||||
|
||||
rl_filename_completion_desired = 1;
|
||||
}
|
||||
|
||||
@@ -2576,6 +2581,7 @@ rl_filename_completion_function (const char *text, int state)
|
||||
/* Now that we have some state, we can read the directory. */
|
||||
|
||||
entry = (struct dirent *)NULL;
|
||||
convfn = dentry = 0;
|
||||
while (directory && (entry = readdir (directory)))
|
||||
{
|
||||
convfn = dentry = entry->d_name;
|
||||
@@ -2593,17 +2599,20 @@ rl_filename_completion_function (const char *text, int state)
|
||||
if (filename_len == 0)
|
||||
{
|
||||
if (_rl_match_hidden_files == 0 && HIDDEN_FILE (convfn))
|
||||
continue;
|
||||
{
|
||||
if (convfn != dentry)
|
||||
xfree (convfn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (convfn[0] != '.' ||
|
||||
(convfn[1] && (convfn[1] != '.' || convfn[2])))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (complete_fncmp (convfn, convlen, filename, filename_len))
|
||||
break;
|
||||
}
|
||||
else if (complete_fncmp (convfn, convlen, filename, filename_len))
|
||||
break;
|
||||
else if (convfn != dentry)
|
||||
xfree (convfn);
|
||||
}
|
||||
|
||||
if (entry == 0)
|
||||
@@ -2825,7 +2834,7 @@ rl_menu_complete (int count, int ignore)
|
||||
static int full_completion = 0; /* set to 1 if menu completion should reinitialize on next call */
|
||||
static int orig_start, orig_end;
|
||||
static char quote_char;
|
||||
static int delimiter, cstate;
|
||||
static int delimiter;
|
||||
|
||||
/* The first time through, we generate the list of matches and set things
|
||||
up to insert them. */
|
||||
@@ -2921,7 +2930,7 @@ rl_menu_complete (int count, int ignore)
|
||||
if (rl_completion_query_items > 0 && match_list_size >= rl_completion_query_items)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
_rl_free_match_list (matches);
|
||||
matches = (char **)0;
|
||||
full_completion = 1;
|
||||
return (0);
|
||||
|
||||
+202
-115
@@ -1,6 +1,6 @@
|
||||
/* display.c -- readline redisplay facility. */
|
||||
|
||||
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -59,10 +59,6 @@
|
||||
#include "rlprivate.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#if !defined (strchr) && !defined (__STDC__)
|
||||
extern char *strchr (), *strrchr ();
|
||||
#endif /* !strchr && !__STDC__ */
|
||||
|
||||
static void putc_face (int, int, char *);
|
||||
static void puts_face (const char *, const char *, int);
|
||||
static void norm_face (char *, int);
|
||||
@@ -282,6 +278,10 @@ static int prompt_physical_chars;
|
||||
characters in the prompt or use heuristics about where they are. */
|
||||
static int *local_prompt_newlines;
|
||||
|
||||
/* An array saying how many invisible characters are in each line of the
|
||||
prompt. */
|
||||
static int *local_prompt_invis_chars;
|
||||
|
||||
/* set to a non-zero value by rl_redisplay if we are marking modified history
|
||||
lines and the current line is so marked. */
|
||||
static int modmark;
|
||||
@@ -295,6 +295,7 @@ static int line_totbytes;
|
||||
static char *saved_local_prompt;
|
||||
static char *saved_local_prefix;
|
||||
static int *saved_local_prompt_newlines;
|
||||
static int *saved_local_prompt_invis_chars;
|
||||
|
||||
static int saved_last_invisible;
|
||||
static int saved_visible_length;
|
||||
@@ -356,7 +357,7 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
|
||||
{
|
||||
char *r, *ret, *p, *igstart, *nprompt, *ms;
|
||||
int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
|
||||
int mlen, newlines, newlines_guess, bound, can_add_invis;
|
||||
int mlen, newlines, newlines_guess, bound, can_add_invis, lastinvis;
|
||||
int mb_cur_max;
|
||||
|
||||
/* We only expand the mode string for the last line of a multiline prompt
|
||||
@@ -399,7 +400,8 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
|
||||
*vlp = l;
|
||||
|
||||
local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * 2);
|
||||
local_prompt_newlines[0] = 0;
|
||||
local_prompt_invis_chars = (int *) xrealloc (local_prompt_invis_chars, sizeof (int) * 2);
|
||||
local_prompt_newlines[0] = local_prompt_invis_chars[0] = 0;
|
||||
local_prompt_newlines[1] = -1;
|
||||
|
||||
return r;
|
||||
@@ -414,15 +416,20 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
|
||||
newlines_guess = (_rl_screenwidth > 0) ? APPROX_DIV(l, _rl_screenwidth) : APPROX_DIV(l, 80);
|
||||
local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * (newlines_guess + 1));
|
||||
local_prompt_newlines[newlines = 0] = 0;
|
||||
local_prompt_invis_chars = (int *) xrealloc (local_prompt_invis_chars, sizeof (int) * (newlines_guess + 1));
|
||||
local_prompt_invis_chars[0] = 0;
|
||||
for (rl = 1; rl <= newlines_guess; rl++)
|
||||
local_prompt_newlines[rl] = -1;
|
||||
{
|
||||
local_prompt_newlines[rl] = -1;
|
||||
local_prompt_invis_chars[rl] = 0;
|
||||
}
|
||||
|
||||
rl = physchars = 0; /* mode string now part of nprompt */
|
||||
invfl = 0; /* invisible chars in first line of prompt */
|
||||
invflset = 0; /* we only want to set invfl once */
|
||||
igstart = 0; /* we're not ignoring any characters yet */
|
||||
|
||||
for (ignoring = last = ninvis = 0, p = nprompt; p && *p; p++)
|
||||
for (ignoring = last = ninvis = lastinvis = 0, p = nprompt; p && *p; p++)
|
||||
{
|
||||
/* This code strips the invisible character string markers
|
||||
RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
|
||||
@@ -447,6 +454,8 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
|
||||
counter. */
|
||||
if (invflset && newlines == 1)
|
||||
invfl = ninvis;
|
||||
local_prompt_invis_chars[newlines - 1] = ninvis - lastinvis;
|
||||
lastinvis = ninvis;
|
||||
}
|
||||
if (p != (igstart + 1))
|
||||
last = r - ret - 1;
|
||||
@@ -511,6 +520,8 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
|
||||
else
|
||||
new = r - ret;
|
||||
local_prompt_newlines[++newlines] = new;
|
||||
local_prompt_invis_chars[newlines - 1] = ninvis - lastinvis;
|
||||
lastinvis = ninvis;
|
||||
}
|
||||
|
||||
/* What if a physical character of width >= 2 is split? There is
|
||||
@@ -525,6 +536,9 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
|
||||
if (rl <= _rl_screenwidth)
|
||||
invfl = ninvis;
|
||||
|
||||
/* Make sure we account for invisible characters on the last line. */
|
||||
local_prompt_invis_chars[newlines] = ninvis - lastinvis;
|
||||
|
||||
*r = '\0';
|
||||
if (lp)
|
||||
*lp = rl;
|
||||
@@ -591,13 +605,22 @@ rl_expand_prompt (char *prompt)
|
||||
FREE (local_prompt);
|
||||
FREE (local_prompt_prefix);
|
||||
|
||||
/* Set default values for variables expand_prompt sets */
|
||||
local_prompt = local_prompt_prefix = (char *)0;
|
||||
local_prompt_len = 0;
|
||||
prompt_last_invisible = prompt_invis_chars_first_line = 0;
|
||||
prompt_visible_length = prompt_physical_chars = 0;
|
||||
|
||||
if (local_prompt_invis_chars == 0)
|
||||
local_prompt_invis_chars = (int *)xmalloc (sizeof (int));
|
||||
local_prompt_invis_chars[0] = 0;
|
||||
|
||||
if (prompt == 0 || *prompt == 0)
|
||||
return (0);
|
||||
{
|
||||
local_prompt = xmalloc (sizeof (char));
|
||||
local_prompt[0] = '\0';
|
||||
return (0);
|
||||
}
|
||||
|
||||
p = strrchr (prompt, '\n');
|
||||
if (p == 0)
|
||||
@@ -641,8 +664,8 @@ rl_expand_prompt (char *prompt)
|
||||
static void
|
||||
realloc_line (int minsize)
|
||||
{
|
||||
int minimum_size;
|
||||
int newsize, delta;
|
||||
size_t minimum_size;
|
||||
size_t newsize, delta;
|
||||
|
||||
minimum_size = DEFAULT_LINE_BUFFER_SIZE;
|
||||
if (minsize < minimum_size)
|
||||
@@ -684,7 +707,7 @@ init_line_structures (int minsize)
|
||||
if (line_size > minsize)
|
||||
minsize = line_size;
|
||||
}
|
||||
realloc_line (minsize);
|
||||
realloc_line (minsize);
|
||||
|
||||
if (vis_lbreaks == 0)
|
||||
{
|
||||
@@ -758,16 +781,39 @@ _rl_optimize_redisplay (void)
|
||||
_rl_quick_redisplay = 1;
|
||||
}
|
||||
|
||||
/* Useful shorthand used by rl_redisplay, update_line, rl_move_cursor_relative */
|
||||
#define INVIS_FIRST() (local_prompt_invis_chars[0])
|
||||
#define WRAP_OFFSET(line, offset) ((line <= prompt_last_screen_line) ? local_prompt_invis_chars[line] : 0)
|
||||
|
||||
#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
|
||||
#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
|
||||
#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
|
||||
#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
|
||||
#define VIS_FACE(line) (vis_face + vis_lbreaks[line])
|
||||
#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
|
||||
#define VIS_LINE_FACE(line) ((line) > _rl_vis_botlin) ? "" : VIS_FACE(line)
|
||||
#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
|
||||
#define INV_LINE_FACE(line) (inv_face + inv_lbreaks[line])
|
||||
|
||||
#define INV_CHARS_CURRENT_PROMPT_LINE(line) \
|
||||
(local_prompt_invis_chars[line] > 0)
|
||||
|
||||
#define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
|
||||
_rl_last_c_pos != o_cpos && \
|
||||
_rl_last_c_pos > wrap_offset && \
|
||||
o_cpos < prompt_last_invisible)
|
||||
|
||||
/* Basic redisplay algorithm. See comments inline. */
|
||||
void
|
||||
rl_redisplay (void)
|
||||
{
|
||||
int in, out, c, linenum, cursor_linenum;
|
||||
int inv_botlin, lb_botlin, lb_linenum, o_cpos;
|
||||
int newlines, lpos, temp, n0, num, prompt_lines_estimate;
|
||||
int newlines, lpos, temp, num, prompt_lines_estimate;
|
||||
char *prompt_this_line;
|
||||
char cur_face;
|
||||
int hl_begin, hl_end;
|
||||
int short_circuit;
|
||||
int mb_cur_max = MB_CUR_MAX;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
WCHAR_T wc;
|
||||
@@ -953,7 +999,7 @@ rl_redisplay (void)
|
||||
the line breaks in the prompt string in expand_prompt, taking invisible
|
||||
characters into account, and if lpos exceeds the screen width, we copy
|
||||
the data in the loop below. */
|
||||
lpos = prompt_physical_chars + modmark;
|
||||
lpos = local_prompt ? prompt_physical_chars + modmark : 0;
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
|
||||
@@ -964,6 +1010,9 @@ rl_redisplay (void)
|
||||
in the first physical line of the prompt.
|
||||
wrap_offset - prompt_invis_chars_first_line is usually the number of
|
||||
invis chars on the second (or, more generally, last) line. */
|
||||
/* XXX - There is code that assumes that all the invisible characters occur
|
||||
on the first and last prompt lines; change that to use
|
||||
local_prompt_invis_chars */
|
||||
|
||||
/* This is zero-based, used to set the newlines */
|
||||
prompt_lines_estimate = lpos / _rl_screenwidth;
|
||||
@@ -982,6 +1031,7 @@ rl_redisplay (void)
|
||||
}
|
||||
|
||||
/* Now set lpos from the last newline */
|
||||
/* XXX - change to use local_prompt_invis_chars[] */
|
||||
if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
|
||||
lpos = _rl_col_width (local_prompt, temp, local_prompt_len, 1) - (wrap_offset - prompt_invis_chars_first_line);
|
||||
else
|
||||
@@ -1044,6 +1094,8 @@ rl_redisplay (void)
|
||||
wc_width = (temp >= 0) ? temp : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
wc_width = 1; /* make sure it's set for the META_CHAR check */
|
||||
#endif
|
||||
|
||||
if (in == rl_point)
|
||||
@@ -1053,31 +1105,32 @@ rl_redisplay (void)
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
|
||||
if (META_CHAR (c) && wc_bytes == 1 && wc_width == 1)
|
||||
#else
|
||||
if (META_CHAR (c))
|
||||
#endif
|
||||
{
|
||||
#if 0
|
||||
/* TAG: readline-8.3 20230227 */
|
||||
/* https://savannah.gnu.org/support/index.php?110830
|
||||
asking for non-printing meta characters to be printed using an
|
||||
escape sequence. */
|
||||
|
||||
/* isprint(c) handles bytes up to UCHAR_MAX */
|
||||
if (_rl_output_meta_chars == 0 || isprint (c) == 0)
|
||||
#else
|
||||
if (_rl_output_meta_chars == 0)
|
||||
#endif
|
||||
{
|
||||
char obuf[5];
|
||||
int olen;
|
||||
|
||||
#if defined (HAVE_VSNPRINTF)
|
||||
olen = snprintf (obuf, sizeof (obuf), "\\%o", c);
|
||||
#else
|
||||
olen = sprintf (obuf, "\\%o", c);
|
||||
|
||||
if (lpos + olen >= _rl_screenwidth)
|
||||
{
|
||||
temp = _rl_screenwidth - lpos;
|
||||
CHECK_INV_LBREAKS ();
|
||||
inv_lbreaks[++newlines] = out + temp;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
|
||||
#endif
|
||||
lpos = olen - temp;
|
||||
}
|
||||
else
|
||||
lpos += olen;
|
||||
|
||||
|
||||
for (temp = 0; temp < olen; temp++)
|
||||
{
|
||||
invis_addc (&out, obuf[temp], cur_face);
|
||||
@@ -1249,26 +1302,6 @@ rl_redisplay (void)
|
||||
second and subsequent lines start at inv_lbreaks[N], offset by
|
||||
OFFSET (which has already been calculated above). */
|
||||
|
||||
#define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
|
||||
#define WRAP_OFFSET(line, offset) ((line == 0) \
|
||||
? (offset ? INVIS_FIRST() : 0) \
|
||||
: ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
|
||||
#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
|
||||
#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
|
||||
#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
|
||||
#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
|
||||
#define VIS_FACE(line) (vis_face + vis_lbreaks[line])
|
||||
#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
|
||||
#define VIS_LINE_FACE(line) ((line) > _rl_vis_botlin) ? "" : VIS_FACE(line)
|
||||
#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
|
||||
#define INV_LINE_FACE(line) (inv_face + inv_lbreaks[line])
|
||||
|
||||
#define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
|
||||
_rl_last_c_pos != o_cpos && \
|
||||
_rl_last_c_pos > wrap_offset && \
|
||||
o_cpos < prompt_last_invisible)
|
||||
|
||||
|
||||
/* We don't want to highlight anything that's going to be off the top
|
||||
of the display; if the current line takes up more than an entire
|
||||
screen, just mark the lines that won't be displayed as having a
|
||||
@@ -1283,9 +1316,54 @@ rl_redisplay (void)
|
||||
norm_face (INV_LINE_FACE(linenum), INV_LLEN (linenum));
|
||||
}
|
||||
|
||||
/* XXX - experimental new code */
|
||||
/* Now that _rl_last_v_pos is a logical count, not bounded by the
|
||||
number of physical screen lines, this is a start at being able
|
||||
to redisplay lines that consume more than the number of physical
|
||||
screen lines in more than a simple `move-to-the-next-line' way.
|
||||
|
||||
If the new line has more lines than there are physical screen
|
||||
lines, and the cursor would be off the top of the screen if we
|
||||
displayed all the new lines, clear the screen without killing
|
||||
the scrollback buffer, clear out the visible line so we do a
|
||||
complete redraw, and make the loop break when we have displayed
|
||||
a physical screen full of lines. Do the same if we are going to
|
||||
move the cursor to a line that's greater than the number of
|
||||
physical screen lines when we weren't before.
|
||||
|
||||
SHORT_CIRCUIT says where to break the loop. Pretty simple right now. */
|
||||
short_circuit = -1;
|
||||
if (inv_botlin >= _rl_screenheight)
|
||||
{
|
||||
int extra;
|
||||
|
||||
extra = inv_botlin - _rl_screenheight; /* lines off the top */
|
||||
/* cursor in portion of line that would be off screen or in
|
||||
the lines that exceed the number of physical screen lines. */
|
||||
if (cursor_linenum <= extra ||
|
||||
(cursor_linenum >= _rl_screenheight && _rl_vis_botlin <= _rl_screenheight))
|
||||
{
|
||||
if (cursor_linenum <= extra)
|
||||
short_circuit = _rl_screenheight;
|
||||
_rl_clear_screen (0);
|
||||
if (visible_line)
|
||||
memset (visible_line, 0, line_size);
|
||||
rl_on_new_line ();
|
||||
}
|
||||
/* The cursor is beyond the number of lines that would be off
|
||||
the top, but we still want to display only the first
|
||||
_RL_SCREENHEIGHT lines starting at the beginning of the line. */
|
||||
else if (cursor_linenum > extra && cursor_linenum <= _rl_screenheight &&
|
||||
_rl_vis_botlin <= _rl_screenheight)
|
||||
short_circuit = _rl_screenheight;
|
||||
}
|
||||
|
||||
/* For each line in the buffer, do the updating display. */
|
||||
for (linenum = 0; linenum <= inv_botlin; linenum++)
|
||||
{
|
||||
if (short_circuit >= 0 && linenum == short_circuit)
|
||||
break;
|
||||
|
||||
/* This can lead us astray if we execute a program that changes
|
||||
the locale from a non-multibyte to a multibyte one. */
|
||||
o_cpos = _rl_last_c_pos;
|
||||
@@ -1319,6 +1397,7 @@ rl_redisplay (void)
|
||||
between the first and last lines of the prompt, if the
|
||||
prompt consumes more than two lines. It's usually right */
|
||||
/* XXX - not sure this is ever executed */
|
||||
/* XXX - use local_prompt_invis_chars[linenum] */
|
||||
_rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
|
||||
|
||||
/* If this is the line with the prompt, we might need to
|
||||
@@ -1388,7 +1467,7 @@ rl_redisplay (void)
|
||||
((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
|
||||
}
|
||||
}
|
||||
_rl_vis_botlin = inv_botlin;
|
||||
_rl_vis_botlin = (short_circuit >= 0) ? short_circuit : inv_botlin;
|
||||
|
||||
/* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
|
||||
different screen line during this redisplay. */
|
||||
@@ -1413,6 +1492,7 @@ rl_redisplay (void)
|
||||
only need to reprint it if the cursor is before the last
|
||||
invisible character in the prompt string. */
|
||||
/* XXX - why not use local_prompt_len? */
|
||||
/* XXX - This is right only if the prompt is a single line. */
|
||||
nleft = prompt_visible_length + wrap_offset;
|
||||
if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
|
||||
_rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
|
||||
@@ -1895,6 +1975,8 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
|
||||
/* See comments at dumb_update: for an explanation of this heuristic */
|
||||
if (nmax < omax)
|
||||
goto clear_rest_of_line;
|
||||
/* XXX - need to use WRAP_OFFSET(current_line, wrap_offset) instead of
|
||||
W_OFFSET - XXX */
|
||||
else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
|
||||
goto clear_rest_of_line;
|
||||
else
|
||||
@@ -1981,7 +2063,11 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
|
||||
assume it's a combining character and back one up so the two base
|
||||
characters no longer compare equivalently. */
|
||||
t = MBRTOWC (&wc, ofd, mb_cur_max, &ps);
|
||||
#if 0
|
||||
if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
|
||||
#else
|
||||
if (t > 0 && IS_COMBINING_CHAR (wc))
|
||||
#endif
|
||||
{
|
||||
old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
|
||||
new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
|
||||
@@ -1998,6 +2084,8 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* Find the last character that is the same between the two lines. This
|
||||
bounds the region that needs to change. */
|
||||
/* In this case, `last character' means the one farthest from the end of
|
||||
the line. */
|
||||
if (mb_cur_max > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
|
||||
@@ -2014,7 +2102,7 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
|
||||
*olsf != *nlsf)
|
||||
break;
|
||||
|
||||
if (*ols == ' ')
|
||||
if (*ols != ' ')
|
||||
wsatend = 0;
|
||||
|
||||
ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
|
||||
@@ -2076,14 +2164,30 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
|
||||
}
|
||||
|
||||
/* count of invisible characters in the current invisible line. */
|
||||
current_invis_chars = W_OFFSET (current_line, wrap_offset);
|
||||
current_invis_chars = WRAP_OFFSET (current_line, wrap_offset);
|
||||
if (_rl_last_v_pos != current_line)
|
||||
{
|
||||
_rl_move_vert (current_line);
|
||||
/* We have moved up to a new screen line. This line may or may not have
|
||||
invisible characters on it, but we do our best to recalculate
|
||||
visible_wrap_offset based on what we know. */
|
||||
if (current_line == 0)
|
||||
/* This first clause handles the case where the prompt has been
|
||||
recalculated (e.g., by rl_message) but the old prompt is still on
|
||||
the visible line because we haven't overwritten it yet. We want
|
||||
to somehow use the old prompt information, but we only want to do
|
||||
this once. */
|
||||
if (current_line == 0 && saved_local_prompt && old[0] == saved_local_prompt[0] && memcmp (old, saved_local_prompt, saved_local_length) == 0)
|
||||
visible_wrap_offset = saved_invis_chars_first_line;
|
||||
/* This clause handles the opposite: the prompt has been restored (e.g.,
|
||||
by rl_clear_message) but the old saved_local_prompt (now NULL, so we
|
||||
can't directly check it) is still on the visible line because we
|
||||
haven't overwritten it yet. We guess that there aren't any invisible
|
||||
characters in any of the prompts we put in with rl_message */
|
||||
else if (current_line == 0 && local_prompt && new[0] == local_prompt[0] &&
|
||||
(memcmp (new, local_prompt, local_prompt_len) == 0) &&
|
||||
(memcmp (old, local_prompt, local_prompt_len) != 0))
|
||||
visible_wrap_offset = 0;
|
||||
else if (current_line == 0)
|
||||
visible_wrap_offset = prompt_invis_chars_first_line; /* XXX */
|
||||
#if 0 /* XXX - not yet */
|
||||
else if (current_line == prompt_last_screen_line && wrap_offset > prompt_invis_chars_first_line)
|
||||
@@ -2140,6 +2244,7 @@ update_line (char *old, char *old_face, char *new, char *new_face, int current_l
|
||||
else
|
||||
/* We take wrap_offset into account here so we can pass correct
|
||||
information to _rl_move_cursor_relative. */
|
||||
/* XXX - can use local_prompt_invis_chars[0] instead of wrap_offset */
|
||||
_rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
|
||||
cpos_adjusted = 1;
|
||||
}
|
||||
@@ -2183,6 +2288,7 @@ dumb_update:
|
||||
wrap_offset-prompt_invis_chars_first_line
|
||||
on the assumption that this is the number of invisible
|
||||
characters in the last line of the prompt. */
|
||||
/* XXX - CHANGE THIS USING local_prompt_invis_chars[current_line] */
|
||||
if (wrap_offset > prompt_invis_chars_first_line &&
|
||||
current_line == prompt_last_screen_line &&
|
||||
prompt_physical_chars > _rl_screenwidth &&
|
||||
@@ -2201,6 +2307,20 @@ dumb_update:
|
||||
wrap_offset >= prompt_invis_chars_first_line &&
|
||||
_rl_horizontal_scroll_mode == 0)
|
||||
ADJUST_CPOS (prompt_invis_chars_first_line);
|
||||
/* XXX - This is experimental. It's a start at supporting
|
||||
prompts where a non-terminal line contains the last
|
||||
invisible characters. We assume that we can use the
|
||||
local_prompt_invis_chars array and that the current line
|
||||
is completely filled with characters to _rl_screenwidth,
|
||||
so we can either adjust by the number of bytes in the
|
||||
current line or just go straight to _rl_screenwidth */
|
||||
else if (current_line > 0 && current_line < prompt_last_screen_line &&
|
||||
INV_CHARS_CURRENT_PROMPT_LINE(current_line) &&
|
||||
_rl_horizontal_scroll_mode == 0)
|
||||
{
|
||||
_rl_last_c_pos = _rl_screenwidth;
|
||||
cpos_adjusted = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
_rl_last_c_pos += temp;
|
||||
@@ -2212,6 +2332,8 @@ dumb_update:
|
||||
know for sure, so we use another heuristic calclulation below. */
|
||||
if (nmax < omax)
|
||||
goto clear_rest_of_line; /* XXX */
|
||||
/* XXX - use WRAP_OFFSET(current_line, wrap_offset) here instead of
|
||||
W_OFFSET since current_line == 0 */
|
||||
else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
|
||||
goto clear_rest_of_line;
|
||||
else
|
||||
@@ -2680,8 +2802,6 @@ rl_on_new_line_with_prompt (void)
|
||||
int
|
||||
rl_forced_update_display (void)
|
||||
{
|
||||
register char *temp;
|
||||
|
||||
if (visible_line)
|
||||
memset (visible_line, 0, line_size);
|
||||
|
||||
@@ -2763,7 +2883,7 @@ _rl_move_cursor_relative (int new, const char *data, const char *dataf)
|
||||
(prompt_last_invisible) in the last line. IN_INVISLINE is the
|
||||
offset of DATA in invisible_line */
|
||||
in_invisline = 0;
|
||||
if (data > invisible_line && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
|
||||
if (data > invisible_line && _rl_inv_botlin < inv_lbsize && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
|
||||
in_invisline = data - invisible_line;
|
||||
|
||||
/* Use NEW when comparing against the last invisible character in the
|
||||
@@ -2866,9 +2986,25 @@ _rl_move_vert (int to)
|
||||
{
|
||||
register int delta, i;
|
||||
|
||||
if (_rl_last_v_pos == to || to > _rl_screenheight)
|
||||
if (_rl_last_v_pos == to)
|
||||
return;
|
||||
|
||||
#if 0
|
||||
/* If we're being asked to move to a line beyond the screen height, and
|
||||
we're currently at the last physical line, issue a newline and let the
|
||||
terminal take care of scrolling the display. */
|
||||
if (to >= _rl_screenheight)
|
||||
{
|
||||
if (_rl_last_v_pos == _rl_screenheight)
|
||||
{
|
||||
putc ('\n', rl_outstream);
|
||||
_rl_cr ();
|
||||
_rl_last_c_pos = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((delta = to - _rl_last_v_pos) > 0)
|
||||
{
|
||||
for (i = 0; i < delta; i++)
|
||||
@@ -2952,29 +3088,15 @@ rl_character_len (int c, int pos)
|
||||
mini-modeline. */
|
||||
static int msg_saved_prompt = 0;
|
||||
|
||||
#if defined (USE_VARARGS)
|
||||
int
|
||||
#if defined (PREFER_STDARG)
|
||||
rl_message (const char *format, ...)
|
||||
#else
|
||||
rl_message (va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#if defined (PREFER_VARARGS)
|
||||
char *format;
|
||||
#endif
|
||||
#if defined (HAVE_VSNPRINTF)
|
||||
int bneed;
|
||||
#endif
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
if (msg_buf == 0)
|
||||
msg_buf = xmalloc (msg_bufsiz = 128);
|
||||
@@ -2987,12 +3109,7 @@ rl_message (va_alist)
|
||||
msg_buf = xrealloc (msg_buf, msg_bufsiz);
|
||||
va_end (args);
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
|
||||
}
|
||||
#else
|
||||
@@ -3023,40 +3140,6 @@ rl_message (va_alist)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* !USE_VARARGS */
|
||||
int
|
||||
rl_message (format, arg1, arg2)
|
||||
char *format;
|
||||
{
|
||||
if (msg_buf == 0)
|
||||
msg_buf = xmalloc (msg_bufsiz = 128);
|
||||
|
||||
sprintf (msg_buf, format, arg1, arg2);
|
||||
msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
|
||||
|
||||
rl_display_prompt = msg_buf;
|
||||
if (saved_local_prompt == 0)
|
||||
{
|
||||
rl_save_prompt ();
|
||||
msg_saved_prompt = 1;
|
||||
}
|
||||
else if (local_prompt != saved_local_prompt)
|
||||
{
|
||||
FREE (local_prompt);
|
||||
FREE (local_prompt_prefix);
|
||||
local_prompt = (char *)NULL;
|
||||
}
|
||||
local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
|
||||
&prompt_last_invisible,
|
||||
&prompt_invis_chars_first_line,
|
||||
&prompt_physical_chars);
|
||||
local_prompt_prefix = (char *)NULL;
|
||||
local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
|
||||
(*rl_redisplay_function) ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* !USE_VARARGS */
|
||||
|
||||
/* How to clear things from the "echo-area". */
|
||||
int
|
||||
@@ -3098,10 +3181,12 @@ rl_save_prompt (void)
|
||||
saved_invis_chars_first_line = prompt_invis_chars_first_line;
|
||||
saved_physical_chars = prompt_physical_chars;
|
||||
saved_local_prompt_newlines = local_prompt_newlines;
|
||||
saved_local_prompt_invis_chars = local_prompt_invis_chars;
|
||||
|
||||
local_prompt = local_prompt_prefix = (char *)0;
|
||||
local_prompt_len = 0;
|
||||
local_prompt_newlines = (int *)0;
|
||||
local_prompt_invis_chars = (int *)0;
|
||||
|
||||
prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
|
||||
prompt_invis_chars_first_line = prompt_physical_chars = 0;
|
||||
@@ -3113,11 +3198,13 @@ rl_restore_prompt (void)
|
||||
FREE (local_prompt);
|
||||
FREE (local_prompt_prefix);
|
||||
FREE (local_prompt_newlines);
|
||||
FREE (local_prompt_invis_chars);
|
||||
|
||||
local_prompt = saved_local_prompt;
|
||||
local_prompt_prefix = saved_local_prefix;
|
||||
local_prompt_len = saved_local_length;
|
||||
local_prompt_newlines = saved_local_prompt_newlines;
|
||||
local_prompt_invis_chars = saved_local_prompt_invis_chars;
|
||||
|
||||
prompt_prefix_length = saved_prefix_length;
|
||||
prompt_last_invisible = saved_last_invisible;
|
||||
@@ -3130,7 +3217,7 @@ rl_restore_prompt (void)
|
||||
saved_local_length = 0;
|
||||
saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
|
||||
saved_invis_chars_first_line = saved_physical_chars = 0;
|
||||
saved_local_prompt_newlines = 0;
|
||||
saved_local_prompt_newlines = saved_local_prompt_invis_chars = 0;
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -3318,7 +3405,7 @@ _rl_update_final (void)
|
||||
full_lines = 1;
|
||||
}
|
||||
_rl_move_vert (_rl_vis_botlin);
|
||||
woff = W_OFFSET(_rl_vis_botlin, wrap_offset);
|
||||
woff = W_OFFSET(_rl_vis_botlin, wrap_offset); /* XXX - WRAP_OFFSET? */
|
||||
botline_length = VIS_LLEN(_rl_vis_botlin) - woff;
|
||||
/* If we've wrapped lines, remove the final xterm line-wrap flag. */
|
||||
if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth)
|
||||
@@ -3327,7 +3414,7 @@ _rl_update_final (void)
|
||||
|
||||
/* LAST_LINE includes invisible characters, so if you want to get the
|
||||
last character of the first line, you have to take WOFF into account.
|
||||
This needs to be done for both calls to _rl_move_cursor_relative,
|
||||
This needs to be done both for calls to _rl_move_cursor_relative,
|
||||
which takes a buffer position as the first argument, and any direct
|
||||
subscripts of LAST_LINE. */
|
||||
last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
|
||||
@@ -3338,9 +3425,9 @@ _rl_update_final (void)
|
||||
puts_face (&last_line[_rl_screenwidth - 1 + woff],
|
||||
&last_face[_rl_screenwidth - 1 + woff], 1);
|
||||
}
|
||||
_rl_vis_botlin = 0;
|
||||
if (botline_length > 0 || _rl_last_c_pos > 0)
|
||||
if ((_rl_vis_botlin == 0 && botline_length == 0) || botline_length > 0 || _rl_last_c_pos > 0)
|
||||
rl_crlf ();
|
||||
_rl_vis_botlin = 0;
|
||||
fflush (rl_outstream);
|
||||
rl_display_fixed++;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ This document describes the GNU History library
|
||||
a programming tool that provides a consistent user interface for
|
||||
recalling lines of previously typed input.
|
||||
|
||||
Copyright @copyright{} 1988--2022 Free Software Foundation, Inc.
|
||||
Copyright @copyright{} 1988--2023 Free Software Foundation, Inc.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@ignore
|
||||
This file documents the user interface to the GNU History library.
|
||||
|
||||
Copyright (C) 1988-2022 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2023 Free Software Foundation, Inc.
|
||||
Authored by Brian Fox and Chet Ramey.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this manual
|
||||
@@ -369,7 +369,7 @@ Returns 0 on success, or @code{errno} on failure.
|
||||
|
||||
These functions implement history expansion.
|
||||
|
||||
@deftypefun int history_expand (char *string, char **output)
|
||||
@deftypefun int history_expand (const char *string, char **output)
|
||||
Expand @var{string}, placing the result into @var{output}, a pointer
|
||||
to a string (@pxref{History Interaction}). Returns:
|
||||
@table @code
|
||||
@@ -517,9 +517,8 @@ The following program demonstrates simple use of the @sc{gnu} History Library.
|
||||
#include <stdio.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@{
|
||||
char line[1024], *t;
|
||||
int len, done = 0;
|
||||
|
||||
@@ -90,8 +90,8 @@ named by @env{$HISTFILE}.
|
||||
If the @code{histappend} shell option is set (@pxref{Bash Builtins}),
|
||||
the lines are appended to the history file,
|
||||
otherwise the history file is overwritten.
|
||||
If @env{HISTFILE}
|
||||
is unset, or if the history file is unwritable, the history is not saved.
|
||||
If @env{HISTFILE} is unset or null,
|
||||
or if the history file is unwritable, the history is not saved.
|
||||
After saving the history, the history file is truncated
|
||||
to contain no more than @env{$HISTFILESIZE} lines.
|
||||
If @env{HISTFILESIZE} is unset, or set to null, a non-numeric value, or
|
||||
@@ -104,7 +104,7 @@ When the history file is read, lines beginning with the history
|
||||
comment character followed immediately by a digit are interpreted
|
||||
as timestamps for the following history entry.
|
||||
|
||||
The builtin command @code{fc} may be used to list or edit and re-execute
|
||||
The @code{fc} builtin command may be used to list or edit and re-execute
|
||||
a portion of the history list.
|
||||
The @code{history} builtin may be used to display or modify the history
|
||||
list and manipulate the history file.
|
||||
@@ -113,8 +113,9 @@ are available in each editing mode that provide access to the
|
||||
history list (@pxref{Commands For History}).
|
||||
|
||||
The shell allows control over which commands are saved on the history
|
||||
list. The @env{HISTCONTROL} and @env{HISTIGNORE}
|
||||
variables may be set to cause the shell to save only a subset of the
|
||||
list.
|
||||
The @env{HISTCONTROL} and @env{HISTIGNORE}
|
||||
variables are used to cause the shell to save only a subset of the
|
||||
commands entered.
|
||||
The @code{cmdhist}
|
||||
shell option, if enabled, causes the shell to attempt to save each
|
||||
@@ -192,7 +193,7 @@ With no options, display the history list with line numbers.
|
||||
Lines prefixed with a @samp{*} have been modified.
|
||||
An argument of @var{n} lists only the last @var{n} lines.
|
||||
If the shell variable @env{HISTTIMEFORMAT} is set and not null,
|
||||
it is used as a format string for @var{strftime} to display
|
||||
it is used as a format string for @code{strftime}(3) to display
|
||||
the time stamp associated with each displayed history entry.
|
||||
No intervening blank is printed between the formatted time stamp
|
||||
and the history line.
|
||||
@@ -250,6 +251,7 @@ If a @var{filename} argument is supplied
|
||||
when any of the @option{-w}, @option{-r}, @option{-a}, or @option{-n} options
|
||||
is used, Bash uses @var{filename} as the history file.
|
||||
If not, then the value of the @env{HISTFILE} variable is used.
|
||||
If @env{HISTFILE} is unset or null, these options have no effect.
|
||||
|
||||
The return value is 0 unless an invalid option is encountered, an
|
||||
error occurs while reading or writing the history file, an invalid
|
||||
@@ -282,14 +284,21 @@ expansion functions about quoting still in effect from previous lines.
|
||||
History expansion takes place in two parts. The first is to determine
|
||||
which line from the history list should be used during substitution.
|
||||
The second is to select portions of that line for inclusion into the
|
||||
current one. The line selected from the history is called the
|
||||
@dfn{event}, and the portions of that line that are acted upon are
|
||||
called @dfn{words}. Various @dfn{modifiers} are available to manipulate
|
||||
the selected words. The line is broken into words in the same fashion
|
||||
current one.
|
||||
|
||||
The line selected from the history is called the @dfn{event},
|
||||
and the portions of that line that are acted upon are called @dfn{words}.
|
||||
The line is broken into words in the same fashion
|
||||
that Bash does, so that several words
|
||||
surrounded by quotes are considered one word.
|
||||
The @dfn{event designator} selects the event, the optional
|
||||
@dfn{word designator} selects words from the event, and
|
||||
various optional @dfn{modifiers} are available to manipulate the
|
||||
selected words.
|
||||
|
||||
History expansions are introduced by the appearance of the
|
||||
history expansion character, which is @samp{!} by default.
|
||||
History expansions may appear anywhere in the input, but do not nest.
|
||||
|
||||
History expansion implements shell-like quoting conventions:
|
||||
a backslash can be used to remove the special handling for the next character;
|
||||
@@ -307,6 +316,16 @@ also treated as quoted if it immediately precedes the closing double quote
|
||||
in a double-quoted string.
|
||||
@end ifset
|
||||
|
||||
There is a special abbreviation for substitution, active when the
|
||||
@var{quick substitution} character (default @samp{^})
|
||||
is the first character on the line.
|
||||
It selects the previous history list entry, using an event designator
|
||||
equivalent to @code{!!},
|
||||
and substitutes one string for another in that line.
|
||||
It is described below (@pxref{Event Designators}).
|
||||
This is the only history expansion that does not begin with the history
|
||||
expansion character.
|
||||
|
||||
@ifset BashFeatures
|
||||
Several shell options settable with the @code{shopt}
|
||||
builtin (@pxref{The Shopt Builtin}) may be used to tailor
|
||||
@@ -347,6 +366,9 @@ An event designator is a reference to a command line entry in the
|
||||
history list.
|
||||
Unless the reference is absolute, events are relative to the current
|
||||
position in the history list.
|
||||
The event designator consists of the portion of the word beginning
|
||||
with the history expansion character, and ending with the word designator
|
||||
if one is present, or the end of the word.
|
||||
@cindex history events
|
||||
|
||||
@table @asis
|
||||
@@ -354,8 +376,9 @@ position in the history list.
|
||||
@item @code{!}
|
||||
@ifset BashFeatures
|
||||
Start a history substitution, except when followed by a space, tab,
|
||||
the end of the line, @samp{=} or @samp{(} (when the
|
||||
@code{extglob} shell option is enabled using the @code{shopt} builtin).
|
||||
the end of the line, @samp{=},
|
||||
or the rest of the shell metacharacters defined above
|
||||
(@pxref{Definitions}).
|
||||
@end ifset
|
||||
@ifclear BashFeatures
|
||||
Start a history substitution, except when followed by a space, tab,
|
||||
@@ -400,6 +423,8 @@ The entire command line typed so far.
|
||||
@subsection Word Designators
|
||||
|
||||
Word designators are used to select desired words from the event.
|
||||
They are optional; if the word designator isn't supplied, the history
|
||||
expansion uses the entire event.
|
||||
A @samp{:} separates the event specification from the word designator. It
|
||||
may be omitted if the word designator begins with a @samp{^}, @samp{$},
|
||||
@samp{*}, @samp{-}, or @samp{%}. Words are numbered from the beginning
|
||||
|
||||
+104
-52
@@ -7,7 +7,7 @@ This document describes the GNU Readline Library, a utility for aiding
|
||||
in the consistency of user interface across discrete programs that need
|
||||
to provide a command line interface.
|
||||
|
||||
Copyright (C) 1988--2022 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988--2023 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
@@ -67,6 +67,9 @@ the simplest way possible, perhaps to replace calls in your code to
|
||||
|
||||
The function @code{readline()} prints a prompt @var{prompt}
|
||||
and then reads and returns a single line of text from the user.
|
||||
Since it's possible to enter characters into the line while quoting
|
||||
them to disable any Readline editing function they might normally have,
|
||||
this line may include embedded newlines and other special characters.
|
||||
If @var{prompt} is @code{NULL} or the empty string, no prompt is displayed.
|
||||
The line @code{readline} returns is allocated with @code{malloc()};
|
||||
the caller should @code{free()} the line when it has finished with it.
|
||||
@@ -476,6 +479,8 @@ The default hook checks @code{rl_instream}; if an application is using a
|
||||
different input source, it should set the hook appropriately.
|
||||
Readline queries for available input when implementing intra-key-sequence
|
||||
timeouts during input and incremental searches.
|
||||
This function must return zero if there is no input available, and non-zero
|
||||
if input is available.
|
||||
This may use an application-specific timeout before returning a value;
|
||||
Readline uses the value passed to @code{rl_set_keyboard_input_timeout()}
|
||||
or the value of the user-settable @var{keyseq-timeout} variable.
|
||||
@@ -513,6 +518,15 @@ By default, this is set to @code{rl_deprep_terminal}
|
||||
(@pxref{Terminal Management}).
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {void} rl_macro_display_hook
|
||||
If set, this points to a function that @code{rl_macro_dumper} will call to
|
||||
display a key sequence bound to a macro.
|
||||
It is called with the key sequence, the "untranslated" macro value (i.e.,
|
||||
with backslash escapes included, as when passed to @code{rl_macro_bind}),
|
||||
the @code{readable} argument passed to @code{rl_macro_dumper}, and any
|
||||
prefix to display before the key sequence.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {Keymap} rl_executing_keymap
|
||||
This variable is set to the keymap (@pxref{Keymaps}) in which the
|
||||
currently executing Readline function was found.
|
||||
@@ -915,9 +929,19 @@ Return an array of strings representing the key sequences used to
|
||||
invoke @var{function} in the keymap @var{map}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void rl_print_keybinding (const char *name, Keymap map, int readable)
|
||||
Print key sequences bound to Readline function name @var{name} in
|
||||
keymap @var{map}.
|
||||
If @var{map} is NULL, this uses the current keymap.
|
||||
If @var{readable} is non-zero,
|
||||
the list is formatted in such a way that it can be made part of an
|
||||
@code{inputrc} file and re-read.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void rl_function_dumper (int readable)
|
||||
Print the Readline function names and the key sequences currently
|
||||
bound to them to @code{rl_outstream}. If @var{readable} is non-zero,
|
||||
bound to them to @code{rl_outstream}.
|
||||
If @var{readable} is non-zero,
|
||||
the list is formatted in such a way that it can be made part of an
|
||||
@code{inputrc} file and re-read.
|
||||
@end deftypefun
|
||||
@@ -1346,13 +1370,15 @@ If @var{c} is a number, return the value it represents.
|
||||
Bind the key sequence @var{keyseq} to invoke the macro @var{macro}.
|
||||
The binding is performed in @var{map}. When @var{keyseq} is invoked, the
|
||||
@var{macro} will be inserted into the line. This function is deprecated;
|
||||
use @code{rl_generic_bind()} instead.
|
||||
use @code{rl_generic_bind} instead.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void rl_macro_dumper (int readable)
|
||||
Print the key sequences bound to macros and their values, using
|
||||
the current keymap, to @code{rl_outstream}.
|
||||
If @var{readable} is non-zero, the list is formatted in such a way
|
||||
If the application has assigned a value to @code{rl_macro_display_hook},
|
||||
@code{rl_macro_dumper} calls it instead of printing anything.
|
||||
If @var{readable} is greater than zero, the list is formatted in such a way
|
||||
that it can be made part of an @code{inputrc} file and re-read.
|
||||
@end deftypefun
|
||||
|
||||
@@ -1389,6 +1415,10 @@ use all of a terminal's capabilities, and this function will return
|
||||
values for only those capabilities Readline uses.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {void} rl_reparse_colors (void)
|
||||
Read or re-read color definitions from @env{LS_COLORS}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {void} rl_clear_history (void)
|
||||
Clear the history list by deleting all of the entries, in the same manner
|
||||
as the History library's @code{clear_history()} function.
|
||||
@@ -2138,7 +2168,9 @@ The function should not modify the directory argument if it returns 0.
|
||||
@deftypevar {rl_dequote_func_t *} rl_filename_rewrite_hook
|
||||
If non-zero, this is the address of a function called when reading
|
||||
directory entries from the filesystem for completion and comparing
|
||||
them to the partial word to be completed. The function should
|
||||
them to the filename portion of the partial word to be completed
|
||||
(after its potential modification by @code{rl_completion_rewrite_hook}).
|
||||
The function should
|
||||
perform any necessary application or system-specific conversion on
|
||||
the filename, such as converting between character sets or converting
|
||||
from a filesystem format to a character input format.
|
||||
@@ -2151,6 +2183,24 @@ matches, is added to the list of matches. Readline will free the
|
||||
allocated string.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {rl_dequote_func_t *} rl_completion_rewrite_hook
|
||||
If non-zero, this is the address of a function to call before
|
||||
comparing the filename portion of a word to be completed with directory
|
||||
entries from the filesystem.
|
||||
The function takes two arguments: @var{fname}, the filename to be converted,
|
||||
after any @code{rl_filename_dequoting_function} has been applied,
|
||||
and @var{fnlen}, its length in bytes.
|
||||
It must either return its first argument (if no conversion takes place)
|
||||
or the converted filename in newly-allocated memory.
|
||||
The function should perform any necessary application or system-specific
|
||||
conversion on the filename, such as converting between character sets or
|
||||
converting from a character input format to some other format.
|
||||
Readline compares the converted form against directory entries, after
|
||||
their potential modification by @code{rl_filename_rewrite_hook}, and adds
|
||||
any matches to the list of matches.
|
||||
Readline will free the allocated string.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {rl_compdisp_func_t *} rl_completion_display_matches_hook
|
||||
If non-zero, then this is the address of a function to call when
|
||||
completing a word would normally display the list of possible matches.
|
||||
@@ -2298,6 +2348,17 @@ The quoting is effected via a call to the function pointed to
|
||||
by @code{rl_filename_quoting_function}.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar int rl_full_quoting_desired
|
||||
Non-zero means that Readline should apply filename-style quoting,
|
||||
including any application-specified quoting mechanism,
|
||||
to all completion matches even if we are not otherwise treating the
|
||||
matches as filenames.
|
||||
This is @emph{always} zero when completion is attempted, and can only
|
||||
be changed within an application-specific completion function.
|
||||
The quoting is effected via a call to the function pointed to
|
||||
by @code{rl_filename_quoting_function}.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar int rl_attempted_completion_over
|
||||
If an application-specific completion function assigned to
|
||||
@code{rl_attempted_completion_function} sets this variable to a non-zero
|
||||
@@ -2423,8 +2484,8 @@ COMMAND commands[] = @{
|
||||
@};
|
||||
|
||||
/* Forward declarations. */
|
||||
char *stripwhite ();
|
||||
COMMAND *find_command ();
|
||||
char *stripwhite (char *);
|
||||
COMMAND *find_command (char *);
|
||||
|
||||
/* The name of this program, as taken from argv[0]. */
|
||||
char *progname;
|
||||
@@ -2433,8 +2494,7 @@ char *progname;
|
||||
int done;
|
||||
|
||||
char *
|
||||
dupstr (s)
|
||||
char *s;
|
||||
dupstr (char *s)
|
||||
@{
|
||||
char *r;
|
||||
|
||||
@@ -2443,9 +2503,8 @@ dupstr (s)
|
||||
return (r);
|
||||
@}
|
||||
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@{
|
||||
char *line, *s;
|
||||
|
||||
@@ -2481,8 +2540,7 @@ main (argc, argv)
|
||||
|
||||
/* Execute a command line. */
|
||||
int
|
||||
execute_line (line)
|
||||
char *line;
|
||||
execute_line (char *line)
|
||||
@{
|
||||
register int i;
|
||||
COMMAND *command;
|
||||
@@ -2521,8 +2579,7 @@ execute_line (line)
|
||||
/* Look up NAME as the name of a command, and return a pointer to that
|
||||
command. Return a NULL pointer if NAME isn't a command name. */
|
||||
COMMAND *
|
||||
find_command (name)
|
||||
char *name;
|
||||
find_command (char *name)
|
||||
@{
|
||||
register int i;
|
||||
|
||||
@@ -2536,8 +2593,7 @@ find_command (name)
|
||||
/* Strip whitespace from the start and end of STRING. Return a pointer
|
||||
into STRING. */
|
||||
char *
|
||||
stripwhite (string)
|
||||
char *string;
|
||||
stripwhite (char *string)
|
||||
@{
|
||||
register char *s, *t;
|
||||
|
||||
@@ -2561,13 +2617,14 @@ stripwhite (string)
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
char *command_generator PARAMS((const char *, int));
|
||||
char **fileman_completion PARAMS((const char *, int, int));
|
||||
char *command_generator (const char *, int);
|
||||
char **fileman_completion (const char *, int, int);
|
||||
|
||||
/* Tell the GNU Readline library how to complete. We want to try to complete
|
||||
on command names if this is the first word in the line, or on filenames
|
||||
if not. */
|
||||
initialize_readline ()
|
||||
void
|
||||
initialize_readline (void)
|
||||
@{
|
||||
/* Allow conditional parsing of the ~/.inputrc file. */
|
||||
rl_readline_name = "FileMan";
|
||||
@@ -2582,9 +2639,7 @@ initialize_readline ()
|
||||
in case we want to do some simple parsing. Return the array of matches,
|
||||
or NULL if there aren't any. */
|
||||
char **
|
||||
fileman_completion (text, start, end)
|
||||
const char *text;
|
||||
int start, end;
|
||||
fileman_completion (const char *text, int start, int end)
|
||||
@{
|
||||
char **matches;
|
||||
|
||||
@@ -2603,9 +2658,7 @@ fileman_completion (text, start, end)
|
||||
to start from scratch; without any state (i.e. STATE == 0), then we
|
||||
start at the top of the list. */
|
||||
char *
|
||||
command_generator (text, state)
|
||||
const char *text;
|
||||
int state;
|
||||
command_generator (const char *text, int state)
|
||||
@{
|
||||
static int list_index, len;
|
||||
char *name;
|
||||
@@ -2643,40 +2696,40 @@ command_generator (text, state)
|
||||
static char syscom[1024];
|
||||
|
||||
/* List the file(s) named in arg. */
|
||||
com_list (arg)
|
||||
char *arg;
|
||||
int
|
||||
com_list (char *arg)
|
||||
@{
|
||||
if (!arg)
|
||||
arg = "";
|
||||
|
||||
sprintf (syscom, "ls -FClg %s", arg);
|
||||
snprintf (syscom, sizeof (syscom), "ls -FClg %s", arg);
|
||||
return (system (syscom));
|
||||
@}
|
||||
|
||||
com_view (arg)
|
||||
char *arg;
|
||||
int
|
||||
com_view (char *arg)
|
||||
@{
|
||||
if (!valid_argument ("view", arg))
|
||||
return 1;
|
||||
|
||||
#if defined (__MSDOS__)
|
||||
/* more.com doesn't grok slashes in pathnames */
|
||||
sprintf (syscom, "less %s", arg);
|
||||
snprintf (syscom, sizeof (syscom), "less %s", arg);
|
||||
#else
|
||||
sprintf (syscom, "more %s", arg);
|
||||
snprintf (syscom, sizeof (syscom), "more %s", arg);
|
||||
#endif
|
||||
return (system (syscom));
|
||||
@}
|
||||
|
||||
com_rename (arg)
|
||||
char *arg;
|
||||
int
|
||||
com_rename (char *arg)
|
||||
@{
|
||||
too_dangerous ("rename");
|
||||
return (1);
|
||||
@}
|
||||
|
||||
com_stat (arg)
|
||||
char *arg;
|
||||
int
|
||||
com_stat (char *arg)
|
||||
@{
|
||||
struct stat finfo;
|
||||
|
||||
@@ -2703,8 +2756,8 @@ com_stat (arg)
|
||||
return (0);
|
||||
@}
|
||||
|
||||
com_delete (arg)
|
||||
char *arg;
|
||||
int
|
||||
com_delete (char *arg)
|
||||
@{
|
||||
too_dangerous ("delete");
|
||||
return (1);
|
||||
@@ -2712,8 +2765,8 @@ com_delete (arg)
|
||||
|
||||
/* Print out help for ARG, or for all of the commands if ARG is
|
||||
not present. */
|
||||
com_help (arg)
|
||||
char *arg;
|
||||
int
|
||||
com_help (char *arg)
|
||||
@{
|
||||
register int i;
|
||||
int printed = 0;
|
||||
@@ -2751,8 +2804,8 @@ com_help (arg)
|
||||
@}
|
||||
|
||||
/* Change to the directory ARG. */
|
||||
com_cd (arg)
|
||||
char *arg;
|
||||
int
|
||||
com_cd (char *arg)
|
||||
@{
|
||||
if (chdir (arg) == -1)
|
||||
@{
|
||||
@@ -2765,8 +2818,8 @@ com_cd (arg)
|
||||
@}
|
||||
|
||||
/* Print out the current working directory. */
|
||||
com_pwd (ignore)
|
||||
char *ignore;
|
||||
int
|
||||
com_pwd (char *ignore)
|
||||
@{
|
||||
char dir[1024], *s;
|
||||
|
||||
@@ -2782,16 +2835,16 @@ com_pwd (ignore)
|
||||
@}
|
||||
|
||||
/* The user wishes to quit using this program. Just set DONE non-zero. */
|
||||
com_quit (arg)
|
||||
char *arg;
|
||||
int
|
||||
com_quit (char *arg)
|
||||
@{
|
||||
done = 1;
|
||||
return (0);
|
||||
@}
|
||||
|
||||
/* Function which tells you that you can't do this. */
|
||||
too_dangerous (caller)
|
||||
char *caller;
|
||||
void
|
||||
too_dangerous (char *caller)
|
||||
@{
|
||||
fprintf (stderr,
|
||||
"%s: Too dangerous for me to distribute. Write it yourself.\n",
|
||||
@@ -2801,8 +2854,7 @@ too_dangerous (caller)
|
||||
/* Return non-zero if ARG is a valid argument for CALLER, else print
|
||||
an error message and return zero. */
|
||||
int
|
||||
valid_argument (caller, arg)
|
||||
char *caller, *arg;
|
||||
valid_argument (char *caller, char *arg)
|
||||
@{
|
||||
if (!arg || !*arg)
|
||||
@{
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@comment %**start of header (This is for running Texinfo on a region.)
|
||||
@ifclear BashFeatures
|
||||
@setfilename rluser.info
|
||||
@end ifclear
|
||||
@comment %**end of header (This is for running Texinfo on a region.)
|
||||
|
||||
@ignore
|
||||
@@ -9,7 +11,7 @@ use these features. There is a document entitled "readline.texinfo"
|
||||
which contains both end-user and programmer documentation for the
|
||||
GNU Readline Library.
|
||||
|
||||
Copyright (C) 1988--2022 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988--2023 Free Software Foundation, Inc.
|
||||
|
||||
Authored by Brian Fox and Chet Ramey.
|
||||
|
||||
@@ -323,13 +325,14 @@ the line, thereby executing the command from the history list.
|
||||
A movement command will terminate the search, make the last line found
|
||||
the current line, and begin editing.
|
||||
|
||||
Readline remembers the last incremental search string. If two
|
||||
@kbd{C-r}s are typed without any intervening characters defining a new
|
||||
search string, any remembered search string is used.
|
||||
Readline remembers the last incremental search string.
|
||||
If two @kbd{C-r}s are typed without any intervening characters defining
|
||||
a new search string, Readline uses any remembered search string.
|
||||
|
||||
Non-incremental searches read the entire search string before starting
|
||||
to search for matching history lines. The search string may be
|
||||
typed by the user or be part of the contents of the current line.
|
||||
to search for matching history lines.
|
||||
The search string may be typed by the user or be part of the contents of
|
||||
the current line.
|
||||
|
||||
@node Readline Init File
|
||||
@section Readline Init File
|
||||
@@ -402,11 +405,12 @@ set editing-mode vi
|
||||
@end example
|
||||
|
||||
Variable names and values, where appropriate, are recognized without regard
|
||||
to case. Unrecognized variable names are ignored.
|
||||
to case.
|
||||
Unrecognized variable names are ignored.
|
||||
|
||||
Boolean variables (those that can be set to on or off) are set to on if
|
||||
the value is null or empty, @var{on} (case-insensitive), or 1. Any other
|
||||
value results in the variable being set to off.
|
||||
the value is null or empty, @var{on} (case-insensitive), or 1.
|
||||
Any other value results in the variable being set to off.
|
||||
|
||||
@ifset BashFeatures
|
||||
The @w{@code{bind -V}} command lists the current Readline variable names
|
||||
@@ -456,8 +460,12 @@ the terminal's bell.
|
||||
@item bind-tty-special-chars
|
||||
@vindex bind-tty-special-chars
|
||||
If set to @samp{on} (the default), Readline attempts to bind the control
|
||||
characters treated specially by the kernel's terminal driver to their
|
||||
characters that are
|
||||
treated specially by the kernel's terminal driver to their
|
||||
Readline equivalents.
|
||||
These override the default Readline bindings described here.
|
||||
Type @samp{stty -a} at a Bash prompt to see your current terminal settings,
|
||||
including the special control characters (usually @code{cchars}).
|
||||
|
||||
@item blink-matching-paren
|
||||
@vindex blink-matching-paren
|
||||
@@ -716,11 +724,11 @@ The default is @samp{off}.
|
||||
|
||||
@item match-hidden-files
|
||||
@vindex match-hidden-files
|
||||
This variable, when set to @samp{on}, causes Readline to match files whose
|
||||
This variable, when set to @samp{on}, forces Readline to match files whose
|
||||
names begin with a @samp{.} (hidden files) when performing filename
|
||||
completion.
|
||||
If set to @samp{off}, the leading @samp{.} must be
|
||||
supplied by the user in the filename to be completed.
|
||||
If set to @samp{off}, the user must include the leading @samp{.}
|
||||
in the filename to be completed.
|
||||
This variable is @samp{on} by default.
|
||||
|
||||
@item menu-complete-display-prefix
|
||||
@@ -757,6 +765,12 @@ before returning when @code{accept-line} is executed. By default,
|
||||
history lines may be modified and retain individual undo lists across
|
||||
calls to @code{readline()}. The default is @samp{off}.
|
||||
|
||||
@item search-ignore-case
|
||||
@vindex search-ignore-case
|
||||
If set to @samp{on}, Readline performs incremental and non-incremental
|
||||
history list searches in a case-insensitive fashion.
|
||||
The default value is @samp{off}.
|
||||
|
||||
@item show-all-if-ambiguous
|
||||
@vindex show-all-if-ambiguous
|
||||
This alters the default behavior of the completion functions. If
|
||||
@@ -1458,6 +1472,16 @@ moving point past that word as well.
|
||||
If the insertion point is at the end of the line, this transposes
|
||||
the last two words on the line.
|
||||
|
||||
@ifset BashFeatures
|
||||
@item shell-transpose-words (M-C-t)
|
||||
Drag the word before point past the word after point,
|
||||
moving point past that word as well.
|
||||
If the insertion point is at the end of the line, this transposes
|
||||
the last two words on the line.
|
||||
Word boundaries are the same as @code{shell-forward-word} and
|
||||
@code{shell-backward-word}.
|
||||
@end ifset
|
||||
|
||||
@item upcase-word (M-u)
|
||||
Uppercase the current (or following) word. With a negative argument,
|
||||
uppercase the previous word, but do not move the cursor.
|
||||
@@ -1528,14 +1552,6 @@ Kill the word behind point.
|
||||
Word boundaries are the same as @code{shell-backward-word}.
|
||||
@end ifset
|
||||
|
||||
@item shell-transpose-words (M-C-t)
|
||||
Drag the word before point past the word after point,
|
||||
moving point past that word as well.
|
||||
If the insertion point is at the end of the line, this transposes
|
||||
the last two words on the line.
|
||||
Word boundaries are the same as @code{shell-forward-word} and
|
||||
@code{shell-backward-word}.
|
||||
|
||||
@item unix-word-rubout (C-w)
|
||||
Kill the word behind point, using white space as a word boundary.
|
||||
The killed text is saved on the kill-ring.
|
||||
@@ -1858,9 +1874,13 @@ pathname expansion.
|
||||
Display version information about the current instance of Bash.
|
||||
|
||||
@item shell-expand-line (M-C-e)
|
||||
Expand the line as the shell does.
|
||||
This performs alias and history expansion as well as all of the shell
|
||||
word expansions (@pxref{Shell Expansions}).
|
||||
Expand the line by performing shell word expansions.
|
||||
This performs alias and history expansion,
|
||||
$'@var{string}' and $"@var{string}" quoting,
|
||||
tilde expansion, parameter and variable expansion, arithmetic expansion,
|
||||
command and proces substitution,
|
||||
word splitting, and quote removal.
|
||||
An explicit argument suppresses command and process substitution.
|
||||
|
||||
@item history-expand-line (M-^)
|
||||
Perform history expansion on the current line.
|
||||
@@ -1898,6 +1918,13 @@ editing mode.
|
||||
|
||||
@end ifclear
|
||||
|
||||
@item execute-named-command (M-x)
|
||||
Read a bindable readline command name from the input and execute the
|
||||
function to which it's bound, as if the key sequence to which it was
|
||||
bound appeared in the input.
|
||||
If this function is supplied with a numeric argument, it passes that
|
||||
argument to the function it executes.
|
||||
|
||||
@end ftable
|
||||
|
||||
@node Readline vi Mode
|
||||
@@ -2098,14 +2125,25 @@ be completed, and two to modify the completion as it is happening.
|
||||
@item compgen
|
||||
@btindex compgen
|
||||
@example
|
||||
@code{compgen [@var{option}] [@var{word}]}
|
||||
@code{compgen [-V @var{varname}] [@var{option}] [@var{word}]}
|
||||
@end example
|
||||
|
||||
Generate possible completion matches for @var{word} according to
|
||||
the @var{option}s, which may be any option accepted by the
|
||||
@code{complete}
|
||||
builtin with the exception of @option{-p} and @option{-r}, and write
|
||||
the matches to the standard output.
|
||||
builtin with the exceptions of
|
||||
@option{-p},
|
||||
@option{-r},
|
||||
@option{-D},
|
||||
@option{-E},
|
||||
and
|
||||
@option{-I},
|
||||
and write the matches to the standard output.
|
||||
|
||||
If the @option{-V} option is supplied, @code{compgen} stores the generated
|
||||
completions into the indexed array variable @var{varname} instead of writing
|
||||
them to the standard output.
|
||||
|
||||
When using the @option{-F} or @option{-C} options, the various shell variables
|
||||
set by the programmable completion facilities, while available, will not
|
||||
have useful values.
|
||||
@@ -2122,14 +2160,15 @@ matches were generated.
|
||||
@item complete
|
||||
@btindex complete
|
||||
@example
|
||||
@code{complete [-abcdefgjksuv] [-o @var{comp-option}] [-DEI] [-A @var{action}] [-G @var{globpat}]
|
||||
[-W @var{wordlist}] [-F @var{function}] [-C @var{command}] [-X @var{filterpat}]
|
||||
[-P @var{prefix}] [-S @var{suffix}] @var{name} [@var{name} @dots{}]}
|
||||
@code{complete [-abcdefgjksuv] [-o @var{comp-option}] [-DEI] [-A @var{action}]
|
||||
[-G @var{globpat}] [-W @var{wordlist}] [-F @var{function}] [-C @var{command}]
|
||||
[-X @var{filterpat}] [-P @var{prefix}] [-S @var{suffix}] @var{name} [@var{name} @dots{}]}
|
||||
@code{complete -pr [-DEI] [@var{name} @dots{}]}
|
||||
@end example
|
||||
|
||||
Specify how arguments to each @var{name} should be completed.
|
||||
If the @option{-p} option is supplied, or if no options are supplied, existing
|
||||
If the @option{-p} option is supplied, or if no options or @var{name}s
|
||||
are supplied, existing
|
||||
completion specifications are printed in a way that allows them to be
|
||||
reused as input.
|
||||
The @option{-r} option removes a completion specification for
|
||||
@@ -2187,6 +2226,10 @@ quoting special characters, or suppressing trailing spaces).
|
||||
This option is intended to be used with shell functions specified
|
||||
with @option{-F}.
|
||||
|
||||
@item fullquote
|
||||
Tell Readline to quote all the completed words even if they are not
|
||||
filenames.
|
||||
|
||||
@item noquote
|
||||
Tell Readline not to quote the completed words if they are filenames
|
||||
(quoting filenames is the default).
|
||||
@@ -2330,7 +2373,14 @@ case, any completion not matching @var{filterpat} is removed.
|
||||
@end table
|
||||
|
||||
The return value is true unless an invalid option is supplied, an option
|
||||
other than @option{-p} or @option{-r} is supplied without a @var{name}
|
||||
other than
|
||||
@option{-p},
|
||||
@option{-r},
|
||||
@option{-D},
|
||||
@option{-E},
|
||||
or
|
||||
@option{-I}
|
||||
is supplied without a @var{name}
|
||||
argument, an attempt is made to remove a completion specification for
|
||||
a @var{name} for which no specification exists, or
|
||||
an error occurs adding a completion specification.
|
||||
@@ -2458,9 +2508,11 @@ complete -o filenames -o nospace -o bashdefault -F _comp_cd cd
|
||||
@noindent
|
||||
Since we'd like Bash and Readline to take care of some
|
||||
of the other details for us, we use several other options to tell Bash
|
||||
and Readline what to do. The @option{-o filenames} option tells Readline
|
||||
and Readline what to do.
|
||||
The @option{-o filenames} option tells Readline
|
||||
that the possible completions should be treated as filenames, and quoted
|
||||
appropriately. That option will also cause Readline to append a slash to
|
||||
appropriately.
|
||||
That option will also cause Readline to append a slash to
|
||||
filenames it can determine are directories (which is why we might want to
|
||||
extend @code{_comp_cd} to append a slash if we're using directories found
|
||||
via @var{CDPATH}: Readline can't tell those completions are directories).
|
||||
@@ -2468,9 +2520,10 @@ The @option{-o nospace} option tells Readline to not append a space
|
||||
character to the directory name, in case we want to append to it.
|
||||
The @option{-o bashdefault} option brings in the rest of the "Bash default"
|
||||
completions -- possible completions that Bash adds to the default Readline
|
||||
set. These include things like command name completion, variable completion
|
||||
for words beginning with @samp{$} or @samp{$@{}, completions containing pathname
|
||||
expansion patterns (@pxref{Filename Expansion}), and so on.
|
||||
set.
|
||||
These include things like command name completion, variable completion
|
||||
for words beginning with @samp{$} or @samp{$@{}, completions containing
|
||||
pathname expansion patterns (@pxref{Filename Expansion}), and so on.
|
||||
|
||||
Once installed using @code{complete}, @code{_comp_cd} will be called every
|
||||
time we attempt word completion for a @code{cd} command.
|
||||
@@ -2479,8 +2532,8 @@ Many more examples -- an extensive collection of completions for most of
|
||||
the common GNU, Unix, and Linux commands -- are available as part of the
|
||||
bash_completion project. This is installed by default on many GNU/Linux
|
||||
distributions. Originally written by Ian Macdonald, the project now lives
|
||||
at @url{https://github.com/scop/bash-completion/}. There are ports for
|
||||
other systems such as Solaris and Mac OS X.
|
||||
at @url{https://github.com/scop/bash-completion/}.
|
||||
There are ports for other systems such as Solaris and Mac OS X.
|
||||
|
||||
An older version of the bash_completion package is distributed with bash
|
||||
in the @file{examples/complete} subdirectory.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
@ignore
|
||||
Copyright (C) 1988-2022 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2024 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set EDITION 8.2
|
||||
@set VERSION 8.2
|
||||
@set EDITION 8.3
|
||||
@set VERSION 8.3
|
||||
|
||||
@set UPDATED 19 September 2022
|
||||
@set UPDATED-MONTH September 2022
|
||||
@set UPDATED 19 January 2024
|
||||
@set UPDATED-MONTH January 2024
|
||||
|
||||
@set LASTCHANGE Mon Sep 19 11:15:16 EDT 2022
|
||||
@set LASTCHANGE Fri Jan 19 11:01:44 EST 2024
|
||||
|
||||
@@ -448,7 +448,7 @@ KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
|
||||
{ ISFUNC, rl_upcase_word }, /* Meta-u */
|
||||
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-v */
|
||||
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-w */
|
||||
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-x */
|
||||
{ ISFUNC, rl_execute_named_command }, /* Meta-x */
|
||||
{ ISFUNC, rl_yank_pop }, /* Meta-y */
|
||||
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-z */
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ cc_t old_vtime;
|
||||
struct termios term;
|
||||
|
||||
int
|
||||
main()
|
||||
main(int c, char **v)
|
||||
{
|
||||
fd_set fds;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* fileman.c - file manager example for readline library. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2009,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
@@ -61,24 +61,24 @@
|
||||
# include <readline/history.h>
|
||||
#endif
|
||||
|
||||
extern char *xmalloc PARAMS((size_t));
|
||||
extern char *xmalloc (size_t);
|
||||
|
||||
void initialize_readline PARAMS((void));
|
||||
void too_dangerous PARAMS((char *));
|
||||
void initialize_readline (void);
|
||||
void too_dangerous (char *);
|
||||
|
||||
int execute_line PARAMS((char *));
|
||||
int valid_argument PARAMS((char *, char *));
|
||||
int execute_line (char *);
|
||||
int valid_argument (char *, char *);
|
||||
|
||||
/* The names of functions that actually do the manipulation. */
|
||||
int com_list PARAMS((char *));
|
||||
int com_view PARAMS((char *));
|
||||
int com_rename PARAMS((char *));
|
||||
int com_stat PARAMS((char *));
|
||||
int com_pwd PARAMS((char *));
|
||||
int com_delete PARAMS((char *));
|
||||
int com_help PARAMS((char *));
|
||||
int com_cd PARAMS((char *));
|
||||
int com_quit PARAMS((char *));
|
||||
int com_list (char *);
|
||||
int com_view (char *);
|
||||
int com_rename (char *);
|
||||
int com_stat (char *);
|
||||
int com_pwd (char *);
|
||||
int com_delete (char *);
|
||||
int com_help (char *);
|
||||
int com_cd (char *);
|
||||
int com_quit (char *);
|
||||
|
||||
/* A structure which contains information on the commands this program
|
||||
can understand. */
|
||||
@@ -105,8 +105,11 @@ COMMAND commands[] = {
|
||||
};
|
||||
|
||||
/* Forward declarations. */
|
||||
char *stripwhite ();
|
||||
COMMAND *find_command ();
|
||||
char *dupstr (char *);
|
||||
int execute_line (char *);
|
||||
char *stripwhite (char *);
|
||||
|
||||
COMMAND *find_command (char *);
|
||||
|
||||
/* The name of this program, as taken from argv[0]. */
|
||||
char *progname;
|
||||
@@ -115,8 +118,7 @@ char *progname;
|
||||
int done;
|
||||
|
||||
char *
|
||||
dupstr (s)
|
||||
char *s;
|
||||
dupstr (char *s)
|
||||
{
|
||||
char *r;
|
||||
|
||||
@@ -125,45 +127,9 @@ dupstr (s)
|
||||
return (r);
|
||||
}
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *line, *s;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
initialize_readline (); /* Bind our completer. */
|
||||
|
||||
/* Loop reading and executing lines until the user quits. */
|
||||
for ( ; done == 0; )
|
||||
{
|
||||
line = readline ("FileMan: ");
|
||||
|
||||
if (!line)
|
||||
break;
|
||||
|
||||
/* Remove leading and trailing whitespace from the line.
|
||||
Then, if there is anything left, add it to the history list
|
||||
and execute it. */
|
||||
s = stripwhite (line);
|
||||
|
||||
if (*s)
|
||||
{
|
||||
add_history (s);
|
||||
execute_line (s);
|
||||
}
|
||||
|
||||
free (line);
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/* Execute a command line. */
|
||||
int
|
||||
execute_line (line)
|
||||
char *line;
|
||||
execute_line (char *line)
|
||||
{
|
||||
register int i;
|
||||
COMMAND *command;
|
||||
@@ -202,8 +168,7 @@ execute_line (line)
|
||||
/* Look up NAME as the name of a command, and return a pointer to that
|
||||
command. Return a NULL pointer if NAME isn't a command name. */
|
||||
COMMAND *
|
||||
find_command (name)
|
||||
char *name;
|
||||
find_command (char *name)
|
||||
{
|
||||
register int i;
|
||||
|
||||
@@ -217,8 +182,7 @@ find_command (name)
|
||||
/* Strip whitespace from the start and end of STRING. Return a pointer
|
||||
into STRING. */
|
||||
char *
|
||||
stripwhite (string)
|
||||
char *string;
|
||||
stripwhite (char *string)
|
||||
{
|
||||
register char *s, *t;
|
||||
|
||||
@@ -242,14 +206,14 @@ stripwhite (string)
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
char *command_generator PARAMS((const char *, int));
|
||||
char **fileman_completion PARAMS((const char *, int, int));
|
||||
char *command_generator (const char *, int);
|
||||
char **fileman_completion (const char *, int, int);
|
||||
|
||||
/* Tell the GNU Readline library how to complete. We want to try to complete
|
||||
on command names if this is the first word in the line, or on filenames
|
||||
if not. */
|
||||
void
|
||||
initialize_readline ()
|
||||
initialize_readline (void)
|
||||
{
|
||||
/* Allow conditional parsing of the ~/.inputrc file. */
|
||||
rl_readline_name = "FileMan";
|
||||
@@ -264,9 +228,7 @@ initialize_readline ()
|
||||
in case we want to do some simple parsing. Return the array of matches,
|
||||
or NULL if there aren't any. */
|
||||
char **
|
||||
fileman_completion (text, start, end)
|
||||
const char *text;
|
||||
int start, end;
|
||||
fileman_completion (const char *text, int start, int end)
|
||||
{
|
||||
char **matches;
|
||||
|
||||
@@ -285,9 +247,7 @@ fileman_completion (text, start, end)
|
||||
to start from scratch; without any state (i.e. STATE == 0), then we
|
||||
start at the top of the list. */
|
||||
char *
|
||||
command_generator (text, state)
|
||||
const char *text;
|
||||
int state;
|
||||
command_generator (const char *text, int state)
|
||||
{
|
||||
static int list_index, len;
|
||||
char *name;
|
||||
@@ -326,43 +286,39 @@ static char syscom[1024];
|
||||
|
||||
/* List the file(s) named in arg. */
|
||||
int
|
||||
com_list (arg)
|
||||
char *arg;
|
||||
com_list (char *arg)
|
||||
{
|
||||
if (!arg)
|
||||
arg = "";
|
||||
|
||||
sprintf (syscom, "ls -FClg %s", arg);
|
||||
snprintf (syscom, sizeof (syscom), "ls -FClg %s", arg);
|
||||
return (system (syscom));
|
||||
}
|
||||
|
||||
int
|
||||
com_view (arg)
|
||||
char *arg;
|
||||
com_view (char *arg)
|
||||
{
|
||||
if (!valid_argument ("view", arg))
|
||||
return 1;
|
||||
|
||||
#if defined (__MSDOS__)
|
||||
/* more.com doesn't grok slashes in pathnames */
|
||||
sprintf (syscom, "less %s", arg);
|
||||
snprintf (syscom, sizeof (syscom), "less %s", arg);
|
||||
#else
|
||||
sprintf (syscom, "more %s", arg);
|
||||
snprintf (syscom, sizeof (syscom), "more %s", arg);
|
||||
#endif
|
||||
return (system (syscom));
|
||||
}
|
||||
|
||||
int
|
||||
com_rename (arg)
|
||||
char *arg;
|
||||
com_rename (char *arg)
|
||||
{
|
||||
too_dangerous ("rename");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
com_stat (arg)
|
||||
char *arg;
|
||||
com_stat (char *arg)
|
||||
{
|
||||
struct stat finfo;
|
||||
|
||||
@@ -390,8 +346,7 @@ com_stat (arg)
|
||||
}
|
||||
|
||||
int
|
||||
com_delete (arg)
|
||||
char *arg;
|
||||
com_delete (char *arg)
|
||||
{
|
||||
too_dangerous ("delete");
|
||||
return (1);
|
||||
@@ -400,8 +355,7 @@ com_delete (arg)
|
||||
/* Print out help for ARG, or for all of the commands if ARG is
|
||||
not present. */
|
||||
int
|
||||
com_help (arg)
|
||||
char *arg;
|
||||
com_help (char *arg)
|
||||
{
|
||||
register int i;
|
||||
int printed = 0;
|
||||
@@ -440,8 +394,7 @@ com_help (arg)
|
||||
|
||||
/* Change to the directory ARG. */
|
||||
int
|
||||
com_cd (arg)
|
||||
char *arg;
|
||||
com_cd (char *arg)
|
||||
{
|
||||
if (chdir (arg) == -1)
|
||||
{
|
||||
@@ -455,8 +408,7 @@ com_cd (arg)
|
||||
|
||||
/* Print out the current working directory. */
|
||||
int
|
||||
com_pwd (ignore)
|
||||
char *ignore;
|
||||
com_pwd (char *ignore)
|
||||
{
|
||||
char dir[1024], *s;
|
||||
|
||||
@@ -473,8 +425,7 @@ com_pwd (ignore)
|
||||
|
||||
/* The user wishes to quit using this program. Just set DONE non-zero. */
|
||||
int
|
||||
com_quit (arg)
|
||||
char *arg;
|
||||
com_quit (char *arg)
|
||||
{
|
||||
done = 1;
|
||||
return (0);
|
||||
@@ -482,8 +433,7 @@ com_quit (arg)
|
||||
|
||||
/* Function which tells you that you can't do this. */
|
||||
void
|
||||
too_dangerous (caller)
|
||||
char *caller;
|
||||
too_dangerous (char *caller)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"%s: Too dangerous for me to distribute. Write it yourself.\n",
|
||||
@@ -493,8 +443,7 @@ too_dangerous (caller)
|
||||
/* Return non-zero if ARG is a valid argument for CALLER, else print
|
||||
an error message and return zero. */
|
||||
int
|
||||
valid_argument (caller, arg)
|
||||
char *caller, *arg;
|
||||
valid_argument (char *caller, char *arg)
|
||||
{
|
||||
if (!arg || !*arg)
|
||||
{
|
||||
@@ -504,3 +453,36 @@ valid_argument (caller, arg)
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
char *line, *s;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
initialize_readline (); /* Bind our completer. */
|
||||
|
||||
/* Loop reading and executing lines until the user quits. */
|
||||
for ( ; done == 0; )
|
||||
{
|
||||
line = readline ("FileMan: ");
|
||||
|
||||
if (!line)
|
||||
break;
|
||||
|
||||
/* Remove leading and trailing whitespace from the line.
|
||||
Then, if there is anything left, add it to the history list
|
||||
and execute it. */
|
||||
s = stripwhite (line);
|
||||
|
||||
if (*s)
|
||||
{
|
||||
add_history (s);
|
||||
execute_line (s);
|
||||
}
|
||||
|
||||
free (line);
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
||||
@@ -32,9 +32,7 @@
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
char line[1024], *t;
|
||||
int len, done;
|
||||
@@ -91,6 +89,7 @@ main (argc, argv)
|
||||
register HIST_ENTRY **the_list;
|
||||
register int i;
|
||||
time_t tt;
|
||||
struct tm *tm;
|
||||
char timestr[128];
|
||||
|
||||
the_list = history_list ();
|
||||
@@ -98,8 +97,9 @@ main (argc, argv)
|
||||
for (i = 0; the_list[i]; i++)
|
||||
{
|
||||
tt = history_get_time (the_list[i]);
|
||||
if (tt)
|
||||
strftime (timestr, sizeof (timestr), "%a %R", localtime(&tt));
|
||||
tm = tt ? localtime (&tt) : 0;
|
||||
if (tm)
|
||||
strftime (timestr, sizeof (timestr), "%a %R", tm);
|
||||
else
|
||||
strcpy (timestr, "??");
|
||||
printf ("%d: %s: %s\n", i + history_base, timestr, the_list[i]->line);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* manexamp.c -- The examples which appear in the documentation are here. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2009,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
@@ -18,9 +18,35 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Readline. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <readline/readline.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if defined (READLINE_LIBRARY)
|
||||
# include "readline.h"
|
||||
# include "history.h"
|
||||
#else
|
||||
# include <readline/readline.h>
|
||||
# include <readline/history.h>
|
||||
#endif
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
@@ -33,7 +59,7 @@ static char *line_read = (char *)NULL;
|
||||
|
||||
/* Read a string, and return a pointer to it. Returns NULL on EOF. */
|
||||
char *
|
||||
rl_gets ()
|
||||
rl_gets (void)
|
||||
{
|
||||
/* If the buffer has already been allocated, return the memory
|
||||
to the free pool. */
|
||||
@@ -60,10 +86,11 @@ rl_gets ()
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Invert the case of the COUNT following characters. */
|
||||
invert_case_line (count, key)
|
||||
int count, key;
|
||||
int
|
||||
invert_case_line (int count, int key)
|
||||
{
|
||||
register int start, end;
|
||||
int start, end;
|
||||
int direction;
|
||||
|
||||
start = rl_point;
|
||||
|
||||
@@ -92,7 +119,7 @@ invert_case_line (count, key)
|
||||
}
|
||||
|
||||
if (start == end)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
/* Tell readline that we are modifying the line, so save the undo
|
||||
information. */
|
||||
@@ -108,4 +135,5 @@ invert_case_line (count, key)
|
||||
|
||||
/* Move point to on top of the last character changed. */
|
||||
rl_point = end - direction;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* usage: rl [-p prompt] [-u unit] [-d default] [-n nchars]
|
||||
*/
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
@@ -55,15 +55,11 @@ extern void exit();
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
#if !defined (strchr) && !defined (__STDC__)
|
||||
extern char *strrchr();
|
||||
#endif
|
||||
|
||||
static char *progname;
|
||||
static char *deftext;
|
||||
|
||||
static int
|
||||
set_deftext ()
|
||||
set_deftext (void)
|
||||
{
|
||||
if (deftext)
|
||||
{
|
||||
@@ -75,16 +71,14 @@ set_deftext ()
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
usage(void)
|
||||
{
|
||||
fprintf (stderr, "%s: usage: %s [-p prompt] [-u unit] [-d default] [-n nchars]\n",
|
||||
progname, progname);
|
||||
}
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
char *temp, *prompt;
|
||||
struct stat sb;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* usage: rlcat
|
||||
*/
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2009,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
@@ -64,27 +64,26 @@ extern int errno;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
static int stdcat();
|
||||
static int fcopy(FILE *);
|
||||
static int stdcat(int, char **);
|
||||
|
||||
static char *progname;
|
||||
static int vflag;
|
||||
|
||||
static void
|
||||
usage()
|
||||
usage(void)
|
||||
{
|
||||
fprintf (stderr, "%s: usage: %s [-vEVN] [filename]\n", progname, progname);
|
||||
}
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
char *temp;
|
||||
int opt, Vflag, Nflag;
|
||||
|
||||
#ifdef HAVE_SETLOCALE
|
||||
setlocale (LC_ALL, ""):
|
||||
setlocale (LC_ALL, "");
|
||||
#endif
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
@@ -134,8 +133,7 @@ main (argc, argv)
|
||||
}
|
||||
|
||||
static int
|
||||
fcopy(fp)
|
||||
FILE *fp;
|
||||
fcopy(FILE *fp)
|
||||
{
|
||||
int c;
|
||||
char *x;
|
||||
@@ -155,9 +153,7 @@ fcopy(fp)
|
||||
}
|
||||
|
||||
int
|
||||
stdcat (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
stdcat (int argc, char **argv)
|
||||
{
|
||||
int i, fd, r;
|
||||
char *s;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2009,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
@@ -48,10 +48,8 @@ extern void exit();
|
||||
# include <readline/history.h>
|
||||
#endif
|
||||
|
||||
extern HIST_ENTRY **history_list ();
|
||||
|
||||
int
|
||||
main ()
|
||||
main (int c, char **v)
|
||||
{
|
||||
char *temp, *prompt;
|
||||
int done;
|
||||
|
||||
@@ -40,16 +40,12 @@
|
||||
|
||||
#include "xmalloc.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef int QSFUNC (const void *, const void *);
|
||||
#else
|
||||
typedef int QSFUNC ();
|
||||
#endif
|
||||
|
||||
extern int _rl_qsort_string_compare (char **, char **);
|
||||
|
||||
FUNMAP **funmap;
|
||||
static int funmap_size;
|
||||
static size_t funmap_size;
|
||||
static int funmap_entry;
|
||||
|
||||
/* After initializing the function map, this is the index of the first
|
||||
@@ -93,6 +89,7 @@ static const FUNMAP default_funmap[] = {
|
||||
{ "end-of-history", rl_end_of_history },
|
||||
{ "end-of-line", rl_end_of_line },
|
||||
{ "exchange-point-and-mark", rl_exchange_point_and_mark },
|
||||
{ "execute-named-command", rl_execute_named_command },
|
||||
{ "fetch-history", rl_fetch_history },
|
||||
{ "forward-backward-delete-char", rl_rubout_or_delete },
|
||||
{ "forward-byte", rl_forward_byte },
|
||||
@@ -251,7 +248,7 @@ const char **
|
||||
rl_funmap_names (void)
|
||||
{
|
||||
const char **result;
|
||||
int result_size, result_index;
|
||||
size_t result_size, result_index;
|
||||
|
||||
/* Make sure that the function map has been initialized. */
|
||||
rl_initialize_funmap ();
|
||||
|
||||
+39
-26
@@ -1,6 +1,6 @@
|
||||
/* histexpand.c -- history expansion. */
|
||||
|
||||
/* Copyright (C) 1989-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2021,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (History), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
@@ -70,12 +70,12 @@ static int subst_rhs_len;
|
||||
specifications from word designators. Static for now */
|
||||
static char *history_event_delimiter_chars = HISTORY_EVENT_DELIMITERS;
|
||||
|
||||
static char *get_history_word_specifier (char *, char *, int *);
|
||||
static char *get_history_word_specifier (const char *, char *, int *);
|
||||
static int history_tokenize_word (const char *, int);
|
||||
static char **history_tokenize_internal (const char *, int, int *);
|
||||
static char *history_substring (const char *, int, int);
|
||||
static void freewords (char **, int);
|
||||
static char *history_find_word (char *, int);
|
||||
static char *history_find_word (const char *, int);
|
||||
|
||||
static char *quote_breaks (char *);
|
||||
|
||||
@@ -319,7 +319,7 @@ get_history_event (const char *string, int *caller_index, int delimiting_quote)
|
||||
to the closing single quote. FLAGS currently used to allow backslash
|
||||
to escape a single quote (e.g., for bash $'...'). */
|
||||
static void
|
||||
hist_string_extract_single_quoted (char *string, int *sindex, int flags)
|
||||
hist_string_extract_single_quoted (const char *string, int *sindex, int flags)
|
||||
{
|
||||
register int i;
|
||||
|
||||
@@ -374,7 +374,7 @@ quote_breaks (char *s)
|
||||
}
|
||||
|
||||
static char *
|
||||
hist_error(char *s, int start, int current, int errtype)
|
||||
hist_error(const char *s, int start, int current, int errtype)
|
||||
{
|
||||
char *temp;
|
||||
const char *emsg;
|
||||
@@ -434,7 +434,7 @@ hist_error(char *s, int start, int current, int errtype)
|
||||
subst_rhs is allowed to be set to the empty string. */
|
||||
|
||||
static char *
|
||||
get_subst_pattern (char *str, int *iptr, int delimiter, int is_rhs, int *lenptr)
|
||||
get_subst_pattern (const char *str, int *iptr, int delimiter, int is_rhs, int *lenptr)
|
||||
{
|
||||
register int si, i, j, k;
|
||||
char *s;
|
||||
@@ -509,7 +509,7 @@ postproc_subst_rhs (void)
|
||||
/* a single backslash protects the `&' from lhs interpolation */
|
||||
if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
|
||||
i++;
|
||||
if (j >= new_size)
|
||||
if (j + 1 >= new_size)
|
||||
new = (char *)xrealloc (new, new_size *= 2);
|
||||
new[j++] = subst_rhs[i];
|
||||
}
|
||||
@@ -527,12 +527,12 @@ postproc_subst_rhs (void)
|
||||
*END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
|
||||
/* need current line for !# */
|
||||
static int
|
||||
history_expand_internal (char *string, int start, int qc, int *end_index_ptr, char **ret_string, char *current_line)
|
||||
history_expand_internal (const char *string, int start, int qc, int *end_index_ptr, char **ret_string, char *current_line)
|
||||
{
|
||||
int i, n, starting_index;
|
||||
int substitute_globally, subst_bywords, want_quotes, print_only;
|
||||
char *event, *temp, *result, *tstr, *t, c, *word_spec;
|
||||
int result_len;
|
||||
size_t result_len;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mbstate_t ps;
|
||||
|
||||
@@ -730,7 +730,7 @@ history_expand_internal (char *string, int start, int qc, int *end_index_ptr, ch
|
||||
|
||||
/* If `&' appears in the rhs, it's supposed to be replaced
|
||||
with the lhs. */
|
||||
if (member ('&', subst_rhs))
|
||||
if (subst_lhs && member ('&', subst_rhs))
|
||||
postproc_subst_rhs ();
|
||||
}
|
||||
else
|
||||
@@ -881,7 +881,7 @@ history_expand_internal (char *string, int start, int qc, int *end_index_ptr, ch
|
||||
#define ADD_STRING(s) \
|
||||
do \
|
||||
{ \
|
||||
int sl = strlen (s); \
|
||||
size_t sl = strlen (s); \
|
||||
j += sl; \
|
||||
if (j >= result_len) \
|
||||
{ \
|
||||
@@ -896,7 +896,7 @@ history_expand_internal (char *string, int start, int qc, int *end_index_ptr, ch
|
||||
#define ADD_CHAR(c) \
|
||||
do \
|
||||
{ \
|
||||
if (j >= result_len - 1) \
|
||||
if ((j + 1) >= result_len) \
|
||||
result = (char *)xrealloc (result, result_len += 64); \
|
||||
result[j++] = c; \
|
||||
result[j] = '\0'; \
|
||||
@@ -904,14 +904,15 @@ history_expand_internal (char *string, int start, int qc, int *end_index_ptr, ch
|
||||
while (0)
|
||||
|
||||
int
|
||||
history_expand (char *hstring, char **output)
|
||||
history_expand (const char *hstring, char **output)
|
||||
{
|
||||
register int j;
|
||||
int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag;
|
||||
int j;
|
||||
int i, r, passc, cc, modified, eindex, only_printing, dquote, squote, flag;
|
||||
size_t l;
|
||||
char *string;
|
||||
|
||||
/* The output string, and its length. */
|
||||
int result_len;
|
||||
size_t result_len;
|
||||
char *result;
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
@@ -949,7 +950,7 @@ history_expand (char *hstring, char **output)
|
||||
/* The quick substitution character is a history expansion all right. That
|
||||
is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
|
||||
that is the substitution that we do. */
|
||||
if (hstring[0] == history_subst_char)
|
||||
if ((history_quoting_state != '\'' || history_quotes_inhibit_expansion == 0) && hstring[0] == history_subst_char)
|
||||
{
|
||||
string = (char *)xmalloc (l + 5);
|
||||
|
||||
@@ -965,7 +966,7 @@ history_expand (char *hstring, char **output)
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
#endif
|
||||
|
||||
string = hstring;
|
||||
string = (char *)hstring;
|
||||
/* If not quick substitution, still maybe have to do expansion. */
|
||||
|
||||
/* `!' followed by one of the characters in history_no_expand_chars
|
||||
@@ -983,6 +984,8 @@ history_expand (char *hstring, char **output)
|
||||
squote = 0;
|
||||
if (string[i])
|
||||
i++;
|
||||
if (i >= l)
|
||||
i = l;
|
||||
}
|
||||
|
||||
for ( ; string[i]; i++)
|
||||
@@ -1053,6 +1056,11 @@ history_expand (char *hstring, char **output)
|
||||
flag = (i > 0 && string[i - 1] == '$');
|
||||
i++;
|
||||
hist_string_extract_single_quoted (string, &i, flag);
|
||||
if (i >= l)
|
||||
{
|
||||
i = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (history_quotes_inhibit_expansion && string[i] == '\\')
|
||||
{
|
||||
@@ -1063,7 +1071,7 @@ history_expand (char *hstring, char **output)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (string[i] != history_expansion_char)
|
||||
{
|
||||
xfree (result);
|
||||
@@ -1113,7 +1121,7 @@ history_expand (char *hstring, char **output)
|
||||
|
||||
c = tchar;
|
||||
memset (mb, 0, sizeof (mb));
|
||||
for (k = 0; k < MB_LEN_MAX; k++)
|
||||
for (k = 0; k < MB_LEN_MAX && i < l; k++)
|
||||
{
|
||||
mb[k] = (char)c;
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
@@ -1303,7 +1311,7 @@ history_expand (char *hstring, char **output)
|
||||
CALLER_INDEX is the offset in SPEC to start looking; it is updated
|
||||
to point to just after the last character parsed. */
|
||||
static char *
|
||||
get_history_word_specifier (char *spec, char *from, int *caller_index)
|
||||
get_history_word_specifier (const char *spec, char *from, int *caller_index)
|
||||
{
|
||||
register int i = *caller_index;
|
||||
int first, last;
|
||||
@@ -1418,7 +1426,7 @@ history_arg_extract (int first, int last, const char *string)
|
||||
{
|
||||
register int i, len;
|
||||
char *result;
|
||||
int size, offset;
|
||||
size_t size, offset;
|
||||
char **list;
|
||||
|
||||
/* XXX - think about making history_tokenize return a struct array,
|
||||
@@ -1475,7 +1483,7 @@ history_arg_extract (int first, int last, const char *string)
|
||||
static int
|
||||
history_tokenize_word (const char *string, int ind)
|
||||
{
|
||||
register int i, j;
|
||||
int i, j;
|
||||
int delimiter, nestdelim, delimopen;
|
||||
|
||||
i = ind;
|
||||
@@ -1562,6 +1570,8 @@ get_word:
|
||||
(delimiter != '"' || member (string[i], slashify_in_quotes)))
|
||||
{
|
||||
i++;
|
||||
if (string[i] == 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1590,6 +1600,8 @@ get_word:
|
||||
if (nestdelim == 0 && delimiter == 0 && member (string[i], "<>$!@?+*") && string[i+1] == '(') /*)*/
|
||||
{
|
||||
i += 2;
|
||||
if (string[i] == 0)
|
||||
break; /* could just return i here */
|
||||
delimopen = '(';
|
||||
delimiter = ')';
|
||||
nestdelim = 1;
|
||||
@@ -1627,7 +1639,8 @@ static char **
|
||||
history_tokenize_internal (const char *string, int wind, int *indp)
|
||||
{
|
||||
char **result;
|
||||
register int i, start, result_index, size;
|
||||
int i, start, result_index;
|
||||
size_t size;
|
||||
|
||||
/* If we're searching for a string that's not part of a word (e.g., " "),
|
||||
make sure we set *INDP to a reasonable value. */
|
||||
@@ -1636,7 +1649,7 @@ history_tokenize_internal (const char *string, int wind, int *indp)
|
||||
|
||||
/* Get a token, and stuff it into RESULT. The tokens are split
|
||||
exactly where the shell would split them. */
|
||||
for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
|
||||
for (i = result_index = 0, size = 0, result = (char **)NULL; string[i]; )
|
||||
{
|
||||
/* Skip leading whitespace. */
|
||||
for (; string[i] && fielddelim (string[i]); i++)
|
||||
@@ -1696,7 +1709,7 @@ freewords (char **words, int start)
|
||||
in the history line LINE. Used to save the word matched by the
|
||||
last history !?string? search. */
|
||||
static char *
|
||||
history_find_word (char *line, int ind)
|
||||
history_find_word (const char *line, int ind)
|
||||
{
|
||||
char **words, *s;
|
||||
int i, wind;
|
||||
|
||||
+89
-25
@@ -1,6 +1,6 @@
|
||||
/* histfile.c - functions to manipulate the history file. */
|
||||
|
||||
/* Copyright (C) 1989-2019 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2019,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (History), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
@@ -153,7 +153,7 @@ history_filename (const char *filename)
|
||||
{
|
||||
char *return_val;
|
||||
const char *home;
|
||||
int home_len;
|
||||
size_t home_len;
|
||||
|
||||
return_val = filename ? savestring (filename) : (char *)NULL;
|
||||
|
||||
@@ -168,9 +168,8 @@ history_filename (const char *filename)
|
||||
|
||||
if (home == 0)
|
||||
return (NULL);
|
||||
else
|
||||
home_len = strlen (home);
|
||||
|
||||
home_len = strlen (home);
|
||||
return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
|
||||
strcpy (return_val, home);
|
||||
return_val[home_len] = '/';
|
||||
@@ -190,7 +189,6 @@ history_backupfile (const char *filename)
|
||||
char *ret, linkbuf[PATH_MAX+1];
|
||||
size_t len;
|
||||
ssize_t n;
|
||||
struct stat fs;
|
||||
|
||||
fn = filename;
|
||||
#if defined (HAVE_READLINK)
|
||||
@@ -218,7 +216,6 @@ history_tempfile (const char *filename)
|
||||
char *ret, linkbuf[PATH_MAX+1];
|
||||
size_t len;
|
||||
ssize_t n;
|
||||
struct stat fs;
|
||||
int pid;
|
||||
|
||||
fn = filename;
|
||||
@@ -284,7 +281,10 @@ read_history_range (const char *filename, int from, int to)
|
||||
|
||||
buffer = last_ts = (char *)NULL;
|
||||
input = history_filename (filename);
|
||||
file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
|
||||
if (input == 0)
|
||||
return 0;
|
||||
errno = 0;
|
||||
file = open (input, O_RDONLY|O_BINARY, 0666);
|
||||
|
||||
if ((file < 0) || (fstat (file, &finfo) == -1))
|
||||
goto error_and_exit;
|
||||
@@ -526,10 +526,14 @@ history_truncate_file (const char *fname, int lines)
|
||||
|
||||
buffer = (char *)NULL;
|
||||
filename = history_filename (fname);
|
||||
if (filename == 0)
|
||||
return 0;
|
||||
tempname = 0;
|
||||
file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
|
||||
file = open (filename, O_RDONLY|O_BINARY, 0666);
|
||||
rv = exists = 0;
|
||||
|
||||
orig_lines = lines;
|
||||
|
||||
/* Don't try to truncate non-regular files. */
|
||||
if (file == -1 || fstat (file, &finfo) == -1)
|
||||
{
|
||||
@@ -578,6 +582,15 @@ history_truncate_file (const char *fname, int lines)
|
||||
goto truncate_exit;
|
||||
}
|
||||
|
||||
/* Don't bother with any of this if we're truncating to zero length. */
|
||||
if (lines == 0)
|
||||
{
|
||||
close (file);
|
||||
buffer[chars_read = 0] = '\0';
|
||||
bp = buffer;
|
||||
goto truncate_write;
|
||||
}
|
||||
|
||||
chars_read = read (file, buffer, file_size);
|
||||
close (file);
|
||||
|
||||
@@ -586,31 +599,38 @@ history_truncate_file (const char *fname, int lines)
|
||||
rv = (chars_read < 0) ? errno : 0;
|
||||
goto truncate_exit;
|
||||
}
|
||||
buffer[chars_read] = '\0'; /* for the initial check of bp1[1] */
|
||||
|
||||
orig_lines = lines;
|
||||
/* Count backwards from the end of buffer until we have passed
|
||||
LINES lines. bp1 is set funny initially. But since bp[1] can't
|
||||
be a comment character (since it's off the end) and *bp can't be
|
||||
both a newline and the history comment character, it should be OK. */
|
||||
for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
|
||||
both a newline and the history comment character, it should be OK.
|
||||
If we are writing history timestamps, we need to add one to LINES
|
||||
because we decrement it one extra time the first time through the loop
|
||||
and we need the final timestamp line. */
|
||||
lines += history_write_timestamps;
|
||||
for (bp1 = bp = buffer + chars_read - 1; lines > 0 && bp > buffer; bp--)
|
||||
{
|
||||
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
|
||||
lines--;
|
||||
bp1 = bp;
|
||||
}
|
||||
|
||||
/* If this is the first line, then the file contains exactly the
|
||||
/* This is the right line, so move to its start. If we're writing history
|
||||
timestamps, we want to go back until *bp == '\n' and bp1 starts a
|
||||
history timestamp. If we're not, just move back to *bp == '\n'.
|
||||
If this is the first line, then the file contains exactly the
|
||||
number of lines we want to truncate to, so we don't need to do
|
||||
anything. It's the first line if we don't find a newline between
|
||||
the current value of i and 0. Otherwise, write from the start of
|
||||
this line until the end of the buffer. */
|
||||
anything, and we'll end up with bp == buffer.
|
||||
Otherwise, write from the start of this line until the end of the
|
||||
buffer. */
|
||||
for ( ; bp > buffer; bp--)
|
||||
{
|
||||
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
|
||||
{
|
||||
if (*bp == '\n' && (history_write_timestamps == 0 || HIST_TIMESTAMP_START(bp1)))
|
||||
{
|
||||
bp++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bp1 = bp;
|
||||
}
|
||||
|
||||
@@ -624,17 +644,24 @@ history_truncate_file (const char *fname, int lines)
|
||||
goto truncate_exit;
|
||||
}
|
||||
|
||||
truncate_write:
|
||||
tempname = history_tempfile (filename);
|
||||
|
||||
if ((file = open (tempname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) != -1)
|
||||
{
|
||||
if (write (file, bp, chars_read - (bp - buffer)) < 0)
|
||||
rv = errno;
|
||||
{
|
||||
rv = errno;
|
||||
close (file);
|
||||
}
|
||||
|
||||
if (fstat (file, &nfinfo) < 0 && rv == 0)
|
||||
rv = errno;
|
||||
if (rv == 0 && fstat (file, &nfinfo) < 0)
|
||||
{
|
||||
rv = errno;
|
||||
close (file);
|
||||
}
|
||||
|
||||
if (close (file) < 0 && rv == 0)
|
||||
if (rv == 0 && close (file) < 0)
|
||||
rv = errno;
|
||||
}
|
||||
else
|
||||
@@ -671,6 +698,38 @@ history_truncate_file (const char *fname, int lines)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Use stdio to write the history file after mmap or malloc fails, on the
|
||||
assumption that the stdio library can allocate the smaller buffers it uses. */
|
||||
static int
|
||||
history_write_slow (int fd, HIST_ENTRY **the_history, int nelements, int overwrite)
|
||||
{
|
||||
FILE *fp;
|
||||
int i, j, e;
|
||||
|
||||
fp = fdopen (fd, overwrite ? "w" : "a");
|
||||
if (fp == 0)
|
||||
return -1;
|
||||
|
||||
for (j = 0, i = history_length - nelements; i < history_length; i++)
|
||||
{
|
||||
if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
|
||||
fprintf (fp, "%s\n", the_history[i]->timestamp);
|
||||
if (fprintf (fp, "%s\n", the_history[i]->line) < 0)
|
||||
goto slow_write_error;
|
||||
}
|
||||
if (fflush (fp) < 0)
|
||||
{
|
||||
slow_write_error:
|
||||
e = errno;
|
||||
fclose (fp);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
if (fclose (fp) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Workhorse function for writing history. Writes the last NELEMENT entries
|
||||
from the history list to FILENAME. OVERWRITE is non-zero if you
|
||||
wish to replace FILENAME with the entries. */
|
||||
@@ -680,7 +739,7 @@ history_do_write (const char *filename, int nelements, int overwrite)
|
||||
register int i;
|
||||
char *output, *tempname, *histname;
|
||||
int file, mode, rv, exists;
|
||||
struct stat finfo, nfinfo;
|
||||
struct stat finfo;
|
||||
#ifdef HISTORY_USE_MMAP
|
||||
size_t cursize;
|
||||
|
||||
@@ -718,8 +777,8 @@ history_do_write (const char *filename, int nelements, int overwrite)
|
||||
Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
|
||||
{
|
||||
HIST_ENTRY **the_history; /* local */
|
||||
register int j;
|
||||
int buffer_size;
|
||||
size_t j;
|
||||
size_t buffer_size;
|
||||
char *buffer;
|
||||
|
||||
the_history = history_list ();
|
||||
@@ -739,6 +798,8 @@ history_do_write (const char *filename, int nelements, int overwrite)
|
||||
if ((void *)buffer == MAP_FAILED)
|
||||
{
|
||||
mmap_error:
|
||||
if ((rv = history_write_slow (file, the_history, nelements, overwrite)) == 0)
|
||||
goto write_success;
|
||||
rv = errno;
|
||||
close (file);
|
||||
if (tempname)
|
||||
@@ -751,6 +812,8 @@ mmap_error:
|
||||
buffer = (char *)malloc (buffer_size);
|
||||
if (buffer == 0)
|
||||
{
|
||||
if ((rv = history_write_slow (file, the_history, nelements, overwrite)) == 0)
|
||||
goto write_success;
|
||||
rv = errno;
|
||||
close (file);
|
||||
if (tempname)
|
||||
@@ -789,6 +852,7 @@ mmap_error:
|
||||
if (close (file) < 0 && rv == 0)
|
||||
rv = errno;
|
||||
|
||||
write_success:
|
||||
if (rv == 0 && histname && tempname)
|
||||
rv = histfile_restore (tempname, histname);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* histlib.h -- internal definitions for the history library. */
|
||||
|
||||
/* Copyright (C) 1989-2009,2021-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2009,2021-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (History), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
@@ -34,6 +34,11 @@
|
||||
: ((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
|
||||
#endif
|
||||
|
||||
#if !defined (HAVE_STRCASECMP)
|
||||
#define strcasecmp(a,b) strcmp ((a), (b))
|
||||
#define strncasecmp(a, b, n) strncmp ((a), (b), (n))
|
||||
#endif
|
||||
|
||||
#ifndef savestring
|
||||
#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
|
||||
#endif
|
||||
@@ -51,9 +56,6 @@
|
||||
#endif
|
||||
|
||||
#ifndef member
|
||||
# if !defined (strchr) && !defined (__STDC__)
|
||||
extern char *strchr ();
|
||||
# endif /* !strchr && !__STDC__ */
|
||||
#define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0)
|
||||
#endif
|
||||
|
||||
@@ -72,6 +74,7 @@ extern char *strchr ();
|
||||
#define NON_ANCHORED_SEARCH 0
|
||||
#define ANCHORED_SEARCH 0x01
|
||||
#define PATTERN_SEARCH 0x02
|
||||
#define CASEFOLD_SEARCH 0x04
|
||||
|
||||
/* Possible definitions for what style of writing the history file we want. */
|
||||
#define HISTORY_APPEND 0
|
||||
@@ -81,9 +84,11 @@ extern char *strchr ();
|
||||
|
||||
/* histsearch.c */
|
||||
extern int _hs_history_patsearch (const char *, int, int);
|
||||
extern int _hs_history_search (const char *, int, int);
|
||||
|
||||
/* history.c */
|
||||
extern void _hs_replace_history_data (int, histdata_t *, histdata_t *);
|
||||
extern int _hs_search_history_data (histdata_t *);
|
||||
extern int _hs_at_end_of_history (void);
|
||||
|
||||
/* histfile.c */
|
||||
|
||||
+140
-21
@@ -1,6 +1,6 @@
|
||||
/* history.c -- standalone history library */
|
||||
|
||||
/* Copyright (C) 1989-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (History), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
@@ -42,6 +42,7 @@
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include "posixtime.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@@ -60,24 +61,39 @@ extern int errno;
|
||||
#define MAX_HISTORY_INITIAL_SIZE 8192
|
||||
|
||||
/* The number of slots to increase the_history by. */
|
||||
#define DEFAULT_HISTORY_GROW_SIZE 50
|
||||
#define DEFAULT_HISTORY_GROW_SIZE 256
|
||||
|
||||
static char *hist_inittime (void);
|
||||
|
||||
static int history_list_grow_size (void);
|
||||
static void history_list_resize (int); /* XXX - size_t? */
|
||||
static void advance_history (void);
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* History Functions */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* An array of HIST_ENTRY. This is where we store the history. */
|
||||
/* An array of HIST_ENTRY. This is where we store the history. the_history is
|
||||
a roving pointer somewhere into this, so the user-visible history list is
|
||||
a window into real_history starting at the_history and extending
|
||||
history_length entries. */
|
||||
static HIST_ENTRY **real_history = (HIST_ENTRY **)NULL;
|
||||
|
||||
/* The current number of slots allocated to the input_history. */
|
||||
static int real_history_size = 0;
|
||||
|
||||
/* A pointer to somewhere in real_history, where the user-visible history
|
||||
starts. */
|
||||
static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
|
||||
|
||||
/* Non-zero means that we have enforced a limit on the amount of
|
||||
history that we save. */
|
||||
static int history_stifled;
|
||||
|
||||
/* The current number of slots allocated to the input_history. */
|
||||
/* The number of history entries available for user use, starting at the_history.
|
||||
real_history_size - history_size == the_history - real_history */
|
||||
static int history_size;
|
||||
|
||||
/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
|
||||
@@ -89,12 +105,59 @@ int max_input_history; /* backwards compatibility */
|
||||
life easier for outside callers. */
|
||||
int history_offset;
|
||||
|
||||
/* The number of strings currently stored in the history list. */
|
||||
/* The number of strings currently stored in the history list. This is
|
||||
always <= real_history_length */
|
||||
int history_length;
|
||||
|
||||
/* The logical `base' of the history array. It defaults to 1. */
|
||||
int history_base = 1;
|
||||
|
||||
/* Compute the number of bits required to store a given nonnegative integer.
|
||||
|
||||
NOTE: _bit_length(0) == 0 */
|
||||
static inline unsigned
|
||||
_bit_length(unsigned n)
|
||||
{
|
||||
/* This implementation is for simplicity, not for performance, but it is
|
||||
fast enough for our purposes here. */
|
||||
unsigned count = 0;
|
||||
while (n)
|
||||
{
|
||||
n >>= 1;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Compute a grow size that adjusts to the size of the history.
|
||||
|
||||
We aim to grow by roughly sqrt(history_size) in order to amortize the cost of
|
||||
realloc() and memmove(). This reduces the total cost of the memmoves from
|
||||
O(N^2) to O(N*sqrt(N)). */
|
||||
static int
|
||||
history_list_grow_size (void)
|
||||
{
|
||||
int width, r;
|
||||
/* Handle small positive values and guard against history_length accidentally
|
||||
being negative. */
|
||||
const int MIN_BITS = 10;
|
||||
if (history_length < (1 << MIN_BITS))
|
||||
return DEFAULT_HISTORY_GROW_SIZE;
|
||||
|
||||
/* For other values, we just want something easy to compute that grows roughly
|
||||
as sqrt(N), where N=history_length. We use approximately 2^((k+1)/2),
|
||||
where k is the bit length of N. This bounds the value between sqrt(2N) and
|
||||
2*sqrt(N). */
|
||||
width = MIN_BITS + _bit_length(history_length >> MIN_BITS);
|
||||
|
||||
/* If width is odd then this is 2^((width+1)/2). An even width gives a value
|
||||
of 3*2^((width-2)/2) ~ 1.06*2^((width+1)/2). */
|
||||
r = (1 << (width / 2)) + (1 << ((width - 1) / 2));
|
||||
|
||||
/* Make sure we always expand the list by at least DEFAULT_HISTORY_GROW_SIZE */
|
||||
return ((r < DEFAULT_HISTORY_GROW_SIZE) ? DEFAULT_HISTORY_GROW_SIZE : r);
|
||||
}
|
||||
|
||||
/* Return the current HISTORY_STATE of the history. */
|
||||
HISTORY_STATE *
|
||||
history_get_history_state (void)
|
||||
@@ -261,7 +324,7 @@ hist_inittime (void)
|
||||
time_t t;
|
||||
char ts[64], *ret;
|
||||
|
||||
t = (time_t) time ((time_t *)0);
|
||||
t = getnow ();
|
||||
#if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
|
||||
snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
|
||||
#else
|
||||
@@ -273,6 +336,48 @@ hist_inittime (void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Ensure space for new history entries by resetting the start pointer
|
||||
(the_history) and resizing real_history if necessary. */
|
||||
static void
|
||||
history_list_resize (int new_size)
|
||||
{
|
||||
/* Do nothing there is already enough user space. history_length is always <=
|
||||
real_history_size */
|
||||
if (new_size < history_length)
|
||||
return;
|
||||
|
||||
/* If we need to, reset the_history to the start of real_history and
|
||||
start over. */
|
||||
if (the_history != real_history)
|
||||
memmove (real_history, the_history, history_length * sizeof (HIST_ENTRY *));
|
||||
|
||||
/* Don't bother if real_history_size is already big enough, since at this
|
||||
point the_history == real_history and we will set history_size to
|
||||
real_history_size. We don't shrink the history list. */
|
||||
if (new_size > real_history_size)
|
||||
{
|
||||
real_history = (HIST_ENTRY **) xrealloc (real_history, new_size * sizeof (HIST_ENTRY *));
|
||||
real_history_size = new_size;
|
||||
}
|
||||
the_history = real_history;
|
||||
history_size = real_history_size;
|
||||
|
||||
if (history_size > history_length)
|
||||
memset (real_history + history_length, 0, (history_size - history_length) * sizeof (HIST_ENTRY *));
|
||||
}
|
||||
|
||||
static void
|
||||
advance_history (void)
|
||||
{
|
||||
/* Advance 'the_history' pointer to simulate dropping the first entry. */
|
||||
the_history++;
|
||||
history_size--;
|
||||
|
||||
/* If full, move all the entries (and trailing NULL) to the beginning. */
|
||||
if (history_length == history_size)
|
||||
history_list_resize (history_length + history_list_grow_size ());
|
||||
}
|
||||
|
||||
/* Place STRING at the end of the history list. The data field
|
||||
is set to NULL. */
|
||||
void
|
||||
@@ -283,8 +388,6 @@ add_history (const char *string)
|
||||
|
||||
if (history_stifled && (history_length == history_max_entries))
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* If the history is stifled, and history_length is zero,
|
||||
and it equals history_max_entries, we don't save items. */
|
||||
if (history_length == 0)
|
||||
@@ -294,9 +397,8 @@ add_history (const char *string)
|
||||
if (the_history[0])
|
||||
(void) free_history_entry (the_history[0]);
|
||||
|
||||
/* Copy the rest of the entries, moving down one slot. Copy includes
|
||||
trailing NULL. */
|
||||
memmove (the_history, the_history + 1, history_length * sizeof (HIST_ENTRY *));
|
||||
/* Advance the pointer into real_history, resizing if necessary. */
|
||||
advance_history ();
|
||||
|
||||
new_length = history_length;
|
||||
history_base++;
|
||||
@@ -305,23 +407,20 @@ add_history (const char *string)
|
||||
{
|
||||
if (history_size == 0)
|
||||
{
|
||||
int initial_size;
|
||||
if (history_stifled && history_max_entries > 0)
|
||||
history_size = (history_max_entries > MAX_HISTORY_INITIAL_SIZE)
|
||||
initial_size = (history_max_entries > MAX_HISTORY_INITIAL_SIZE)
|
||||
? MAX_HISTORY_INITIAL_SIZE
|
||||
: history_max_entries + 2;
|
||||
else
|
||||
history_size = DEFAULT_HISTORY_INITIAL_SIZE;
|
||||
the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
|
||||
initial_size = DEFAULT_HISTORY_INITIAL_SIZE;
|
||||
history_list_resize (initial_size);
|
||||
new_length = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (history_length == (history_size - 1))
|
||||
{
|
||||
history_size += DEFAULT_HISTORY_GROW_SIZE;
|
||||
the_history = (HIST_ENTRY **)
|
||||
xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
|
||||
}
|
||||
history_list_resize (real_history_size + history_list_grow_size ());
|
||||
new_length = history_length + 1;
|
||||
}
|
||||
}
|
||||
@@ -460,7 +559,7 @@ _hs_replace_history_data (int which, histdata_t *old, histdata_t *new)
|
||||
}
|
||||
|
||||
last = -1;
|
||||
for (i = 0; i < history_length; i++)
|
||||
for (i = history_length - 1; i >= 0; i--)
|
||||
{
|
||||
entry = the_history[i];
|
||||
if (entry == 0)
|
||||
@@ -477,7 +576,27 @@ _hs_replace_history_data (int which, histdata_t *old, histdata_t *new)
|
||||
entry = the_history[last];
|
||||
entry->data = new; /* XXX - we don't check entry->old */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
_hs_search_history_data (histdata_t *needle)
|
||||
{
|
||||
register int i;
|
||||
HIST_ENTRY *entry;
|
||||
|
||||
if (history_length == 0 || the_history == 0)
|
||||
return -1;
|
||||
|
||||
for (i = history_length - 1; i >= 0; i--)
|
||||
{
|
||||
entry = the_history[i];
|
||||
if (entry == 0)
|
||||
continue;
|
||||
if (entry->data == needle)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Remove history element WHICH from the history. The removed
|
||||
element is returned to you so you can free the line, data,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* history.h -- the names of functions that you can call in history. */
|
||||
|
||||
/* Copyright (C) 1989-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (History), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
@@ -36,11 +36,7 @@ extern "C" {
|
||||
# include <readline/rltypedefs.h>
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef void *histdata_t;
|
||||
#else
|
||||
typedef char *histdata_t;
|
||||
#endif
|
||||
|
||||
/* Let's not step on anyone else's define for now, since we don't use this yet. */
|
||||
#ifndef HS_HISTORY_VERSION
|
||||
@@ -54,6 +50,10 @@ typedef struct _hist_entry {
|
||||
histdata_t data;
|
||||
} HIST_ENTRY;
|
||||
|
||||
#ifndef HIST_ENTRY_DEFINED
|
||||
# define HIST_ENTRY_DEFINED
|
||||
#endif
|
||||
|
||||
/* Size of the history-library-managed space in history entry HS. */
|
||||
#define HISTENT_BYTES(hs) (strlen ((hs)->line) + strlen ((hs)->timestamp))
|
||||
|
||||
@@ -232,7 +232,7 @@ extern int history_truncate_file (const char *, int);
|
||||
|
||||
If an error occurred in expansion, then OUTPUT contains a descriptive
|
||||
error message. */
|
||||
extern int history_expand (char *, char **);
|
||||
extern int history_expand (const char *, char **);
|
||||
|
||||
/* Extract a string segment consisting of the FIRST through LAST
|
||||
arguments present in STRING. Arguments are broken up as in
|
||||
|
||||
+83
-32
@@ -1,6 +1,6 @@
|
||||
/* histsearch.c -- searching the history list. */
|
||||
|
||||
/* Copyright (C) 1989, 1992-2009,2017,2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989, 1992-2009,2017,2021,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (History), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
@@ -47,6 +47,8 @@
|
||||
#include "histlib.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#include "rlmbutil.h"
|
||||
|
||||
/* The list of alternate characters that can delimit a history search
|
||||
string. */
|
||||
char *history_search_delimiter_chars = (char *)NULL;
|
||||
@@ -57,7 +59,10 @@ static int history_search_internal (const char *, int, int);
|
||||
If DIRECTION < 0, then the search is through previous entries, else
|
||||
through subsequent. If ANCHORED is non-zero, the string must
|
||||
appear at the beginning of a history line, otherwise, the string
|
||||
may appear anywhere in the line. If the string is found, then
|
||||
may appear anywhere in the line. If PATSEARCH is non-zero, and fnmatch(3)
|
||||
is available, fnmatch is used to match the string instead of a simple
|
||||
string comparison. If IGNORECASE is set, the string comparison is
|
||||
performed case-insensitively. If the string is found, then
|
||||
current_history () is the history entry, and the value of this
|
||||
function is the offset in the line of that history entry that the
|
||||
string was found in. Otherwise, nothing is changed, and a -1 is
|
||||
@@ -66,10 +71,12 @@ static int history_search_internal (const char *, int, int);
|
||||
static int
|
||||
history_search_internal (const char *string, int direction, int flags)
|
||||
{
|
||||
register int i, reverse;
|
||||
register char *line;
|
||||
register int line_index;
|
||||
int string_len, anchored, patsearch;
|
||||
int i, reverse;
|
||||
char *line;
|
||||
size_t string_len, line_len;
|
||||
int line_index; /* can't be unsigned */
|
||||
int anchored, patsearch, igncase;
|
||||
int found, mb_cur_max;
|
||||
HIST_ENTRY **the_history; /* local */
|
||||
|
||||
i = history_offset;
|
||||
@@ -80,6 +87,7 @@ history_search_internal (const char *string, int direction, int flags)
|
||||
#else
|
||||
patsearch = 0;
|
||||
#endif
|
||||
igncase = (flags & CASEFOLD_SEARCH);
|
||||
|
||||
/* Take care of trivial cases first. */
|
||||
if (string == 0 || *string == '\0')
|
||||
@@ -91,6 +99,8 @@ history_search_internal (const char *string, int direction, int flags)
|
||||
if (reverse && (i >= history_length))
|
||||
i = history_length - 1;
|
||||
|
||||
mb_cur_max = MB_CUR_MAX;
|
||||
|
||||
#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
|
||||
|
||||
the_history = history_list ();
|
||||
@@ -104,7 +114,7 @@ history_search_internal (const char *string, int direction, int flags)
|
||||
return (-1);
|
||||
|
||||
line = the_history[i]->line;
|
||||
line_index = strlen (line);
|
||||
line_len = line_index = strlen (line);
|
||||
|
||||
/* If STRING is longer than line, no match. */
|
||||
if (patsearch == 0 && (string_len > line_index))
|
||||
@@ -116,18 +126,27 @@ history_search_internal (const char *string, int direction, int flags)
|
||||
/* Handle anchored searches first. */
|
||||
if (anchored == ANCHORED_SEARCH)
|
||||
{
|
||||
found = 0;
|
||||
#if defined (HAVE_FNMATCH)
|
||||
if (patsearch)
|
||||
{
|
||||
if (fnmatch (string, line, 0) == 0)
|
||||
{
|
||||
history_offset = i;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
found = fnmatch (string, line, 0) == 0;
|
||||
else
|
||||
#endif
|
||||
if (STREQN (string, line, string_len))
|
||||
if (igncase)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (mb_cur_max > 1) /* no rl_byte_oriented equivalent */
|
||||
found = _rl_mb_strcaseeqn (string, string_len,
|
||||
line, line_len,
|
||||
string_len, 0);
|
||||
else
|
||||
#endif
|
||||
found = strncasecmp (string, line, string_len) == 0;
|
||||
}
|
||||
else
|
||||
found = STREQN (string, line, string_len);
|
||||
|
||||
if (found)
|
||||
{
|
||||
history_offset = i;
|
||||
return (0);
|
||||
@@ -140,55 +159,80 @@ history_search_internal (const char *string, int direction, int flags)
|
||||
/* Do substring search. */
|
||||
if (reverse)
|
||||
{
|
||||
line_index -= (patsearch == 0) ? string_len : 1;
|
||||
size_t ll;
|
||||
|
||||
ll = (patsearch == 0) ? string_len : 1;
|
||||
line_index -= ll;
|
||||
found = 0;
|
||||
|
||||
while (line_index >= 0)
|
||||
{
|
||||
#if defined (HAVE_FNMATCH)
|
||||
if (patsearch)
|
||||
{
|
||||
if (fnmatch (string, line + line_index, 0) == 0)
|
||||
{
|
||||
history_offset = i;
|
||||
return (line_index);
|
||||
}
|
||||
}
|
||||
found = fnmatch (string, line + line_index, 0) == 0;
|
||||
else
|
||||
#endif
|
||||
if (STREQN (string, line + line_index, string_len))
|
||||
if (igncase)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (mb_cur_max > 1) /* no rl_byte_oriented equivalent */
|
||||
found = _rl_mb_strcaseeqn (string, string_len,
|
||||
line + line_index, ll,
|
||||
string_len, 0);
|
||||
else
|
||||
#endif
|
||||
found = strncasecmp (string, line + line_index, string_len) == 0;
|
||||
}
|
||||
else
|
||||
found = STREQN (string, line + line_index, string_len);
|
||||
|
||||
if (found)
|
||||
{
|
||||
history_offset = i;
|
||||
return (line_index);
|
||||
}
|
||||
line_index--;
|
||||
ll++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
register int limit;
|
||||
size_t ll;
|
||||
|
||||
ll = line_len;
|
||||
limit = line_index - string_len + 1;
|
||||
line_index = 0;
|
||||
found = 0;
|
||||
|
||||
while (line_index < limit)
|
||||
{
|
||||
#if defined (HAVE_FNMATCH)
|
||||
if (patsearch)
|
||||
{
|
||||
if (fnmatch (string, line + line_index, 0) == 0)
|
||||
{
|
||||
history_offset = i;
|
||||
return (line_index);
|
||||
}
|
||||
}
|
||||
found = fnmatch (string, line + line_index, 0) == 0;
|
||||
else
|
||||
#endif
|
||||
if (STREQN (string, line + line_index, string_len))
|
||||
if (igncase)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (mb_cur_max > 1) /* no rl_byte_oriented equivalent */
|
||||
found = _rl_mb_strcaseeqn (string, string_len,
|
||||
line + line_index, ll,
|
||||
string_len, 0);
|
||||
else
|
||||
#endif
|
||||
found = strncasecmp (string, line + line_index, string_len) == 0;
|
||||
}
|
||||
else
|
||||
found = STREQN (string, line + line_index, string_len);
|
||||
|
||||
if (found)
|
||||
{
|
||||
history_offset = i;
|
||||
return (line_index);
|
||||
}
|
||||
line_index++;
|
||||
ll--;
|
||||
}
|
||||
}
|
||||
NEXT_LINE ();
|
||||
@@ -266,6 +310,13 @@ history_search_prefix (const char *string, int direction)
|
||||
return (history_search_internal (string, direction, ANCHORED_SEARCH));
|
||||
}
|
||||
|
||||
/* At some point, make this public for users of the history library. */
|
||||
int
|
||||
_hs_history_search (const char *string, int direction, int flags)
|
||||
{
|
||||
return (history_search_internal (string, direction, flags));
|
||||
}
|
||||
|
||||
/* Search for STRING in the history list. DIR is < 0 for searching
|
||||
backwards. POS is an absolute index into the history list at
|
||||
which point to begin searching. */
|
||||
|
||||
+71
-31
@@ -1,6 +1,6 @@
|
||||
/* input.c -- character input functions for readline. */
|
||||
|
||||
/* Copyright (C) 1994-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1994-2022 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -138,20 +138,16 @@ win32_isatty (int fd)
|
||||
|
||||
/* Readline timeouts */
|
||||
|
||||
/* I don't know how to set a timeout for _getch() in MinGW32, so we use
|
||||
SIGALRM. */
|
||||
#if (defined (HAVE_PSELECT) || defined (HAVE_SELECT)) && !defined (__MINGW32__)
|
||||
# define RL_TIMEOUT_USE_SELECT
|
||||
#else
|
||||
# define RL_TIMEOUT_USE_SIGALRM
|
||||
#endif
|
||||
/* We now define RL_TIMEOUT_USE_SELECT or RL_TIMEOUT_USE_SIGALRM in rlprivate.h */
|
||||
|
||||
int rl_set_timeout (unsigned int, unsigned int);
|
||||
int rl_timeout_remaining (unsigned int *, unsigned int *);
|
||||
|
||||
int _rl_timeout_init (void);
|
||||
int _rl_timeout_sigalrm_handler (void);
|
||||
int _rl_timeout_handle_sigalrm (void);
|
||||
#if defined (RL_TIMEOUT_USE_SELECT)
|
||||
int _rl_timeout_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *, const sigset_t *);
|
||||
#endif
|
||||
|
||||
static void _rl_timeout_handle (void);
|
||||
#if defined (RL_TIMEOUT_USE_SIGALRM)
|
||||
@@ -248,38 +244,53 @@ rl_gather_tyi (void)
|
||||
register int tem, result;
|
||||
int chars_avail, k;
|
||||
char input;
|
||||
#if defined(HAVE_SELECT)
|
||||
#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
|
||||
fd_set readfds, exceptfds;
|
||||
struct timeval timeout;
|
||||
#endif
|
||||
|
||||
result = -1;
|
||||
chars_avail = 0;
|
||||
input = 0;
|
||||
tty = fileno (rl_instream);
|
||||
|
||||
/* Move this up here to give it first shot, but it can't set chars_avail */
|
||||
/* XXX - need rl_chars_available_hook? */
|
||||
if (rl_input_available_hook)
|
||||
{
|
||||
result = (*rl_input_available_hook) ();
|
||||
if (result == 0)
|
||||
result = -1;
|
||||
}
|
||||
|
||||
#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
|
||||
FD_ZERO (&readfds);
|
||||
FD_ZERO (&exceptfds);
|
||||
FD_SET (tty, &readfds);
|
||||
FD_SET (tty, &exceptfds);
|
||||
USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout);
|
||||
if (result == -1)
|
||||
{
|
||||
FD_ZERO (&readfds);
|
||||
FD_ZERO (&exceptfds);
|
||||
FD_SET (tty, &readfds);
|
||||
FD_SET (tty, &exceptfds);
|
||||
USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout);
|
||||
#if defined (RL_TIMEOUT_USE_SELECT)
|
||||
result = _rl_timeout_select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout, NULL);
|
||||
result = _rl_timeout_select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout, NULL);
|
||||
#else
|
||||
result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
|
||||
result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
|
||||
#endif
|
||||
if (result <= 0)
|
||||
return 0; /* Nothing to read. */
|
||||
if (result <= 0)
|
||||
return 0; /* Nothing to read. */
|
||||
}
|
||||
#endif
|
||||
|
||||
result = -1;
|
||||
errno = 0;
|
||||
#if defined (FIONREAD)
|
||||
result = ioctl (tty, FIONREAD, &chars_avail);
|
||||
if (result == -1 && errno == EIO)
|
||||
return -1;
|
||||
if (result == -1)
|
||||
chars_avail = 0;
|
||||
{
|
||||
errno = 0;
|
||||
result = ioctl (tty, FIONREAD, &chars_avail);
|
||||
if (result == -1 && errno == EIO)
|
||||
return -1;
|
||||
if (result == -1)
|
||||
chars_avail = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (O_NDELAY)
|
||||
@@ -306,8 +317,11 @@ rl_gather_tyi (void)
|
||||
#if defined (__MINGW32__)
|
||||
/* Use getch/_kbhit to check for available console input, in the same way
|
||||
that we read it normally. */
|
||||
chars_avail = isatty (tty) ? _kbhit () : 0;
|
||||
result = 0;
|
||||
if (result == -1)
|
||||
{
|
||||
chars_avail = isatty (tty) ? _kbhit () : 0;
|
||||
result = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If there's nothing available, don't waste time trying to read
|
||||
@@ -649,7 +663,7 @@ rl_timeout_remaining (unsigned int *secs, unsigned int *usecs)
|
||||
|
||||
/* This should only be called if RL_TIMEOUT_USE_SELECT is defined. */
|
||||
|
||||
#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
|
||||
#if defined (RL_TIMEOUT_USE_SELECT)
|
||||
int
|
||||
_rl_timeout_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout, const sigset_t *sigmask)
|
||||
{
|
||||
@@ -802,10 +816,10 @@ rl_read_key (void)
|
||||
int
|
||||
rl_getc (FILE *stream)
|
||||
{
|
||||
int result;
|
||||
int result, ostate, osig;
|
||||
unsigned char c;
|
||||
int fd;
|
||||
#if defined (HAVE_PSELECT)
|
||||
#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
|
||||
sigset_t empty_set;
|
||||
fd_set readfds;
|
||||
#endif
|
||||
@@ -813,12 +827,26 @@ rl_getc (FILE *stream)
|
||||
fd = fileno (stream);
|
||||
while (1)
|
||||
{
|
||||
osig = _rl_caught_signal;
|
||||
ostate = rl_readline_state;
|
||||
|
||||
RL_CHECK_SIGNALS ();
|
||||
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
/* Do signal handling post-processing here, but just in callback mode
|
||||
for right now because the signal cleanup can change some of the
|
||||
callback state, and we need to either let the application have a
|
||||
chance to react or abort some current operation that gets cleaned
|
||||
up by rl_callback_sigcleanup(). If not, we'll just run through the
|
||||
loop again. */
|
||||
if (osig != 0 && (ostate & RL_STATE_CALLBACK))
|
||||
goto postproc_signal;
|
||||
#endif
|
||||
|
||||
/* We know at this point that _rl_caught_signal == 0 */
|
||||
|
||||
#if defined (__MINGW32__)
|
||||
if (isatty (fd)
|
||||
if (isatty (fd))
|
||||
return (_getch ()); /* "There is no error return." */
|
||||
#endif
|
||||
result = 0;
|
||||
@@ -878,6 +906,9 @@ rl_getc (FILE *stream)
|
||||
/* fprintf(stderr, "rl_getc: result = %d errno = %d\n", result, errno); */
|
||||
|
||||
handle_error:
|
||||
osig = _rl_caught_signal;
|
||||
ostate = rl_readline_state;
|
||||
|
||||
/* If the error that we received was EINTR, then try again,
|
||||
this is simply an interrupted system call to read (). We allow
|
||||
the read to be interrupted if we caught SIGHUP, SIGTERM, or any
|
||||
@@ -918,8 +949,17 @@ handle_error:
|
||||
RL_CHECK_SIGNALS ();
|
||||
#endif /* SIGALRM */
|
||||
|
||||
postproc_signal:
|
||||
/* POSIX says read(2)/pselect(2)/select(2) don't return EINTR for any
|
||||
reason other than being interrupted by a signal, so we can safely
|
||||
call the application's signal event hook. */
|
||||
if (rl_signal_event_hook)
|
||||
(*rl_signal_event_hook) ();
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
else if (osig == SIGINT && (ostate & RL_STATE_CALLBACK) && (ostate & (RL_STATE_ISEARCH|RL_STATE_NSEARCH|RL_STATE_NUMERICARG)))
|
||||
/* just these cases for now */
|
||||
_rl_abort_internal ();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+80
-12
@@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2021,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -59,6 +59,8 @@ char *_rl_isearch_terminators = (char *)NULL;
|
||||
|
||||
_rl_search_cxt *_rl_iscxt = 0;
|
||||
|
||||
int _rl_search_case_fold = 0;
|
||||
|
||||
static int rl_search_history (int, int);
|
||||
|
||||
static _rl_search_cxt *_rl_isearch_init (int);
|
||||
@@ -150,7 +152,7 @@ static void
|
||||
rl_display_search (char *search_string, int flags, int where)
|
||||
{
|
||||
char *message;
|
||||
int msglen, searchlen;
|
||||
size_t msglen, searchlen;
|
||||
|
||||
searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
|
||||
|
||||
@@ -340,7 +342,7 @@ _rl_search_getchar (_rl_search_cxt *cxt)
|
||||
int
|
||||
_rl_isearch_dispatch (_rl_search_cxt *cxt, int c)
|
||||
{
|
||||
int n, wstart, wlen, limit, cval, incr;
|
||||
int n, wstart, wlen, limit, cval;
|
||||
char *paste;
|
||||
size_t pastelen;
|
||||
int j;
|
||||
@@ -428,7 +430,11 @@ add_character:
|
||||
{
|
||||
f = cxt->keymap[c].function;
|
||||
if (f == rl_do_lowercase_version)
|
||||
f = cxt->keymap[_rl_to_lower (c)].function;
|
||||
{
|
||||
f = cxt->keymap[_rl_to_lower (c)].function;
|
||||
if (f == rl_do_lowercase_version)
|
||||
f = rl_insert;
|
||||
}
|
||||
}
|
||||
|
||||
if (f == rl_reverse_search_history)
|
||||
@@ -445,6 +451,8 @@ add_character:
|
||||
cxt->lastc = -6;
|
||||
else if (f == rl_bracketed_paste_begin)
|
||||
cxt->lastc = -7;
|
||||
else if (c == CTRL('V') || f == rl_quoted_insert)
|
||||
cxt->lastc = -8;
|
||||
}
|
||||
|
||||
/* If we changed the keymap earlier while translating a key sequence into
|
||||
@@ -463,6 +471,11 @@ add_character:
|
||||
{
|
||||
rl_stuff_char (cxt->lastc);
|
||||
rl_execute_next (cxt->prevc);
|
||||
|
||||
/* We're going to read the last two characters again. */
|
||||
_rl_del_executing_keyseq ();
|
||||
_rl_del_executing_keyseq ();
|
||||
|
||||
/* XXX - do we insert everything in cxt->pmb? */
|
||||
return (0);
|
||||
}
|
||||
@@ -477,6 +490,8 @@ add_character:
|
||||
/* Make lastc be the next character read */
|
||||
/* XXX - do we insert everything in cxt->mb? */
|
||||
rl_execute_next (cxt->lastc);
|
||||
_rl_del_executing_keyseq ();
|
||||
|
||||
/* Dispatch on the previous character (insert into search string) */
|
||||
cxt->lastc = cxt->prevc;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
@@ -524,7 +539,10 @@ add_character:
|
||||
settable keyboard timeout value, this could alternatively
|
||||
use _rl_input_queued(100000) */
|
||||
if (cxt->lastc == ESC && (_rl_pushed_input_available () || _rl_input_available ()))
|
||||
rl_execute_next (ESC);
|
||||
{
|
||||
rl_execute_next (ESC);
|
||||
_rl_del_executing_keyseq ();
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -536,6 +554,7 @@ add_character:
|
||||
/* This sets rl_pending_input to LASTC; it will be picked up the next
|
||||
time rl_read_key is called. */
|
||||
rl_execute_next (cxt->lastc);
|
||||
_rl_del_executing_keyseq ();
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
@@ -546,6 +565,7 @@ add_character:
|
||||
/* This sets rl_pending_input to LASTC; it will be picked up the next
|
||||
time rl_read_key is called. */
|
||||
rl_execute_next (cxt->lastc);
|
||||
_rl_del_executing_keyseq ();
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -698,6 +718,27 @@ opcode_dispatch:
|
||||
xfree (paste);
|
||||
break;
|
||||
|
||||
case -8: /* quoted insert */
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
|
||||
_rl_disable_tty_signals ();
|
||||
#endif
|
||||
c = _rl_search_getchar (cxt);
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
|
||||
_rl_restore_tty_signals ();
|
||||
#endif
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
cxt->sflags |= SF_FAILED;
|
||||
cxt->history_pos = cxt->last_found_line;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_rl_add_executing_keyseq (c);
|
||||
|
||||
/*FALLTHROUGH*/
|
||||
/* Add character to search string and continue search. */
|
||||
default:
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
@@ -713,13 +754,13 @@ opcode_dispatch:
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
int j;
|
||||
int w;
|
||||
|
||||
if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
|
||||
else
|
||||
for (j = 0; j < wlen; )
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
|
||||
for (w = 0; w < wlen; )
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->mb[w++];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -741,7 +782,27 @@ opcode_dispatch:
|
||||
/* Search the current line. */
|
||||
while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
|
||||
{
|
||||
if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
|
||||
int found;
|
||||
|
||||
if (_rl_search_case_fold)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
found = _rl_mb_strcaseeqn (cxt->search_string,
|
||||
cxt->search_string_index,
|
||||
cxt->sline + cxt->sline_index,
|
||||
limit,
|
||||
cxt->search_string_index, 0);
|
||||
else
|
||||
found = _rl_strnicmp (cxt->search_string,
|
||||
cxt->sline + cxt->sline_index,
|
||||
cxt->search_string_index) == 0;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
found = STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index);
|
||||
|
||||
if (found)
|
||||
{
|
||||
cxt->sflags |= SF_FOUND;
|
||||
break;
|
||||
@@ -749,7 +810,7 @@ opcode_dispatch:
|
||||
else
|
||||
cxt->sline_index += cxt->direction;
|
||||
|
||||
if (cxt->sline_index < 0)
|
||||
if (cxt->sline_index < 0 || cxt->sline_index > cxt->sline_len)
|
||||
{
|
||||
cxt->sline_index = 0;
|
||||
break;
|
||||
@@ -782,8 +843,8 @@ opcode_dispatch:
|
||||
|
||||
if (cxt->sflags & SF_FAILED)
|
||||
{
|
||||
/* XXX - reset sline_index if < 0 */
|
||||
if (cxt->sline_index < 0)
|
||||
/* XXX - reset sline_index if < 0 or longer than the history line */
|
||||
if (cxt->sline_index < 0 || cxt->sline_index > cxt->sline_len)
|
||||
cxt->sline_index = 0;
|
||||
break;
|
||||
}
|
||||
@@ -885,6 +946,13 @@ _rl_isearch_callback (_rl_search_cxt *cxt)
|
||||
int c, r;
|
||||
|
||||
c = _rl_search_getchar (cxt);
|
||||
|
||||
if (c < 0) /* EOF */
|
||||
return 1;
|
||||
|
||||
if (RL_ISSTATE (RL_STATE_ISEARCH) == 0) /* signal could turn it off */
|
||||
return 1;
|
||||
|
||||
/* We might want to handle EOF here */
|
||||
r = _rl_isearch_dispatch (cxt, cxt->lastc);
|
||||
|
||||
|
||||
+17
-15
@@ -1,6 +1,6 @@
|
||||
/* kill.c -- kill ring management. */
|
||||
|
||||
/* Copyright (C) 1994-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1994-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -348,15 +348,15 @@ rl_unix_filename_rubout (int count, int key)
|
||||
if (count <= 0)
|
||||
count = 1;
|
||||
|
||||
while (count--)
|
||||
while (rl_point > 0 && count--)
|
||||
{
|
||||
c = rl_line_buffer[rl_point - 1];
|
||||
|
||||
/* First move backwards through whitespace */
|
||||
while (rl_point && whitespace (c))
|
||||
{
|
||||
rl_point--;
|
||||
c = rl_line_buffer[rl_point - 1];
|
||||
if (--rl_point)
|
||||
c = rl_line_buffer[rl_point - 1];
|
||||
}
|
||||
|
||||
/* Consume one or more slashes. */
|
||||
@@ -377,14 +377,14 @@ rl_unix_filename_rubout (int count, int key)
|
||||
|
||||
while (rl_point && (whitespace (c) || c == '/'))
|
||||
{
|
||||
rl_point--;
|
||||
c = rl_line_buffer[rl_point - 1];
|
||||
if (--rl_point)
|
||||
c = rl_line_buffer[rl_point - 1];
|
||||
}
|
||||
|
||||
while (rl_point && (whitespace (c) == 0) && c != '/')
|
||||
{
|
||||
rl_point--; /* XXX - multibyte? */
|
||||
c = rl_line_buffer[rl_point - 1];
|
||||
if (--rl_point) /* XXX - multibyte? */
|
||||
c = rl_line_buffer[rl_point - 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,7 +569,7 @@ rl_vi_yank_pop (int count, int key)
|
||||
}
|
||||
|
||||
l = strlen (rl_kill_ring[rl_kill_index]);
|
||||
#if 0 /* TAG:readline-8.3 8/29/2022 matteopaolini1995@gmail.com */
|
||||
#if 1
|
||||
origpoint = rl_point;
|
||||
n = rl_point - l + 1;
|
||||
#else
|
||||
@@ -577,7 +577,7 @@ rl_vi_yank_pop (int count, int key)
|
||||
#endif
|
||||
if (n >= 0 && STREQN (rl_line_buffer + n, rl_kill_ring[rl_kill_index], l))
|
||||
{
|
||||
#if 0 /* TAG:readline-8.3 */
|
||||
#if 1
|
||||
rl_delete_text (n, n + l); /* remember vi cursor positioning */
|
||||
rl_point = origpoint - l;
|
||||
#else
|
||||
@@ -756,8 +756,8 @@ _rl_bracketed_text (size_t *lenp)
|
||||
int
|
||||
rl_bracketed_paste_begin (int count, int key)
|
||||
{
|
||||
int retval, c;
|
||||
size_t len, cap;
|
||||
int retval;
|
||||
size_t len;
|
||||
char *buf;
|
||||
|
||||
buf = _rl_bracketed_text (&len);
|
||||
@@ -774,12 +774,12 @@ int
|
||||
_rl_read_bracketed_paste_prefix (int c)
|
||||
{
|
||||
char pbuf[BRACK_PASTE_SLEN+1], *pbpref;
|
||||
int key, ind, j;
|
||||
int key, ind;
|
||||
|
||||
pbpref = BRACK_PASTE_PREF; /* XXX - debugging */
|
||||
if (c != pbpref[0])
|
||||
return (0);
|
||||
pbuf[ind = 0] = c;
|
||||
pbuf[ind = 0] = key = c;
|
||||
while (ind < BRACK_PASTE_SLEN-1 &&
|
||||
(RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) &&
|
||||
_rl_pushed_input_available () == 0 &&
|
||||
@@ -846,7 +846,7 @@ _rl_bracketed_read_key ()
|
||||
int
|
||||
_rl_bracketed_read_mbstring (char *mb, int mlen)
|
||||
{
|
||||
int c, r;
|
||||
int c;
|
||||
|
||||
c = _rl_bracketed_read_key ();
|
||||
if (c < 0)
|
||||
@@ -865,6 +865,8 @@ _rl_bracketed_read_mbstring (char *mb, int mlen)
|
||||
|
||||
/* A special paste command for Windows users. */
|
||||
#if defined (_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
int
|
||||
|
||||
@@ -69,7 +69,7 @@ static int executing_macro_index;
|
||||
static char *current_macro = (char *)NULL;
|
||||
|
||||
/* The size of the buffer allocated to current_macro. */
|
||||
static int current_macro_size;
|
||||
static size_t current_macro_size;
|
||||
|
||||
/* The index at which characters are being added to current_macro. */
|
||||
static int current_macro_index;
|
||||
|
||||
+101
-20
@@ -1,6 +1,6 @@
|
||||
/* mbutil.c -- readline multibyte character utility functions */
|
||||
|
||||
/* Copyright (C) 2001-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001-2021,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -148,7 +148,7 @@ _rl_utf8_mblen (const char *s, size_t n)
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_find_next_mbchar_internal (char *string, int seed, int count, int find_non_zero)
|
||||
_rl_find_next_mbchar_internal (const char *string, int seed, int count, int find_non_zero)
|
||||
{
|
||||
size_t tmp, len;
|
||||
mbstate_t ps;
|
||||
@@ -216,11 +216,13 @@ _rl_find_next_mbchar_internal (char *string, int seed, int count, int find_non_z
|
||||
|
||||
if (find_non_zero)
|
||||
{
|
||||
tmp = MBRTOWC (&wc, string + point, strlen (string + point), &ps);
|
||||
len = strlen (string + point);
|
||||
tmp = MBRTOWC (&wc, string + point, len, &ps);
|
||||
while (MB_NULLWCH (tmp) == 0 && MB_INVALIDCH (tmp) == 0 && WCWIDTH (wc) == 0)
|
||||
{
|
||||
point += tmp;
|
||||
tmp = MBRTOWC (&wc, string + point, strlen (string + point), &ps);
|
||||
len -= tmp;
|
||||
tmp = MBRTOWC (&wc, string + point, len, &ps);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +230,7 @@ _rl_find_next_mbchar_internal (char *string, int seed, int count, int find_non_z
|
||||
}
|
||||
|
||||
static inline int
|
||||
_rl_test_nonzero (char *string, int ind, int len)
|
||||
_rl_test_nonzero (const char *string, int ind, int len)
|
||||
{
|
||||
size_t tmp;
|
||||
WCHAR_T wc;
|
||||
@@ -242,9 +244,8 @@ _rl_test_nonzero (char *string, int ind, int len)
|
||||
|
||||
/* experimental -- needs to handle zero-width characters better */
|
||||
static int
|
||||
_rl_find_prev_utf8char (char *string, int seed, int find_non_zero)
|
||||
_rl_find_prev_utf8char (const char *string, int seed, int find_non_zero)
|
||||
{
|
||||
char *s;
|
||||
unsigned char b;
|
||||
int save, prev;
|
||||
size_t len;
|
||||
@@ -262,11 +263,16 @@ _rl_find_prev_utf8char (char *string, int seed, int find_non_zero)
|
||||
save = prev;
|
||||
|
||||
/* Move back until we're not in the middle of a multibyte char */
|
||||
#if 0
|
||||
if (UTF8_MBCHAR (b))
|
||||
{
|
||||
while (prev > 0 && (b = (unsigned char)string[--prev]) && UTF8_MBCHAR (b))
|
||||
;
|
||||
}
|
||||
#else
|
||||
while (prev > 0 && (b = (unsigned char)string[--prev]) && UTF8_MBFIRSTCHAR (b) == 0)
|
||||
;
|
||||
#endif
|
||||
|
||||
if (UTF8_MBFIRSTCHAR (b))
|
||||
{
|
||||
@@ -288,7 +294,7 @@ _rl_find_prev_utf8char (char *string, int seed, int find_non_zero)
|
||||
}
|
||||
|
||||
/*static*/ int
|
||||
_rl_find_prev_mbchar_internal (char *string, int seed, int find_non_zero)
|
||||
_rl_find_prev_mbchar_internal (const char *string, int seed, int find_non_zero)
|
||||
{
|
||||
mbstate_t ps;
|
||||
int prev, non_zero_prev, point, length;
|
||||
@@ -356,19 +362,19 @@ _rl_find_prev_mbchar_internal (char *string, int seed, int find_non_zero)
|
||||
if an invalid multibyte sequence was encountered. It returns (size_t)(-2)
|
||||
if it couldn't parse a complete multibyte character. */
|
||||
int
|
||||
_rl_get_char_len (char *src, mbstate_t *ps)
|
||||
_rl_get_char_len (const char *src, mbstate_t *ps)
|
||||
{
|
||||
size_t tmp, l;
|
||||
int mb_cur_max;
|
||||
|
||||
/* Look at no more than MB_CUR_MAX characters */
|
||||
l = (size_t)strlen (src);
|
||||
if (_rl_utf8locale && l > 0 && UTF8_SINGLEBYTE(*src))
|
||||
l = strlen (src);
|
||||
if (_rl_utf8locale && l >= 0 && UTF8_SINGLEBYTE(*src))
|
||||
tmp = (*src != 0) ? 1 : 0;
|
||||
else
|
||||
{
|
||||
mb_cur_max = MB_CUR_MAX;
|
||||
tmp = mbrlen((const char *)src, (l < mb_cur_max) ? l : mb_cur_max, ps);
|
||||
tmp = mbrlen(src, (l < mb_cur_max) ? l : mb_cur_max, ps);
|
||||
}
|
||||
if (tmp == (size_t)(-2))
|
||||
{
|
||||
@@ -394,7 +400,7 @@ _rl_get_char_len (char *src, mbstate_t *ps)
|
||||
/* compare the specified two characters. If the characters matched,
|
||||
return 1. Otherwise return 0. */
|
||||
int
|
||||
_rl_compare_chars (char *buf1, int pos1, mbstate_t *ps1, char *buf2, int pos2, mbstate_t *ps2)
|
||||
_rl_compare_chars (const char *buf1, int pos1, mbstate_t *ps1, const char *buf2, int pos2, mbstate_t *ps2)
|
||||
{
|
||||
int i, w1, w2;
|
||||
|
||||
@@ -417,7 +423,7 @@ _rl_compare_chars (char *buf1, int pos1, mbstate_t *ps1, char *buf2, int pos2, m
|
||||
if point is invalid (point < 0 || more than string length),
|
||||
it returns -1 */
|
||||
int
|
||||
_rl_adjust_point (char *string, int point, mbstate_t *ps)
|
||||
_rl_adjust_point (const char *string, int point, mbstate_t *ps)
|
||||
{
|
||||
size_t tmp;
|
||||
int length, pos;
|
||||
@@ -457,7 +463,7 @@ _rl_adjust_point (char *string, int point, mbstate_t *ps)
|
||||
}
|
||||
|
||||
int
|
||||
_rl_is_mbchar_matched (char *string, int seed, int end, char *mbchar, int length)
|
||||
_rl_is_mbchar_matched (const char *string, int seed, int end, char *mbchar, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -471,19 +477,19 @@ _rl_is_mbchar_matched (char *string, int seed, int end, char *mbchar, int length
|
||||
}
|
||||
|
||||
WCHAR_T
|
||||
_rl_char_value (char *buf, int ind)
|
||||
_rl_char_value (const char *buf, int ind)
|
||||
{
|
||||
size_t tmp;
|
||||
WCHAR_T wc;
|
||||
mbstate_t ps;
|
||||
int l;
|
||||
size_t l;
|
||||
|
||||
if (MB_LEN_MAX == 1 || rl_byte_oriented)
|
||||
return ((WCHAR_T) buf[ind]);
|
||||
if (_rl_utf8locale && UTF8_SINGLEBYTE(buf[ind]))
|
||||
return ((WCHAR_T) buf[ind]);
|
||||
l = strlen (buf);
|
||||
if (ind >= l - 1)
|
||||
if (ind + 1 >= l)
|
||||
return ((WCHAR_T) buf[ind]);
|
||||
if (l < ind) /* Sanity check */
|
||||
l = strlen (buf+ind);
|
||||
@@ -500,7 +506,7 @@ _rl_char_value (char *buf, int ind)
|
||||
characters. */
|
||||
#undef _rl_find_next_mbchar
|
||||
int
|
||||
_rl_find_next_mbchar (char *string, int seed, int count, int flags)
|
||||
_rl_find_next_mbchar (const char *string, int seed, int count, int flags)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
return _rl_find_next_mbchar_internal (string, seed, count, flags);
|
||||
@@ -514,7 +520,7 @@ _rl_find_next_mbchar (char *string, int seed, int count, int flags)
|
||||
we look for non-zero-width multibyte characters. */
|
||||
#undef _rl_find_prev_mbchar
|
||||
int
|
||||
_rl_find_prev_mbchar (char *string, int seed, int flags)
|
||||
_rl_find_prev_mbchar (const char *string, int seed, int flags)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
return _rl_find_prev_mbchar_internal (string, seed, flags);
|
||||
@@ -522,3 +528,78 @@ _rl_find_prev_mbchar (char *string, int seed, int flags)
|
||||
return ((seed == 0) ? seed : seed - 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Compare the first N characters of S1 and S2 without regard to case. If
|
||||
FLAGS&1, apply the mapping specified by completion-map-case and make
|
||||
`-' and `_' equivalent. Returns 1 if the strings are equal. */
|
||||
int
|
||||
_rl_mb_strcaseeqn (const char *s1, size_t l1, const char *s2, size_t l2, size_t n, int flags)
|
||||
{
|
||||
size_t v1, v2;
|
||||
mbstate_t ps1, ps2;
|
||||
WCHAR_T wc1, wc2;
|
||||
|
||||
memset (&ps1, 0, sizeof (mbstate_t));
|
||||
memset (&ps2, 0, sizeof (mbstate_t));
|
||||
|
||||
do
|
||||
{
|
||||
v1 = MBRTOWC(&wc1, s1, l1, &ps1);
|
||||
v2 = MBRTOWC(&wc2, s2, l2, &ps2);
|
||||
if (v1 == 0 && v2 == 0)
|
||||
return 1;
|
||||
else if (MB_INVALIDCH(v1) || MB_INVALIDCH(v2))
|
||||
{
|
||||
int d;
|
||||
d = _rl_to_lower (*s1) - _rl_to_lower (*s2); /* do byte comparison */
|
||||
if ((flags & 1) && (*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
|
||||
d = 0; /* case insensitive character mapping */
|
||||
if (d != 0)
|
||||
return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
n--;
|
||||
continue;
|
||||
}
|
||||
wc1 = towlower(wc1);
|
||||
wc2 = towlower(wc2);
|
||||
s1 += v1;
|
||||
s2 += v1;
|
||||
n -= v1;
|
||||
if ((flags & 1) && (wc1 == L'-' || wc1 == L'_') && (wc2 == L'-' || wc2 == L'_'))
|
||||
continue;
|
||||
if (wc1 != wc2)
|
||||
return 0;
|
||||
}
|
||||
while (n != 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return 1 if the multibyte characters pointed to by S1 and S2 are equal
|
||||
without regard to case. If FLAGS&1, apply the mapping specified by
|
||||
completion-map-case and make `-' and `_' equivalent. */
|
||||
int
|
||||
_rl_mb_charcasecmp (const char *s1, mbstate_t *ps1, const char *s2, mbstate_t *ps2, int flags)
|
||||
{
|
||||
int d;
|
||||
size_t v1, v2;
|
||||
wchar_t wc1, wc2;
|
||||
|
||||
d = MB_CUR_MAX;
|
||||
v1 = MBRTOWC(&wc1, s1, d, ps1);
|
||||
v2 = MBRTOWC(&wc2, s2, d, ps2);
|
||||
if (v1 == 0 && v2 == 0)
|
||||
return 1;
|
||||
else if (MB_INVALIDCH(v1) || MB_INVALIDCH(v2))
|
||||
{
|
||||
if ((flags & 1) && (*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
|
||||
return 1;
|
||||
return (_rl_to_lower (*s1) == _rl_to_lower (*s2));
|
||||
}
|
||||
wc1 = towlower(wc1);
|
||||
wc2 = towlower(wc2);
|
||||
if ((flags & 1) && (wc1 == L'-' || wc1 == L'_') && (wc2 == L'-' || wc2 == L'_'))
|
||||
return 1;
|
||||
return (wc1 == wc2);
|
||||
}
|
||||
|
||||
+114
-63
@@ -1,6 +1,6 @@
|
||||
/* misc.c -- miscellaneous bindable readline functions. */
|
||||
|
||||
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -150,6 +150,7 @@ _rl_arg_dispatch (_rl_arg_cxt cxt, int c)
|
||||
|
||||
if (_rl_digit_p (c))
|
||||
{
|
||||
_rl_add_executing_keyseq (key);
|
||||
r = _rl_digit_value (c);
|
||||
rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r;
|
||||
rl_explicit_arg = 1;
|
||||
@@ -157,6 +158,7 @@ _rl_arg_dispatch (_rl_arg_cxt cxt, int c)
|
||||
}
|
||||
else if (c == '-' && rl_explicit_arg == 0)
|
||||
{
|
||||
_rl_add_executing_keyseq (key);
|
||||
rl_numeric_arg = 1;
|
||||
_rl_argcxt |= NUM_SAWMINUS;
|
||||
rl_arg_sign = -1;
|
||||
@@ -235,6 +237,7 @@ rl_digit_argument (int ignore, int key)
|
||||
else
|
||||
{
|
||||
rl_execute_next (key);
|
||||
_rl_del_executing_keyseq ();
|
||||
return (rl_digit_loop ());
|
||||
}
|
||||
}
|
||||
@@ -306,9 +309,11 @@ void
|
||||
_rl_start_using_history (void)
|
||||
{
|
||||
using_history ();
|
||||
if (_rl_saved_line_for_history)
|
||||
_rl_free_saved_history_line ();
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
#if 1
|
||||
if (_rl_saved_line_for_history && _rl_saved_line_for_history->data)
|
||||
_rl_free_undo_list ((UNDO_LIST *)_rl_saved_line_for_history->data);
|
||||
#endif
|
||||
_rl_free_saved_history_line ();
|
||||
_rl_history_search_pos = -99; /* some random invalid history position */
|
||||
}
|
||||
|
||||
@@ -339,64 +344,83 @@ rl_maybe_replace_line (void)
|
||||
xfree (temp->line);
|
||||
FREE (temp->timestamp);
|
||||
xfree (temp);
|
||||
/* What about _rl_saved_line_for_history? if the saved undo list is
|
||||
rl_undo_list, and we just put that into a history entry, should
|
||||
we set the saved undo list to NULL? */
|
||||
if (_rl_saved_line_for_history && (UNDO_LIST *)_rl_saved_line_for_history->data == rl_undo_list)
|
||||
_rl_saved_line_for_history->data = 0;
|
||||
/* Do we want to set rl_undo_list = 0 here since we just saved it into
|
||||
a history entry? */
|
||||
rl_undo_list = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_rl_unsave_line (HIST_ENTRY *entry)
|
||||
{
|
||||
/* Can't call with `1' because rl_undo_list might point to an undo
|
||||
list from a history entry, as in rl_replace_from_history() below. */
|
||||
rl_replace_line (entry->line, 0);
|
||||
rl_undo_list = (UNDO_LIST *)entry->data;
|
||||
|
||||
/* Doesn't free `data'. */
|
||||
_rl_free_history_entry (entry);
|
||||
|
||||
rl_point = rl_end; /* rl_replace_line sets rl_end */
|
||||
}
|
||||
|
||||
/* Restore the _rl_saved_line_for_history if there is one. */
|
||||
int
|
||||
rl_maybe_unsave_line (void)
|
||||
{
|
||||
if (_rl_saved_line_for_history)
|
||||
{
|
||||
/* Can't call with `1' because rl_undo_list might point to an undo
|
||||
list from a history entry, as in rl_replace_from_history() below. */
|
||||
rl_replace_line (_rl_saved_line_for_history->line, 0);
|
||||
rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
|
||||
|
||||
/* Doesn't free `data'. */
|
||||
_rl_free_history_entry (_rl_saved_line_for_history);
|
||||
_rl_unsave_line (_rl_saved_line_for_history);
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
rl_point = rl_end; /* rl_replace_line sets rl_end */
|
||||
}
|
||||
else
|
||||
rl_ding ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HIST_ENTRY *
|
||||
_rl_alloc_saved_line (void)
|
||||
{
|
||||
HIST_ENTRY *ret;
|
||||
|
||||
ret = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
|
||||
|
||||
ret->line = savestring (rl_line_buffer);
|
||||
ret->timestamp = (char *)NULL;
|
||||
ret->data = (char *)rl_undo_list;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Save the current line in _rl_saved_line_for_history. */
|
||||
int
|
||||
rl_maybe_save_line (void)
|
||||
{
|
||||
if (_rl_saved_line_for_history == 0)
|
||||
{
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
|
||||
_rl_saved_line_for_history->line = savestring (rl_line_buffer);
|
||||
_rl_saved_line_for_history->timestamp = (char *)NULL;
|
||||
_rl_saved_line_for_history->data = (char *)rl_undo_list;
|
||||
}
|
||||
_rl_saved_line_for_history = _rl_alloc_saved_line ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just a wrapper, any self-respecting compiler will inline it. */
|
||||
void
|
||||
_rl_free_saved_line (HIST_ENTRY *entry)
|
||||
{
|
||||
_rl_free_history_entry (entry);
|
||||
}
|
||||
|
||||
int
|
||||
_rl_free_saved_history_line (void)
|
||||
{
|
||||
UNDO_LIST *orig;
|
||||
_rl_free_saved_line (_rl_saved_line_for_history);
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
|
||||
if (_rl_saved_line_for_history)
|
||||
{
|
||||
if (rl_undo_list && rl_undo_list == (UNDO_LIST *)_rl_saved_line_for_history->data)
|
||||
rl_undo_list = 0;
|
||||
/* Have to free this separately because _rl_free_history entry can't:
|
||||
it doesn't know whether or not this has application data. Only the
|
||||
callers that know this is _rl_saved_line_for_history can know that
|
||||
it's an undo list. */
|
||||
if (_rl_saved_line_for_history->data)
|
||||
_rl_free_undo_list ((UNDO_LIST *)_rl_saved_line_for_history->data);
|
||||
_rl_free_history_entry (_rl_saved_line_for_history);
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -554,20 +578,11 @@ rl_end_of_history (int count, int key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Move down to the next history line. */
|
||||
int
|
||||
rl_get_next_history (int count, int key)
|
||||
_rl_next_history_internal (int count)
|
||||
{
|
||||
HIST_ENTRY *temp;
|
||||
|
||||
if (count < 0)
|
||||
return (rl_get_previous_history (-count, key));
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
rl_maybe_replace_line ();
|
||||
|
||||
/* either not saved by rl_newline or at end of line, so set appropriately. */
|
||||
if (_rl_history_saved_point == -1 && (rl_point || rl_end))
|
||||
_rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
|
||||
@@ -582,41 +597,48 @@ rl_get_next_history (int count, int key)
|
||||
}
|
||||
|
||||
if (temp == 0)
|
||||
rl_maybe_unsave_line ();
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
rl_replace_from_history (temp, 0);
|
||||
_rl_history_set_point ();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move down to the next history line. */
|
||||
int
|
||||
rl_get_next_history (int count, int key)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (count < 0)
|
||||
return (rl_get_previous_history (-count, key));
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
rl_maybe_replace_line ();
|
||||
|
||||
r = _rl_next_history_internal (count);
|
||||
|
||||
if (r == 0)
|
||||
rl_maybe_unsave_line ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the previous item out of our interactive history, making it the current
|
||||
line. If there is no previous history, just ding. */
|
||||
int
|
||||
rl_get_previous_history (int count, int key)
|
||||
_rl_previous_history_internal (int count)
|
||||
{
|
||||
HIST_ENTRY *old_temp, *temp;
|
||||
int had_saved_line;
|
||||
|
||||
if (count < 0)
|
||||
return (rl_get_next_history (-count, key));
|
||||
|
||||
if (count == 0 || history_list () == 0)
|
||||
return 0;
|
||||
temp = old_temp = (HIST_ENTRY *)NULL;
|
||||
|
||||
/* either not saved by rl_newline or at end of line, so set appropriately. */
|
||||
if (_rl_history_saved_point == -1 && (rl_point || rl_end))
|
||||
_rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
|
||||
|
||||
/* If we don't have a line saved, then save this one. */
|
||||
had_saved_line = _rl_saved_line_for_history != 0;
|
||||
rl_maybe_save_line ();
|
||||
|
||||
/* If the current line has changed, save the changes. */
|
||||
rl_maybe_replace_line ();
|
||||
|
||||
temp = old_temp = (HIST_ENTRY *)NULL;
|
||||
while (count)
|
||||
{
|
||||
temp = previous_history ();
|
||||
@@ -634,15 +656,41 @@ rl_get_previous_history (int count, int key)
|
||||
|
||||
if (temp == 0)
|
||||
{
|
||||
if (had_saved_line == 0)
|
||||
_rl_free_saved_history_line ();
|
||||
rl_ding ();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rl_replace_from_history (temp, 0);
|
||||
_rl_history_set_point ();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the previous item out of our interactive history, making it the current
|
||||
line. If there is no previous history, just ding. */
|
||||
int
|
||||
rl_get_previous_history (int count, int key)
|
||||
{
|
||||
int had_saved_line, r;
|
||||
|
||||
if (count < 0)
|
||||
return (rl_get_next_history (-count, key));
|
||||
|
||||
if (count == 0 || history_list () == 0)
|
||||
return 0;
|
||||
|
||||
/* If we don't have a line saved, then save this one. */
|
||||
had_saved_line = _rl_saved_line_for_history != 0;
|
||||
rl_maybe_save_line ();
|
||||
|
||||
/* If the current line has changed, save the changes. */
|
||||
rl_maybe_replace_line ();
|
||||
|
||||
r = _rl_previous_history_internal (count);
|
||||
|
||||
if (r == 0 && had_saved_line == 0) /* failed to find previous history */
|
||||
_rl_free_saved_history_line ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -693,7 +741,7 @@ static int saved_history_logical_offset = -1;
|
||||
#define HISTORY_FULL() (history_is_stifled () && history_length >= history_max_entries)
|
||||
|
||||
static int
|
||||
set_saved_history ()
|
||||
set_saved_history (void)
|
||||
{
|
||||
int absolute_offset, count;
|
||||
|
||||
@@ -762,7 +810,10 @@ _rl_set_insert_mode (int im, int force)
|
||||
_rl_set_cursor (im, force);
|
||||
#endif
|
||||
|
||||
RL_UNSETSTATE (RL_STATE_OVERWRITE);
|
||||
rl_insert_mode = im;
|
||||
if (rl_insert_mode == RL_IM_OVERWRITE)
|
||||
RL_SETSTATE (RL_STATE_OVERWRITE);
|
||||
}
|
||||
|
||||
/* Toggle overwrite mode. A positive explicit argument selects overwrite
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "rlstdc.h"
|
||||
#include "posixselect.h"
|
||||
|
||||
#if defined (HAVE_STRING_H)
|
||||
@@ -46,10 +47,6 @@
|
||||
# include <strings.h>
|
||||
#endif /* !HAVE_STRING_H */
|
||||
|
||||
#if !defined (strchr) && !defined (__STDC__)
|
||||
extern char *strchr (), *strrchr ();
|
||||
#endif /* !strchr && !__STDC__ */
|
||||
|
||||
#include "readline.h"
|
||||
#include "rlprivate.h"
|
||||
|
||||
|
||||
@@ -297,6 +297,22 @@ get_funky_string (char **dest, const char **src, bool equals_end, size_t *output
|
||||
}
|
||||
#endif /* COLOR_SUPPORT */
|
||||
|
||||
static void
|
||||
free_color_ext_list (void)
|
||||
{
|
||||
COLOR_EXT_TYPE *e;
|
||||
COLOR_EXT_TYPE *e2;
|
||||
|
||||
for (e = _rl_color_ext_list; e != NULL; /* empty */)
|
||||
{
|
||||
e2 = e;
|
||||
e = e->next;
|
||||
free (e2);
|
||||
}
|
||||
|
||||
_rl_color_ext_list = 0;
|
||||
}
|
||||
|
||||
void _rl_parse_colors(void)
|
||||
{
|
||||
#if defined (COLOR_SUPPORT)
|
||||
@@ -420,21 +436,32 @@ void _rl_parse_colors(void)
|
||||
|
||||
if (state < 0)
|
||||
{
|
||||
COLOR_EXT_TYPE *e;
|
||||
COLOR_EXT_TYPE *e2;
|
||||
|
||||
_rl_errmsg ("unparsable value for LS_COLORS environment variable");
|
||||
free (color_buf);
|
||||
for (e = _rl_color_ext_list; e != NULL; /* empty */)
|
||||
{
|
||||
e2 = e;
|
||||
e = e->next;
|
||||
free (e2);
|
||||
}
|
||||
_rl_color_ext_list = NULL;
|
||||
free_color_ext_list ();
|
||||
|
||||
_rl_colored_stats = 0; /* can't have colored stats without colors */
|
||||
_rl_colored_completion_prefix = 0; /* or colored prefixes */
|
||||
}
|
||||
#else /* !COLOR_SUPPORT */
|
||||
;
|
||||
#endif /* !COLOR_SUPPORT */
|
||||
}
|
||||
|
||||
void
|
||||
rl_reparse_colors (void)
|
||||
{
|
||||
char *v;
|
||||
|
||||
v = sh_get_env_value ("LS_COLORS");
|
||||
if (v == 0 && color_buf == 0)
|
||||
return; /* no change */
|
||||
if (v && color_buf && STREQ (v, color_buf))
|
||||
return; /* no change */
|
||||
|
||||
free (color_buf);
|
||||
free_color_ext_list ();
|
||||
|
||||
_rl_parse_colors ();
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
#ifndef _POSIXSELECT_H_
|
||||
#define _POSIXSELECT_H_
|
||||
|
||||
#if defined (FD_SET) && !defined (HAVE_SELECT)
|
||||
#if defined (FD_SET) && !defined (HAVE_SELECT) && !defined (_WIN32)
|
||||
# define HAVE_SELECT 1
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
|
||||
# include <sys/time.h>
|
||||
# include "posixtime.h"
|
||||
# endif
|
||||
#endif /* HAVE_SELECT */
|
||||
#if defined (HAVE_SYS_SELECT_H)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* posixtime.h -- wrapper for time.h, sys/times.h mess. */
|
||||
|
||||
/* Copyright (C) 1999-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999-2022 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -49,9 +49,18 @@ struct timeval
|
||||
#endif
|
||||
|
||||
#if !HAVE_GETTIMEOFDAY
|
||||
extern int gettimeofday PARAMS((struct timeval *, void *));
|
||||
extern int gettimeofday (struct timeval * restrict, void * restrict);
|
||||
#endif
|
||||
|
||||
/* consistently use gettimeofday for time information */
|
||||
static inline time_t
|
||||
getnow(void)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday (&now, 0);
|
||||
return now.tv_sec;
|
||||
}
|
||||
|
||||
/* These exist on BSD systems, at least. */
|
||||
#if !defined (timerclear)
|
||||
# define timerclear(tvp) do { (tvp)->tv_sec = 0; (tvp)->tv_usec = 0; } while (0)
|
||||
|
||||
+42
-18
@@ -1,7 +1,7 @@
|
||||
/* readline.c -- a general facility for reading lines of input
|
||||
with emacs style editing and completion. */
|
||||
|
||||
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -262,7 +262,7 @@ _rl_keyseq_cxt *_rl_kscxt = 0;
|
||||
|
||||
int rl_executing_key;
|
||||
char *rl_executing_keyseq = 0;
|
||||
int _rl_executing_keyseq_size = 0;
|
||||
size_t _rl_executing_keyseq_size = 0;
|
||||
|
||||
struct _rl_cmd _rl_pending_command;
|
||||
struct _rl_cmd *_rl_command_to_execute = (struct _rl_cmd *)NULL;
|
||||
@@ -474,17 +474,12 @@ readline_internal_setup (void)
|
||||
RL_CHECK_SIGNALS ();
|
||||
}
|
||||
|
||||
STATIC_CALLBACK char *
|
||||
readline_internal_teardown (int eof)
|
||||
STATIC_CALLBACK void
|
||||
readline_common_teardown (void)
|
||||
{
|
||||
char *temp;
|
||||
HIST_ENTRY *entry;
|
||||
|
||||
RL_CHECK_SIGNALS ();
|
||||
|
||||
if (eof)
|
||||
RL_SETSTATE (RL_STATE_EOF); /* XXX */
|
||||
|
||||
/* Restore the original of this history line, iff the line that we
|
||||
are editing was originally in the history, AND the line has changed. */
|
||||
entry = current_history ();
|
||||
@@ -510,6 +505,17 @@ readline_internal_teardown (int eof)
|
||||
rid of it now. */
|
||||
if (rl_undo_list)
|
||||
rl_free_undo_list ();
|
||||
}
|
||||
|
||||
STATIC_CALLBACK char *
|
||||
readline_internal_teardown (int eof)
|
||||
{
|
||||
RL_CHECK_SIGNALS ();
|
||||
|
||||
if (eof)
|
||||
RL_SETSTATE (RL_STATE_EOF); /* XXX */
|
||||
|
||||
readline_common_teardown ();
|
||||
|
||||
/* Disable the meta key, if this terminal has one and we were told to use it.
|
||||
The check whether or not we sent the enable string is in
|
||||
@@ -566,6 +572,7 @@ readline_internal_charloop (void)
|
||||
{
|
||||
static int lastc, eof_found;
|
||||
int c, code, lk, r;
|
||||
static procenv_t olevel;
|
||||
|
||||
lastc = EOF;
|
||||
|
||||
@@ -576,6 +583,9 @@ readline_internal_charloop (void)
|
||||
#endif
|
||||
lk = _rl_last_command_was_kill;
|
||||
|
||||
/* Save and restore _rl_top_level even though most of the time it
|
||||
doesn't matter. */
|
||||
memcpy ((void *)olevel, (void *)_rl_top_level, sizeof (procenv_t));
|
||||
#if defined (HAVE_POSIX_SIGSETJMP)
|
||||
code = sigsetjmp (_rl_top_level, 0);
|
||||
#else
|
||||
@@ -586,13 +596,14 @@ readline_internal_charloop (void)
|
||||
{
|
||||
(*rl_redisplay_function) ();
|
||||
_rl_want_redisplay = 0;
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK))
|
||||
memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
|
||||
|
||||
/* If we longjmped because of a timeout, handle it here. */
|
||||
if (RL_ISSTATE (RL_STATE_TIMEOUT))
|
||||
{
|
||||
RL_SETSTATE (RL_STATE_DONE);
|
||||
rl_done = 1;
|
||||
return 1;
|
||||
return (rl_done = 1);
|
||||
}
|
||||
|
||||
/* If we get here, we're not being called from something dispatched
|
||||
@@ -703,6 +714,7 @@ readline_internal_charloop (void)
|
||||
_rl_internal_char_cleanup ();
|
||||
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
|
||||
return 0;
|
||||
#else
|
||||
}
|
||||
@@ -899,8 +911,17 @@ _rl_dispatch_subseq (register int key, Keymap map, int got_subseq)
|
||||
{
|
||||
/* Special case rl_do_lowercase_version (). */
|
||||
if (func == rl_do_lowercase_version)
|
||||
/* Should we do anything special if key == ANYOTHERKEY? */
|
||||
return (_rl_dispatch (_rl_to_lower ((unsigned char)key), map));
|
||||
{
|
||||
/* Should we do anything special if key == ANYOTHERKEY? */
|
||||
newkey = _rl_to_lower ((unsigned char)key);
|
||||
if (newkey != key)
|
||||
return (_rl_dispatch (newkey, map));
|
||||
else
|
||||
{
|
||||
rl_ding (); /* gentle failure */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rl_executing_keymap = map;
|
||||
rl_executing_key = key;
|
||||
@@ -1109,7 +1130,11 @@ _rl_subseq_result (int r, Keymap map, int key, int got_subseq)
|
||||
type = m[ANYOTHERKEY].type;
|
||||
func = m[ANYOTHERKEY].function;
|
||||
if (type == ISFUNC && func == rl_do_lowercase_version)
|
||||
r = _rl_dispatch (_rl_to_lower ((unsigned char)key), map);
|
||||
{
|
||||
int newkey = _rl_to_lower ((unsigned char)key);
|
||||
/* check that there is actually a lowercase version to avoid infinite recursion */
|
||||
r = (newkey != key) ? _rl_dispatch (newkey, map) : 1;
|
||||
}
|
||||
else if (type == ISFUNC)
|
||||
{
|
||||
/* If we shadowed a function, whatever it is, we somehow need a
|
||||
@@ -1322,9 +1347,8 @@ readline_initialize_everything (void)
|
||||
_rl_parse_colors ();
|
||||
#endif
|
||||
|
||||
rl_executing_keyseq = malloc (_rl_executing_keyseq_size = 16);
|
||||
if (rl_executing_keyseq)
|
||||
rl_executing_keyseq[rl_key_sequence_length = 0] = '\0';
|
||||
rl_executing_keyseq = xmalloc (_rl_executing_keyseq_size = 16);
|
||||
rl_executing_keyseq[rl_key_sequence_length = 0] = '\0';
|
||||
}
|
||||
|
||||
/* If this system allows us to look at the values of the regular
|
||||
@@ -1562,7 +1586,7 @@ void
|
||||
_rl_add_executing_keyseq (int key)
|
||||
{
|
||||
RESIZE_KEYSEQ_BUFFER ();
|
||||
rl_executing_keyseq[rl_key_sequence_length++] = key;
|
||||
rl_executing_keyseq[rl_key_sequence_length++] = key;
|
||||
}
|
||||
|
||||
/* `delete' the last character added to the executing key sequence. Use this
|
||||
|
||||
+63
-38
@@ -1,6 +1,6 @@
|
||||
/* Readline.h -- the names of functions callable from within readline. */
|
||||
|
||||
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -39,9 +39,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Hex-encoded Readline version number. */
|
||||
#define RL_READLINE_VERSION 0x0802 /* Readline 8.2 */
|
||||
#define RL_READLINE_VERSION 0x0803 /* Readline 8.3 */
|
||||
#define RL_VERSION_MAJOR 8
|
||||
#define RL_VERSION_MINOR 2
|
||||
#define RL_VERSION_MINOR 3
|
||||
|
||||
/* Readline data structures. */
|
||||
|
||||
@@ -209,6 +209,8 @@ extern int rl_stop_output (int, int);
|
||||
extern int rl_abort (int, int);
|
||||
extern int rl_tty_status (int, int);
|
||||
|
||||
extern int rl_execute_named_command (int, int);
|
||||
|
||||
/* Bindable commands for incremental and non-incremental history searching. */
|
||||
extern int rl_history_search_forward (int, int);
|
||||
extern int rl_history_search_backward (int, int);
|
||||
@@ -341,7 +343,9 @@ extern int rl_trim_arg_from_keyseq (const char *, size_t, Keymap);
|
||||
extern void rl_list_funmap_names (void);
|
||||
extern char **rl_invoking_keyseqs_in_map (rl_command_func_t *, Keymap);
|
||||
extern char **rl_invoking_keyseqs (rl_command_func_t *);
|
||||
|
||||
|
||||
extern void rl_print_keybinding (const char *, Keymap, int);
|
||||
|
||||
extern void rl_function_dumper (int);
|
||||
extern void rl_macro_dumper (int);
|
||||
extern void rl_variable_dumper (int);
|
||||
@@ -404,11 +408,7 @@ extern void rl_activate_mark (void);
|
||||
extern void rl_deactivate_mark (void);
|
||||
extern int rl_mark_active_p (void);
|
||||
|
||||
#if defined (USE_VARARGS) && defined (PREFER_STDARG)
|
||||
extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
|
||||
#else
|
||||
extern int rl_message ();
|
||||
#endif
|
||||
|
||||
extern int rl_show_char (int);
|
||||
|
||||
@@ -441,6 +441,7 @@ extern void rl_get_screen_size (int *, int *);
|
||||
extern void rl_reset_screen_size (void);
|
||||
|
||||
extern char *rl_get_termcap (const char *);
|
||||
extern void rl_reparse_colors (void);
|
||||
|
||||
/* Functions for character input. */
|
||||
extern int rl_stuff_char (int);
|
||||
@@ -627,6 +628,8 @@ extern rl_voidfunc_t *rl_redisplay_function;
|
||||
extern rl_vintfunc_t *rl_prep_term_function;
|
||||
extern rl_voidfunc_t *rl_deprep_term_function;
|
||||
|
||||
extern rl_macro_print_func_t *rl_macro_display_hook;
|
||||
|
||||
/* Dispatch variables. */
|
||||
extern Keymap rl_executing_keymap;
|
||||
extern Keymap rl_binding_keymap;
|
||||
@@ -770,6 +773,19 @@ extern rl_icppfunc_t *rl_filename_stat_hook;
|
||||
converted. */
|
||||
extern rl_dequote_func_t *rl_filename_rewrite_hook;
|
||||
|
||||
/* If non-zero, this is the address of a function to call before
|
||||
comparing the filename portion of a word to be completed with directory
|
||||
entries from the filesystem. This takes the address of the partial word
|
||||
to be completed, after any rl_filename_dequoting_function has been applied.
|
||||
The function should either return its first argument (if no conversion
|
||||
takes place) or newly-allocated memory. This can, for instance, convert
|
||||
the filename portion of the completion word to a character set suitable
|
||||
for comparison against directory entries read from the filesystem (after
|
||||
their potential modification by rl_filename_rewrite_hook).
|
||||
The returned value is what is added to the list of matches.
|
||||
The second argument is the length of the filename to be converted. */
|
||||
extern rl_dequote_func_t *rl_completion_rewrite_hook;
|
||||
|
||||
/* Backwards compatibility with previous versions of readline. */
|
||||
#define rl_symbolic_link_hook rl_directory_completion_hook
|
||||
|
||||
@@ -794,6 +810,12 @@ extern int rl_filename_completion_desired;
|
||||
entry finder function. */
|
||||
extern int rl_filename_quoting_desired;
|
||||
|
||||
/* Non-zero means we should apply filename-type quoting to all completions
|
||||
even if we are not otherwise treating the matches as filenames. This is
|
||||
ALWAYS zero on entry, and can only be changed within a completion entry
|
||||
finder function. */
|
||||
extern int rl_full_quoting_desired;
|
||||
|
||||
/* Set to a function to quote a filename in an application-specific fashion.
|
||||
Called with the text to quote, the type of match found (single or multiple)
|
||||
and a pointer to the quoting character to be used, which the function can
|
||||
@@ -892,37 +914,40 @@ extern int rl_persistent_signal_handlers;
|
||||
#define MULT_MATCH 2
|
||||
|
||||
/* Possible state values for rl_readline_state */
|
||||
#define RL_STATE_NONE 0x000000 /* no state; before first call */
|
||||
#define RL_STATE_NONE 0x0000000 /* no state; before first call */
|
||||
|
||||
#define RL_STATE_INITIALIZING 0x0000001 /* initializing */
|
||||
#define RL_STATE_INITIALIZED 0x0000002 /* initialization done */
|
||||
#define RL_STATE_TERMPREPPED 0x0000004 /* terminal is prepped */
|
||||
#define RL_STATE_READCMD 0x0000008 /* reading a command key */
|
||||
#define RL_STATE_METANEXT 0x0000010 /* reading input after ESC */
|
||||
#define RL_STATE_DISPATCHING 0x0000020 /* dispatching to a command */
|
||||
#define RL_STATE_MOREINPUT 0x0000040 /* reading more input in a command function */
|
||||
#define RL_STATE_ISEARCH 0x0000080 /* doing incremental search */
|
||||
#define RL_STATE_NSEARCH 0x0000100 /* doing non-inc search */
|
||||
#define RL_STATE_SEARCH 0x0000200 /* doing a history search */
|
||||
#define RL_STATE_NUMERICARG 0x0000400 /* reading numeric argument */
|
||||
#define RL_STATE_MACROINPUT 0x0000800 /* getting input from a macro */
|
||||
#define RL_STATE_MACRODEF 0x0001000 /* defining keyboard macro */
|
||||
#define RL_STATE_OVERWRITE 0x0002000 /* overwrite mode */
|
||||
#define RL_STATE_COMPLETING 0x0004000 /* doing completion */
|
||||
#define RL_STATE_SIGHANDLER 0x0008000 /* in readline sighandler */
|
||||
#define RL_STATE_UNDOING 0x0010000 /* doing an undo */
|
||||
#define RL_STATE_INPUTPENDING 0x0020000 /* rl_execute_next called */
|
||||
#define RL_STATE_TTYCSAVED 0x0040000 /* tty special chars saved */
|
||||
#define RL_STATE_CALLBACK 0x0080000 /* using the callback interface */
|
||||
#define RL_STATE_VIMOTION 0x0100000 /* reading vi motion arg */
|
||||
#define RL_STATE_MULTIKEY 0x0200000 /* reading multiple-key command */
|
||||
#define RL_STATE_VICMDONCE 0x0400000 /* entered vi command mode at least once */
|
||||
#define RL_STATE_CHARSEARCH 0x0800000 /* vi mode char search */
|
||||
#define RL_STATE_REDISPLAYING 0x1000000 /* updating terminal display */
|
||||
#define RL_STATE_INITIALIZING 0x00000001 /* initializing */
|
||||
#define RL_STATE_INITIALIZED 0x00000002 /* initialization done */
|
||||
#define RL_STATE_TERMPREPPED 0x00000004 /* terminal is prepped */
|
||||
#define RL_STATE_READCMD 0x00000008 /* reading a command key */
|
||||
#define RL_STATE_METANEXT 0x00000010 /* reading input after ESC */
|
||||
#define RL_STATE_DISPATCHING 0x00000020 /* dispatching to a command */
|
||||
#define RL_STATE_MOREINPUT 0x00000040 /* reading more input in a command function */
|
||||
#define RL_STATE_ISEARCH 0x00000080 /* doing incremental search */
|
||||
#define RL_STATE_NSEARCH 0x00000100 /* doing non-inc search */
|
||||
#define RL_STATE_SEARCH 0x00000200 /* doing a history search */
|
||||
#define RL_STATE_NUMERICARG 0x00000400 /* reading numeric argument */
|
||||
#define RL_STATE_MACROINPUT 0x00000800 /* getting input from a macro */
|
||||
#define RL_STATE_MACRODEF 0x00001000 /* defining keyboard macro */
|
||||
#define RL_STATE_OVERWRITE 0x00002000 /* overwrite mode */
|
||||
#define RL_STATE_COMPLETING 0x00004000 /* doing completion */
|
||||
#define RL_STATE_SIGHANDLER 0x00008000 /* in readline sighandler */
|
||||
#define RL_STATE_UNDOING 0x00010000 /* doing an undo */
|
||||
#define RL_STATE_INPUTPENDING 0x00020000 /* rl_execute_next called */
|
||||
#define RL_STATE_TTYCSAVED 0x00040000 /* tty special chars saved */
|
||||
#define RL_STATE_CALLBACK 0x00080000 /* using the callback interface */
|
||||
#define RL_STATE_VIMOTION 0x00100000 /* reading vi motion arg */
|
||||
#define RL_STATE_MULTIKEY 0x00200000 /* reading multiple-key command */
|
||||
#define RL_STATE_VICMDONCE 0x00400000 /* entered vi command mode at least once */
|
||||
#define RL_STATE_CHARSEARCH 0x00800000 /* vi mode char search */
|
||||
#define RL_STATE_REDISPLAYING 0x01000000 /* updating terminal display */
|
||||
|
||||
#define RL_STATE_DONE 0x2000000 /* done; accepted line */
|
||||
#define RL_STATE_TIMEOUT 0x4000000 /* done; timed out */
|
||||
#define RL_STATE_EOF 0x8000000 /* done; got eof on read */
|
||||
#define RL_STATE_DONE 0x02000000 /* done; accepted line */
|
||||
#define RL_STATE_TIMEOUT 0x04000000 /* done; timed out */
|
||||
#define RL_STATE_EOF 0x08000000 /* done; got eof on read */
|
||||
|
||||
/* Rearrange these for next major version */
|
||||
#define RL_STATE_READSTR 0x10000000 /* reading a string for M-x */
|
||||
|
||||
#define RL_SETSTATE(x) (rl_readline_state |= (x))
|
||||
#define RL_UNSETSTATE(x) (rl_readline_state &= ~(x))
|
||||
@@ -939,7 +964,7 @@ struct readline_state {
|
||||
char *prompt;
|
||||
|
||||
/* global state */
|
||||
int rlstate;
|
||||
int rlstate; /* XXX -- needs to be unsigned long */
|
||||
int done;
|
||||
Keymap kmap;
|
||||
|
||||
|
||||
@@ -76,4 +76,9 @@
|
||||
#define RL_VI_CMD_MODESTR_DEFAULT "(cmd)"
|
||||
#define RL_VI_CMD_MODESTR_DEFLEN 5
|
||||
|
||||
/* Do you want readline to assume it's running in an ANSI-compatible terminal
|
||||
by default? If set to 0, readline tries to check and verify whether or not
|
||||
it is. */
|
||||
#define RL_ANSI_TERM_DEFAULT 1 /* for now */
|
||||
|
||||
#endif /* _RLCONF_H_ */
|
||||
|
||||
+3
-13
@@ -40,7 +40,7 @@
|
||||
# if defined (HAVE_TERMIO_H)
|
||||
# define TERMIO_TTY_DRIVER
|
||||
# else
|
||||
# if !defined (__MINGW32__)
|
||||
# if !defined (__MINGW32__) && !defined (_MSC_VER)
|
||||
# define NEW_TTY_DRIVER
|
||||
# else
|
||||
# define NO_TTY_DRIVER
|
||||
@@ -63,17 +63,7 @@
|
||||
# include <strings.h>
|
||||
#endif /* !HAVE_STRING_H */
|
||||
|
||||
#if !defined (strchr) && !defined (__STDC__)
|
||||
extern char *strchr (), *strrchr ();
|
||||
#endif /* !strchr && !__STDC__ */
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# if defined (PREFER_VARARGS)
|
||||
# include <varargs.h>
|
||||
# endif
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined (HAVE_STRCASECMP)
|
||||
#define _rl_stricmp strcasecmp
|
||||
@@ -83,7 +73,7 @@ extern int _rl_stricmp (const char *, const char *);
|
||||
extern int _rl_strnicmp (const char *, const char *, int);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_STRPBRK) && !defined (HAVE_MULTIBYTE)
|
||||
#if defined (HAVE_STRPBRK) && !defined (HANDLE_MULTIBYTE)
|
||||
# define _rl_strpbrk(a,b) strpbrk((a),(b))
|
||||
#else
|
||||
extern char *_rl_strpbrk (const char *, const char *);
|
||||
|
||||
+21
-11
@@ -1,6 +1,6 @@
|
||||
/* rlmbutil.h -- utility functions for multibyte characters. */
|
||||
|
||||
/* Copyright (C) 2001-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001-2021,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -104,23 +104,26 @@
|
||||
#define MB_FIND_ANY 0x00
|
||||
#define MB_FIND_NONZERO 0x01
|
||||
|
||||
extern int _rl_find_prev_mbchar (char *, int, int);
|
||||
extern int _rl_find_next_mbchar (char *, int, int, int);
|
||||
extern int _rl_find_prev_mbchar (const char *, int, int);
|
||||
extern int _rl_find_next_mbchar (const char *, int, int, int);
|
||||
|
||||
#ifdef HANDLE_MULTIBYTE
|
||||
|
||||
extern int _rl_compare_chars (char *, int, mbstate_t *, char *, int, mbstate_t *);
|
||||
extern int _rl_get_char_len (char *, mbstate_t *);
|
||||
extern int _rl_adjust_point (char *, int, mbstate_t *);
|
||||
extern int _rl_compare_chars (const char *, int, mbstate_t *, const char *, int, mbstate_t *);
|
||||
extern int _rl_get_char_len (const char *, mbstate_t *);
|
||||
extern int _rl_adjust_point (const char *, int, mbstate_t *);
|
||||
|
||||
extern int _rl_read_mbchar (char *, int);
|
||||
extern int _rl_read_mbstring (int, char *, int);
|
||||
|
||||
extern int _rl_is_mbchar_matched (char *, int, int, char *, int);
|
||||
extern int _rl_is_mbchar_matched (const char *, int, int, char *, int);
|
||||
|
||||
extern WCHAR_T _rl_char_value (char *, int);
|
||||
extern WCHAR_T _rl_char_value (const char *, int);
|
||||
extern int _rl_walphabetic (WCHAR_T);
|
||||
|
||||
extern int _rl_mb_strcaseeqn (const char *, size_t, const char *, size_t, size_t, int);
|
||||
extern int _rl_mb_charcasecmp (const char *, mbstate_t *, const char *, mbstate_t *, int);
|
||||
|
||||
#define _rl_to_wupper(wc) (iswlower (wc) ? towupper (wc) : (wc))
|
||||
#define _rl_to_wlower(wc) (iswupper (wc) ? towlower (wc) : (wc))
|
||||
|
||||
@@ -169,11 +172,16 @@ _rl_wcwidth (WCHAR_T wc)
|
||||
}
|
||||
}
|
||||
|
||||
/* Unicode combining characters range from U+0300 to U+036F */
|
||||
#define UNICODE_COMBINING_CHAR(x) ((x) >= 768 && (x) <= 879)
|
||||
/* Unicode combining characters as of version 15.1 */
|
||||
#define UNICODE_COMBINING_CHAR(x) \
|
||||
(((x) >= 0x0300 && (x) <= 0x036F) || \
|
||||
((x) >= 0x1AB0 && (x) <= 0x1AFF) || \
|
||||
((x) >= 0x1DC0 && (x) <= 0x1DFF) || \
|
||||
((x) >= 0x20D0 && (x) <= 0x20FF) || \
|
||||
((x) >= 0xFE20 && (x) <= 0xFE2F))
|
||||
|
||||
#if defined (WCWIDTH_BROKEN)
|
||||
# define WCWIDTH(wc) ((_rl_utf8locale && UNICODE_COMBINING_CHAR(wc)) ? 0 : _rl_wcwidth(wc))
|
||||
# define WCWIDTH(wc) ((_rl_utf8locale && UNICODE_COMBINING_CHAR((int)wc)) ? 0 : _rl_wcwidth(wc))
|
||||
#else
|
||||
# define WCWIDTH(wc) _rl_wcwidth(wc)
|
||||
#endif
|
||||
@@ -184,6 +192,8 @@ _rl_wcwidth (WCHAR_T wc)
|
||||
# define IS_COMBINING_CHAR(x) (WCWIDTH(x) == 0)
|
||||
#endif
|
||||
|
||||
#define IS_BASE_CHAR(x) (iswgraph(x) && WCWIDTH(x) > 0)
|
||||
|
||||
#define UTF8_SINGLEBYTE(c) (((c) & 0x80) == 0)
|
||||
#define UTF8_MBFIRSTCHAR(c) (((c) & 0xc0) == 0xc0)
|
||||
#define UTF8_MBCHAR(c) (((c) & 0xc0) == 0x80)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* rlprivate.h -- functions and variables global to the readline library,
|
||||
but not intended for use by applications. */
|
||||
|
||||
/* Copyright (C) 1999-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -67,6 +67,7 @@
|
||||
#define SF_CHGKMAP 0x08
|
||||
#define SF_PATTERN 0x10
|
||||
#define SF_NOCASE 0x20 /* unused so far */
|
||||
#define SF_FREEPMT 0x40 /* saved prompt separately, need to free it */
|
||||
|
||||
typedef struct __rl_search_context
|
||||
{
|
||||
@@ -110,6 +111,28 @@ typedef struct __rl_search_context
|
||||
char *search_terminators;
|
||||
} _rl_search_cxt;
|
||||
|
||||
/* readstr flags */
|
||||
#define READSTR_NOSPACE 0x01 /* don't insert space, use for completion */
|
||||
#define READSTR_FREEPMT 0x02 /* called rl_save_prompt, need to free it ourselves */
|
||||
|
||||
typedef struct __rl_readstr_context
|
||||
{
|
||||
int flags;
|
||||
|
||||
int prevc;
|
||||
int lastc;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
char mb[MB_LEN_MAX];
|
||||
char pmb[MB_LEN_MAX];
|
||||
#endif
|
||||
|
||||
int save_point;
|
||||
int save_mark;
|
||||
int save_line;
|
||||
|
||||
int (*compfunc) (struct __rl_readstr_context *, int);
|
||||
} _rl_readstr_cxt;
|
||||
|
||||
struct _rl_cmd {
|
||||
Keymap map;
|
||||
int count;
|
||||
@@ -247,10 +270,11 @@ extern char *_rl_savestring (const char *);
|
||||
* Undocumented private functions *
|
||||
*************************************************************************/
|
||||
|
||||
#if defined(READLINE_CALLBACKS)
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
|
||||
/* readline.c */
|
||||
extern void readline_internal_setup (void);
|
||||
extern void readline_common_teardown (void);
|
||||
extern char *readline_internal_teardown (int);
|
||||
extern int readline_internal_char (void);
|
||||
|
||||
@@ -303,8 +327,22 @@ extern int _rl_pushed_input_available (void);
|
||||
|
||||
extern int _rl_timeout_init (void);
|
||||
extern int _rl_timeout_handle_sigalrm (void);
|
||||
|
||||
#if defined (_POSIXSELECT_H_)
|
||||
/* use as a sentinel for fd_set, struct timeval, and sigset_t definitions */
|
||||
|
||||
#if defined (__MINGW32__)
|
||||
# define RL_TIMEOUT_USE_SIGALRM
|
||||
#elif defined (HAVE_SELECT) || defined (HAVE_PSELECT)
|
||||
# define RL_TIMEOUT_USE_SELECT
|
||||
#elif defined (_MSC_VER)
|
||||
/* can't use select/pselect or SIGALRM, so no timeouts */
|
||||
#else
|
||||
# define RL_TIMEOUT_USE_SIGALRM
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#if defined (RL_TIMEOUT_USE_SELECT)
|
||||
extern int _rl_timeout_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *, const sigset_t *);
|
||||
#endif
|
||||
|
||||
@@ -355,7 +393,13 @@ extern int _rl_arg_callback (_rl_arg_cxt);
|
||||
extern void _rl_reset_argument (void);
|
||||
|
||||
extern void _rl_start_using_history (void);
|
||||
#if defined (HIST_ENTRY_DEFINED)
|
||||
extern HIST_ENTRY *_rl_alloc_saved_line (void);
|
||||
extern void _rl_free_saved_line (HIST_ENTRY *);
|
||||
extern void _rl_unsave_line (HIST_ENTRY *);
|
||||
#endif
|
||||
extern int _rl_free_saved_history_line (void);
|
||||
|
||||
extern void _rl_set_insert_mode (int, int);
|
||||
|
||||
extern void _rl_revert_previous_lines (void);
|
||||
@@ -391,6 +435,9 @@ extern int _rl_restore_tty_signals (void);
|
||||
/* search.c */
|
||||
extern int _rl_nsearch_callback (_rl_search_cxt *);
|
||||
extern int _rl_nsearch_cleanup (_rl_search_cxt *, int);
|
||||
extern int _rl_nsearch_sigcleanup (_rl_search_cxt *, int);
|
||||
|
||||
extern void _rl_free_saved_search_line (void);
|
||||
|
||||
/* signals.c */
|
||||
extern void _rl_signal_handler (int);
|
||||
@@ -400,6 +447,8 @@ extern void _rl_release_sigint (void);
|
||||
extern void _rl_block_sigwinch (void);
|
||||
extern void _rl_release_sigwinch (void);
|
||||
|
||||
extern void _rl_state_sigcleanup (void);
|
||||
|
||||
/* terminal.c */
|
||||
extern void _rl_get_screen_size (int, int);
|
||||
extern void _rl_sigwinch_resize_terminal (void);
|
||||
@@ -439,21 +488,26 @@ extern int _rl_char_search_internal (int, int, int);
|
||||
#endif
|
||||
extern int _rl_set_mark_at_pos (int);
|
||||
|
||||
extern _rl_readstr_cxt *_rl_rscxt_alloc (int);
|
||||
extern void _rl_rscxt_dispose (_rl_readstr_cxt *, int);
|
||||
extern void _rl_free_saved_readstr_line (void);
|
||||
extern void _rl_unsave_saved_readstr_line (void);
|
||||
extern _rl_readstr_cxt *_rl_readstr_init (int, int);
|
||||
extern int _rl_readstr_cleanup (_rl_readstr_cxt *, int);
|
||||
extern int _rl_readstr_sigcleanup (_rl_readstr_cxt *, int);
|
||||
extern void _rl_readstr_restore (_rl_readstr_cxt *);
|
||||
extern int _rl_readstr_getchar (_rl_readstr_cxt *);
|
||||
extern int _rl_readstr_dispatch (_rl_readstr_cxt *, int);
|
||||
|
||||
/* undo.c */
|
||||
extern UNDO_LIST *_rl_copy_undo_entry (UNDO_LIST *);
|
||||
extern UNDO_LIST *_rl_copy_undo_list (UNDO_LIST *);
|
||||
extern void _rl_free_undo_list (UNDO_LIST *);
|
||||
|
||||
/* util.c */
|
||||
#if defined (USE_VARARGS) && defined (PREFER_STDARG)
|
||||
extern void _rl_ttymsg (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
|
||||
extern void _rl_errmsg (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
|
||||
extern void _rl_trace (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
|
||||
#else
|
||||
extern void _rl_ttymsg ();
|
||||
extern void _rl_errmsg ();
|
||||
extern void _rl_trace ();
|
||||
#endif
|
||||
extern void _rl_audit_tty (char *);
|
||||
|
||||
extern int _rl_tropen (void);
|
||||
@@ -461,6 +515,8 @@ extern int _rl_tropen (void);
|
||||
extern int _rl_abort_internal (void);
|
||||
extern int _rl_null_function (int, int);
|
||||
extern char *_rl_strindex (const char *, const char *);
|
||||
extern int _rl_strcaseeqn (const char *, const char *, size_t, int);
|
||||
extern int _rl_charcasecmp (int, int, int);
|
||||
extern int _rl_qsort_string_compare (char **, char **);
|
||||
extern int (_rl_uppercase_p) (int);
|
||||
extern int (_rl_lowercase_p) (int);
|
||||
@@ -516,6 +572,7 @@ extern int _rl_menu_complete_prefix_first;
|
||||
/* display.c */
|
||||
extern int _rl_vis_botlin;
|
||||
extern int _rl_last_c_pos;
|
||||
extern int _rl_last_v_pos;
|
||||
extern int _rl_suppress_redisplay;
|
||||
extern int _rl_want_redisplay;
|
||||
|
||||
@@ -530,6 +587,7 @@ extern int _rl_vi_cmd_modestr_len;
|
||||
extern char *_rl_isearch_terminators;
|
||||
|
||||
extern _rl_search_cxt *_rl_iscxt;
|
||||
extern int _rl_search_case_fold;
|
||||
|
||||
/* macro.c */
|
||||
extern char *_rl_executing_macro;
|
||||
@@ -570,7 +628,7 @@ extern procenv_t _rl_top_level;
|
||||
extern _rl_keyseq_cxt *_rl_kscxt;
|
||||
extern int _rl_keyseq_timeout;
|
||||
|
||||
extern int _rl_executing_keyseq_size;
|
||||
extern size_t _rl_executing_keyseq_size;
|
||||
|
||||
extern rl_hook_func_t *_rl_internal_startup_hook;
|
||||
|
||||
@@ -615,6 +673,8 @@ extern int _rl_term_autowrap;
|
||||
extern int _rl_optimize_typeahead;
|
||||
extern int _rl_keep_mark_active;
|
||||
|
||||
extern _rl_readstr_cxt *_rl_rscxt;
|
||||
|
||||
/* undo.c */
|
||||
extern int _rl_doing_an_undo;
|
||||
extern int _rl_undo_group_level;
|
||||
|
||||
+1
-13
@@ -1,6 +1,6 @@
|
||||
/* stdc.h -- macros to make source compile on both ANSI C and K&R C compilers. */
|
||||
|
||||
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2009,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -42,16 +42,4 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Moved from config.h.in because readline.h:rl_message depends on these
|
||||
defines. */
|
||||
#if defined (__STDC__) && defined (HAVE_STDARG_H)
|
||||
# define PREFER_STDARG
|
||||
# define USE_VARARGS
|
||||
#else
|
||||
# if defined (HAVE_VARARGS_H)
|
||||
# define PREFER_VARARGS
|
||||
# define USE_VARARGS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* !_RL_STDC_H_ */
|
||||
|
||||
+18
-17
@@ -1,7 +1,7 @@
|
||||
/* rltty.c -- functions to prepare and restore the terminal for readline's
|
||||
use. */
|
||||
|
||||
/* Copyright (C) 1992-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1992-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -49,6 +49,8 @@
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
int _rl_use_tty_xon_xoff = 1;
|
||||
|
||||
rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal;
|
||||
rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal;
|
||||
|
||||
@@ -80,8 +82,7 @@ static int ksrflow;
|
||||
/* Dummy call to force a backgrounded readline to stop before it tries
|
||||
to get the tty settings. */
|
||||
static void
|
||||
set_winsize (tty)
|
||||
int tty;
|
||||
set_winsize (int tty)
|
||||
{
|
||||
#if defined (TIOCGWINSZ)
|
||||
struct winsize w;
|
||||
@@ -276,15 +277,16 @@ prepare_terminal_settings (int meta_flag, TIOTYPE oldtio, TIOTYPE *tiop)
|
||||
}
|
||||
|
||||
#if defined (TIOCGETC)
|
||||
# if defined (USE_XON_XOFF)
|
||||
/* Get rid of terminal output start and stop characters. */
|
||||
tiop->tchars.t_stopc = -1; /* C-s */
|
||||
tiop->tchars.t_startc = -1; /* C-q */
|
||||
if (_rl_use_tty_xon_xoff == 0)
|
||||
{
|
||||
/* Get rid of terminal output start and stop characters. */
|
||||
tiop->tchars.t_stopc = -1; /* C-s */
|
||||
tiop->tchars.t_startc = -1; /* C-q */
|
||||
|
||||
/* If there is an XON character, bind it to restart the output. */
|
||||
if (oldtio.tchars.t_startc != -1)
|
||||
rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
|
||||
# endif /* USE_XON_XOFF */
|
||||
/* If there is an XON character, bind it to restart the output. */
|
||||
if (oldtio.tchars.t_startc != -1)
|
||||
rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
|
||||
}
|
||||
|
||||
/* If there is an EOF char, bind _rl_eof_char to it. */
|
||||
if (oldtio.tchars.t_eofc != -1)
|
||||
@@ -515,14 +517,13 @@ prepare_terminal_settings (int meta_flag, TIOTYPE oldtio, TIOTYPE *tiop)
|
||||
if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
|
||||
_rl_eof_char = oldtio.c_cc[VEOF];
|
||||
|
||||
#if defined (USE_XON_XOFF)
|
||||
if (_rl_use_tty_xon_xoff == 0)
|
||||
#if defined (IXANY)
|
||||
tiop->c_iflag &= ~(IXON | IXANY);
|
||||
tiop->c_iflag &= ~(IXON | IXANY);
|
||||
#else
|
||||
/* `strict' Posix systems do not define IXANY. */
|
||||
tiop->c_iflag &= ~IXON;
|
||||
/* `strict' Posix systems do not define IXANY. */
|
||||
tiop->c_iflag &= ~IXON;
|
||||
#endif /* IXANY */
|
||||
#endif /* USE_XON_XOFF */
|
||||
|
||||
/* Only turn this off if we are using all 8 bits. */
|
||||
if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
|
||||
@@ -729,7 +730,7 @@ rl_tty_set_echoing (int u)
|
||||
_rl_echoing_p = u;
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Bogus Flow Control */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* rltypedefs.h -- Type declarations for readline functions. */
|
||||
|
||||
/* Copyright (C) 2000-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2000-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -28,22 +28,15 @@ extern "C" {
|
||||
|
||||
/* Old-style, attempt to mark as deprecated in some way people will notice. */
|
||||
|
||||
#if !defined (_FUNCTION_DEF)
|
||||
#if !defined (_FUNCTION_DEF) && defined (WANT_OBSOLETE_TYPEDEFS)
|
||||
# define _FUNCTION_DEF
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
typedef int Function () __attribute__((deprecated));
|
||||
typedef void VFunction () __attribute__((deprecated));
|
||||
typedef char *CPFunction () __attribute__((deprecated));
|
||||
typedef char **CPPFunction () __attribute__((deprecated));
|
||||
#else
|
||||
typedef int Function ();
|
||||
typedef void VFunction ();
|
||||
typedef char *CPFunction ();
|
||||
typedef char **CPPFunction ();
|
||||
#endif
|
||||
|
||||
#endif /* _FUNCTION_DEF */
|
||||
#endif /* _FUNCTION_DEF && WANT_OBSOLETE_TYPEDEFS */
|
||||
|
||||
/* New style. */
|
||||
|
||||
@@ -64,6 +57,9 @@ typedef int rl_compignore_func_t (char **);
|
||||
|
||||
typedef void rl_compdisp_func_t (char **, int, int);
|
||||
|
||||
/* Functions for displaying key bindings. Currently only one. */
|
||||
typedef void rl_macro_print_func_t (const char *, const char *, int, const char *);
|
||||
|
||||
/* Type for input and pre-read hook functions like rl_event_hook */
|
||||
typedef int rl_hook_func_t (void);
|
||||
|
||||
|
||||
+124
-49
@@ -1,6 +1,6 @@
|
||||
/* search.c - code for non-incremental searching in emacs and vi modes. */
|
||||
|
||||
/* Copyright (C) 1992-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1992-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -55,6 +55,8 @@
|
||||
|
||||
_rl_search_cxt *_rl_nscxt = 0;
|
||||
|
||||
static HIST_ENTRY *_rl_saved_line_for_search;
|
||||
|
||||
static char *noninc_search_string = (char *) NULL;
|
||||
static int noninc_history_pos;
|
||||
|
||||
@@ -65,7 +67,7 @@ static int _rl_history_search_len;
|
||||
static int _rl_history_search_flags;
|
||||
|
||||
static char *history_search_string;
|
||||
static int history_string_size;
|
||||
static size_t history_string_size;
|
||||
|
||||
static void make_history_line_current (HIST_ENTRY *);
|
||||
static int noninc_search_from_pos (char *, int, int, int, int *);
|
||||
@@ -78,21 +80,57 @@ static _rl_search_cxt *_rl_nsearch_init (int, int);
|
||||
static void _rl_nsearch_abort (_rl_search_cxt *);
|
||||
static int _rl_nsearch_dispatch (_rl_search_cxt *, int);
|
||||
|
||||
void
|
||||
_rl_free_saved_search_line (void)
|
||||
{
|
||||
if (_rl_saved_line_for_search)
|
||||
_rl_free_saved_line (_rl_saved_line_for_search);
|
||||
_rl_saved_line_for_search = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_rl_unsave_saved_search_line (void)
|
||||
{
|
||||
if (_rl_saved_line_for_search)
|
||||
_rl_unsave_line (_rl_saved_line_for_search);
|
||||
_rl_saved_line_for_search = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
|
||||
/* We're going to replace the undo list with the one created by inserting
|
||||
the matching line we found, so we want to free rl_undo_list if it's not
|
||||
from a history entry. We assume the undo list does not come from a
|
||||
history entry if we are at the end of the history, entering a new line.
|
||||
|
||||
The call to rl_maybe_replace_line() has already ensured that any undo
|
||||
list pointing to a history entry has already been saved back to the
|
||||
history and set rl_undo_list to NULL. */
|
||||
|
||||
static void
|
||||
dispose_saved_search_line (void)
|
||||
{
|
||||
UNDO_LIST *xlist;
|
||||
|
||||
if (_hs_at_end_of_history () == 0)
|
||||
_rl_unsave_saved_search_line ();
|
||||
else if (_rl_saved_line_for_search)
|
||||
{
|
||||
xlist = _rl_saved_line_for_search ? (UNDO_LIST *)_rl_saved_line_for_search->data : 0;
|
||||
if (xlist)
|
||||
_rl_free_undo_list (xlist);
|
||||
_rl_saved_line_for_search->data = 0;
|
||||
_rl_free_saved_search_line ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the data from the history entry ENTRY be the contents of the
|
||||
current line. This doesn't do anything with rl_point; the caller
|
||||
must set it. */
|
||||
static void
|
||||
make_history_line_current (HIST_ENTRY *entry)
|
||||
{
|
||||
UNDO_LIST *xlist;
|
||||
|
||||
xlist = _rl_saved_line_for_history ? (UNDO_LIST *)_rl_saved_line_for_history->data : 0;
|
||||
/* At this point, rl_undo_list points to a private search string list. */
|
||||
if (rl_undo_list && rl_undo_list != (UNDO_LIST *)entry->data && rl_undo_list != xlist)
|
||||
rl_free_undo_list ();
|
||||
|
||||
/* Now we create a new undo list with a single insert for this text.
|
||||
WE DON'T CHANGE THE ORIGINAL HISTORY ENTRY UNDO LIST */
|
||||
rl_undo_list = 0; /* XXX */
|
||||
_rl_replace_text (entry->line, 0, rl_end);
|
||||
_rl_fix_point (1);
|
||||
#if defined (VI_MODE)
|
||||
@@ -103,15 +141,6 @@ make_history_line_current (HIST_ENTRY *entry)
|
||||
current editing buffer. */
|
||||
rl_free_undo_list ();
|
||||
#endif
|
||||
|
||||
/* This will need to free the saved undo list associated with the original
|
||||
(pre-search) line buffer.
|
||||
XXX - look at _rl_free_saved_history_line and consider calling it if
|
||||
rl_undo_list != xlist (or calling rl_free_undo list directly on
|
||||
_rl_saved_line_for_history->data) */
|
||||
if (_rl_saved_line_for_history)
|
||||
_rl_free_history_entry (_rl_saved_line_for_history);
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
|
||||
/* Search the history list for STRING starting at absolute history position
|
||||
@@ -135,21 +164,23 @@ noninc_search_from_pos (char *string, int pos, int dir, int flags, int *ncp)
|
||||
RL_SETSTATE(RL_STATE_SEARCH);
|
||||
/* These functions return the match offset in the line; history_offset gives
|
||||
the matching line in the history list */
|
||||
if (flags & SF_PATTERN)
|
||||
|
||||
sflags = 0; /* Non-anchored search */
|
||||
s = string;
|
||||
if (*s == '^')
|
||||
{
|
||||
s = string;
|
||||
sflags = 0; /* Non-anchored search */
|
||||
if (*s == '^')
|
||||
{
|
||||
sflags |= ANCHORED_SEARCH;
|
||||
s++;
|
||||
}
|
||||
ret = _hs_history_patsearch (s, dir, sflags);
|
||||
sflags |= ANCHORED_SEARCH;
|
||||
s++;
|
||||
}
|
||||
else if (*string == '^')
|
||||
ret = history_search_prefix (string + 1, dir);
|
||||
|
||||
if (flags & SF_PATTERN)
|
||||
ret = _hs_history_patsearch (s, dir, sflags);
|
||||
else
|
||||
ret = history_search (string, dir);
|
||||
{
|
||||
if (_rl_search_case_fold)
|
||||
sflags |= CASEFOLD_SEARCH;
|
||||
ret = _hs_history_search (s, dir, sflags);
|
||||
}
|
||||
RL_UNSETSTATE(RL_STATE_SEARCH);
|
||||
|
||||
if (ncp)
|
||||
@@ -181,7 +212,7 @@ noninc_dosearch (char *string, int dir, int flags)
|
||||
if (pos == -1)
|
||||
{
|
||||
/* Search failed, current history position unchanged. */
|
||||
rl_maybe_unsave_line ();
|
||||
_rl_unsave_saved_search_line ();
|
||||
rl_clear_message ();
|
||||
rl_point = 0;
|
||||
rl_ding ();
|
||||
@@ -190,6 +221,10 @@ noninc_dosearch (char *string, int dir, int flags)
|
||||
|
||||
noninc_history_pos = pos;
|
||||
|
||||
/* We're committed to making the line we found the current contents of
|
||||
rl_line_buffer. We can dispose of _rl_saved_line_for_search. */
|
||||
dispose_saved_search_line ();
|
||||
|
||||
oldpos = where_history ();
|
||||
history_set_pos (noninc_history_pos);
|
||||
entry = current_history (); /* will never be NULL after successful search */
|
||||
@@ -201,7 +236,7 @@ noninc_dosearch (char *string, int dir, int flags)
|
||||
|
||||
make_history_line_current (entry);
|
||||
|
||||
if (_rl_enable_active_region && ((flags & SF_PATTERN) == 0) && ind > 0 && ind < rl_end)
|
||||
if (_rl_enable_active_region && ((flags & SF_PATTERN) == 0) && ind >= 0 && ind < rl_end)
|
||||
{
|
||||
rl_point = ind;
|
||||
rl_mark = ind + strlen (string);
|
||||
@@ -236,7 +271,10 @@ _rl_nsearch_init (int dir, int pchar)
|
||||
cxt->direction = dir;
|
||||
cxt->history_pos = cxt->save_line;
|
||||
|
||||
rl_maybe_save_line ();
|
||||
/* If the current line has changed, put it back into the history if necessary. */
|
||||
rl_maybe_replace_line ();
|
||||
|
||||
_rl_saved_line_for_search = _rl_alloc_saved_line ();
|
||||
|
||||
/* Clear the undo list, since reading the search string should create its
|
||||
own undo list, and the whole list will end up being freed when we
|
||||
@@ -248,6 +286,7 @@ _rl_nsearch_init (int dir, int pchar)
|
||||
rl_end = rl_point = 0;
|
||||
|
||||
p = _rl_make_prompt_for_search (pchar ? pchar : ':');
|
||||
cxt->sflags |= SF_FREEPMT;
|
||||
rl_message ("%s", p);
|
||||
xfree (p);
|
||||
|
||||
@@ -272,16 +311,27 @@ _rl_nsearch_cleanup (_rl_search_cxt *cxt, int r)
|
||||
static void
|
||||
_rl_nsearch_abort (_rl_search_cxt *cxt)
|
||||
{
|
||||
rl_maybe_unsave_line ();
|
||||
_rl_unsave_saved_search_line ();
|
||||
rl_point = cxt->save_point;
|
||||
rl_mark = cxt->save_mark;
|
||||
rl_restore_prompt ();
|
||||
if (cxt->sflags & SF_FREEPMT)
|
||||
rl_restore_prompt (); /* _rl_make_prompt_for_search saved it */
|
||||
cxt->sflags &= ~SF_FREEPMT;
|
||||
rl_clear_message ();
|
||||
_rl_fix_point (1);
|
||||
|
||||
RL_UNSETSTATE (RL_STATE_NSEARCH);
|
||||
}
|
||||
|
||||
int
|
||||
_rl_nsearch_sigcleanup (_rl_search_cxt *cxt, int r)
|
||||
{
|
||||
if (cxt->sflags & SF_FREEPMT)
|
||||
rl_restore_prompt (); /* _rl_make_prompt_for_search saved it */
|
||||
cxt->sflags &= ~SF_FREEPMT;
|
||||
return (_rl_nsearch_cleanup (cxt, r));
|
||||
}
|
||||
|
||||
/* Process just-read character C according to search context CXT. Return -1
|
||||
if the caller should abort the search, 0 if we should break out of the
|
||||
loop, and 1 if we should continue to read characters. */
|
||||
@@ -303,6 +353,17 @@ _rl_nsearch_dispatch (_rl_search_cxt *cxt, int c)
|
||||
rl_unix_line_discard (1, c);
|
||||
break;
|
||||
|
||||
case CTRL('Q'):
|
||||
case CTRL('V'):
|
||||
n = rl_quoted_insert (1, c);
|
||||
if (n < 0)
|
||||
{
|
||||
_rl_nsearch_abort (cxt);
|
||||
return -1;
|
||||
}
|
||||
cxt->lastc = (rl_point > 0) ? rl_line_buffer[rl_point - 1] : rl_line_buffer[0];
|
||||
break;
|
||||
|
||||
case RETURN:
|
||||
case NEWLINE:
|
||||
return 0;
|
||||
@@ -376,8 +437,11 @@ _rl_nsearch_dosearch (_rl_search_cxt *cxt)
|
||||
{
|
||||
if (noninc_search_string == 0)
|
||||
{
|
||||
_rl_free_saved_search_line ();
|
||||
rl_ding ();
|
||||
rl_restore_prompt ();
|
||||
if (cxt->sflags & SF_FREEPMT)
|
||||
rl_restore_prompt ();
|
||||
cxt->sflags &= ~SF_FREEPMT;
|
||||
RL_UNSETSTATE (RL_STATE_NSEARCH);
|
||||
return -1;
|
||||
}
|
||||
@@ -389,15 +453,22 @@ _rl_nsearch_dosearch (_rl_search_cxt *cxt)
|
||||
FREE (noninc_search_string);
|
||||
noninc_search_string = savestring (rl_line_buffer);
|
||||
|
||||
/* If we don't want the subsequent undo list generated by the search
|
||||
/* We don't want the subsequent undo list generated by the search
|
||||
matching a history line to include the contents of the search string,
|
||||
we need to clear rl_line_buffer here. For now, we just clear the
|
||||
undo list generated by reading the search string. (If the search
|
||||
fails, the old undo list will be restored by rl_maybe_unsave_line.) */
|
||||
so we need to clear rl_line_buffer here. If we don't want that,
|
||||
change the #if 1 to an #if 0 below. We clear the undo list
|
||||
generated by reading the search string. (If the search fails, the
|
||||
old undo list will be restored by _rl_unsave_line.) */
|
||||
|
||||
rl_free_undo_list ();
|
||||
#if 1
|
||||
rl_line_buffer[rl_point = rl_end = 0] = '\0';
|
||||
#endif
|
||||
}
|
||||
|
||||
rl_restore_prompt ();
|
||||
if (cxt->sflags & SF_FREEPMT)
|
||||
rl_restore_prompt ();
|
||||
cxt->sflags &= ~SF_FREEPMT;
|
||||
return (noninc_dosearch (noninc_search_string, cxt->direction, cxt->sflags&SF_PATTERN));
|
||||
}
|
||||
|
||||
@@ -530,11 +601,12 @@ rl_history_search_internal (int count, int dir)
|
||||
{
|
||||
HIST_ENTRY *temp;
|
||||
int ret, oldpos, newcol;
|
||||
int had_saved_line;
|
||||
char *t;
|
||||
|
||||
had_saved_line = _rl_saved_line_for_history != 0;
|
||||
rl_maybe_save_line ();
|
||||
/* If the current line has changed, put it back into the history if necessary. */
|
||||
rl_maybe_replace_line ();
|
||||
|
||||
_rl_saved_line_for_search = _rl_alloc_saved_line ();
|
||||
temp = (HIST_ENTRY *)NULL;
|
||||
|
||||
/* Search COUNT times through the history for a line matching
|
||||
@@ -566,8 +638,7 @@ rl_history_search_internal (int count, int dir)
|
||||
/* If we didn't find anything at all, return. */
|
||||
if (temp == 0)
|
||||
{
|
||||
/* XXX - check had_saved_line here? */
|
||||
rl_maybe_unsave_line ();
|
||||
_rl_unsave_saved_search_line ();
|
||||
rl_ding ();
|
||||
/* If you don't want the saved history line (last match) to show up
|
||||
in the line buffer after the search fails, change the #if 0 to
|
||||
@@ -580,12 +651,16 @@ rl_history_search_internal (int count, int dir)
|
||||
rl_mark = 0;
|
||||
}
|
||||
#else
|
||||
rl_point = _rl_history_search_len; /* rl_maybe_unsave_line changes it */
|
||||
rl_point = _rl_history_search_len; /* _rl_unsave_line changes it */
|
||||
rl_mark = rl_end;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We're committed to making the line we found the current contents of
|
||||
rl_line_buffer. We can dispose of _rl_saved_line_for_search. */
|
||||
dispose_saved_search_line ();
|
||||
|
||||
/* Copy the line we found into the current line buffer. */
|
||||
make_history_line_current (temp);
|
||||
|
||||
@@ -619,7 +694,7 @@ rl_history_search_reinit (int flags)
|
||||
if (rl_point)
|
||||
{
|
||||
/* Allocate enough space for anchored and non-anchored searches */
|
||||
if (_rl_history_search_len >= history_string_size - 2)
|
||||
if (_rl_history_search_len + 2 >= history_string_size)
|
||||
{
|
||||
history_string_size = _rl_history_search_len + 2;
|
||||
history_search_string = (char *)xrealloc (history_search_string, history_string_size);
|
||||
@@ -630,7 +705,7 @@ rl_history_search_reinit (int flags)
|
||||
strncpy (history_search_string + sind, rl_line_buffer, rl_point);
|
||||
history_search_string[rl_point + sind] = '\0';
|
||||
}
|
||||
_rl_free_saved_history_line (); /* XXX rl_undo_list? */
|
||||
_rl_free_saved_search_line ();
|
||||
}
|
||||
|
||||
/* Search forward in the history for the string of characters
|
||||
|
||||
@@ -67,10 +67,6 @@
|
||||
extern struct passwd *getpwuid (uid_t);
|
||||
#endif /* HAVE_GETPWUID && !HAVE_GETPW_DECLS */
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
+20
-2
@@ -1,6 +1,6 @@
|
||||
/* signals.c -- signal handling support for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -267,6 +267,9 @@ _rl_handle_signal (int sig)
|
||||
sigprocmask (SIG_BLOCK, &set, &oset);
|
||||
#endif
|
||||
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0 || rl_persistent_signal_handlers)
|
||||
#endif
|
||||
rl_echo_signal_char (sig);
|
||||
rl_cleanup_after_signal ();
|
||||
|
||||
@@ -582,6 +585,19 @@ rl_reset_after_signal (void)
|
||||
rl_set_signals ();
|
||||
}
|
||||
|
||||
/* Similar to rl_callback_sigcleanup, but cleans up operations that allocate
|
||||
state even when not in callback mode. */
|
||||
void
|
||||
_rl_state_sigcleanup (void)
|
||||
{
|
||||
if (RL_ISSTATE (RL_STATE_ISEARCH)) /* incremental search */
|
||||
_rl_isearch_cleanup (_rl_iscxt, 0);
|
||||
else if (RL_ISSTATE (RL_STATE_NSEARCH)) /* non-incremental search */
|
||||
_rl_nsearch_sigcleanup (_rl_nscxt, 0);
|
||||
else if (RL_ISSTATE (RL_STATE_READSTR)) /* reading a string */
|
||||
_rl_readstr_sigcleanup (_rl_rscxt, 0);
|
||||
}
|
||||
|
||||
/* Free up the readline variable line state for the current line (undo list,
|
||||
any partial history entry, any keyboard macros in progress, and any
|
||||
numeric arguments in process) after catching a signal, before calling
|
||||
@@ -591,6 +607,9 @@ rl_free_line_state (void)
|
||||
{
|
||||
register HIST_ENTRY *entry;
|
||||
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
|
||||
_rl_state_sigcleanup ();
|
||||
|
||||
rl_free_undo_list ();
|
||||
|
||||
entry = current_history ();
|
||||
@@ -622,7 +641,6 @@ rl_check_signals (void)
|
||||
/* **************************************************************** */
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
static sigset_t sigint_set, sigint_oset;
|
||||
static sigset_t sigwinch_set, sigwinch_oset;
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
/* tcap.h -- termcap library functions and variables. */
|
||||
|
||||
/* Copyright (C) 1996-2015 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2015,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -46,14 +46,14 @@ extern char *UP, *BC;
|
||||
|
||||
extern short ospeed;
|
||||
|
||||
extern int tgetent ();
|
||||
extern int tgetflag ();
|
||||
extern int tgetnum ();
|
||||
extern char *tgetstr ();
|
||||
extern int tgetent (char *, const char *);
|
||||
extern int tgetflag (const char *);
|
||||
extern int tgetnum (const char *);
|
||||
extern char *tgetstr (const char *, char **);
|
||||
|
||||
extern int tputs ();
|
||||
extern int tputs (const char *, int, int (*)(int));
|
||||
|
||||
extern char *tgoto ();
|
||||
extern char *tgoto (const char *, int, int);
|
||||
|
||||
#endif /* HAVE_TERMCAP_H */
|
||||
|
||||
|
||||
+92
-7
@@ -1,6 +1,6 @@
|
||||
/* terminal.c -- controlling the terminal with termcap. */
|
||||
|
||||
/* Copyright (C) 1996-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -69,7 +69,7 @@
|
||||
#include "rlshell.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#if defined (__MINGW32__)
|
||||
#if defined (_WIN32)
|
||||
# include <windows.h>
|
||||
# include <wincon.h>
|
||||
|
||||
@@ -113,6 +113,7 @@ char PC, *BC, *UP;
|
||||
char *_rl_term_clreol;
|
||||
char *_rl_term_clrpag;
|
||||
char *_rl_term_clrscroll;
|
||||
char *_rl_term_ho;
|
||||
char *_rl_term_cr;
|
||||
char *_rl_term_backspace;
|
||||
char *_rl_term_goto;
|
||||
@@ -185,6 +186,12 @@ static char *_rl_term_kN;
|
||||
static char *_rl_term_vs; /* very visible */
|
||||
static char *_rl_term_ve; /* normal */
|
||||
|
||||
/* Bracketed paste */
|
||||
static char *_rl_term_BE; /* enable */
|
||||
static char *_rl_term_BD; /* disable */
|
||||
static char *_rl_term_PS; /* paste start */
|
||||
static char *_rl_term_PE; /* paste end */
|
||||
|
||||
/* User-settable color sequences to begin and end the active region. Defaults
|
||||
are rl_term_so and rl_term_se on non-dumb terminals. */
|
||||
char *_rl_active_region_start_color = NULL;
|
||||
@@ -214,6 +221,9 @@ int _rl_enable_keypad;
|
||||
/* Non-zero means the user wants to enable a meta key. */
|
||||
int _rl_enable_meta = 1;
|
||||
|
||||
/* Non-zero means this is an ANSI-compatible terminal; assume it is. */
|
||||
int _rl_term_isansi = RL_ANSI_TERM_DEFAULT;
|
||||
|
||||
#if defined (__EMX__)
|
||||
static void
|
||||
_emx_get_screensize (int *swp, int *shp)
|
||||
@@ -229,7 +239,7 @@ _emx_get_screensize (int *swp, int *shp)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (__MINGW32__)
|
||||
#if defined (_WIN32)
|
||||
static void
|
||||
_win_get_screensize (int *swp, int *shp)
|
||||
{
|
||||
@@ -272,7 +282,7 @@ _rl_get_screen_size (int tty, int ignore_env)
|
||||
|
||||
#if defined (__EMX__)
|
||||
_emx_get_screensize (&wc, &wr);
|
||||
#elif defined (__MINGW32__)
|
||||
#elif defined (_WIN32) && !defined (__CYGWIN__)
|
||||
_win_get_screensize (&wc, &wr);
|
||||
#endif
|
||||
|
||||
@@ -415,14 +425,19 @@ struct _tc_string {
|
||||
static const struct _tc_string tc_strings[] =
|
||||
{
|
||||
{ "@7", &_rl_term_at7 },
|
||||
{ "BD", &_rl_term_BD },
|
||||
{ "BE", &_rl_term_BE },
|
||||
{ "DC", &_rl_term_DC },
|
||||
{ "E3", &_rl_term_clrscroll },
|
||||
{ "IC", &_rl_term_IC },
|
||||
{ "PE", &_rl_term_PE },
|
||||
{ "PS", &_rl_term_PS },
|
||||
{ "ce", &_rl_term_clreol },
|
||||
{ "cl", &_rl_term_clrpag },
|
||||
{ "cr", &_rl_term_cr },
|
||||
{ "dc", &_rl_term_dc },
|
||||
{ "ei", &_rl_term_ei },
|
||||
{ "ho", &_rl_term_ho },
|
||||
{ "ic", &_rl_term_ic },
|
||||
{ "im", &_rl_term_im },
|
||||
{ "kD", &_rl_term_kD }, /* delete */
|
||||
@@ -466,6 +481,63 @@ get_term_capabilities (char **bp)
|
||||
tcap_initialized = 1;
|
||||
}
|
||||
|
||||
struct _term_name {
|
||||
const char * const name;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/* Non-exhaustive list of ANSI/ECMA terminals. */
|
||||
static const struct _term_name ansiterms[] =
|
||||
{
|
||||
{ "xterm", 5 },
|
||||
{ "rxvt", 4 },
|
||||
{ "eterm", 5 },
|
||||
{ "screen", 6 },
|
||||
{ "tmux", 4 },
|
||||
{ "vt100", 5 },
|
||||
{ "vt102", 5 },
|
||||
{ "vt220", 5 },
|
||||
{ "vt320", 5 },
|
||||
{ "ansi", 4 },
|
||||
{ "scoansi", 7 },
|
||||
{ "cygwin", 6 },
|
||||
{ "linux", 5 },
|
||||
{ "konsole", 7 },
|
||||
{ "bvterm", 6 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static inline int
|
||||
iscsi (const char *s)
|
||||
{
|
||||
return ((s[0] == ESC && s[1] == '[') ? 2
|
||||
: ((unsigned char)s[0] == 0x9b) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_check_ansi_terminal (const char *terminal_name)
|
||||
{
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
for (i = 0; ansiterms[i].name; i++)
|
||||
if (STREQN (terminal_name, ansiterms[i].name, ansiterms[i].len))
|
||||
return 1;
|
||||
|
||||
if (_rl_term_clreol == 0 || _rl_term_forward_char == 0 ||
|
||||
_rl_term_ho == 0 || _rl_term_up == 0)
|
||||
return 0;
|
||||
|
||||
/* check some common capabilities */
|
||||
if (((len = iscsi (_rl_term_clreol)) && _rl_term_clreol[len] == 'K') && /* ce */
|
||||
((len = iscsi (_rl_term_forward_char)) && _rl_term_forward_char[len] == 'C') && /* nd */
|
||||
((len = iscsi (_rl_term_ho)) && _rl_term_ho[len] == 'H') && /* ho */
|
||||
((len = iscsi (_rl_term_up)) && _rl_term_up[len] == 'A')) /* up */
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_rl_init_terminal_io (const char *terminal_name)
|
||||
{
|
||||
@@ -480,7 +552,10 @@ _rl_init_terminal_io (const char *terminal_name)
|
||||
if (term == 0)
|
||||
term = "dumb";
|
||||
|
||||
dumbterm = STREQ (term, "dumb");
|
||||
_rl_term_isansi = RL_ANSI_TERM_DEFAULT;
|
||||
dumbterm = STREQ (term, "dumb") || STREQ (term, "vt52") || STREQ (term, "adm3a");
|
||||
if (dumbterm)
|
||||
_rl_term_isansi = 0;
|
||||
|
||||
reset_region_colors = 1;
|
||||
|
||||
@@ -492,11 +567,13 @@ _rl_init_terminal_io (const char *terminal_name)
|
||||
_rl_terminal_can_insert = term_has_meta = _rl_term_autowrap = 0;
|
||||
_rl_term_cr = "\r";
|
||||
_rl_term_backspace = (char *)NULL;
|
||||
_rl_term_ho = (char *)NULL;
|
||||
_rl_term_goto = _rl_term_pc = _rl_term_ip = (char *)NULL;
|
||||
_rl_term_ks = _rl_term_ke =_rl_term_vs = _rl_term_ve = (char *)NULL;
|
||||
_rl_term_kh = _rl_term_kH = _rl_term_at7 = _rl_term_kI = (char *)NULL;
|
||||
_rl_term_kN = _rl_term_kP = (char *)NULL;
|
||||
_rl_term_so = _rl_term_se = (char *)NULL;
|
||||
_rl_term_BD = _rl_term_BE = _rl_term_PE = _rl_term_PS = (char *)NULL;
|
||||
#if defined(HACK_TERMCAP_MOTION)
|
||||
_rl_term_forward_char = (char *)NULL;
|
||||
#endif
|
||||
@@ -553,6 +630,7 @@ _rl_init_terminal_io (const char *terminal_name)
|
||||
/* Everything below here is used by the redisplay code (tputs). */
|
||||
_rl_screenchars = _rl_screenwidth * _rl_screenheight;
|
||||
_rl_term_cr = "\r";
|
||||
_rl_term_ho = (char *)NULL;
|
||||
_rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
|
||||
_rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
|
||||
_rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
|
||||
@@ -565,8 +643,11 @@ _rl_init_terminal_io (const char *terminal_name)
|
||||
_rl_term_so = _rl_term_se = (char *)NULL;
|
||||
_rl_terminal_can_insert = term_has_meta = 0;
|
||||
|
||||
_rl_term_isansi = 0; /* not an ANSI terminal */
|
||||
|
||||
/* Assume generic unknown terminal can't handle the enable/disable
|
||||
escape sequences */
|
||||
_rl_term_BD = _rl_term_BE = _rl_term_PE = _rl_term_PS = (char *)NULL;
|
||||
_rl_enable_bracketed_paste = 0;
|
||||
|
||||
/* No terminal so/se capabilities. */
|
||||
@@ -625,9 +706,13 @@ _rl_init_terminal_io (const char *terminal_name)
|
||||
bind_termcap_arrow_keys (vi_insertion_keymap);
|
||||
#endif /* VI_MODE */
|
||||
|
||||
if (dumbterm == 0 && _rl_term_isansi == 0)
|
||||
_rl_term_isansi = _rl_check_ansi_terminal (terminal_name);
|
||||
|
||||
/* There's no way to determine whether or not a given terminal supports
|
||||
bracketed paste mode, so we assume a terminal named "dumb" does not. */
|
||||
if (dumbterm)
|
||||
bracketed paste mode, so we assume a non-ANSI terminal (as best as we
|
||||
can determine) does not. */
|
||||
if (_rl_term_isansi == 0)
|
||||
_rl_enable_bracketed_paste = _rl_enable_active_region = 0;
|
||||
|
||||
if (reset_region_colors)
|
||||
|
||||
+510
-18
@@ -1,6 +1,6 @@
|
||||
/* text.c -- text handling commands for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2021,2023-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -85,7 +85,8 @@ int _rl_optimize_typeahead = 1; /* rl_insert tries to read typeahead */
|
||||
int
|
||||
rl_insert_text (const char *string)
|
||||
{
|
||||
register int i, l;
|
||||
register int i;
|
||||
size_t l;
|
||||
|
||||
l = (string && *string) ? strlen (string) : 0;
|
||||
if (l == 0)
|
||||
@@ -704,7 +705,11 @@ static mbstate_t ps = {0};
|
||||
|
||||
/* Insert the character C at the current location, moving point forward.
|
||||
If C introduces a multibyte sequence, we read the whole sequence and
|
||||
then insert the multibyte char into the line buffer. */
|
||||
then insert the multibyte char into the line buffer.
|
||||
If C == 0, we immediately insert any pending partial multibyte character,
|
||||
assuming that we have read a character that doesn't map to self-insert.
|
||||
This doesn't completely handle characters that are part of a multibyte
|
||||
character but map to editing functions. */
|
||||
int
|
||||
_rl_insert_char (int count, int c)
|
||||
{
|
||||
@@ -718,11 +723,28 @@ _rl_insert_char (int count, int c)
|
||||
static int stored_count = 0;
|
||||
#endif
|
||||
|
||||
#if !defined (HANDLE_MULTIBYTE)
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
#else
|
||||
if (count < 0)
|
||||
return 0;
|
||||
if (count == 0)
|
||||
{
|
||||
if (pending_bytes_length == 0)
|
||||
return 0;
|
||||
if (stored_count <= 0)
|
||||
stored_count = count;
|
||||
else
|
||||
count = stored_count;
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX == 1 || rl_byte_oriented)
|
||||
memcpy (incoming, pending_bytes, pending_bytes_length);
|
||||
incoming[pending_bytes_length] = '\0';
|
||||
incoming_length = pending_bytes_length;
|
||||
pending_bytes_length = 0;
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
}
|
||||
else if (MB_CUR_MAX == 1 || rl_byte_oriented)
|
||||
{
|
||||
incoming[0] = c;
|
||||
incoming[1] = '\0';
|
||||
@@ -730,6 +752,9 @@ _rl_insert_char (int count, int c)
|
||||
}
|
||||
else if (_rl_utf8locale && (c & 0x80) == 0)
|
||||
{
|
||||
if (pending_bytes_length)
|
||||
_rl_insert_char (0, 0);
|
||||
|
||||
incoming[0] = c;
|
||||
incoming[1] = '\0';
|
||||
incoming_length = 1;
|
||||
@@ -764,7 +789,8 @@ _rl_insert_char (int count, int c)
|
||||
incoming[1] = '\0';
|
||||
incoming_length = 1;
|
||||
pending_bytes_length--;
|
||||
memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
|
||||
if (pending_bytes_length)
|
||||
memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
|
||||
/* Clear the state of the byte sequence, because in this case the
|
||||
effect of mbstate is undefined. */
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
@@ -827,7 +853,11 @@ _rl_insert_char (int count, int c)
|
||||
rl_insert_text (string);
|
||||
xfree (string);
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
return (pending_bytes_length != 0);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (count > TEXT_COUNT_MAX)
|
||||
@@ -860,6 +890,8 @@ _rl_insert_char (int count, int c)
|
||||
xfree (string);
|
||||
incoming_length = 0;
|
||||
stored_count = 0;
|
||||
|
||||
return (pending_bytes_length != 0);
|
||||
#else /* !HANDLE_MULTIBYTE */
|
||||
char str[TEXT_COUNT_MAX+1];
|
||||
|
||||
@@ -873,9 +905,9 @@ _rl_insert_char (int count, int c)
|
||||
rl_insert_text (str);
|
||||
count -= decreaser;
|
||||
}
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
return 0;
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
}
|
||||
|
||||
if (MB_CUR_MAX == 1 || rl_byte_oriented)
|
||||
@@ -903,9 +935,11 @@ _rl_insert_char (int count, int c)
|
||||
rl_insert_text (incoming);
|
||||
stored_count = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return (pending_bytes_length != 0);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Overwrite the character at point (or next COUNT characters) with C.
|
||||
@@ -983,6 +1017,11 @@ rl_insert (int count, int c)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we didn't insert n and there are pending bytes, we need to insert
|
||||
them if _rl_insert_char didn't do that on its own. */
|
||||
if (r == 1 && rl_insert_mode == RL_IM_INSERT)
|
||||
r = _rl_insert_char (0, 0); /* flush partial multibyte char */
|
||||
|
||||
if (n != (unsigned short)-2) /* -2 = sentinel value for having inserted N */
|
||||
{
|
||||
/* setting rl_pending_input inhibits setting rl_last_func so we do it
|
||||
@@ -992,7 +1031,6 @@ rl_insert (int count, int c)
|
||||
rl_executing_keyseq[rl_key_sequence_length = 0] = '\0';
|
||||
r = rl_execute_next (n);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1054,6 +1092,8 @@ _rl_insert_next_callback (_rl_callback_generic_arg *data)
|
||||
int
|
||||
rl_quoted_insert (int count, int key)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* Let's see...should the callback interface futz with signal handling? */
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
|
||||
@@ -1072,15 +1112,17 @@ rl_quoted_insert (int count, int key)
|
||||
/* A negative count means to quote the next -COUNT characters. */
|
||||
if (count < 0)
|
||||
{
|
||||
int r;
|
||||
|
||||
do
|
||||
r = _rl_insert_next (1);
|
||||
while (r == 0 && ++count < 0);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
r = _rl_insert_next (count);
|
||||
|
||||
return _rl_insert_next (count);
|
||||
if (r == 1)
|
||||
_rl_insert_char (0, 0); /* insert partial multibyte character */
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Insert a tab character. */
|
||||
@@ -1229,11 +1271,12 @@ _rl_rubout_char (int count, int key)
|
||||
c = rl_line_buffer[--rl_point];
|
||||
rl_delete_text (rl_point, orig_point);
|
||||
/* The erase-at-end-of-line hack is of questionable merit now. */
|
||||
if (rl_point == rl_end && ISPRINT ((unsigned char)c) && _rl_last_c_pos)
|
||||
if (rl_point == rl_end && ISPRINT ((unsigned char)c) && _rl_last_c_pos && _rl_last_v_pos == 0)
|
||||
{
|
||||
int l;
|
||||
l = rl_character_len (c, rl_point);
|
||||
_rl_erase_at_end_of_line (l);
|
||||
if (_rl_last_c_pos >= l)
|
||||
_rl_erase_at_end_of_line (l);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1764,8 +1807,7 @@ _rl_char_search (int count, int fdir, int bdir)
|
||||
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
static int
|
||||
_rl_char_search_callback (data)
|
||||
_rl_callback_generic_arg *data;
|
||||
_rl_char_search_callback (_rl_callback_generic_arg *data)
|
||||
{
|
||||
_rl_callback_func = 0;
|
||||
_rl_want_redisplay = 1;
|
||||
@@ -1886,3 +1928,453 @@ rl_mark_active_p (void)
|
||||
{
|
||||
return (mark_active);
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Reading a string entered from the keyboard */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* A very simple set of functions to read a string from the keyboard using
|
||||
the line buffer as temporary storage. The caller can set a completion
|
||||
function to perform completion on TAB and SPACE. */
|
||||
|
||||
/* XXX - this is all very similar to the search stuff but with a different
|
||||
CXT. */
|
||||
|
||||
static HIST_ENTRY *_rl_saved_line_for_readstr;
|
||||
_rl_readstr_cxt *_rl_rscxt;
|
||||
|
||||
_rl_readstr_cxt *
|
||||
_rl_rscxt_alloc (int flags)
|
||||
{
|
||||
_rl_readstr_cxt *cxt;
|
||||
|
||||
cxt = (_rl_readstr_cxt *)xmalloc (sizeof (_rl_readstr_cxt));
|
||||
|
||||
cxt->flags = flags;
|
||||
|
||||
cxt->save_point = rl_point;
|
||||
cxt->save_mark = rl_mark;
|
||||
cxt->save_line = where_history ();
|
||||
|
||||
cxt->prevc = cxt->lastc = 0;
|
||||
|
||||
cxt->compfunc = NULL;
|
||||
|
||||
return cxt;
|
||||
}
|
||||
|
||||
void
|
||||
_rl_rscxt_dispose (_rl_readstr_cxt *cxt, int flags)
|
||||
{
|
||||
xfree (cxt);
|
||||
}
|
||||
|
||||
/* This isn't used yet */
|
||||
void
|
||||
_rl_free_saved_readstr_line ()
|
||||
{
|
||||
if (_rl_saved_line_for_readstr)
|
||||
/* This doesn't free any saved undo list, if it needs to,
|
||||
rl_clear_history shows how to do it. */
|
||||
_rl_free_saved_line (_rl_saved_line_for_readstr);
|
||||
_rl_saved_line_for_readstr = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_rl_unsave_saved_readstr_line ()
|
||||
{
|
||||
if (_rl_saved_line_for_readstr)
|
||||
{
|
||||
_rl_free_undo_list (rl_undo_list);
|
||||
_rl_unsave_line (_rl_saved_line_for_readstr); /* restores rl_undo_list */
|
||||
}
|
||||
_rl_saved_line_for_readstr = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
|
||||
_rl_readstr_cxt *
|
||||
_rl_readstr_init (int pchar, int flags)
|
||||
{
|
||||
_rl_readstr_cxt *cxt;
|
||||
char *p;
|
||||
|
||||
cxt = _rl_rscxt_alloc (flags);
|
||||
|
||||
rl_maybe_replace_line ();
|
||||
_rl_saved_line_for_readstr = _rl_alloc_saved_line ();
|
||||
|
||||
rl_undo_list = 0;
|
||||
|
||||
rl_line_buffer[0] = 0;
|
||||
rl_end = rl_point = 0;
|
||||
|
||||
p = _rl_make_prompt_for_search (pchar ? pchar : '@');
|
||||
cxt->flags |= READSTR_FREEPMT;
|
||||
rl_message ("%s", p);
|
||||
xfree (p);
|
||||
|
||||
RL_SETSTATE (RL_STATE_READSTR);
|
||||
|
||||
_rl_rscxt = cxt;
|
||||
|
||||
return cxt;
|
||||
}
|
||||
|
||||
int
|
||||
_rl_readstr_cleanup (_rl_readstr_cxt *cxt, int r)
|
||||
{
|
||||
_rl_rscxt_dispose (cxt, 0);
|
||||
_rl_rscxt = 0;
|
||||
|
||||
RL_UNSETSTATE (RL_STATE_READSTR);
|
||||
|
||||
return (r != 1);
|
||||
}
|
||||
|
||||
void
|
||||
_rl_readstr_restore (_rl_readstr_cxt *cxt)
|
||||
{
|
||||
_rl_unsave_saved_readstr_line (); /* restores rl_undo_list */
|
||||
rl_point = cxt->save_point;
|
||||
rl_mark = cxt->save_mark;
|
||||
if (cxt->flags & READSTR_FREEPMT)
|
||||
rl_restore_prompt (); /* _rl_make_prompt_for_search saved it */
|
||||
cxt->flags &= ~READSTR_FREEPMT;
|
||||
rl_clear_message ();
|
||||
_rl_fix_point (1);
|
||||
}
|
||||
|
||||
int
|
||||
_rl_readstr_sigcleanup (_rl_readstr_cxt *cxt, int r)
|
||||
{
|
||||
if (cxt->flags & READSTR_FREEPMT)
|
||||
rl_restore_prompt (); /* _rl_make_prompt_for_search saved it */
|
||||
cxt->flags &= ~READSTR_FREEPMT;
|
||||
return (_rl_readstr_cleanup (cxt, r));
|
||||
}
|
||||
|
||||
int
|
||||
_rl_readstr_getchar (_rl_readstr_cxt *cxt)
|
||||
{
|
||||
int c;
|
||||
|
||||
cxt->prevc = cxt->lastc;
|
||||
|
||||
/* Read a key and decide how to proceed. */
|
||||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
c = cxt->lastc = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* This ends up with C (and LASTC) being set to the last byte of the
|
||||
multibyte character. In most cases c == lastc == mb[0] */
|
||||
if (c >= 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
|
||||
#endif
|
||||
|
||||
RL_CHECK_SIGNALS ();
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Process just-read character C according to readstr context CXT. Return -1
|
||||
if the caller should abort the read, 0 if we should break out of the
|
||||
loop, and 1 if we should continue to read characters. This can perform
|
||||
completion on the string read so far (stored in rl_line_buffer) if the
|
||||
caller has set up a completion function. The completion function can
|
||||
return -1 to indicate that we should abort the read. If we return -1
|
||||
we will call _rl_readstr_restore to clean up the state, leaving the caller
|
||||
to free the context. */
|
||||
int
|
||||
_rl_readstr_dispatch (_rl_readstr_cxt *cxt, int c)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (c < 0)
|
||||
c = CTRL ('C');
|
||||
|
||||
/* could consider looking up the function bound to they key and dispatching
|
||||
off that, but you want most characters inserted by default without having
|
||||
to quote. */
|
||||
switch (c)
|
||||
{
|
||||
case CTRL('W'):
|
||||
rl_unix_word_rubout (1, c);
|
||||
break;
|
||||
|
||||
case CTRL('U'):
|
||||
rl_unix_line_discard (1, c);
|
||||
break;
|
||||
|
||||
case CTRL('Q'):
|
||||
case CTRL('V'):
|
||||
n = rl_quoted_insert (1, c);
|
||||
if (n < 0)
|
||||
{
|
||||
_rl_readstr_restore (cxt);
|
||||
return -1;
|
||||
}
|
||||
cxt->lastc = (rl_point > 0) ? rl_line_buffer[rl_point - 1] : rl_line_buffer[0]; /* preserve prevc */
|
||||
break;
|
||||
|
||||
case RETURN:
|
||||
case NEWLINE:
|
||||
return 0;
|
||||
|
||||
case CTRL('H'):
|
||||
case RUBOUT:
|
||||
if (rl_point == 0)
|
||||
{
|
||||
_rl_readstr_restore (cxt);
|
||||
return -1;
|
||||
}
|
||||
_rl_rubout_char (1, c);
|
||||
break;
|
||||
|
||||
case CTRL('C'):
|
||||
case CTRL('G'):
|
||||
rl_ding ();
|
||||
_rl_readstr_restore (cxt);
|
||||
return -1;
|
||||
|
||||
case ESC:
|
||||
/* Allow users to bracketed-paste text into the string.
|
||||
Similar code is in search.c:_rl_nsearch_dispatch(). */
|
||||
if (_rl_enable_bracketed_paste && ((n = _rl_nchars_available ()) >= (BRACK_PASTE_SLEN-1)))
|
||||
{
|
||||
if (_rl_read_bracketed_paste_prefix (c) == 1)
|
||||
rl_bracketed_paste_begin (1, c);
|
||||
else
|
||||
{
|
||||
c = rl_read_key (); /* get the ESC that got pushed back */
|
||||
_rl_insert_char (1, c);
|
||||
}
|
||||
}
|
||||
else
|
||||
_rl_insert_char (1, c);
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
if ((cxt->flags & READSTR_NOSPACE) == 0)
|
||||
{
|
||||
_rl_insert_char (1, c);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case TAB:
|
||||
/* Perform completion if the caller has set a completion function. */
|
||||
n = (cxt->compfunc) ? (*cxt->compfunc) (cxt, c) : _rl_insert_char (1, c);
|
||||
if (n < 0)
|
||||
{
|
||||
_rl_readstr_restore (cxt);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case CTRL('_'):
|
||||
rl_do_undo ();
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
rl_insert_text (cxt->mb);
|
||||
else
|
||||
#endif
|
||||
_rl_insert_char (1, c);
|
||||
break;
|
||||
}
|
||||
|
||||
(*rl_redisplay_function) ();
|
||||
rl_deactivate_mark ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Reading and Executing named commands */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* A completion generator for bindable readline command names. */
|
||||
static char *
|
||||
readcmd_completion_function (const char *text, int state)
|
||||
{
|
||||
static const char **cmdlist = NULL;
|
||||
static size_t lind, nlen;
|
||||
const char *cmdname;
|
||||
|
||||
if (state == 0)
|
||||
{
|
||||
if (cmdlist)
|
||||
free (cmdlist);
|
||||
|
||||
cmdlist = rl_funmap_names ();
|
||||
lind = 0;
|
||||
nlen = RL_STRLEN (text);
|
||||
}
|
||||
if (cmdlist == 0 || cmdlist[lind] == 0)
|
||||
return (char *)NULL;
|
||||
|
||||
while (cmdlist[lind])
|
||||
{
|
||||
cmdname = cmdlist[lind++];
|
||||
if (STREQN (text, cmdname, nlen))
|
||||
return (savestring (cmdname));
|
||||
}
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_display_cmdname_matches (char **matches)
|
||||
{
|
||||
size_t len, max, i;
|
||||
int old;
|
||||
|
||||
old = rl_filename_completion_desired;
|
||||
rl_filename_completion_desired = 0;
|
||||
|
||||
/* There is more than one match. Find out how many there are,
|
||||
and find the maximum printed length of a single entry. */
|
||||
for (max = 0, i = 1; matches[i]; i++)
|
||||
{
|
||||
len = strlen (matches[i]);
|
||||
|
||||
if (len > max)
|
||||
max = len;
|
||||
}
|
||||
len = i - 1;
|
||||
|
||||
rl_display_match_list (matches, len, max);
|
||||
rl_filename_completion_desired = old;
|
||||
|
||||
rl_forced_update_display ();
|
||||
rl_display_fixed = 1;
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_readcmd_complete (_rl_readstr_cxt *cxt, int c)
|
||||
{
|
||||
char **matches;
|
||||
char *prefix;
|
||||
size_t plen;
|
||||
|
||||
matches = rl_completion_matches (rl_line_buffer, readcmd_completion_function);
|
||||
|
||||
if (RL_SIG_RECEIVED())
|
||||
{
|
||||
_rl_free_match_list (matches);
|
||||
matches = 0;
|
||||
RL_CHECK_SIGNALS ();
|
||||
return -1;
|
||||
}
|
||||
else if (matches == 0)
|
||||
rl_ding ();
|
||||
|
||||
/* Whether or not there are multiple matches, we just want to append the
|
||||
new characters in matches[0]. We display possible matches if we didn't
|
||||
append anything. */
|
||||
if (matches)
|
||||
{
|
||||
prefix = matches[0];
|
||||
plen = strlen (prefix);
|
||||
|
||||
if (plen > rl_end)
|
||||
{
|
||||
size_t n;
|
||||
for (n = rl_end; n < plen && prefix[n]; n++)
|
||||
_rl_insert_char (1, prefix[n]);
|
||||
}
|
||||
else if (matches[1])
|
||||
_rl_display_cmdname_matches (matches);
|
||||
_rl_free_match_list (matches);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use the readstr functions to read a bindable command name using the
|
||||
line buffer, with completion. */
|
||||
static char *
|
||||
_rl_read_command_name ()
|
||||
{
|
||||
_rl_readstr_cxt *cxt;
|
||||
char *ret;
|
||||
int c, r;
|
||||
|
||||
cxt = _rl_readstr_init ('!', READSTR_NOSPACE);
|
||||
cxt->compfunc = _rl_readcmd_complete;
|
||||
|
||||
/* skip callback stuff for now */
|
||||
r = 0;
|
||||
while (1)
|
||||
{
|
||||
c = _rl_readstr_getchar (cxt);
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
_rl_readstr_restore (cxt);
|
||||
_rl_readstr_cleanup (cxt, r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (c == 0)
|
||||
break;
|
||||
|
||||
r = _rl_readstr_dispatch (cxt, c);
|
||||
if (r < 0)
|
||||
{
|
||||
_rl_readstr_cleanup (cxt, r);
|
||||
return NULL; /* dispatch function cleans up */
|
||||
}
|
||||
else if (r == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = savestring (rl_line_buffer);
|
||||
|
||||
/* Now restore the original line and perform one final redisplay. */
|
||||
_rl_readstr_restore (cxt);
|
||||
(*rl_redisplay_function) ();
|
||||
|
||||
/* And free up the context. */
|
||||
_rl_readstr_cleanup (cxt, r);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read a command name from the keyboard and execute it as if the bound key
|
||||
sequence had been entered. */
|
||||
int
|
||||
rl_execute_named_command (int count, int key)
|
||||
{
|
||||
char *command;
|
||||
rl_command_func_t *func;
|
||||
int r;
|
||||
|
||||
command = _rl_read_command_name ();
|
||||
if (command == 0 || *command == '\0')
|
||||
return 1;
|
||||
if (func = rl_named_function (command))
|
||||
{
|
||||
int prev, ostate;
|
||||
|
||||
prev = rl_dispatching;
|
||||
ostate = RL_ISSTATE (RL_STATE_DISPATCHING);
|
||||
rl_dispatching = 1;
|
||||
RL_SETSTATE (RL_STATE_DISPATCHING); /* make sure it's set */
|
||||
r = (*func) (count, key);
|
||||
if (ostate == 0)
|
||||
RL_UNSETSTATE (RL_STATE_DISPATCHING); /* unset it if it wasn't set */
|
||||
rl_dispatching = prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
rl_ding ();
|
||||
r = 1;
|
||||
}
|
||||
|
||||
free (command);
|
||||
return r;
|
||||
}
|
||||
|
||||
+7
-14
@@ -1,6 +1,6 @@
|
||||
/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
|
||||
|
||||
/* Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1988-2020,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -68,14 +68,6 @@ extern struct passwd *getpwnam (const char *);
|
||||
#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x))
|
||||
#endif /* !savestring */
|
||||
|
||||
#if !defined (NULL)
|
||||
# if defined (__STDC__)
|
||||
# define NULL ((void *) 0)
|
||||
# else
|
||||
# define NULL 0x0
|
||||
# endif /* !__STDC__ */
|
||||
#endif /* !NULL */
|
||||
|
||||
/* If being compiled as part of bash, these will be satisfied from
|
||||
variables.o. If being compiled as part of readline, they will
|
||||
be satisfied from shell.o. */
|
||||
@@ -160,8 +152,9 @@ tilde_find_prefix (const char *string, int *len)
|
||||
static int
|
||||
tilde_find_suffix (const char *string)
|
||||
{
|
||||
register int i, j, string_len;
|
||||
register char **suffixes;
|
||||
int i, j;
|
||||
size_t string_len;
|
||||
char **suffixes;
|
||||
|
||||
suffixes = tilde_additional_suffixes;
|
||||
string_len = strlen (string);
|
||||
@@ -189,7 +182,7 @@ char *
|
||||
tilde_expand (const char *string)
|
||||
{
|
||||
char *result;
|
||||
int result_size, result_index;
|
||||
size_t result_size, result_index;
|
||||
|
||||
result_index = result_size = 0;
|
||||
if (result = strchr (string, '~'))
|
||||
@@ -200,7 +193,7 @@ tilde_expand (const char *string)
|
||||
/* Scan through STRING expanding tildes as we come to them. */
|
||||
while (1)
|
||||
{
|
||||
register int start, end;
|
||||
int start, end;
|
||||
char *tilde_word, *expansion;
|
||||
int len;
|
||||
|
||||
@@ -318,7 +311,7 @@ static char *
|
||||
glue_prefix_and_suffix (char *prefix, const char *suffix, int suffind)
|
||||
{
|
||||
char *ret;
|
||||
int plen, slen;
|
||||
size_t plen, slen;
|
||||
|
||||
plen = (prefix && *prefix) ? strlen (prefix) : 0;
|
||||
slen = strlen (suffix + suffind);
|
||||
|
||||
+3
-1
@@ -116,12 +116,14 @@ _rl_free_undo_list (UNDO_LIST *ul)
|
||||
void
|
||||
rl_free_undo_list (void)
|
||||
{
|
||||
UNDO_LIST *release, *orig_list;
|
||||
UNDO_LIST *orig_list;
|
||||
|
||||
orig_list = rl_undo_list;
|
||||
_rl_free_undo_list (rl_undo_list);
|
||||
rl_undo_list = (UNDO_LIST *)NULL;
|
||||
_hs_replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
|
||||
if (_rl_saved_line_for_history && (UNDO_LIST *)_rl_saved_line_for_history->data == orig_list)
|
||||
_rl_saved_line_for_history->data = 0;
|
||||
}
|
||||
|
||||
UNDO_LIST *
|
||||
|
||||
+48
-68
@@ -43,8 +43,8 @@
|
||||
#include <ctype.h>
|
||||
|
||||
/* System-specific feature definitions and include files. */
|
||||
#include "rldefs.h"
|
||||
#include "rlmbutil.h"
|
||||
#include "rldefs.h"
|
||||
|
||||
#if defined (TIOCSTAT_IN_SYS_IOCTL)
|
||||
# include <sys/ioctl.h>
|
||||
@@ -229,26 +229,12 @@ rl_tilde_expand (int ignore, int key)
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined (USE_VARARGS)
|
||||
void
|
||||
#if defined (PREFER_STDARG)
|
||||
_rl_ttymsg (const char *format, ...)
|
||||
#else
|
||||
_rl_ttymsg (va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#if defined (PREFER_VARARGS)
|
||||
char *format;
|
||||
#endif
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
fprintf (stderr, "readline: ");
|
||||
vfprintf (stderr, format, args);
|
||||
@@ -261,24 +247,11 @@ _rl_ttymsg (va_alist)
|
||||
}
|
||||
|
||||
void
|
||||
#if defined (PREFER_STDARG)
|
||||
_rl_errmsg (const char *format, ...)
|
||||
#else
|
||||
_rl_errmsg (va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#if defined (PREFER_VARARGS)
|
||||
char *format;
|
||||
#endif
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
fprintf (stderr, "readline: ");
|
||||
vfprintf (stderr, format, args);
|
||||
@@ -288,28 +261,6 @@ _rl_errmsg (va_alist)
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
#else /* !USE_VARARGS */
|
||||
void
|
||||
_rl_ttymsg (format, arg1, arg2)
|
||||
char *format;
|
||||
{
|
||||
fprintf (stderr, "readline: ");
|
||||
fprintf (stderr, format, arg1, arg2);
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
rl_forced_update_display ();
|
||||
}
|
||||
|
||||
void
|
||||
_rl_errmsg (format, arg1, arg2)
|
||||
char *format;
|
||||
{
|
||||
fprintf (stderr, "readline: ");
|
||||
fprintf (stderr, format, arg1, arg2);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
#endif /* !USE_VARARGS */
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* String Utility Functions */
|
||||
@@ -321,7 +272,8 @@ _rl_errmsg (format, arg1, arg2)
|
||||
char *
|
||||
_rl_strindex (const char *s1, const char *s2)
|
||||
{
|
||||
register int i, l, len;
|
||||
int i;
|
||||
size_t l, len;
|
||||
|
||||
for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++)
|
||||
if (_rl_strnicmp (s1 + i, s2, l) == 0)
|
||||
@@ -329,9 +281,10 @@ _rl_strindex (const char *s1, const char *s2)
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRPBRK
|
||||
#if !defined (HAVE_STRPBRK) || defined (HANDLE_MULTIBYTE)
|
||||
/* Find the first occurrence in STRING1 of any character from STRING2.
|
||||
Return a pointer to the character in STRING1. */
|
||||
Return a pointer to the character in STRING1. Understands multibyte
|
||||
characters. */
|
||||
char *
|
||||
_rl_strpbrk (const char *string1, const char *string2)
|
||||
{
|
||||
@@ -417,6 +370,48 @@ _rl_stricmp (const char *string1, const char *string2)
|
||||
}
|
||||
#endif /* !HAVE_STRCASECMP */
|
||||
|
||||
/* Compare the first N characters of S1 and S2 without regard to case. If
|
||||
FLAGS&1, apply the mapping specified by completion-map-case and make
|
||||
`-' and `_' equivalent. Returns 1 if the strings are equal. */
|
||||
int
|
||||
_rl_strcaseeqn(const char *s1, const char *s2, size_t n, int flags)
|
||||
{
|
||||
int c1, c2;
|
||||
int d;
|
||||
|
||||
if ((flags & 1) == 0)
|
||||
return (_rl_strnicmp (s1, s2, n) == 0);
|
||||
|
||||
do
|
||||
{
|
||||
c1 = _rl_to_lower (*s1);
|
||||
c2 = _rl_to_lower (*s2);
|
||||
|
||||
d = c1 - c2;
|
||||
if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
|
||||
d = 0; /* case insensitive character mapping */
|
||||
if (d != 0)
|
||||
return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
n--;
|
||||
}
|
||||
while (n != 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return 1 if the characters C1 and C2 are equal without regard to case.
|
||||
If FLAGS&1, apply the mapping specified by completion-map-case and make
|
||||
`-' and `_' equivalent. */
|
||||
int
|
||||
_rl_charcasecmp (int c1, int c2, int flags)
|
||||
{
|
||||
if ((flags & 1) && (c1 == '-' || c1 == '_') && (c2 == '-' || c2 == '_'))
|
||||
return 1;
|
||||
return ( _rl_to_lower (c1) == _rl_to_lower (c2));
|
||||
}
|
||||
|
||||
/* Stupid comparison routine for qsort () ing strings. */
|
||||
int
|
||||
_rl_qsort_string_compare (char **s1, char **s2)
|
||||
@@ -464,28 +459,14 @@ _rl_savestring (const char *s)
|
||||
}
|
||||
|
||||
#if defined (DEBUG)
|
||||
#if defined (USE_VARARGS)
|
||||
static FILE *_rl_tracefp;
|
||||
|
||||
void
|
||||
#if defined (PREFER_STDARG)
|
||||
_rl_trace (const char *format, ...)
|
||||
#else
|
||||
_rl_trace (va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#if defined (PREFER_VARARGS)
|
||||
char *format;
|
||||
#endif
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
if (_rl_tracefp == 0)
|
||||
_rl_tropen ();
|
||||
@@ -531,7 +512,6 @@ _rl_settracefp (FILE *fp)
|
||||
{
|
||||
_rl_tracefp = fp;
|
||||
}
|
||||
#endif
|
||||
#endif /* DEBUG */
|
||||
|
||||
|
||||
|
||||
+69
-14
@@ -1,7 +1,7 @@
|
||||
/* vi_mode.c -- A vi emulation mode for Bash.
|
||||
Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
|
||||
|
||||
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2021,2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -76,6 +76,10 @@
|
||||
#define INCREMENT_POS(start) (start)++
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
/* Flags for the motion context */
|
||||
#define MOVE_SUCCESS 0
|
||||
#define MOVE_FAILED 0x01
|
||||
|
||||
/* This is global so other parts of the code can check whether the last
|
||||
command was a text modification command. */
|
||||
int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
|
||||
@@ -101,9 +105,8 @@ static int vi_replace_count;
|
||||
/* If non-zero, we have text inserted after a c[motion] command that put
|
||||
us implicitly into insert mode. Some people want this text to be
|
||||
attached to the command so that it is `redoable' with `.'. */
|
||||
static int vi_continued_command;
|
||||
static char *vi_insert_buffer;
|
||||
static int vi_insert_buffer_size;
|
||||
static size_t vi_insert_buffer_size;
|
||||
|
||||
static int _rl_vi_last_repeat = 1;
|
||||
static int _rl_vi_last_arg_sign = 1;
|
||||
@@ -364,12 +367,12 @@ rl_vi_search (int count, int key)
|
||||
switch (key)
|
||||
{
|
||||
case '?':
|
||||
_rl_free_saved_history_line ();
|
||||
_rl_free_saved_search_line (); /* just in case */
|
||||
rl_noninc_forward_search (count, key);
|
||||
break;
|
||||
|
||||
case '/':
|
||||
_rl_free_saved_history_line ();
|
||||
_rl_free_saved_search_line ();
|
||||
rl_noninc_reverse_search (count, key);
|
||||
break;
|
||||
|
||||
@@ -1087,6 +1090,7 @@ _rl_vi_arg_dispatch (int c)
|
||||
}
|
||||
else
|
||||
{
|
||||
rl_restore_prompt ();
|
||||
rl_clear_message ();
|
||||
rl_stuff_char (key);
|
||||
return 0; /* done */
|
||||
@@ -1150,10 +1154,27 @@ _rl_mvcxt_dispose (_rl_vimotion_cxt *m)
|
||||
xfree (m);
|
||||
}
|
||||
|
||||
static inline int
|
||||
vi_charsearch_command (int c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 't':
|
||||
case 'T':
|
||||
case ';':
|
||||
case ',':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
rl_domove_motion_callback (_rl_vimotion_cxt *m)
|
||||
{
|
||||
int c;
|
||||
int c, r, opoint;
|
||||
|
||||
_rl_vi_last_motion = c = m->motion;
|
||||
|
||||
@@ -1163,8 +1184,15 @@ rl_domove_motion_callback (_rl_vimotion_cxt *m)
|
||||
rl_extend_line_buffer (rl_end + 1);
|
||||
rl_line_buffer[rl_end++] = ' ';
|
||||
rl_line_buffer[rl_end] = '\0';
|
||||
opoint = rl_point;
|
||||
|
||||
_rl_dispatch (c, _rl_keymap);
|
||||
r = _rl_dispatch (c, _rl_keymap);
|
||||
|
||||
/* Note in the context that the motion command failed. Right now we only do
|
||||
this for unsuccessful searches (ones where _rl_dispatch returns non-zero
|
||||
and point doesn't move). */
|
||||
if (r != 0 && rl_point == opoint && vi_charsearch_command (c))
|
||||
m->flags |= MOVE_FAILED;
|
||||
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK))
|
||||
@@ -1199,7 +1227,15 @@ _rl_vi_domove_motion_cleanup (int c, _rl_vimotion_cxt *m)
|
||||
{
|
||||
/* 'c' and 'C' enter insert mode after the delete even if the motion
|
||||
didn't delete anything, as long as the motion command is valid. */
|
||||
if (_rl_to_upper (m->key) == 'C' && _rl_vi_motion_command (c))
|
||||
if (_rl_to_upper (m->key) == 'C' && _rl_vi_motion_command (c) && (m->flags & MOVE_FAILED) == 0)
|
||||
return (vidomove_dispatch (m));
|
||||
/* 'd' and 'D' must delete at least one character even if the motion
|
||||
command doesn't move the cursor. */
|
||||
if (_rl_to_upper (m->key) == 'D' && _rl_vi_motion_command (c) && (m->flags & MOVE_FAILED) == 0)
|
||||
return (vidomove_dispatch (m));
|
||||
/* 'y' and 'Y' must yank at least one character even if the motion
|
||||
command doean't move the cursor. */
|
||||
if (_rl_to_upper (m->key) == 'Y' && _rl_vi_motion_command (c) && (m->flags & MOVE_FAILED) == 0)
|
||||
return (vidomove_dispatch (m));
|
||||
RL_UNSETSTATE (RL_STATE_VIMOTION);
|
||||
return (-1);
|
||||
@@ -1285,7 +1321,7 @@ rl_domove_read_callback (_rl_vimotion_cxt *m)
|
||||
/* Readine vi motion char starting numeric argument */
|
||||
else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
|
||||
{
|
||||
RL_SETSTATE (RL_STATE_NUMERICARG);
|
||||
_rl_arg_init ();
|
||||
return (_rl_vi_arg_dispatch (c));
|
||||
}
|
||||
#endif
|
||||
@@ -1295,7 +1331,7 @@ rl_domove_read_callback (_rl_vimotion_cxt *m)
|
||||
save = rl_numeric_arg;
|
||||
rl_numeric_arg = _rl_digit_value (c);
|
||||
rl_explicit_arg = 1;
|
||||
RL_SETSTATE (RL_STATE_NUMERICARG);
|
||||
_rl_arg_init ();
|
||||
rl_digit_loop1 ();
|
||||
rl_numeric_arg *= save;
|
||||
c = rl_vi_domove_getchar (m);
|
||||
@@ -1304,6 +1340,13 @@ rl_domove_read_callback (_rl_vimotion_cxt *m)
|
||||
m->motion = 0;
|
||||
return -1;
|
||||
}
|
||||
else if (member (c, vi_motion) == 0)
|
||||
{
|
||||
m->motion = 0;
|
||||
RL_UNSETSTATE (RL_STATE_VIMOTION);
|
||||
RL_UNSETSTATE (RL_STATE_NUMERICARG);
|
||||
return (1);
|
||||
}
|
||||
m->motion = c;
|
||||
return (rl_domove_motion_callback (m));
|
||||
}
|
||||
@@ -1328,6 +1371,7 @@ _rl_vi_domove_callback (_rl_vimotion_cxt *m)
|
||||
int c, r;
|
||||
|
||||
m->motion = c = rl_vi_domove_getchar (m);
|
||||
|
||||
if (c < 0)
|
||||
return 1; /* EOF */
|
||||
r = rl_domove_read_callback (m);
|
||||
@@ -1340,7 +1384,6 @@ _rl_vi_domove_callback (_rl_vimotion_cxt *m)
|
||||
int
|
||||
rl_vi_domove (int x, int *ignore)
|
||||
{
|
||||
int r;
|
||||
_rl_vimotion_cxt *m;
|
||||
|
||||
m = _rl_vimvcxt;
|
||||
@@ -1381,7 +1424,11 @@ rl_vi_delete_to (int count, int key)
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
|
||||
}
|
||||
else if (_rl_vimvcxt)
|
||||
_rl_mvcxt_init (_rl_vimvcxt, VIM_DELETE, key);
|
||||
{
|
||||
/* are we being called recursively or by `y' or `c'? */
|
||||
savecxt = _rl_vimvcxt;
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
|
||||
}
|
||||
else
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
|
||||
|
||||
@@ -1480,7 +1527,11 @@ rl_vi_change_to (int count, int key)
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
|
||||
}
|
||||
else if (_rl_vimvcxt)
|
||||
_rl_mvcxt_init (_rl_vimvcxt, VIM_CHANGE, key);
|
||||
{
|
||||
/* are we being called recursively or by `y' or `d'? */
|
||||
savecxt = _rl_vimvcxt;
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
|
||||
}
|
||||
else
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
|
||||
_rl_vimvcxt->start = rl_point;
|
||||
@@ -1559,7 +1610,11 @@ rl_vi_yank_to (int count, int key)
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
|
||||
}
|
||||
else if (_rl_vimvcxt)
|
||||
_rl_mvcxt_init (_rl_vimvcxt, VIM_YANK, key);
|
||||
{
|
||||
/* are we being called recursively or by `c' or `d'? */
|
||||
savecxt = _rl_vimvcxt;
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
|
||||
}
|
||||
else
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
|
||||
_rl_vimvcxt->start = rl_point;
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
/* **************************************************************** */
|
||||
|
||||
static void
|
||||
memory_error_and_abort (char *fname)
|
||||
memory_error_and_abort (const char * const fname)
|
||||
{
|
||||
fprintf (stderr, "%s: out of virtual memory\n", fname);
|
||||
exit (2);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* xmalloc.h -- memory allocation that aborts on errors. */
|
||||
|
||||
/* Copyright (C) 1999-2009,2010-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999-2009,2010-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -29,13 +29,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef PTR_T
|
||||
|
||||
#ifdef __STDC__
|
||||
# define PTR_T void *
|
||||
#else
|
||||
# define PTR_T char *
|
||||
#endif
|
||||
|
||||
# define PTR_T void *
|
||||
#endif /* !PTR_T */
|
||||
|
||||
extern PTR_T xmalloc (size_t);
|
||||
|
||||
Reference in New Issue
Block a user