From 8aeb9782f4a5d98c23b918bdae2477810088d0d1 Mon Sep 17 00:00:00 2001 From: ache Date: Mon, 27 Mar 2006 22:47:12 +0000 Subject: Virgin import of GNU Readline 5.1 --- contrib/libreadline/display.c | 268 ++++++++++++++++++++++++++---------------- 1 file changed, 169 insertions(+), 99 deletions(-) (limited to 'contrib/libreadline/display.c') diff --git a/contrib/libreadline/display.c b/contrib/libreadline/display.c index ff0cf5a..b22521b 100644 --- a/contrib/libreadline/display.c +++ b/contrib/libreadline/display.c @@ -1,6 +1,6 @@ /* display.c -- readline redisplay facility. */ -/* Copyright (C) 1987-2004 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 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. @@ -118,16 +118,24 @@ rl_voidfunc_t *rl_redisplay_function = rl_redisplay; int rl_display_fixed = 0; int _rl_suppress_redisplay = 0; +int _rl_want_redisplay = 0; /* The stuff that gets printed out before the actual text of the line. This is usually pointing to rl_prompt. */ char *rl_display_prompt = (char *)NULL; /* Pseudo-global variables declared here. */ + /* The visible cursor position. If you print some text, adjust this. */ +/* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale + supporting multibyte characters, and an absolute cursor position when + in such a locale. This is an artifact of the donated multibyte support. + Care must be taken when modifying its value. */ int _rl_last_c_pos = 0; int _rl_last_v_pos = 0; +static int cpos_adjusted; + /* Number of lines currently on screen minus 1. */ int _rl_vis_botlin = 0; @@ -180,6 +188,18 @@ static int prompt_last_screen_line; static int prompt_physical_chars; +/* Variables to save and restore prompt and display information. */ + +/* These are getting numerous enough that it's time to create a struct. */ + +static char *saved_local_prompt; +static char *saved_local_prefix; +static int saved_last_invisible; +static int saved_visible_length; +static int saved_prefix_length; +static int saved_invis_chars_first_line; +static int saved_physical_chars; + /* Expand the prompt string S and return the number of visible characters in *LP, if LP is not null. This is currently more-or-less a placeholder for expansion. LIP, if non-null is a place to store the @@ -236,7 +256,8 @@ expand_prompt (pmt, lp, lip, niflp, vlp) else if (ignoring && *p == RL_PROMPT_END_IGNORE) { ignoring = 0; - last = r - ret - 1; + if (p[-1] != RL_PROMPT_START_IGNORE) + last = r - ret - 1; continue; } else @@ -335,7 +356,8 @@ rl_expand_prompt (prompt) FREE (local_prompt_prefix); local_prompt = local_prompt_prefix = (char *)0; - prompt_last_invisible = prompt_visible_length = 0; + prompt_last_invisible = prompt_invis_chars_first_line = 0; + prompt_visible_length = prompt_physical_chars = 0; if (prompt == 0 || *prompt == 0) return (0); @@ -423,7 +445,7 @@ rl_redisplay () { register int in, out, c, linenum, cursor_linenum; register char *line; - int c_pos, inv_botlin, lb_botlin, lb_linenum; + int c_pos, inv_botlin, lb_botlin, lb_linenum, o_cpos; int newlines, lpos, temp, modmark, n0, num; char *prompt_this_line; #if defined (HANDLE_MULTIBYTE) @@ -440,7 +462,7 @@ rl_redisplay () if (!rl_display_prompt) rl_display_prompt = ""; - if (invisible_line == 0) + if (invisible_line == 0 || vis_lbreaks == 0) { init_line_structures (0); rl_on_new_line (); @@ -833,7 +855,7 @@ rl_redisplay () if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) { - int nleft, pos, changed_screen_line; + int nleft, pos, changed_screen_line, tx; if (!rl_display_fixed || forced_display) { @@ -864,9 +886,26 @@ rl_redisplay () /* For each line in the buffer, do the updating display. */ for (linenum = 0; linenum <= inv_botlin; linenum++) { + o_cpos = _rl_last_c_pos; + cpos_adjusted = 0; update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin); + /* update_line potentially changes _rl_last_c_pos, but doesn't + 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 + 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; + /* If this is the line with the prompt, we might need to compensate for invisible characters in the new line. Do this only if there is not more than one new line (which @@ -878,7 +917,10 @@ rl_redisplay () (wrap_offset > visible_wrap_offset) && (_rl_last_c_pos < visible_first_line_len)) { - nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + nleft = _rl_screenwidth - _rl_last_c_pos; + else + nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; if (nleft) _rl_clear_to_eol (nleft); } @@ -914,7 +956,7 @@ rl_redisplay () the physical cursor position on the screen stays the same, but the buffer position needs to be adjusted to account for invisible characters. */ - if (cursor_linenum == 0 && wrap_offset) + if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset) _rl_last_c_pos += wrap_offset; } @@ -935,7 +977,7 @@ rl_redisplay () #endif _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); + _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset; else _rl_last_c_pos = nleft; } @@ -947,18 +989,31 @@ rl_redisplay () start of the line and the cursor position. */ nleft = c_pos - 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 + position that doesn't take invisible characters in the prompt + into account. We use a fudge factor to compensate. */ + /* Since _rl_backspace() doesn't know about invisible characters in the prompt, and there's no good way to tell it, we compensate for those characters here and call _rl_backspace() directly. */ if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) { - _rl_backspace (_rl_last_c_pos - nleft); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft); + tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset; else - _rl_last_c_pos = nleft; + tx = nleft; + if (_rl_last_c_pos > tx) + { + _rl_backspace (_rl_last_c_pos - tx); /* XXX */ + _rl_last_c_pos = tx; + } } + /* We need to note that in a multibyte locale we are dealing with + _rl_last_c_pos as an absolute cursor position, but moving to a + point specified by a buffer position (NLEFT) that doesn't take + invisible characters into account. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) _rl_move_cursor_relative (nleft, &invisible_line[pos]); else if (nleft != _rl_last_c_pos) @@ -1117,7 +1172,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) the exact cursor position and cut-and-paste with certain terminal emulators. In this calculation, TEMP is the physical screen position of the cursor. */ - temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); + 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); if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode && _rl_last_v_pos == current_line - 1) { @@ -1182,7 +1240,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) putc (new[0], rl_outstream); else putc (' ', rl_outstream); - _rl_last_c_pos = 1; /* XXX */ + _rl_last_c_pos = 1; _rl_last_v_pos++; if (old[0] && new[0]) old[0] = new[0]; @@ -1323,7 +1381,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if (_rl_last_v_pos != current_line) { _rl_move_vert (current_line); - if (current_line == 0 && visible_wrap_offset) + if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset) _rl_last_c_pos += visible_wrap_offset; } @@ -1352,7 +1410,12 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) #endif _rl_output_some_chars (local_prompt, lendiff); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff); + { + /* 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; + cpos_adjusted = 1; + } else _rl_last_c_pos = lendiff; } @@ -1414,7 +1477,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) insert_some_chars (nfd, lendiff, col_lendiff); _rl_last_c_pos += col_lendiff; } - else if (*ols == 0 && lendiff > 0) + 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 be "inserted". They can just be placed on the screen. */ @@ -1453,6 +1516,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) /* cannot insert chars, write to EOL */ _rl_output_some_chars (nfd, temp); _rl_last_c_pos += col_temp; + /* If we're in a multibyte locale and were before the last invisible + 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. */ } } else /* Delete characters from line. */ @@ -1484,7 +1551,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if (temp > 0) { _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += col_temp; + _rl_last_c_pos += col_temp; /* XXX */ } lendiff = (oe - old) - (ne - new); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) @@ -1546,7 +1613,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); + _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); /* XXX */ else _rl_last_c_pos = l; @@ -1595,6 +1662,8 @@ rl_forced_update_display () } /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. + (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. */ void @@ -1603,28 +1672,40 @@ _rl_move_cursor_relative (new, data) const char *data; { register int i; + int woff; /* number of invisible chars on current line */ + int cpos, dpos; /* current and desired cursor positions */ - /* If we don't have to do anything, then return. */ + woff = W_OFFSET (_rl_last_v_pos, wrap_offset); + cpos = _rl_last_c_pos; #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 this case, NEW's display position is not obvious and must be - calculated. */ - if (MB_CUR_MAX == 1 || rl_byte_oriented) + calculated. We need to account for invisible characters in this line, + as long as we are past them and they are counted by _rl_col_width. */ + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { - if (_rl_last_c_pos == new) - return; + dpos = _rl_col_width (data, 0, new); + if (dpos > woff) + dpos -= woff; } - else if (_rl_last_c_pos == _rl_col_width (data, 0, new)) - return; -#else - if (_rl_last_c_pos == new) return; + else #endif + dpos = new; + + /* If we don't have to do anything, then return. */ + if (cpos == dpos) + return; /* It may be faster to output a CR, and then move forwards instead of moving backwards. */ /* i == current physical cursor position. */ - i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + i = _rl_last_c_pos; + else +#endif + i = _rl_last_c_pos - woff; if (new == 0 || CR_FASTER (new, _rl_last_c_pos) || (_rl_term_autowrap && i == _rl_screenwidth)) { @@ -1633,10 +1714,10 @@ _rl_move_cursor_relative (new, data) #else tputs (_rl_term_cr, 1, _rl_output_character_function); #endif /* !__MSDOS__ */ - _rl_last_c_pos = 0; + cpos = _rl_last_c_pos = 0; } - if (_rl_last_c_pos < new) + if (cpos < dpos) { /* Move the cursor forward. We do it by printing the command to move the cursor forward if there is one, else print that @@ -1650,31 +1731,11 @@ _rl_move_cursor_relative (new, data) #if defined (HACK_TERMCAP_MOTION) if (_rl_term_forward_char) { - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - int width; - width = _rl_col_width (data, _rl_last_c_pos, new); - for (i = 0; i < width; i++) - tputs (_rl_term_forward_char, 1, _rl_output_character_function); - } - else - { - for (i = _rl_last_c_pos; i < new; i++) - tputs (_rl_term_forward_char, 1, _rl_output_character_function); - } - } - else 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); + for (i = cpos; i < dpos; i++) + tputs (_rl_term_forward_char, 1, _rl_output_character_function); } else - for (i = _rl_last_c_pos; i < new; i++) - putc (data[i], rl_outstream); - -#else /* !HACK_TERMCAP_MOTION */ - +#endif /* HACK_TERMCAP_MOTION */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { tputs (_rl_term_cr, 1, _rl_output_character_function); @@ -1682,32 +1743,20 @@ _rl_move_cursor_relative (new, data) putc (data[i], rl_outstream); } else - for (i = _rl_last_c_pos; i < new; i++) + for (i = cpos; i < new; i++) putc (data[i], rl_outstream); - -#endif /* !HACK_TERMCAP_MOTION */ - } + #if defined (HANDLE_MULTIBYTE) /* NEW points to the buffer point, but _rl_last_c_pos is the display point. The byte length of the string is probably bigger than the column width of the string, which means that if NEW == _rl_last_c_pos, then NEW's display point is less than _rl_last_c_pos. */ - else if (_rl_last_c_pos >= new) -#else - else if (_rl_last_c_pos > new) #endif - { - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_backspace (_rl_last_c_pos - _rl_col_width (data, 0, new)); - else - _rl_backspace (_rl_last_c_pos - new); - } + else if (cpos > dpos) + _rl_backspace (cpos - dpos); - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (data, 0, new); - else - _rl_last_c_pos = new; + _rl_last_c_pos = dpos; } /* PWP: move the cursor up or down. */ @@ -1796,9 +1845,9 @@ rl_character_len (c, pos) return ((ISPRINT (uc)) ? 1 : 2); } - /* How to print things in the "echo-area". The prompt is treated as a mini-modeline. */ +static int msg_saved_prompt = 0; #if defined (USE_VARARGS) int @@ -1829,8 +1878,19 @@ rl_message (va_alist) #endif va_end (args); + if (saved_local_prompt == 0) + { + rl_save_prompt (); + msg_saved_prompt = 1; + } rl_display_prompt = msg_buf; + local_prompt = expand_prompt (msg_buf, &prompt_visible_length, + &prompt_last_invisible, + &prompt_invis_chars_first_line, + &prompt_physical_chars); + local_prompt_prefix = (char *)NULL; (*rl_redisplay_function) (); + return 0; } #else /* !USE_VARARGS */ @@ -1840,8 +1900,20 @@ rl_message (format, arg1, arg2) { sprintf (msg_buf, format, arg1, arg2); msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ + rl_display_prompt = msg_buf; + if (saved_local_prompt == 0) + { + rl_save_prompt (); + msg_saved_prompt = 1; + } + local_prompt = expand_prompt (msg_buf, &prompt_visible_length, + &prompt_last_invisible, + &prompt_invis_chars_first_line, + &prompt_physical_chars); + local_prompt_prefix = (char *)NULL; (*rl_redisplay_function) (); + return 0; } #endif /* !USE_VARARGS */ @@ -1851,6 +1923,11 @@ int rl_clear_message () { rl_display_prompt = rl_prompt; + if (msg_saved_prompt) + { + rl_restore_prompt (); + msg_saved_prompt = 0; + } (*rl_redisplay_function) (); return 0; } @@ -1865,27 +1942,19 @@ rl_reset_line_state () return 0; } -/* These are getting numerous enough that it's time to create a struct. */ - -static char *saved_local_prompt; -static char *saved_local_prefix; -static int saved_last_invisible; -static int saved_visible_length; -static int saved_invis_chars_first_line; -static int saved_physical_chars; - void rl_save_prompt () { saved_local_prompt = local_prompt; saved_local_prefix = local_prompt_prefix; + saved_prefix_length = prompt_prefix_length; 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; - prompt_last_invisible = prompt_visible_length = 0; + prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0; prompt_invis_chars_first_line = prompt_physical_chars = 0; } @@ -1897,10 +1966,16 @@ rl_restore_prompt () local_prompt = saved_local_prompt; local_prompt_prefix = saved_local_prefix; + prompt_prefix_length = saved_prefix_length; prompt_last_invisible = saved_last_invisible; prompt_visible_length = saved_visible_length; prompt_invis_chars_first_line = saved_invis_chars_first_line; prompt_physical_chars = saved_physical_chars; + + /* can test saved_local_prompt to see if prompt info has been saved. */ + saved_local_prompt = saved_local_prefix = (char *)0; + saved_last_invisible = saved_visible_length = saved_prefix_length = 0; + saved_invis_chars_first_line = saved_physical_chars = 0; } char * @@ -1934,6 +2009,8 @@ _rl_make_prompt_for_search (pchar) prompt_visible_length = saved_visible_length + 1; } + prompt_physical_chars = saved_physical_chars + 1; + return pmt; } @@ -1994,6 +2071,9 @@ insert_some_chars (string, count, col) char *string; int count, col; { +#if defined (__MSDOS__) || defined (__MINGW32__) + _rl_output_some_chars (string, count); +#else /* DEBUGGING */ if (MB_CUR_MAX == 1 || rl_byte_oriented) if (count != col) @@ -2032,6 +2112,7 @@ insert_some_chars (string, count, col) if (_rl_term_ei && *_rl_term_ei) tputs (_rl_term_ei, 1, _rl_output_character_function); } +#endif /* __MSDOS__ || __MINGW32__ */ } /* Delete COUNT characters from the display line. */ @@ -2042,6 +2123,7 @@ delete_chars (count) if (count > _rl_screenwidth) /* XXX */ return; +#if !defined (__MSDOS__) && !defined (__MINGW32__) if (_rl_term_DC && *_rl_term_DC) { char *buffer; @@ -2054,6 +2136,7 @@ delete_chars (count) while (count--) tputs (_rl_term_dc, 1, _rl_output_character_function); } +#endif /* !__MSDOS__ && !__MINGW32__ */ } void @@ -2109,18 +2192,10 @@ static void redraw_prompt (t) char *t; { - char *oldp, *oldl, *oldlprefix; - int oldlen, oldlast, oldplen, oldninvis, oldphyschars; + char *oldp; - /* Geez, I should make this a struct. */ oldp = rl_display_prompt; - oldl = local_prompt; - oldlprefix = local_prompt_prefix; - oldlen = prompt_visible_length; - oldplen = prompt_prefix_length; - oldlast = prompt_last_invisible; - oldninvis = prompt_invis_chars_first_line; - oldphyschars = prompt_physical_chars; + rl_save_prompt (); rl_display_prompt = t; local_prompt = expand_prompt (t, &prompt_visible_length, @@ -2128,16 +2203,11 @@ redraw_prompt (t) &prompt_invis_chars_first_line, &prompt_physical_chars); local_prompt_prefix = (char *)NULL; + rl_forced_update_display (); rl_display_prompt = oldp; - local_prompt = oldl; - local_prompt_prefix = oldlprefix; - prompt_visible_length = oldlen; - prompt_prefix_length = oldplen; - prompt_last_invisible = oldlast; - prompt_invis_chars_first_line = oldninvis; - prompt_physical_chars = oldphyschars; + rl_restore_prompt(); } /* Redisplay the current line after a SIGWINCH is received. */ -- cgit v1.1