From: Chet Ramey Date: Tue, 23 Feb 2016 16:38:53 +0000 (-0500) Subject: readline-7.0 rc1 distribution X-Git-Tag: readline-7.0-rc1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1a756901a2224cce5e121adf1671962e06a5e8d1;p=thirdparty%2Freadline.git readline-7.0 rc1 distribution --- diff --git a/CHANGES b/CHANGES index 13d75fc..266cd53 100644 --- a/CHANGES +++ b/CHANGES @@ -78,6 +78,25 @@ y. Updated tty auditing feature based on patch from Red Hat. z. Fixed a bug that could cause the history library to crash on overflows introduced by malicious editing of timestamps in the history file. +aa. The history file writing functions only attempt to create and use a backup + history file if the history file exists and is a regular file. + +bb. Fixed an out-of-bounds read in readline's internal tilde expansion interface. + +cc. Fixed several redisplay bugs with prompt strings containing multibyte + and non-visible characters whose physical length is longer than the screen + width. + +dd. Fixed a redisplay bug with prompt strings containing invisible characters + whose physical length exceeds the screen width and using incremental search. + +ee. Readline prints more descriptive error messages when it encounters errors + while reading an inputrc file. + +ff. Fixed a bug in the character insertion code that attempts to optimize + typeahead when it reads a character that is not bound to self-insert and + resets the key sequence state. + 2. New Features in Readline a. The history truncation code now uses the same error recovery mechansim as @@ -112,6 +131,17 @@ i. rl_callback_sigcleanup: a new application function that can clean up and unset any state set by readline's callback mode. Intended to be used after a signal. +j. If an incremental search string has its last character removed with DEL, the + resulting empty search string no longer matches the previous line. + +k. If readline reads a history file that begins with `#' (or the value of + the history comment character) and has enabled history timestamps, the history + entries are assumed to be delimited by timestamps. This allows multi-line + history entries. + +l. Readline now throws an error if it parses a key binding without a terminating + `:' or whitespace. + ------------------------------------------------------------------------------- This document details the changes between this version, readline-6.3, and the previous version, readline-6.2. diff --git a/CHANGES-7.0 b/CHANGES-7.0 new file mode 100644 index 0000000..7d2868d --- /dev/null +++ b/CHANGES-7.0 @@ -0,0 +1,143 @@ +This document details the changes between this version, readline-7.0, and the +previous version, readline-6.3. + +1. Changes to Readline + +a. A bug that caused vi-mode `.' to be unable to redo `c', `d', and `y' + commands with modifiers was fixed. + +b. Fixed a bug that caused callback mode to dump core when reading a + multiple-key sequence (e.g., arrow keys). + +c. Fixed a bug that caused the redisplay code to erase some of the line when + using horizontal scrolling with incremental search. + +d. Readline's input handler now performs signal processing if read(2) is + interrupted by SIGALRM or SIGVTALRM. + +e. Fixed a problem with revert-all-at-newline freeing freed memory. + +f. Clarified the documentation for the history_quotes_inhibit_expansion + variable to note that it inhibits scanning for the history comment + character and that it only affects double-quoted strings. + +g. Fixed an off-by-one error in the prompt printed when performing searches. + +h. Use pselect(2), if available, to wait for input before calling read(2), so + a SIGWINCH can interrupt it, since it doesn't interrupt read(2). + +i. Some memory leaks caused by signals interrupting filename completion have + been fixed. + +j. Reading EOF twice on a non-empty line causes EOF to be returned, rather + than the partial line. This can cause partial lines to be executed on + SIGHUP, for example. + +k. Fixed a bug concerning deleting multibyte characters from the search + string while performing an incremental search. + +l. Fixed a bug with tilde expanding directory names in filename completion. + +m. Fixed a bug that did not allow binding sequences beginning with a `\'. + +n. Fixed a redisplay bug involving incorrect line wrapping when the prompt + contains a multibyte character in the last screen column. + +o. Fixed a bug that caused history expansion to disregard characters that are + documented to delimit a history event specifier without requiring `:'. + +p. Fixed a bug that could cause reading past the end of a string when reading + the value when binding the set of isearch terminators. + +q. Fixed a bug that caused readline commands that depend on knowing which + key invoked them to misbehave when dispatching key sequences that are + prefixes of other key bindings. + +r. Paren matching now works in vi insert mode. + +s. Colored completion prefixes are now displayed using a different color, less + likely to collide with files. + +t. Fixed a bug that caused vi-mode character search to misbehave when + running in callback mode. + +u. Fixed a bug that caused output to be delayed when input is coming from a + macro in vi-mode. + +v. Fixed a bug that caused the vi-mode `.' command to misbehave when redoing + a multi-key key sequence via a macro. + +w. Fixed a bug that caused problems with applications that supply their own + input function when performing completion. + +x. When read returns -1/EIO when attempting to read a key, return an error + instead of line termination back to the caller. + +y. Updated tty auditing feature based on patch from Red Hat. + +z. Fixed a bug that could cause the history library to crash on overflows + introduced by malicious editing of timestamps in the history file. + +aa. The history file writing functions only attempt to create and use a backup + history file if the history file exists and is a regular file. + +bb. Fixed an out-of-bounds read in readline's internal tilde expansion interface. + +cc. Fixed several redisplay bugs with prompt strings containing multibyte + and non-visible characters whose physical length is longer than the screen + width. + +dd. Fixed a redisplay bug with prompt strings containing invisible characters + whose physical length exceeds the screen width and using incremental search. + +ee. Readline prints more descriptive error messages when it encounters errors + while reading an inputrc file. + +ff. Fixed a bug in the character insertion code that attempts to optimize + typeahead when it reads a character that is not bound to self-insert and + resets the key sequence state. + +2. New Features in Readline + +a. The history truncation code now uses the same error recovery mechansim as + the history writing code, and restores the old version of the history file + on error. The error recovery mechanism handles symlinked history files. + +b. There is a new bindable variable, `enable-bracketed-paste', which enables + support for a terminal's bracketed paste mode. + +c. The editing mode indicators can now be strings and are user-settable + (new `emacs-mode-string', `vi-cmd-mode-string' and `vi-ins-mode-string' + variables). Mode strings can contain invisible character sequences. + Setting mode strings to null strings restores the defaults. + +d. Prompt expansion adds the mode string to the last line of a multi-line + prompt (one with embedded newlines). + +e. There is a new bindable variable, `colored-completion-prefix', which, if + set, causes the common prefix of a set of possible completions to be + displayed in color. + +f. There is a new bindable command `vi-yank-pop', a vi-mode version of emacs- + mode yank-pop. + +g. The redisplay code underwent several efficiency improvements for multibyte + locales. + +h. The insert-char function attempts to batch-insert all pending typeahead + that maps to self-insert, as long as it is coming from the terminal. + +i. rl_callback_sigcleanup: a new application function that can clean up and + unset any state set by readline's callback mode. Intended to be used + after a signal. + +j. If an incremental search string has its last character removed with DEL, the + resulting empty search string no longer matches the previous line. + +k. If readline reads a history file that begins with `#' (or the value of + the history comment character) and has enabled history timestamps, the history + entries are assumed to be delimited by timestamps. This allows multi-line + history entries. + +l. Readline now throws an error if it parses a key binding without a terminating + `:' or whitespace. diff --git a/NEWS b/NEWS index 11ac0e3..cf7107e 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,17 @@ i. rl_callback_sigcleanup: a new application function that can clean up and unset any state set by readline's callback mode. Intended to be used after a signal. +j. If an incremental search string has its last character removed with DEL, the + resulting empty search string no longer matches the previous line. + +k. If readline reads a history file that begins with `#' (or the value of + the history comment character) and has enabled history timestamps, the history + entries are assumed to be delimited by timestamps. This allows multi-line + history entries. + +l. Readline now throws an error if it parses a key binding without a terminating + `:' or whitespace. + ------------------------------------------------------------------------------- This is a terse description of the new features added to readline-6.3 since the release of readline-6.2. diff --git a/aclocal.m4 b/aclocal.m4 index 7730d2d..d3bac07 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1856,7 +1856,7 @@ main() ], ac_cv_rl_version=`cat conftest.rlv`, ac_cv_rl_version='0.0', -ac_cv_rl_version='4.2')]) +ac_cv_rl_version='6.3')]) CFLAGS="$_save_CFLAGS" LDFLAGS="$_save_LDFLAGS" diff --git a/bind.c b/bind.c index f88e5aa..3dbc1ce 100644 --- a/bind.c +++ b/bind.c @@ -1,6 +1,6 @@ /* bind.c -- key binding and startup file support for the readline library. */ -/* Copyright (C) 1987-2012 Free Software Foundation, Inc. +/* Copyright (C) 1987-2016 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. @@ -74,8 +74,13 @@ Keymap rl_binding_keymap; static int _rl_skip_to_delim PARAMS((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 char *_rl_read_file PARAMS((char *, size_t *)); -static void _rl_init_file_error PARAMS((const char *)); static int _rl_read_init_file PARAMS((const char *, int)); static int glean_key_from_name PARAMS((char *)); @@ -989,14 +994,35 @@ _rl_read_init_file (filename, include_level) } static void -_rl_init_file_error (msg) - const char *msg; +#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) - _rl_errmsg ("%s: line %d: %s\n", current_readline_init_file, - current_readline_init_lineno, msg); - else - _rl_errmsg ("%s", msg); + fprintf (stderr, "%s: line %d: ", current_readline_init_file, + current_readline_init_lineno); + + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + fflush (stderr); + + va_end (args); } /* **************************************************************** */ @@ -1216,7 +1242,7 @@ handle_parser_directive (statement) } /* display an error message about the unknown parser directive */ - _rl_init_file_error ("unknown parser directive"); + _rl_init_file_error ("%s: unknown parser directive", directive); return (1); } @@ -1262,7 +1288,7 @@ rl_parse_and_bind (string) { char *funname, *kname; register int c, i; - int key, equivalency; + int key, equivalency, foundmod, foundsep; while (string && whitespace (*string)) string++; @@ -1292,7 +1318,7 @@ rl_parse_and_bind (string) /* If we didn't find a closing quote, abort the line. */ if (string[i] == '\0') { - _rl_init_file_error ("no closing `\"' in key binding"); + _rl_init_file_error ("%s: no closing `\"' in key binding", string); return 1; } else @@ -1304,6 +1330,8 @@ rl_parse_and_bind (string) equivalency = (c == ':' && string[i + 1] == '='); + foundsep = c != 0; + /* Mark the end of the command (or keyname). */ if (string[i]) string[i++] = '\0'; @@ -1393,6 +1421,12 @@ remove_trailing: return 0; } + if (foundsep == 0) + { + _rl_init_file_error ("%s: no key sequence terminator", string); + return 1; + } + /* If this is a new-style key-binding, then do the binding with rl_bind_keyseq (). Otherwise, let the older code deal with it. */ if (*string == '"') @@ -1449,11 +1483,24 @@ remove_trailing: key = glean_key_from_name (kname); /* Add in control and meta bits. */ + foundmod = 0; if (substring_member_of_array (string, _rl_possible_control_prefixes)) - key = CTRL (_rl_to_upper (key)); + { + key = CTRL (_rl_to_upper (key)); + foundmod = 1; + } if (substring_member_of_array (string, _rl_possible_meta_prefixes)) - key = META (key); + { + key = META (key); + foundmod = 1; + } + + if (foundmod == 0 && kname != string) + { + _rl_init_file_error ("%s: unknown key modifier", string); + return 1; + } /* Temporary. Handle old-style keyname with macro-binding. */ if (*funname == '\'' || *funname == '"') @@ -1480,6 +1527,7 @@ remove_trailing: #endif /* PREFIX_META_HACK */ else rl_bind_key (key, rl_named_function (funname)); + return 0; } @@ -1681,10 +1729,14 @@ rl_variable_bind (name, value) i = find_string_var (name); - /* For the time being, unknown variable names or string names without a - handler function are simply ignored. */ + /* For the time being, string names without a handler function are simply + ignored. */ if (i < 0 || string_varlist[i].set_func == 0) - return 0; + { + if (i < 0) + _rl_init_file_error ("%s: unknown variable name", name); + return 0; + } v = (*string_varlist[i].set_func) (value); return v; diff --git a/callback.c b/callback.c index ec48b76..fafe5a5 100644 --- a/callback.c +++ b/callback.c @@ -1,6 +1,6 @@ /* callback.c -- functions to use readline as an X `callback' mechanism. */ -/* Copyright (C) 1987-2009 Free Software Foundation, Inc. +/* Copyright (C) 1987-2015 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. diff --git a/chardefs.h b/chardefs.h index 43aab7a..3cf1326 100644 --- a/chardefs.h +++ b/chardefs.h @@ -1,6 +1,6 @@ /* chardefs.h -- Character definitions for readline. */ -/* Copyright (C) 1994-2009 Free Software Foundation, Inc. +/* Copyright (C) 1994-2015 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. diff --git a/colors.c b/colors.c index d4bcb32..7859f5d 100644 --- a/colors.c +++ b/colors.c @@ -2,8 +2,8 @@ Modified by Chet Ramey for Readline. - Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 Free Software Foundation, - Inc. + Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012, 2015 + Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/colors.h b/colors.h index ec62774..6561ad9 100644 --- a/colors.h +++ b/colors.h @@ -2,8 +2,8 @@ Modified by Chet Ramey for Readline. - Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 Free Software Foundation, - Inc. + Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012, 2015 + Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/display.c b/display.c index 4353d6e..f261933 100644 --- a/display.c +++ b/display.c @@ -1,6 +1,6 @@ /* display.c -- readline redisplay facility. */ -/* Copyright (C) 1987-2013 Free Software Foundation, Inc. +/* Copyright (C) 1987-2015 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. @@ -192,6 +192,8 @@ static int prompt_multibyte_chars; /* Number of lines currently on screen minus 1. */ int _rl_vis_botlin = 0; +static int _rl_inv_botlin = 0; + /* Variables used only in this file. */ /* The last left edge of text that was displayed. This is used when doing horizontal scrolling. It shifts in thirds of a screenwidth. */ @@ -580,13 +582,13 @@ rl_redisplay () int inv_botlin, lb_botlin, lb_linenum, o_cpos; int newlines, lpos, temp, n0, num, prompt_lines_estimate; char *prompt_this_line; + int mb_cur_max = MB_CUR_MAX; #if defined (HANDLE_MULTIBYTE) wchar_t wc; size_t wc_bytes; int wc_width; mbstate_t ps; int _rl_wrapped_multicolumn = 0; - int mb_cur_max = MB_CUR_MAX; #endif if (_rl_echoing_p == 0) @@ -737,6 +739,8 @@ rl_redisplay () /* inv_lbreaks[i] is where line i starts in the buffer. */ inv_lbreaks[newlines = 0] = 0; + /* lpos is a physical cursor position, so it needs to be adjusted by the + number of invisible characters in the prompt, per line */ lpos = prompt_physical_chars + modmark; #if defined (HANDLE_MULTIBYTE) @@ -757,6 +761,16 @@ rl_redisplay () while (lpos >= _rl_screenwidth) { int z, p; + int nocorrect, wadjust; + + nocorrect = 0; + /* Adjust depending on the invisible characters in the line. We use a + heuristic based on experience: invisible characters nearly always + appear in the first and last lines of the prompt */ + wadjust = (newlines == 0) + ? prompt_invis_chars_first_line + : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line); + /* fix from Darin Johnson 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 @@ -767,11 +781,14 @@ rl_redisplay () #if defined (HANDLE_MULTIBYTE) if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0) { + nocorrect = 1; n0 = num; temp = local_prompt_len; while (num < temp) { - z = _rl_col_width (local_prompt, n0, num, 1); + /* This has to take invisible characters in the prompt into + account. */ + z = _rl_col_width (local_prompt, n0, num, 1) - wadjust; if (z > _rl_screenwidth) { num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY); @@ -798,16 +815,18 @@ rl_redisplay () /* 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 += (newlines == 0) ? prompt_invis_chars_first_line - : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line); + if (nocorrect == 0) + temp += wadjust; inv_lbreaks[++newlines] = temp; #if defined (HANDLE_MULTIBYTE) + /* lpos is a physical cursor position, so it needs to take the invisible + characters into account. */ if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0) - lpos -= _rl_col_width (local_prompt, n0, num, 1); + lpos -= _rl_col_width (local_prompt, n0, num, 1) - wadjust; else #endif - lpos -= _rl_screenwidth; + lpos -= _rl_screenwidth - wadjust; } prompt_last_screen_line = newlines; @@ -999,7 +1018,7 @@ rl_redisplay () lb_linenum = newlines; } - inv_botlin = lb_botlin = newlines; + inv_botlin = lb_botlin = _rl_inv_botlin = newlines; CHECK_INV_LBREAKS (); inv_lbreaks[newlines+1] = out; cursor_linenum = lb_linenum; @@ -1029,9 +1048,11 @@ rl_redisplay () not the first. */ if (out >= _rl_screenchars) { +#if defined (HANDLE_MULTIBYTE) if (mb_cur_max > 1 && rl_byte_oriented == 0) out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY); else +#endif out = _rl_screenchars - 1; } @@ -1616,6 +1637,11 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) 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) + visible_wrap_offset = prompt_invis_chars_first_line; /* XXX */ if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset) _rl_last_c_pos += visible_wrap_offset; } @@ -1627,16 +1653,31 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) string, then redraw the entire prompt string. We can only do this reliably if the terminal supports a `cr' capability. + This can also happen if the prompt string has changed, and the first + difference in the line is in the middle of the prompt string, after a + sequence of invisible characters (worst case) and before the end of + the prompt. In this case, we have to redraw the entire prompt string + so that the entire sequence of invisible characters is drawn. We need + to handle the worst case, when the difference is after (or in the middle + of) a sequence of invisible characters that changes the text color and + before the sequence that restores the text color to normal. Then we have + to make sure that the lines still differ -- if they don't, we can + return immediately. + This is not an efficiency hack -- there is a problem with redrawing portions of the prompt string if they contain terminal escape sequences (like drawing the `unbold' sequence without a corresponding `bold') that manifests itself on certain terminals. */ lendiff = local_prompt_len; + if (lendiff > nmax) + lendiff = nmax; od = ofd - old; /* index of first difference in visible line */ + nd = nfd - new; 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_ENDING_INDEX) + (((od > 0 || nd > 0) && (od < PROMPT_ENDING_INDEX || nd < PROMPT_ENDING_INDEX)) || + ((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX))) { #if defined (__MSDOS__) putc ('\r', rl_outstream); @@ -1655,6 +1696,43 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) } else _rl_last_c_pos = lendiff + modmark; + + /* Now if we have printed the prompt string because the first difference + was within the prompt, see if we need to recompute where the lines + differ. Check whether where we are now is past the last place where + the old and new lines are the same and short-circuit now if we are. */ + if ((od < PROMPT_ENDING_INDEX || nd < PROMPT_ENDING_INDEX) && + omax == nmax && + lendiff > (ols-old) && lendiff > (nls-new)) + return; + + /* XXX - we need to fix up our calculations if we are now past the + old ofd/nfd and the prompt length (or line length) has changed. + We punt on the problem and do a dumb update. We'd like to be able + to just output the prompt from the beginning of the line up to the + first difference, but you don't know the number of invisible + characters in that case. + This needs a lot of work to be efficient. */ + if ((od < PROMPT_ENDING_INDEX || nd < PROMPT_ENDING_INDEX)) + { + nfd = new + lendiff; /* number of characters we output above */ + nd = lendiff; + + /* Do a dumb update and return */ + temp = ne - nfd; + if (temp > 0) + { + _rl_output_some_chars (nfd, temp); + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + _rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1); + else + _rl_last_c_pos += temp; + } + if (nmax < omax) + goto clear_rest_of_line; /* XXX */ + else + return; + } } o_cpos = _rl_last_c_pos; @@ -1816,11 +1894,15 @@ 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. */ + /* The current_line*rl_screenwidth+prompt_invis_chars_first_line is a + crude attempt to compute how far into the new line buffer we are. + It doesn't work well in the face of multibyte characters and needs + to be rethought. XXX */ if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == prompt_last_screen_line && wrap_offset && displaying_prompt_first_line && wrap_offset != prompt_invis_chars_first_line && - ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth)))) + ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth+prompt_invis_chars_first_line)))) { _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line; cpos_adjusted = 1; @@ -2039,7 +2121,8 @@ rl_redraw_prompt_last_line () (Well, when we don't have multibyte characters, _rl_last_c_pos is a buffer index.) DATA is the contents of the screen line of interest; i.e., where - the movement is being done. */ + the movement is being done. + DATA is always the visible line or the invisible line */ void _rl_move_cursor_relative (new, data) int new; @@ -2049,6 +2132,7 @@ _rl_move_cursor_relative (new, data) int woff; /* number of invisible chars on current line */ int cpos, dpos; /* current and desired cursor positions */ int adjust; + int in_invisline; woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset); cpos = _rl_last_c_pos; @@ -2087,14 +2171,28 @@ _rl_move_cursor_relative (new, data) if (displaying_prompt_first_line == 0) adjust = 0; + /* yet another special case: printing the last line of a prompt with + multibyte characters and invisible characters whose printable length + exceeds the screen width with the last invisible character + (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]) + in_invisline = data - invisible_line; + /* 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. */ + /* NEW is relative to the current displayed line, while + PROMPT_LAST_INVISIBLE is relative to the entire (wrapped) line. + Need a way to reconcile these two variables by turning NEW into a + buffer position relative to the start of the line */ if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */ - (prompt_physical_chars >= _rl_screenwidth && + (new+in_invisline > prompt_last_invisible) || /* invisible line */ + (prompt_physical_chars >= _rl_screenwidth && /* visible line */ _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)))) + new > (prompt_last_invisible-(vis_lbreaks[_rl_last_v_pos])-wrap_offset)))) /* XXX last comparison might need to be >= */ { dpos -= woff; diff --git a/doc/history.dvi b/doc/history.dvi index 7007d52..4ab5410 100644 Binary files a/doc/history.dvi and b/doc/history.dvi differ diff --git a/doc/history.html b/doc/history.html index cba7535..a6be6e3 100644 --- a/doc/history.html +++ b/doc/history.html @@ -1,6 +1,6 @@ - + + +