/* complete.c -- filename completion for readline. */
-/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
+/* Copyright (C) 1987-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.
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
if (do_replace != NO_MATCH && rl_filename_quoting_function)
replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
}
+
return (replacement);
}
char *
rl_username_completion_function (const char *text, int state)
{
-#if defined (__WIN32__) || defined (__OPENNT)
+#if defined (_WIN32) || defined (__OPENNT)
return (char *)NULL;
-#else /* !__WIN32__ && !__OPENNT) */
+#else /* !_WIN32 && !__OPENNT) */
static char *username = (char *)NULL;
static struct passwd *entry;
static int namelen, first_char, first_char_loc;
return (value);
}
-#endif /* !__WIN32__ && !__OPENNT */
+#endif /* !_WIN32 && !__OPENNT */
}
/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
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
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);
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;
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;
{
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
*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;
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 */
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;
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
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;
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);
_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)
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;
}
/* 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
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
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
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)
/* 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
}
/* 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);
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;
}
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 &&
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;
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
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;
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;
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 *
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)
/* 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); */