diff options
Diffstat (limited to 'readline/display.c')
-rw-r--r-- | readline/display.c | 641 |
1 files changed, 471 insertions, 170 deletions
diff --git a/readline/display.c b/readline/display.c index 575b0ad..7653d87 100644 --- a/readline/display.c +++ b/readline/display.c @@ -1,24 +1,24 @@ /* display.c -- readline redisplay facility. */ -/* Copyright (C) 1987-2005 Free Software Foundation, Inc. +/* Copyright (C) 1987-2009 Free Software Foundation, Inc. - This file is part of the GNU Readline Library, a library for - reading lines of text with interactive input and history editing. + This file is part of the GNU Readline Library (Readline), a library + for reading lines of text with interactive input and history editing. - The GNU Readline Library is free software; you can redistribute it - and/or modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2, or + Readline is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - The GNU Readline Library is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY; without even the implied warranty - of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + Readline is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - The GNU General Public License is often shipped with GNU software, and - is generally kept in a file called COPYING or LICENSE. If you do not - have a copy of the license, write to the Free Software Foundation, - 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + You should have received a copy of the GNU General Public License + along with Readline. If not, see <http://www.gnu.org/licenses/>. +*/ + #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -63,30 +63,59 @@ extern char *strchr (), *strrchr (); #endif /* !strchr && !__STDC__ */ -#if defined (HACK_TERMCAP_MOTION) -extern char *_rl_term_forward_char; -#endif - static void update_line PARAMS((char *, char *, int, int, int, int)); static void space_to_eol PARAMS((int)); static void delete_chars PARAMS((int)); static void insert_some_chars PARAMS((char *, int, int)); static void cr PARAMS((void)); +/* State of visible and invisible lines. */ +struct line_state + { + char *line; + int *lbreaks; + int lbsize; #if defined (HANDLE_MULTIBYTE) -static int _rl_col_width PARAMS((const char *, int, int)); -static int *_rl_wrapped_line; -#else -# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s)) + int *wrapped_line; + int wbsize; #endif + }; + +/* The line display buffers. One is the line currently displayed on + the screen. The other is the line about to be displayed. */ +static struct line_state line_state_array[2]; +static struct line_state *line_state_visible = &line_state_array[0]; +static struct line_state *line_state_invisible = &line_state_array[1]; +static int line_structures_initialized = 0; -static int *inv_lbreaks, *vis_lbreaks; -static int inv_lbsize, vis_lbsize; +/* Backwards-compatible names. */ +#define inv_lbreaks (line_state_invisible->lbreaks) +#define inv_lbsize (line_state_invisible->lbsize) +#define vis_lbreaks (line_state_visible->lbreaks) +#define vis_lbsize (line_state_visible->lbsize) + +#define visible_line (line_state_visible->line) +#define invisible_line (line_state_invisible->line) + +#if defined (HANDLE_MULTIBYTE) +static int _rl_col_width PARAMS((const char *, int, int, int)); +#else +# define _rl_col_width(l, s, e, f) (((e) <= (s)) ? 0 : (e) - (s)) +#endif /* Heuristic used to decide whether it is faster to move from CUR to NEW - by backing up or outputting a carriage return and moving forward. */ + by backing up or outputting a carriage return and moving forward. CUR + and NEW are either both buffer positions or absolute screen positions. */ #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new))) +/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a + buffer index in others. This macro is used when deciding whether the + current cursor position is in the middle of a prompt string containing + invisible characters. XXX - might need to take `modmark' into account. */ +#define PROMPT_ENDING_INDEX \ + ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1) + + /* **************************************************************** */ /* */ /* Display stuff */ @@ -139,6 +168,8 @@ int _rl_last_c_pos = 0; int _rl_last_v_pos = 0; static int cpos_adjusted; +static int cpos_buffer_position; +static int prompt_multibyte_chars; /* Number of lines currently on screen minus 1. */ int _rl_vis_botlin = 0; @@ -148,11 +179,6 @@ int _rl_vis_botlin = 0; doing horizontal scrolling. It shifts in thirds of a screenwidth. */ static int last_lmargin; -/* The line display buffers. One is the line currently displayed on - the screen. The other is the line about to be displayed. */ -static char *visible_line = (char *)NULL; -static char *invisible_line = (char *)NULL; - /* A buffer for `modeline' messages. */ static char msg_buf[128]; @@ -166,6 +192,7 @@ static int line_size = 1024; include invisible characters. */ static char *local_prompt, *local_prompt_prefix; +static int local_prompt_len; static int prompt_visible_length, prompt_prefix_length; /* The number of invisible characters in the line currently being @@ -192,6 +219,10 @@ static int prompt_last_screen_line; static int prompt_physical_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; + /* Variables to save and restore prompt and display information. */ /* These are getting numerous enough that it's time to create a struct. */ @@ -201,6 +232,7 @@ static char *saved_local_prefix; static int saved_last_invisible; static int saved_visible_length; static int saved_prefix_length; +static int saved_local_length; static int saved_invis_chars_first_line; static int saved_physical_chars; @@ -224,7 +256,7 @@ expand_prompt (pmt, lp, lip, niflp, vlp) char *pmt; int *lp, *lip, *niflp, *vlp; { - char *r, *ret, *p; + char *r, *ret, *p, *igstart; int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars; /* Short-circuit if we can. */ @@ -248,19 +280,21 @@ expand_prompt (pmt, lp, lip, niflp, vlp) invfl = 0; /* invisible chars in first line of prompt */ invflset = 0; /* we only want to set invfl once */ + igstart = 0; for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++) { /* This code strips the invisible character string markers RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ - if (*p == RL_PROMPT_START_IGNORE) + if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */ { - ignoring++; + ignoring = 1; + igstart = p; continue; } else if (ignoring && *p == RL_PROMPT_END_IGNORE) { ignoring = 0; - if (p[-1] != RL_PROMPT_START_IGNORE) + if (p != (igstart + 1)) last = r - ret - 1; continue; } @@ -276,8 +310,13 @@ expand_prompt (pmt, lp, lip, niflp, vlp) *r++ = *p++; if (!ignoring) { + /* rl ends up being assigned to prompt_visible_length, + which is the number of characters in the buffer that + contribute to characters on the screen, which might + not be the same as the number of physical characters + on the screen in the presence of multibyte characters */ rl += ind - pind; - physchars += _rl_col_width (pmt, pind, ind); + physchars += _rl_col_width (pmt, pind, ind, 0); } else ninvis += ind - pind; @@ -360,6 +399,7 @@ rl_expand_prompt (prompt) FREE (local_prompt_prefix); 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; @@ -375,6 +415,7 @@ rl_expand_prompt (prompt) &prompt_invis_chars_first_line, &prompt_physical_chars); local_prompt_prefix = (char *)0; + local_prompt_len = local_prompt ? strlen (local_prompt) : 0; return (prompt_visible_length); } else @@ -383,16 +424,17 @@ rl_expand_prompt (prompt) t = ++p; local_prompt = expand_prompt (p, &prompt_visible_length, &prompt_last_invisible, - (int *)NULL, + &prompt_invis_chars_first_line, &prompt_physical_chars); c = *t; *t = '\0'; /* The portion of the prompt string up to and including the final newline is now null-terminated. */ local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length, (int *)NULL, - &prompt_invis_chars_first_line, + (int *)NULL, (int *)NULL); *t = c; + local_prompt_len = local_prompt ? strlen (local_prompt) : 0; return (prompt_prefix_length); } } @@ -434,13 +476,21 @@ init_line_structures (minsize) { /* should be enough. */ inv_lbsize = vis_lbsize = 256; - inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int)); - vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int)); + #if defined (HANDLE_MULTIBYTE) - _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int)); + line_state_visible->wbsize = vis_lbsize; + line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int)); + + line_state_invisible->wbsize = inv_lbsize; + line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int)); #endif + + inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int)); + vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int)); inv_lbreaks[0] = vis_lbreaks[0] = 0; } + + line_structures_initialized = 1; } /* Basic redisplay algorithm. */ @@ -449,8 +499,8 @@ rl_redisplay () { register int in, out, c, linenum, cursor_linenum; register char *line; - int c_pos, inv_botlin, lb_botlin, lb_linenum, o_cpos; - int newlines, lpos, temp, modmark, n0, num; + int inv_botlin, lb_botlin, lb_linenum, o_cpos; + int newlines, lpos, temp, n0, num, prompt_lines_estimate; char *prompt_this_line; #if defined (HANDLE_MULTIBYTE) wchar_t wc; @@ -460,24 +510,27 @@ rl_redisplay () int _rl_wrapped_multicolumn = 0; #endif - if (!readline_echoing_p) + if (_rl_echoing_p == 0) return; - /* Signals are blocked through this function as the global data structures - could get corrupted upon modifications from an invoked signal handler. */ - _rl_block_sigint (); + /* Block keyboard interrupts because this function manipulates global + data structures. */ + _rl_block_sigint (); + RL_SETSTATE (RL_STATE_REDISPLAYING); if (!rl_display_prompt) rl_display_prompt = ""; - if (invisible_line == 0 || vis_lbreaks == 0) + if (line_structures_initialized == 0) { init_line_structures (0); rl_on_new_line (); } /* Draw the line into the buffer. */ - c_pos = -1; + cpos_buffer_position = -1; + + prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars; line = invisible_line; out = inv_botlin = 0; @@ -504,24 +557,23 @@ rl_redisplay () number of non-visible characters in the prompt string. */ if (rl_display_prompt == rl_prompt || local_prompt) { - int local_len = local_prompt ? strlen (local_prompt) : 0; if (local_prompt_prefix && forced_display) _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix)); - if (local_len > 0) + if (local_prompt_len > 0) { - temp = local_len + out + 2; + temp = local_prompt_len + out + 2; if (temp >= line_size) { line_size = (temp + 1024) - (temp % 1024); visible_line = (char *)xrealloc (visible_line, line_size); line = invisible_line = (char *)xrealloc (invisible_line, line_size); } - strncpy (line + out, local_prompt, local_len); - out += local_len; + strncpy (line + out, local_prompt, local_prompt_len); + out += local_prompt_len; } line[out] = '\0'; - wrap_offset = local_len - prompt_visible_length; + wrap_offset = local_prompt_len - prompt_visible_length; } else { @@ -576,10 +628,14 @@ rl_redisplay () { \ inv_lbsize *= 2; \ inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ - _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \ } \ inv_lbreaks[++newlines] = out; \ - _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \ + if (newlines >= (line_state_invisible->wbsize - 1)) \ + { \ + line_state_invisible->wbsize *= 2; \ + line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \ + } \ + line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \ lpos = 0; \ } \ } while (0) @@ -602,26 +658,26 @@ rl_redisplay () /* inv_lbreaks[i] is where line i starts in the buffer. */ inv_lbreaks[newlines = 0] = 0; -#if 0 - lpos = out - wrap_offset; -#else lpos = prompt_physical_chars + modmark; -#endif #if defined (HANDLE_MULTIBYTE) - memset (_rl_wrapped_line, 0, vis_lbsize); + memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int)); num = 0; #endif /* prompt_invis_chars_first_line is the number of invisible characters in the first physical line of the prompt. wrap_offset - prompt_invis_chars_first_line is the number of invis - chars on the second line. */ + chars on the second (or, more generally, last) line. */ + + /* This is zero-based, used to set the newlines */ + prompt_lines_estimate = lpos / _rl_screenwidth; /* what if lpos is already >= _rl_screenwidth before we start drawing the contents of the command line? */ while (lpos >= _rl_screenwidth) { + int z; /* fix from Darin Johnson <darin@acuson.com> for prompt string with invisible characters that is longer than the screen width. The prompt_invis_chars_first_line variable could be made into an array @@ -630,37 +686,48 @@ rl_redisplay () prompts that exceed two physical lines? Additional logic fix from Edward Catmur <ed@catmur.co.uk> */ #if defined (HANDLE_MULTIBYTE) - n0 = num; - temp = local_prompt ? strlen (local_prompt) : 0; - while (num < temp) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0) { - if (_rl_col_width (local_prompt, n0, num) > _rl_screenwidth) + n0 = num; + temp = local_prompt_len; + while (num < temp) { - num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY); - break; + z = _rl_col_width (local_prompt, n0, num, 1); + if (z > _rl_screenwidth) + { + num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY); + break; + } + else if (z == _rl_screenwidth) + break; + num++; } - num++; + temp = num; } - temp = num + -#else - temp = ((newlines + 1) * _rl_screenwidth) + + else #endif /* !HANDLE_MULTIBYTE */ - ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line - : ((newlines == 1) ? wrap_offset : 0)) - : ((newlines == 0) ? wrap_offset :0)); + temp = ((newlines + 1) * _rl_screenwidth); + + /* Now account for invisible characters in the current line. */ + /* XXX - this assumes that the invisible characters may be split, but only + between the first and the last lines. */ + temp += ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line + : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line)) + : ((newlines == 0) ? wrap_offset : 0)); inv_lbreaks[++newlines] = temp; #if defined (HANDLE_MULTIBYTE) - lpos -= _rl_col_width (local_prompt, n0, num); -#else - lpos -= _rl_screenwidth; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0) + lpos -= _rl_col_width (local_prompt, n0, num, 1); + else #endif + lpos -= _rl_screenwidth; } prompt_last_screen_line = newlines; /* Draw the rest of the line (after the prompt) into invisible_line, keeping - track of where the cursor is (c_pos), the number of the line containing + track of where the cursor is (cpos_buffer_position), the number of the line containing the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin). It maintains an array of line breaks for display (inv_lbreaks). This handles expanding tabs for display and displaying meta characters. */ @@ -670,6 +737,7 @@ rl_redisplay () if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { memset (&ps, 0, sizeof (mbstate_t)); + /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */ wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps); } else @@ -713,7 +781,7 @@ rl_redisplay () if (in == rl_point) { - c_pos = out; + cpos_buffer_position = out; lb_linenum = newlines; } @@ -807,7 +875,7 @@ rl_redisplay () } if (in == rl_point) { - c_pos = out; + cpos_buffer_position = out; lb_linenum = newlines; } for (i = in; i < in+wc_bytes; i++) @@ -830,6 +898,7 @@ rl_redisplay () if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { in += wc_bytes; + /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */ wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps); } else @@ -838,9 +907,9 @@ rl_redisplay () } line[out] = '\0'; - if (c_pos < 0) + if (cpos_buffer_position < 0) { - c_pos = out; + cpos_buffer_position = out; lb_linenum = newlines; } @@ -849,7 +918,7 @@ rl_redisplay () inv_lbreaks[newlines+1] = out; cursor_linenum = lb_linenum; - /* C_POS == position in buffer where cursor should be placed. + /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed. CURSOR_LINENUM == line number where the cursor should be placed. */ /* PWP: now is when things get a bit hairy. The visible and invisible @@ -884,6 +953,10 @@ rl_redisplay () 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]) @@ -891,9 +964,16 @@ rl_redisplay () #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) #define INV_LINE(line) (invisible_line + 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) + /* For each line in the buffer, do the updating display. */ for (linenum = 0; linenum <= inv_botlin; linenum++) { + /* 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; cpos_adjusted = 0; update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, @@ -903,16 +983,22 @@ rl_redisplay () take invisible characters into account, since _rl_last_c_pos is an absolute cursor position in a multibyte locale. See if compensating here is the right thing, or if we have to - change update_line itself. There is one case in which + change update_line itself. There are several cases in which update_line adjusts _rl_last_c_pos itself (so it can pass _rl_move_cursor_relative accurate values); it communicates - this back by setting cpos_adjusted */ - if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && - cpos_adjusted == 0 && - _rl_last_c_pos != o_cpos && - _rl_last_c_pos > wrap_offset && - o_cpos < prompt_last_invisible) - _rl_last_c_pos -= wrap_offset; + this back by setting cpos_adjusted. If we assume that + _rl_last_c_pos is correct (an absolute cursor position) each + time update_line is called, then we can assume in our + calculations that o_cpos does not need to be adjusted by + wrap_offset. */ + if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT()) + _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */ + else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth && + (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && + cpos_adjusted == 0 && + _rl_last_c_pos != o_cpos && + _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line)) + _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line); /* If this is the line with the prompt, we might need to compensate for invisible characters in the new line. Do @@ -932,6 +1018,19 @@ rl_redisplay () if (nleft) _rl_clear_to_eol (nleft); } +#if 0 + /* This segment is intended to handle the case where the prompt + has invisible characters on the second line and the new line + to be displayed needs to clear the rest of the old characters + out (e.g., when printing the i-search prompt). In general, + the case of the new line being shorter than the old. + Incomplete */ + else if (linenum == prompt_last_screen_line && + prompt_physical_chars > _rl_screenwidth && + wrap_offset != prompt_invis_chars_first_line && + _rl_last_c_pos == out && +#endif + /* Since the new first line is now visible, save its length. */ if (linenum == 0) @@ -975,7 +1074,11 @@ rl_redisplay () invisible character in the prompt string. */ nleft = prompt_visible_length + wrap_offset; if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && - _rl_last_c_pos <= prompt_last_invisible && local_prompt) +#if 0 + _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt) +#else + _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt) +#endif { #if defined (__MSDOS__) putc ('\r', rl_outstream); @@ -983,19 +1086,22 @@ rl_redisplay () if (_rl_term_cr) tputs (_rl_term_cr, 1, _rl_output_character_function); #endif + if (modmark) + _rl_output_some_chars ("*", 1); + _rl_output_some_chars (local_prompt, nleft); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset; + _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark; else - _rl_last_c_pos = nleft; + _rl_last_c_pos = nleft + modmark; } /* Where on that line? And where does that line start in the buffer? */ pos = inv_lbreaks[cursor_linenum]; /* nleft == number of characters in the line buffer between the - start of the line and the cursor position. */ - nleft = c_pos - pos; + start of the line and the desired cursor position. */ + nleft = cpos_buffer_position - pos; /* NLEFT is now a number of characters in a buffer. When in a multibyte locale, however, _rl_last_c_pos is an absolute cursor @@ -1007,11 +1113,12 @@ rl_redisplay () those characters here and call _rl_backspace() directly. */ if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) { + /* TX == new physical cursor position in multibyte locale. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset; + tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset; else tx = nleft; - if (_rl_last_c_pos > tx) + if (tx >= 0 && _rl_last_c_pos > tx) { _rl_backspace (_rl_last_c_pos - tx); /* XXX */ _rl_last_c_pos = tx; @@ -1040,11 +1147,11 @@ rl_redisplay () will be LMARGIN. */ /* The number of characters that will be displayed before the cursor. */ - ndisp = c_pos - wrap_offset; + ndisp = cpos_buffer_position - wrap_offset; nleft = prompt_visible_length + wrap_offset; /* Where the new cursor position will be on the screen. This can be longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ - phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset); + phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset); t = _rl_screenwidth / 3; /* If the number of characters had already exceeded the screenwidth, @@ -1055,7 +1162,7 @@ rl_redisplay () two-thirds of the way across the screen. */ if (phys_c_pos > _rl_screenwidth - 2) { - lmargin = c_pos - (2 * t); + lmargin = cpos_buffer_position - (2 * t); if (lmargin < 0) lmargin = 0; /* If the left margin would be in the middle of a prompt with @@ -1069,7 +1176,7 @@ rl_redisplay () { /* If we are moving back towards the beginning of the line and the last margin is no longer correct, compute a new one. */ - lmargin = ((c_pos - 1) / t) * t; /* XXX */ + lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */ if (wrap_offset && lmargin > 0 && lmargin < nleft) lmargin = nleft; } @@ -1089,9 +1196,11 @@ rl_redisplay () if (t < out) line[t - 1] = '>'; - if (!rl_display_fixed || forced_display || lmargin != last_lmargin) + if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin) { forced_display = 0; + o_cpos = _rl_last_c_pos; + cpos_adjusted = 0; update_line (&visible_line[last_lmargin], &invisible_line[lmargin], 0, @@ -1099,6 +1208,9 @@ rl_redisplay () _rl_screenwidth + (lmargin ? 0 : wrap_offset), 0); + if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT()) + _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */ + /* If the visible new line is shorter than the old, but the number of invisible characters is greater, and we are at the end of the new line, we need to clear to eol. */ @@ -1114,7 +1226,7 @@ rl_redisplay () if (visible_first_line_len > _rl_screenwidth) visible_first_line_len = _rl_screenwidth; - _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]); + _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]); last_lmargin = lmargin; } } @@ -1122,17 +1234,10 @@ rl_redisplay () /* Swap visible and non-visible lines. */ { - char *vtemp = visible_line; - int *itemp = vis_lbreaks, ntemp = vis_lbsize; - - visible_line = invisible_line; - invisible_line = vtemp; + struct line_state *vtemp = line_state_visible; - vis_lbreaks = inv_lbreaks; - inv_lbreaks = itemp; - - vis_lbsize = inv_lbsize; - inv_lbsize = ntemp; + line_state_visible = line_state_invisible; + line_state_invisible = vtemp; rl_display_fixed = 0; /* If we are displaying on a single line, and last_lmargin is > 0, we @@ -1144,6 +1249,7 @@ rl_redisplay () visible_wrap_offset = wrap_offset; } + RL_UNSETSTATE (RL_STATE_REDISPLAYING); _rl_release_sigint (); } @@ -1169,12 +1275,12 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) int current_line, omax, nmax, inv_botlin; { register char *ofd, *ols, *oe, *nfd, *nls, *ne; - int temp, lendiff, wsatend, od, nd; + int temp, lendiff, wsatend, od, nd, twidth, o_cpos; int current_invis_chars; int col_lendiff, col_temp; #if defined (HANDLE_MULTIBYTE) mbstate_t ps_new, ps_old; - int new_offset, old_offset, tmp; + int new_offset, old_offset; #endif /* If we're at the right edge of a terminal that supports xn, we're @@ -1185,7 +1291,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) temp = _rl_last_c_pos; else - temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); + temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset); if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode && _rl_last_v_pos == current_line - 1) { @@ -1200,8 +1306,8 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) /* This fixes only double-column characters, but if the wrapped character comsumes more than three columns, spaces will be inserted in the string buffer. */ - if (_rl_wrapped_line[current_line] > 0) - _rl_clear_to_eol (_rl_wrapped_line[current_line]); + if (current_line < line_state_visible->wbsize && line_state_visible->wrapped_line[current_line] > 0) + _rl_clear_to_eol (line_state_visible->wrapped_line[current_line]); memset (&ps, 0, sizeof (mbstate_t)); ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps); @@ -1217,7 +1323,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if (tempwidth > 0) { - int count; + int count, i; bytes = ret; for (count = 0; count < bytes; count++) putc (new[count], rl_outstream); @@ -1228,10 +1334,13 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if (ret != 0 && bytes != 0) { if (MB_INVALIDCH (ret)) - memmove (old+bytes, old+1, strlen (old+1)); - else - memmove (old+bytes, old+ret, strlen (old+ret)); + ret = 1; + memmove (old+bytes, old+ret, strlen (old+ret)); memcpy (old, new, bytes); + /* Fix up indices if we copy data from one line to another */ + omax += bytes - ret; + for (i = current_line+1; i < inv_botlin+1; i++) + vis_lbreaks[i] += bytes - ret; } } else @@ -1265,7 +1374,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) /* See if the old line is a subset of the new line, so that the only change is adding characters. */ temp = (omax < nmax) ? omax : nmax; - if (memcmp (old, new, temp) == 0) + if (memcmp (old, new, temp) == 0) /* adding at the end */ { ofd = old + temp; nfd = new + temp; @@ -1407,30 +1516,48 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) sequences (like drawing the `unbold' sequence without a corresponding `bold') that manifests itself on certain terminals. */ - lendiff = local_prompt ? strlen (local_prompt) : 0; + lendiff = local_prompt_len; od = ofd - old; /* index of first difference in visible line */ if (current_line == 0 && !_rl_horizontal_scroll_mode && _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 && - od >= lendiff && _rl_last_c_pos <= prompt_last_invisible) + od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX) { #if defined (__MSDOS__) putc ('\r', rl_outstream); #else tputs (_rl_term_cr, 1, _rl_output_character_function); #endif + if (modmark) + _rl_output_some_chars ("*", 1); _rl_output_some_chars (local_prompt, lendiff); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { /* We take wrap_offset into account here so we can pass correct information to _rl_move_cursor_relative. */ - _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset; + _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark; cpos_adjusted = 1; } else - _rl_last_c_pos = lendiff; + _rl_last_c_pos = lendiff + modmark; } + o_cpos = _rl_last_c_pos; + + /* When this function returns, _rl_last_c_pos is correct, and an absolute + cursor postion in multibyte mode, but a buffer index when not in a + multibyte locale. */ _rl_move_cursor_relative (od, old); +#if 1 +#if defined (HANDLE_MULTIBYTE) + /* We need to indicate that the cursor position is correct in the presence of + invisible characters in the prompt string. Let's see if setting this when + we make sure we're at the end of the drawn prompt string works. */ + if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && + (_rl_last_c_pos > 0 || o_cpos > 0) && + _rl_last_c_pos == prompt_physical_chars) + cpos_adjusted = 1; +#endif +#endif /* if (len (new) > len (old)) lendiff == difference in buffer @@ -1438,7 +1565,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) When not using multibyte characters, these are equal */ lendiff = (nls - nfd) - (ols - ofd); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old); + col_lendiff = _rl_col_width (new, nfd - new, nls - new, 1) - _rl_col_width (old, ofd - old, ols - old, 1); else col_lendiff = lendiff; @@ -1463,7 +1590,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) /* Insert (diff (len (old), len (new)) ch. */ temp = ne - nfd; if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - col_temp = _rl_col_width (new, nfd - new, ne - new); + col_temp = _rl_col_width (new, nfd - new, ne - new, 1); else col_temp = temp; @@ -1471,22 +1598,60 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) { /* Non-zero if we're increasing the number of lines. */ int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; + /* If col_lendiff is > 0, implying that the new string takes up more + screen real estate than the old, but lendiff is < 0, meaning that it + takes fewer bytes, we need to just output the characters starting + from the first difference. These will overwrite what is on the + display, so there's no reason to do a smart update. This can really + only happen in a multibyte environment. */ + if (lendiff < 0) + { + _rl_output_some_chars (nfd, temp); + _rl_last_c_pos += _rl_col_width (nfd, 0, temp, 1); + /* If nfd begins before any invisible characters in the prompt, + adjust _rl_last_c_pos to account for wrap_offset and set + cpos_adjusted to let the caller know. */ + if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) + { + _rl_last_c_pos -= wrap_offset; + cpos_adjusted = 1; + } + return; + } /* Sometimes it is cheaper to print the characters rather than use the terminal's capabilities. If we're growing the number of lines, make sure we actually cause the new line to wrap around on auto-wrapping terminals. */ - if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) + else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) { /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and _rl_horizontal_scroll_mode == 1, inserting the characters with _rl_term_IC or _rl_term_ic will screw up the screen because of the invisible characters. We need to just draw them. */ - if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 || - lendiff <= prompt_visible_length || !current_invis_chars)) + /* The same thing happens if we're trying to draw before the last + invisible character in the prompt string or we're increasing the + number of invisible characters in the line and we're not drawing + the entire prompt string. */ + if (*ols && ((_rl_horizontal_scroll_mode && + _rl_last_c_pos == 0 && + lendiff > prompt_visible_length && + current_invis_chars > 0) == 0) && + (((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && + current_line == 0 && wrap_offset && + ((nfd - new) <= prompt_last_invisible) && + (col_lendiff < prompt_visible_length)) == 0) && + (visible_wrap_offset >= current_invis_chars)) { insert_some_chars (nfd, lendiff, col_lendiff); _rl_last_c_pos += col_lendiff; } +#if 0 /* XXX - for now */ + else if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && _rl_last_c_pos == 0 && wrap_offset && (nfd-new) <= prompt_last_invisible && col_lendiff < prompt_visible_length && visible_wrap_offset >= current_invis_chars) + { + _rl_output_some_chars (nfd, lendiff); + _rl_last_c_pos += col_lendiff; + } +#endif else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0) { /* At the end of a line the characters do not have to @@ -1498,11 +1663,16 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) } else { - /* We have horizontal scrolling and we are not inserting at - the end. We have invisible characters in this line. This - is a dumb update. */ _rl_output_some_chars (nfd, temp); _rl_last_c_pos += col_temp; + /* If nfd begins before the last invisible character in the + prompt, adjust _rl_last_c_pos to account for wrap_offset + and set cpos_adjusted to let the caller know. */ + if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) + { + _rl_last_c_pos -= wrap_offset; + cpos_adjusted = 1; + } return; } /* Copy (new) chars to screen from first diff to last match. */ @@ -1510,15 +1680,23 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if ((temp - lendiff) > 0) { _rl_output_some_chars (nfd + lendiff, temp - lendiff); -#if 1 /* XXX -- this bears closer inspection. Fixes a redisplay bug reported against bash-3.0-alpha by Andreas Schwab involving multibyte characters and prompt strings with invisible characters, but was previously disabled. */ - _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff); -#else - _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff); -#endif + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + twidth = _rl_col_width (nfd+lendiff, 0, temp-col_lendiff, 1); + else + twidth = temp - lendiff; + _rl_last_c_pos += twidth; + /* If nfd begins before the last invisible character in the + prompt, adjust _rl_last_c_pos to account for wrap_offset + and set cpos_adjusted to let the caller know. */ + if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) + { + _rl_last_c_pos -= wrap_offset; + cpos_adjusted = 1; + } } } else @@ -1530,6 +1708,14 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) char in the current line (which implies we just output some invisible characters) we need to adjust _rl_last_c_pos, since it represents a physical character position. */ + if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && + current_line == prompt_last_screen_line && wrap_offset && + wrap_offset != prompt_invis_chars_first_line && + ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth)))) + { + _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line; + cpos_adjusted = 1; + } } } else /* Delete characters from line. */ @@ -1551,8 +1737,22 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) temp = nls - nfd; if (temp > 0) { + /* If nfd begins at the prompt, or before the invisible + characters in the prompt, we need to adjust _rl_last_c_pos + in a multibyte locale to account for the wrap offset and + set cpos_adjusted accordingly. */ _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += _rl_col_width (nfd, 0, temp);; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + _rl_last_c_pos += _rl_col_width (nfd, 0, temp, 1); + if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) + { + _rl_last_c_pos -= wrap_offset; + cpos_adjusted = 1; + } + } + else + _rl_last_c_pos += temp; } } /* Otherwise, print over the existing material. */ @@ -1560,16 +1760,37 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) { if (temp > 0) { + /* If nfd begins at the prompt, or before the invisible + characters in the prompt, we need to adjust _rl_last_c_pos + in a multibyte locale to account for the wrap offset and + set cpos_adjusted accordingly. */ _rl_output_some_chars (nfd, temp); _rl_last_c_pos += col_temp; /* XXX */ + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) + { + _rl_last_c_pos -= wrap_offset; + cpos_adjusted = 1; + } + } } lendiff = (oe - old) - (ne - new); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new); + col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1); else col_lendiff = lendiff; +#if 0 if (col_lendiff) +#else + /* If we've already printed over the entire width of the screen, + including the old material, then col_lendiff doesn't matter and + space_to_eol will insert too many spaces. XXX - maybe we should + adjust col_lendiff based on the difference between _rl_last_c_pos + and _rl_screenwidth */ + if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth))) +#endif { if (_rl_term_autowrap && current_line < inv_botlin) space_to_eol (col_lendiff); @@ -1623,7 +1844,7 @@ rl_on_new_line_with_prompt () l = strlen (prompt_last_line); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); /* XXX */ + _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1); /* XXX */ else _rl_last_c_pos = l; @@ -1658,10 +1879,11 @@ rl_on_new_line_with_prompt () int rl_forced_update_display () { + register char *temp; + if (visible_line) { - register char *temp = visible_line; - + temp = visible_line; while (*temp) *temp++ = '\0'; } @@ -1684,9 +1906,14 @@ _rl_move_cursor_relative (new, data) register int i; int woff; /* number of invisible chars on current line */ int cpos, dpos; /* current and desired cursor positions */ + int adjust; - woff = W_OFFSET (_rl_last_v_pos, wrap_offset); + woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset); cpos = _rl_last_c_pos; + + if (cpos == 0 && cpos == new) + return; + #if defined (HANDLE_MULTIBYTE) /* If we have multibyte characters, NEW is indexed by the buffer point in a multibyte string, but _rl_last_c_pos is the display position. In @@ -1695,9 +1922,42 @@ _rl_move_cursor_relative (new, data) as long as we are past them and they are counted by _rl_col_width. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { - dpos = _rl_col_width (data, 0, new); - if (dpos > woff) - dpos -= woff; + adjust = 1; + /* Try to short-circuit common cases and eliminate a bunch of multibyte + character function calls. */ + /* 1. prompt string */ + if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0) + { + dpos = prompt_physical_chars; + cpos_adjusted = 1; + adjust = 0; + } + /* 2. prompt_string + line contents */ + else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0) + { + dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1); + cpos_adjusted = 1; + adjust = 0; + } + else + dpos = _rl_col_width (data, 0, new, 1); + + /* Use NEW when comparing against the last invisible character in the + prompt string, since they're both buffer indices and DPOS is a + desired display position. */ + if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */ + (prompt_physical_chars >= _rl_screenwidth && + _rl_last_v_pos == prompt_last_screen_line && + wrap_offset >= woff && dpos >= woff && + new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset)))) + /* XXX last comparison might need to be >= */ + { + dpos -= woff; + /* Since this will be assigned to _rl_last_c_pos at the end (more + precisely, _rl_last_c_pos == dpos when this function returns), + let the caller know. */ + cpos_adjusted = 1; + } } else #endif @@ -1716,7 +1976,7 @@ _rl_move_cursor_relative (new, data) else #endif i = _rl_last_c_pos - woff; - if (new == 0 || CR_FASTER (new, _rl_last_c_pos) || + if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) || (_rl_term_autowrap && i == _rl_screenwidth)) { #if defined (__MSDOS__) @@ -1738,19 +1998,27 @@ _rl_move_cursor_relative (new, data) sequence telling the terminal to move forward one character. That kind of control is for people who don't know what the data is underneath the cursor. */ -#if defined (HACK_TERMCAP_MOTION) - if (_rl_term_forward_char) - { - for (i = cpos; i < dpos; i++) - tputs (_rl_term_forward_char, 1, _rl_output_character_function); - } - else -#endif /* HACK_TERMCAP_MOTION */ + + /* However, we need a handle on where the current display position is + in the buffer for the immediately preceding comment to be true. + In multibyte locales, we don't currently have that info available. + Without it, we don't know where the data we have to display begins + in the buffer and we have to go back to the beginning of the screen + line. In this case, we can use the terminal sequence to move forward + if it's available. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { - tputs (_rl_term_cr, 1, _rl_output_character_function); - for (i = 0; i < new; i++) - putc (data[i], rl_outstream); + if (_rl_term_forward_char) + { + for (i = cpos; i < dpos; i++) + tputs (_rl_term_forward_char, 1, _rl_output_character_function); + } + else + { + tputs (_rl_term_cr, 1, _rl_output_character_function); + for (i = 0; i < new; i++) + putc (data[i], rl_outstream); + } } else for (i = cpos; i < new; i++) @@ -1908,6 +2176,7 @@ rl_message (va_alist) &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; @@ -1931,6 +2200,7 @@ rl_message (format, arg1, arg2) &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; @@ -1967,12 +2237,14 @@ rl_save_prompt () saved_local_prompt = local_prompt; saved_local_prefix = local_prompt_prefix; saved_prefix_length = prompt_prefix_length; + saved_local_length = local_prompt_len; saved_last_invisible = prompt_last_invisible; saved_visible_length = prompt_visible_length; saved_invis_chars_first_line = prompt_invis_chars_first_line; saved_physical_chars = prompt_physical_chars; local_prompt = local_prompt_prefix = (char *)0; + local_prompt_len = 0; prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0; prompt_invis_chars_first_line = prompt_physical_chars = 0; } @@ -1985,6 +2257,7 @@ rl_restore_prompt () local_prompt = saved_local_prompt; local_prompt_prefix = saved_local_prefix; + local_prompt_len = saved_local_length; prompt_prefix_length = saved_prefix_length; prompt_last_invisible = saved_last_invisible; prompt_visible_length = saved_visible_length; @@ -1993,6 +2266,7 @@ rl_restore_prompt () /* can test saved_local_prompt to see if prompt info has been saved. */ saved_local_prompt = saved_local_prefix = (char *)0; + saved_local_length = 0; saved_last_invisible = saved_visible_length = saved_prefix_length = 0; saved_invis_chars_first_line = saved_physical_chars = 0; } @@ -2106,7 +2380,7 @@ insert_some_chars (string, count, col) /* DEBUGGING */ if (MB_CUR_MAX == 1 || rl_byte_oriented) if (count != col) - fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col); + _rl_ttymsg ("debug: insert_some_chars: count (%d) != col (%d)", count, col); /* If IC is defined, then we do not have to "enter" insert mode. */ if (_rl_term_IC) @@ -2189,7 +2463,8 @@ _rl_update_final () char *last_line; last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; - _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); + cpos_buffer_position = -1; /* don't know where we are in buffer */ + _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */ _rl_clear_to_eol (0); putc (last_line[_rl_screenwidth - 1], rl_outstream); } @@ -2232,6 +2507,7 @@ redraw_prompt (t) &prompt_invis_chars_first_line, &prompt_physical_chars); local_prompt_prefix = (char *)NULL; + local_prompt_len = local_prompt ? strlen (local_prompt) : 0; rl_forced_update_display (); @@ -2245,10 +2521,14 @@ _rl_redisplay_after_sigwinch () { char *t; - /* Clear the current line and put the cursor at column 0. Make sure - the right thing happens if we have wrapped to a new screen line. */ + /* Clear the last line (assuming that the screen size change will result in + either more or fewer characters on that line only) and put the cursor at + column 0. Make sure the right thing happens if we have wrapped to a new + screen line. */ if (_rl_term_cr) { + _rl_move_vert (_rl_vis_botlin); + #if defined (__MSDOS__) putc ('\r', rl_outstream); #else @@ -2284,7 +2564,7 @@ _rl_redisplay_after_sigwinch () void _rl_clean_up_for_exit () { - if (readline_echoing_p) + if (_rl_echoing_p) { _rl_move_vert (_rl_vis_botlin); _rl_vis_botlin = 0; @@ -2329,20 +2609,41 @@ _rl_current_display_line () In the case of multibyte characters with stateful encoding, we have to scan from the beginning of the string to take the state into account. */ static int -_rl_col_width (str, start, end) +_rl_col_width (str, start, end, flags) const char *str; - int start, end; + int start, end, flags; { wchar_t wc; - mbstate_t ps = {0}; + mbstate_t ps; int tmp, point, width, max; if (end <= start) return 0; + if (MB_CUR_MAX == 1 || rl_byte_oriented) +{ +_rl_ttymsg ("_rl_col_width: called with MB_CUR_MAX == 1"); + return (end - start); +} + + memset (&ps, 0, sizeof (mbstate_t)); point = 0; max = end; + /* Try to short-circuit common cases. The adjustment to remove wrap_offset + is done by the caller. */ + /* 1. prompt string */ + if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0) + return (prompt_physical_chars + wrap_offset); + /* 2. prompt string + line contents */ + else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0) + { + tmp = prompt_physical_chars + wrap_offset; + /* XXX - try to call ourselves recursively with non-prompt portion */ + tmp += _rl_col_width (str, local_prompt_len, end, flags); + return (tmp); + } + while (point < start) { tmp = mbrlen (str + point, max, &ps); |